From 26692f53ef550f7b8dc43fc5171c6187094632a8 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 9 Aug 2009 11:42:32 +0200 Subject: VIDEO: Correct use of request_region/request_mem_region request_region should be used with release_region, not request_mem_region. Geert Uytterhoeven pointed out that in the case of drivers/video/gbefb.c, the problem is actually the other way around; request_mem_region should be used instead of request_region. The semantic patch that finds/fixes this problem is as follows: (http://coccinelle.lip6.fr/) // @r1@ expression start; @@ request_region(start,...) @b1@ expression r1.start; @@ request_mem_region(start,...) @depends on !b1@ expression r1.start; expression E; @@ - release_mem_region + release_region (start,E) // Signed-off-by: Julia Lawall Signed-off-by: Ralf Baechle diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 9805483..3ee5e63 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c @@ -1571,8 +1571,8 @@ out_err_iobase: if (default_par->mtrr_handle >= 0) mtrr_del(default_par->mtrr_handle, info->fix.smem_start, info->fix.smem_len); - release_mem_region(pci_resource_start(pdev, 2), - pci_resource_len(pdev, 2)); + release_region(pci_resource_start(pdev, 2), + pci_resource_len(pdev, 2)); out_err_screenbase: if (info->screen_base) iounmap(info->screen_base); -- cgit v0.10.2 From 40cb989fcf9f0caf6a116562132c2fffed38d261 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 18 May 2010 00:38:05 +0900 Subject: MIPS: TX49xx: Define ARCH_KMALLOC_MINALIGN With SLAB, it works without ARCH_KMALLOC_MINALIGN, but with SLOB/SLUB, ARCH_KMALLOC_MINALIGN is required to ensure alignment of kmalloced buffer. Signed-off-by: Atsushi Nemoto To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1248/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-tx49xx/kmalloc.h b/arch/mips/include/asm/mach-tx49xx/kmalloc.h index 913ff19..b74caf6 100644 --- a/arch/mips/include/asm/mach-tx49xx/kmalloc.h +++ b/arch/mips/include/asm/mach-tx49xx/kmalloc.h @@ -1,8 +1,6 @@ #ifndef __ASM_MACH_TX49XX_KMALLOC_H #define __ASM_MACH_TX49XX_KMALLOC_H -/* - * All happy, no need to define ARCH_KMALLOC_MINALIGN - */ +#define ARCH_KMALLOC_MINALIGN L1_CACHE_BYTES #endif /* __ASM_MACH_TX49XX_KMALLOC_H */ -- cgit v0.10.2 From 6165df980801e1be7a5b65686bd52f55e0407db1 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 20 May 2010 19:15:17 +0100 Subject: MIPS: IP27: Don't include into . The include is unecessary and will when building the IP35 result in recursive header inclusion spaghetti. Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/sn/agent.h b/arch/mips/include/asm/sn/agent.h index ac4ea85..dc81114 100644 --- a/arch/mips/include/asm/sn/agent.h +++ b/arch/mips/include/asm/sn/agent.h @@ -11,7 +11,6 @@ #ifndef _ASM_SGI_SN_AGENT_H #define _ASM_SGI_SN_AGENT_H -#include #include #include -- cgit v0.10.2 From 4d2b11252b92c6aca9f9222ee05e00f7262c2e53 Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 19 May 2010 10:40:53 -0700 Subject: MIPS: Don't overflow cevt-r4k.c calculations at high clock rates. The 'mult' element of struct clock_event_device must never be wider than 32-bits. If it were, it would get truncated when used by clockevent_delta2ns() when this calls do_div(). We can meet this requirement by using clockevent_set_clock() to set the MULT and SHIFT values. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1253/ Acked-by: Thomas Gleixner Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 0b2450c..2a4d50f 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -163,7 +163,6 @@ int c0_compare_int_usable(void) int __cpuinit r4k_clockevent_init(void) { - uint64_t mips_freq = mips_hpt_frequency; unsigned int cpu = smp_processor_id(); struct clock_event_device *cd; unsigned int irq; @@ -188,9 +187,9 @@ int __cpuinit r4k_clockevent_init(void) cd->name = "MIPS"; cd->features = CLOCK_EVT_FEAT_ONESHOT; + clockevent_set_clock(cd, mips_hpt_frequency); + /* Calculate the min / max delta */ - cd->mult = div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32); - cd->shift = 32; cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); cd->min_delta_ns = clockevent_delta2ns(0x300, cd); -- cgit v0.10.2 From e10c53a5f31ae1535e13ef51d6615662c36d36c6 Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 29 Jul 2010 13:43:04 -0700 Subject: MIPS: N32: Fix syscall number comments. Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1515/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index a4facee..a3d6613 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -400,22 +400,22 @@ EXPORT(sysn32_call_table) PTR sys_ioprio_set PTR sys_ioprio_get PTR compat_sys_utimensat - PTR compat_sys_signalfd /* 5280 */ + PTR compat_sys_signalfd /* 6280 */ PTR sys_ni_syscall PTR sys_eventfd PTR sys_fallocate PTR sys_timerfd_create - PTR compat_sys_timerfd_gettime /* 5285 */ + PTR compat_sys_timerfd_gettime /* 6285 */ PTR compat_sys_timerfd_settime PTR sys_signalfd4 PTR sys_eventfd2 PTR sys_epoll_create1 - PTR sys_dup3 /* 5290 */ + PTR sys_dup3 /* 6290 */ PTR sys_pipe2 PTR sys_inotify_init1 PTR sys_preadv PTR sys_pwritev - PTR compat_sys_rt_tgsigqueueinfo /* 5295 */ + PTR compat_sys_rt_tgsigqueueinfo /* 6295 */ PTR sys_perf_event_open PTR sys_accept4 PTR compat_sys_recvmmsg -- cgit v0.10.2 From 5c8974538afd97990d3730ef6fea731a34ef1f85 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 29 Jul 2010 00:13:07 +0200 Subject: MIPS: Octeon: Workaround link failures with gcc-4.4.x 32-bits toolchains When building with a gcc-4.4.x toolchain that is configured to produce 32-bits executables by default, we will produce __lshrti3 in sched_clock() which is never resolved so the kernel fails to link. Unconditionally use the inline assembly version as suggested by David Daney, which works around the issue. Signed-off-by: Florian Fainelli To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1514/ Acked-by: David Daney Signed-off-by: Ralf Baechle diff --git a/arch/mips/cavium-octeon/csrc-octeon.c b/arch/mips/cavium-octeon/csrc-octeon.c index 0bf4bbe..36400d2 100644 --- a/arch/mips/cavium-octeon/csrc-octeon.c +++ b/arch/mips/cavium-octeon/csrc-octeon.c @@ -53,7 +53,6 @@ static struct clocksource clocksource_mips = { unsigned long long notrace sched_clock(void) { /* 64-bit arithmatic can overflow, so use 128-bit. */ -#if (__GNUC__ < 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ <= 3)) u64 t1, t2, t3; unsigned long long rv; u64 mult = clocksource_mips.mult; @@ -73,13 +72,6 @@ unsigned long long notrace sched_clock(void) : [cnt] "r" (cnt), [mult] "r" (mult), [shift] "r" (shift) : "hi", "lo"); return rv; -#else - /* GCC > 4.3 do it the easy way. */ - unsigned int __attribute__((mode(TI))) t; - t = read_c0_cvmcount(); - t = t * clocksource_mips.mult; - return (unsigned long long)(t >> clocksource_mips.shift); -#endif } void __init plat_time_init(void) -- cgit v0.10.2 From aec9222551353890190af810a4c93ed7050bfa19 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 27 Jul 2010 22:12:43 +0200 Subject: MIPS: BCM47xx: Really fix 128MB RAM problem The previous patch 4a86f2d27733f610e642649aca3e82e86fca9e22 (lmo) rsp. 84a6fcb368a080620d12fc4d79e07902dbee7335 (kernel.org) was wrong. The BCM47xx architecture maps the ram into a 128MB address space. It will be spaced there as often as goes into the 128MB. Detection tries to find the position where the same memory is found. When reading beyond 128MB the processor will throw an exception. If 128MB RAM is installed, it will not find a memory alias because it tries to read beyond the 128MB border. Now it just assumes 128MB installed ram if it can not find an alias. Signed-off-by: Hauke Mehrtens To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1508/ Acked-by: Florian Fainelli Signed-off-by: Ralf Baechle diff --git a/arch/mips/bcm47xx/prom.c b/arch/mips/bcm47xx/prom.c index 0fa646c..f6e9063 100644 --- a/arch/mips/bcm47xx/prom.c +++ b/arch/mips/bcm47xx/prom.c @@ -126,6 +126,7 @@ static __init void prom_init_cmdline(void) static __init void prom_init_mem(void) { unsigned long mem; + unsigned long max; /* Figure out memory size by finding aliases. * @@ -134,21 +135,26 @@ static __init void prom_init_mem(void) * want to reuse the memory used by CFE (around 4MB). That means cfe_* * functions stop to work at some point during the boot, we should only * call them at the beginning of the boot. + * + * BCM47XX uses 128MB for addressing the ram, if the system contains + * less that that amount of ram it remaps the ram more often into the + * available space. + * Accessing memory after 128MB will cause an exception. + * max contains the biggest possible address supported by the platform. + * If the method wants to try something above we assume 128MB ram. */ + max = ((unsigned long)(prom_init) | ((128 << 20) - 1)); for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) { + if (((unsigned long)(prom_init) + mem) > max) { + mem = (128 << 20); + printk(KERN_DEBUG "assume 128MB RAM\n"); + break; + } if (*(unsigned long *)((unsigned long)(prom_init) + mem) == *(unsigned long *)(prom_init)) break; } - /* Ignoring the last page when ddr size is 128M. Cached - * accesses to last page is causing the processor to prefetch - * using address above 128M stepping out of the ddr address - * space. - */ - if (mem == 0x8000000) - mem -= 0x1000; - add_memory_region(0, mem, BOOT_MEM_RAM); } -- cgit v0.10.2 From 220937b1aa97025a0e2fff0604b00ee6e9b7ccd3 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 27 Jul 2010 22:12:45 +0200 Subject: MIPS: BCM47xx: Activate SSB_B43_PCI_BRIDGE by default B43_pci_bridge is needed to use the b43 driver with brcm47xx. Activate it by default if PCI is available. Signed-off-by: Hauke Mehrtens To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1510/ Acked-by: Florian Fainelli Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index cdaae94..b81a6b2 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -62,6 +62,7 @@ config BCM47XX select SSB_DRIVER_MIPS select SSB_DRIVER_EXTIF select SSB_EMBEDDED + select SSB_B43_PCI_BRIDGE if PCI select SSB_PCICORE_HOSTMODE if PCI select GENERIC_GPIO select SYS_HAS_EARLY_PRINTK -- cgit v0.10.2 From 36f217d9df3e6bf8e6ae7647827b485b79dbaf8e Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 3 Aug 2010 03:42:32 +0100 Subject: MIPS: MTX1: Fix build. CC arch/mips/alchemy/mtx-1/board_setup.o {standard input}: Assembler messages: {standard input}:263: Error: opcode not supported on this processor: mips1 (mips1) `sync' {standard input}:274: Error: opcode not supported on this processor: mips1 (mips1) `sync' {standard input}:296: Error: opcode not supported on this processor: mips1 (mips1) `sync' [...] Any .set mipsX statement other than .set mips0 at the end of inline assembler is a big fat bug. Introduced by 9482eabeca315c0276ffb50026b7482481b7097b (linux-mips.org) rsp. 32fd6901a6d8d19f94e4de6be4e4b552ab078620 (kernel.org). While at it, fix the same issue in arch/mips/alchemy/devboards/pb1000/board_setup.c arch/mips/alchemy/xxs1500/board_setup.c as well. Signed-off-by: Ralf Baechle diff --git a/arch/mips/alchemy/devboards/pb1000/board_setup.c b/arch/mips/alchemy/devboards/pb1000/board_setup.c index 4ef50d8..46fdc8c 100644 --- a/arch/mips/alchemy/devboards/pb1000/board_setup.c +++ b/arch/mips/alchemy/devboards/pb1000/board_setup.c @@ -49,7 +49,10 @@ static void board_power_off(void) { printk(KERN_ALERT "It's now safe to remove power\n"); while (1) - asm volatile (".set mips3 ; wait ; .set mips1"); + asm volatile ( + " .set mips32 \n" + " wait \n" + " .set mips0 \n"); } void __init board_setup(void) diff --git a/arch/mips/alchemy/mtx-1/board_setup.c b/arch/mips/alchemy/mtx-1/board_setup.c index 52d883d..def1a75 100644 --- a/arch/mips/alchemy/mtx-1/board_setup.c +++ b/arch/mips/alchemy/mtx-1/board_setup.c @@ -62,7 +62,10 @@ static void mtx1_power_off(void) { printk(KERN_ALERT "It's now safe to remove power\n"); while (1) - asm volatile (".set mips3 ; wait ; .set mips1"); + asm volatile ( + " .set mips32 \n" + " wait \n" + " .set mips0 \n"); } void __init board_setup(void) diff --git a/arch/mips/alchemy/xxs1500/board_setup.c b/arch/mips/alchemy/xxs1500/board_setup.c index 47b4292..7868aea 100644 --- a/arch/mips/alchemy/xxs1500/board_setup.c +++ b/arch/mips/alchemy/xxs1500/board_setup.c @@ -44,7 +44,10 @@ static void xxs1500_power_off(void) { printk(KERN_ALERT "It's now safe to remove power\n"); while (1) - asm volatile (".set mips3 ; wait ; .set mips1"); + asm volatile ( + " .set mips32 \n" + " wait \n" + " .set mips0 \n"); } void __init board_setup(void) -- cgit v0.10.2 From ca36c36b7821b573fe06ce6bc34db03b557f3ce4 Mon Sep 17 00:00:00 2001 From: David VomLehn Date: Fri, 21 May 2010 11:25:36 -0700 Subject: MIPS: PowerTV: Use O(1) algorthm for phys_to_dma/dma_to_phys Replace phys_to_dma()/dma_to_phys() looping algorithm with an O(1) algorithm The approach taken is inspired by the sparse memory implementation: take a certain number of high-order bits off the address them, use this as an index into a table containing an offset to the desired address and add it to the original value. There is a table for mapping physical addresses to DMA addresses and another one for the reverse mapping. The table sizes depend on how fine-grained the mappings need to be; Coarser granularity less to smaller tables. On a processor with 32-bit physical and DMA addresses, with 4 MIB granularity, memory usage is two 2048-byte arrays. Each 32-byte cache line thus covers 64 MiB of address space. Also, renames phys_to_bus() to phys_to_dma() and bus_to_phys() to dma_to_phys() to align with kernel usage. [Ralf: Fixed silly build breakage due to stackoverflow warning caused by huge array on stack.] Signed-off-by: David VomLehn To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1257/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-powertv/dma-coherence.h b/arch/mips/include/asm/mach-powertv/dma-coherence.h index 5b8d5eb..f76029c 100644 --- a/arch/mips/include/asm/mach-powertv/dma-coherence.h +++ b/arch/mips/include/asm/mach-powertv/dma-coherence.h @@ -65,21 +65,21 @@ static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size) { if (is_kseg2(addr)) - return phys_to_bus(virt_to_phys_from_pte(addr)); + return phys_to_dma(virt_to_phys_from_pte(addr)); else - return phys_to_bus(virt_to_phys(addr)); + return phys_to_dma(virt_to_phys(addr)); } static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page) { - return phys_to_bus(page_to_phys(page)); + return phys_to_dma(page_to_phys(page)); } static inline unsigned long plat_dma_addr_to_phys(struct device *dev, dma_addr_t dma_addr) { - return bus_to_phys(dma_addr); + return dma_to_phys(dma_addr); } static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr, diff --git a/arch/mips/include/asm/mach-powertv/ioremap.h b/arch/mips/include/asm/mach-powertv/ioremap.h index e6276d5..076f2ee 100644 --- a/arch/mips/include/asm/mach-powertv/ioremap.h +++ b/arch/mips/include/asm/mach-powertv/ioremap.h @@ -10,64 +10,101 @@ #define __ASM_MACH_POWERTV_IOREMAP_H #include +#include +#include -#define LOW_MEM_BOUNDARY_PHYS 0x20000000 -#define LOW_MEM_BOUNDARY_MASK (~(LOW_MEM_BOUNDARY_PHYS - 1)) +#include +#include + +/* We're going to mess with bits, so get sizes */ +#define IOR_BPC 8 /* Bits per char */ +#define IOR_PHYS_BITS (IOR_BPC * sizeof(phys_addr_t)) +#define IOR_DMA_BITS (IOR_BPC * sizeof(dma_addr_t)) /* - * The bus addresses are different than the physical addresses that - * the processor sees by an offset. This offset varies by ASIC - * version. Define a variable to hold the offset and some macros to - * make the conversion simpler. */ -extern unsigned long phys_to_bus_offset; - -#ifdef CONFIG_HIGHMEM -#define MEM_GAP_PHYS 0x60000000 + * Define the granularity of physical/DMA mapping in terms of the number + * of bits that defines the offset within a grain. These will be the + * least significant bits of the address. The rest of a physical or DMA + * address will be used to index into an appropriate table to find the + * offset to add to the address to yield the corresponding DMA or physical + * address, respectively. + */ +#define IOR_LSBITS 22 /* Bits in a grain */ + /* - * TODO: We will use the hard code for conversion between physical and - * bus until the bootloader releases their device tree to us. + * Compute the number of most significant address bits after removing those + * used for the offset within a grain and then compute the number of table + * entries for the conversion. */ -#define phys_to_bus(x) (((x) < LOW_MEM_BOUNDARY_PHYS) ? \ - ((x) + phys_to_bus_offset) : (x)) -#define bus_to_phys(x) (((x) < MEM_GAP_PHYS_ADDR) ? \ - ((x) - phys_to_bus_offset) : (x)) -#else -#define phys_to_bus(x) ((x) + phys_to_bus_offset) -#define bus_to_phys(x) ((x) - phys_to_bus_offset) -#endif +#define IOR_PHYS_MSBITS (IOR_PHYS_BITS - IOR_LSBITS) +#define IOR_NUM_PHYS_TO_DMA ((phys_addr_t) 1 << IOR_PHYS_MSBITS) + +#define IOR_DMA_MSBITS (IOR_DMA_BITS - IOR_LSBITS) +#define IOR_NUM_DMA_TO_PHYS ((dma_addr_t) 1 << IOR_DMA_MSBITS) /* - * Determine whether the address we are given is for an ASIC device - * Params: addr Address to check - * Returns: Zero if the address is not for ASIC devices, non-zero - * if it is. + * Define data structures used as elements in the arrays for the conversion + * between physical and DMA addresses. We do some slightly fancy math to + * compute the width of the offset element of the conversion tables so + * that we can have the smallest conversion tables. Next, round up the + * sizes to the next higher power of two, i.e. the offset element will have + * 8, 16, 32, 64, etc. bits. This eliminates the need to mask off any + * bits. Finally, we compute a shift value that puts the most significant + * bits of the offset into the most significant bits of the offset element. + * This makes it more efficient on processors without barrel shifters and + * easier to see the values if the conversion table is dumped in binary. */ -static inline int asic_is_device_addr(phys_t addr) +#define _IOR_OFFSET_WIDTH(n) (1 << order_base_2(n)) +#define IOR_OFFSET_WIDTH(n) \ + (_IOR_OFFSET_WIDTH(n) < 8 ? 8 : _IOR_OFFSET_WIDTH(n)) + +#define IOR_PHYS_OFFSET_BITS IOR_OFFSET_WIDTH(IOR_PHYS_MSBITS) +#define IOR_PHYS_SHIFT (IOR_PHYS_BITS - IOR_PHYS_OFFSET_BITS) + +#define IOR_DMA_OFFSET_BITS IOR_OFFSET_WIDTH(IOR_DMA_MSBITS) +#define IOR_DMA_SHIFT (IOR_DMA_BITS - IOR_DMA_OFFSET_BITS) + +struct ior_phys_to_dma { + dma_addr_t offset:IOR_DMA_OFFSET_BITS __packed + __aligned((IOR_DMA_OFFSET_BITS / IOR_BPC)); +}; + +struct ior_dma_to_phys { + dma_addr_t offset:IOR_PHYS_OFFSET_BITS __packed + __aligned((IOR_PHYS_OFFSET_BITS / IOR_BPC)); +}; + +extern struct ior_phys_to_dma _ior_phys_to_dma[IOR_NUM_PHYS_TO_DMA]; +extern struct ior_dma_to_phys _ior_dma_to_phys[IOR_NUM_DMA_TO_PHYS]; + +static inline dma_addr_t _phys_to_dma_offset_raw(phys_addr_t phys) { - return !((phys_t)addr & (phys_t) LOW_MEM_BOUNDARY_MASK); + return (dma_addr_t)_ior_phys_to_dma[phys >> IOR_LSBITS].offset; } -/* - * Determine whether the address we are given is external RAM mappable - * into KSEG1. - * Params: addr Address to check - * Returns: Zero if the address is not for external RAM and - */ -static inline int asic_is_lowmem_ram_addr(phys_t addr) +static inline dma_addr_t _dma_to_phys_offset_raw(dma_addr_t dma) { - /* - * The RAM always starts at the following address in the processor's - * physical address space - */ - static const phys_t phys_ram_base = 0x10000000; - phys_t bus_ram_base; + return (dma_addr_t)_ior_dma_to_phys[dma >> IOR_LSBITS].offset; +} - bus_ram_base = phys_to_bus_offset + phys_ram_base; +/* These are not portable and should not be used in drivers. Drivers should + * be using ioremap() and friends to map physical addreses to virtual + * addresses and dma_map*() and friends to map virtual addresses into DMA + * addresses and back. + */ +static inline dma_addr_t phys_to_dma(phys_addr_t phys) +{ + return phys + (_phys_to_dma_offset_raw(phys) << IOR_PHYS_SHIFT); +} - return addr >= bus_ram_base && - addr < (bus_ram_base + (LOW_MEM_BOUNDARY_PHYS - phys_ram_base)); +static inline phys_addr_t dma_to_phys(dma_addr_t dma) +{ + return dma + (_dma_to_phys_offset_raw(dma) << IOR_DMA_SHIFT); } +extern void ioremap_add_map(dma_addr_t phys, phys_addr_t alias, + dma_addr_t size); + /* * Allow physical addresses to be fixed up to help peripherals located * outside the low 32-bit range -- generic pass-through version. @@ -77,10 +114,50 @@ static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size) return phys_addr; } -static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size, +/* + * Handle the special case of addresses the area aliased into the first + * 512 MiB of the processor's physical address space. These turn into either + * kseg0 or kseg1 addresses, depending on flags. + */ +static inline void __iomem *plat_ioremap(phys_t start, unsigned long size, unsigned long flags) { - return NULL; + phys_addr_t start_offset; + void __iomem *result = NULL; + + /* Start by checking to see whether this is an aliased address */ + start_offset = _dma_to_phys_offset_raw(start); + + /* + * If: + * o the memory is aliased into the first 512 MiB, and + * o the start and end are in the same RAM bank, and + * o we don't have a zero size or wrap around, and + * o we are supposed to create an uncached mapping, + * handle this is a kseg0 or kseg1 address + */ + if (start_offset != 0) { + phys_addr_t last; + dma_addr_t dma_to_phys_offset; + + last = start + size - 1; + dma_to_phys_offset = + _dma_to_phys_offset_raw(last) << IOR_DMA_SHIFT; + + if (dma_to_phys_offset == start_offset && + size != 0 && start <= last) { + phys_t adjusted_start; + adjusted_start = start + start_offset; + if (flags == _CACHE_UNCACHED) + result = (void __iomem *) (unsigned long) + CKSEG1ADDR(adjusted_start); + else + result = (void __iomem *) (unsigned long) + CKSEG0ADDR(adjusted_start); + } + } + + return result; } static inline int plat_iounmap(const volatile void __iomem *addr) diff --git a/arch/mips/powertv/Makefile b/arch/mips/powertv/Makefile index 0a0d73c..e9fe1c6e 100644 --- a/arch/mips/powertv/Makefile +++ b/arch/mips/powertv/Makefile @@ -23,6 +23,7 @@ # under Linux. # -obj-y += init.o memory.o reset.o time.o powertv_setup.o asic/ pci/ +obj-y += init.o ioremap.o memory.o powertv_setup.o reset.o time.o \ + asic/ pci/ EXTRA_CFLAGS += -Wall -Werror diff --git a/arch/mips/powertv/asic/asic_devices.c b/arch/mips/powertv/asic/asic_devices.c index 9ec523e..c81dd49 100644 --- a/arch/mips/powertv/asic/asic_devices.c +++ b/arch/mips/powertv/asic/asic_devices.c @@ -80,8 +80,8 @@ static bool usb_configured; * Don't recommend to use it directly, it is usually used by kernel internally. * Portable code should be using interfaces such as ioremp, dma_map_single, etc. */ -unsigned long phys_to_bus_offset; -EXPORT_SYMBOL(phys_to_bus_offset); +unsigned long phys_to_dma_offset; +EXPORT_SYMBOL(phys_to_dma_offset); /* * @@ -533,10 +533,10 @@ void __init configure_platform(void) switch (asic) { case ASIC_ZEUS: - phys_to_bus_offset = 0x30000000; + phys_to_dma_offset = 0x30000000; break; case ASIC_CALLIOPE: - phys_to_bus_offset = 0x10000000; + phys_to_dma_offset = 0x10000000; break; case ASIC_CRONUSLITE: /* Fall through */ @@ -546,10 +546,10 @@ void __init configure_platform(void) * 0x2XXXXXXX. If 0x10000000 aliases into 0x60000000- * 0x6XXXXXXX, the offset should be 0x50000000, not 0x10000000. */ - phys_to_bus_offset = 0x10000000; + phys_to_dma_offset = 0x10000000; break; default: - phys_to_bus_offset = 0x00000000; + phys_to_dma_offset = 0x00000000; break; } } @@ -603,7 +603,7 @@ void __init platform_alloc_bootmem(void) int size = gp_resources[i].end - gp_resources[i].start + 1; if ((gp_resources[i].start != 0) && ((gp_resources[i].flags & IORESOURCE_MEM) != 0)) { - reserve_bootmem(bus_to_phys(gp_resources[i].start), + reserve_bootmem(dma_to_phys(gp_resources[i].start), size, 0); total += gp_resources[i].end - gp_resources[i].start + 1; @@ -627,7 +627,7 @@ void __init platform_alloc_bootmem(void) else { gp_resources[i].start = - phys_to_bus(virt_to_phys(mem)); + phys_to_dma(virt_to_phys(mem)); gp_resources[i].end = gp_resources[i].start + size - 1; total += size; @@ -691,7 +691,7 @@ static void __init pmem_setup_resource(void) if (resource && pmemaddr && pmemlen) { /* The address provided by bootloader is in kseg0. Convert to * a bus address. */ - resource->start = phys_to_bus(pmemaddr - 0x80000000); + resource->start = phys_to_dma(pmemaddr - 0x80000000); resource->end = resource->start + pmemlen - 1; pr_info("persistent memory: start=0x%x end=0x%x\n", diff --git a/arch/mips/powertv/ioremap.c b/arch/mips/powertv/ioremap.c new file mode 100644 index 0000000..a77c6f6 --- /dev/null +++ b/arch/mips/powertv/ioremap.c @@ -0,0 +1,136 @@ +/* + * ioremap.c + * + * Support for mapping between dma_addr_t values a phys_addr_t values. + * + * Copyright (C) 2005-2009 Scientific-Atlanta, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: David VomLehn + * + * Description: Defines the platform resources for the SA settop. + * + * NOTE: The bootloader allocates persistent memory at an address which is + * 16 MiB below the end of the highest address in KSEG0. All fixed + * address memory reservations must avoid this region. + */ + +#include +#include + +#include + +/* + * Define the sizes of and masks for grains in physical and DMA space. The + * values are the same but the types are not. + */ +#define IOR_PHYS_GRAIN ((phys_addr_t) 1 << IOR_LSBITS) +#define IOR_PHYS_GRAIN_MASK (IOR_PHYS_GRAIN - 1) + +#define IOR_DMA_GRAIN ((dma_addr_t) 1 << IOR_LSBITS) +#define IOR_DMA_GRAIN_MASK (IOR_DMA_GRAIN - 1) + +/* + * Values that, when accessed by an index derived from a phys_addr_t and + * added to phys_addr_t value, yield a DMA address + */ +struct ior_phys_to_dma _ior_phys_to_dma[IOR_NUM_PHYS_TO_DMA]; +EXPORT_SYMBOL(_ior_phys_to_dma); + +/* + * Values that, when accessed by an index derived from a dma_addr_t and + * added to that dma_addr_t value, yield a physical address + */ +struct ior_dma_to_phys _ior_dma_to_phys[IOR_NUM_DMA_TO_PHYS]; +EXPORT_SYMBOL(_ior_dma_to_phys); + +/** + * setup_dma_to_phys - set up conversion from DMA to physical addresses + * @dma_idx: Top IOR_LSBITS bits of the DMA address, i.e. an index + * into the array _dma_to_phys. + * @delta: Value that, when added to the DMA address, will yield the + * physical address + * @s: Number of bytes in the section of memory with the given delta + * between DMA and physical addresses. + */ +static void setup_dma_to_phys(dma_addr_t dma, phys_addr_t delta, dma_addr_t s) +{ + int dma_idx, first_idx, last_idx; + phys_addr_t first, last; + + /* + * Calculate the first and last indices, rounding the first up and + * the second down. + */ + first = dma & ~IOR_DMA_GRAIN_MASK; + last = (dma + s - 1) & ~IOR_DMA_GRAIN_MASK; + first_idx = first >> IOR_LSBITS; /* Convert to indices */ + last_idx = last >> IOR_LSBITS; + + for (dma_idx = first_idx; dma_idx <= last_idx; dma_idx++) + _ior_dma_to_phys[dma_idx].offset = delta >> IOR_DMA_SHIFT; +} + +/** + * setup_phys_to_dma - set up conversion from DMA to physical addresses + * @phys_idx: Top IOR_LSBITS bits of the DMA address, i.e. an index + * into the array _phys_to_dma. + * @delta: Value that, when added to the DMA address, will yield the + * physical address + * @s: Number of bytes in the section of memory with the given delta + * between DMA and physical addresses. + */ +static void setup_phys_to_dma(phys_addr_t phys, dma_addr_t delta, phys_addr_t s) +{ + int phys_idx, first_idx, last_idx; + phys_addr_t first, last; + + /* + * Calculate the first and last indices, rounding the first up and + * the second down. + */ + first = phys & ~IOR_PHYS_GRAIN_MASK; + last = (phys + s - 1) & ~IOR_PHYS_GRAIN_MASK; + first_idx = first >> IOR_LSBITS; /* Convert to indices */ + last_idx = last >> IOR_LSBITS; + + for (phys_idx = first_idx; phys_idx <= last_idx; phys_idx++) + _ior_phys_to_dma[phys_idx].offset = delta >> IOR_PHYS_SHIFT; +} + +/** + * ioremap_add_map - add to the physical and DMA address conversion arrays + * @phys: Process's view of the address of the start of the memory chunk + * @dma: DMA address of the start of the memory chunk + * @size: Size, in bytes, of the chunk of memory + * + * NOTE: It might be obvious, but the assumption is that all @size bytes have + * the same offset between the physical address and the DMA address. + */ +void ioremap_add_map(phys_addr_t phys, phys_addr_t dma, phys_addr_t size) +{ + if (size == 0) + return; + + if ((dma & IOR_DMA_GRAIN_MASK) != 0 || + (phys & IOR_PHYS_GRAIN_MASK) != 0 || + (size & IOR_PHYS_GRAIN_MASK) != 0) + pr_crit("Memory allocation must be in chunks of 0x%x bytes\n", + IOR_PHYS_GRAIN); + + setup_dma_to_phys(dma, phys - dma, size); + setup_phys_to_dma(phys, dma - phys, size); +} diff --git a/arch/mips/powertv/memory.c b/arch/mips/powertv/memory.c index f49eb3d..73880ad 100644 --- a/arch/mips/powertv/memory.c +++ b/arch/mips/powertv/memory.c @@ -30,28 +30,141 @@ #include #include +#include +#include #include "init.h" /* Memory constants */ #define KIBIBYTE(n) ((n) * 1024) /* Number of kibibytes */ #define MEBIBYTE(n) ((n) * KIBIBYTE(1024)) /* Number of mebibytes */ -#define DEFAULT_MEMSIZE MEBIBYTE(256) /* If no memsize provided */ -#define LOW_MEM_MAX MEBIBYTE(252) /* Max usable low mem */ -#define RES_BOOTLDR_MEMSIZE MEBIBYTE(1) /* Memory reserved for bldr */ -#define BOOT_MEM_SIZE KIBIBYTE(256) /* Memory reserved for bldr */ -#define PHYS_MEM_START 0x10000000 /* Start of physical memory */ +#define DEFAULT_MEMSIZE MEBIBYTE(128) /* If no memsize provided */ -char __initdata cmdline[COMMAND_LINE_SIZE]; +#define BLDR_SIZE KIBIBYTE(256) /* Memory reserved for bldr */ +#define RV_SIZE MEBIBYTE(4) /* Size of reset vector */ -void __init prom_meminit(void) +#define LOW_MEM_END 0x20000000 /* Highest low memory address */ +#define BLDR_ALIAS 0x10000000 /* Bootloader address */ +#define RV_PHYS 0x1fc00000 /* Reset vector address */ +#define LOW_RAM_END RV_PHYS /* End of real RAM in low mem */ + +/* + * Very low-level conversion from processor physical address to device + * DMA address for the first bank of memory. + */ +#define PHYS_TO_DMA(paddr) ((paddr) + (CONFIG_LOW_RAM_DMA - LOW_RAM_ALIAS)) + +unsigned long ptv_memsize; + +/* + * struct low_mem_reserved - Items in low memmory that are reserved + * @start: Physical address of item + * @size: Size, in bytes, of this item + * @is_aliased: True if this is RAM aliased from another location. If false, + * it is something other than aliased RAM and the RAM in the + * unaliased address is still visible outside of low memory. + */ +struct low_mem_reserved { + phys_addr_t start; + phys_addr_t size; + bool is_aliased; +}; + +/* + * Must be in ascending address order + */ +struct low_mem_reserved low_mem_reserved[] = { + {BLDR_ALIAS, BLDR_SIZE, true}, /* Bootloader RAM */ + {RV_PHYS, RV_SIZE, false}, /* Reset vector */ +}; + +/* + * struct mem_layout - layout of a piece of the system RAM + * @phys: Physical address of the start of this piece of RAM. This is the + * address at which both the processor and I/O devices see the + * RAM. + * @alias: Alias of this piece of memory in order to make it appear in + * the low memory part of the processor's address space. I/O + * devices don't see anything here. + * @size: Size, in bytes, of this piece of RAM + */ +struct mem_layout { + phys_addr_t phys; + phys_addr_t alias; + phys_addr_t size; +}; + +/* + * struct mem_layout_list - list descriptor for layouts of system RAM pieces + * @family: Specifies the family being described + * @n: Number of &struct mem_layout elements + * @layout: Pointer to the list of &mem_layout structures + */ +struct mem_layout_list { + enum family_type family; + size_t n; + struct mem_layout *layout; +}; + +static struct mem_layout f1500_layout[] = { + {0x20000000, 0x10000000, MEBIBYTE(256)}, +}; + +static struct mem_layout f4500_layout[] = { + {0x40000000, 0x10000000, MEBIBYTE(256)}, + {0x20000000, 0x20000000, MEBIBYTE(32)}, +}; + +static struct mem_layout f8500_layout[] = { + {0x40000000, 0x10000000, MEBIBYTE(256)}, + {0x20000000, 0x20000000, MEBIBYTE(32)}, + {0x30000000, 0x30000000, MEBIBYTE(32)}, +}; + +static struct mem_layout fx600_layout[] = { + {0x20000000, 0x10000000, MEBIBYTE(256)}, + {0x60000000, 0x60000000, MEBIBYTE(128)}, +}; + +static struct mem_layout_list layout_list[] = { + {FAMILY_1500, ARRAY_SIZE(f1500_layout), f1500_layout}, + {FAMILY_1500VZE, ARRAY_SIZE(f1500_layout), f1500_layout}, + {FAMILY_1500VZF, ARRAY_SIZE(f1500_layout), f1500_layout}, + {FAMILY_4500, ARRAY_SIZE(f4500_layout), f4500_layout}, + {FAMILY_8500, ARRAY_SIZE(f8500_layout), f8500_layout}, + {FAMILY_8500RNG, ARRAY_SIZE(f8500_layout), f8500_layout}, + {FAMILY_4600, ARRAY_SIZE(fx600_layout), fx600_layout}, + {FAMILY_4600VZA, ARRAY_SIZE(fx600_layout), fx600_layout}, + {FAMILY_8600, ARRAY_SIZE(fx600_layout), fx600_layout}, + {FAMILY_8600VZB, ARRAY_SIZE(fx600_layout), fx600_layout}, +}; + +/* If we can't determine the layout, use this */ +static struct mem_layout default_layout[] = { + {0x20000000, 0x10000000, MEBIBYTE(128)}, +}; + +/** + * register_non_ram - register low memory not available for RAM usage + */ +static __init void register_non_ram(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(low_mem_reserved); i++) + add_memory_region(low_mem_reserved[i].start, + low_mem_reserved[i].size, BOOT_MEM_RESERVED); +} + +/** + * get_memsize - get the size of memory as a single bank + */ +static phys_addr_t get_memsize(void) { + static char cmdline[COMMAND_LINE_SIZE] __initdata; + phys_addr_t memsize = 0; char *memsize_str; - unsigned long memsize = 0; - unsigned int physend; char *ptr; - int low_mem; - int high_mem; /* Check the command line first for a memsize directive */ strcpy(cmdline, arcs_cmdline); @@ -73,96 +186,156 @@ void __init prom_meminit(void) if (memsize == 0) { if (_prom_memsize != 0) { memsize = _prom_memsize; - pr_info("_prom_memsize = 0x%lx\n", memsize); + pr_info("_prom_memsize = 0x%x\n", memsize); /* add in memory that the bootloader doesn't * report */ - memsize += BOOT_MEM_SIZE; + memsize += BLDR_SIZE; } else { memsize = DEFAULT_MEMSIZE; pr_info("Memsize not passed by bootloader, " - "defaulting to 0x%lx\n", memsize); + "defaulting to 0x%x\n", memsize); } } } - physend = PFN_ALIGN(&_end) - 0x80000000; - if (memsize > LOW_MEM_MAX) { - low_mem = LOW_MEM_MAX; - high_mem = memsize - low_mem; - } else { - low_mem = memsize; - high_mem = 0; + return memsize; +} + +/** + * register_low_ram - register an aliased section of RAM + * @p: Alias address of memory + * @n: Number of bytes in this section of memory + * + * Returns the number of bytes registered + * + */ +static __init phys_addr_t register_low_ram(phys_addr_t p, phys_addr_t n) +{ + phys_addr_t s; + int i; + phys_addr_t orig_n; + + orig_n = n; + + BUG_ON(p + n > RV_PHYS); + + for (i = 0; n != 0 && i < ARRAY_SIZE(low_mem_reserved); i++) { + phys_addr_t start; + phys_addr_t size; + + start = low_mem_reserved[i].start; + size = low_mem_reserved[i].size; + + /* Handle memory before this low memory section */ + if (p < start) { + phys_addr_t s; + s = min(n, start - p); + add_memory_region(p, s, BOOT_MEM_RAM); + p += s; + n -= s; + } + + /* Handle the low memory section itself. If it's aliased, + * we reduce the number of byes left, but if not, the RAM + * is available elsewhere and we don't reduce the number of + * bytes remaining. */ + if (p == start) { + if (low_mem_reserved[i].is_aliased) { + s = min(n, size); + n -= s; + p += s; + } else + p += n; + } } + return orig_n - n; +} + /* - * TODO: We will use the hard code for memory configuration until - * the bootloader releases their device tree to us. + * register_ram - register real RAM + * @p: Address of memory as seen by devices + * @alias: If the memory is seen at an additional address by the processor, + * this will be the address, otherwise it is the same as @p. + * @n: Number of bytes in this section of memory */ +static __init void register_ram(phys_addr_t p, phys_addr_t alias, + phys_addr_t n) +{ /* - * Add the memory reserved for use by the bootloader to the - * memory map. - */ - add_memory_region(PHYS_MEM_START, RES_BOOTLDR_MEMSIZE, - BOOT_MEM_RESERVED); -#ifdef CONFIG_HIGHMEM_256_128 - /* - * Add memory in low for general use by the kernel and its friends - * (like drivers, applications, etc). - */ - add_memory_region(PHYS_MEM_START + RES_BOOTLDR_MEMSIZE, - LOW_MEM_MAX - RES_BOOTLDR_MEMSIZE, BOOT_MEM_RAM); - /* - * Add the memory reserved for reset vector. - */ - add_memory_region(0x1fc00000, MEBIBYTE(4), BOOT_MEM_RESERVED); - /* - * Add the memory reserved. - */ - add_memory_region(0x20000000, MEBIBYTE(1024 + 75), BOOT_MEM_RESERVED); - /* - * Add memory in high for general use by the kernel and its friends - * (like drivers, applications, etc). - * - * 75MB is reserved for devices which are using the memory in high. - */ - add_memory_region(0x60000000 + MEBIBYTE(75), MEBIBYTE(128 - 75), - BOOT_MEM_RAM); -#elif defined CONFIG_HIGHMEM_128_128 - /* - * Add memory in low for general use by the kernel and its friends - * (like drivers, applications, etc). - */ - add_memory_region(PHYS_MEM_START + RES_BOOTLDR_MEMSIZE, - MEBIBYTE(128) - RES_BOOTLDR_MEMSIZE, BOOT_MEM_RAM); - /* - * Add the memory reserved. - */ - add_memory_region(PHYS_MEM_START + MEBIBYTE(128), - MEBIBYTE(128 + 1024 + 75), BOOT_MEM_RESERVED); - /* - * Add memory in high for general use by the kernel and its friends - * (like drivers, applications, etc). - * - * 75MB is reserved for devices which are using the memory in high. - */ - add_memory_region(0x60000000 + MEBIBYTE(75), MEBIBYTE(128 - 75), - BOOT_MEM_RAM); -#else - /* Add low memory regions for either: - * - no-highmemory configuration case -OR- - * - highmemory "HIGHMEM_LOWBANK_ONLY" case - */ - /* - * Add memory for general use by the kernel and its friends - * (like drivers, applications, etc). + * If some or all of this memory has an alias, break it into the + * aliased and non-aliased portion. */ - add_memory_region(PHYS_MEM_START + RES_BOOTLDR_MEMSIZE, - low_mem - RES_BOOTLDR_MEMSIZE, BOOT_MEM_RAM); + if (p != alias) { + phys_addr_t alias_size; + phys_addr_t registered; + + alias_size = min(n, LOW_RAM_END - alias); + registered = register_low_ram(alias, alias_size); + ioremap_add_map(alias, p, n); + n -= registered; + p += registered; + } + +#ifdef CONFIG_HIGHMEM + if (n != 0) { + add_memory_region(p, n, BOOT_MEM_RAM); + ioremap_add_map(p, p, n); + } +#endif +} + +/** + * register_address_space - register things in the address space + * @memsize: Number of bytes of RAM installed + * + * Takes the given number of bytes of RAM and registers as many of the regions, + * or partial regions, as it can. So, the default configuration might have + * two regions with 256 MiB each. If the memsize passed in on the command line + * is 384 MiB, it will register the first region with 256 MiB and the second + * with 128 MiB. + */ +static __init void register_address_space(phys_addr_t memsize) +{ + int i; + phys_addr_t size; + size_t n; + struct mem_layout *layout; + enum family_type family; + /* - * Add the memory reserved for reset vector. + * Register all of the things that aren't available to the kernel as + * memory. */ - add_memory_region(0x1fc00000, MEBIBYTE(4), BOOT_MEM_RESERVED); -#endif + register_non_ram(); + + /* Find the appropriate memory description */ + family = platform_get_family(); + + for (i = 0; i < ARRAY_SIZE(layout_list); i++) { + if (layout_list[i].family == family) + break; + } + + if (i == ARRAY_SIZE(layout_list)) { + n = ARRAY_SIZE(default_layout); + layout = default_layout; + } else { + n = layout_list[i].n; + layout = layout_list[i].layout; + } + + for (i = 0; memsize != 0 && i < n; i++) { + size = min(memsize, layout[i].size); + register_ram(layout[i].phys, layout[i].alias, size); + memsize -= size; + } +} + +void __init prom_meminit(void) +{ + ptv_memsize = get_memsize(); + register_address_space(ptv_memsize); } void __init prom_free_prom_memory(void) -- cgit v0.10.2 From 339e658b88108d4bc7daf61736df494dcf4a43e4 Mon Sep 17 00:00:00 2001 From: David VomLehn Date: Fri, 21 May 2010 11:25:59 -0700 Subject: MIPS: PowerTV: Correct ASIC device register names and locations Correct ASIC device register names and addresses for USB devices. Signed-off-by: David VomLehn To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1258/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-powertv/asic_reg_map.h b/arch/mips/include/asm/mach-powertv/asic_reg_map.h index 6f26cb0..20348e8 100644 --- a/arch/mips/include/asm/mach-powertv/asic_reg_map.h +++ b/arch/mips/include/asm/mach-powertv/asic_reg_map.h @@ -64,7 +64,7 @@ REGISTER_MAP_ELEMENT(int_level_0_1) REGISTER_MAP_ELEMENT(int_level_0_0) REGISTER_MAP_ELEMENT(int_docsis_en) REGISTER_MAP_ELEMENT(mips_pll_setup) -REGISTER_MAP_ELEMENT(usb_fs) +REGISTER_MAP_ELEMENT(fs432x4b4_usb_ctl) REGISTER_MAP_ELEMENT(test_bus) REGISTER_MAP_ELEMENT(crt_spare) REGISTER_MAP_ELEMENT(usb2_ohci_int_mask) diff --git a/arch/mips/powertv/asic/asic-calliope.c b/arch/mips/powertv/asic/asic-calliope.c index 1ae6623..0a170e0 100644 --- a/arch/mips/powertv/asic/asic-calliope.c +++ b/arch/mips/powertv/asic/asic-calliope.c @@ -77,7 +77,7 @@ const struct register_map calliope_register_map __initdata = { .int_docsis_en = {.phys = CALLIOPE_ADDR(0xA028F4)}, .mips_pll_setup = {.phys = CALLIOPE_ADDR(0x980000)}, - .usb_fs = {.phys = CALLIOPE_ADDR(0x980030)}, + .fs432x4b4_usb_ctl = {.phys = CALLIOPE_ADDR(0x980030)}, .test_bus = {.phys = CALLIOPE_ADDR(0x9800CC)}, .crt_spare = {.phys = CALLIOPE_ADDR(0x9800d4)}, .usb2_ohci_int_mask = {.phys = CALLIOPE_ADDR(0x9A000c)}, diff --git a/arch/mips/powertv/asic/asic-cronus.c b/arch/mips/powertv/asic/asic-cronus.c index 5bb64bf..bbc0c12 100644 --- a/arch/mips/powertv/asic/asic-cronus.c +++ b/arch/mips/powertv/asic/asic-cronus.c @@ -77,13 +77,13 @@ const struct register_map cronus_register_map __initdata = { .int_docsis_en = {.phys = CRONUS_ADDR(0x2A28F4)}, .mips_pll_setup = {.phys = CRONUS_ADDR(0x1C0000)}, - .usb_fs = {.phys = CRONUS_ADDR(0x1C0018)}, + .fs432x4b4_usb_ctl = {.phys = CRONUS_ADDR(0x1C0028)}, .test_bus = {.phys = CRONUS_ADDR(0x1C00CC)}, .crt_spare = {.phys = CRONUS_ADDR(0x1c00d4)}, .usb2_ohci_int_mask = {.phys = CRONUS_ADDR(0x20000C)}, .usb2_strap = {.phys = CRONUS_ADDR(0x200014)}, .ehci_hcapbase = {.phys = CRONUS_ADDR(0x21FE00)}, - .ohci_hc_revision = {.phys = CRONUS_ADDR(0x1E0000)}, + .ohci_hc_revision = {.phys = CRONUS_ADDR(0x21fc00)}, .bcm1_bs_lmi_steer = {.phys = CRONUS_ADDR(0x2E0008)}, .usb2_control = {.phys = CRONUS_ADDR(0x2E004C)}, .usb2_stbus_obc = {.phys = CRONUS_ADDR(0x21FF00)}, diff --git a/arch/mips/powertv/asic/asic-zeus.c b/arch/mips/powertv/asic/asic-zeus.c index 095cbe10..4a05bb0 100644 --- a/arch/mips/powertv/asic/asic-zeus.c +++ b/arch/mips/powertv/asic/asic-zeus.c @@ -77,7 +77,7 @@ const struct register_map zeus_register_map __initdata = { .int_docsis_en = {.phys = ZEUS_ADDR(0x2828F4)}, .mips_pll_setup = {.phys = ZEUS_ADDR(0x1a0000)}, - .usb_fs = {.phys = ZEUS_ADDR(0x1a0018)}, + .fs432x4b4_usb_ctl = {.phys = ZEUS_ADDR(0x1a0018)}, .test_bus = {.phys = ZEUS_ADDR(0x1a0238)}, .crt_spare = {.phys = ZEUS_ADDR(0x1a0090)}, .usb2_ohci_int_mask = {.phys = ZEUS_ADDR(0x1e000c)}, diff --git a/arch/mips/powertv/asic/asic_devices.c b/arch/mips/powertv/asic/asic_devices.c index c81dd49..006285c 100644 --- a/arch/mips/powertv/asic/asic_devices.c +++ b/arch/mips/powertv/asic/asic_devices.c @@ -180,9 +180,9 @@ static void __init fs_update(int pe, int md, int sdiv, int disable_div_by_3) val = ((sdiv << 29) | (md << 24) | (pe<<8) | (sout<<3) | (byp<<2) | (nsb<<1) | (disable_div_by_3<<5)); - asic_write(val, usb_fs); - asic_write(val | (en_prg<<4), usb_fs); - asic_write(val | (en_prg<<4) | pwr, usb_fs); + asic_write(val, fs432x4b4_usb_ctl); + asic_write(val | (en_prg<<4), fs432x4b4_usb_ctl); + asic_write(val | (en_prg<<4) | pwr, fs432x4b4_usb_ctl); } /* -- cgit v0.10.2 From d3bbfbc29d5010d4288f089370682a7b882fa559 Mon Sep 17 00:00:00 2001 From: Andrea Gelmini Date: Sun, 23 May 2010 21:52:03 +0200 Subject: MIPS: Yosemite: ht-irq.c: Checkpatch cleanup arch/mips/pmc-sierra/yosemite/ht-irq.c:38: ERROR: code indent should use tabs where possible arch/mips/pmc-sierra/yosemite/ht-irq.c:39: ERROR: code indent should use tabs where possible arch/mips/pmc-sierra/yosemite/ht-irq.c:40: ERROR: code indent should use tabs where possible arch/mips/pmc-sierra/yosemite/ht-irq.c:43: ERROR: code indent should use tabs where possible arch/mips/pmc-sierra/yosemite/ht-irq.c:44: ERROR: code indent should use tabs where possible arch/mips/pmc-sierra/yosemite/ht-irq.c:45: ERROR: code indent should use tabs where possible Signed-off-by: Andrea Gelmini Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1268/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/pmc-sierra/yosemite/ht-irq.c b/arch/mips/pmc-sierra/yosemite/ht-irq.c index 5aec405..86b98e9 100644 --- a/arch/mips/pmc-sierra/yosemite/ht-irq.c +++ b/arch/mips/pmc-sierra/yosemite/ht-irq.c @@ -35,18 +35,17 @@ */ void __init titan_ht_pcibios_fixup_bus(struct pci_bus *bus) { - struct pci_bus *current_bus = bus; - struct pci_dev *devices; - struct list_head *devices_link; + struct pci_bus *current_bus = bus; + struct pci_dev *devices; + struct list_head *devices_link; list_for_each(devices_link, &(current_bus->devices)) { - devices = pci_dev_b(devices_link); - if (devices == NULL) - continue; + devices = pci_dev_b(devices_link); + if (devices == NULL) + continue; } /* * PLX and SPKT related changes go here */ - } -- cgit v0.10.2 From cb5dcea176a87d47a7c2e8d8ac5ecf6a667140a1 Mon Sep 17 00:00:00 2001 From: Andrea Gelmini Date: Sun, 23 May 2010 21:52:04 +0200 Subject: MIPS: DECstation: Checkpatch cleanup arch/mips/dec/promcon.c:37: ERROR: that open brace { should be on the previous line Signed-off-by: Andrea Gelmini Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1270/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/dec/promcon.c b/arch/mips/dec/promcon.c index 9f0972f..c239c25b 100644 --- a/arch/mips/dec/promcon.c +++ b/arch/mips/dec/promcon.c @@ -33,8 +33,7 @@ static int __init prom_console_setup(struct console *co, char *options) return 0; } -static struct console sercons = -{ +static struct console sercons = { .name = "ttyS", .write = prom_console_write, .setup = prom_console_setup, -- cgit v0.10.2 From 055899a0e249ad9c1c709376c37ee7103abb22c4 Mon Sep 17 00:00:00 2001 From: Andrea Gelmini Date: Sun, 23 May 2010 21:52:05 +0200 Subject: MIPS: math-emu: Checkpatch cleanup arch/mips/math-emu/dp_modf.c:32: ERROR: "foo * bar" should be "foo *bar" Signed-off-by: Andrea Gelmini Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1269/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/dp_modf.c b/arch/mips/math-emu/dp_modf.c index 25861a4..a8570e5 100644 --- a/arch/mips/math-emu/dp_modf.c +++ b/arch/mips/math-emu/dp_modf.c @@ -29,7 +29,7 @@ /* modf function is always exact for a finite number */ -ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip) +ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp *ip) { COMPXDP; -- cgit v0.10.2 From 6337f5e5aab7faf6029d9ac4eba7496295bdf93c Mon Sep 17 00:00:00 2001 From: Andrea Gelmini Date: Sun, 23 May 2010 21:52:06 +0200 Subject: MIPS: math-emu: Checkpatch cleanup arch/mips/math-emu/dp_tint.c:73: ERROR: else should follow close brace '}' Signed-off-by: Andrea Gelmini Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1271/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/dp_tint.c b/arch/mips/math-emu/dp_tint.c index 77b2b7c..2447862 100644 --- a/arch/mips/math-emu/dp_tint.c +++ b/arch/mips/math-emu/dp_tint.c @@ -69,8 +69,7 @@ int ieee754dp_tint(ieee754dp x) round = 0; sticky = residue != 0; xm = 0; - } - else { + } else { residue = xm << (64 - DP_MBITS + xe); round = (residue >> 63) != 0; sticky = (residue << 1) != 0; -- cgit v0.10.2 From c273625b42dc93094b9f5db64944a0a8c6775c99 Mon Sep 17 00:00:00 2001 From: Andrea Gelmini Date: Sun, 23 May 2010 21:52:07 +0200 Subject: MIPS: math-emu: Checkpatch cleanup arch/mips/math-emu/dp_tlong.c:75: ERROR: else should follow close brace '}' Signed-off-by: Andrea Gelmini Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1272/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/dp_tlong.c b/arch/mips/math-emu/dp_tlong.c index d71113e..0f07ec2 100644 --- a/arch/mips/math-emu/dp_tlong.c +++ b/arch/mips/math-emu/dp_tlong.c @@ -71,8 +71,7 @@ s64 ieee754dp_tlong(ieee754dp x) round = 0; sticky = residue != 0; xm = 0; - } - else { + } else { /* Shifting a u64 64 times does not work, * so we do it in two steps. Be aware that xe * may be -1 */ -- cgit v0.10.2 From 24da36cdc5c7bc8ccde1876f81f884d6d42c0602 Mon Sep 17 00:00:00 2001 From: Andrea Gelmini Date: Sun, 23 May 2010 21:52:08 +0200 Subject: MIPS: math-emu: Checkpatch cleanup arch/mips/math-emu/sp_modf.c:32: ERROR: "foo * bar" should be "foo *bar" Signed-off-by: Andrea Gelmini Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1273/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/sp_modf.c b/arch/mips/math-emu/sp_modf.c index 4b1dbac..7656894 100644 --- a/arch/mips/math-emu/sp_modf.c +++ b/arch/mips/math-emu/sp_modf.c @@ -29,7 +29,7 @@ /* modf function is always exact for a finite number */ -ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip) +ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp *ip) { COMPXSP; -- cgit v0.10.2 From 3e4088affe2bd73dc4235cf0cc735722641085a6 Mon Sep 17 00:00:00 2001 From: Andrea Gelmini Date: Sun, 23 May 2010 21:52:09 +0200 Subject: MIPS: math-emu: Checkpatch cleanup arch/mips/math-emu/sp_tint.c:76: ERROR: else should follow close brace '}' Signed-off-by: Andrea Gelmini Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1275/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/sp_tint.c b/arch/mips/math-emu/sp_tint.c index 1d73d2a..352dc3a 100644 --- a/arch/mips/math-emu/sp_tint.c +++ b/arch/mips/math-emu/sp_tint.c @@ -72,8 +72,7 @@ int ieee754sp_tint(ieee754sp x) round = 0; sticky = residue != 0; xm = 0; - } - else { + } else { /* Shifting a u32 32 times does not work, * so we do it in two steps. Be aware that xe * may be -1 */ -- cgit v0.10.2 From abb86dc5430abe4e07f53b9221fc8eb59321dc41 Mon Sep 17 00:00:00 2001 From: Andrea Gelmini Date: Sun, 23 May 2010 21:52:10 +0200 Subject: MIPS: math-emu: Checkpatch cleanup arch/mips/math-emu/sp_tlong.c:75: ERROR: else should follow close brace '}' Signed-off-by: Andrea Gelmini Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1276/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/sp_tlong.c b/arch/mips/math-emu/sp_tlong.c index 4be21aa..92cd9c5 100644 --- a/arch/mips/math-emu/sp_tlong.c +++ b/arch/mips/math-emu/sp_tlong.c @@ -71,8 +71,7 @@ s64 ieee754sp_tlong(ieee754sp x) round = 0; sticky = residue != 0; xm = 0; - } - else { + } else { residue = xm << (32 - SP_MBITS + xe); round = (residue >> 31) != 0; sticky = (residue << 1) != 0; -- cgit v0.10.2 From 11ed4add992062de988773287c32e43f294968ac Mon Sep 17 00:00:00 2001 From: Andrea Gelmini Date: Sun, 23 May 2010 21:52:11 +0200 Subject: MIPS: PCI: RM9000 checkpatch cleanup arch/mips/pci/ops-titan-ht.c:36: ERROR: "foo * bar" should be "foo *bar" arch/mips/pci/ops-titan-ht.c:68: ERROR: "foo * bar" should be "foo *bar" Signed-off-by: Andrea Gelmini Cc: Tejun Heo Cc: Christoph Lameter Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1277/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/pci/ops-titan-ht.c b/arch/mips/pci/ops-titan-ht.c index 749c192..57d54ad 100644 --- a/arch/mips/pci/ops-titan-ht.c +++ b/arch/mips/pci/ops-titan-ht.c @@ -32,7 +32,7 @@ #include static int titan_ht_config_read_dword(struct pci_bus *bus, unsigned int devfn, - int offset, u32 * val) + int offset, u32 *val) { volatile uint32_t address; int busno; @@ -64,7 +64,7 @@ static int titan_ht_config_read_dword(struct pci_bus *bus, unsigned int devfn, } static int titan_ht_config_read(struct pci_bus *bus, unsigned int devfn, - int offset, int size, u32 * val) + int offset, int size, u32 *val) { uint32_t dword; -- cgit v0.10.2 From 78e6f4c03d51e4004866918a1482d48624e38d67 Mon Sep 17 00:00:00 2001 From: Andrea Gelmini Date: Sun, 23 May 2010 21:52:12 +0200 Subject: MIPS: IP27: klconfig.c checkpatch cleanup arch/mips/sgi-ip27/ip27-klconfig.c:51: ERROR: "foo * bar" should be "foo *bar" arch/mips/sgi-ip27/ip27-klconfig.c:63: ERROR: "foo * bar" should be "foo *bar" arch/mips/sgi-ip27/ip27-klconfig.c:81: ERROR: "foo * bar" should be "foo *bar" arch/mips/sgi-ip27/ip27-klconfig.c:100: ERROR: "foo * bar" should be "foo *bar" Signed-off-by: Andrea Gelmini Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1278/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/sgi-ip27/ip27-klconfig.c b/arch/mips/sgi-ip27/ip27-klconfig.c index dd830b3..7afe146 100644 --- a/arch/mips/sgi-ip27/ip27-klconfig.c +++ b/arch/mips/sgi-ip27/ip27-klconfig.c @@ -48,7 +48,7 @@ klinfo_t *find_first_component(lboard_t *brd, unsigned char struct_type) return find_component(brd, (klinfo_t *)NULL, struct_type); } -lboard_t * find_lboard(lboard_t *start, unsigned char brd_type) +lboard_t *find_lboard(lboard_t *start, unsigned char brd_type) { /* Search all boards stored on this node. */ while (start) { @@ -60,7 +60,7 @@ lboard_t * find_lboard(lboard_t *start, unsigned char brd_type) return (lboard_t *)NULL; } -lboard_t * find_lboard_class(lboard_t *start, unsigned char brd_type) +lboard_t *find_lboard_class(lboard_t *start, unsigned char brd_type) { /* Search all boards stored on this node. */ while (start) { @@ -78,7 +78,7 @@ cnodeid_t get_cpu_cnode(cpuid_t cpu) return CPUID_TO_COMPACT_NODEID(cpu); } -klcpu_t * nasid_slice_to_cpuinfo(nasid_t nasid, int slice) +klcpu_t *nasid_slice_to_cpuinfo(nasid_t nasid, int slice) { lboard_t *brd; klcpu_t *acpu; @@ -97,7 +97,7 @@ klcpu_t * nasid_slice_to_cpuinfo(nasid_t nasid, int slice) return (klcpu_t *)NULL; } -klcpu_t * sn_get_cpuinfo(cpuid_t cpu) +klcpu_t *sn_get_cpuinfo(cpuid_t cpu) { nasid_t nasid; int slice; -- cgit v0.10.2 From 9aeb404b4cfed41fdfd01e6fb3cc995c327ba98e Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 30 May 2010 13:27:22 +0200 Subject: MIPS: Introduce arch/mips/Kbuild Signed-off-by: Sam Ravnborg To: linux-mips To: Wu Zhangjin Patchwork: https://patchwork.linux-mips.org/patch/1300/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild b/arch/mips/Kbuild new file mode 100644 index 0000000..a18eb5d4 --- /dev/null +++ b/arch/mips/Kbuild @@ -0,0 +1,6 @@ +# mips object files +# The object files are linked as core-y files would be linked + +obj-y += kernel/ +obj-y += mm/ +obj-y += math-emu/ diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 0b9c01a..d39be47 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -706,7 +706,8 @@ head-y := arch/mips/kernel/head.o arch/mips/kernel/init_task.o libs-y += arch/mips/lib/ -core-y += arch/mips/kernel/ arch/mips/mm/ arch/mips/math-emu/ +# See arch/mips/Kbuild for content of core part of the kernel +core-y += arch/mips/ drivers-$(CONFIG_OPROFILE) += arch/mips/oprofile/ -- cgit v0.10.2 From 66f9ba101f54bda63ab1db97f9e9e94763d0651b Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 30 May 2010 16:26:40 +0200 Subject: MIPS: Add -Werror to arch/mips/Kbuild Adding subdirs-ccflags-y := -Werror to arch/mips/Kbuild let us in one go cover all files with -Werror. In addition this allows us to remove the individual -Werror definition in various Makefile. Adding the definition to Kbuild as a recursive option help us not to forget to do so. With this change we now compile arch/mips/kernel/cpufreq with -Werror One drawback: When specifying a subdirectory covered by the Kbuild file like this: make arch/mips/kernel/ then kbuild fails to pick up the -Werror definition. Signed-off-by: Sam Ravnborg To: linux-mips To: Wu Zhangjin Patchwork: https://patchwork.linux-mips.org/patch/1301/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild b/arch/mips/Kbuild index a18eb5d4..6ce9382 100644 --- a/arch/mips/Kbuild +++ b/arch/mips/Kbuild @@ -1,3 +1,9 @@ +# Fail on warnings - also for files referenced in subdirs +# -Werror can be disabled for specific files using: +# CFLAGS_ := -Wno-error +subdir-ccflags-y := -Werror + + # mips object files # The object files are linked as core-y files would be linked diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 7a6ac50..ff5ec2e 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -101,6 +101,4 @@ obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) += 8250-platform.o obj-$(CONFIG_MIPS_CPUFREQ) += cpufreq/ -EXTRA_CFLAGS += -Werror - CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS) diff --git a/arch/mips/math-emu/Makefile b/arch/mips/math-emu/Makefile index d547efd..9660723 100644 --- a/arch/mips/math-emu/Makefile +++ b/arch/mips/math-emu/Makefile @@ -10,4 +10,3 @@ obj-y := cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \ sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \ dp_sqrt.o sp_sqrt.o kernel_linkage.o dsemul.o -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile index f0e4355..d679c77 100644 --- a/arch/mips/mm/Makefile +++ b/arch/mips/mm/Makefile @@ -34,5 +34,3 @@ obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o obj-$(CONFIG_MIPS_CPU_SCACHE) += sc-mips.o - -EXTRA_CFLAGS += -Werror -- cgit v0.10.2 From 5d25b01cf90c1a27d196a52f48d5364458b80b86 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 30 May 2010 16:27:10 +0200 Subject: MIPS: Introduce support for Platform definitions Move platform specific definitions to the platfrom directories. Each platform shall do the following: 1) include an entry in arch/mips/Kbuild.platforms 2) add relevant definitions to arch/mips//Platform This commits changes ar7 to the new scheme as an example. Introducing a platform speecific Platfrom file has following advantages: 1) decentralization of platfrom definitions 2) simplification af arch/mips/Makefile 3) force all platfrom to build with -Werror (done in arch/mips/Kbuild) [Ralf: Remove forgotten -Werror from AR7 Makefile] Signed-off-by: Sam Ravnborg To: linux-mips To: Wu Zhangjin Patchwork: https://patchwork.linux-mips.org/patch/1302/ Patchwork: http://patchwork.linux-mips.org/patch/1308/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild b/arch/mips/Kbuild index 6ce9382..e322d65 100644 --- a/arch/mips/Kbuild +++ b/arch/mips/Kbuild @@ -3,6 +3,9 @@ # CFLAGS_ := -Wno-error subdir-ccflags-y := -Werror +# platform specific definitions +include arch/mips/Kbuild.platforms +obj-y := $(platform-y) # mips object files # The object files are linked as core-y files would be linked diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms new file mode 100644 index 0000000..681b2d4 --- /dev/null +++ b/arch/mips/Kbuild.platforms @@ -0,0 +1,6 @@ +# All platforms listed in alphabetic order + +platforms += ar7 + +# include the platform specific files +include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms)) diff --git a/arch/mips/Makefile b/arch/mips/Makefile index d39be47..b4ec8e9 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -209,13 +209,7 @@ endif # # Board-dependent options and extra files # - -# -# Texas Instruments AR7 -# -core-$(CONFIG_AR7) += arch/mips/ar7/ -cflags-$(CONFIG_AR7) += -I$(srctree)/arch/mips/include/asm/mach-ar7 -load-$(CONFIG_AR7) += 0xffffffff94100000 +include $(srctree)/arch/mips/Kbuild.platforms # # Acer PICA 61, Mips Magnum 4000 and Olivetti M700. diff --git a/arch/mips/ar7/Makefile b/arch/mips/ar7/Makefile index 26bc5da..7435e44 100644 --- a/arch/mips/ar7/Makefile +++ b/arch/mips/ar7/Makefile @@ -8,4 +8,3 @@ obj-y := \ platform.o \ gpio.o \ clock.o -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/ar7/Platform b/arch/mips/ar7/Platform new file mode 100644 index 0000000..0bf85c4 --- /dev/null +++ b/arch/mips/ar7/Platform @@ -0,0 +1,6 @@ +# +# Texas Instruments AR7 +# +platform-$(CONFIG_AR7) += ar7/ +cflags-$(CONFIG_AR7) += -I$(srctree)/arch/mips/include/asm/mach-ar7 +load-$(CONFIG_AR7) += 0xffffffff94100000 -- cgit v0.10.2 From 28c945c88676bf71ec649429f2c1c4ce3719cd7c Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Tue, 1 Jun 2010 18:29:04 +0800 Subject: MIPS: Loongson: Migrate makefile to new Platform file Signed-off-by: Wu Zhangjin To: linux-mips Cc: Alexander Clouter Cc: Manuel Lauss Cc: Sam Ravnborg , Patchwork: https://patchwork.linux-mips.org/patch/1313/ Patchwork: https://patchwork.linux-mips.org/patch/1326/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 681b2d4..9784c49 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -1,6 +1,7 @@ # All platforms listed in alphabetic order platforms += ar7 +platforms += loongson # include the platform specific files include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms)) diff --git a/arch/mips/Makefile b/arch/mips/Makefile index b4ec8e9..3eafe7f 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -130,26 +130,6 @@ cflags-$(CONFIG_CPU_R4300) += -march=r4300 -Wa,--trap cflags-$(CONFIG_CPU_VR41XX) += -march=r4100 -Wa,--trap cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap -# only gcc >= 4.4 have the loongson-specific support -cflags-$(CONFIG_CPU_LOONGSON2) += -Wa,--trap -cflags-$(CONFIG_CPU_LOONGSON2E) += \ - $(call cc-option,-march=loongson2e,-march=r4600) -cflags-$(CONFIG_CPU_LOONGSON2F) += \ - $(call cc-option,-march=loongson2f,-march=r4600) -# enable the workarounds for loongson2f -ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS - ifeq ($(call as-option,-Wa$(comma)-mfix-loongson2f-nop,),) - $(error only binutils >= 2.20.2 have needed option -mfix-loongson2f-nop) - else - cflags-$(CONFIG_CPU_NOP_WORKAROUNDS) += -Wa$(comma)-mfix-loongson2f-nop - endif - ifeq ($(call as-option,-Wa$(comma)-mfix-loongson2f-jump,),) - $(error only binutils >= 2.20.2 have needed option -mfix-loongson2f-jump) - else - cflags-$(CONFIG_CPU_JUMP_WORKAROUNDS) += -Wa$(comma)-mfix-loongson2f-jump - endif -endif - cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \ -Wa,-mips32 -Wa,--trap cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \ @@ -346,15 +326,6 @@ cflags-$(CONFIG_WR_PPMC) += -I$(srctree)/arch/mips/include/asm/mach-wrppmc load-$(CONFIG_WR_PPMC) += 0xffffffff80100000 # -# Loongson family -# -core-$(CONFIG_MACH_LOONGSON) += arch/mips/loongson/ -cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson \ - -mno-branch-likely -load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000 -load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000 - -# # MIPS Malta board # core-$(CONFIG_MIPS_MALTA) += arch/mips/mti-malta/ diff --git a/arch/mips/loongson/Platform b/arch/mips/loongson/Platform new file mode 100644 index 0000000..29692e5 --- /dev/null +++ b/arch/mips/loongson/Platform @@ -0,0 +1,32 @@ +# +# Loongson Processors' Support +# + +# Only gcc >= 4.4 have Loongson specific support +cflags-$(CONFIG_CPU_LOONGSON2) += -Wa,--trap +cflags-$(CONFIG_CPU_LOONGSON2E) += \ + $(call cc-option,-march=loongson2e,-march=r4600) +cflags-$(CONFIG_CPU_LOONGSON2F) += \ + $(call cc-option,-march=loongson2f,-march=r4600) +# Enable the workarounds for Loongson2f +ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS + ifeq ($(call as-option,-Wa$(comma)-mfix-loongson2f-nop,),) + $(error only binutils >= 2.20.2 have needed option -mfix-loongson2f-nop) + else + cflags-$(CONFIG_CPU_NOP_WORKAROUNDS) += -Wa$(comma)-mfix-loongson2f-nop + endif + ifeq ($(call as-option,-Wa$(comma)-mfix-loongson2f-jump,),) + $(error only binutils >= 2.20.2 have needed option -mfix-loongson2f-jump) + else + cflags-$(CONFIG_CPU_JUMP_WORKAROUNDS) += -Wa$(comma)-mfix-loongson2f-jump + endif +endif + +# +# Loongson Machines' Support +# + +platform-$(CONFIG_MACH_LOONGSON) += loongson/ +cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson -mno-branch-likely +load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000 +load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000 diff --git a/arch/mips/loongson/common/cs5536/Makefile b/arch/mips/loongson/common/cs5536/Makefile index 510d4cd..f12e640 100644 --- a/arch/mips/loongson/common/cs5536/Makefile +++ b/arch/mips/loongson/common/cs5536/Makefile @@ -9,5 +9,3 @@ obj-$(CONFIG_CS5536) += cs5536_pci.o cs5536_ide.o cs5536_acc.o cs5536_ohci.o \ # Enable cs5536 mfgpt Timer # obj-$(CONFIG_CS5536_MFGPT) += cs5536_mfgpt.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/loongson/fuloong-2e/Makefile b/arch/mips/loongson/fuloong-2e/Makefile index 3aba5fc..b762272 100644 --- a/arch/mips/loongson/fuloong-2e/Makefile +++ b/arch/mips/loongson/fuloong-2e/Makefile @@ -3,5 +3,3 @@ # obj-y += irq.o reset.o - -EXTRA_CFLAGS += -Werror -- cgit v0.10.2 From 526a2fe2f5d887ef8b89243c3a5e64f0f38c21cc Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:45 +0100 Subject: MIPS: MIPSsim: Migrate to new Platform file Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 9784c49..13244f3 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -2,6 +2,7 @@ platforms += ar7 platforms += loongson +platforms += mipssim # include the platform specific files include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms)) diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 3eafe7f..cc2ae36 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -334,13 +334,6 @@ load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000 all-$(CONFIG_MIPS_MALTA) := $(COMPRESSION_FNAME).bin # -# MIPS SIM -# -core-$(CONFIG_MIPS_SIM) += arch/mips/mipssim/ -cflags-$(CONFIG_MIPS_SIM) += -I$(srctree)/arch/mips/include/asm/mach-mipssim -load-$(CONFIG_MIPS_SIM) += 0x80100000 - -# # PMC-Sierra MSP SOCs # core-$(CONFIG_PMC_MSP) += arch/mips/pmc-sierra/msp71xx/ diff --git a/arch/mips/mipssim/Makefile b/arch/mips/mipssim/Makefile index 41b9657..01410a3 100644 --- a/arch/mips/mipssim/Makefile +++ b/arch/mips/mipssim/Makefile @@ -21,5 +21,3 @@ obj-y := sim_platform.o sim_setup.o sim_mem.o sim_time.o sim_int.o obj-$(CONFIG_EARLY_PRINTK) += sim_console.o obj-$(CONFIG_MIPS_MT_SMTC) += sim_smtc.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/mipssim/Platform b/arch/mips/mipssim/Platform new file mode 100644 index 0000000..3df60b8 --- /dev/null +++ b/arch/mips/mipssim/Platform @@ -0,0 +1,6 @@ +# +# MIPS SIM +# +platform-$(CONFIG_MIPS_SIM) += mipssim/ +cflags-$(CONFIG_MIPS_SIM) += -I$(srctree)/arch/mips/include/asm/mach-mipssim +load-$(CONFIG_MIPS_SIM) += 0x80100000 -- cgit v0.10.2 From 4767d7ddbb904ac481bcf1340eae7758d124db96 Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Tue, 1 Jun 2010 22:30:36 +0200 Subject: MIPS: Alchemy: move boards over to obj-y Preparatory step for moving Alchemy over to new MIPS Platform build system support. Signed-off-by: Manuel Lauss To: Linux-MIPS Patchwork: https://patchwork.linux-mips.org/patch/1318/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Makefile b/arch/mips/Makefile index cc2ae36..72f4357 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -290,13 +290,13 @@ load-$(CONFIG_MIPS_MIRAGE) += 0xffffffff80100000 # # 4G-Systems eval board # -libs-$(CONFIG_MIPS_MTX1) += arch/mips/alchemy/mtx-1/ +core-$(CONFIG_MIPS_MTX1) += arch/mips/alchemy/mtx-1/ load-$(CONFIG_MIPS_MTX1) += 0xffffffff80100000 # # MyCable eval board # -libs-$(CONFIG_MIPS_XXS1500) += arch/mips/alchemy/xxs1500/ +core-$(CONFIG_MIPS_XXS1500) += arch/mips/alchemy/xxs1500/ load-$(CONFIG_MIPS_XXS1500) += 0xffffffff80100000 # must be last for Alchemy systems for GPIO to work properly diff --git a/arch/mips/alchemy/mtx-1/Makefile b/arch/mips/alchemy/mtx-1/Makefile index 4a53815..f912022 100644 --- a/arch/mips/alchemy/mtx-1/Makefile +++ b/arch/mips/alchemy/mtx-1/Makefile @@ -6,7 +6,6 @@ # Makefile for 4G Systems MTX-1 board. # -lib-y := init.o board_setup.o -obj-y := platform.o +obj-y += init.o board_setup.o platform.o EXTRA_CFLAGS += -Werror diff --git a/arch/mips/alchemy/xxs1500/Makefile b/arch/mips/alchemy/xxs1500/Makefile index 4dc81d7..81c516e 100644 --- a/arch/mips/alchemy/xxs1500/Makefile +++ b/arch/mips/alchemy/xxs1500/Makefile @@ -5,6 +5,6 @@ # Makefile for MyCable XXS1500 board. # -lib-y := init.o board_setup.o platform.o +obj-y += init.o board_setup.o platform.o EXTRA_CFLAGS += -Werror -- cgit v0.10.2 From 25c8f83864878e1ec95c0bd8273405ab415eb0a4 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 24 Jun 2010 01:26:09 +0900 Subject: MIPS: Alchemy: fix deprecated compile warnings Replace deprecated DMA_32BIT_MASK with DMA_BIT_MASK. This is needed because the new style platform makefiles will enable -Werror. cc1: warnings being treated as errors arch/mips/alchemy/devboards/db1200/platform.c:219: error: 'DMA_nnBIT_MASK' is deprecated arch/mips/alchemy/devboards/db1200/platform.c:226: error: 'DMA_nnBIT_MASK' is deprecated arch/mips/alchemy/devboards/db1200/platform.c:388: error: 'DMA_nnBIT_MASK' is deprecated arch/mips/alchemy/devboards/db1200/platform.c:393: error: 'DMA_nnBIT_MASK' is deprecated Signed-off-by: FUJITA Tomonori To: linux-mips@linux-mips.org Acked-by: Manuel Lauss Patchwork: https://patchwork.linux-mips.org/patch/1427/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/alchemy/devboards/db1200/platform.c b/arch/mips/alchemy/devboards/db1200/platform.c index 3cb95a9..3fa34c3 100644 --- a/arch/mips/alchemy/devboards/db1200/platform.c +++ b/arch/mips/alchemy/devboards/db1200/platform.c @@ -216,14 +216,14 @@ static struct resource db1200_ide_res[] = { } }; -static u64 ide_dmamask = DMA_32BIT_MASK; +static u64 ide_dmamask = DMA_BIT_MASK(32); static struct platform_device db1200_ide_dev = { .name = "au1200-ide", .id = 0, .dev = { .dma_mask = &ide_dmamask, - .coherent_dma_mask = DMA_32BIT_MASK, + .coherent_dma_mask = DMA_BIT_MASK(32), }, .num_resources = ARRAY_SIZE(db1200_ide_res), .resource = db1200_ide_res, @@ -385,12 +385,12 @@ static struct au1550_spi_info db1200_spi_platdata = { .activate_cs = db1200_spi_cs_en, }; -static u64 spi_dmamask = DMA_32BIT_MASK; +static u64 spi_dmamask = DMA_BIT_MASK(32); static struct platform_device db1200_spi_dev = { .dev = { .dma_mask = &spi_dmamask, - .coherent_dma_mask = DMA_32BIT_MASK, + .coherent_dma_mask = DMA_BIT_MASK(32), .platform_data = &db1200_spi_platdata, }, .name = "au1550-spi", -- cgit v0.10.2 From baf3eb233df301081b66637a257ce0e9f6f84706 Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Tue, 1 Jun 2010 22:30:37 +0200 Subject: MIPS: Move Alchemy Makefile parts to their own Platform file. [Ralf: Remove a forgotten -Werror in Pb1200 Makefile.] Signed-off-by: Manuel Lauss To: Linux-MIPS Cc: Sam Ravnborg Cc: Manuel Lauss Patchwork: https://patchwork.linux-mips.org/patch/1319/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 13244f3..68794bb 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -1,5 +1,6 @@ # All platforms listed in alphabetic order +platforms += alchemy platforms += ar7 platforms += loongson platforms += mipssim diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 72f4357..57ca331 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -199,111 +199,6 @@ cflags-$(CONFIG_MACH_JAZZ) += -I$(srctree)/arch/mips/include/asm/mach-jazz load-$(CONFIG_MACH_JAZZ) += 0xffffffff80080000 # -# Common Alchemy Au1x00 stuff -# -core-$(CONFIG_SOC_AU1X00) += arch/mips/alchemy/common/ - -# -# AMD Alchemy Pb1000 eval board -# -core-$(CONFIG_MIPS_PB1000) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_PB1000) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 -load-$(CONFIG_MIPS_PB1000) += 0xffffffff80100000 - -# -# AMD Alchemy Pb1100 eval board -# -core-$(CONFIG_MIPS_PB1100) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_PB1100) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 -load-$(CONFIG_MIPS_PB1100) += 0xffffffff80100000 - -# -# AMD Alchemy Pb1500 eval board -# -core-$(CONFIG_MIPS_PB1500) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_PB1500) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 -load-$(CONFIG_MIPS_PB1500) += 0xffffffff80100000 - -# -# AMD Alchemy Pb1550 eval board -# -core-$(CONFIG_MIPS_PB1550) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_PB1550) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 -load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000 - -# -# AMD Alchemy Pb1200 eval board -# -core-$(CONFIG_MIPS_PB1200) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_PB1200) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 -load-$(CONFIG_MIPS_PB1200) += 0xffffffff80100000 - -# -# AMD Alchemy Db1000 eval board -# -core-$(CONFIG_MIPS_DB1000) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_DB1000) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 -load-$(CONFIG_MIPS_DB1000) += 0xffffffff80100000 - -# -# AMD Alchemy Db1100 eval board -# -core-$(CONFIG_MIPS_DB1100) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_DB1100) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 -load-$(CONFIG_MIPS_DB1100) += 0xffffffff80100000 - -# -# AMD Alchemy Db1500 eval board -# -core-$(CONFIG_MIPS_DB1500) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_DB1500) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 -load-$(CONFIG_MIPS_DB1500) += 0xffffffff80100000 - -# -# AMD Alchemy Db1550 eval board -# -core-$(CONFIG_MIPS_DB1550) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_DB1550) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 -load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000 - -# -# AMD Alchemy Db1200 eval board -# -core-$(CONFIG_MIPS_DB1200) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_DB1200) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 -load-$(CONFIG_MIPS_DB1200) += 0xffffffff80100000 - -# -# AMD Alchemy Bosporus eval board -# -core-$(CONFIG_MIPS_BOSPORUS) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_BOSPORUS) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 -load-$(CONFIG_MIPS_BOSPORUS) += 0xffffffff80100000 - -# -# AMD Alchemy Mirage eval board -# -core-$(CONFIG_MIPS_MIRAGE) += arch/mips/alchemy/devboards/ -cflags-$(CONFIG_MIPS_MIRAGE) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 -load-$(CONFIG_MIPS_MIRAGE) += 0xffffffff80100000 - -# -# 4G-Systems eval board -# -core-$(CONFIG_MIPS_MTX1) += arch/mips/alchemy/mtx-1/ -load-$(CONFIG_MIPS_MTX1) += 0xffffffff80100000 - -# -# MyCable eval board -# -core-$(CONFIG_MIPS_XXS1500) += arch/mips/alchemy/xxs1500/ -load-$(CONFIG_MIPS_XXS1500) += 0xffffffff80100000 - -# must be last for Alchemy systems for GPIO to work properly -cflags-$(CONFIG_SOC_AU1X00) += -I$(srctree)/arch/mips/include/asm/mach-au1x00 - - -# # Cobalt Server # core-$(CONFIG_MIPS_COBALT) += arch/mips/cobalt/ diff --git a/arch/mips/alchemy/Platform b/arch/mips/alchemy/Platform new file mode 100644 index 0000000..495cc9a --- /dev/null +++ b/arch/mips/alchemy/Platform @@ -0,0 +1,109 @@ +# +# Core Alchemy code +# +platform-$(CONFIG_MACH_ALCHEMY) += alchemy/common/ + + +# +# AMD Alchemy Pb1000 eval board +# +platform-$(CONFIG_MIPS_PB1000) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_PB1000) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 +load-$(CONFIG_MIPS_PB1000) += 0xffffffff80100000 + +# +# AMD Alchemy Pb1100 eval board +# +platform-$(CONFIG_MIPS_PB1100) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_PB1100) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 +load-$(CONFIG_MIPS_PB1100) += 0xffffffff80100000 + +# +# AMD Alchemy Pb1500 eval board +# +platform-$(CONFIG_MIPS_PB1500) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_PB1500) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 +load-$(CONFIG_MIPS_PB1500) += 0xffffffff80100000 + +# +# AMD Alchemy Pb1550 eval board +# +platform-$(CONFIG_MIPS_PB1550) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_PB1550) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 +load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000 + +# +# AMD Alchemy Pb1200 eval board +# +platform-$(CONFIG_MIPS_PB1200) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_PB1200) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00 +load-$(CONFIG_MIPS_PB1200) += 0xffffffff80100000 + +# +# AMD Alchemy Db1000 eval board +# +platform-$(CONFIG_MIPS_DB1000) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_DB1000) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 +load-$(CONFIG_MIPS_DB1000) += 0xffffffff80100000 + +# +# AMD Alchemy Db1100 eval board +# +platform-$(CONFIG_MIPS_DB1100) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_DB1100) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 +load-$(CONFIG_MIPS_DB1100) += 0xffffffff80100000 + +# +# AMD Alchemy Db1500 eval board +# +platform-$(CONFIG_MIPS_DB1500) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_DB1500) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 +load-$(CONFIG_MIPS_DB1500) += 0xffffffff80100000 + +# +# AMD Alchemy Db1550 eval board +# +platform-$(CONFIG_MIPS_DB1550) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_DB1550) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 +load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000 + +# +# AMD Alchemy Db1200 eval board +# +platform-$(CONFIG_MIPS_DB1200) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_DB1200) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 +load-$(CONFIG_MIPS_DB1200) += 0xffffffff80100000 + +# +# AMD Alchemy Bosporus eval board +# +platform-$(CONFIG_MIPS_BOSPORUS) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_BOSPORUS) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 +load-$(CONFIG_MIPS_BOSPORUS) += 0xffffffff80100000 + +# +# AMD Alchemy Mirage eval board +# +platform-$(CONFIG_MIPS_MIRAGE) += alchemy/devboards/ +cflags-$(CONFIG_MIPS_MIRAGE) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 +load-$(CONFIG_MIPS_MIRAGE) += 0xffffffff80100000 + +# +# 4G-Systems eval board +# +platform-$(CONFIG_MIPS_MTX1) += alchemy/mtx-1/ +load-$(CONFIG_MIPS_MTX1) += 0xffffffff80100000 + +# +# MyCable eval board +# +platform-$(CONFIG_MIPS_XXS1500) += alchemy/xxs1500/ +load-$(CONFIG_MIPS_XXS1500) += 0xffffffff80100000 + + +# boards can specify their own in one of their include dirs. +# If they do, placing this line here at the end will make sure the +# compiler picks the board one. If they don't, it will make sure +# the alchemy generic gpio header is picked up. + +cflags-$(CONFIG_MACH_ALCHEMY) += -I$(srctree)/arch/mips/include/asm/mach-au1x00 diff --git a/arch/mips/alchemy/common/Makefile b/arch/mips/alchemy/common/Makefile index 06c0e65..27811fe 100644 --- a/arch/mips/alchemy/common/Makefile +++ b/arch/mips/alchemy/common/Makefile @@ -18,5 +18,3 @@ ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),) endif obj-$(CONFIG_PCI) += pci.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/alchemy/devboards/Makefile b/arch/mips/alchemy/devboards/Makefile index ecbd37f..826449c 100644 --- a/arch/mips/alchemy/devboards/Makefile +++ b/arch/mips/alchemy/devboards/Makefile @@ -16,5 +16,3 @@ obj-$(CONFIG_MIPS_DB1500) += db1x00/ obj-$(CONFIG_MIPS_DB1550) += db1x00/ obj-$(CONFIG_MIPS_BOSPORUS) += db1x00/ obj-$(CONFIG_MIPS_MIRAGE) += db1x00/ - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/alchemy/devboards/pb1200/Makefile b/arch/mips/alchemy/devboards/pb1200/Makefile index 2ea9b02..18c1bd5 100644 --- a/arch/mips/alchemy/devboards/pb1200/Makefile +++ b/arch/mips/alchemy/devboards/pb1200/Makefile @@ -3,5 +3,3 @@ # obj-y := board_setup.o platform.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/alchemy/mtx-1/Makefile b/arch/mips/alchemy/mtx-1/Makefile index f912022..81b540c 100644 --- a/arch/mips/alchemy/mtx-1/Makefile +++ b/arch/mips/alchemy/mtx-1/Makefile @@ -7,5 +7,3 @@ # obj-y += init.o board_setup.o platform.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/alchemy/xxs1500/Makefile b/arch/mips/alchemy/xxs1500/Makefile index 81c516e..91defcf 100644 --- a/arch/mips/alchemy/xxs1500/Makefile +++ b/arch/mips/alchemy/xxs1500/Makefile @@ -6,5 +6,3 @@ # obj-y += init.o board_setup.o platform.o - -EXTRA_CFLAGS += -Werror -- cgit v0.10.2 From 6a0cd4dca00110fd11b8b07b7c2e08a60d22c580 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:47 +0100 Subject: MIPS: IP27: Migrate to new Platform file Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 68794bb..77e48b9 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -4,6 +4,7 @@ platforms += alchemy platforms += ar7 platforms += loongson platforms += mipssim +platforms += sgi-ip27 # include the platform specific files include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms)) diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 57ca331..ec2cd73 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -347,26 +347,6 @@ load-$(CONFIG_SGI_IP22) += 0xffffffff88004000 endif # -# SGI-IP27 (Origin200/2000) -# -# Set the load address to >= 0xc000000000300000 if you want to leave space for -# symmon, 0xc00000000001c000 for production kernels. Note that the value must -# be 16kb aligned or the handling of the current variable will break. -# -ifdef CONFIG_SGI_IP27 -core-$(CONFIG_SGI_IP27) += arch/mips/sgi-ip27/ -cflags-$(CONFIG_SGI_IP27) += -I$(srctree)/arch/mips/include/asm/mach-ip27 -ifdef CONFIG_MAPPED_KERNEL -load-$(CONFIG_SGI_IP27) += 0xc00000004001c000 -OBJCOPYFLAGS := --change-addresses=0x3fffffff80000000 -dataoffset-$(CONFIG_SGI_IP27) += 0x01000000 -else -load-$(CONFIG_SGI_IP27) += 0xa80000000001c000 -OBJCOPYFLAGS := --change-addresses=0x57ffffff80000000 -endif -endif - -# # SGI IP28 (Indigo2 R10k) # # Set the load address to >= 0xa800000020080000 if you want to leave space for diff --git a/arch/mips/sgi-ip27/Makefile b/arch/mips/sgi-ip27/Makefile index 31f4931..1f29e76 100644 --- a/arch/mips/sgi-ip27/Makefile +++ b/arch/mips/sgi-ip27/Makefile @@ -8,5 +8,3 @@ obj-y := ip27-berr.o ip27-irq.o ip27-init.o ip27-klconfig.o ip27-klnuma.o \ obj-$(CONFIG_EARLY_PRINTK) += ip27-console.o obj-$(CONFIG_SMP) += ip27-smp.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/sgi-ip27/Platform b/arch/mips/sgi-ip27/Platform new file mode 100644 index 0000000..1fb9c2e --- /dev/null +++ b/arch/mips/sgi-ip27/Platform @@ -0,0 +1,19 @@ +# +# SGI-IP27 (Origin200/2000) +# +# Set the load address to >= 0xc000000000300000 if you want to leave space for +# symmon, 0xc00000000001c000 for production kernels. Note that the value must +# be 16kb aligned or the handling of the current variable will break. +# +ifdef CONFIG_SGI_IP27 +platform-$(CONFIG_SGI_IP27) += sgi-ip27/ +cflags-$(CONFIG_SGI_IP27) += -I$(srctree)/arch/mips/include/asm/mach-ip27 +ifdef CONFIG_MAPPED_KERNEL +load-$(CONFIG_SGI_IP27) += 0xc00000004001c000 +OBJCOPYFLAGS := --change-addresses=0x3fffffff80000000 +dataoffset-$(CONFIG_SGI_IP27) += 0x01000000 +else +load-$(CONFIG_SGI_IP27) += 0xa80000000001c000 +OBJCOPYFLAGS := --change-addresses=0x57ffffff80000000 +endif +endif -- cgit v0.10.2 From 5c6aecbda882b62c84abf72cf056e39e215feac3 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Wed, 2 Jun 2010 16:51:16 +0900 Subject: MIPS: Move Cobalt Makefile parts to their own Platform file Signed-off-by: Yoichi Yuasa Cc: linux-mips Patchwork: https://patchwork.linux-mips.org/patch/1321/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 77e48b9..6c163c2 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -2,6 +2,7 @@ platforms += alchemy platforms += ar7 +platforms += cobalt platforms += loongson platforms += mipssim platforms += sgi-ip27 diff --git a/arch/mips/Makefile b/arch/mips/Makefile index ec2cd73..01fbd91 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -199,13 +199,6 @@ cflags-$(CONFIG_MACH_JAZZ) += -I$(srctree)/arch/mips/include/asm/mach-jazz load-$(CONFIG_MACH_JAZZ) += 0xffffffff80080000 # -# Cobalt Server -# -core-$(CONFIG_MIPS_COBALT) += arch/mips/cobalt/ -cflags-$(CONFIG_MIPS_COBALT) += -I$(srctree)/arch/mips/include/asm/mach-cobalt -load-$(CONFIG_MIPS_COBALT) += 0xffffffff80080000 - -# # DECstation family # core-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/ diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile index 2379262..61a334a 100644 --- a/arch/mips/cobalt/Makefile +++ b/arch/mips/cobalt/Makefile @@ -7,5 +7,3 @@ obj-y := buttons.o irq.o lcd.o led.o reset.o rtc.o serial.o setup.o time.o obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_EARLY_PRINTK) += console.o obj-$(CONFIG_MTD_PHYSMAP) += mtd.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/cobalt/Platform b/arch/mips/cobalt/Platform new file mode 100644 index 0000000..34123ef --- /dev/null +++ b/arch/mips/cobalt/Platform @@ -0,0 +1,6 @@ +# +# Cobalt Server +# +platform-$(CONFIG_MIPS_COBALT) += cobalt/ +cflags-$(CONFIG_MIPS_COBALT) += -I$(srctree)/arch/mips/include/asm/mach-cobalt +load-$(CONFIG_MIPS_COBALT) += 0xffffffff80080000 -- cgit v0.10.2 From 4300a92e9b3794caee33a8f3985ad883db1b4650 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Wed, 2 Jun 2010 16:52:21 +0900 Subject: MIPS: Move VR41xx Makefile parts to their own Platform file Signed-off-by: Yoichi Yuasa Cc: linux-mips Patchwork: https://patchwork.linux-mips.org/patch/1322/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 6c163c2..9b6e8d7 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -6,6 +6,7 @@ platforms += cobalt platforms += loongson platforms += mipssim platforms += sgi-ip27 +platforms += vr41xx # include the platform specific files include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms)) diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 01fbd91..84fe05a 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -243,39 +243,6 @@ core-$(CONFIG_LASAT) += arch/mips/lasat/ cflags-$(CONFIG_LASAT) += -I$(srctree)/arch/mips/include/asm/mach-lasat load-$(CONFIG_LASAT) += 0xffffffff80000000 -# -# Common VR41xx -# -core-$(CONFIG_MACH_VR41XX) += arch/mips/vr41xx/common/ -cflags-$(CONFIG_MACH_VR41XX) += -I$(srctree)/arch/mips/include/asm/mach-vr41xx - -# -# ZAO Networks Capcella (VR4131) -# -load-$(CONFIG_ZAO_CAPCELLA) += 0xffffffff80000000 - -# -# Victor MP-C303/304 (VR4122) -# -load-$(CONFIG_VICTOR_MPC30X) += 0xffffffff80001000 - -# -# IBM WorkPad z50 (VR4121) -# -core-$(CONFIG_IBM_WORKPAD) += arch/mips/vr41xx/ibm-workpad/ -load-$(CONFIG_IBM_WORKPAD) += 0xffffffff80004000 - -# -# CASIO CASSIPEIA E-55/65 (VR4111) -# -core-$(CONFIG_CASIO_E55) += arch/mips/vr41xx/casio-e55/ -load-$(CONFIG_CASIO_E55) += 0xffffffff80004000 - -# -# TANBAC VR4131 multichip module(TB0225) and TANBAC VR4131DIMM(TB0229) (VR4131) -# -load-$(CONFIG_TANBAC_TB022X) += 0xffffffff80000000 - # NXP STB225 core-$(CONFIG_SOC_PNX833X) += arch/mips/nxp/pnx833x/common/ cflags-$(CONFIG_SOC_PNX833X) += -Iarch/mips/include/asm/mach-pnx833x diff --git a/arch/mips/vr41xx/Platform b/arch/mips/vr41xx/Platform new file mode 100644 index 0000000..b6c8d5c --- /dev/null +++ b/arch/mips/vr41xx/Platform @@ -0,0 +1,32 @@ +# +# NEC VR4100 series based machines +# +platform-$(CONFIG_MACH_VR41XX) += vr41xx/common/ +cflags-$(CONFIG_MACH_VR41XX) += -I$(srctree)/arch/mips/include/asm/mach-vr41xx + +# +# CASIO CASSIPEIA E-55/65 (VR4111) +# +platform-$(CONFIG_CASIO_E55) += vr41xx/casio-e55/ +load-$(CONFIG_CASIO_E55) += 0xffffffff80004000 + +# +# IBM WorkPad z50 (VR4121) +# +platform-$(CONFIG_IBM_WORKPAD) += vr41xx/ibm-workpad/ +load-$(CONFIG_IBM_WORKPAD) += 0xffffffff80004000 + +# +# TANBAC VR4131 multichip module(TB0225) and TANBAC VR4131DIMM(TB0229) (VR4131) +# +load-$(CONFIG_TANBAC_TB022X) += 0xffffffff80000000 + +# +# Victor MP-C303/304 (VR4122) +# +load-$(CONFIG_VICTOR_MPC30X) += 0xffffffff80001000 + +# +# ZAO Networks Capcella (VR4131) +# +load-$(CONFIG_ZAO_CAPCELLA) += 0xffffffff80000000 diff --git a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile index 7d5d83b..d0d84ec 100644 --- a/arch/mips/vr41xx/common/Makefile +++ b/arch/mips/vr41xx/common/Makefile @@ -3,5 +3,3 @@ # obj-y += bcu.o cmu.o giu.o icu.o init.o irq.o pmu.o rtc.o siu.o type.o - -EXTRA_CFLAGS += -Werror -- cgit v0.10.2 From 82baa6b0829b810329dd72a31cd5721cba05488a Mon Sep 17 00:00:00 2001 From: Shane McDonald Date: Thu, 3 Jun 2010 04:34:06 -0600 Subject: MIPS: PMC-Sierra: Move board Makefile parts to their own Platform file Signed-off-by: Shane McDonald To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1354/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 9b6e8d7..c074ee2 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -5,6 +5,7 @@ platforms += ar7 platforms += cobalt platforms += loongson platforms += mipssim +platforms += pmc-sierra platforms += sgi-ip27 platforms += vr41xx diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 84fe05a..e83a88d 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -222,21 +222,6 @@ load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000 all-$(CONFIG_MIPS_MALTA) := $(COMPRESSION_FNAME).bin # -# PMC-Sierra MSP SOCs -# -core-$(CONFIG_PMC_MSP) += arch/mips/pmc-sierra/msp71xx/ -cflags-$(CONFIG_PMC_MSP) += -I$(srctree)/arch/mips/include/asm/pmc-sierra/msp71xx \ - -mno-branch-likely -load-$(CONFIG_PMC_MSP) += 0xffffffff80100000 - -# -# PMC-Sierra Yosemite -# -core-$(CONFIG_PMC_YOSEMITE) += arch/mips/pmc-sierra/yosemite/ -cflags-$(CONFIG_PMC_YOSEMITE) += -I$(srctree)/arch/mips/include/asm/mach-yosemite -load-$(CONFIG_PMC_YOSEMITE) += 0xffffffff80100000 - -# # LASAT platforms # core-$(CONFIG_LASAT) += arch/mips/lasat/ diff --git a/arch/mips/pmc-sierra/Platform b/arch/mips/pmc-sierra/Platform new file mode 100644 index 0000000..f092f25 --- /dev/null +++ b/arch/mips/pmc-sierra/Platform @@ -0,0 +1,14 @@ +# +# PMC-Sierra MSP SOCs +# +platform-$(CONFIG_PMC_MSP) += pmc-sierra/msp71xx/ +cflags-$(CONFIG_PMC_MSP) += -I$(srctree)/arch/mips/include/asm/pmc-sierra/msp71xx \ + -mno-branch-likely +load-$(CONFIG_PMC_MSP) += 0xffffffff80100000 + +# +# PMC-Sierra Yosemite +# +platform-$(CONFIG_PMC_YOSEMITE) += pmc-sierra/yosemite/ +cflags-$(CONFIG_PMC_YOSEMITE) += -I$(srctree)/arch/mips/include/asm/mach-yosemite +load-$(CONFIG_PMC_YOSEMITE) += 0xffffffff80100000 -- cgit v0.10.2 From 1505b60757694512b76edce8ecc6f73b4a8a7f9f Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:48 +0100 Subject: MIPS: Jazz: Migrate to new platform makefile style. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index c074ee2..7973bb0 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -3,6 +3,7 @@ platforms += alchemy platforms += ar7 platforms += cobalt +platforms += jazz platforms += loongson platforms += mipssim platforms += pmc-sierra diff --git a/arch/mips/Makefile b/arch/mips/Makefile index e83a88d..f714c85 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -192,13 +192,6 @@ endif include $(srctree)/arch/mips/Kbuild.platforms # -# Acer PICA 61, Mips Magnum 4000 and Olivetti M700. -# -core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/ -cflags-$(CONFIG_MACH_JAZZ) += -I$(srctree)/arch/mips/include/asm/mach-jazz -load-$(CONFIG_MACH_JAZZ) += 0xffffffff80080000 - -# # DECstation family # core-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/ diff --git a/arch/mips/jazz/Makefile b/arch/mips/jazz/Makefile index 5aee0c2..dd9d99b 100644 --- a/arch/mips/jazz/Makefile +++ b/arch/mips/jazz/Makefile @@ -3,5 +3,3 @@ # obj-y := irq.o jazzdma.o reset.o setup.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/jazz/Platform b/arch/mips/jazz/Platform new file mode 100644 index 0000000..3373788 --- /dev/null +++ b/arch/mips/jazz/Platform @@ -0,0 +1,6 @@ +# +# Acer PICA 61, Mips Magnum 4000 and Olivetti M700. +# +platform-$(CONFIG_MACH_JAZZ) += jazz/ +cflags-$(CONFIG_MACH_JAZZ) += -I$(srctree)/arch/mips/include/asm/mach-jazz +load-$(CONFIG_MACH_JAZZ) += 0xffffffff80080000 -- cgit v0.10.2 From c136af0906ba714b67bdc8623a0f82ddd7a7ba21 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:49 +0100 Subject: MIPS: DECstation: Migrate to new platform makefile style. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 7973bb0..0ba692c 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -3,6 +3,7 @@ platforms += alchemy platforms += ar7 platforms += cobalt +platforms += dec platforms += jazz platforms += loongson platforms += mipssim diff --git a/arch/mips/Makefile b/arch/mips/Makefile index f714c85..efaae85 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -192,14 +192,6 @@ endif include $(srctree)/arch/mips/Kbuild.platforms # -# DECstation family -# -core-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/ -cflags-$(CONFIG_MACH_DECSTATION)+= -I$(srctree)/arch/mips/include/asm/mach-dec -libs-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/prom/ -load-$(CONFIG_MACH_DECSTATION) += 0xffffffff80040000 - -# # Wind River PPMC Board (4KC + GT64120) # core-$(CONFIG_WR_PPMC) += arch/mips/gt64120/wrppmc/ diff --git a/arch/mips/dec/Makefile b/arch/mips/dec/Makefile index c530208e..9eb2f9c 100644 --- a/arch/mips/dec/Makefile +++ b/arch/mips/dec/Makefile @@ -8,5 +8,3 @@ obj-y := ecc-berr.o int-handler.o ioasic-irq.o kn01-berr.o \ obj-$(CONFIG_PROM_CONSOLE) += promcon.o obj-$(CONFIG_TC) += tc.o obj-$(CONFIG_CPU_HAS_WB) += wbflush.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/dec/Platform b/arch/mips/dec/Platform new file mode 100644 index 0000000..3adbcbd --- /dev/null +++ b/arch/mips/dec/Platform @@ -0,0 +1,8 @@ +# +# DECstation family +# +platform-$(CONFIG_MACH_DECSTATION) = dec/ +cflags-$(CONFIG_MACH_DECSTATION) += \ + -I$(srctree)/arch/mips/include/asm/mach-dec +libs-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/prom/ +load-$(CONFIG_MACH_DECSTATION) += 0xffffffff80040000 -- cgit v0.10.2 From 655f40e4870a46551a4510695765913d2c0518ce Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:49 +0100 Subject: MIPS: SNI: Migrate to new platform makefile style. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 0ba692c..e391b6d 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -9,6 +9,7 @@ platforms += loongson platforms += mipssim platforms += pmc-sierra platforms += sgi-ip27 +platforms += sni platforms += vr41xx # include the platform specific files diff --git a/arch/mips/Makefile b/arch/mips/Makefile index efaae85..ccbb367 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -370,18 +370,6 @@ cflags-$(CONFIG_BCM63XX) += -I$(srctree)/arch/mips/include/asm/mach-bcm63xx/ load-$(CONFIG_BCM63XX) := 0xffffffff80010000 # -# SNI RM -# -core-$(CONFIG_SNI_RM) += arch/mips/sni/ -cflags-$(CONFIG_SNI_RM) += -I$(srctree)/arch/mips/include/asm/mach-rm -ifdef CONFIG_CPU_LITTLE_ENDIAN -load-$(CONFIG_SNI_RM) += 0xffffffff80600000 -else -load-$(CONFIG_SNI_RM) += 0xffffffff80030000 -endif -all-$(CONFIG_SNI_RM) := $(COMPRESSION_FNAME).ecoff - -# # Common TXx9 # core-$(CONFIG_MACH_TX39XX) += arch/mips/txx9/generic/ diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile index a7dbeeb..9d3bad32 100644 --- a/arch/mips/sni/Makefile +++ b/arch/mips/sni/Makefile @@ -4,5 +4,3 @@ obj-y += irq.o reset.o setup.o a20r.o rm200.o pcimt.o pcit.o time.o obj-$(CONFIG_EISA) += eisa.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/sni/Platform b/arch/mips/sni/Platform new file mode 100644 index 0000000..2644a9d --- /dev/null +++ b/arch/mips/sni/Platform @@ -0,0 +1,11 @@ +# +# SNI RM +# +platform-$(CONFIG_SNI_RM) += sni/ +cflags-$(CONFIG_SNI_RM) += -I$(srctree)/arch/mips/include/asm/mach-rm +ifdef CONFIG_CPU_LITTLE_ENDIAN +load-$(CONFIG_SNI_RM) += 0xffffffff80600000 +else +load-$(CONFIG_SNI_RM) += 0xffffffff80030000 +endif +all-$(CONFIG_SNI_RM) := $(COMPRESSION_FNAME).ecoff -- cgit v0.10.2 From b9dbdce11b0c961d5cf22488ee059f2f9d930431 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:49 +0100 Subject: MIPS: IP22, IP28: Migrate to new platform makefile style. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index e391b6d..acc3dc8 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -8,6 +8,7 @@ platforms += jazz platforms += loongson platforms += mipssim platforms += pmc-sierra +platforms += sgi-ip22 platforms += sgi-ip27 platforms += sni platforms += vr41xx diff --git a/arch/mips/Makefile b/arch/mips/Makefile index ccbb367..3c89ccb 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -259,41 +259,6 @@ cflags-$(CONFIG_POWERTV) += -I$(srctree)/arch/mips/include/asm/mach-power load-$(CONFIG_POWERTV) += 0xffffffff90800000 # -# SGI IP22 (Indy/Indigo2) -# -# Set the load address to >= 0xffffffff88069000 if you want to leave space for -# symmon, 0xffffffff80002000 for production kernels. Note that the value must -# be aligned to a multiple of the kernel stack size or the handling of the -# current variable will break so for 64-bit kernels we have to raise the start -# address by 8kb. -# -core-$(CONFIG_SGI_IP22) += arch/mips/sgi-ip22/ -cflags-$(CONFIG_SGI_IP22) += -I$(srctree)/arch/mips/include/asm/mach-ip22 -ifdef CONFIG_32BIT -load-$(CONFIG_SGI_IP22) += 0xffffffff88002000 -endif -ifdef CONFIG_64BIT -load-$(CONFIG_SGI_IP22) += 0xffffffff88004000 -endif - -# -# SGI IP28 (Indigo2 R10k) -# -# Set the load address to >= 0xa800000020080000 if you want to leave space for -# symmon, 0xa800000020004000 for production kernels ? Note that the value must -# be 16kb aligned or the handling of the current variable will break. -# Simplified: what IP22 does at 128MB+ in ksegN, IP28 does at 512MB+ in xkphys -# -ifdef CONFIG_SGI_IP28 - ifeq ($(call cc-option-yn,-mr10k-cache-barrier=store), n) - $(error gcc doesn't support needed option -mr10k-cache-barrier=store) - endif -endif -core-$(CONFIG_SGI_IP28) += arch/mips/sgi-ip22/ -cflags-$(CONFIG_SGI_IP28) += -mr10k-cache-barrier=store -I$(srctree)/arch/mips/include/asm/mach-ip28 -load-$(CONFIG_SGI_IP28) += 0xa800000020004000 - -# # SGI-IP32 (O2) # # Set the load address to >= 80069000 if you want to leave space for symmon, diff --git a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile index 416b18f..cc53849 100644 --- a/arch/mips/sgi-ip22/Makefile +++ b/arch/mips/sgi-ip22/Makefile @@ -9,5 +9,3 @@ obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-time.o ip22-nvram.o \ obj-$(CONFIG_SGI_IP22) += ip22-berr.o obj-$(CONFIG_SGI_IP28) += ip28-berr.o obj-$(CONFIG_EISA) += ip22-eisa.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/sgi-ip22/Platform b/arch/mips/sgi-ip22/Platform new file mode 100644 index 0000000..b7a4b7e --- /dev/null +++ b/arch/mips/sgi-ip22/Platform @@ -0,0 +1,34 @@ +# +# SGI IP22 (Indy/Indigo2) +# +# Set the load address to >= 0xffffffff88069000 if you want to leave space for +# symmon, 0xffffffff80002000 for production kernels. Note that the value must +# be aligned to a multiple of the kernel stack size or the handling of the +# current variable will break so for 64-bit kernels we have to raise the start +# address by 8kb. +# +platform-$(CONFIG_SGI_IP22) += sgi-ip22/ +cflags-$(CONFIG_SGI_IP22) += -I$(srctree)/arch/mips/include/asm/mach-ip22 +ifdef CONFIG_32BIT +load-$(CONFIG_SGI_IP22) += 0xffffffff88002000 +endif +ifdef CONFIG_64BIT +load-$(CONFIG_SGI_IP22) += 0xffffffff88004000 +endif + +# +# SGI IP28 (Indigo2 R10k) +# +# Set the load address to >= 0xa800000020080000 if you want to leave space for +# symmon, 0xa800000020004000 for production kernels ? Note that the value must +# be 16kb aligned or the handling of the current variable will break. +# Simplified: what IP22 does at 128MB+ in ksegN, IP28 does at 512MB+ in xkphys +# +ifdef CONFIG_SGI_IP28 + ifeq ($(call cc-option-yn,-mr10k-cache-barrier=store), n) + $(error gcc doesn't support needed option -mr10k-cache-barrier=store) + endif +endif +platform-$(CONFIG_SGI_IP28) += sgi-ip22/ +cflags-$(CONFIG_SGI_IP28) += -mr10k-cache-barrier=store -I$(srctree)/arch/mips/include/asm/mach-ip28 +load-$(CONFIG_SGI_IP28) += 0xa800000020004000 -- cgit v0.10.2 From 36bb97e97176e57d88db93593720531f51ea75b6 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:50 +0100 Subject: MIPS: Malta: Migrate to new platform makefile style. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index acc3dc8..4d87f3d 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -7,6 +7,7 @@ platforms += dec platforms += jazz platforms += loongson platforms += mipssim +platforms += mti-malta platforms += pmc-sierra platforms += sgi-ip22 platforms += sgi-ip27 diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 3c89ccb..719aad5 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -199,14 +199,6 @@ cflags-$(CONFIG_WR_PPMC) += -I$(srctree)/arch/mips/include/asm/mach-wrppmc load-$(CONFIG_WR_PPMC) += 0xffffffff80100000 # -# MIPS Malta board -# -core-$(CONFIG_MIPS_MALTA) += arch/mips/mti-malta/ -cflags-$(CONFIG_MIPS_MALTA) += -I$(srctree)/arch/mips/include/asm/mach-malta -load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000 -all-$(CONFIG_MIPS_MALTA) := $(COMPRESSION_FNAME).bin - -# # LASAT platforms # core-$(CONFIG_LASAT) += arch/mips/lasat/ diff --git a/arch/mips/mti-malta/Makefile b/arch/mips/mti-malta/Makefile index 32e8478..6079ef3 100644 --- a/arch/mips/mti-malta/Makefile +++ b/arch/mips/mti-malta/Makefile @@ -15,5 +15,3 @@ obj-$(CONFIG_PCI) += malta-pci.o # FIXME FIXME FIXME obj-$(CONFIG_MIPS_MT_SMTC) += malta-smtc.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/mti-malta/Platform b/arch/mips/mti-malta/Platform new file mode 100644 index 0000000..5b548b5 --- /dev/null +++ b/arch/mips/mti-malta/Platform @@ -0,0 +1,7 @@ +# +# MIPS Malta board +# +platform-$(CONFIG_MIPS_MALTA) += mti-malta/ +cflags-$(CONFIG_MIPS_MALTA) += -I$(srctree)/arch/mips/include/asm/mach-malta +load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000 +all-$(CONFIG_MIPS_MALTA) := $(COMPRESSION_FNAME).bin -- cgit v0.10.2 From 4fa8a557c301b14a53dcd654aa0c2988c71cbd4d Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:50 +0100 Subject: MIPS: IP32: Migrate to new platform makefile style. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 4d87f3d..8a8f99b 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -11,6 +11,7 @@ platforms += mti-malta platforms += pmc-sierra platforms += sgi-ip22 platforms += sgi-ip27 +platforms += sgi-ip32 platforms += sni platforms += vr41xx diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 719aad5..175c647 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -251,18 +251,6 @@ cflags-$(CONFIG_POWERTV) += -I$(srctree)/arch/mips/include/asm/mach-power load-$(CONFIG_POWERTV) += 0xffffffff90800000 # -# SGI-IP32 (O2) -# -# Set the load address to >= 80069000 if you want to leave space for symmon, -# 0xffffffff80004000 for production kernels. Note that the value must be aligned to -# a multiple of the kernel stack size or the handling of the current variable -# will break. -# -core-$(CONFIG_SGI_IP32) += arch/mips/sgi-ip32/ -cflags-$(CONFIG_SGI_IP32) += -I$(srctree)/arch/mips/include/asm/mach-ip32 -load-$(CONFIG_SGI_IP32) += 0xffffffff80004000 - -# # Sibyte SB1250/BCM1480 SOC # # This is a LIB so that it links at the end, and initcalls are later diff --git a/arch/mips/sgi-ip32/Makefile b/arch/mips/sgi-ip32/Makefile index 31c9aa1..60f0227 100644 --- a/arch/mips/sgi-ip32/Makefile +++ b/arch/mips/sgi-ip32/Makefile @@ -5,5 +5,3 @@ obj-y += ip32-berr.o ip32-irq.o ip32-platform.o ip32-setup.o ip32-reset.o \ crime.o ip32-memory.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/sgi-ip32/Platform b/arch/mips/sgi-ip32/Platform new file mode 100644 index 0000000..0fea556 --- /dev/null +++ b/arch/mips/sgi-ip32/Platform @@ -0,0 +1,11 @@ +# +# SGI-IP32 (O2) +# +# Set the load address to >= 80069000 if you want to leave space for symmon, +# 0xffffffff80004000 for production kernels. Note that the value must be aligned to +# a multiple of the kernel stack size or the handling of the current variable +# will break. +# +platform-$(CONFIG_SGI_IP32) += sgi-ip32/ +cflags-$(CONFIG_SGI_IP32) += -I$(srctree)/arch/mips/include/asm/mach-ip32 +load-$(CONFIG_SGI_IP32) += 0xffffffff80004000 -- cgit v0.10.2 From 91598965ecb508dc7bc154ec9d3e35dcadb3fa5f Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:50 +0100 Subject: MIPS: RB532: Migrate to new platform makefile style. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 8a8f99b..61f150b 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -9,6 +9,7 @@ platforms += loongson platforms += mipssim platforms += mti-malta platforms += pmc-sierra +platforms += rb532 platforms += sgi-ip22 platforms += sgi-ip27 platforms += sgi-ip32 diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 175c647..2fbce8e 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -330,13 +330,6 @@ load-$(CONFIG_MACH_TX49XX) += 0xffffffff80100000 core-$(CONFIG_TOSHIBA_JMR3927) += arch/mips/txx9/jmr3927/ # -# Routerboard 532 board -# -core-$(CONFIG_MIKROTIK_RB532) += arch/mips/rb532/ -cflags-$(CONFIG_MIKROTIK_RB532) += -I$(srctree)/arch/mips/include/asm/mach-rc32434 -load-$(CONFIG_MIKROTIK_RB532) += 0xffffffff80101000 - -# # Toshiba RBTX49XX boards # core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/txx9/rbtx4927/ diff --git a/arch/mips/rb532/Makefile b/arch/mips/rb532/Makefile index 8f0b6b6..efdecdb 100644 --- a/arch/mips/rb532/Makefile +++ b/arch/mips/rb532/Makefile @@ -3,5 +3,3 @@ # obj-y += irq.o time.o setup.o serial.o prom.o gpio.o devices.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/rb532/Platform b/arch/mips/rb532/Platform new file mode 100644 index 0000000..aeec45a --- /dev/null +++ b/arch/mips/rb532/Platform @@ -0,0 +1,7 @@ +# +# Routerboard 532 +# +platform-$(CONFIG_MIKROTIK_RB532) += rb532/ +cflags-$(CONFIG_MIKROTIK_RB532) += \ + -I$(srctree)/arch/mips/include/asm/mach-rc32434 +load-$(CONFIG_MIKROTIK_RB532) += 0xffffffff80101000 -- cgit v0.10.2 From 9ebc2935f346964c34e5f376263c4071f66edcd9 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:50 +0100 Subject: MIPS: WRPPMC: Move code one directory level up. It was the last platform under gt64120 and will fit better into the new platform makefile scheme, if moved. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 2fbce8e..10e8a29 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -194,7 +194,7 @@ include $(srctree)/arch/mips/Kbuild.platforms # # Wind River PPMC Board (4KC + GT64120) # -core-$(CONFIG_WR_PPMC) += arch/mips/gt64120/wrppmc/ +core-$(CONFIG_WR_PPMC) += arch/mips/wrppmc/ cflags-$(CONFIG_WR_PPMC) += -I$(srctree)/arch/mips/include/asm/mach-wrppmc load-$(CONFIG_WR_PPMC) += 0xffffffff80100000 diff --git a/arch/mips/gt64120/wrppmc/Makefile b/arch/mips/gt64120/wrppmc/Makefile deleted file mode 100644 index b49d282..0000000 --- a/arch/mips/gt64120/wrppmc/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# This file is subject to the terms and conditions of the GNU General Public -# License. See the file "COPYING" in the main directory of this archive -# for more details. -# -# Copyright 2006 Wind River System, Inc. -# Author: Rongkai.Zhan -# -# Makefile for the Wind River MIPS 4KC PPMC Eval Board -# - -obj-y += irq.o pci.o reset.o serial.o setup.o time.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/gt64120/wrppmc/irq.c b/arch/mips/gt64120/wrppmc/irq.c deleted file mode 100644 index c6e7062..0000000 --- a/arch/mips/gt64120/wrppmc/irq.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * irq.c: GT64120 Interrupt Controller - * - * Copyright (C) 2006, Wind River System Inc. - * Author: Rongkai.Zhan, - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ -#include -#include -#include - -#include -#include -#include - -asmlinkage void plat_irq_dispatch(void) -{ - unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; - - if (pending & STATUSF_IP7) - do_IRQ(WRPPMC_MIPS_TIMER_IRQ); /* CPU Compare/Count internal timer */ - else if (pending & STATUSF_IP6) - do_IRQ(WRPPMC_UART16550_IRQ); /* UART 16550 port */ - else if (pending & STATUSF_IP3) - do_IRQ(WRPPMC_PCI_INTA_IRQ); /* PCI INT_A */ - else - spurious_interrupt(); -} - -/** - * Initialize GT64120 Interrupt Controller - */ -void gt64120_init_pic(void) -{ - /* clear CPU Interrupt Cause Registers */ - GT_WRITE(GT_INTRCAUSE_OFS, (0x1F << 21)); - GT_WRITE(GT_HINTRCAUSE_OFS, 0x00); - - /* Disable all interrupts from GT64120 bridge chip */ - GT_WRITE(GT_INTRMASK_OFS, 0x00); - GT_WRITE(GT_HINTRMASK_OFS, 0x00); - GT_WRITE(GT_PCI0_ICMASK_OFS, 0x00); - GT_WRITE(GT_PCI0_HICMASK_OFS, 0x00); -} - -void __init arch_init_irq(void) -{ - /* IRQ 0 - 7 are for MIPS common irq_cpu controller */ - mips_cpu_irq_init(); - - gt64120_init_pic(); -} diff --git a/arch/mips/gt64120/wrppmc/pci.c b/arch/mips/gt64120/wrppmc/pci.c deleted file mode 100644 index d06192f..0000000 --- a/arch/mips/gt64120/wrppmc/pci.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * pci.c: GT64120 PCI support. - * - * Copyright (C) 2006, Wind River System Inc. Rongkai.Zhan - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include - -#include - -extern struct pci_ops gt64xxx_pci0_ops; - -static struct resource pci0_io_resource = { - .name = "pci_0 io", - .start = GT_PCI_IO_BASE, - .end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1, - .flags = IORESOURCE_IO, -}; - -static struct resource pci0_mem_resource = { - .name = "pci_0 memory", - .start = GT_PCI_MEM_BASE, - .end = GT_PCI_MEM_BASE + GT_PCI_MEM_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -static struct pci_controller hose_0 = { - .pci_ops = >64xxx_pci0_ops, - .io_resource = &pci0_io_resource, - .mem_resource = &pci0_mem_resource, -}; - -static int __init gt64120_pci_init(void) -{ - u32 tmp; - - tmp = GT_READ(GT_PCI0_CMD_OFS); /* Huh??? -- Ralf */ - tmp = GT_READ(GT_PCI0_BARE_OFS); - - /* reset the whole PCI I/O space range */ - ioport_resource.start = GT_PCI_IO_BASE; - ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1; - - register_pci_controller(&hose_0); - return 0; -} - -arch_initcall(gt64120_pci_init); diff --git a/arch/mips/gt64120/wrppmc/reset.c b/arch/mips/gt64120/wrppmc/reset.c deleted file mode 100644 index cc5474b..0000000 --- a/arch/mips/gt64120/wrppmc/reset.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1997 Ralf Baechle - */ -#include -#include - -#include -#include -#include - -void wrppmc_machine_restart(char *command) -{ - /* - * Ouch, we're still alive ... This time we take the silver bullet ... - * ... and find that we leave the hardware in a state in which the - * kernel in the flush locks up somewhen during of after the PCI - * detection stuff. - */ - local_irq_disable(); - set_c0_status(ST0_BEV | ST0_ERL); - change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); - flush_cache_all(); - write_c0_wired(0); - __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); -} - -void wrppmc_machine_halt(void) -{ - local_irq_disable(); - - printk(KERN_NOTICE "You can safely turn off the power\n"); - while (1) { - if (cpu_wait) - cpu_wait(); - } -} diff --git a/arch/mips/gt64120/wrppmc/serial.c b/arch/mips/gt64120/wrppmc/serial.c deleted file mode 100644 index 6f9d085..0000000 --- a/arch/mips/gt64120/wrppmc/serial.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Registration of WRPPMC UART platform device. - * - * Copyright (C) 2007 Yoichi Yuasa - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include -#include -#include -#include -#include - -#include - -static struct resource wrppmc_uart_resource[] __initdata = { - { - .start = WRPPMC_UART16550_BASE, - .end = WRPPMC_UART16550_BASE + 7, - .flags = IORESOURCE_MEM, - }, - { - .start = WRPPMC_UART16550_IRQ, - .end = WRPPMC_UART16550_IRQ, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct plat_serial8250_port wrppmc_serial8250_port[] = { - { - .irq = WRPPMC_UART16550_IRQ, - .uartclk = WRPPMC_UART16550_CLOCK, - .iotype = UPIO_MEM, - .flags = UPF_IOREMAP | UPF_SKIP_TEST, - .mapbase = WRPPMC_UART16550_BASE, - }, - {}, -}; - -static __init int wrppmc_uart_add(void) -{ - struct platform_device *pdev; - int retval; - - pdev = platform_device_alloc("serial8250", -1); - if (!pdev) - return -ENOMEM; - - pdev->id = PLAT8250_DEV_PLATFORM; - pdev->dev.platform_data = wrppmc_serial8250_port; - - retval = platform_device_add_resources(pdev, wrppmc_uart_resource, - ARRAY_SIZE(wrppmc_uart_resource)); - if (retval) - goto err_free_device; - - retval = platform_device_add(pdev); - if (retval) - goto err_free_device; - - return 0; - -err_free_device: - platform_device_put(pdev); - - return retval; -} -device_initcall(wrppmc_uart_add); diff --git a/arch/mips/gt64120/wrppmc/setup.c b/arch/mips/gt64120/wrppmc/setup.c deleted file mode 100644 index ca65c84..0000000 --- a/arch/mips/gt64120/wrppmc/setup.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * setup.c: Setup pointers to hardware dependent routines. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org) - * Copyright (C) 2006, Wind River System Inc. Rongkai.zhan - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -unsigned long gt64120_base = KSEG1ADDR(0x14000000); - -#ifdef WRPPMC_EARLY_DEBUG - -static volatile unsigned char * wrppmc_led = \ - (volatile unsigned char *)KSEG1ADDR(WRPPMC_LED_BASE); - -/* - * PPMC LED control register: - * -) bit[0] controls DS1 LED (1 - OFF, 0 - ON) - * -) bit[1] controls DS2 LED (1 - OFF, 0 - ON) - * -) bit[2] controls DS4 LED (1 - OFF, 0 - ON) - */ -void wrppmc_led_on(int mask) -{ - unsigned char value = *wrppmc_led; - - value &= (0xF8 | mask); - *wrppmc_led = value; -} - -/* If mask = 0, turn off all LEDs */ -void wrppmc_led_off(int mask) -{ - unsigned char value = *wrppmc_led; - - value |= (0x7 & mask); - *wrppmc_led = value; -} - -/* - * We assume that bootloader has initialized UART16550 correctly - */ -void __init wrppmc_early_putc(char ch) -{ - static volatile unsigned char *wrppmc_uart = \ - (volatile unsigned char *)KSEG1ADDR(WRPPMC_UART16550_BASE); - unsigned char value; - - /* Wait until Transmit-Holding-Register is empty */ - while (1) { - value = *(wrppmc_uart + 5); - if (value & 0x20) - break; - } - - *wrppmc_uart = ch; -} - -void __init wrppmc_early_printk(const char *fmt, ...) -{ - static char pbuf[256] = {'\0', }; - char *ch = pbuf; - va_list args; - unsigned int i; - - memset(pbuf, 0, 256); - va_start(args, fmt); - i = vsprintf(pbuf, fmt, args); - va_end(args); - - /* Print the string */ - while (*ch != '\0') { - wrppmc_early_putc(*ch); - /* if print '\n', also print '\r' */ - if (*ch++ == '\n') - wrppmc_early_putc('\r'); - } -} -#endif /* WRPPMC_EARLY_DEBUG */ - -void __init prom_free_prom_memory(void) -{ -} - -void __init plat_mem_setup(void) -{ - extern void wrppmc_machine_restart(char *command); - extern void wrppmc_machine_halt(void); - - _machine_restart = wrppmc_machine_restart; - _machine_halt = wrppmc_machine_halt; - pm_power_off = wrppmc_machine_halt; - - /* This makes the operations of 'in/out[bwl]' to the - * physical address ( < KSEG0) can work via KSEG1 - */ - set_io_port_base(KSEG1); -} - -const char *get_system_type(void) -{ - return "Wind River PPMC (GT64120)"; -} - -/* - * Initializes basic routines and structures pointers, memory size (as - * given by the bios and saves the command line. - */ -void __init prom_init(void) -{ - add_memory_region(WRPPMC_SDRAM_SCS0_BASE, WRPPMC_SDRAM_SCS0_SIZE, BOOT_MEM_RAM); - add_memory_region(WRPPMC_BOOTROM_BASE, WRPPMC_BOOTROM_SIZE, BOOT_MEM_ROM_DATA); - - wrppmc_early_printk("prom_init: GT64120 SDRAM Bank 0: 0x%x - 0x%08lx\n", - WRPPMC_SDRAM_SCS0_BASE, (WRPPMC_SDRAM_SCS0_BASE + WRPPMC_SDRAM_SCS0_SIZE)); -} diff --git a/arch/mips/gt64120/wrppmc/time.c b/arch/mips/gt64120/wrppmc/time.c deleted file mode 100644 index 668dbd5..0000000 --- a/arch/mips/gt64120/wrppmc/time.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * time.c: MIPS CPU Count/Compare timer hookup - * - * Author: Mark.Zhan, - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org) - * Copyright (C) 2006, Wind River System Inc. - */ -#include -#include -#include - -#include -#include - -#define WRPPMC_CPU_CLK_FREQ 40000000 /* 40MHZ */ - -/* - * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect - * - * NOTE: We disable all GT64120 timers, and use MIPS processor internal - * timer as the source of kernel clock tick. - */ -void __init plat_time_init(void) -{ - /* Disable GT64120 timers */ - GT_WRITE(GT_TC_CONTROL_OFS, 0x00); - GT_WRITE(GT_TC0_OFS, 0x00); - GT_WRITE(GT_TC1_OFS, 0x00); - GT_WRITE(GT_TC2_OFS, 0x00); - GT_WRITE(GT_TC3_OFS, 0x00); - - /* Use MIPS compare/count internal timer */ - mips_hpt_frequency = WRPPMC_CPU_CLK_FREQ; -} diff --git a/arch/mips/wrppmc/Makefile b/arch/mips/wrppmc/Makefile new file mode 100644 index 0000000..b49d282 --- /dev/null +++ b/arch/mips/wrppmc/Makefile @@ -0,0 +1,14 @@ +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright 2006 Wind River System, Inc. +# Author: Rongkai.Zhan +# +# Makefile for the Wind River MIPS 4KC PPMC Eval Board +# + +obj-y += irq.o pci.o reset.o serial.o setup.o time.o + +EXTRA_CFLAGS += -Werror diff --git a/arch/mips/wrppmc/irq.c b/arch/mips/wrppmc/irq.c new file mode 100644 index 0000000..c6e7062 --- /dev/null +++ b/arch/mips/wrppmc/irq.c @@ -0,0 +1,56 @@ +/* + * irq.c: GT64120 Interrupt Controller + * + * Copyright (C) 2006, Wind River System Inc. + * Author: Rongkai.Zhan, + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include + +#include +#include +#include + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; + + if (pending & STATUSF_IP7) + do_IRQ(WRPPMC_MIPS_TIMER_IRQ); /* CPU Compare/Count internal timer */ + else if (pending & STATUSF_IP6) + do_IRQ(WRPPMC_UART16550_IRQ); /* UART 16550 port */ + else if (pending & STATUSF_IP3) + do_IRQ(WRPPMC_PCI_INTA_IRQ); /* PCI INT_A */ + else + spurious_interrupt(); +} + +/** + * Initialize GT64120 Interrupt Controller + */ +void gt64120_init_pic(void) +{ + /* clear CPU Interrupt Cause Registers */ + GT_WRITE(GT_INTRCAUSE_OFS, (0x1F << 21)); + GT_WRITE(GT_HINTRCAUSE_OFS, 0x00); + + /* Disable all interrupts from GT64120 bridge chip */ + GT_WRITE(GT_INTRMASK_OFS, 0x00); + GT_WRITE(GT_HINTRMASK_OFS, 0x00); + GT_WRITE(GT_PCI0_ICMASK_OFS, 0x00); + GT_WRITE(GT_PCI0_HICMASK_OFS, 0x00); +} + +void __init arch_init_irq(void) +{ + /* IRQ 0 - 7 are for MIPS common irq_cpu controller */ + mips_cpu_irq_init(); + + gt64120_init_pic(); +} diff --git a/arch/mips/wrppmc/pci.c b/arch/mips/wrppmc/pci.c new file mode 100644 index 0000000..d06192f --- /dev/null +++ b/arch/mips/wrppmc/pci.c @@ -0,0 +1,54 @@ +/* + * pci.c: GT64120 PCI support. + * + * Copyright (C) 2006, Wind River System Inc. Rongkai.Zhan + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include + +#include + +extern struct pci_ops gt64xxx_pci0_ops; + +static struct resource pci0_io_resource = { + .name = "pci_0 io", + .start = GT_PCI_IO_BASE, + .end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1, + .flags = IORESOURCE_IO, +}; + +static struct resource pci0_mem_resource = { + .name = "pci_0 memory", + .start = GT_PCI_MEM_BASE, + .end = GT_PCI_MEM_BASE + GT_PCI_MEM_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +static struct pci_controller hose_0 = { + .pci_ops = >64xxx_pci0_ops, + .io_resource = &pci0_io_resource, + .mem_resource = &pci0_mem_resource, +}; + +static int __init gt64120_pci_init(void) +{ + u32 tmp; + + tmp = GT_READ(GT_PCI0_CMD_OFS); /* Huh??? -- Ralf */ + tmp = GT_READ(GT_PCI0_BARE_OFS); + + /* reset the whole PCI I/O space range */ + ioport_resource.start = GT_PCI_IO_BASE; + ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1; + + register_pci_controller(&hose_0); + return 0; +} + +arch_initcall(gt64120_pci_init); diff --git a/arch/mips/wrppmc/reset.c b/arch/mips/wrppmc/reset.c new file mode 100644 index 0000000..cc5474b --- /dev/null +++ b/arch/mips/wrppmc/reset.c @@ -0,0 +1,40 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1997 Ralf Baechle + */ +#include +#include + +#include +#include +#include + +void wrppmc_machine_restart(char *command) +{ + /* + * Ouch, we're still alive ... This time we take the silver bullet ... + * ... and find that we leave the hardware in a state in which the + * kernel in the flush locks up somewhen during of after the PCI + * detection stuff. + */ + local_irq_disable(); + set_c0_status(ST0_BEV | ST0_ERL); + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + flush_cache_all(); + write_c0_wired(0); + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); +} + +void wrppmc_machine_halt(void) +{ + local_irq_disable(); + + printk(KERN_NOTICE "You can safely turn off the power\n"); + while (1) { + if (cpu_wait) + cpu_wait(); + } +} diff --git a/arch/mips/wrppmc/serial.c b/arch/mips/wrppmc/serial.c new file mode 100644 index 0000000..6f9d085 --- /dev/null +++ b/arch/mips/wrppmc/serial.c @@ -0,0 +1,80 @@ +/* + * Registration of WRPPMC UART platform device. + * + * Copyright (C) 2007 Yoichi Yuasa + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include + +#include + +static struct resource wrppmc_uart_resource[] __initdata = { + { + .start = WRPPMC_UART16550_BASE, + .end = WRPPMC_UART16550_BASE + 7, + .flags = IORESOURCE_MEM, + }, + { + .start = WRPPMC_UART16550_IRQ, + .end = WRPPMC_UART16550_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct plat_serial8250_port wrppmc_serial8250_port[] = { + { + .irq = WRPPMC_UART16550_IRQ, + .uartclk = WRPPMC_UART16550_CLOCK, + .iotype = UPIO_MEM, + .flags = UPF_IOREMAP | UPF_SKIP_TEST, + .mapbase = WRPPMC_UART16550_BASE, + }, + {}, +}; + +static __init int wrppmc_uart_add(void) +{ + struct platform_device *pdev; + int retval; + + pdev = platform_device_alloc("serial8250", -1); + if (!pdev) + return -ENOMEM; + + pdev->id = PLAT8250_DEV_PLATFORM; + pdev->dev.platform_data = wrppmc_serial8250_port; + + retval = platform_device_add_resources(pdev, wrppmc_uart_resource, + ARRAY_SIZE(wrppmc_uart_resource)); + if (retval) + goto err_free_device; + + retval = platform_device_add(pdev); + if (retval) + goto err_free_device; + + return 0; + +err_free_device: + platform_device_put(pdev); + + return retval; +} +device_initcall(wrppmc_uart_add); diff --git a/arch/mips/wrppmc/setup.c b/arch/mips/wrppmc/setup.c new file mode 100644 index 0000000..ca65c84 --- /dev/null +++ b/arch/mips/wrppmc/setup.c @@ -0,0 +1,128 @@ +/* + * setup.c: Setup pointers to hardware dependent routines. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2006, Wind River System Inc. Rongkai.zhan + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +unsigned long gt64120_base = KSEG1ADDR(0x14000000); + +#ifdef WRPPMC_EARLY_DEBUG + +static volatile unsigned char * wrppmc_led = \ + (volatile unsigned char *)KSEG1ADDR(WRPPMC_LED_BASE); + +/* + * PPMC LED control register: + * -) bit[0] controls DS1 LED (1 - OFF, 0 - ON) + * -) bit[1] controls DS2 LED (1 - OFF, 0 - ON) + * -) bit[2] controls DS4 LED (1 - OFF, 0 - ON) + */ +void wrppmc_led_on(int mask) +{ + unsigned char value = *wrppmc_led; + + value &= (0xF8 | mask); + *wrppmc_led = value; +} + +/* If mask = 0, turn off all LEDs */ +void wrppmc_led_off(int mask) +{ + unsigned char value = *wrppmc_led; + + value |= (0x7 & mask); + *wrppmc_led = value; +} + +/* + * We assume that bootloader has initialized UART16550 correctly + */ +void __init wrppmc_early_putc(char ch) +{ + static volatile unsigned char *wrppmc_uart = \ + (volatile unsigned char *)KSEG1ADDR(WRPPMC_UART16550_BASE); + unsigned char value; + + /* Wait until Transmit-Holding-Register is empty */ + while (1) { + value = *(wrppmc_uart + 5); + if (value & 0x20) + break; + } + + *wrppmc_uart = ch; +} + +void __init wrppmc_early_printk(const char *fmt, ...) +{ + static char pbuf[256] = {'\0', }; + char *ch = pbuf; + va_list args; + unsigned int i; + + memset(pbuf, 0, 256); + va_start(args, fmt); + i = vsprintf(pbuf, fmt, args); + va_end(args); + + /* Print the string */ + while (*ch != '\0') { + wrppmc_early_putc(*ch); + /* if print '\n', also print '\r' */ + if (*ch++ == '\n') + wrppmc_early_putc('\r'); + } +} +#endif /* WRPPMC_EARLY_DEBUG */ + +void __init prom_free_prom_memory(void) +{ +} + +void __init plat_mem_setup(void) +{ + extern void wrppmc_machine_restart(char *command); + extern void wrppmc_machine_halt(void); + + _machine_restart = wrppmc_machine_restart; + _machine_halt = wrppmc_machine_halt; + pm_power_off = wrppmc_machine_halt; + + /* This makes the operations of 'in/out[bwl]' to the + * physical address ( < KSEG0) can work via KSEG1 + */ + set_io_port_base(KSEG1); +} + +const char *get_system_type(void) +{ + return "Wind River PPMC (GT64120)"; +} + +/* + * Initializes basic routines and structures pointers, memory size (as + * given by the bios and saves the command line. + */ +void __init prom_init(void) +{ + add_memory_region(WRPPMC_SDRAM_SCS0_BASE, WRPPMC_SDRAM_SCS0_SIZE, BOOT_MEM_RAM); + add_memory_region(WRPPMC_BOOTROM_BASE, WRPPMC_BOOTROM_SIZE, BOOT_MEM_ROM_DATA); + + wrppmc_early_printk("prom_init: GT64120 SDRAM Bank 0: 0x%x - 0x%08lx\n", + WRPPMC_SDRAM_SCS0_BASE, (WRPPMC_SDRAM_SCS0_BASE + WRPPMC_SDRAM_SCS0_SIZE)); +} diff --git a/arch/mips/wrppmc/time.c b/arch/mips/wrppmc/time.c new file mode 100644 index 0000000..668dbd5 --- /dev/null +++ b/arch/mips/wrppmc/time.c @@ -0,0 +1,39 @@ +/* + * time.c: MIPS CPU Count/Compare timer hookup + * + * Author: Mark.Zhan, + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2006, Wind River System Inc. + */ +#include +#include +#include + +#include +#include + +#define WRPPMC_CPU_CLK_FREQ 40000000 /* 40MHZ */ + +/* + * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect + * + * NOTE: We disable all GT64120 timers, and use MIPS processor internal + * timer as the source of kernel clock tick. + */ +void __init plat_time_init(void) +{ + /* Disable GT64120 timers */ + GT_WRITE(GT_TC_CONTROL_OFS, 0x00); + GT_WRITE(GT_TC0_OFS, 0x00); + GT_WRITE(GT_TC1_OFS, 0x00); + GT_WRITE(GT_TC2_OFS, 0x00); + GT_WRITE(GT_TC3_OFS, 0x00); + + /* Use MIPS compare/count internal timer */ + mips_hpt_frequency = WRPPMC_CPU_CLK_FREQ; +} -- cgit v0.10.2 From f70a974dd04619575723331a4f767254b76e3c8e Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:51 +0100 Subject: MIPS: WRPPMC: Migrate to new platform makefile style. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 61f150b..ad35f7b 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -15,6 +15,7 @@ platforms += sgi-ip27 platforms += sgi-ip32 platforms += sni platforms += vr41xx +platforms += wrppmc # include the platform specific files include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms)) diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 10e8a29..ff68150 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -192,13 +192,6 @@ endif include $(srctree)/arch/mips/Kbuild.platforms # -# Wind River PPMC Board (4KC + GT64120) -# -core-$(CONFIG_WR_PPMC) += arch/mips/wrppmc/ -cflags-$(CONFIG_WR_PPMC) += -I$(srctree)/arch/mips/include/asm/mach-wrppmc -load-$(CONFIG_WR_PPMC) += 0xffffffff80100000 - -# # LASAT platforms # core-$(CONFIG_LASAT) += arch/mips/lasat/ diff --git a/arch/mips/wrppmc/Makefile b/arch/mips/wrppmc/Makefile index b49d282..307cc69 100644 --- a/arch/mips/wrppmc/Makefile +++ b/arch/mips/wrppmc/Makefile @@ -6,9 +6,7 @@ # Copyright 2006 Wind River System, Inc. # Author: Rongkai.Zhan # -# Makefile for the Wind River MIPS 4KC PPMC Eval Board +# Makefile for the Wind River MIPS 4Kc PPMC Eval Board # obj-y += irq.o pci.o reset.o serial.o setup.o time.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/wrppmc/Platform b/arch/mips/wrppmc/Platform new file mode 100644 index 0000000..e758645 --- /dev/null +++ b/arch/mips/wrppmc/Platform @@ -0,0 +1,7 @@ +# +# Wind River PPMC Board (4KC + GT64120) +# +platform-$(CONFIG_WR_PPMC) += wrppmc/ +cflags-$(CONFIG_WR_PPMC) += \ + -I$(srctree)/arch/mips/include/asm/mach-wrppmc +load-$(CONFIG_WR_PPMC) += 0xffffffff80100000 -- cgit v0.10.2 From 026dab3c51d3d6129cf66f24bc592e9315856fdb Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:52 +0100 Subject: MIPS: PowerTV: Migrate to new platform makefile style. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index ad35f7b..31bba5b 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -9,6 +9,7 @@ platforms += loongson platforms += mipssim platforms += mti-malta platforms += pmc-sierra +platforms += powertv platforms += rb532 platforms += sgi-ip22 platforms += sgi-ip27 diff --git a/arch/mips/Makefile b/arch/mips/Makefile index ff68150..c983a87 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -237,13 +237,6 @@ core-$(CONFIG_NEC_MARKEINS) += arch/mips/emma/markeins/ load-$(CONFIG_NEC_MARKEINS) += 0xffffffff88100000 # -# Cisco PowerTV Platform -# -core-$(CONFIG_POWERTV) += arch/mips/powertv/ -cflags-$(CONFIG_POWERTV) += -I$(srctree)/arch/mips/include/asm/mach-powertv -load-$(CONFIG_POWERTV) += 0xffffffff90800000 - -# # Sibyte SB1250/BCM1480 SOC # # This is a LIB so that it links at the end, and initcalls are later diff --git a/arch/mips/powertv/Makefile b/arch/mips/powertv/Makefile index e9fe1c6e..506c4ca 100644 --- a/arch/mips/powertv/Makefile +++ b/arch/mips/powertv/Makefile @@ -26,4 +26,4 @@ obj-y += init.o ioremap.o memory.o powertv_setup.o reset.o time.o \ asic/ pci/ -EXTRA_CFLAGS += -Wall -Werror +EXTRA_CFLAGS += -Wall diff --git a/arch/mips/powertv/Platform b/arch/mips/powertv/Platform new file mode 100644 index 0000000..4eb5af1 --- /dev/null +++ b/arch/mips/powertv/Platform @@ -0,0 +1,7 @@ +# +# Cisco PowerTV Platform +# +platform-$(CONFIG_POWERTV) += powertv/ +cflags-$(CONFIG_POWERTV) += \ + -I$(srctree)/arch/mips/include/asm/mach-powertv +load-$(CONFIG_POWERTV) += 0xffffffff90800000 -- cgit v0.10.2 From bd152b095ef67898ed794f100e4ecc5298a61ad8 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:53 +0100 Subject: MIPS: Lasat: Migrate to new platform makefile style. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 31bba5b..d99704c 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -5,6 +5,7 @@ platforms += ar7 platforms += cobalt platforms += dec platforms += jazz +platforms += lasat platforms += loongson platforms += mipssim platforms += mti-malta diff --git a/arch/mips/Makefile b/arch/mips/Makefile index c983a87..24ba939 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -191,13 +191,6 @@ endif # include $(srctree)/arch/mips/Kbuild.platforms -# -# LASAT platforms -# -core-$(CONFIG_LASAT) += arch/mips/lasat/ -cflags-$(CONFIG_LASAT) += -I$(srctree)/arch/mips/include/asm/mach-lasat -load-$(CONFIG_LASAT) += 0xffffffff80000000 - # NXP STB225 core-$(CONFIG_SOC_PNX833X) += arch/mips/nxp/pnx833x/common/ cflags-$(CONFIG_SOC_PNX833X) += -Iarch/mips/include/asm/mach-pnx833x diff --git a/arch/mips/lasat/Makefile b/arch/mips/lasat/Makefile index 3379160..9cc4e4d 100644 --- a/arch/mips/lasat/Makefile +++ b/arch/mips/lasat/Makefile @@ -12,5 +12,3 @@ obj-$(CONFIG_PICVUE_PROC) += picvue_proc.o clean: make -C image clean - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/lasat/Platform b/arch/mips/lasat/Platform new file mode 100644 index 0000000..7602528 --- /dev/null +++ b/arch/mips/lasat/Platform @@ -0,0 +1,7 @@ +# +# LASAT platforms +# +platform-$(CONFIG_LASAT) += lasat/ +cflags-$(CONFIG_LASAT) += \ + -I$(srctree)/arch/mips/include/asm/mach-lasat +load-$(CONFIG_LASAT) += 0xffffffff80000000 -- cgit v0.10.2 From 53e4345906703785d6d02bd1b418abe2e8c9ebc1 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:54 +0100 Subject: MIPS: BCM47xx: Migrate to new platform makefile style. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index d99704c..e4c991e 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -2,6 +2,7 @@ platforms += alchemy platforms += ar7 +platforms += bcm47xx platforms += cobalt platforms += dec platforms += jazz diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 24ba939..b855d06 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -280,13 +280,6 @@ core-$(CONFIG_SIBYTE_BIGSUR) += arch/mips/sibyte/swarm/ load-$(CONFIG_SIBYTE_BIGSUR) := 0xffffffff80100000 # -# Broadcom BCM47XX boards -# -core-$(CONFIG_BCM47XX) += arch/mips/bcm47xx/ -cflags-$(CONFIG_BCM47XX) += -I$(srctree)/arch/mips/include/asm/mach-bcm47xx -load-$(CONFIG_BCM47XX) := 0xffffffff80001000 - -# # Broadcom BCM63XX boards # core-$(CONFIG_BCM63XX) += arch/mips/bcm63xx/ diff --git a/arch/mips/bcm47xx/Platform b/arch/mips/bcm47xx/Platform new file mode 100644 index 0000000..874b7ca --- /dev/null +++ b/arch/mips/bcm47xx/Platform @@ -0,0 +1,7 @@ +# +# Broadcom BCM47XX boards +# +platform-$(CONFIG_BCM47XX) += bcm47xx/ +cflags-$(CONFIG_BCM47XX) += \ + -I$(srctree)/arch/mips/include/asm/mach-bcm47xx +load-$(CONFIG_BCM47XX) := 0xffffffff80001000 -- cgit v0.10.2 From f5e8abd6f1fdba3abf6675700069005e25531208 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:54 +0100 Subject: MIPS: BCM63xx: Migrate to new platform makefile style. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index e4c991e..c00aa34 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -3,6 +3,7 @@ platforms += alchemy platforms += ar7 platforms += bcm47xx +platforms += bcm63xx platforms += cobalt platforms += dec platforms += jazz diff --git a/arch/mips/Makefile b/arch/mips/Makefile index b855d06..4cb60db6 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -280,13 +280,6 @@ core-$(CONFIG_SIBYTE_BIGSUR) += arch/mips/sibyte/swarm/ load-$(CONFIG_SIBYTE_BIGSUR) := 0xffffffff80100000 # -# Broadcom BCM63XX boards -# -core-$(CONFIG_BCM63XX) += arch/mips/bcm63xx/ -cflags-$(CONFIG_BCM63XX) += -I$(srctree)/arch/mips/include/asm/mach-bcm63xx/ -load-$(CONFIG_BCM63XX) := 0xffffffff80010000 - -# # Common TXx9 # core-$(CONFIG_MACH_TX39XX) += arch/mips/txx9/generic/ diff --git a/arch/mips/bcm63xx/Makefile b/arch/mips/bcm63xx/Makefile index 00064b6..6dfdc69 100644 --- a/arch/mips/bcm63xx/Makefile +++ b/arch/mips/bcm63xx/Makefile @@ -3,5 +3,3 @@ obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-y += boards/ - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/bcm63xx/Platform b/arch/mips/bcm63xx/Platform new file mode 100644 index 0000000..5f86b2f --- /dev/null +++ b/arch/mips/bcm63xx/Platform @@ -0,0 +1,7 @@ +# +# Broadcom BCM63XX boards +# +platform-$(CONFIG_BCM63XX) += bcm63xx/ +cflags-$(CONFIG_BCM63XX) += \ + -I$(srctree)/arch/mips/include/asm/mach-bcm63xx/ +load-$(CONFIG_BCM63XX) := 0xffffffff80010000 -- cgit v0.10.2 From f6e1db1b87a9199275694d10713d4baa80030fc7 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:54 +0100 Subject: MIPS: Octeon: Migrate to new platform makefile style. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index c00aa34..5a45333 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -4,6 +4,7 @@ platforms += alchemy platforms += ar7 platforms += bcm47xx platforms += bcm63xx +platforms += cavium-octeon platforms += cobalt platforms += dec platforms += jazz diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 4cb60db6..b62d832 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -301,18 +301,6 @@ core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/txx9/rbtx4927/ core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/txx9/rbtx4938/ core-$(CONFIG_TOSHIBA_RBTX4939) += arch/mips/txx9/rbtx4939/ -# -# Cavium Octeon -# -core-$(CONFIG_CPU_CAVIUM_OCTEON) += arch/mips/cavium-octeon/ -cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += -I$(srctree)/arch/mips/include/asm/mach-cavium-octeon -core-$(CONFIG_CPU_CAVIUM_OCTEON) += arch/mips/cavium-octeon/executive/ -ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL -load-$(CONFIG_CPU_CAVIUM_OCTEON) += 0xffffffff84100000 -else -load-$(CONFIG_CPU_CAVIUM_OCTEON) += 0xffffffff81100000 -endif - cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic drivers-$(CONFIG_PCI) += arch/mips/pci/ diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile index 3e98763..19eb043 100644 --- a/arch/mips/cavium-octeon/Makefile +++ b/arch/mips/cavium-octeon/Makefile @@ -12,7 +12,6 @@ obj-y := cpu.o setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o obj-y += dma-octeon.o flash_setup.o obj-y += octeon-memcpy.o +obj-y += executive/ obj-$(CONFIG_SMP) += smp.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/cavium-octeon/Platform b/arch/mips/cavium-octeon/Platform new file mode 100644 index 0000000..1e43ccf --- /dev/null +++ b/arch/mips/cavium-octeon/Platform @@ -0,0 +1,11 @@ +# +# Cavium Octeon +# +platform-$(CONFIG_CPU_CAVIUM_OCTEON) += cavium-octeon/ +cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += \ + -I$(srctree)/arch/mips/include/asm/mach-cavium-octeon +ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL +load-$(CONFIG_CPU_CAVIUM_OCTEON) += 0xffffffff84100000 +else +load-$(CONFIG_CPU_CAVIUM_OCTEON) += 0xffffffff81100000 +endif -- cgit v0.10.2 From 34f5c1c5787bd13a3fbfc284ff7f719846427b9d Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:55 +0100 Subject: MIPS: Sibyte: Migrate to new platform makefile style. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 5a45333..e0fb370 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -18,6 +18,7 @@ platforms += rb532 platforms += sgi-ip22 platforms += sgi-ip27 platforms += sgi-ip32 +platforms += sibyte platforms += sni platforms += vr41xx platforms += wrppmc diff --git a/arch/mips/Makefile b/arch/mips/Makefile index b62d832..4cf7258 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -230,56 +230,6 @@ core-$(CONFIG_NEC_MARKEINS) += arch/mips/emma/markeins/ load-$(CONFIG_NEC_MARKEINS) += 0xffffffff88100000 # -# Sibyte SB1250/BCM1480 SOC -# -# This is a LIB so that it links at the end, and initcalls are later -# the sequence; but it is built as an object so that modules don't get -# removed (as happens, even if they have __initcall/module_init) -# -core-$(CONFIG_SIBYTE_BCM112X) += arch/mips/sibyte/sb1250/ -core-$(CONFIG_SIBYTE_BCM112X) += arch/mips/sibyte/common/ -cflags-$(CONFIG_SIBYTE_BCM112X) += -I$(srctree)/arch/mips/include/asm/mach-sibyte \ - -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL - -core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/sb1250/ -core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/common/ -cflags-$(CONFIG_SIBYTE_SB1250) += -I$(srctree)/arch/mips/include/asm/mach-sibyte \ - -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL - -core-$(CONFIG_SIBYTE_BCM1x55) += arch/mips/sibyte/bcm1480/ -core-$(CONFIG_SIBYTE_BCM1x55) += arch/mips/sibyte/common/ -cflags-$(CONFIG_SIBYTE_BCM1x55) += -I$(srctree)/arch/mips/include/asm/mach-sibyte \ - -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL - -core-$(CONFIG_SIBYTE_BCM1x80) += arch/mips/sibyte/bcm1480/ -core-$(CONFIG_SIBYTE_BCM1x80) += arch/mips/sibyte/common/ -cflags-$(CONFIG_SIBYTE_BCM1x80) += -I$(srctree)/arch/mips/include/asm/mach-sibyte \ - -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL - -# -# Sibyte BCM91120x (Carmel) board -# Sibyte BCM91120C (CRhine) board -# Sibyte BCM91125C (CRhone) board -# Sibyte BCM91125E (Rhone) board -# Sibyte SWARM board -# Sibyte BCM91x80 (BigSur) board -# -core-$(CONFIG_SIBYTE_CARMEL) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_CARMEL) := 0xffffffff80100000 -core-$(CONFIG_SIBYTE_CRHINE) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_CRHINE) := 0xffffffff80100000 -core-$(CONFIG_SIBYTE_CRHONE) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_CRHONE) := 0xffffffff80100000 -core-$(CONFIG_SIBYTE_RHONE) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_RHONE) := 0xffffffff80100000 -core-$(CONFIG_SIBYTE_SENTOSA) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_SENTOSA) := 0xffffffff80100000 -core-$(CONFIG_SIBYTE_SWARM) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_SWARM) := 0xffffffff80100000 -core-$(CONFIG_SIBYTE_BIGSUR) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_BIGSUR) := 0xffffffff80100000 - -# # Common TXx9 # core-$(CONFIG_MACH_TX39XX) += arch/mips/txx9/generic/ diff --git a/arch/mips/sibyte/Makefile b/arch/mips/sibyte/Makefile new file mode 100644 index 0000000..c8ed2c8 --- /dev/null +++ b/arch/mips/sibyte/Makefile @@ -0,0 +1,27 @@ +# +# Sibyte SB1250 / BCM1480 family of SOCs +# +obj-$(CONFIG_SIBYTE_BCM112X) += sb1250/ +obj-$(CONFIG_SIBYTE_BCM112X) += common/ +obj-$(CONFIG_SIBYTE_SB1250) += sb1250/ +obj-$(CONFIG_SIBYTE_SB1250) += common/ +obj-$(CONFIG_SIBYTE_BCM1x55) += bcm1480/ +obj-$(CONFIG_SIBYTE_BCM1x55) += common/ +obj-$(CONFIG_SIBYTE_BCM1x80) += bcm1480/ +obj-$(CONFIG_SIBYTE_BCM1x80) += common/ + +# +# Sibyte BCM91120x (Carmel) board +# Sibyte BCM91120C (CRhine) board +# Sibyte BCM91125C (CRhone) board +# Sibyte BCM91125E (Rhone) board +# Sibyte SWARM board +# Sibyte BCM91x80 (BigSur) board +# +obj-$(CONFIG_SIBYTE_CARMEL) += swarm/ +obj-$(CONFIG_SIBYTE_CRHINE) += swarm/ +obj-$(CONFIG_SIBYTE_CRHONE) += swarm/ +obj-$(CONFIG_SIBYTE_RHONE) += swarm/ +obj-$(CONFIG_SIBYTE_SENTOSA) += swarm/ +obj-$(CONFIG_SIBYTE_SWARM) += swarm/ +obj-$(CONFIG_SIBYTE_BIGSUR) += swarm/ diff --git a/arch/mips/sibyte/Platform b/arch/mips/sibyte/Platform new file mode 100644 index 0000000..911dfe3 --- /dev/null +++ b/arch/mips/sibyte/Platform @@ -0,0 +1,43 @@ +# +# These are all rather similar so we consider them a single platform +# +platform-$(CONFIG_SIBYTE_BCM112X) += sibyte/ +platform-$(CONFIG_SIBYTE_SB1250) += sibyte/ +platform-$(CONFIG_SIBYTE_BCM1x55) += sibyte/ +platform-$(CONFIG_SIBYTE_BCM1x80) += sibyte/ + +# +# Sibyte SB1250 / BCM1480 family of SOCs +# +cflags-$(CONFIG_SIBYTE_BCM112X) += \ + -I$(srctree)/arch/mips/include/asm/mach-sibyte \ + -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL + +platform-$(CONFIG_SIBYTE_SB1250) += sibyte/ +cflags-$(CONFIG_SIBYTE_SB1250) += \ + -I$(srctree)/arch/mips/include/asm/mach-sibyte \ + -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL + +cflags-$(CONFIG_SIBYTE_BCM1x55) += \ + -I$(srctree)/arch/mips/include/asm/mach-sibyte \ + -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL + +cflags-$(CONFIG_SIBYTE_BCM1x80) += \ + -I$(srctree)/arch/mips/include/asm/mach-sibyte \ + -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL + +# +# Sibyte BCM91120x (Carmel) board +# Sibyte BCM91120C (CRhine) board +# Sibyte BCM91125C (CRhone) board +# Sibyte BCM91125E (Rhone) board +# Sibyte SWARM board +# Sibyte BCM91x80 (BigSur) board +# +load-$(CONFIG_SIBYTE_CARMEL) := 0xffffffff80100000 +load-$(CONFIG_SIBYTE_CRHINE) := 0xffffffff80100000 +load-$(CONFIG_SIBYTE_CRHONE) := 0xffffffff80100000 +load-$(CONFIG_SIBYTE_RHONE) := 0xffffffff80100000 +load-$(CONFIG_SIBYTE_SENTOSA) := 0xffffffff80100000 +load-$(CONFIG_SIBYTE_SWARM) := 0xffffffff80100000 +load-$(CONFIG_SIBYTE_BIGSUR) := 0xffffffff80100000 diff --git a/arch/mips/sibyte/bcm1480/Makefile b/arch/mips/sibyte/bcm1480/Makefile index f292f7d..cdc4c56 100644 --- a/arch/mips/sibyte/bcm1480/Makefile +++ b/arch/mips/sibyte/bcm1480/Makefile @@ -1,5 +1,3 @@ obj-y := setup.o irq.o time.o obj-$(CONFIG_SMP) += smp.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/sibyte/common/Makefile b/arch/mips/sibyte/common/Makefile index 4f65983..36aa700 100644 --- a/arch/mips/sibyte/common/Makefile +++ b/arch/mips/sibyte/common/Makefile @@ -1,5 +1,3 @@ obj-y := cfe.o obj-$(CONFIG_SIBYTE_CFE_CONSOLE) += cfe_console.o obj-$(CONFIG_SIBYTE_TBPROF) += sb_tbprof.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/sibyte/sb1250/Makefile b/arch/mips/sibyte/sb1250/Makefile index 1896f4e..d3d969d 100644 --- a/arch/mips/sibyte/sb1250/Makefile +++ b/arch/mips/sibyte/sb1250/Makefile @@ -2,5 +2,3 @@ obj-y := setup.o irq.o time.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SIBYTE_BUS_WATCHER) += bus_watcher.o - -EXTRA_CFLAGS += -Werror -- cgit v0.10.2 From a8b361d97f8e5a496a6144c470be03595247ad9f Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:55 +0100 Subject: MIPS: TXx9: Migrate to new platform makefile style. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index e0fb370..a4bda75 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -20,6 +20,7 @@ platforms += sgi-ip27 platforms += sgi-ip32 platforms += sibyte platforms += sni +platforms += txx9 platforms += vr41xx platforms += wrppmc diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 4cf7258..e136e62 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -229,28 +229,6 @@ cflags-$(CONFIG_SOC_EMMA2RH) += -I$(srctree)/arch/mips/include/asm/mach-emma2rh core-$(CONFIG_NEC_MARKEINS) += arch/mips/emma/markeins/ load-$(CONFIG_NEC_MARKEINS) += 0xffffffff88100000 -# -# Common TXx9 -# -core-$(CONFIG_MACH_TX39XX) += arch/mips/txx9/generic/ -cflags-$(CONFIG_MACH_TX39XX) += -I$(srctree)/arch/mips/include/asm/mach-tx39xx -load-$(CONFIG_MACH_TX39XX) += 0xffffffff80050000 -core-$(CONFIG_MACH_TX49XX) += arch/mips/txx9/generic/ -cflags-$(CONFIG_MACH_TX49XX) += -I$(srctree)/arch/mips/include/asm/mach-tx49xx -load-$(CONFIG_MACH_TX49XX) += 0xffffffff80100000 - -# -# Toshiba JMR-TX3927 board -# -core-$(CONFIG_TOSHIBA_JMR3927) += arch/mips/txx9/jmr3927/ - -# -# Toshiba RBTX49XX boards -# -core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/txx9/rbtx4927/ -core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/txx9/rbtx4938/ -core-$(CONFIG_TOSHIBA_RBTX4939) += arch/mips/txx9/rbtx4939/ - cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic drivers-$(CONFIG_PCI) += arch/mips/pci/ diff --git a/arch/mips/txx9/Makefile b/arch/mips/txx9/Makefile new file mode 100644 index 0000000..34787da --- /dev/null +++ b/arch/mips/txx9/Makefile @@ -0,0 +1,17 @@ +# +# Common TXx9 +# +obj-$(CONFIG_MACH_TX39XX) += generic/ +obj-$(CONFIG_MACH_TX49XX) += generic/ + +# +# Toshiba JMR-TX3927 board +# +obj-$(CONFIG_TOSHIBA_JMR3927) += jmr3927/ + +# +# Toshiba RBTX49XX boards +# +obj-$(CONFIG_TOSHIBA_RBTX4927) += rbtx4927/ +obj-$(CONFIG_TOSHIBA_RBTX4938) += rbtx4938/ +obj-$(CONFIG_TOSHIBA_RBTX4939) += rbtx4939/ diff --git a/arch/mips/txx9/Platform b/arch/mips/txx9/Platform new file mode 100644 index 0000000..a801abb --- /dev/null +++ b/arch/mips/txx9/Platform @@ -0,0 +1,10 @@ +platform-$(CONFIG_MACH_TX39XX) += txx9/ +platform-$(CONFIG_MACH_TX49XX) += txx9/ + +cflags-$(CONFIG_MACH_TX39XX) += \ + -I$(srctree)/arch/mips/include/asm/mach-tx39xx +cflags-$(CONFIG_MACH_TX49XX) += \ + -I$(srctree)/arch/mips/include/asm/mach-tx49xx + +load-$(CONFIG_MACH_TX39XX) += 0xffffffff80050000 +load-$(CONFIG_MACH_TX49XX) += 0xffffffff80100000 diff --git a/arch/mips/txx9/generic/Makefile b/arch/mips/txx9/generic/Makefile index f2579ce..1863c16 100644 --- a/arch/mips/txx9/generic/Makefile +++ b/arch/mips/txx9/generic/Makefile @@ -11,5 +11,3 @@ obj-$(CONFIG_SOC_TX4939) += setup_tx4939.o irq_tx4939.o obj-$(CONFIG_TOSHIBA_FPCIB0) += smsc_fdc37m81x.o obj-$(CONFIG_SPI) += spi_eeprom.o obj-$(CONFIG_TXX9_7SEGLED) += 7segled.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/txx9/jmr3927/Makefile b/arch/mips/txx9/jmr3927/Makefile index 20d61ac..9f5d5b6 100644 --- a/arch/mips/txx9/jmr3927/Makefile +++ b/arch/mips/txx9/jmr3927/Makefile @@ -3,5 +3,3 @@ # obj-y += prom.o irq.o setup.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/txx9/rbtx4927/Makefile b/arch/mips/txx9/rbtx4927/Makefile index f3e1f59..60b24c8 100644 --- a/arch/mips/txx9/rbtx4927/Makefile +++ b/arch/mips/txx9/rbtx4927/Makefile @@ -1,3 +1 @@ obj-y += prom.o setup.o irq.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/txx9/rbtx4938/Makefile b/arch/mips/txx9/rbtx4938/Makefile index f3e1f59..60b24c8 100644 --- a/arch/mips/txx9/rbtx4938/Makefile +++ b/arch/mips/txx9/rbtx4938/Makefile @@ -1,3 +1 @@ obj-y += prom.o setup.o irq.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/txx9/rbtx4939/Makefile b/arch/mips/txx9/rbtx4939/Makefile index 3232cd0..5c84625 100644 --- a/arch/mips/txx9/rbtx4939/Makefile +++ b/arch/mips/txx9/rbtx4939/Makefile @@ -1,3 +1 @@ obj-y += irq.o setup.o prom.o - -EXTRA_CFLAGS += -Werror -- cgit v0.10.2 From 2f22f456933c1db57d84627a046dd20e935ad51a Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:55 +0100 Subject: MIPS: EMMA: Migrate to new platform makefile style. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index a4bda75..8985487 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -7,6 +7,7 @@ platforms += bcm63xx platforms += cavium-octeon platforms += cobalt platforms += dec +platforms += emma platforms += jazz platforms += lasat platforms += loongson diff --git a/arch/mips/Makefile b/arch/mips/Makefile index e136e62..2ba20d9 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -217,18 +217,6 @@ load-$(CONFIG_PNX8550_JBS) += 0xffffffff80060000 libs-$(CONFIG_PNX8550_STB810) += arch/mips/nxp/pnx8550/stb810/ load-$(CONFIG_PNX8550_STB810) += 0xffffffff80060000 -# -# Common NEC EMMAXXX -# -core-$(CONFIG_SOC_EMMA2RH) += arch/mips/emma/common/ -cflags-$(CONFIG_SOC_EMMA2RH) += -I$(srctree)/arch/mips/include/asm/mach-emma2rh - -# -# NEC EMMA2RH Mark-eins -# -core-$(CONFIG_NEC_MARKEINS) += arch/mips/emma/markeins/ -load-$(CONFIG_NEC_MARKEINS) += 0xffffffff88100000 - cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic drivers-$(CONFIG_PCI) += arch/mips/pci/ diff --git a/arch/mips/emma/Makefile b/arch/mips/emma/Makefile new file mode 100644 index 0000000..4254a31 --- /dev/null +++ b/arch/mips/emma/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_SOC_EMMA2RH) += common/ + +# +# NEC EMMA2RH Mark-eins +# +obj-$(CONFIG_NEC_MARKEINS) += markeins/ diff --git a/arch/mips/emma/Platform b/arch/mips/emma/Platform new file mode 100644 index 0000000..0282f7f --- /dev/null +++ b/arch/mips/emma/Platform @@ -0,0 +1,4 @@ +platform-$(CONFIG_SOC_EMMA2RH) += emma/ +cflags-$(CONFIG_SOC_EMMA2RH) += \ + -I$(srctree)/arch/mips/include/asm/mach-emma2rh +load-$(CONFIG_NEC_MARKEINS) += 0xffffffff88100000 -- cgit v0.10.2 From 86c6d4d0acc64543a485c11e197d0bd2c5ae0bb2 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:55 +0100 Subject: MIPS: PNX833x: Move code one directory level up. It was sharing the nxp directory but no code with pnx8550 and will fit better into the new platform makefile scheme, if moved. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 2ba20d9..0556bc4 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -192,11 +192,11 @@ endif include $(srctree)/arch/mips/Kbuild.platforms # NXP STB225 -core-$(CONFIG_SOC_PNX833X) += arch/mips/nxp/pnx833x/common/ +core-$(CONFIG_SOC_PNX833X) += arch/mips/pnx833x/common/ cflags-$(CONFIG_SOC_PNX833X) += -Iarch/mips/include/asm/mach-pnx833x -libs-$(CONFIG_NXP_STB220) += arch/mips/nxp/pnx833x/stb22x/ +libs-$(CONFIG_NXP_STB220) += arch/mips/pnx833x/stb22x/ load-$(CONFIG_NXP_STB220) += 0xffffffff80001000 -libs-$(CONFIG_NXP_STB225) += arch/mips/nxp/pnx833x/stb22x/ +libs-$(CONFIG_NXP_STB225) += arch/mips/pnx833x/stb22x/ load-$(CONFIG_NXP_STB225) += 0xffffffff80001000 # diff --git a/arch/mips/nxp/pnx833x/common/Makefile b/arch/mips/nxp/pnx833x/common/Makefile deleted file mode 100644 index 4a16f3b..0000000 --- a/arch/mips/nxp/pnx833x/common/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-y := interrupts.o platform.o prom.o setup.o reset.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/nxp/pnx833x/common/interrupts.c b/arch/mips/nxp/pnx833x/common/interrupts.c deleted file mode 100644 index 941916f..0000000 --- a/arch/mips/nxp/pnx833x/common/interrupts.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * interrupts.c: Interrupt mappings for PNX833X. - * - * Copyright 2008 NXP Semiconductors - * Chris Steel - * Daniel Laird - * - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int mips_cpu_timer_irq; - -static const unsigned int irq_prio[PNX833X_PIC_NUM_IRQ] = -{ - 0, /* unused */ - 4, /* PNX833X_PIC_I2C0_INT 1 */ - 4, /* PNX833X_PIC_I2C1_INT 2 */ - 1, /* PNX833X_PIC_UART0_INT 3 */ - 1, /* PNX833X_PIC_UART1_INT 4 */ - 6, /* PNX833X_PIC_TS_IN0_DV_INT 5 */ - 6, /* PNX833X_PIC_TS_IN0_DMA_INT 6 */ - 7, /* PNX833X_PIC_GPIO_INT 7 */ - 4, /* PNX833X_PIC_AUDIO_DEC_INT 8 */ - 5, /* PNX833X_PIC_VIDEO_DEC_INT 9 */ - 4, /* PNX833X_PIC_CONFIG_INT 10 */ - 4, /* PNX833X_PIC_AOI_INT 11 */ - 9, /* PNX833X_PIC_SYNC_INT 12 */ - 9, /* PNX8335_PIC_SATA_INT 13 */ - 4, /* PNX833X_PIC_OSD_INT 14 */ - 9, /* PNX833X_PIC_DISP1_INT 15 */ - 4, /* PNX833X_PIC_DEINTERLACER_INT 16 */ - 9, /* PNX833X_PIC_DISPLAY2_INT 17 */ - 4, /* PNX833X_PIC_VC_INT 18 */ - 4, /* PNX833X_PIC_SC_INT 19 */ - 9, /* PNX833X_PIC_IDE_INT 20 */ - 9, /* PNX833X_PIC_IDE_DMA_INT 21 */ - 6, /* PNX833X_PIC_TS_IN1_DV_INT 22 */ - 6, /* PNX833X_PIC_TS_IN1_DMA_INT 23 */ - 4, /* PNX833X_PIC_SGDX_DMA_INT 24 */ - 4, /* PNX833X_PIC_TS_OUT_INT 25 */ - 4, /* PNX833X_PIC_IR_INT 26 */ - 3, /* PNX833X_PIC_VMSP1_INT 27 */ - 3, /* PNX833X_PIC_VMSP2_INT 28 */ - 4, /* PNX833X_PIC_PIBC_INT 29 */ - 4, /* PNX833X_PIC_TS_IN0_TRD_INT 30 */ - 4, /* PNX833X_PIC_SGDX_TPD_INT 31 */ - 5, /* PNX833X_PIC_USB_INT 32 */ - 4, /* PNX833X_PIC_TS_IN1_TRD_INT 33 */ - 4, /* PNX833X_PIC_CLOCK_INT 34 */ - 4, /* PNX833X_PIC_SGDX_PARSER_INT 35 */ - 4, /* PNX833X_PIC_VMSP_DMA_INT 36 */ -#if defined(CONFIG_SOC_PNX8335) - 4, /* PNX8335_PIC_MIU_INT 37 */ - 4, /* PNX8335_PIC_AVCHIP_IRQ_INT 38 */ - 9, /* PNX8335_PIC_SYNC_HD_INT 39 */ - 9, /* PNX8335_PIC_DISP_HD_INT 40 */ - 9, /* PNX8335_PIC_DISP_SCALER_INT 41 */ - 4, /* PNX8335_PIC_OSD_HD1_INT 42 */ - 4, /* PNX8335_PIC_DTL_WRITER_Y_INT 43 */ - 4, /* PNX8335_PIC_DTL_WRITER_C_INT 44 */ - 4, /* PNX8335_PIC_DTL_EMULATOR_Y_IR_INT 45 */ - 4, /* PNX8335_PIC_DTL_EMULATOR_C_IR_INT 46 */ - 4, /* PNX8335_PIC_DENC_TTX_INT 47 */ - 4, /* PNX8335_PIC_MMI_SIF0_INT 48 */ - 4, /* PNX8335_PIC_MMI_SIF1_INT 49 */ - 4, /* PNX8335_PIC_MMI_CDMMU_INT 50 */ - 4, /* PNX8335_PIC_PIBCS_INT 51 */ - 12, /* PNX8335_PIC_ETHERNET_INT 52 */ - 3, /* PNX8335_PIC_VMSP1_0_INT 53 */ - 3, /* PNX8335_PIC_VMSP1_1_INT 54 */ - 4, /* PNX8335_PIC_VMSP1_DMA_INT 55 */ - 4, /* PNX8335_PIC_TDGR_DE_INT 56 */ - 4, /* PNX8335_PIC_IR1_IRQ_INT 57 */ -#endif -}; - -static void pnx833x_timer_dispatch(void) -{ - do_IRQ(mips_cpu_timer_irq); -} - -static void pic_dispatch(void) -{ - unsigned int irq = PNX833X_REGFIELD(PIC_INT_SRC, INT_SRC); - - if ((irq >= 1) && (irq < (PNX833X_PIC_NUM_IRQ))) { - unsigned long priority = PNX833X_PIC_INT_PRIORITY; - PNX833X_PIC_INT_PRIORITY = irq_prio[irq]; - - if (irq == PNX833X_PIC_GPIO_INT) { - unsigned long mask = PNX833X_PIO_INT_STATUS & PNX833X_PIO_INT_ENABLE; - int pin; - while ((pin = ffs(mask & 0xffff))) { - pin -= 1; - do_IRQ(PNX833X_GPIO_IRQ_BASE + pin); - mask &= ~(1 << pin); - } - } else { - do_IRQ(irq + PNX833X_PIC_IRQ_BASE); - } - - PNX833X_PIC_INT_PRIORITY = priority; - } else { - printk(KERN_ERR "plat_irq_dispatch: unexpected irq %u\n", irq); - } -} - -asmlinkage void plat_irq_dispatch(void) -{ - unsigned int pending = read_c0_status() & read_c0_cause(); - - if (pending & STATUSF_IP4) - pic_dispatch(); - else if (pending & STATUSF_IP7) - do_IRQ(PNX833X_TIMER_IRQ); - else - spurious_interrupt(); -} - -static inline void pnx833x_hard_enable_pic_irq(unsigned int irq) -{ - /* Currently we do this by setting IRQ priority to 1. - If priority support is being implemented, 1 should be repalced - by a better value. */ - PNX833X_PIC_INT_REG(irq) = irq_prio[irq]; -} - -static inline void pnx833x_hard_disable_pic_irq(unsigned int irq) -{ - /* Disable IRQ by writing setting it's priority to 0 */ - PNX833X_PIC_INT_REG(irq) = 0; -} - -static int irqflags[PNX833X_PIC_NUM_IRQ]; /* initialized by zeroes */ -#define IRQFLAG_STARTED 1 -#define IRQFLAG_DISABLED 2 - -static DEFINE_RAW_SPINLOCK(pnx833x_irq_lock); - -static unsigned int pnx833x_startup_pic_irq(unsigned int irq) -{ - unsigned long flags; - unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; - - raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); - - irqflags[pic_irq] = IRQFLAG_STARTED; /* started, not disabled */ - pnx833x_hard_enable_pic_irq(pic_irq); - - raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); - return 0; -} - -static void pnx833x_shutdown_pic_irq(unsigned int irq) -{ - unsigned long flags; - unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; - - raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); - - irqflags[pic_irq] = 0; /* not started */ - pnx833x_hard_disable_pic_irq(pic_irq); - - raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); -} - -static void pnx833x_enable_pic_irq(unsigned int irq) -{ - unsigned long flags; - unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; - - raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); - - irqflags[pic_irq] &= ~IRQFLAG_DISABLED; - if (irqflags[pic_irq] == IRQFLAG_STARTED) - pnx833x_hard_enable_pic_irq(pic_irq); - - raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); -} - -static void pnx833x_disable_pic_irq(unsigned int irq) -{ - unsigned long flags; - unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; - - raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); - - irqflags[pic_irq] |= IRQFLAG_DISABLED; - pnx833x_hard_disable_pic_irq(pic_irq); - - raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); -} - -static void pnx833x_ack_pic_irq(unsigned int irq) -{ -} - -static void pnx833x_end_pic_irq(unsigned int irq) -{ -} - -static DEFINE_RAW_SPINLOCK(pnx833x_gpio_pnx833x_irq_lock); - -static unsigned int pnx833x_startup_gpio_irq(unsigned int irq) -{ - int pin = irq - PNX833X_GPIO_IRQ_BASE; - unsigned long flags; - raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); - pnx833x_gpio_enable_irq(pin); - raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); - return 0; -} - -static void pnx833x_enable_gpio_irq(unsigned int irq) -{ - int pin = irq - PNX833X_GPIO_IRQ_BASE; - unsigned long flags; - raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); - pnx833x_gpio_enable_irq(pin); - raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); -} - -static void pnx833x_disable_gpio_irq(unsigned int irq) -{ - int pin = irq - PNX833X_GPIO_IRQ_BASE; - unsigned long flags; - raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); - pnx833x_gpio_disable_irq(pin); - raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); -} - -static void pnx833x_ack_gpio_irq(unsigned int irq) -{ -} - -static void pnx833x_end_gpio_irq(unsigned int irq) -{ - int pin = irq - PNX833X_GPIO_IRQ_BASE; - unsigned long flags; - raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); - pnx833x_gpio_clear_irq(pin); - raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); -} - -static int pnx833x_set_type_gpio_irq(unsigned int irq, unsigned int flow_type) -{ - int pin = irq - PNX833X_GPIO_IRQ_BASE; - int gpio_mode; - - switch (flow_type) { - case IRQ_TYPE_EDGE_RISING: - gpio_mode = GPIO_INT_EDGE_RISING; - break; - case IRQ_TYPE_EDGE_FALLING: - gpio_mode = GPIO_INT_EDGE_FALLING; - break; - case IRQ_TYPE_EDGE_BOTH: - gpio_mode = GPIO_INT_EDGE_BOTH; - break; - case IRQ_TYPE_LEVEL_HIGH: - gpio_mode = GPIO_INT_LEVEL_HIGH; - break; - case IRQ_TYPE_LEVEL_LOW: - gpio_mode = GPIO_INT_LEVEL_LOW; - break; - default: - gpio_mode = GPIO_INT_NONE; - break; - } - - pnx833x_gpio_setup_irq(gpio_mode, pin); - - return 0; -} - -static struct irq_chip pnx833x_pic_irq_type = { - .name = "PNX-PIC", - .startup = pnx833x_startup_pic_irq, - .shutdown = pnx833x_shutdown_pic_irq, - .enable = pnx833x_enable_pic_irq, - .disable = pnx833x_disable_pic_irq, - .ack = pnx833x_ack_pic_irq, - .end = pnx833x_end_pic_irq -}; - -static struct irq_chip pnx833x_gpio_irq_type = { - .name = "PNX-GPIO", - .startup = pnx833x_startup_gpio_irq, - .shutdown = pnx833x_disable_gpio_irq, - .enable = pnx833x_enable_gpio_irq, - .disable = pnx833x_disable_gpio_irq, - .ack = pnx833x_ack_gpio_irq, - .end = pnx833x_end_gpio_irq, - .set_type = pnx833x_set_type_gpio_irq -}; - -void __init arch_init_irq(void) -{ - unsigned int irq; - - /* setup standard internal cpu irqs */ - mips_cpu_irq_init(); - - /* Set IRQ information in irq_desc */ - for (irq = PNX833X_PIC_IRQ_BASE; irq < (PNX833X_PIC_IRQ_BASE + PNX833X_PIC_NUM_IRQ); irq++) { - pnx833x_hard_disable_pic_irq(irq); - set_irq_chip_and_handler(irq, &pnx833x_pic_irq_type, handle_simple_irq); - } - - for (irq = PNX833X_GPIO_IRQ_BASE; irq < (PNX833X_GPIO_IRQ_BASE + PNX833X_GPIO_NUM_IRQ); irq++) - set_irq_chip_and_handler(irq, &pnx833x_gpio_irq_type, handle_simple_irq); - - /* Set PIC priority limiter register to 0 */ - PNX833X_PIC_INT_PRIORITY = 0; - - /* Setup GPIO IRQ dispatching */ - pnx833x_startup_pic_irq(PNX833X_PIC_GPIO_INT); - - /* Enable PIC IRQs (HWIRQ2) */ - if (cpu_has_vint) - set_vi_handler(4, pic_dispatch); - - write_c0_status(read_c0_status() | IE_IRQ2); -} - -unsigned int __cpuinit get_c0_compare_int(void) -{ - if (cpu_has_vint) - set_vi_handler(cp0_compare_irq, pnx833x_timer_dispatch); - - mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; - return mips_cpu_timer_irq; -} - -void __init plat_time_init(void) -{ - /* calculate mips_hpt_frequency based on PNX833X_CLOCK_CPUCP_CTL reg */ - - extern unsigned long mips_hpt_frequency; - unsigned long reg = PNX833X_CLOCK_CPUCP_CTL; - - if (!(PNX833X_BIT(reg, CLOCK_CPUCP_CTL, EXIT_RESET))) { - /* Functional clock is disabled so use crystal frequency */ - mips_hpt_frequency = 25; - } else { -#if defined(CONFIG_SOC_PNX8335) - /* Functional clock is enabled, so get clock multiplier */ - mips_hpt_frequency = 90 + (10 * PNX8335_REGFIELD(CLOCK_PLL_CPU_CTL, FREQ)); -#else - static const unsigned long int freq[4] = {240, 160, 120, 80}; - mips_hpt_frequency = freq[PNX833X_FIELD(reg, CLOCK_CPUCP_CTL, DIV_CLOCK)]; -#endif - } - - printk(KERN_INFO "CPU clock is %ld MHz\n", mips_hpt_frequency); - - mips_hpt_frequency *= 500000; -} diff --git a/arch/mips/nxp/pnx833x/common/platform.c b/arch/mips/nxp/pnx833x/common/platform.c deleted file mode 100644 index 01f8345..0000000 --- a/arch/mips/nxp/pnx833x/common/platform.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * platform.c: platform support for PNX833X. - * - * Copyright 2008 NXP Semiconductors - * Chris Steel - * Daniel Laird - * - * Based on software written by: - * Nikita Youshchenko , based on PNX8550 code. - * - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_I2C_PNX0105 -/* Until i2c driver available in kernel.*/ -#include -#endif - -#include -#include -#include - -static u64 uart_dmamask = DMA_BIT_MASK(32); - -static struct resource pnx833x_uart_resources[] = { - [0] = { - .start = PNX833X_UART0_PORTS_START, - .end = PNX833X_UART0_PORTS_END, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = PNX833X_PIC_UART0_INT, - .end = PNX833X_PIC_UART0_INT, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = PNX833X_UART1_PORTS_START, - .end = PNX833X_UART1_PORTS_END, - .flags = IORESOURCE_MEM, - }, - [3] = { - .start = PNX833X_PIC_UART1_INT, - .end = PNX833X_PIC_UART1_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -struct pnx8xxx_port pnx8xxx_ports[] = { - [0] = { - .port = { - .type = PORT_PNX8XXX, - .iotype = UPIO_MEM, - .membase = (void __iomem *)PNX833X_UART0_PORTS_START, - .mapbase = PNX833X_UART0_PORTS_START, - .irq = PNX833X_PIC_UART0_INT, - .uartclk = 3692300, - .fifosize = 16, - .flags = UPF_BOOT_AUTOCONF, - .line = 0, - }, - }, - [1] = { - .port = { - .type = PORT_PNX8XXX, - .iotype = UPIO_MEM, - .membase = (void __iomem *)PNX833X_UART1_PORTS_START, - .mapbase = PNX833X_UART1_PORTS_START, - .irq = PNX833X_PIC_UART1_INT, - .uartclk = 3692300, - .fifosize = 16, - .flags = UPF_BOOT_AUTOCONF, - .line = 1, - }, - }, -}; - -static struct platform_device pnx833x_uart_device = { - .name = "pnx8xxx-uart", - .id = -1, - .dev = { - .dma_mask = &uart_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = pnx8xxx_ports, - }, - .num_resources = ARRAY_SIZE(pnx833x_uart_resources), - .resource = pnx833x_uart_resources, -}; - -static u64 ehci_dmamask = DMA_BIT_MASK(32); - -static struct resource pnx833x_usb_ehci_resources[] = { - [0] = { - .start = PNX833X_USB_PORTS_START, - .end = PNX833X_USB_PORTS_END, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = PNX833X_PIC_USB_INT, - .end = PNX833X_PIC_USB_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device pnx833x_usb_ehci_device = { - .name = "pnx833x-ehci", - .id = -1, - .dev = { - .dma_mask = &ehci_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, - .num_resources = ARRAY_SIZE(pnx833x_usb_ehci_resources), - .resource = pnx833x_usb_ehci_resources, -}; - -#ifdef CONFIG_I2C_PNX0105 -static struct resource pnx833x_i2c0_resources[] = { - { - .start = PNX833X_I2C0_PORTS_START, - .end = PNX833X_I2C0_PORTS_END, - .flags = IORESOURCE_MEM, - }, - { - .start = PNX833X_PIC_I2C0_INT, - .end = PNX833X_PIC_I2C0_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource pnx833x_i2c1_resources[] = { - { - .start = PNX833X_I2C1_PORTS_START, - .end = PNX833X_I2C1_PORTS_END, - .flags = IORESOURCE_MEM, - }, - { - .start = PNX833X_PIC_I2C1_INT, - .end = PNX833X_PIC_I2C1_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct i2c_pnx0105_dev pnx833x_i2c_dev[] = { - { - .base = PNX833X_I2C0_PORTS_START, - .irq = -1, /* should be PNX833X_PIC_I2C0_INT but polling is faster */ - .clock = 6, /* 0 == 400 kHz, 4 == 100 kHz(Maximum HDMI), 6 = 50kHz(Prefered HDCP) */ - .bus_addr = 0, /* no slave support */ - }, - { - .base = PNX833X_I2C1_PORTS_START, - .irq = -1, /* on high freq, polling is faster */ - /*.irq = PNX833X_PIC_I2C1_INT,*/ - .clock = 4, /* 0 == 400 kHz, 4 == 100 kHz. 100 kHz seems a safe default for now */ - .bus_addr = 0, /* no slave support */ - }, -}; - -static struct platform_device pnx833x_i2c0_device = { - .name = "i2c-pnx0105", - .id = 0, - .dev = { - .platform_data = &pnx833x_i2c_dev[0], - }, - .num_resources = ARRAY_SIZE(pnx833x_i2c0_resources), - .resource = pnx833x_i2c0_resources, -}; - -static struct platform_device pnx833x_i2c1_device = { - .name = "i2c-pnx0105", - .id = 1, - .dev = { - .platform_data = &pnx833x_i2c_dev[1], - }, - .num_resources = ARRAY_SIZE(pnx833x_i2c1_resources), - .resource = pnx833x_i2c1_resources, -}; -#endif - -static u64 ethernet_dmamask = DMA_BIT_MASK(32); - -static struct resource pnx833x_ethernet_resources[] = { - [0] = { - .start = PNX8335_IP3902_PORTS_START, - .end = PNX8335_IP3902_PORTS_END, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = PNX8335_PIC_ETHERNET_INT, - .end = PNX8335_PIC_ETHERNET_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device pnx833x_ethernet_device = { - .name = "ip3902-eth", - .id = -1, - .dev = { - .dma_mask = ðernet_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, - .num_resources = ARRAY_SIZE(pnx833x_ethernet_resources), - .resource = pnx833x_ethernet_resources, -}; - -static struct resource pnx833x_sata_resources[] = { - [0] = { - .start = PNX8335_SATA_PORTS_START, - .end = PNX8335_SATA_PORTS_END, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = PNX8335_PIC_SATA_INT, - .end = PNX8335_PIC_SATA_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device pnx833x_sata_device = { - .name = "pnx833x-sata", - .id = -1, - .num_resources = ARRAY_SIZE(pnx833x_sata_resources), - .resource = pnx833x_sata_resources, -}; - -static const char *part_probes[] = { - "cmdlinepart", - NULL -}; - -static void -pnx833x_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) -{ - struct nand_chip *this = mtd->priv; - unsigned long nandaddr = (unsigned long)this->IO_ADDR_W; - - if (cmd == NAND_CMD_NONE) - return; - - if (ctrl & NAND_CLE) - writeb(cmd, (void __iomem *)(nandaddr + PNX8335_NAND_CLE_MASK)); - else - writeb(cmd, (void __iomem *)(nandaddr + PNX8335_NAND_ALE_MASK)); -} - -static struct platform_nand_data pnx833x_flash_nand_data = { - .chip = { - .chip_delay = 25, - .part_probe_types = part_probes, - }, - .ctrl = { - .cmd_ctrl = pnx833x_flash_nand_cmd_ctrl - } -}; - -/* - * Set start to be the correct address (PNX8335_NAND_BASE with no 0xb!!), - * 12 bytes more seems to be the standard that allows for NAND access. - */ -static struct resource pnx833x_flash_nand_resource = { - .start = PNX8335_NAND_BASE, - .end = PNX8335_NAND_BASE + 12, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device pnx833x_flash_nand = { - .name = "gen_nand", - .id = -1, - .num_resources = 1, - .resource = &pnx833x_flash_nand_resource, - .dev = { - .platform_data = &pnx833x_flash_nand_data, - }, -}; - -static struct platform_device *pnx833x_platform_devices[] __initdata = { - &pnx833x_uart_device, - &pnx833x_usb_ehci_device, -#ifdef CONFIG_I2C_PNX0105 - &pnx833x_i2c0_device, - &pnx833x_i2c1_device, -#endif - &pnx833x_ethernet_device, - &pnx833x_sata_device, - &pnx833x_flash_nand, -}; - -static int __init pnx833x_platform_init(void) -{ - int res; - - res = platform_add_devices(pnx833x_platform_devices, - ARRAY_SIZE(pnx833x_platform_devices)); - - return res; -} - -arch_initcall(pnx833x_platform_init); diff --git a/arch/mips/nxp/pnx833x/common/prom.c b/arch/mips/nxp/pnx833x/common/prom.c deleted file mode 100644 index 29969f9..0000000 --- a/arch/mips/nxp/pnx833x/common/prom.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * prom.c: - * - * Copyright 2008 NXP Semiconductors - * Chris Steel - * Daniel Laird - * - * Based on software written by: - * Nikita Youshchenko , based on PNX8550 code. - * - * 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. - */ -#include -#include -#include - -void __init prom_init_cmdline(void) -{ - int argc = fw_arg0; - char **argv = (char **)fw_arg1; - char *c = &(arcs_cmdline[0]); - int i; - - for (i = 1; i < argc; i++) { - strcpy(c, argv[i]); - c += strlen(argv[i]); - if (i < argc-1) - *c++ = ' '; - } - *c = 0; -} - -char __init *prom_getenv(char *envname) -{ - extern char **prom_envp; - char **env = prom_envp; - int i; - - i = strlen(envname); - - while (*env) { - if (strncmp(envname, *env, i) == 0 && *(*env+i) == '=') - return *env + i + 1; - env++; - } - - return 0; -} - -void __init prom_free_prom_memory(void) -{ -} diff --git a/arch/mips/nxp/pnx833x/common/reset.c b/arch/mips/nxp/pnx833x/common/reset.c deleted file mode 100644 index e0ea96d..0000000 --- a/arch/mips/nxp/pnx833x/common/reset.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * reset.c: reset support for PNX833X. - * - * Copyright 2008 NXP Semiconductors - * Chris Steel - * Daniel Laird - * - * Based on software written by: - * Nikita Youshchenko , based on PNX8550 code. - * - * 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. - */ -#include -#include - -void pnx833x_machine_restart(char *command) -{ - PNX833X_RESET_CONTROL_2 = 0; - PNX833X_RESET_CONTROL = 0; -} - -void pnx833x_machine_halt(void) -{ - while (1) - __asm__ __volatile__ ("wait"); - -} - -void pnx833x_machine_power_off(void) -{ - pnx833x_machine_halt(); -} diff --git a/arch/mips/nxp/pnx833x/common/setup.c b/arch/mips/nxp/pnx833x/common/setup.c deleted file mode 100644 index e51fbc4..0000000 --- a/arch/mips/nxp/pnx833x/common/setup.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * setup.c: Setup PNX833X Soc. - * - * Copyright 2008 NXP Semiconductors - * Chris Steel - * Daniel Laird - * - * Based on software written by: - * Nikita Youshchenko , based on PNX8550 code. - * - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -extern void pnx833x_board_setup(void); -extern void pnx833x_machine_restart(char *); -extern void pnx833x_machine_halt(void); -extern void pnx833x_machine_power_off(void); - -int __init plat_mem_setup(void) -{ - /* fake pci bus to avoid bounce buffers */ - PCI_DMA_BUS_IS_PHYS = 1; - - /* set mips clock to 320MHz */ -#if defined(CONFIG_SOC_PNX8335) - PNX8335_WRITEFIELD(0x17, CLOCK_PLL_CPU_CTL, FREQ); -#endif - pnx833x_gpio_init(); /* so it will be ready in board_setup() */ - - pnx833x_board_setup(); - - _machine_restart = pnx833x_machine_restart; - _machine_halt = pnx833x_machine_halt; - pm_power_off = pnx833x_machine_power_off; - - /* IO/MEM resources. */ - set_io_port_base(KSEG1); - ioport_resource.start = 0; - ioport_resource.end = ~0; - iomem_resource.start = 0; - iomem_resource.end = ~0; - - return 0; -} diff --git a/arch/mips/nxp/pnx833x/stb22x/Makefile b/arch/mips/nxp/pnx833x/stb22x/Makefile deleted file mode 100644 index f81c580..0000000 --- a/arch/mips/nxp/pnx833x/stb22x/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -lib-y := board.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/nxp/pnx833x/stb22x/board.c b/arch/mips/nxp/pnx833x/stb22x/board.c deleted file mode 100644 index 644eb7c..0000000 --- a/arch/mips/nxp/pnx833x/stb22x/board.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * board.c: STB225 board support. - * - * Copyright 2008 NXP Semiconductors - * Chris Steel - * Daniel Laird - * - * Based on software written by: - * Nikita Youshchenko , based on PNX8550 code. - * - * 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. - */ -#include -#include -#include -#include -#include - -/* endianess twiddlers */ -#define PNX8335_DEBUG0 0x4400 -#define PNX8335_DEBUG1 0x4404 -#define PNX8335_DEBUG2 0x4408 -#define PNX8335_DEBUG3 0x440c -#define PNX8335_DEBUG4 0x4410 -#define PNX8335_DEBUG5 0x4414 -#define PNX8335_DEBUG6 0x4418 -#define PNX8335_DEBUG7 0x441c - -int prom_argc; -char **prom_argv, **prom_envp; - -extern void prom_init_cmdline(void); -extern char *prom_getenv(char *envname); - -const char *get_system_type(void) -{ - return "NXP STB22x"; -} - -static inline unsigned long env_or_default(char *env, unsigned long dfl) -{ - char *str = prom_getenv(env); - return str ? simple_strtol(str, 0, 0) : dfl; -} - -void __init prom_init(void) -{ - unsigned long memsize; - - prom_argc = fw_arg0; - prom_argv = (char **)fw_arg1; - prom_envp = (char **)fw_arg2; - - prom_init_cmdline(); - - memsize = env_or_default("memsize", 0x02000000); - add_memory_region(0, memsize, BOOT_MEM_RAM); -} - -void __init pnx833x_board_setup(void) -{ - pnx833x_gpio_select_function_alt(4); - pnx833x_gpio_select_output(4); - pnx833x_gpio_select_function_alt(5); - pnx833x_gpio_select_input(5); - pnx833x_gpio_select_function_alt(6); - pnx833x_gpio_select_input(6); - pnx833x_gpio_select_function_alt(7); - pnx833x_gpio_select_output(7); - - pnx833x_gpio_select_function_alt(25); - pnx833x_gpio_select_function_alt(26); - - pnx833x_gpio_select_function_alt(27); - pnx833x_gpio_select_function_alt(28); - pnx833x_gpio_select_function_alt(29); - pnx833x_gpio_select_function_alt(30); - pnx833x_gpio_select_function_alt(31); - pnx833x_gpio_select_function_alt(32); - pnx833x_gpio_select_function_alt(33); - -#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE) - /* Setup MIU for NAND access on CS0... - * - * (it seems that we must also configure CS1 for reliable operation, - * otherwise the first read ID command will fail if it's read as 4 bytes - * but pass if it's read as 1 word.) - */ - - /* Setup MIU CS0 & CS1 timing */ - PNX833X_MIU_SEL0 = 0; - PNX833X_MIU_SEL1 = 0; - PNX833X_MIU_SEL0_TIMING = 0x50003081; - PNX833X_MIU_SEL1_TIMING = 0x50003081; - - /* Setup GPIO 00 for use as MIU CS1 (CS0 is not multiplexed, so does not need this) */ - pnx833x_gpio_select_function_alt(0); - - /* Setup GPIO 04 to input NAND read/busy signal */ - pnx833x_gpio_select_function_io(4); - pnx833x_gpio_select_input(4); - - /* Setup GPIO 05 to disable NAND write protect */ - pnx833x_gpio_select_function_io(5); - pnx833x_gpio_select_output(5); - pnx833x_gpio_write(1, 5); - -#elif defined(CONFIG_MTD_CFI) || defined(CONFIG_MTD_CFI_MODULE) - - /* Set up MIU for 16-bit NOR access on CS0 and CS1... */ - - /* Setup MIU CS0 & CS1 timing */ - PNX833X_MIU_SEL0 = 1; - PNX833X_MIU_SEL1 = 1; - PNX833X_MIU_SEL0_TIMING = 0x6A08D082; - PNX833X_MIU_SEL1_TIMING = 0x6A08D082; - - /* Setup GPIO 00 for use as MIU CS1 (CS0 is not multiplexed, so does not need this) */ - pnx833x_gpio_select_function_alt(0); -#endif -} diff --git a/arch/mips/pnx833x/common/Makefile b/arch/mips/pnx833x/common/Makefile new file mode 100644 index 0000000..4a16f3b --- /dev/null +++ b/arch/mips/pnx833x/common/Makefile @@ -0,0 +1,3 @@ +obj-y := interrupts.o platform.o prom.o setup.o reset.o + +EXTRA_CFLAGS += -Werror diff --git a/arch/mips/pnx833x/common/interrupts.c b/arch/mips/pnx833x/common/interrupts.c new file mode 100644 index 0000000..941916f --- /dev/null +++ b/arch/mips/pnx833x/common/interrupts.c @@ -0,0 +1,379 @@ +/* + * interrupts.c: Interrupt mappings for PNX833X. + * + * Copyright 2008 NXP Semiconductors + * Chris Steel + * Daniel Laird + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int mips_cpu_timer_irq; + +static const unsigned int irq_prio[PNX833X_PIC_NUM_IRQ] = +{ + 0, /* unused */ + 4, /* PNX833X_PIC_I2C0_INT 1 */ + 4, /* PNX833X_PIC_I2C1_INT 2 */ + 1, /* PNX833X_PIC_UART0_INT 3 */ + 1, /* PNX833X_PIC_UART1_INT 4 */ + 6, /* PNX833X_PIC_TS_IN0_DV_INT 5 */ + 6, /* PNX833X_PIC_TS_IN0_DMA_INT 6 */ + 7, /* PNX833X_PIC_GPIO_INT 7 */ + 4, /* PNX833X_PIC_AUDIO_DEC_INT 8 */ + 5, /* PNX833X_PIC_VIDEO_DEC_INT 9 */ + 4, /* PNX833X_PIC_CONFIG_INT 10 */ + 4, /* PNX833X_PIC_AOI_INT 11 */ + 9, /* PNX833X_PIC_SYNC_INT 12 */ + 9, /* PNX8335_PIC_SATA_INT 13 */ + 4, /* PNX833X_PIC_OSD_INT 14 */ + 9, /* PNX833X_PIC_DISP1_INT 15 */ + 4, /* PNX833X_PIC_DEINTERLACER_INT 16 */ + 9, /* PNX833X_PIC_DISPLAY2_INT 17 */ + 4, /* PNX833X_PIC_VC_INT 18 */ + 4, /* PNX833X_PIC_SC_INT 19 */ + 9, /* PNX833X_PIC_IDE_INT 20 */ + 9, /* PNX833X_PIC_IDE_DMA_INT 21 */ + 6, /* PNX833X_PIC_TS_IN1_DV_INT 22 */ + 6, /* PNX833X_PIC_TS_IN1_DMA_INT 23 */ + 4, /* PNX833X_PIC_SGDX_DMA_INT 24 */ + 4, /* PNX833X_PIC_TS_OUT_INT 25 */ + 4, /* PNX833X_PIC_IR_INT 26 */ + 3, /* PNX833X_PIC_VMSP1_INT 27 */ + 3, /* PNX833X_PIC_VMSP2_INT 28 */ + 4, /* PNX833X_PIC_PIBC_INT 29 */ + 4, /* PNX833X_PIC_TS_IN0_TRD_INT 30 */ + 4, /* PNX833X_PIC_SGDX_TPD_INT 31 */ + 5, /* PNX833X_PIC_USB_INT 32 */ + 4, /* PNX833X_PIC_TS_IN1_TRD_INT 33 */ + 4, /* PNX833X_PIC_CLOCK_INT 34 */ + 4, /* PNX833X_PIC_SGDX_PARSER_INT 35 */ + 4, /* PNX833X_PIC_VMSP_DMA_INT 36 */ +#if defined(CONFIG_SOC_PNX8335) + 4, /* PNX8335_PIC_MIU_INT 37 */ + 4, /* PNX8335_PIC_AVCHIP_IRQ_INT 38 */ + 9, /* PNX8335_PIC_SYNC_HD_INT 39 */ + 9, /* PNX8335_PIC_DISP_HD_INT 40 */ + 9, /* PNX8335_PIC_DISP_SCALER_INT 41 */ + 4, /* PNX8335_PIC_OSD_HD1_INT 42 */ + 4, /* PNX8335_PIC_DTL_WRITER_Y_INT 43 */ + 4, /* PNX8335_PIC_DTL_WRITER_C_INT 44 */ + 4, /* PNX8335_PIC_DTL_EMULATOR_Y_IR_INT 45 */ + 4, /* PNX8335_PIC_DTL_EMULATOR_C_IR_INT 46 */ + 4, /* PNX8335_PIC_DENC_TTX_INT 47 */ + 4, /* PNX8335_PIC_MMI_SIF0_INT 48 */ + 4, /* PNX8335_PIC_MMI_SIF1_INT 49 */ + 4, /* PNX8335_PIC_MMI_CDMMU_INT 50 */ + 4, /* PNX8335_PIC_PIBCS_INT 51 */ + 12, /* PNX8335_PIC_ETHERNET_INT 52 */ + 3, /* PNX8335_PIC_VMSP1_0_INT 53 */ + 3, /* PNX8335_PIC_VMSP1_1_INT 54 */ + 4, /* PNX8335_PIC_VMSP1_DMA_INT 55 */ + 4, /* PNX8335_PIC_TDGR_DE_INT 56 */ + 4, /* PNX8335_PIC_IR1_IRQ_INT 57 */ +#endif +}; + +static void pnx833x_timer_dispatch(void) +{ + do_IRQ(mips_cpu_timer_irq); +} + +static void pic_dispatch(void) +{ + unsigned int irq = PNX833X_REGFIELD(PIC_INT_SRC, INT_SRC); + + if ((irq >= 1) && (irq < (PNX833X_PIC_NUM_IRQ))) { + unsigned long priority = PNX833X_PIC_INT_PRIORITY; + PNX833X_PIC_INT_PRIORITY = irq_prio[irq]; + + if (irq == PNX833X_PIC_GPIO_INT) { + unsigned long mask = PNX833X_PIO_INT_STATUS & PNX833X_PIO_INT_ENABLE; + int pin; + while ((pin = ffs(mask & 0xffff))) { + pin -= 1; + do_IRQ(PNX833X_GPIO_IRQ_BASE + pin); + mask &= ~(1 << pin); + } + } else { + do_IRQ(irq + PNX833X_PIC_IRQ_BASE); + } + + PNX833X_PIC_INT_PRIORITY = priority; + } else { + printk(KERN_ERR "plat_irq_dispatch: unexpected irq %u\n", irq); + } +} + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned int pending = read_c0_status() & read_c0_cause(); + + if (pending & STATUSF_IP4) + pic_dispatch(); + else if (pending & STATUSF_IP7) + do_IRQ(PNX833X_TIMER_IRQ); + else + spurious_interrupt(); +} + +static inline void pnx833x_hard_enable_pic_irq(unsigned int irq) +{ + /* Currently we do this by setting IRQ priority to 1. + If priority support is being implemented, 1 should be repalced + by a better value. */ + PNX833X_PIC_INT_REG(irq) = irq_prio[irq]; +} + +static inline void pnx833x_hard_disable_pic_irq(unsigned int irq) +{ + /* Disable IRQ by writing setting it's priority to 0 */ + PNX833X_PIC_INT_REG(irq) = 0; +} + +static int irqflags[PNX833X_PIC_NUM_IRQ]; /* initialized by zeroes */ +#define IRQFLAG_STARTED 1 +#define IRQFLAG_DISABLED 2 + +static DEFINE_RAW_SPINLOCK(pnx833x_irq_lock); + +static unsigned int pnx833x_startup_pic_irq(unsigned int irq) +{ + unsigned long flags; + unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; + + raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); + + irqflags[pic_irq] = IRQFLAG_STARTED; /* started, not disabled */ + pnx833x_hard_enable_pic_irq(pic_irq); + + raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); + return 0; +} + +static void pnx833x_shutdown_pic_irq(unsigned int irq) +{ + unsigned long flags; + unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; + + raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); + + irqflags[pic_irq] = 0; /* not started */ + pnx833x_hard_disable_pic_irq(pic_irq); + + raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); +} + +static void pnx833x_enable_pic_irq(unsigned int irq) +{ + unsigned long flags; + unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; + + raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); + + irqflags[pic_irq] &= ~IRQFLAG_DISABLED; + if (irqflags[pic_irq] == IRQFLAG_STARTED) + pnx833x_hard_enable_pic_irq(pic_irq); + + raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); +} + +static void pnx833x_disable_pic_irq(unsigned int irq) +{ + unsigned long flags; + unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE; + + raw_spin_lock_irqsave(&pnx833x_irq_lock, flags); + + irqflags[pic_irq] |= IRQFLAG_DISABLED; + pnx833x_hard_disable_pic_irq(pic_irq); + + raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags); +} + +static void pnx833x_ack_pic_irq(unsigned int irq) +{ +} + +static void pnx833x_end_pic_irq(unsigned int irq) +{ +} + +static DEFINE_RAW_SPINLOCK(pnx833x_gpio_pnx833x_irq_lock); + +static unsigned int pnx833x_startup_gpio_irq(unsigned int irq) +{ + int pin = irq - PNX833X_GPIO_IRQ_BASE; + unsigned long flags; + raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); + pnx833x_gpio_enable_irq(pin); + raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); + return 0; +} + +static void pnx833x_enable_gpio_irq(unsigned int irq) +{ + int pin = irq - PNX833X_GPIO_IRQ_BASE; + unsigned long flags; + raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); + pnx833x_gpio_enable_irq(pin); + raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); +} + +static void pnx833x_disable_gpio_irq(unsigned int irq) +{ + int pin = irq - PNX833X_GPIO_IRQ_BASE; + unsigned long flags; + raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); + pnx833x_gpio_disable_irq(pin); + raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); +} + +static void pnx833x_ack_gpio_irq(unsigned int irq) +{ +} + +static void pnx833x_end_gpio_irq(unsigned int irq) +{ + int pin = irq - PNX833X_GPIO_IRQ_BASE; + unsigned long flags; + raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags); + pnx833x_gpio_clear_irq(pin); + raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags); +} + +static int pnx833x_set_type_gpio_irq(unsigned int irq, unsigned int flow_type) +{ + int pin = irq - PNX833X_GPIO_IRQ_BASE; + int gpio_mode; + + switch (flow_type) { + case IRQ_TYPE_EDGE_RISING: + gpio_mode = GPIO_INT_EDGE_RISING; + break; + case IRQ_TYPE_EDGE_FALLING: + gpio_mode = GPIO_INT_EDGE_FALLING; + break; + case IRQ_TYPE_EDGE_BOTH: + gpio_mode = GPIO_INT_EDGE_BOTH; + break; + case IRQ_TYPE_LEVEL_HIGH: + gpio_mode = GPIO_INT_LEVEL_HIGH; + break; + case IRQ_TYPE_LEVEL_LOW: + gpio_mode = GPIO_INT_LEVEL_LOW; + break; + default: + gpio_mode = GPIO_INT_NONE; + break; + } + + pnx833x_gpio_setup_irq(gpio_mode, pin); + + return 0; +} + +static struct irq_chip pnx833x_pic_irq_type = { + .name = "PNX-PIC", + .startup = pnx833x_startup_pic_irq, + .shutdown = pnx833x_shutdown_pic_irq, + .enable = pnx833x_enable_pic_irq, + .disable = pnx833x_disable_pic_irq, + .ack = pnx833x_ack_pic_irq, + .end = pnx833x_end_pic_irq +}; + +static struct irq_chip pnx833x_gpio_irq_type = { + .name = "PNX-GPIO", + .startup = pnx833x_startup_gpio_irq, + .shutdown = pnx833x_disable_gpio_irq, + .enable = pnx833x_enable_gpio_irq, + .disable = pnx833x_disable_gpio_irq, + .ack = pnx833x_ack_gpio_irq, + .end = pnx833x_end_gpio_irq, + .set_type = pnx833x_set_type_gpio_irq +}; + +void __init arch_init_irq(void) +{ + unsigned int irq; + + /* setup standard internal cpu irqs */ + mips_cpu_irq_init(); + + /* Set IRQ information in irq_desc */ + for (irq = PNX833X_PIC_IRQ_BASE; irq < (PNX833X_PIC_IRQ_BASE + PNX833X_PIC_NUM_IRQ); irq++) { + pnx833x_hard_disable_pic_irq(irq); + set_irq_chip_and_handler(irq, &pnx833x_pic_irq_type, handle_simple_irq); + } + + for (irq = PNX833X_GPIO_IRQ_BASE; irq < (PNX833X_GPIO_IRQ_BASE + PNX833X_GPIO_NUM_IRQ); irq++) + set_irq_chip_and_handler(irq, &pnx833x_gpio_irq_type, handle_simple_irq); + + /* Set PIC priority limiter register to 0 */ + PNX833X_PIC_INT_PRIORITY = 0; + + /* Setup GPIO IRQ dispatching */ + pnx833x_startup_pic_irq(PNX833X_PIC_GPIO_INT); + + /* Enable PIC IRQs (HWIRQ2) */ + if (cpu_has_vint) + set_vi_handler(4, pic_dispatch); + + write_c0_status(read_c0_status() | IE_IRQ2); +} + +unsigned int __cpuinit get_c0_compare_int(void) +{ + if (cpu_has_vint) + set_vi_handler(cp0_compare_irq, pnx833x_timer_dispatch); + + mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; + return mips_cpu_timer_irq; +} + +void __init plat_time_init(void) +{ + /* calculate mips_hpt_frequency based on PNX833X_CLOCK_CPUCP_CTL reg */ + + extern unsigned long mips_hpt_frequency; + unsigned long reg = PNX833X_CLOCK_CPUCP_CTL; + + if (!(PNX833X_BIT(reg, CLOCK_CPUCP_CTL, EXIT_RESET))) { + /* Functional clock is disabled so use crystal frequency */ + mips_hpt_frequency = 25; + } else { +#if defined(CONFIG_SOC_PNX8335) + /* Functional clock is enabled, so get clock multiplier */ + mips_hpt_frequency = 90 + (10 * PNX8335_REGFIELD(CLOCK_PLL_CPU_CTL, FREQ)); +#else + static const unsigned long int freq[4] = {240, 160, 120, 80}; + mips_hpt_frequency = freq[PNX833X_FIELD(reg, CLOCK_CPUCP_CTL, DIV_CLOCK)]; +#endif + } + + printk(KERN_INFO "CPU clock is %ld MHz\n", mips_hpt_frequency); + + mips_hpt_frequency *= 500000; +} diff --git a/arch/mips/pnx833x/common/platform.c b/arch/mips/pnx833x/common/platform.c new file mode 100644 index 0000000..01f8345 --- /dev/null +++ b/arch/mips/pnx833x/common/platform.c @@ -0,0 +1,319 @@ +/* + * platform.c: platform support for PNX833X. + * + * Copyright 2008 NXP Semiconductors + * Chris Steel + * Daniel Laird + * + * Based on software written by: + * Nikita Youshchenko , based on PNX8550 code. + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_I2C_PNX0105 +/* Until i2c driver available in kernel.*/ +#include +#endif + +#include +#include +#include + +static u64 uart_dmamask = DMA_BIT_MASK(32); + +static struct resource pnx833x_uart_resources[] = { + [0] = { + .start = PNX833X_UART0_PORTS_START, + .end = PNX833X_UART0_PORTS_END, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PNX833X_PIC_UART0_INT, + .end = PNX833X_PIC_UART0_INT, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = PNX833X_UART1_PORTS_START, + .end = PNX833X_UART1_PORTS_END, + .flags = IORESOURCE_MEM, + }, + [3] = { + .start = PNX833X_PIC_UART1_INT, + .end = PNX833X_PIC_UART1_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +struct pnx8xxx_port pnx8xxx_ports[] = { + [0] = { + .port = { + .type = PORT_PNX8XXX, + .iotype = UPIO_MEM, + .membase = (void __iomem *)PNX833X_UART0_PORTS_START, + .mapbase = PNX833X_UART0_PORTS_START, + .irq = PNX833X_PIC_UART0_INT, + .uartclk = 3692300, + .fifosize = 16, + .flags = UPF_BOOT_AUTOCONF, + .line = 0, + }, + }, + [1] = { + .port = { + .type = PORT_PNX8XXX, + .iotype = UPIO_MEM, + .membase = (void __iomem *)PNX833X_UART1_PORTS_START, + .mapbase = PNX833X_UART1_PORTS_START, + .irq = PNX833X_PIC_UART1_INT, + .uartclk = 3692300, + .fifosize = 16, + .flags = UPF_BOOT_AUTOCONF, + .line = 1, + }, + }, +}; + +static struct platform_device pnx833x_uart_device = { + .name = "pnx8xxx-uart", + .id = -1, + .dev = { + .dma_mask = &uart_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = pnx8xxx_ports, + }, + .num_resources = ARRAY_SIZE(pnx833x_uart_resources), + .resource = pnx833x_uart_resources, +}; + +static u64 ehci_dmamask = DMA_BIT_MASK(32); + +static struct resource pnx833x_usb_ehci_resources[] = { + [0] = { + .start = PNX833X_USB_PORTS_START, + .end = PNX833X_USB_PORTS_END, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PNX833X_PIC_USB_INT, + .end = PNX833X_PIC_USB_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device pnx833x_usb_ehci_device = { + .name = "pnx833x-ehci", + .id = -1, + .dev = { + .dma_mask = &ehci_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(pnx833x_usb_ehci_resources), + .resource = pnx833x_usb_ehci_resources, +}; + +#ifdef CONFIG_I2C_PNX0105 +static struct resource pnx833x_i2c0_resources[] = { + { + .start = PNX833X_I2C0_PORTS_START, + .end = PNX833X_I2C0_PORTS_END, + .flags = IORESOURCE_MEM, + }, + { + .start = PNX833X_PIC_I2C0_INT, + .end = PNX833X_PIC_I2C0_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource pnx833x_i2c1_resources[] = { + { + .start = PNX833X_I2C1_PORTS_START, + .end = PNX833X_I2C1_PORTS_END, + .flags = IORESOURCE_MEM, + }, + { + .start = PNX833X_PIC_I2C1_INT, + .end = PNX833X_PIC_I2C1_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct i2c_pnx0105_dev pnx833x_i2c_dev[] = { + { + .base = PNX833X_I2C0_PORTS_START, + .irq = -1, /* should be PNX833X_PIC_I2C0_INT but polling is faster */ + .clock = 6, /* 0 == 400 kHz, 4 == 100 kHz(Maximum HDMI), 6 = 50kHz(Prefered HDCP) */ + .bus_addr = 0, /* no slave support */ + }, + { + .base = PNX833X_I2C1_PORTS_START, + .irq = -1, /* on high freq, polling is faster */ + /*.irq = PNX833X_PIC_I2C1_INT,*/ + .clock = 4, /* 0 == 400 kHz, 4 == 100 kHz. 100 kHz seems a safe default for now */ + .bus_addr = 0, /* no slave support */ + }, +}; + +static struct platform_device pnx833x_i2c0_device = { + .name = "i2c-pnx0105", + .id = 0, + .dev = { + .platform_data = &pnx833x_i2c_dev[0], + }, + .num_resources = ARRAY_SIZE(pnx833x_i2c0_resources), + .resource = pnx833x_i2c0_resources, +}; + +static struct platform_device pnx833x_i2c1_device = { + .name = "i2c-pnx0105", + .id = 1, + .dev = { + .platform_data = &pnx833x_i2c_dev[1], + }, + .num_resources = ARRAY_SIZE(pnx833x_i2c1_resources), + .resource = pnx833x_i2c1_resources, +}; +#endif + +static u64 ethernet_dmamask = DMA_BIT_MASK(32); + +static struct resource pnx833x_ethernet_resources[] = { + [0] = { + .start = PNX8335_IP3902_PORTS_START, + .end = PNX8335_IP3902_PORTS_END, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PNX8335_PIC_ETHERNET_INT, + .end = PNX8335_PIC_ETHERNET_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device pnx833x_ethernet_device = { + .name = "ip3902-eth", + .id = -1, + .dev = { + .dma_mask = ðernet_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(pnx833x_ethernet_resources), + .resource = pnx833x_ethernet_resources, +}; + +static struct resource pnx833x_sata_resources[] = { + [0] = { + .start = PNX8335_SATA_PORTS_START, + .end = PNX8335_SATA_PORTS_END, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PNX8335_PIC_SATA_INT, + .end = PNX8335_PIC_SATA_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device pnx833x_sata_device = { + .name = "pnx833x-sata", + .id = -1, + .num_resources = ARRAY_SIZE(pnx833x_sata_resources), + .resource = pnx833x_sata_resources, +}; + +static const char *part_probes[] = { + "cmdlinepart", + NULL +}; + +static void +pnx833x_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + struct nand_chip *this = mtd->priv; + unsigned long nandaddr = (unsigned long)this->IO_ADDR_W; + + if (cmd == NAND_CMD_NONE) + return; + + if (ctrl & NAND_CLE) + writeb(cmd, (void __iomem *)(nandaddr + PNX8335_NAND_CLE_MASK)); + else + writeb(cmd, (void __iomem *)(nandaddr + PNX8335_NAND_ALE_MASK)); +} + +static struct platform_nand_data pnx833x_flash_nand_data = { + .chip = { + .chip_delay = 25, + .part_probe_types = part_probes, + }, + .ctrl = { + .cmd_ctrl = pnx833x_flash_nand_cmd_ctrl + } +}; + +/* + * Set start to be the correct address (PNX8335_NAND_BASE with no 0xb!!), + * 12 bytes more seems to be the standard that allows for NAND access. + */ +static struct resource pnx833x_flash_nand_resource = { + .start = PNX8335_NAND_BASE, + .end = PNX8335_NAND_BASE + 12, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device pnx833x_flash_nand = { + .name = "gen_nand", + .id = -1, + .num_resources = 1, + .resource = &pnx833x_flash_nand_resource, + .dev = { + .platform_data = &pnx833x_flash_nand_data, + }, +}; + +static struct platform_device *pnx833x_platform_devices[] __initdata = { + &pnx833x_uart_device, + &pnx833x_usb_ehci_device, +#ifdef CONFIG_I2C_PNX0105 + &pnx833x_i2c0_device, + &pnx833x_i2c1_device, +#endif + &pnx833x_ethernet_device, + &pnx833x_sata_device, + &pnx833x_flash_nand, +}; + +static int __init pnx833x_platform_init(void) +{ + int res; + + res = platform_add_devices(pnx833x_platform_devices, + ARRAY_SIZE(pnx833x_platform_devices)); + + return res; +} + +arch_initcall(pnx833x_platform_init); diff --git a/arch/mips/pnx833x/common/prom.c b/arch/mips/pnx833x/common/prom.c new file mode 100644 index 0000000..29969f9 --- /dev/null +++ b/arch/mips/pnx833x/common/prom.c @@ -0,0 +1,64 @@ +/* + * prom.c: + * + * Copyright 2008 NXP Semiconductors + * Chris Steel + * Daniel Laird + * + * Based on software written by: + * Nikita Youshchenko , based on PNX8550 code. + * + * 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. + */ +#include +#include +#include + +void __init prom_init_cmdline(void) +{ + int argc = fw_arg0; + char **argv = (char **)fw_arg1; + char *c = &(arcs_cmdline[0]); + int i; + + for (i = 1; i < argc; i++) { + strcpy(c, argv[i]); + c += strlen(argv[i]); + if (i < argc-1) + *c++ = ' '; + } + *c = 0; +} + +char __init *prom_getenv(char *envname) +{ + extern char **prom_envp; + char **env = prom_envp; + int i; + + i = strlen(envname); + + while (*env) { + if (strncmp(envname, *env, i) == 0 && *(*env+i) == '=') + return *env + i + 1; + env++; + } + + return 0; +} + +void __init prom_free_prom_memory(void) +{ +} diff --git a/arch/mips/pnx833x/common/reset.c b/arch/mips/pnx833x/common/reset.c new file mode 100644 index 0000000..e0ea96d --- /dev/null +++ b/arch/mips/pnx833x/common/reset.c @@ -0,0 +1,44 @@ +/* + * reset.c: reset support for PNX833X. + * + * Copyright 2008 NXP Semiconductors + * Chris Steel + * Daniel Laird + * + * Based on software written by: + * Nikita Youshchenko , based on PNX8550 code. + * + * 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. + */ +#include +#include + +void pnx833x_machine_restart(char *command) +{ + PNX833X_RESET_CONTROL_2 = 0; + PNX833X_RESET_CONTROL = 0; +} + +void pnx833x_machine_halt(void) +{ + while (1) + __asm__ __volatile__ ("wait"); + +} + +void pnx833x_machine_power_off(void) +{ + pnx833x_machine_halt(); +} diff --git a/arch/mips/pnx833x/common/setup.c b/arch/mips/pnx833x/common/setup.c new file mode 100644 index 0000000..e51fbc4 --- /dev/null +++ b/arch/mips/pnx833x/common/setup.c @@ -0,0 +1,64 @@ +/* + * setup.c: Setup PNX833X Soc. + * + * Copyright 2008 NXP Semiconductors + * Chris Steel + * Daniel Laird + * + * Based on software written by: + * Nikita Youshchenko , based on PNX8550 code. + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +extern void pnx833x_board_setup(void); +extern void pnx833x_machine_restart(char *); +extern void pnx833x_machine_halt(void); +extern void pnx833x_machine_power_off(void); + +int __init plat_mem_setup(void) +{ + /* fake pci bus to avoid bounce buffers */ + PCI_DMA_BUS_IS_PHYS = 1; + + /* set mips clock to 320MHz */ +#if defined(CONFIG_SOC_PNX8335) + PNX8335_WRITEFIELD(0x17, CLOCK_PLL_CPU_CTL, FREQ); +#endif + pnx833x_gpio_init(); /* so it will be ready in board_setup() */ + + pnx833x_board_setup(); + + _machine_restart = pnx833x_machine_restart; + _machine_halt = pnx833x_machine_halt; + pm_power_off = pnx833x_machine_power_off; + + /* IO/MEM resources. */ + set_io_port_base(KSEG1); + ioport_resource.start = 0; + ioport_resource.end = ~0; + iomem_resource.start = 0; + iomem_resource.end = ~0; + + return 0; +} diff --git a/arch/mips/pnx833x/stb22x/Makefile b/arch/mips/pnx833x/stb22x/Makefile new file mode 100644 index 0000000..f81c580 --- /dev/null +++ b/arch/mips/pnx833x/stb22x/Makefile @@ -0,0 +1,3 @@ +lib-y := board.o + +EXTRA_CFLAGS += -Werror diff --git a/arch/mips/pnx833x/stb22x/board.c b/arch/mips/pnx833x/stb22x/board.c new file mode 100644 index 0000000..644eb7c --- /dev/null +++ b/arch/mips/pnx833x/stb22x/board.c @@ -0,0 +1,133 @@ +/* + * board.c: STB225 board support. + * + * Copyright 2008 NXP Semiconductors + * Chris Steel + * Daniel Laird + * + * Based on software written by: + * Nikita Youshchenko , based on PNX8550 code. + * + * 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. + */ +#include +#include +#include +#include +#include + +/* endianess twiddlers */ +#define PNX8335_DEBUG0 0x4400 +#define PNX8335_DEBUG1 0x4404 +#define PNX8335_DEBUG2 0x4408 +#define PNX8335_DEBUG3 0x440c +#define PNX8335_DEBUG4 0x4410 +#define PNX8335_DEBUG5 0x4414 +#define PNX8335_DEBUG6 0x4418 +#define PNX8335_DEBUG7 0x441c + +int prom_argc; +char **prom_argv, **prom_envp; + +extern void prom_init_cmdline(void); +extern char *prom_getenv(char *envname); + +const char *get_system_type(void) +{ + return "NXP STB22x"; +} + +static inline unsigned long env_or_default(char *env, unsigned long dfl) +{ + char *str = prom_getenv(env); + return str ? simple_strtol(str, 0, 0) : dfl; +} + +void __init prom_init(void) +{ + unsigned long memsize; + + prom_argc = fw_arg0; + prom_argv = (char **)fw_arg1; + prom_envp = (char **)fw_arg2; + + prom_init_cmdline(); + + memsize = env_or_default("memsize", 0x02000000); + add_memory_region(0, memsize, BOOT_MEM_RAM); +} + +void __init pnx833x_board_setup(void) +{ + pnx833x_gpio_select_function_alt(4); + pnx833x_gpio_select_output(4); + pnx833x_gpio_select_function_alt(5); + pnx833x_gpio_select_input(5); + pnx833x_gpio_select_function_alt(6); + pnx833x_gpio_select_input(6); + pnx833x_gpio_select_function_alt(7); + pnx833x_gpio_select_output(7); + + pnx833x_gpio_select_function_alt(25); + pnx833x_gpio_select_function_alt(26); + + pnx833x_gpio_select_function_alt(27); + pnx833x_gpio_select_function_alt(28); + pnx833x_gpio_select_function_alt(29); + pnx833x_gpio_select_function_alt(30); + pnx833x_gpio_select_function_alt(31); + pnx833x_gpio_select_function_alt(32); + pnx833x_gpio_select_function_alt(33); + +#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE) + /* Setup MIU for NAND access on CS0... + * + * (it seems that we must also configure CS1 for reliable operation, + * otherwise the first read ID command will fail if it's read as 4 bytes + * but pass if it's read as 1 word.) + */ + + /* Setup MIU CS0 & CS1 timing */ + PNX833X_MIU_SEL0 = 0; + PNX833X_MIU_SEL1 = 0; + PNX833X_MIU_SEL0_TIMING = 0x50003081; + PNX833X_MIU_SEL1_TIMING = 0x50003081; + + /* Setup GPIO 00 for use as MIU CS1 (CS0 is not multiplexed, so does not need this) */ + pnx833x_gpio_select_function_alt(0); + + /* Setup GPIO 04 to input NAND read/busy signal */ + pnx833x_gpio_select_function_io(4); + pnx833x_gpio_select_input(4); + + /* Setup GPIO 05 to disable NAND write protect */ + pnx833x_gpio_select_function_io(5); + pnx833x_gpio_select_output(5); + pnx833x_gpio_write(1, 5); + +#elif defined(CONFIG_MTD_CFI) || defined(CONFIG_MTD_CFI_MODULE) + + /* Set up MIU for 16-bit NOR access on CS0 and CS1... */ + + /* Setup MIU CS0 & CS1 timing */ + PNX833X_MIU_SEL0 = 1; + PNX833X_MIU_SEL1 = 1; + PNX833X_MIU_SEL0_TIMING = 0x6A08D082; + PNX833X_MIU_SEL1_TIMING = 0x6A08D082; + + /* Setup GPIO 00 for use as MIU CS1 (CS0 is not multiplexed, so does not need this) */ + pnx833x_gpio_select_function_alt(0); +#endif +} -- cgit v0.10.2 From 79d7cd31f9a3d3e75ae67f742aa5eb199cfa71cf Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:56 +0100 Subject: MIPS: PNX8550: Move code one directory level up. It was sharing the nxp directory but no code with pnx833x and will fit better into the new platform makefile scheme, if moved. Also after the pnx833x code has been moved up, the pnx8550 Code was the last users of the nxp dir. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 0556bc4..ac50de1 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -202,19 +202,19 @@ load-$(CONFIG_NXP_STB225) += 0xffffffff80001000 # # Common NXP PNX8550 # -core-$(CONFIG_SOC_PNX8550) += arch/mips/nxp/pnx8550/common/ +core-$(CONFIG_SOC_PNX8550) += arch/mips/pnx8550/common/ cflags-$(CONFIG_SOC_PNX8550) += -I$(srctree)/arch/mips/include/asm/mach-pnx8550 # # NXP PNX8550 JBS board # -libs-$(CONFIG_PNX8550_JBS) += arch/mips/nxp/pnx8550/jbs/ +libs-$(CONFIG_PNX8550_JBS) += arch/mips/pnx8550/jbs/ #cflags-$(CONFIG_PNX8550_JBS) += -I$(srctree)/arch/mips/include/asm/mach-pnx8550 load-$(CONFIG_PNX8550_JBS) += 0xffffffff80060000 # NXP PNX8550 STB810 board # -libs-$(CONFIG_PNX8550_STB810) += arch/mips/nxp/pnx8550/stb810/ +libs-$(CONFIG_PNX8550_STB810) += arch/mips/pnx8550/stb810/ load-$(CONFIG_PNX8550_STB810) += 0xffffffff80060000 cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic diff --git a/arch/mips/nxp/pnx8550/common/Makefile b/arch/mips/nxp/pnx8550/common/Makefile deleted file mode 100644 index dd9e7b1..0000000 --- a/arch/mips/nxp/pnx8550/common/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -# -# Per Hallsmark, per.hallsmark@mvista.com -# -# ######################################################################## -# -# This program is free software; you can distribute it and/or modify it -# under the terms of the GNU General Public License (Version 2) as -# published by the Free Software Foundation. -# -# This program is distributed in the hope 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. -# -# ####################################################################### -# -# Makefile for the PNX8550 specific kernel interface routines -# under Linux. -# - -obj-y := setup.o prom.o int.o reset.o time.o proc.o platform.o -obj-$(CONFIG_PCI) += pci.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/nxp/pnx8550/common/int.c b/arch/mips/nxp/pnx8550/common/int.c deleted file mode 100644 index cfed505..0000000 --- a/arch/mips/nxp/pnx8550/common/int.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * - * Copyright (C) 2005 Embedded Alley Solutions, Inc - * Ported to 2.6. - * - * Per Hallsmark, per.hallsmark@mvista.com - * Copyright (C) 2000, 2001 MIPS Technologies, Inc. - * Copyright (C) 2001 Ralf Baechle - * - * Cleaned up and bug fixing: Pete Popov, ppopov@embeddedalley.com - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* default prio for interrupts */ -/* first one is a no-no so therefore always prio 0 (disabled) */ -static char gic_prio[PNX8550_INT_GIC_TOTINT] = { - 0, 1, 1, 1, 1, 15, 1, 1, 1, 1, // 0 - 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 10 - 19 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 20 - 29 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 30 - 39 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40 - 49 - 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 50 - 59 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60 - 69 - 1 // 70 -}; - -static void hw0_irqdispatch(int irq) -{ - /* find out which interrupt */ - irq = PNX8550_GIC_VECTOR_0 >> 3; - - if (irq == 0) { - printk("hw0_irqdispatch: irq 0, spurious interrupt?\n"); - return; - } - do_IRQ(PNX8550_INT_GIC_MIN + irq); -} - - -static void timer_irqdispatch(int irq) -{ - irq = (0x01c0 & read_c0_config7()) >> 6; - - if (unlikely(irq == 0)) { - printk("timer_irqdispatch: irq 0, spurious interrupt?\n"); - return; - } - - if (irq & 0x1) - do_IRQ(PNX8550_INT_TIMER1); - if (irq & 0x2) - do_IRQ(PNX8550_INT_TIMER2); - if (irq & 0x4) - do_IRQ(PNX8550_INT_TIMER3); -} - -asmlinkage void plat_irq_dispatch(void) -{ - unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; - - if (pending & STATUSF_IP2) - hw0_irqdispatch(2); - else if (pending & STATUSF_IP7) { - if (read_c0_config7() & 0x01c0) - timer_irqdispatch(7); - } else - spurious_interrupt(); -} - -static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask) -{ - unsigned long status = read_c0_status(); - - status &= ~((clr_mask & 0xFF) << 8); - status |= (set_mask & 0xFF) << 8; - - write_c0_status(status); -} - -static inline void mask_gic_int(unsigned int irq_nr) -{ - /* interrupt disabled, bit 26(WE_ENABLE)=1 and bit 16(enable)=0 */ - PNX8550_GIC_REQ(irq_nr) = 1<<28; /* set priority to 0 */ -} - -static inline void unmask_gic_int(unsigned int irq_nr) -{ - /* set prio mask to lower four bits and enable interrupt */ - PNX8550_GIC_REQ(irq_nr) = (1<<26 | 1<<16) | (1<<28) | gic_prio[irq_nr]; -} - -static inline void mask_irq(unsigned int irq_nr) -{ - if ((PNX8550_INT_CP0_MIN <= irq_nr) && (irq_nr <= PNX8550_INT_CP0_MAX)) { - modify_cp0_intmask(1 << irq_nr, 0); - } else if ((PNX8550_INT_GIC_MIN <= irq_nr) && - (irq_nr <= PNX8550_INT_GIC_MAX)) { - mask_gic_int(irq_nr - PNX8550_INT_GIC_MIN); - } else if ((PNX8550_INT_TIMER_MIN <= irq_nr) && - (irq_nr <= PNX8550_INT_TIMER_MAX)) { - modify_cp0_intmask(1 << 7, 0); - } else { - printk("mask_irq: irq %d doesn't exist!\n", irq_nr); - } -} - -static inline void unmask_irq(unsigned int irq_nr) -{ - if ((PNX8550_INT_CP0_MIN <= irq_nr) && (irq_nr <= PNX8550_INT_CP0_MAX)) { - modify_cp0_intmask(0, 1 << irq_nr); - } else if ((PNX8550_INT_GIC_MIN <= irq_nr) && - (irq_nr <= PNX8550_INT_GIC_MAX)) { - unmask_gic_int(irq_nr - PNX8550_INT_GIC_MIN); - } else if ((PNX8550_INT_TIMER_MIN <= irq_nr) && - (irq_nr <= PNX8550_INT_TIMER_MAX)) { - modify_cp0_intmask(0, 1 << 7); - } else { - printk("mask_irq: irq %d doesn't exist!\n", irq_nr); - } -} - -int pnx8550_set_gic_priority(int irq, int priority) -{ - int gic_irq = irq-PNX8550_INT_GIC_MIN; - int prev_priority = PNX8550_GIC_REQ(gic_irq) & 0xf; - - gic_prio[gic_irq] = priority; - PNX8550_GIC_REQ(gic_irq) |= (0x10000000 | gic_prio[gic_irq]); - - return prev_priority; -} - -static struct irq_chip level_irq_type = { - .name = "PNX Level IRQ", - .ack = mask_irq, - .mask = mask_irq, - .mask_ack = mask_irq, - .unmask = unmask_irq, -}; - -static struct irqaction gic_action = { - .handler = no_action, - .flags = IRQF_DISABLED, - .name = "GIC", -}; - -static struct irqaction timer_action = { - .handler = no_action, - .flags = IRQF_DISABLED | IRQF_TIMER, - .name = "Timer", -}; - -void __init arch_init_irq(void) -{ - int i; - int configPR; - - for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++) { - set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq); - mask_irq(i); /* mask the irq just in case */ - } - - /* init of GIC/IPC interrupts */ - /* should be done before cp0 since cp0 init enables the GIC int */ - for (i = PNX8550_INT_GIC_MIN; i <= PNX8550_INT_GIC_MAX; i++) { - int gic_int_line = i - PNX8550_INT_GIC_MIN; - if (gic_int_line == 0 ) - continue; // don't fiddle with int 0 - /* - * enable change of TARGET, ENABLE and ACTIVE_LOW bits - * set TARGET 0 to route through hw0 interrupt - * set ACTIVE_LOW 0 active high (correct?) - * - * We really should setup an interrupt description table - * to do this nicely. - * Note, PCI INTA is active low on the bus, but inverted - * in the GIC, so to us it's active high. - */ - PNX8550_GIC_REQ(i - PNX8550_INT_GIC_MIN) = 0x1E000000; - - /* mask/priority is still 0 so we will not get any - * interrupts until it is unmasked */ - - set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq); - } - - /* Priority level 0 */ - PNX8550_GIC_PRIMASK_0 = PNX8550_GIC_PRIMASK_1 = 0; - - /* Set int vector table address */ - PNX8550_GIC_VECTOR_0 = PNX8550_GIC_VECTOR_1 = 0; - - set_irq_chip_and_handler(MIPS_CPU_GIC_IRQ, &level_irq_type, - handle_level_irq); - setup_irq(MIPS_CPU_GIC_IRQ, &gic_action); - - /* init of Timer interrupts */ - for (i = PNX8550_INT_TIMER_MIN; i <= PNX8550_INT_TIMER_MAX; i++) - set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq); - - /* Stop Timer 1-3 */ - configPR = read_c0_config7(); - configPR |= 0x00000038; - write_c0_config7(configPR); - - set_irq_chip_and_handler(MIPS_CPU_TIMER_IRQ, &level_irq_type, - handle_level_irq); - setup_irq(MIPS_CPU_TIMER_IRQ, &timer_action); -} - -EXPORT_SYMBOL(pnx8550_set_gic_priority); diff --git a/arch/mips/nxp/pnx8550/common/platform.c b/arch/mips/nxp/pnx8550/common/platform.c deleted file mode 100644 index 5264cc0..0000000 --- a/arch/mips/nxp/pnx8550/common/platform.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Platform device support for NXP PNX8550 SoCs - * - * Copyright 2005, Embedded Alley Solutions, Inc - * - * Based on arch/mips/au1000/common/platform.c - * Platform device support for Au1x00 SoCs. - * - * Copyright 2004, Matt Porter - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -static struct resource pnx8550_usb_ohci_resources[] = { - [0] = { - .start = PNX8550_USB_OHCI_OP_BASE, - .end = PNX8550_USB_OHCI_OP_BASE + - PNX8550_USB_OHCI_OP_LEN, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = PNX8550_INT_USB, - .end = PNX8550_INT_USB, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource pnx8550_uart_resources[] = { - [0] = { - .start = PNX8550_UART_PORT0, - .end = PNX8550_UART_PORT0 + 0xfff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = PNX8550_UART_INT(0), - .end = PNX8550_UART_INT(0), - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = PNX8550_UART_PORT1, - .end = PNX8550_UART_PORT1 + 0xfff, - .flags = IORESOURCE_MEM, - }, - [3] = { - .start = PNX8550_UART_INT(1), - .end = PNX8550_UART_INT(1), - .flags = IORESOURCE_IRQ, - }, -}; - -struct pnx8xxx_port pnx8xxx_ports[] = { - [0] = { - .port = { - .type = PORT_PNX8XXX, - .iotype = UPIO_MEM, - .membase = (void __iomem *)PNX8550_UART_PORT0, - .mapbase = PNX8550_UART_PORT0, - .irq = PNX8550_UART_INT(0), - .uartclk = 3692300, - .fifosize = 16, - .flags = UPF_BOOT_AUTOCONF, - .line = 0, - }, - }, - [1] = { - .port = { - .type = PORT_PNX8XXX, - .iotype = UPIO_MEM, - .membase = (void __iomem *)PNX8550_UART_PORT1, - .mapbase = PNX8550_UART_PORT1, - .irq = PNX8550_UART_INT(1), - .uartclk = 3692300, - .fifosize = 16, - .flags = UPF_BOOT_AUTOCONF, - .line = 1, - }, - }, -}; - -/* The dmamask must be set for OHCI to work */ -static u64 ohci_dmamask = DMA_BIT_MASK(32); - -static u64 uart_dmamask = DMA_BIT_MASK(32); - -static struct platform_device pnx8550_usb_ohci_device = { - .name = "pnx8550-ohci", - .id = -1, - .dev = { - .dma_mask = &ohci_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, - .num_resources = ARRAY_SIZE(pnx8550_usb_ohci_resources), - .resource = pnx8550_usb_ohci_resources, -}; - -static struct platform_device pnx8550_uart_device = { - .name = "pnx8xxx-uart", - .id = -1, - .dev = { - .dma_mask = &uart_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = pnx8xxx_ports, - }, - .num_resources = ARRAY_SIZE(pnx8550_uart_resources), - .resource = pnx8550_uart_resources, -}; - -static struct platform_device *pnx8550_platform_devices[] __initdata = { - &pnx8550_usb_ohci_device, - &pnx8550_uart_device, -}; - -static int __init pnx8550_platform_init(void) -{ - return platform_add_devices(pnx8550_platform_devices, - ARRAY_SIZE(pnx8550_platform_devices)); -} - -arch_initcall(pnx8550_platform_init); diff --git a/arch/mips/nxp/pnx8550/common/proc.c b/arch/mips/nxp/pnx8550/common/proc.c deleted file mode 100644 index 3bba5ec..0000000 --- a/arch/mips/nxp/pnx8550/common/proc.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -static int pnx8550_timers_read(char* page, char** start, off_t offset, int count, int* eof, void* data) -{ - int len = 0; - int configPR = read_c0_config7(); - - if (offset==0) { - len += sprintf(&page[len], "Timer: count, compare, tc, status\n"); - len += sprintf(&page[len], " 1: %11i, %8i, %1i, %s\n", - read_c0_count(), read_c0_compare(), - (configPR>>6)&0x1, ((configPR>>3)&0x1)? "off":"on"); - len += sprintf(&page[len], " 2: %11i, %8i, %1i, %s\n", - read_c0_count2(), read_c0_compare2(), - (configPR>>7)&0x1, ((configPR>>4)&0x1)? "off":"on"); - len += sprintf(&page[len], " 3: %11i, %8i, %1i, %s\n", - read_c0_count3(), read_c0_compare3(), - (configPR>>8)&0x1, ((configPR>>5)&0x1)? "off":"on"); - } - - return len; -} - -static int pnx8550_registers_read(char* page, char** start, off_t offset, int count, int* eof, void* data) -{ - int len = 0; - - if (offset==0) { - len += sprintf(&page[len], "config1: %#10.8x\n", read_c0_config1()); - len += sprintf(&page[len], "config2: %#10.8x\n", read_c0_config2()); - len += sprintf(&page[len], "config3: %#10.8x\n", read_c0_config3()); - len += sprintf(&page[len], "configPR: %#10.8x\n", read_c0_config7()); - len += sprintf(&page[len], "status: %#10.8x\n", read_c0_status()); - len += sprintf(&page[len], "cause: %#10.8x\n", read_c0_cause()); - len += sprintf(&page[len], "count: %#10.8x\n", read_c0_count()); - len += sprintf(&page[len], "count_2: %#10.8x\n", read_c0_count2()); - len += sprintf(&page[len], "count_3: %#10.8x\n", read_c0_count3()); - len += sprintf(&page[len], "compare: %#10.8x\n", read_c0_compare()); - len += sprintf(&page[len], "compare_2: %#10.8x\n", read_c0_compare2()); - len += sprintf(&page[len], "compare_3: %#10.8x\n", read_c0_compare3()); - } - - return len; -} - -static struct proc_dir_entry* pnx8550_dir; -static struct proc_dir_entry* pnx8550_timers; -static struct proc_dir_entry* pnx8550_registers; - -static int pnx8550_proc_init( void ) -{ - - // Create /proc/pnx8550 - pnx8550_dir = proc_mkdir("pnx8550", NULL); - if (!pnx8550_dir) { - printk(KERN_ERR "Can't create pnx8550 proc dir\n"); - return -1; - } - - // Create /proc/pnx8550/timers - pnx8550_timers = create_proc_read_entry( - "timers", - 0, - pnx8550_dir, - pnx8550_timers_read, - NULL); - - if (!pnx8550_timers) - printk(KERN_ERR "Can't create pnx8550 timers proc file\n"); - - // Create /proc/pnx8550/registers - pnx8550_registers = create_proc_read_entry( - "registers", - 0, - pnx8550_dir, - pnx8550_registers_read, - NULL); - - if (!pnx8550_registers) - printk(KERN_ERR "Can't create pnx8550 registers proc file\n"); - - return 0; -} - -__initcall(pnx8550_proc_init); diff --git a/arch/mips/nxp/pnx8550/common/prom.c b/arch/mips/nxp/pnx8550/common/prom.c deleted file mode 100644 index 32f7009..0000000 --- a/arch/mips/nxp/pnx8550/common/prom.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * - * Per Hallsmark, per.hallsmark@mvista.com - * - * Based on jmr3927/common/prom.c - * - * 2004 (c) MontaVista Software, Inc. This file is licensed under the - * terms of the GNU General Public License version 2. This program is - * licensed "as is" without any warranty of any kind, whether express - * or implied. - */ -#include -#include -#include -#include -#include - -#include -#include - -/* #define DEBUG_CMDLINE */ - -extern int prom_argc; -extern char **prom_argv, **prom_envp; - -typedef struct -{ - char *name; -/* char *val; */ -}t_env_var; - - -char * prom_getcmdline(void) -{ - return &(arcs_cmdline[0]); -} - -void __init prom_init_cmdline(void) -{ - int i; - - arcs_cmdline[0] = '\0'; - for (i = 0; i < prom_argc; i++) { - strcat(arcs_cmdline, prom_argv[i]); - strcat(arcs_cmdline, " "); - } -} - -char *prom_getenv(char *envname) -{ - /* - * Return a pointer to the given environment variable. - * Environment variables are stored in the form of "memsize=64". - */ - - t_env_var *env = (t_env_var *)prom_envp; - int i; - - i = strlen(envname); - - while(env->name) { - if(strncmp(envname, env->name, i) == 0) { - return(env->name + strlen(envname) + 1); - } - env++; - } - return(NULL); -} - -inline unsigned char str2hexnum(unsigned char c) -{ - if(c >= '0' && c <= '9') - return c - '0'; - if(c >= 'a' && c <= 'f') - return c - 'a' + 10; - if(c >= 'A' && c <= 'F') - return c - 'A' + 10; - return 0; /* foo */ -} - -inline void str2eaddr(unsigned char *ea, unsigned char *str) -{ - int i; - - for(i = 0; i < 6; i++) { - unsigned char num; - - if((*str == '.') || (*str == ':')) - str++; - num = str2hexnum(*str++) << 4; - num |= (str2hexnum(*str++)); - ea[i] = num; - } -} - -int get_ethernet_addr(char *ethernet_addr) -{ - char *ethaddr_str; - - ethaddr_str = prom_getenv("ethaddr"); - if (!ethaddr_str) { - printk("ethaddr not set in boot prom\n"); - return -1; - } - str2eaddr(ethernet_addr, ethaddr_str); - return 0; -} - -void __init prom_free_prom_memory(void) -{ -} - -extern int pnx8550_console_port; - -/* used by early printk */ -void prom_putchar(char c) -{ - if (pnx8550_console_port != -1) { - /* Wait until FIFO not full */ - while( ((ip3106_fifo(UART_BASE, pnx8550_console_port) & PNX8XXX_UART_FIFO_TXFIFO) >> 16) >= 16) - ; - /* Send one char */ - ip3106_fifo(UART_BASE, pnx8550_console_port) = c; - } -} - -EXPORT_SYMBOL(get_ethernet_addr); -EXPORT_SYMBOL(str2eaddr); diff --git a/arch/mips/nxp/pnx8550/common/reset.c b/arch/mips/nxp/pnx8550/common/reset.c deleted file mode 100644 index fadd8744..0000000 --- a/arch/mips/nxp/pnx8550/common/reset.c +++ /dev/null @@ -1,50 +0,0 @@ -/*. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * ######################################################################## - * - * Reset the PNX8550 board. - * - */ -#include - -#include -#include - -void pnx8550_machine_restart(char *command) -{ - char head[] = "************* Machine restart *************"; - char foot[] = "*******************************************"; - - printk("\n\n"); - printk("%s\n", head); - if (command != NULL) - printk("* %s\n", command); - printk("%s\n", foot); - - PNX8550_RST_CTL = PNX8550_RST_DO_SW_RST; -} - -void pnx8550_machine_halt(void) -{ - printk("*** Machine halt. (Not implemented) ***\n"); -} - -void pnx8550_machine_power_off(void) -{ - printk("*** Machine power off. (Not implemented) ***\n"); -} diff --git a/arch/mips/nxp/pnx8550/common/time.c b/arch/mips/nxp/pnx8550/common/time.c deleted file mode 100644 index 8836c62..0000000 --- a/arch/mips/nxp/pnx8550/common/time.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2001, 2002, 2003 MontaVista Software Inc. - * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net - * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org) - * - * Common time service routines for MIPS machines. See - * Documents/MIPS/README.txt. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -static unsigned long cpj; - -static cycle_t hpt_read(struct clocksource *cs) -{ - return read_c0_count2(); -} - -static struct clocksource pnx_clocksource = { - .name = "pnx8xxx", - .rating = 200, - .read = hpt_read, - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static irqreturn_t pnx8xxx_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *c = dev_id; - - /* clear MATCH, signal the event */ - c->event_handler(c); - - return IRQ_HANDLED; -} - -static struct irqaction pnx8xxx_timer_irq = { - .handler = pnx8xxx_timer_interrupt, - .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER, - .name = "pnx8xxx_timer", -}; - -static irqreturn_t monotonic_interrupt(int irq, void *dev_id) -{ - /* Timer 2 clear interrupt */ - write_c0_compare2(-1); - return IRQ_HANDLED; -} - -static struct irqaction monotonic_irqaction = { - .handler = monotonic_interrupt, - .flags = IRQF_DISABLED | IRQF_TIMER, - .name = "Monotonic timer", -}; - -static int pnx8xxx_set_next_event(unsigned long delta, - struct clock_event_device *evt) -{ - write_c0_compare(delta); - return 0; -} - -static struct clock_event_device pnx8xxx_clockevent = { - .name = "pnx8xxx_clockevent", - .features = CLOCK_EVT_FEAT_ONESHOT, - .set_next_event = pnx8xxx_set_next_event, -}; - -static inline void timer_ack(void) -{ - write_c0_compare(cpj); -} - -__init void plat_time_init(void) -{ - unsigned int configPR; - unsigned int n; - unsigned int m; - unsigned int p; - unsigned int pow2p; - - pnx8xxx_clockevent.cpumask = cpu_none_mask; - clockevents_register_device(&pnx8xxx_clockevent); - clocksource_register(&pnx_clocksource); - - /* Timer 1 start */ - configPR = read_c0_config7(); - configPR &= ~0x00000008; - write_c0_config7(configPR); - - /* Timer 2 start */ - configPR = read_c0_config7(); - configPR &= ~0x00000010; - write_c0_config7(configPR); - - /* Timer 3 stop */ - configPR = read_c0_config7(); - configPR |= 0x00000020; - write_c0_config7(configPR); - - - /* PLL0 sets MIPS clock (PLL1 <=> TM1, PLL6 <=> TM2, PLL5 <=> mem) */ - /* (but only if CLK_MIPS_CTL select value [bits 3:1] is 1: FIXME) */ - - n = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_N_MASK) >> 16; - m = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_M_MASK) >> 8; - p = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_P_MASK) >> 2; - pow2p = (1 << p); - - db_assert(m != 0 && pow2p != 0); - - /* - * Compute the frequency as in the PNX8550 User Manual 1.0, p.186 - * (a.k.a. 8-10). Divide by HZ for a timer offset that results in - * HZ timer interrupts per second. - */ - mips_hpt_frequency = 27UL * ((1000000UL * n)/(m * pow2p)); - cpj = DIV_ROUND_CLOSEST(mips_hpt_frequency, HZ); - write_c0_count(0); - timer_ack(); - - /* Setup Timer 2 */ - write_c0_count2(0); - write_c0_compare2(0xffffffff); - - setup_irq(PNX8550_INT_TIMER1, &pnx8xxx_timer_irq); - setup_irq(PNX8550_INT_TIMER2, &monotonic_irqaction); -} diff --git a/arch/mips/nxp/pnx8550/jbs/Makefile b/arch/mips/nxp/pnx8550/jbs/Makefile deleted file mode 100644 index ad6a8ca..0000000 --- a/arch/mips/nxp/pnx8550/jbs/Makefile +++ /dev/null @@ -1,4 +0,0 @@ - -# Makefile for the NXP JBS Board. - -lib-y := init.o board_setup.o irqmap.o diff --git a/arch/mips/nxp/pnx8550/jbs/board_setup.c b/arch/mips/nxp/pnx8550/jbs/board_setup.c deleted file mode 100644 index 57dd903..0000000 --- a/arch/mips/nxp/pnx8550/jbs/board_setup.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * JBS Specific board startup routines. - * - * Copyright 2005, Embedded Alley Solutions, Inc - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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. - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -/* CP0 hazard avoidance. */ -#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ - "nop; nop; nop; nop; nop; nop;\n\t" \ - ".set reorder\n\t") - -void __init board_setup(void) -{ - unsigned long configpr; - - configpr = read_c0_config7(); - configpr |= (1<<19); /* enable tlb */ - write_c0_config7(configpr); - BARRIER; -} diff --git a/arch/mips/nxp/pnx8550/jbs/init.c b/arch/mips/nxp/pnx8550/jbs/init.c deleted file mode 100644 index d59b4a4..0000000 --- a/arch/mips/nxp/pnx8550/jbs/init.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * Copyright 2005 Embedded Alley Solutions, Inc - * source@embeddedalley.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -int prom_argc; -char **prom_argv, **prom_envp; -extern void __init prom_init_cmdline(void); -extern char *prom_getenv(char *envname); - -const char *get_system_type(void) -{ - return "NXP PNX8550/JBS"; -} - -void __init prom_init(void) -{ - unsigned long memsize; - - //memsize = 0x02800000; /* Trimedia uses memory above */ - memsize = 0x08000000; /* Trimedia uses memory above */ - add_memory_region(0, memsize, BOOT_MEM_RAM); -} diff --git a/arch/mips/nxp/pnx8550/jbs/irqmap.c b/arch/mips/nxp/pnx8550/jbs/irqmap.c deleted file mode 100644 index 7fc89842..0000000 --- a/arch/mips/nxp/pnx8550/jbs/irqmap.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * NXP JBS board irqmap. - * - * Copyright 2005 Embedded Alley Solutions, Inc - * source@embeddealley.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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. - */ - -#include -#include - -char pnx8550_irq_tab[][5] __initdata = { - [8] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, - [9] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, - [17] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, -}; diff --git a/arch/mips/nxp/pnx8550/stb810/Makefile b/arch/mips/nxp/pnx8550/stb810/Makefile deleted file mode 100644 index ab91d72..0000000 --- a/arch/mips/nxp/pnx8550/stb810/Makefile +++ /dev/null @@ -1,4 +0,0 @@ - -# Makefile for the NXP STB810 Board. - -lib-y := prom_init.o board_setup.o irqmap.o diff --git a/arch/mips/nxp/pnx8550/stb810/board_setup.c b/arch/mips/nxp/pnx8550/stb810/board_setup.c deleted file mode 100644 index af2a55e..0000000 --- a/arch/mips/nxp/pnx8550/stb810/board_setup.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * STB810 specific board startup routines. - * - * Based on the arch/mips/nxp/pnx8550/jbs/board_setup.c - * - * Author: MontaVista Software, Inc. - * source@mvista.com - * - * Copyright 2005 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -void __init board_setup(void) -{ - unsigned long configpr; - - configpr = read_c0_config7(); - configpr |= (1<<19); /* enable tlb */ - write_c0_config7(configpr); -} diff --git a/arch/mips/nxp/pnx8550/stb810/irqmap.c b/arch/mips/nxp/pnx8550/stb810/irqmap.c deleted file mode 100644 index 8c03496..0000000 --- a/arch/mips/nxp/pnx8550/stb810/irqmap.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * NXP STB810 board irqmap. - * - * Author: MontaVista Software, Inc. - * source@mvista.com - * - * Copyright 2005 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include - -char pnx8550_irq_tab[][5] __initdata = { - [8] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, - [9] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, - [10] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, -}; diff --git a/arch/mips/nxp/pnx8550/stb810/prom_init.c b/arch/mips/nxp/pnx8550/stb810/prom_init.c deleted file mode 100644 index ca7f4ad..0000000 --- a/arch/mips/nxp/pnx8550/stb810/prom_init.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * STB810 specific prom routines - * - * Author: MontaVista Software, Inc. - * source@mvista.com - * - * Copyright 2005 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -int prom_argc; -char **prom_argv, **prom_envp; -extern void __init prom_init_cmdline(void); -extern char *prom_getenv(char *envname); - -const char *get_system_type(void) -{ - return "NXP PNX8950/STB810"; -} - -void __init prom_init(void) -{ - unsigned long memsize; - - prom_argc = (int) fw_arg0; - prom_argv = (char **) fw_arg1; - prom_envp = (char **) fw_arg2; - - prom_init_cmdline(); - - memsize = 0x08000000; /* Trimedia uses memory above */ - add_memory_region(0, memsize, BOOT_MEM_RAM); -} diff --git a/arch/mips/pnx8550/common/Makefile b/arch/mips/pnx8550/common/Makefile new file mode 100644 index 0000000..dd9e7b1 --- /dev/null +++ b/arch/mips/pnx8550/common/Makefile @@ -0,0 +1,28 @@ +# +# Per Hallsmark, per.hallsmark@mvista.com +# +# ######################################################################## +# +# This program is free software; you can distribute it and/or modify it +# under the terms of the GNU General Public License (Version 2) as +# published by the Free Software Foundation. +# +# This program is distributed in the hope 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. +# +# ####################################################################### +# +# Makefile for the PNX8550 specific kernel interface routines +# under Linux. +# + +obj-y := setup.o prom.o int.o reset.o time.o proc.o platform.o +obj-$(CONFIG_PCI) += pci.o + +EXTRA_CFLAGS += -Werror diff --git a/arch/mips/pnx8550/common/int.c b/arch/mips/pnx8550/common/int.c new file mode 100644 index 0000000..cfed505 --- /dev/null +++ b/arch/mips/pnx8550/common/int.c @@ -0,0 +1,236 @@ +/* + * + * Copyright (C) 2005 Embedded Alley Solutions, Inc + * Ported to 2.6. + * + * Per Hallsmark, per.hallsmark@mvista.com + * Copyright (C) 2000, 2001 MIPS Technologies, Inc. + * Copyright (C) 2001 Ralf Baechle + * + * Cleaned up and bug fixing: Pete Popov, ppopov@embeddedalley.com + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* default prio for interrupts */ +/* first one is a no-no so therefore always prio 0 (disabled) */ +static char gic_prio[PNX8550_INT_GIC_TOTINT] = { + 0, 1, 1, 1, 1, 15, 1, 1, 1, 1, // 0 - 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 10 - 19 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 20 - 29 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 30 - 39 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40 - 49 + 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 50 - 59 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60 - 69 + 1 // 70 +}; + +static void hw0_irqdispatch(int irq) +{ + /* find out which interrupt */ + irq = PNX8550_GIC_VECTOR_0 >> 3; + + if (irq == 0) { + printk("hw0_irqdispatch: irq 0, spurious interrupt?\n"); + return; + } + do_IRQ(PNX8550_INT_GIC_MIN + irq); +} + + +static void timer_irqdispatch(int irq) +{ + irq = (0x01c0 & read_c0_config7()) >> 6; + + if (unlikely(irq == 0)) { + printk("timer_irqdispatch: irq 0, spurious interrupt?\n"); + return; + } + + if (irq & 0x1) + do_IRQ(PNX8550_INT_TIMER1); + if (irq & 0x2) + do_IRQ(PNX8550_INT_TIMER2); + if (irq & 0x4) + do_IRQ(PNX8550_INT_TIMER3); +} + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; + + if (pending & STATUSF_IP2) + hw0_irqdispatch(2); + else if (pending & STATUSF_IP7) { + if (read_c0_config7() & 0x01c0) + timer_irqdispatch(7); + } else + spurious_interrupt(); +} + +static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask) +{ + unsigned long status = read_c0_status(); + + status &= ~((clr_mask & 0xFF) << 8); + status |= (set_mask & 0xFF) << 8; + + write_c0_status(status); +} + +static inline void mask_gic_int(unsigned int irq_nr) +{ + /* interrupt disabled, bit 26(WE_ENABLE)=1 and bit 16(enable)=0 */ + PNX8550_GIC_REQ(irq_nr) = 1<<28; /* set priority to 0 */ +} + +static inline void unmask_gic_int(unsigned int irq_nr) +{ + /* set prio mask to lower four bits and enable interrupt */ + PNX8550_GIC_REQ(irq_nr) = (1<<26 | 1<<16) | (1<<28) | gic_prio[irq_nr]; +} + +static inline void mask_irq(unsigned int irq_nr) +{ + if ((PNX8550_INT_CP0_MIN <= irq_nr) && (irq_nr <= PNX8550_INT_CP0_MAX)) { + modify_cp0_intmask(1 << irq_nr, 0); + } else if ((PNX8550_INT_GIC_MIN <= irq_nr) && + (irq_nr <= PNX8550_INT_GIC_MAX)) { + mask_gic_int(irq_nr - PNX8550_INT_GIC_MIN); + } else if ((PNX8550_INT_TIMER_MIN <= irq_nr) && + (irq_nr <= PNX8550_INT_TIMER_MAX)) { + modify_cp0_intmask(1 << 7, 0); + } else { + printk("mask_irq: irq %d doesn't exist!\n", irq_nr); + } +} + +static inline void unmask_irq(unsigned int irq_nr) +{ + if ((PNX8550_INT_CP0_MIN <= irq_nr) && (irq_nr <= PNX8550_INT_CP0_MAX)) { + modify_cp0_intmask(0, 1 << irq_nr); + } else if ((PNX8550_INT_GIC_MIN <= irq_nr) && + (irq_nr <= PNX8550_INT_GIC_MAX)) { + unmask_gic_int(irq_nr - PNX8550_INT_GIC_MIN); + } else if ((PNX8550_INT_TIMER_MIN <= irq_nr) && + (irq_nr <= PNX8550_INT_TIMER_MAX)) { + modify_cp0_intmask(0, 1 << 7); + } else { + printk("mask_irq: irq %d doesn't exist!\n", irq_nr); + } +} + +int pnx8550_set_gic_priority(int irq, int priority) +{ + int gic_irq = irq-PNX8550_INT_GIC_MIN; + int prev_priority = PNX8550_GIC_REQ(gic_irq) & 0xf; + + gic_prio[gic_irq] = priority; + PNX8550_GIC_REQ(gic_irq) |= (0x10000000 | gic_prio[gic_irq]); + + return prev_priority; +} + +static struct irq_chip level_irq_type = { + .name = "PNX Level IRQ", + .ack = mask_irq, + .mask = mask_irq, + .mask_ack = mask_irq, + .unmask = unmask_irq, +}; + +static struct irqaction gic_action = { + .handler = no_action, + .flags = IRQF_DISABLED, + .name = "GIC", +}; + +static struct irqaction timer_action = { + .handler = no_action, + .flags = IRQF_DISABLED | IRQF_TIMER, + .name = "Timer", +}; + +void __init arch_init_irq(void) +{ + int i; + int configPR; + + for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++) { + set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq); + mask_irq(i); /* mask the irq just in case */ + } + + /* init of GIC/IPC interrupts */ + /* should be done before cp0 since cp0 init enables the GIC int */ + for (i = PNX8550_INT_GIC_MIN; i <= PNX8550_INT_GIC_MAX; i++) { + int gic_int_line = i - PNX8550_INT_GIC_MIN; + if (gic_int_line == 0 ) + continue; // don't fiddle with int 0 + /* + * enable change of TARGET, ENABLE and ACTIVE_LOW bits + * set TARGET 0 to route through hw0 interrupt + * set ACTIVE_LOW 0 active high (correct?) + * + * We really should setup an interrupt description table + * to do this nicely. + * Note, PCI INTA is active low on the bus, but inverted + * in the GIC, so to us it's active high. + */ + PNX8550_GIC_REQ(i - PNX8550_INT_GIC_MIN) = 0x1E000000; + + /* mask/priority is still 0 so we will not get any + * interrupts until it is unmasked */ + + set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq); + } + + /* Priority level 0 */ + PNX8550_GIC_PRIMASK_0 = PNX8550_GIC_PRIMASK_1 = 0; + + /* Set int vector table address */ + PNX8550_GIC_VECTOR_0 = PNX8550_GIC_VECTOR_1 = 0; + + set_irq_chip_and_handler(MIPS_CPU_GIC_IRQ, &level_irq_type, + handle_level_irq); + setup_irq(MIPS_CPU_GIC_IRQ, &gic_action); + + /* init of Timer interrupts */ + for (i = PNX8550_INT_TIMER_MIN; i <= PNX8550_INT_TIMER_MAX; i++) + set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq); + + /* Stop Timer 1-3 */ + configPR = read_c0_config7(); + configPR |= 0x00000038; + write_c0_config7(configPR); + + set_irq_chip_and_handler(MIPS_CPU_TIMER_IRQ, &level_irq_type, + handle_level_irq); + setup_irq(MIPS_CPU_TIMER_IRQ, &timer_action); +} + +EXPORT_SYMBOL(pnx8550_set_gic_priority); diff --git a/arch/mips/pnx8550/common/pci.c b/arch/mips/pnx8550/common/pci.c new file mode 100644 index 0000000..98e86dd --- /dev/null +++ b/arch/mips/pnx8550/common/pci.c @@ -0,0 +1,134 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * + * Author: source@mvista.com + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ +#include +#include +#include +#include + +#include +#include +#include + +static struct resource pci_io_resource = { + .start = PNX8550_PCIIO + 0x1000, /* reserve regacy I/O space */ + .end = PNX8550_PCIIO + PNX8550_PCIIO_SIZE, + .name = "pci IO space", + .flags = IORESOURCE_IO +}; + +static struct resource pci_mem_resource = { + .start = PNX8550_PCIMEM, + .end = PNX8550_PCIMEM + PNX8550_PCIMEM_SIZE - 1, + .name = "pci memory space", + .flags = IORESOURCE_MEM +}; + +extern struct pci_ops pnx8550_pci_ops; + +static struct pci_controller pnx8550_controller = { + .pci_ops = &pnx8550_pci_ops, + .io_map_base = PNX8550_PORT_BASE, + .io_resource = &pci_io_resource, + .mem_resource = &pci_mem_resource, +}; + +/* Return the total size of DRAM-memory, (RANK0 + RANK1) */ +static inline unsigned long get_system_mem_size(void) +{ + /* Read IP2031_RANK0_ADDR_LO */ + unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010); + /* Read IP2031_RANK1_ADDR_HI */ + unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018); + + return dram_r1_hi - dram_r0_lo + 1; +} + +static int __init pnx8550_pci_setup(void) +{ + int pci_mem_code; + int mem_size = get_system_mem_size() >> 20; + + /* Clear the Global 2 Register, PCI Inta Output Enable Registers + Bit 1:Enable DAC Powerdown + -> 0:DACs are enabled and are working normally + 1:DACs are powerdown + Bit 0:Enable of PCI inta output + -> 0 = Disable PCI inta output + 1 = Enable PCI inta output + */ + PNX8550_GLB2_ENAB_INTA_O = 0; + + /* Calc the PCI mem size code */ + if (mem_size >= 128) + pci_mem_code = SIZE_128M; + else if (mem_size >= 64) + pci_mem_code = SIZE_64M; + else if (mem_size >= 32) + pci_mem_code = SIZE_32M; + else + pci_mem_code = SIZE_16M; + + /* Set PCI_XIO registers */ + outl(pci_mem_resource.start, PCI_BASE | PCI_BASE1_LO); + outl(pci_mem_resource.end + 1, PCI_BASE | PCI_BASE1_HI); + outl(pci_io_resource.start, PCI_BASE | PCI_BASE2_LO); + outl(pci_io_resource.end, PCI_BASE | PCI_BASE2_HI); + + /* Send memory transaction via PCI_BASE2 */ + outl(0x00000001, PCI_BASE | PCI_IO); + + /* Unlock the setup register */ + outl(0xca, PCI_BASE | PCI_UNLOCKREG); + + /* + * BAR0 of PNX8550 (pci base 10) must be zero in order for ide + * to work, and in order for bus_to_baddr to work without any + * hacks. + */ + outl(0x00000000, PCI_BASE | PCI_BASE10); + + /* + *These two bars are set by default or the boot code. + * However, it's safer to set them here so we're not boot + * code dependent. + */ + outl(0x1be00000, PCI_BASE | PCI_BASE14); /* PNX MMIO */ + outl(PNX8550_NAND_BASE_ADDR, PCI_BASE | PCI_BASE18); /* XIO */ + + outl(PCI_EN_TA | + PCI_EN_PCI2MMI | + PCI_EN_XIO | + PCI_SETUP_BASE18_SIZE(SIZE_32M) | + PCI_SETUP_BASE18_EN | + PCI_SETUP_BASE14_EN | + PCI_SETUP_BASE10_PREF | + PCI_SETUP_BASE10_SIZE(pci_mem_code) | + PCI_SETUP_CFGMANAGE_EN | + PCI_SETUP_PCIARB_EN, + PCI_BASE | + PCI_SETUP); /* PCI_SETUP */ + outl(0x00000000, PCI_BASE | PCI_CTRL); /* PCI_CONTROL */ + + register_pci_controller(&pnx8550_controller); + + return 0; +} + +arch_initcall(pnx8550_pci_setup); diff --git a/arch/mips/pnx8550/common/platform.c b/arch/mips/pnx8550/common/platform.c new file mode 100644 index 0000000..5264cc0 --- /dev/null +++ b/arch/mips/pnx8550/common/platform.c @@ -0,0 +1,133 @@ +/* + * Platform device support for NXP PNX8550 SoCs + * + * Copyright 2005, Embedded Alley Solutions, Inc + * + * Based on arch/mips/au1000/common/platform.c + * Platform device support for Au1x00 SoCs. + * + * Copyright 2004, Matt Porter + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static struct resource pnx8550_usb_ohci_resources[] = { + [0] = { + .start = PNX8550_USB_OHCI_OP_BASE, + .end = PNX8550_USB_OHCI_OP_BASE + + PNX8550_USB_OHCI_OP_LEN, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PNX8550_INT_USB, + .end = PNX8550_INT_USB, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource pnx8550_uart_resources[] = { + [0] = { + .start = PNX8550_UART_PORT0, + .end = PNX8550_UART_PORT0 + 0xfff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PNX8550_UART_INT(0), + .end = PNX8550_UART_INT(0), + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = PNX8550_UART_PORT1, + .end = PNX8550_UART_PORT1 + 0xfff, + .flags = IORESOURCE_MEM, + }, + [3] = { + .start = PNX8550_UART_INT(1), + .end = PNX8550_UART_INT(1), + .flags = IORESOURCE_IRQ, + }, +}; + +struct pnx8xxx_port pnx8xxx_ports[] = { + [0] = { + .port = { + .type = PORT_PNX8XXX, + .iotype = UPIO_MEM, + .membase = (void __iomem *)PNX8550_UART_PORT0, + .mapbase = PNX8550_UART_PORT0, + .irq = PNX8550_UART_INT(0), + .uartclk = 3692300, + .fifosize = 16, + .flags = UPF_BOOT_AUTOCONF, + .line = 0, + }, + }, + [1] = { + .port = { + .type = PORT_PNX8XXX, + .iotype = UPIO_MEM, + .membase = (void __iomem *)PNX8550_UART_PORT1, + .mapbase = PNX8550_UART_PORT1, + .irq = PNX8550_UART_INT(1), + .uartclk = 3692300, + .fifosize = 16, + .flags = UPF_BOOT_AUTOCONF, + .line = 1, + }, + }, +}; + +/* The dmamask must be set for OHCI to work */ +static u64 ohci_dmamask = DMA_BIT_MASK(32); + +static u64 uart_dmamask = DMA_BIT_MASK(32); + +static struct platform_device pnx8550_usb_ohci_device = { + .name = "pnx8550-ohci", + .id = -1, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(pnx8550_usb_ohci_resources), + .resource = pnx8550_usb_ohci_resources, +}; + +static struct platform_device pnx8550_uart_device = { + .name = "pnx8xxx-uart", + .id = -1, + .dev = { + .dma_mask = &uart_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = pnx8xxx_ports, + }, + .num_resources = ARRAY_SIZE(pnx8550_uart_resources), + .resource = pnx8550_uart_resources, +}; + +static struct platform_device *pnx8550_platform_devices[] __initdata = { + &pnx8550_usb_ohci_device, + &pnx8550_uart_device, +}; + +static int __init pnx8550_platform_init(void) +{ + return platform_add_devices(pnx8550_platform_devices, + ARRAY_SIZE(pnx8550_platform_devices)); +} + +arch_initcall(pnx8550_platform_init); diff --git a/arch/mips/pnx8550/common/proc.c b/arch/mips/pnx8550/common/proc.c new file mode 100644 index 0000000..3bba5ec --- /dev/null +++ b/arch/mips/pnx8550/common/proc.c @@ -0,0 +1,110 @@ +/* + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +static int pnx8550_timers_read(char* page, char** start, off_t offset, int count, int* eof, void* data) +{ + int len = 0; + int configPR = read_c0_config7(); + + if (offset==0) { + len += sprintf(&page[len], "Timer: count, compare, tc, status\n"); + len += sprintf(&page[len], " 1: %11i, %8i, %1i, %s\n", + read_c0_count(), read_c0_compare(), + (configPR>>6)&0x1, ((configPR>>3)&0x1)? "off":"on"); + len += sprintf(&page[len], " 2: %11i, %8i, %1i, %s\n", + read_c0_count2(), read_c0_compare2(), + (configPR>>7)&0x1, ((configPR>>4)&0x1)? "off":"on"); + len += sprintf(&page[len], " 3: %11i, %8i, %1i, %s\n", + read_c0_count3(), read_c0_compare3(), + (configPR>>8)&0x1, ((configPR>>5)&0x1)? "off":"on"); + } + + return len; +} + +static int pnx8550_registers_read(char* page, char** start, off_t offset, int count, int* eof, void* data) +{ + int len = 0; + + if (offset==0) { + len += sprintf(&page[len], "config1: %#10.8x\n", read_c0_config1()); + len += sprintf(&page[len], "config2: %#10.8x\n", read_c0_config2()); + len += sprintf(&page[len], "config3: %#10.8x\n", read_c0_config3()); + len += sprintf(&page[len], "configPR: %#10.8x\n", read_c0_config7()); + len += sprintf(&page[len], "status: %#10.8x\n", read_c0_status()); + len += sprintf(&page[len], "cause: %#10.8x\n", read_c0_cause()); + len += sprintf(&page[len], "count: %#10.8x\n", read_c0_count()); + len += sprintf(&page[len], "count_2: %#10.8x\n", read_c0_count2()); + len += sprintf(&page[len], "count_3: %#10.8x\n", read_c0_count3()); + len += sprintf(&page[len], "compare: %#10.8x\n", read_c0_compare()); + len += sprintf(&page[len], "compare_2: %#10.8x\n", read_c0_compare2()); + len += sprintf(&page[len], "compare_3: %#10.8x\n", read_c0_compare3()); + } + + return len; +} + +static struct proc_dir_entry* pnx8550_dir; +static struct proc_dir_entry* pnx8550_timers; +static struct proc_dir_entry* pnx8550_registers; + +static int pnx8550_proc_init( void ) +{ + + // Create /proc/pnx8550 + pnx8550_dir = proc_mkdir("pnx8550", NULL); + if (!pnx8550_dir) { + printk(KERN_ERR "Can't create pnx8550 proc dir\n"); + return -1; + } + + // Create /proc/pnx8550/timers + pnx8550_timers = create_proc_read_entry( + "timers", + 0, + pnx8550_dir, + pnx8550_timers_read, + NULL); + + if (!pnx8550_timers) + printk(KERN_ERR "Can't create pnx8550 timers proc file\n"); + + // Create /proc/pnx8550/registers + pnx8550_registers = create_proc_read_entry( + "registers", + 0, + pnx8550_dir, + pnx8550_registers_read, + NULL); + + if (!pnx8550_registers) + printk(KERN_ERR "Can't create pnx8550 registers proc file\n"); + + return 0; +} + +__initcall(pnx8550_proc_init); diff --git a/arch/mips/pnx8550/common/prom.c b/arch/mips/pnx8550/common/prom.c new file mode 100644 index 0000000..32f7009 --- /dev/null +++ b/arch/mips/pnx8550/common/prom.c @@ -0,0 +1,128 @@ +/* + * + * Per Hallsmark, per.hallsmark@mvista.com + * + * Based on jmr3927/common/prom.c + * + * 2004 (c) MontaVista Software, Inc. This file is licensed under the + * terms of the GNU General Public License version 2. This program is + * licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#include +#include +#include +#include +#include + +#include +#include + +/* #define DEBUG_CMDLINE */ + +extern int prom_argc; +extern char **prom_argv, **prom_envp; + +typedef struct +{ + char *name; +/* char *val; */ +}t_env_var; + + +char * prom_getcmdline(void) +{ + return &(arcs_cmdline[0]); +} + +void __init prom_init_cmdline(void) +{ + int i; + + arcs_cmdline[0] = '\0'; + for (i = 0; i < prom_argc; i++) { + strcat(arcs_cmdline, prom_argv[i]); + strcat(arcs_cmdline, " "); + } +} + +char *prom_getenv(char *envname) +{ + /* + * Return a pointer to the given environment variable. + * Environment variables are stored in the form of "memsize=64". + */ + + t_env_var *env = (t_env_var *)prom_envp; + int i; + + i = strlen(envname); + + while(env->name) { + if(strncmp(envname, env->name, i) == 0) { + return(env->name + strlen(envname) + 1); + } + env++; + } + return(NULL); +} + +inline unsigned char str2hexnum(unsigned char c) +{ + if(c >= '0' && c <= '9') + return c - '0'; + if(c >= 'a' && c <= 'f') + return c - 'a' + 10; + if(c >= 'A' && c <= 'F') + return c - 'A' + 10; + return 0; /* foo */ +} + +inline void str2eaddr(unsigned char *ea, unsigned char *str) +{ + int i; + + for(i = 0; i < 6; i++) { + unsigned char num; + + if((*str == '.') || (*str == ':')) + str++; + num = str2hexnum(*str++) << 4; + num |= (str2hexnum(*str++)); + ea[i] = num; + } +} + +int get_ethernet_addr(char *ethernet_addr) +{ + char *ethaddr_str; + + ethaddr_str = prom_getenv("ethaddr"); + if (!ethaddr_str) { + printk("ethaddr not set in boot prom\n"); + return -1; + } + str2eaddr(ethernet_addr, ethaddr_str); + return 0; +} + +void __init prom_free_prom_memory(void) +{ +} + +extern int pnx8550_console_port; + +/* used by early printk */ +void prom_putchar(char c) +{ + if (pnx8550_console_port != -1) { + /* Wait until FIFO not full */ + while( ((ip3106_fifo(UART_BASE, pnx8550_console_port) & PNX8XXX_UART_FIFO_TXFIFO) >> 16) >= 16) + ; + /* Send one char */ + ip3106_fifo(UART_BASE, pnx8550_console_port) = c; + } +} + +EXPORT_SYMBOL(get_ethernet_addr); +EXPORT_SYMBOL(str2eaddr); diff --git a/arch/mips/pnx8550/common/reset.c b/arch/mips/pnx8550/common/reset.c new file mode 100644 index 0000000..fadd8744 --- /dev/null +++ b/arch/mips/pnx8550/common/reset.c @@ -0,0 +1,50 @@ +/*. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * ######################################################################## + * + * Reset the PNX8550 board. + * + */ +#include + +#include +#include + +void pnx8550_machine_restart(char *command) +{ + char head[] = "************* Machine restart *************"; + char foot[] = "*******************************************"; + + printk("\n\n"); + printk("%s\n", head); + if (command != NULL) + printk("* %s\n", command); + printk("%s\n", foot); + + PNX8550_RST_CTL = PNX8550_RST_DO_SW_RST; +} + +void pnx8550_machine_halt(void) +{ + printk("*** Machine halt. (Not implemented) ***\n"); +} + +void pnx8550_machine_power_off(void) +{ + printk("*** Machine power off. (Not implemented) ***\n"); +} diff --git a/arch/mips/pnx8550/common/setup.c b/arch/mips/pnx8550/common/setup.c new file mode 100644 index 0000000..64246c9 --- /dev/null +++ b/arch/mips/pnx8550/common/setup.c @@ -0,0 +1,145 @@ +/* + * + * 2.6 port, Embedded Alley Solutions, Inc + * + * Based on Per Hallsmark, per.hallsmark@mvista.com + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +extern void __init board_setup(void); +extern void pnx8550_machine_restart(char *); +extern void pnx8550_machine_halt(void); +extern void pnx8550_machine_power_off(void); +extern struct resource ioport_resource; +extern struct resource iomem_resource; +extern char *prom_getcmdline(void); + +struct resource standard_io_resources[] = { + { + .start = 0x00, + .end = 0x1f, + .name = "dma1", + .flags = IORESOURCE_BUSY + }, { + .start = 0x40, + .end = 0x5f, + .name = "timer", + .flags = IORESOURCE_BUSY + }, { + .start = 0x80, + .end = 0x8f, + .name = "dma page reg", + .flags = IORESOURCE_BUSY + }, { + .start = 0xc0, + .end = 0xdf, + .name = "dma2", + .flags = IORESOURCE_BUSY + }, +}; + +#define STANDARD_IO_RESOURCES ARRAY_SIZE(standard_io_resources) + +extern struct resource pci_io_resource; +extern struct resource pci_mem_resource; + +/* Return the total size of DRAM-memory, (RANK0 + RANK1) */ +unsigned long get_system_mem_size(void) +{ + /* Read IP2031_RANK0_ADDR_LO */ + unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010); + /* Read IP2031_RANK1_ADDR_HI */ + unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018); + + return dram_r1_hi - dram_r0_lo + 1; +} + +int pnx8550_console_port = -1; + +void __init plat_mem_setup(void) +{ + int i; + char* argptr; + + board_setup(); /* board specific setup */ + + _machine_restart = pnx8550_machine_restart; + _machine_halt = pnx8550_machine_halt; + pm_power_off = pnx8550_machine_power_off; + + /* Clear the Global 2 Register, PCI Inta Output Enable Registers + Bit 1:Enable DAC Powerdown + -> 0:DACs are enabled and are working normally + 1:DACs are powerdown + Bit 0:Enable of PCI inta output + -> 0 = Disable PCI inta output + 1 = Enable PCI inta output + */ + PNX8550_GLB2_ENAB_INTA_O = 0; + + /* IO/MEM resources. */ + set_io_port_base(PNX8550_PORT_BASE); + ioport_resource.start = 0; + ioport_resource.end = ~0; + iomem_resource.start = 0; + iomem_resource.end = ~0; + + /* Request I/O space for devices on this board */ + for (i = 0; i < STANDARD_IO_RESOURCES; i++) + request_resource(&ioport_resource, standard_io_resources + i); + + /* Place the Mode Control bit for GPIO pin 16 in primary function */ + /* Pin 16 is used by UART1, UA1_TX */ + outl((PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_16_BIT) | + (PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_17_BIT), + PNX8550_GPIO_MC1); + + argptr = prom_getcmdline(); + if ((argptr = strstr(argptr, "console=ttyS")) != NULL) { + argptr += strlen("console=ttyS"); + pnx8550_console_port = *argptr == '0' ? 0 : 1; + + /* We must initialize the UART (console) before early printk */ + /* Set LCR to 8-bit and BAUD to 38400 (no 5) */ + ip3106_lcr(UART_BASE, pnx8550_console_port) = + PNX8XXX_UART_LCR_8BIT; + ip3106_baud(UART_BASE, pnx8550_console_port) = 5; + } + + return; +} diff --git a/arch/mips/pnx8550/common/time.c b/arch/mips/pnx8550/common/time.c new file mode 100644 index 0000000..8836c62 --- /dev/null +++ b/arch/mips/pnx8550/common/time.c @@ -0,0 +1,151 @@ +/* + * Copyright 2001, 2002, 2003 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org) + * + * Common time service routines for MIPS machines. See + * Documents/MIPS/README.txt. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +static unsigned long cpj; + +static cycle_t hpt_read(struct clocksource *cs) +{ + return read_c0_count2(); +} + +static struct clocksource pnx_clocksource = { + .name = "pnx8xxx", + .rating = 200, + .read = hpt_read, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static irqreturn_t pnx8xxx_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *c = dev_id; + + /* clear MATCH, signal the event */ + c->event_handler(c); + + return IRQ_HANDLED; +} + +static struct irqaction pnx8xxx_timer_irq = { + .handler = pnx8xxx_timer_interrupt, + .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER, + .name = "pnx8xxx_timer", +}; + +static irqreturn_t monotonic_interrupt(int irq, void *dev_id) +{ + /* Timer 2 clear interrupt */ + write_c0_compare2(-1); + return IRQ_HANDLED; +} + +static struct irqaction monotonic_irqaction = { + .handler = monotonic_interrupt, + .flags = IRQF_DISABLED | IRQF_TIMER, + .name = "Monotonic timer", +}; + +static int pnx8xxx_set_next_event(unsigned long delta, + struct clock_event_device *evt) +{ + write_c0_compare(delta); + return 0; +} + +static struct clock_event_device pnx8xxx_clockevent = { + .name = "pnx8xxx_clockevent", + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_next_event = pnx8xxx_set_next_event, +}; + +static inline void timer_ack(void) +{ + write_c0_compare(cpj); +} + +__init void plat_time_init(void) +{ + unsigned int configPR; + unsigned int n; + unsigned int m; + unsigned int p; + unsigned int pow2p; + + pnx8xxx_clockevent.cpumask = cpu_none_mask; + clockevents_register_device(&pnx8xxx_clockevent); + clocksource_register(&pnx_clocksource); + + /* Timer 1 start */ + configPR = read_c0_config7(); + configPR &= ~0x00000008; + write_c0_config7(configPR); + + /* Timer 2 start */ + configPR = read_c0_config7(); + configPR &= ~0x00000010; + write_c0_config7(configPR); + + /* Timer 3 stop */ + configPR = read_c0_config7(); + configPR |= 0x00000020; + write_c0_config7(configPR); + + + /* PLL0 sets MIPS clock (PLL1 <=> TM1, PLL6 <=> TM2, PLL5 <=> mem) */ + /* (but only if CLK_MIPS_CTL select value [bits 3:1] is 1: FIXME) */ + + n = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_N_MASK) >> 16; + m = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_M_MASK) >> 8; + p = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_P_MASK) >> 2; + pow2p = (1 << p); + + db_assert(m != 0 && pow2p != 0); + + /* + * Compute the frequency as in the PNX8550 User Manual 1.0, p.186 + * (a.k.a. 8-10). Divide by HZ for a timer offset that results in + * HZ timer interrupts per second. + */ + mips_hpt_frequency = 27UL * ((1000000UL * n)/(m * pow2p)); + cpj = DIV_ROUND_CLOSEST(mips_hpt_frequency, HZ); + write_c0_count(0); + timer_ack(); + + /* Setup Timer 2 */ + write_c0_count2(0); + write_c0_compare2(0xffffffff); + + setup_irq(PNX8550_INT_TIMER1, &pnx8xxx_timer_irq); + setup_irq(PNX8550_INT_TIMER2, &monotonic_irqaction); +} diff --git a/arch/mips/pnx8550/jbs/Makefile b/arch/mips/pnx8550/jbs/Makefile new file mode 100644 index 0000000..ad6a8ca --- /dev/null +++ b/arch/mips/pnx8550/jbs/Makefile @@ -0,0 +1,4 @@ + +# Makefile for the NXP JBS Board. + +lib-y := init.o board_setup.o irqmap.o diff --git a/arch/mips/pnx8550/jbs/board_setup.c b/arch/mips/pnx8550/jbs/board_setup.c new file mode 100644 index 0000000..57dd903 --- /dev/null +++ b/arch/mips/pnx8550/jbs/board_setup.c @@ -0,0 +1,56 @@ +/* + * JBS Specific board startup routines. + * + * Copyright 2005, Embedded Alley Solutions, Inc + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* CP0 hazard avoidance. */ +#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ + "nop; nop; nop; nop; nop; nop;\n\t" \ + ".set reorder\n\t") + +void __init board_setup(void) +{ + unsigned long configpr; + + configpr = read_c0_config7(); + configpr |= (1<<19); /* enable tlb */ + write_c0_config7(configpr); + BARRIER; +} diff --git a/arch/mips/pnx8550/jbs/init.c b/arch/mips/pnx8550/jbs/init.c new file mode 100644 index 0000000..d59b4a4 --- /dev/null +++ b/arch/mips/pnx8550/jbs/init.c @@ -0,0 +1,53 @@ +/* + * + * Copyright 2005 Embedded Alley Solutions, Inc + * source@embeddedalley.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); + +const char *get_system_type(void) +{ + return "NXP PNX8550/JBS"; +} + +void __init prom_init(void) +{ + unsigned long memsize; + + //memsize = 0x02800000; /* Trimedia uses memory above */ + memsize = 0x08000000; /* Trimedia uses memory above */ + add_memory_region(0, memsize, BOOT_MEM_RAM); +} diff --git a/arch/mips/pnx8550/jbs/irqmap.c b/arch/mips/pnx8550/jbs/irqmap.c new file mode 100644 index 0000000..7fc89842 --- /dev/null +++ b/arch/mips/pnx8550/jbs/irqmap.c @@ -0,0 +1,35 @@ +/* + * NXP JBS board irqmap. + * + * Copyright 2005 Embedded Alley Solutions, Inc + * source@embeddealley.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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. + */ + +#include +#include + +char pnx8550_irq_tab[][5] __initdata = { + [8] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, + [9] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, + [17] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, +}; diff --git a/arch/mips/pnx8550/stb810/Makefile b/arch/mips/pnx8550/stb810/Makefile new file mode 100644 index 0000000..ab91d72 --- /dev/null +++ b/arch/mips/pnx8550/stb810/Makefile @@ -0,0 +1,4 @@ + +# Makefile for the NXP STB810 Board. + +lib-y := prom_init.o board_setup.o irqmap.o diff --git a/arch/mips/pnx8550/stb810/board_setup.c b/arch/mips/pnx8550/stb810/board_setup.c new file mode 100644 index 0000000..af2a55e --- /dev/null +++ b/arch/mips/pnx8550/stb810/board_setup.c @@ -0,0 +1,41 @@ +/* + * STB810 specific board startup routines. + * + * Based on the arch/mips/nxp/pnx8550/jbs/board_setup.c + * + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * Copyright 2005 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +void __init board_setup(void) +{ + unsigned long configpr; + + configpr = read_c0_config7(); + configpr |= (1<<19); /* enable tlb */ + write_c0_config7(configpr); +} diff --git a/arch/mips/pnx8550/stb810/irqmap.c b/arch/mips/pnx8550/stb810/irqmap.c new file mode 100644 index 0000000..8c03496 --- /dev/null +++ b/arch/mips/pnx8550/stb810/irqmap.c @@ -0,0 +1,22 @@ +/* + * NXP STB810 board irqmap. + * + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * Copyright 2005 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include + +char pnx8550_irq_tab[][5] __initdata = { + [8] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, + [9] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, + [10] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff}, +}; diff --git a/arch/mips/pnx8550/stb810/prom_init.c b/arch/mips/pnx8550/stb810/prom_init.c new file mode 100644 index 0000000..ca7f4ad --- /dev/null +++ b/arch/mips/pnx8550/stb810/prom_init.c @@ -0,0 +1,46 @@ +/* + * STB810 specific prom routines + * + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * Copyright 2005 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); + +const char *get_system_type(void) +{ + return "NXP PNX8950/STB810"; +} + +void __init prom_init(void) +{ + unsigned long memsize; + + prom_argc = (int) fw_arg0; + prom_argv = (char **) fw_arg1; + prom_envp = (char **) fw_arg2; + + prom_init_cmdline(); + + memsize = 0x08000000; /* Trimedia uses memory above */ + add_memory_region(0, memsize, BOOT_MEM_RAM); +} -- cgit v0.10.2 From 98e9aee33797c6319425aa729d828e9fe304774c Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:56 +0100 Subject: MIPS: STB22x: Move boards over to obj-y Preparatory cleanup for moving Alchemy over to new MIPS Platform build system support. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Makefile b/arch/mips/Makefile index ac50de1..ae1bbd5 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -194,9 +194,9 @@ include $(srctree)/arch/mips/Kbuild.platforms # NXP STB225 core-$(CONFIG_SOC_PNX833X) += arch/mips/pnx833x/common/ cflags-$(CONFIG_SOC_PNX833X) += -Iarch/mips/include/asm/mach-pnx833x -libs-$(CONFIG_NXP_STB220) += arch/mips/pnx833x/stb22x/ +core-$(CONFIG_NXP_STB220) += arch/mips/pnx833x/stb22x/ load-$(CONFIG_NXP_STB220) += 0xffffffff80001000 -libs-$(CONFIG_NXP_STB225) += arch/mips/pnx833x/stb22x/ +core-$(CONFIG_NXP_STB225) += arch/mips/pnx833x/stb22x/ load-$(CONFIG_NXP_STB225) += 0xffffffff80001000 # diff --git a/arch/mips/pnx833x/stb22x/Makefile b/arch/mips/pnx833x/stb22x/Makefile index f81c580..0c4df9f 100644 --- a/arch/mips/pnx833x/stb22x/Makefile +++ b/arch/mips/pnx833x/stb22x/Makefile @@ -1,3 +1,3 @@ -lib-y := board.o +obj-y := board.o EXTRA_CFLAGS += -Werror -- cgit v0.10.2 From 9453e84d1765d2a532c2ba26ab2a5c3c9b8867c4 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:56 +0100 Subject: MIPS: STB8550: Move boards over to obj-y Preparatory cleanup for moving Alchemy over to new MIPS Platform build system support. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Makefile b/arch/mips/Makefile index ae1bbd5..4ba8070 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -208,13 +208,13 @@ cflags-$(CONFIG_SOC_PNX8550) += -I$(srctree)/arch/mips/include/asm/mach-pnx8550 # # NXP PNX8550 JBS board # -libs-$(CONFIG_PNX8550_JBS) += arch/mips/pnx8550/jbs/ +core-$(CONFIG_PNX8550_JBS) += arch/mips/pnx8550/jbs/ #cflags-$(CONFIG_PNX8550_JBS) += -I$(srctree)/arch/mips/include/asm/mach-pnx8550 load-$(CONFIG_PNX8550_JBS) += 0xffffffff80060000 # NXP PNX8550 STB810 board # -libs-$(CONFIG_PNX8550_STB810) += arch/mips/pnx8550/stb810/ +core-$(CONFIG_PNX8550_STB810) += arch/mips/pnx8550/stb810/ load-$(CONFIG_PNX8550_STB810) += 0xffffffff80060000 cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic diff --git a/arch/mips/pnx8550/jbs/Makefile b/arch/mips/pnx8550/jbs/Makefile index ad6a8ca..c4dc3d5 100644 --- a/arch/mips/pnx8550/jbs/Makefile +++ b/arch/mips/pnx8550/jbs/Makefile @@ -1,4 +1,4 @@ # Makefile for the NXP JBS Board. -lib-y := init.o board_setup.o irqmap.o +obj-y := init.o board_setup.o irqmap.o diff --git a/arch/mips/pnx8550/stb810/Makefile b/arch/mips/pnx8550/stb810/Makefile index ab91d72..cb4ff02 100644 --- a/arch/mips/pnx8550/stb810/Makefile +++ b/arch/mips/pnx8550/stb810/Makefile @@ -1,4 +1,4 @@ # Makefile for the NXP STB810 Board. -lib-y := prom_init.o board_setup.o irqmap.o +obj-y := prom_init.o board_setup.o irqmap.o -- cgit v0.10.2 From 91a548d57e9c95bb47b66d9d3ac0bf381619a6e7 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:56 +0100 Subject: MIPS: PNX833x: Migrate to new platform makefile style. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 8985487..6f007c3 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -14,6 +14,7 @@ platforms += loongson platforms += mipssim platforms += mti-malta platforms += pmc-sierra +platforms += pnx833x platforms += powertv platforms += rb532 platforms += sgi-ip22 diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 4ba8070..17f9331 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -191,14 +191,6 @@ endif # include $(srctree)/arch/mips/Kbuild.platforms -# NXP STB225 -core-$(CONFIG_SOC_PNX833X) += arch/mips/pnx833x/common/ -cflags-$(CONFIG_SOC_PNX833X) += -Iarch/mips/include/asm/mach-pnx833x -core-$(CONFIG_NXP_STB220) += arch/mips/pnx833x/stb22x/ -load-$(CONFIG_NXP_STB220) += 0xffffffff80001000 -core-$(CONFIG_NXP_STB225) += arch/mips/pnx833x/stb22x/ -load-$(CONFIG_NXP_STB225) += 0xffffffff80001000 - # # Common NXP PNX8550 # diff --git a/arch/mips/pnx833x/Makefile b/arch/mips/pnx833x/Makefile new file mode 100644 index 0000000..02c4698 --- /dev/null +++ b/arch/mips/pnx833x/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_SOC_PNX833X) += common/ +obj-$(CONFIG_NXP_STB220) += stb22x/ +obj-$(CONFIG_NXP_STB225) += stb22x/ diff --git a/arch/mips/pnx833x/Platform b/arch/mips/pnx833x/Platform new file mode 100644 index 0000000..7e6ec4d --- /dev/null +++ b/arch/mips/pnx833x/Platform @@ -0,0 +1,5 @@ +# NXP STB225 +platform-$(CONFIG_SOC_PNX833X) += pnx833x/ +cflags-$(CONFIG_SOC_PNX833X) += -Iarch/mips/include/asm/mach-pnx833x +load-$(CONFIG_NXP_STB220) += 0xffffffff80001000 +load-$(CONFIG_NXP_STB225) += 0xffffffff80001000 diff --git a/arch/mips/pnx833x/common/Makefile b/arch/mips/pnx833x/common/Makefile index 4a16f3b..1a46dd2 100644 --- a/arch/mips/pnx833x/common/Makefile +++ b/arch/mips/pnx833x/common/Makefile @@ -1,3 +1 @@ obj-y := interrupts.o platform.o prom.o setup.o reset.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/pnx833x/stb22x/Makefile b/arch/mips/pnx833x/stb22x/Makefile index 0c4df9f..7b58006 100644 --- a/arch/mips/pnx833x/stb22x/Makefile +++ b/arch/mips/pnx833x/stb22x/Makefile @@ -1,3 +1 @@ obj-y := board.o - -EXTRA_CFLAGS += -Werror -- cgit v0.10.2 From ad5f2635578a19ff8885bff1ef4d5adf7193cb02 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:57 +0100 Subject: MIPS: PNX8550: Migrate to new platform makefile style. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 6f007c3..ea3b96c 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -15,6 +15,7 @@ platforms += mipssim platforms += mti-malta platforms += pmc-sierra platforms += pnx833x +platforms += pnx8550 platforms += powertv platforms += rb532 platforms += sgi-ip22 diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 17f9331..50f780a 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -191,24 +191,6 @@ endif # include $(srctree)/arch/mips/Kbuild.platforms -# -# Common NXP PNX8550 -# -core-$(CONFIG_SOC_PNX8550) += arch/mips/pnx8550/common/ -cflags-$(CONFIG_SOC_PNX8550) += -I$(srctree)/arch/mips/include/asm/mach-pnx8550 - -# -# NXP PNX8550 JBS board -# -core-$(CONFIG_PNX8550_JBS) += arch/mips/pnx8550/jbs/ -#cflags-$(CONFIG_PNX8550_JBS) += -I$(srctree)/arch/mips/include/asm/mach-pnx8550 -load-$(CONFIG_PNX8550_JBS) += 0xffffffff80060000 - -# NXP PNX8550 STB810 board -# -core-$(CONFIG_PNX8550_STB810) += arch/mips/pnx8550/stb810/ -load-$(CONFIG_PNX8550_STB810) += 0xffffffff80060000 - cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic drivers-$(CONFIG_PCI) += arch/mips/pci/ diff --git a/arch/mips/pnx8550/Makefile b/arch/mips/pnx8550/Makefile new file mode 100644 index 0000000..3f7e856 --- /dev/null +++ b/arch/mips/pnx8550/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_SOC_PNX8550) += common/ +obj-$(CONFIG_PNX8550_JBS) += jbs/ +obj-$(CONFIG_PNX8550_STB810) += stb810/ diff --git a/arch/mips/pnx8550/Platform b/arch/mips/pnx8550/Platform new file mode 100644 index 0000000..0e7fbde --- /dev/null +++ b/arch/mips/pnx8550/Platform @@ -0,0 +1,7 @@ +platform-$(CONFIG_SOC_PNX8550) += pnx8550/ + +cflags-$(CONFIG_SOC_PNX8550) += \ + -I$(srctree)/arch/mips/include/asm/mach-pnx8550 + +load-$(CONFIG_PNX8550_JBS) += 0xffffffff80060000 +load-$(CONFIG_PNX8550_STB810) += 0xffffffff80060000 diff --git a/arch/mips/pnx8550/common/Makefile b/arch/mips/pnx8550/common/Makefile index dd9e7b1..f8ce695 100644 --- a/arch/mips/pnx8550/common/Makefile +++ b/arch/mips/pnx8550/common/Makefile @@ -24,5 +24,3 @@ obj-y := setup.o prom.o int.o reset.o time.o proc.o platform.o obj-$(CONFIG_PCI) += pci.o - -EXTRA_CFLAGS += -Werror -- cgit v0.10.2 From 961e196c7a3b3c3d1d9eb32629b0e745ce0a68d1 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 30 May 2010 16:27:33 +0200 Subject: MIPS: Refactor arch/mips/boot/Makefile - remove stuff that is not needed VMLINUX assignment, all: rule - use hostprogs-y for the host program - use kbuild rules for the three targets - to beautify output - drop clean-files - it is no longer needed - simplify arch/mips/Makefile when calling targets in boot/Makefile Signed-off-by: Sam Ravnborg To: linux-mips To: Wu Zhangjin Patchwork: https://patchwork.linux-mips.org/patch/1303/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 50f780a..93ce1ce 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -266,7 +266,6 @@ vmlinux.32: vmlinux vmlinux.64: vmlinux $(OBJCOPY) -O $(64bit-bfd) $(OBJCOPYFLAGS) $< $@ -makeboot =$(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) $(1) makezboot =$(Q)$(MAKE) $(build)=arch/mips/boot/compressed \ VMLINUX_LOAD_ADDRESS=$(load-y) 32bit-bfd=$(32bit-bfd) $(1) @@ -284,14 +283,8 @@ vmlinuz.ecoff: vmlinux vmlinuz.srec: vmlinux +@$(call makezboot,$@) -vmlinux.bin: $(vmlinux-32) - +@$(call makeboot,$@) - -vmlinux.ecoff: $(vmlinux-32) - +@$(call makeboot,$@) - -vmlinux.srec: $(vmlinux-32) - +@$(call makeboot,$@) +vmlinux.bin vmlinux.ecoff vmlinux.srec: $(vmlinux-32) FORCE + $(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) arch/mips/boot/$@ CLEAN_FILES += vmlinux.ecoff \ vmlinux.srec diff --git a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile index e39a08e..85bcb5a 100644 --- a/arch/mips/boot/Makefile +++ b/arch/mips/boot/Makefile @@ -11,35 +11,32 @@ # Some DECstations need all possible sections of an ECOFF executable # ifdef CONFIG_MACH_DECSTATION - E2EFLAGS = -a -else - E2EFLAGS = + e2eflag := -a endif # # Drop some uninteresting sections in the kernel. # This is only relevant for ELF kernels but doesn't hurt a.out # -drop-sections = .reginfo .mdebug .comment .note .pdr .options .MIPS.options -strip-flags = $(addprefix --remove-section=,$(drop-sections)) - -VMLINUX = vmlinux - -all: vmlinux.ecoff vmlinux.srec - -vmlinux.ecoff: $(obj)/elf2ecoff $(VMLINUX) - $(obj)/elf2ecoff $(VMLINUX) $(obj)/vmlinux.ecoff $(E2EFLAGS) - -$(obj)/elf2ecoff: $(obj)/elf2ecoff.c - $(HOSTCC) -o $@ $^ - -vmlinux.bin: $(VMLINUX) - $(OBJCOPY) -O binary $(strip-flags) $(VMLINUX) $(obj)/vmlinux.bin - -vmlinux.srec: $(VMLINUX) - $(OBJCOPY) -S -O srec $(strip-flags) $(VMLINUX) $(obj)/vmlinux.srec - -clean-files += elf2ecoff \ - vmlinux.bin \ - vmlinux.ecoff \ - vmlinux.srec +drop-sections := .reginfo .mdebug .comment .note .pdr .options .MIPS.options +strip-flags := $(addprefix --remove-section=,$(drop-sections)) + +hostprogs-y := elf2ecoff + +targets := vmlinux.ecoff +quiet_cmd_ecoff = ECOFF $@ + cmd_ecoff = $(obj)/elf2ecoff $(VMLINUX) $@ $(e2eflag) +$(obj)/vmlinux.ecoff: $(obj)/elf2ecoff $(VMLINUX) FORCE + $(call if_changed,ecoff) + +targets += vmlinux.bin +quiet_cmd_bin = OBJCOPY $@ + cmd_bin = $(OBJCOPY) -O binary $(strip-flags) $(VMLINUX) $@ +$(obj)/vmlinux.bin: $(VMLINUX) FORCE + $(call if_changed,bin) + +targets += vmlinux.srec +quiet_cmd_srec = OBJCOPY $@ + cmd_srec = $(OBJCOPY) -S -O srec $(strip-flags) $(VMLINUX) $@ +$(obj)/vmlinux.srec: $(VMLINUX) FORCE + $(call if_changed,srec) -- cgit v0.10.2 From 35eaa1e9c9b4579100320814aeebff167ee59b0a Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 30 May 2010 16:28:03 +0200 Subject: MIPS: Refactor arch/mips/boot/compressed/Makefile - use hostprogs-y for the elf2ecoff - list all *.o file in targets - renamed obj-y to vmlinuzobjs-y (it was confusing to re-use a kbuild variable) - fix all uses of if_changed/cmd - use kbuild rules to beautify output - update clean-file to clean vmlinuz.* in top-level directory - simplied logic in arch/mips/Makefile for compressed targets The net result is a more kbuild conformant Makefile but readability did not increase. Signed-off-by: Sam Ravnborg To: linux-mips To: Wu Zhangjin Patchwork: https://patchwork.linux-mips.org/patch/1304/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 93ce1ce..3637ba5 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -266,26 +266,18 @@ vmlinux.32: vmlinux vmlinux.64: vmlinux $(OBJCOPY) -O $(64bit-bfd) $(OBJCOPYFLAGS) $< $@ -makezboot =$(Q)$(MAKE) $(build)=arch/mips/boot/compressed \ - VMLINUX_LOAD_ADDRESS=$(load-y) 32bit-bfd=$(32bit-bfd) $(1) - all: $(all-y) -vmlinuz: vmlinux FORCE - +@$(call makezboot,$@) - -vmlinuz.bin: vmlinux - +@$(call makezboot,$@) - -vmlinuz.ecoff: vmlinux - +@$(call makezboot,$@) - -vmlinuz.srec: vmlinux - +@$(call makezboot,$@) - +# boot vmlinux.bin vmlinux.ecoff vmlinux.srec: $(vmlinux-32) FORCE $(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) arch/mips/boot/$@ +# boot/compressed +vmlinuz vmlinuz.bin vmlinuz.ecoff vmlinuz.srec: $(vmlinux-32) FORCE + $(Q)$(MAKE) $(build)=arch/mips/boot/compressed \ + VMLINUX_LOAD_ADDRESS=$(load-y) 32bit-bfd=$(32bit-bfd) $@ + + CLEAN_FILES += vmlinux.ecoff \ vmlinux.srec diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile index 790ddd3..74a52d7 100644 --- a/arch/mips/boot/compressed/Makefile +++ b/arch/mips/boot/compressed/Makefile @@ -33,15 +33,19 @@ KBUILD_AFLAGS := $(LINUXINCLUDE) $(KBUILD_AFLAGS) -D__ASSEMBLY__ \ -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) \ -DKERNEL_ENTRY=0x$(shell $(NM) $(objtree)/$(KBUILD_IMAGE) 2>/dev/null | grep " kernel_entry" | cut -f1 -d \ ) -obj-y := $(obj)/head.o $(obj)/decompress.o $(obj)/dbg.o +targets := head.o decompress.o dbg.o uart-16550.o uart-alchemy.o + +# decompressor objects (linked with vmlinuz) +vmlinuzobjs-y := $(obj)/head.o $(obj)/decompress.o $(obj)/dbg.o ifdef CONFIG_DEBUG_ZBOOT -obj-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART16550) += $(obj)/uart-16550.o -obj-$(CONFIG_MACH_ALCHEMY) += $(obj)/uart-alchemy.o +vmlinuzobjs-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART16550) += $(obj)/uart-16550.o +vmlinuzobjs-$(CONFIG_MACH_ALCHEMY) += $(obj)/uart-alchemy.o endif +targets += vmlinux.bin OBJCOPYFLAGS_vmlinux.bin := $(OBJCOPYFLAGS) -O binary -R .comment -S -$(obj)/vmlinux.bin: $(KBUILD_IMAGE) +$(obj)/vmlinux.bin: $(KBUILD_IMAGE) FORCE $(call if_changed,objcopy) suffix_$(CONFIG_KERNEL_GZIP) = gz @@ -52,30 +56,31 @@ tool_$(CONFIG_KERNEL_GZIP) = gzip tool_$(CONFIG_KERNEL_BZIP2) = bzip2 tool_$(CONFIG_KERNEL_LZMA) = lzma tool_$(CONFIG_KERNEL_LZO) = lzo -$(obj)/vmlinux.$(suffix_y): $(obj)/vmlinux.bin + +targets += vmlinux.gz vmlinux.bz2 vmlinux.lzma vmlinux.lzo +$(obj)/vmlinux.$(suffix_y): $(obj)/vmlinux.bin FORCE $(call if_changed,$(tool_y)) -$(obj)/piggy.o: $(obj)/vmlinux.$(suffix_y) $(obj)/dummy.o - $(Q)$(OBJCOPY) $(OBJCOPYFLAGS) \ - --add-section=.image=$< \ - --set-section-flags=.image=contents,alloc,load,readonly,data \ - $(obj)/dummy.o $@ +targets += piggy.o +OBJCOPYFLAGS_piggy.o := --add-section=.image=$(obj)/vmlinux.$(suffix_y) \ + --set-section-flags=.image=contents,alloc,load,readonly,data +$(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.$(suffix_y) FORCE + $(call if_changed,objcopy) LDFLAGS_vmlinuz := $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T -vmlinuz: $(src)/ld.script $(obj-y) $(obj)/piggy.o - $(call if_changed,ld) +vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/piggy.o + $(call cmd,ld) $(Q)$(OBJCOPY) $(OBJCOPYFLAGS) $@ # # Some DECstations need all possible sections of an ECOFF executable # ifdef CONFIG_MACH_DECSTATION - E2EFLAGS = -a -else - E2EFLAGS = + e2eflag := -a endif # elf2ecoff can only handle 32bit image +hostprogs-y := ../elf2ecoff ifdef CONFIG_32BIT VMLINUZ = vmlinuz @@ -83,23 +88,22 @@ else VMLINUZ = vmlinuz.32 endif +quiet_cmd_32 = OBJCOPY $@ + cmd_32 = $(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@ vmlinuz.32: vmlinuz - $(Q)$(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@ + $(call cmd,32) +quiet_cmd_ecoff = ECOFF $@ + cmd_ecoff = $< $(VMLINUZ) $@ $(e2eflag) vmlinuz.ecoff: $(obj)/../elf2ecoff $(VMLINUZ) - $(Q)$(obj)/../elf2ecoff $(VMLINUZ) vmlinuz.ecoff $(E2EFLAGS) - -$(obj)/../elf2ecoff: $(src)/../elf2ecoff.c - $(Q)$(HOSTCC) -o $@ $^ + $(call cmd,ecoff) OBJCOPYFLAGS_vmlinuz.bin := $(OBJCOPYFLAGS) -O binary vmlinuz.bin: vmlinuz - $(call if_changed,objcopy) + $(call cmd,objcopy) OBJCOPYFLAGS_vmlinuz.srec := $(OBJCOPYFLAGS) -S -O srec vmlinuz.srec: vmlinuz - $(call if_changed,objcopy) + $(call cmd,objcopy) -clean: -clean-files += *.o \ - vmlinu* +clean-files := $(objtree)/vmlinuz.* -- cgit v0.10.2 From d745866e4d8c0675bab90868b5e4a8fcd053eff2 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 30 May 2010 16:28:31 +0200 Subject: MIPS: Clean up arch/mips/Makefile - Drop CLEAN_FILES assignments that is no longer required - Add $(Q) in a few rules Signed-off-by: Sam Ravnborg To: linux-mips To: Wu Zhangjin Patchwork: https://patchwork.linux-mips.org/patch/1305/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 3637ba5..9296cbf 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -278,8 +278,7 @@ vmlinuz vmlinuz.bin vmlinuz.ecoff vmlinuz.srec: $(vmlinux-32) FORCE VMLINUX_LOAD_ADDRESS=$(load-y) 32bit-bfd=$(32bit-bfd) $@ -CLEAN_FILES += vmlinux.ecoff \ - vmlinux.srec +CLEAN_FILES += vmlinux.32 vmlinux.64 archprepare: ifdef CONFIG_MIPS32_N32 @@ -298,9 +297,9 @@ install: $(Q)install -D -m 644 System.map $(INSTALL_PATH)/System.map-$(KERNELRELEASE) archclean: - @$(MAKE) $(clean)=arch/mips/boot - @$(MAKE) $(clean)=arch/mips/boot/compressed - @$(MAKE) $(clean)=arch/mips/lasat + $(Q)$(MAKE) $(clean)=arch/mips/boot + $(Q)$(MAKE) $(clean)=arch/mips/boot/compressed + $(Q)$(MAKE) $(clean)=arch/mips/lasat define archhelp echo ' install - install kernel into $(INSTALL_PATH)' @@ -314,11 +313,3 @@ define archhelp echo echo ' These will be default as apropriate for a configured platform.' endef - -CLEAN_FILES += vmlinux.32 \ - vmlinux.64 \ - vmlinux.ecoff \ - vmlinuz \ - vmlinuz.ecoff \ - vmlinuz.bin \ - vmlinuz.srec -- cgit v0.10.2 From 034260d6779087431a8b2f67589c68b919299e5c Mon Sep 17 00:00:00 2001 From: Kevin Cernekee Date: Thu, 3 Jun 2010 22:11:25 -0700 Subject: printk: fix delayed messages from CPU hotplug events When a secondary CPU is being brought up, it is not uncommon for printk() to be invoked when cpu_online(smp_processor_id()) == 0. The case that I witnessed personally was on MIPS: http://lkml.org/lkml/2010/5/30/4 If (can_use_console() == 0), printk() will spool its output to log_buf and it will be visible in "dmesg", but that output will NOT be echoed to the console until somebody calls release_console_sem() from a CPU that is online. Therefore, the boot time messages from the new CPU can get stuck in "limbo" for a long time, and might suddenly appear on the screen when a completely unrelated event (e.g. "eth0: link is down") occurs. This patch modifies the console code so that any pending messages are automatically flushed out to the console whenever a CPU hotplug operation completes successfully or aborts. The issue was seen on 2.6.34. Original patch by Kevin Cernekee with cleanups by akpm and additional fixes by Santosh Shilimkar. This patch superseeds https://patchwork.linux-mips.org/patch/1357/. Signed-off-by: Kevin Cernekee To: To: To: To: To: Cc: Cc: Reviewed-by: Paul Mundt Signed-off-by: Kevin Cernekee Patchwork: https://patchwork.linux-mips.org/patch/1534/ LKML-Reference: LKML-Reference: Signed-off-by: Ralf Baechle diff --git a/kernel/printk.c b/kernel/printk.c index 444b770..4ab0164 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include @@ -985,6 +987,32 @@ void resume_console(void) } /** + * console_cpu_notify - print deferred console messages after CPU hotplug + * @self: notifier struct + * @action: CPU hotplug event + * @hcpu: unused + * + * If printk() is called from a CPU that is not online yet, the messages + * will be spooled but will not show up on the console. This function is + * called when a new CPU comes online (or fails to come up), and ensures + * that any such output gets printed. + */ +static int __cpuinit console_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + switch (action) { + case CPU_ONLINE: + case CPU_DEAD: + case CPU_DYING: + case CPU_DOWN_FAILED: + case CPU_UP_CANCELED: + acquire_console_sem(); + release_console_sem(); + } + return NOTIFY_OK; +} + +/** * acquire_console_sem - lock the console system for exclusive use. * * Acquires a semaphore which guarantees that the caller has @@ -1371,7 +1399,7 @@ int unregister_console(struct console *console) } EXPORT_SYMBOL(unregister_console); -static int __init disable_boot_consoles(void) +static int __init printk_late_init(void) { struct console *con; @@ -1382,9 +1410,10 @@ static int __init disable_boot_consoles(void) unregister_console(con); } } + hotcpu_notifier(console_cpu_notify, 0); return 0; } -late_initcall(disable_boot_consoles); +late_initcall(printk_late_init); #if defined CONFIG_PRINTK -- cgit v0.10.2 From ea7a8463be6b5dd824bdf42b8f2af1d34f157877 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:59 +0100 Subject: MIPS: Remove unnecessary header file inclusion from fault.c. Signed-off-by: Ralf Baechle diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index b78f7d9..b4aac42 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c @@ -16,7 +16,6 @@ #include #include #include -#include /* For unblank_screen() */ #include #include -- cgit v0.10.2 From 4483b159168d3db41458925512523e44d0d49cd4 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:25:59 +0100 Subject: MIPS: Provide more elevant interface cu2_notifier for CP2 extensions. Signed-off-by: Ralf Baechle Signed-off-by: David Daney Patchwork: https://patchwork.linux-mips.org/patch/1504/ diff --git a/arch/mips/cavium-octeon/cpu.c b/arch/mips/cavium-octeon/cpu.c index b6df538..c664c8c 100644 --- a/arch/mips/cavium-octeon/cpu.c +++ b/arch/mips/cavium-octeon/cpu.c @@ -41,12 +41,8 @@ static int cnmips_cu2_call(struct notifier_block *nfb, unsigned long action, return NOTIFY_OK; /* Let default notifier send signals */ } -static struct notifier_block cnmips_cu2_notifier = { - .notifier_call = cnmips_cu2_call, -}; - static int cnmips_cu2_setup(void) { - return register_cu2_notifier(&cnmips_cu2_notifier); + return cu2_notifier(cnmips_cu2_call, 0); } early_initcall(cnmips_cu2_setup); diff --git a/arch/mips/include/asm/cop2.h b/arch/mips/include/asm/cop2.h index 6b04c98..2cb2f0c 100644 --- a/arch/mips/include/asm/cop2.h +++ b/arch/mips/include/asm/cop2.h @@ -9,6 +9,8 @@ #ifndef __ASM_COP2_H #define __ASM_COP2_H +#include + enum cu2_ops { CU2_EXCEPTION, CU2_LWC2_OP, @@ -20,4 +22,14 @@ enum cu2_ops { extern int register_cu2_notifier(struct notifier_block *nb); extern int cu2_notifier_call_chain(unsigned long val, void *v); +#define cu2_notifier(fn, pri) \ +({ \ + static struct notifier_block fn##_nb __cpuinitdata = { \ + .notifier_call = fn, \ + .priority = pri \ + }; \ + \ + register_cu2_notifier(&fn##_nb); \ +}) + #endif /* __ASM_COP2_H */ diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 8527808..1515b67 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -907,11 +907,6 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action, return NOTIFY_OK; } -static struct notifier_block default_cu2_notifier = { - .notifier_call = default_cu2_call, - .priority = 0x80000000, /* Run last */ -}; - asmlinkage void do_cpu(struct pt_regs *regs) { unsigned int __user *epc; @@ -1734,5 +1729,5 @@ void __init trap_init(void) sort_extable(__start___dbe_table, __stop___dbe_table); - register_cu2_notifier(&default_cu2_notifier); + cu2_notifier(default_cu2_call, 0x80000000); /* Run last */ } -- cgit v0.10.2 From 9b98031e673df81989c0f4f63a99b79fa6630ff5 Mon Sep 17 00:00:00 2001 From: Christoph Egger Date: Wed, 9 Jun 2010 13:20:23 +0200 Subject: MIPS: Alchemy: Remove dead CONFIG_SOC_AU1000_FREQUENCY CONFIG_SOC_AU1000_FREQUENCY doesn't exist in Kconfig, therefore removing all references for it from the source code. Signed-off-by: Christoph Egger To: linux-mips@linux-mips.org To: linux-kernel@vger.kernel.org Cc: vamos@i4.informatik.uni-erlangen.de Patchwork: https://patchwork.linux-mips.org/patch/1367/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/alchemy/common/clocks.c b/arch/mips/alchemy/common/clocks.c index 460c628..af0fe41 100644 --- a/arch/mips/alchemy/common/clocks.c +++ b/arch/mips/alchemy/common/clocks.c @@ -89,11 +89,7 @@ unsigned long au1xxx_calc_clock(void) * over backwards trying to determine the frequency. */ if (au1xxx_cpu_has_pll_wo()) -#ifdef CONFIG_SOC_AU1000_FREQUENCY - cpu_speed = CONFIG_SOC_AU1000_FREQUENCY; -#else cpu_speed = 396000000; -#endif else cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK; -- cgit v0.10.2 From 723b7f812fbcf76abad2c03674b3b3893ccd8516 Mon Sep 17 00:00:00 2001 From: Christoph Egger Date: Wed, 9 Jun 2010 13:20:41 +0200 Subject: MIPS: Cavium: Remove dead CONFIG_GDB_CONSOLE CONFIG_GDB_CONSOLE doesn't exist in Kconfig, therefore removing all references for it from the source code. Signed-off-by: Christoph Egger To: David Daney To: Yang Shi To: Herbert Xu To: Tejun Heo To: linux-mips@linux-mips.org To: linux-kernel@vger.kernel.org Cc: vamos@i4.informatik.uni-erlangen.de Patchwork: https://patchwork.linux-mips.org/patch/1368/ Acked-by: David Daney Signed-off-by: Ralf Baechle diff --git a/arch/mips/cavium-octeon/serial.c b/arch/mips/cavium-octeon/serial.c index 83eac37..638adab 100644 --- a/arch/mips/cavium-octeon/serial.c +++ b/arch/mips/cavium-octeon/serial.c @@ -18,11 +18,7 @@ #include -#ifdef CONFIG_GDB_CONSOLE -#define DEBUG_UART 0 -#else #define DEBUG_UART 1 -#endif unsigned int octeon_serial_in(struct uart_port *up, int offset) { diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index d1b5ffa..8c81a5c 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -578,9 +578,6 @@ void __init prom_init(void) } if (strstr(arcs_cmdline, "console=") == NULL) { -#ifdef CONFIG_GDB_CONSOLE - strcat(arcs_cmdline, " console=gdb"); -#else #ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL strcat(arcs_cmdline, " console=ttyS0,115200"); #else @@ -589,7 +586,6 @@ void __init prom_init(void) else strcat(arcs_cmdline, " console=ttyS0,115200"); #endif -#endif } if (octeon_is_simulation()) { diff --git a/arch/mips/pmc-sierra/yosemite/irq.c b/arch/mips/pmc-sierra/yosemite/irq.c index 51021cf..25bbbf4 100644 --- a/arch/mips/pmc-sierra/yosemite/irq.c +++ b/arch/mips/pmc-sierra/yosemite/irq.c @@ -150,8 +150,4 @@ void __init arch_init_irq(void) mips_cpu_irq_init(); rm7k_cpu_irq_init(); rm9k_cpu_irq_init(); - -#ifdef CONFIG_GDB_CONSOLE - register_gdb_console(); -#endif } -- cgit v0.10.2 From 3f441ee1cc150623aa64ddb1333d57eca78fdac2 Mon Sep 17 00:00:00 2001 From: Christoph Egger Date: Wed, 9 Jun 2010 13:21:30 +0200 Subject: MIPS: Remove dead CONFIG_MTD_PB1550_BOOT, CONFIG_MTD_PB1550_USER CONFIG_MTD_PB1550_BOOT, CONFIG_MTD_PB1550_USER doesn't exist in Kconfig, therefore removing all references for it from the source code. Signed-off-by: Christoph Egger To: Manuel Lauss , To: linux-mips@linux-mips.org To: linux-kernel@vger.kernel.org Cc: vamos@i4.informatik.uni-erlangen.de Patchwork: https://patchwork.linux-mips.org/patch/1370/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-pb1x00/pb1550.h b/arch/mips/include/asm/mach-pb1x00/pb1550.h index 5879641..fc4d766 100644 --- a/arch/mips/include/asm/mach-pb1x00/pb1550.h +++ b/arch/mips/include/asm/mach-pb1x00/pb1550.h @@ -40,14 +40,6 @@ #define SMBUS_PSC_BASE PSC2_BASE_ADDR #define I2S_PSC_BASE PSC3_BASE_ADDR -#if defined(CONFIG_MTD_PB1550_BOOT) && defined(CONFIG_MTD_PB1550_USER) -#define PB1550_BOTH_BANKS -#elif defined(CONFIG_MTD_PB1550_BOOT) && !defined(CONFIG_MTD_PB1550_USER) -#define PB1550_BOOT_ONLY -#elif !defined(CONFIG_MTD_PB1550_BOOT) && defined(CONFIG_MTD_PB1550_USER) -#define PB1550_USER_ONLY -#endif - /* * Timing values as described in databook, * ns value stripped of * lower 2 bits. -- cgit v0.10.2 From 8b284dbc22001a958e64a30a10aa5f274cf6f33d Mon Sep 17 00:00:00 2001 From: Christoph Egger Date: Wed, 9 Jun 2010 13:22:37 +0200 Subject: MIPS: PNX Removing dead CONFIG_PMCTWILED CONFIG_PMCTWILED doesn't exist in Kconfig, therefore removing all references for it from the source code. Signed-off-by: Christoph Egger To: linux-mips@linux-mips.org To: linux-kernel@vger.kernel.org Cc: vamos@i4.informatik.uni-erlangen.de Acked-by: Shane McDonald Patchwork: https://patchwork.linux-mips.org/patch/1373/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c b/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c index 11769b5..c841f08 100644 --- a/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c +++ b/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c @@ -32,9 +32,6 @@ #include #include #include -#ifdef CONFIG_PMCTWILED -#include -#endif /* For hwbutton_interrupt->initial_state */ #define HWBUTTON_HI 0x1 @@ -82,10 +79,6 @@ static void standby_on(void *data) printk(KERN_WARNING "STANDBY switch was set to ON (not implemented)\n"); /* TODO: Put board in standby mode */ -#ifdef CONFIG_PMCTWILED - msp_led_turn_off(MSP_LED_PWRSTANDBY_GREEN); - msp_led_turn_on(MSP_LED_PWRSTANDBY_RED); -#endif } static void standby_off(void *data) @@ -94,10 +87,6 @@ static void standby_off(void *data) "STANDBY switch was set to OFF (not implemented)\n"); /* TODO: Take out of standby mode */ -#ifdef CONFIG_PMCTWILED - msp_led_turn_on(MSP_LED_PWRSTANDBY_GREEN); - msp_led_turn_off(MSP_LED_PWRSTANDBY_RED); -#endif } static struct hwbutton_interrupt softreset_sw = { -- cgit v0.10.2 From bc7cb37788533e43e7c5f6063c928abcd11a6ae1 Mon Sep 17 00:00:00 2001 From: Christoph Egger Date: Wed, 9 Jun 2010 13:23:02 +0200 Subject: MIPS: PowerTV: Removing dead CONFIG_DIAGNOSTICS CONFIG_DIAGNOSTICS doesn't exist in Kconfig, therefore removing all references for it from the source code. Signed-off-by: Christoph Egger To: David VomLehn To: Yoichi Yuasa To: linux-mips@linux-mips.org To: linux-kernel@vger.kernel.org Cc: vamos@i4.informatik.uni-erlangen.de Patchwork: https://patchwork.linux-mips.org/patch/1374/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/powertv/powertv_setup.c b/arch/mips/powertv/powertv_setup.c index af2cae0..3933c37 100644 --- a/arch/mips/powertv/powertv_setup.c +++ b/arch/mips/powertv/powertv_setup.c @@ -199,14 +199,8 @@ static int panic_handler(struct notifier_block *notifier_block, my_regs.cp0_status = read_c0_status(); } -#ifdef CONFIG_DIAGNOSTICS - failure_report((char *) cause_string, - have_die_regs ? &die_regs : &my_regs); - have_die_regs = false; -#else pr_crit("I'm feeling a bit sleepy. hmmmmm... perhaps a nap would... " "zzzz... \n"); -#endif return NOTIFY_DONE; } -- cgit v0.10.2 From e6a033c1cac98be10634e7f82fe0269c8adaf3e5 Mon Sep 17 00:00:00 2001 From: Christoph Egger Date: Wed, 9 Jun 2010 13:23:27 +0200 Subject: MIPS: MSP71xx: Remove dead CONFIG_MTD_PMC_MSP_RAMROOT CONFIG_MTD_PMC_MSP_RAMROOT doesn't exist in Kconfig, therefore removing all references for it from the source code. Signed-off-by: Christoph Egger To: Ralf Baechle , Yoichi Yuasa , linux-mips@linux-mips.org, linux-kernel@vger.kernel.org Cc: vamos@i4.informatik.uni-erlangen.de Acked-by: Shane McDonald Patchwork: https://patchwork.linux-mips.org/patch/1375/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/pmc-sierra/msp71xx/msp_prom.h b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_prom.h index 54ef1a9..786d82d 100644 --- a/arch/mips/include/asm/pmc-sierra/msp71xx/msp_prom.h +++ b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_prom.h @@ -124,10 +124,6 @@ extern void prom_meminit(void); extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem); -#ifdef CONFIG_MTD_PMC_MSP_RAMROOT -extern bool get_ramroot(void **start, unsigned long *size); -#endif - extern int get_ethernet_addr(char *ethaddr_name, char *ethernet_addr); extern unsigned long get_deviceid(void); extern char identify_enet(unsigned long interface_num); -- cgit v0.10.2 From 417a5eb02ce8e5fbaf3d97d8dacc813b0a273ec3 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:26:01 +0100 Subject: MIPS: Update comment for cpu_has_clo_clz Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index ac73ced..ca400f7 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -159,7 +159,8 @@ /* * MIPS32, MIPS64, VR5500, IDT32332, IDT32334 and maybe a few other - * pre-MIPS32/MIPS53 processors have CLO, CLZ. For 64-bit kernels + * pre-MIPS32/MIPS53 processors have CLO, CLZ. The IDT RC64574 is 64-bit and + * has CLO and CLZ but not DCLO nor DCLZ. For 64-bit kernels * cpu_has_clo_clz also indicates the availability of DCLO and DCLZ. */ # ifndef cpu_has_clo_clz -- cgit v0.10.2 From 0d59050496db973d8689f954baf8a202ddd4d51a Mon Sep 17 00:00:00 2001 From: David VomLehn Date: Thu, 1 Jul 2010 13:37:52 -0700 Subject: MIPS: PowerTV: Simplify command line handling and needed config changes Additional changes to Youichi Yuasa's command line simplication code The PowerTV platform uses a non-standard way to get the kernel command line--we insert a built-in command line into arcs_cmdline and to get additional command line information from the bootloader via a pointer in the a1 register. It is necessary to insert a space between to the two strings or the last argument from arcs_cmdline and the first argument from the bootloader may be inadvertantly combined. It is also necessary to set CONFIG_CMDLINE_BOOL to "y" and to set the default command line to an empty string to get the simplified code to work properly in the PowerTV environment. Signed-off-by: David VomLehn To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1438/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/configs/powertv_defconfig b/arch/mips/configs/powertv_defconfig index 7291633..af0ab73 100644 --- a/arch/mips/configs/powertv_defconfig +++ b/arch/mips/configs/powertv_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.31-rc5 -# Fri Aug 28 14:49:33 2009 +# Linux kernel version: 2.6.35-rc3 +# Thu Jul 1 11:03:28 2010 # CONFIG_MIPS=y @@ -11,11 +11,12 @@ CONFIG_MIPS=y # CONFIG_MACH_ALCHEMY is not set # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set +# CONFIG_BCM63XX is not set # CONFIG_MIPS_COBALT is not set # CONFIG_MACH_DECSTATION is not set # CONFIG_MACH_JAZZ is not set # CONFIG_LASAT is not set -# CONFIG_LEMOTE_FULONG is not set +# CONFIG_MACH_LOONGSON is not set # CONFIG_MIPS_MALTA is not set # CONFIG_MIPS_SIM is not set # CONFIG_NEC_MARKEINS is not set @@ -50,7 +51,6 @@ CONFIG_POWERTV=y # CONFIG_MIN_RUNTIME_RESOURCES is not set # CONFIG_BOOTLOADER_DRIVER is not set CONFIG_BOOTLOADER_FAMILY="R2" -CONFIG_CSRC_POWERTV=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set @@ -65,9 +65,9 @@ CONFIG_SCHED_OMIT_FRAME_POINTER=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_CEVT_R4K_LIB=y CONFIG_CEVT_R4K=y +CONFIG_CSRC_POWERTV=y CONFIG_DMA_NONCOHERENT=y -CONFIG_DMA_NEED_PCI_MAP_STATE=y -# CONFIG_EARLY_PRINTK is not set +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_SYS_HAS_EARLY_PRINTK=y # CONFIG_NO_IOPORT is not set CONFIG_CPU_BIG_ENDIAN=y @@ -79,7 +79,8 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5 # # CPU selection # -# CONFIG_CPU_LOONGSON2 is not set +# CONFIG_CPU_LOONGSON2E is not set +# CONFIG_CPU_LOONGSON2F is not set # CONFIG_CPU_MIPS32_R1 is not set CONFIG_CPU_MIPS32_R2=y # CONFIG_CPU_MIPS64_R1 is not set @@ -122,7 +123,7 @@ CONFIG_CPU_HAS_PREFETCH=y CONFIG_MIPS_MT_DISABLED=y # CONFIG_MIPS_MT_SMP is not set # CONFIG_MIPS_MT_SMTC is not set -CONFIG_CPU_HAS_LLSC=y +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set CONFIG_CPU_MIPSR2_IRQ_VI=y CONFIG_CPU_MIPSR2_IRQ_EI=y CONFIG_CPU_HAS_SYNC=y @@ -144,8 +145,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 CONFIG_VIRT_TO_BUS=y -CONFIG_HAVE_MLOCK=y -CONFIG_HAVE_MLOCKED_PAGE_BIT=y +# CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 CONFIG_TICK_ONESHOT=y CONFIG_NO_HZ=y @@ -177,6 +177,7 @@ CONFIG_EXPERIMENTAL=y CONFIG_BROKEN_ON_SMP=y CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="mips-linux-" CONFIG_LOCALVERSION="" CONFIG_LOCALVERSION_AUTO=y # CONFIG_SWAP is not set @@ -190,19 +191,15 @@ CONFIG_SYSVIPC_SYSCTL=y # # RCU Subsystem # -CONFIG_CLASSIC_RCU=y -# CONFIG_TREE_RCU is not set -# CONFIG_PREEMPT_RCU is not set +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_TINY_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set # CONFIG_TREE_RCU_TRACE is not set -# CONFIG_PREEMPT_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=16 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set -# CONFIG_CGROUPS is not set # CONFIG_SYSFS_DEPRECATED_V2 is not set CONFIG_RELAY=y # CONFIG_NAMESPACES is not set @@ -211,6 +208,7 @@ CONFIG_INITRAMFS_SOURCE="" # CONFIG_RD_GZIP is not set # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -234,18 +232,16 @@ CONFIG_SHMEM=y CONFIG_AIO=y # -# Performance Counters +# Kernel Performance Events And Counters # # CONFIG_VM_EVENT_COUNTERS is not set CONFIG_PCI_QUIRKS=y # CONFIG_SLUB_DEBUG is not set -# CONFIG_STRIP_ASM_SYMS is not set CONFIG_COMPAT_BRK=y # CONFIG_SLAB is not set CONFIG_SLUB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set -# CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y # @@ -253,7 +249,7 @@ CONFIG_HAVE_OPROFILE=y # # CONFIG_GCOV_KERNEL is not set # CONFIG_SLOW_WORK is not set -# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_RT_MUTEXES=y CONFIG_BASE_SMALL=0 CONFIG_MODULES=y @@ -271,15 +267,41 @@ CONFIG_LBDAF=y # IO Schedulers # CONFIG_IOSCHED_NOOP=y -# CONFIG_IOSCHED_AS is not set # CONFIG_IOSCHED_DEADLINE is not set # CONFIG_IOSCHED_CFQ is not set -# CONFIG_DEFAULT_AS is not set # CONFIG_DEFAULT_DEADLINE is not set # CONFIG_DEFAULT_CFQ is not set CONFIG_DEFAULT_NOOP=y CONFIG_DEFAULT_IOSCHED="noop" -# CONFIG_PROBE_INITRD_HEADER is not set +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +# CONFIG_INLINE_SPIN_UNLOCK is not set +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +# CONFIG_INLINE_READ_UNLOCK is not set +# CONFIG_INLINE_READ_UNLOCK_BH is not set +# CONFIG_INLINE_READ_UNLOCK_IRQ is not set +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +# CONFIG_INLINE_WRITE_UNLOCK is not set +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set # CONFIG_FREEZER is not set # @@ -289,7 +311,6 @@ CONFIG_HW_HAS_PCI=y CONFIG_PCI=y CONFIG_PCI_DOMAINS=y # CONFIG_ARCH_SUPPORTS_MSI is not set -# CONFIG_PCI_LEGACY is not set # CONFIG_PCI_DEBUG is not set # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set @@ -318,7 +339,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -390,12 +410,26 @@ CONFIG_NETFILTER_ADVANCED=y # CONFIG_NETFILTER_NETLINK_LOG is not set # CONFIG_NF_CONNTRACK is not set CONFIG_NETFILTER_XTABLES=y + +# +# Xtables combined modules +# +# CONFIG_NETFILTER_XT_MARK is not set + +# +# Xtables targets +# # CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set # CONFIG_NETFILTER_XT_TARGET_MARK is not set # CONFIG_NETFILTER_XT_TARGET_NFLOG is not set # CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set # CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +# CONFIG_NETFILTER_XT_TARGET_TEE is not set # CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set + +# +# Xtables matches +# # CONFIG_NETFILTER_XT_MATCH_COMMENT is not set # CONFIG_NETFILTER_XT_MATCH_DCCP is not set # CONFIG_NETFILTER_XT_MATCH_DSCP is not set @@ -465,10 +499,13 @@ CONFIG_IP6_NF_FILTER=y # CONFIG_IP6_NF_RAW is not set # CONFIG_IP_DCCP is not set # CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set # CONFIG_TIPC is not set # CONFIG_ATM is not set +# CONFIG_L2TP is not set CONFIG_STP=y CONFIG_BRIDGE=y +CONFIG_BRIDGE_IGMP_SNOOPING=y # CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set @@ -526,10 +563,21 @@ CONFIG_NET_SCH_FIFO=y # CONFIG_IRDA is not set # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set -# CONFIG_WIRELESS is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# + +# +# Some wireless drivers require a rate control algorithm +# # CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set +# CONFIG_CAIF is not set # # Device Drivers @@ -539,6 +587,7 @@ CONFIG_NET_SCH_FIFO=y # Generic Driver Options # CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y @@ -550,9 +599,9 @@ CONFIG_EXTRA_FIRMWARE="" # CONFIG_CONNECTOR is not set CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_TESTS is not set # CONFIG_MTD_CONCAT is not set CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_TESTS is not set # CONFIG_MTD_REDBOOT_PARTS is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AR7_PARTS is not set @@ -568,6 +617,7 @@ CONFIG_MTD_BLOCK=y # CONFIG_INFTL is not set # CONFIG_RFD_FTL is not set # CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set # CONFIG_MTD_OOPS is not set # @@ -611,11 +661,16 @@ CONFIG_MTD_CFI_I2=y # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set # CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set CONFIG_MTD_NAND=y # CONFIG_MTD_NAND_VERIFY_WRITE is not set -# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_SM_COMMON is not set # CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_DENALI is not set +CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xFF108018 CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_RICOH is not set # CONFIG_MTD_NAND_DISKONCHIP is not set # CONFIG_MTD_NAND_CAFE is not set # CONFIG_MTD_NAND_NANDSIM is not set @@ -641,6 +696,10 @@ CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set + +# +# DRBD disabled because PROC_FS, INET or CONNECTOR not selected +# # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_UB is not set @@ -658,6 +717,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -693,64 +753,95 @@ CONFIG_SCSI_WAIT_SCAN=m # CONFIG_SCSI_OSD_INITIATOR is not set CONFIG_ATA=y # CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y CONFIG_SATA_PMP=y + +# +# Controllers with non-SFF native interface +# # CONFIG_SATA_AHCI is not set +# CONFIG_SATA_AHCI_PLATFORM is not set +# CONFIG_SATA_INIC162X is not set # CONFIG_SATA_SIL24 is not set CONFIG_ATA_SFF=y -# CONFIG_SATA_SVW is not set + +# +# SFF controllers with custom DMA interface +# +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_SX4 is not set +CONFIG_ATA_BMDMA=y + +# +# SATA SFF controllers with BMDMA +# # CONFIG_ATA_PIIX is not set # CONFIG_SATA_MV is not set # CONFIG_SATA_NV is not set -# CONFIG_PDC_ADMA is not set -# CONFIG_SATA_QSTOR is not set # CONFIG_SATA_PROMISE is not set -# CONFIG_SATA_SX4 is not set # CONFIG_SATA_SIL is not set # CONFIG_SATA_SIS is not set +# CONFIG_SATA_SVW is not set # CONFIG_SATA_ULI is not set # CONFIG_SATA_VIA is not set # CONFIG_SATA_VITESSE is not set -# CONFIG_SATA_INIC162X is not set + +# +# PATA SFF controllers with BMDMA +# # CONFIG_PATA_ALI is not set # CONFIG_PATA_AMD is not set # CONFIG_PATA_ARTOP is not set # CONFIG_PATA_ATIIXP is not set -# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_ATP867X is not set # CONFIG_PATA_CMD64X is not set # CONFIG_PATA_CS5520 is not set # CONFIG_PATA_CS5530 is not set # CONFIG_PATA_CYPRESS is not set # CONFIG_PATA_EFAR is not set -# CONFIG_ATA_GENERIC is not set # CONFIG_PATA_HPT366 is not set # CONFIG_PATA_HPT37X is not set # CONFIG_PATA_HPT3X2N is not set # CONFIG_PATA_HPT3X3 is not set -# CONFIG_PATA_IT821X is not set # CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_IT821X is not set # CONFIG_PATA_JMICRON is not set -# CONFIG_PATA_TRIFLEX is not set # CONFIG_PATA_MARVELL is not set -# CONFIG_PATA_MPIIX is not set -# CONFIG_PATA_OLDPIIX is not set # CONFIG_PATA_NETCELL is not set # CONFIG_PATA_NINJA32 is not set -# CONFIG_PATA_NS87410 is not set # CONFIG_PATA_NS87415 is not set -# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OLDPIIX is not set # CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC2027X is not set # CONFIG_PATA_PDC_OLD is not set # CONFIG_PATA_RADISYS is not set -# CONFIG_PATA_RZ1000 is not set +# CONFIG_PATA_RDC is not set # CONFIG_PATA_SC1200 is not set +# CONFIG_PATA_SCH is not set # CONFIG_PATA_SERVERWORKS is not set -# CONFIG_PATA_PDC2027X is not set # CONFIG_PATA_SIL680 is not set # CONFIG_PATA_SIS is not set +# CONFIG_PATA_TOSHIBA is not set +# CONFIG_PATA_TRIFLEX is not set # CONFIG_PATA_VIA is not set # CONFIG_PATA_WINBOND is not set + +# +# PIO-only SFF controllers +# +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_OPTI is not set # CONFIG_PATA_PLATFORM is not set -# CONFIG_PATA_SCH is not set +# CONFIG_PATA_RZ1000 is not set + +# +# Generic fallback / legacy drivers +# +# CONFIG_ATA_GENERIC is not set +# CONFIG_PATA_LEGACY is not set # CONFIG_MD is not set # CONFIG_FUSION is not set @@ -763,7 +854,7 @@ CONFIG_ATA_SFF=y # # -# See the help texts for more information. +# The newer stack is recommended. # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set @@ -787,6 +878,7 @@ CONFIG_MII=y # CONFIG_SMC91X is not set # CONFIG_DM9000 is not set # CONFIG_ETHOC is not set +# CONFIG_SMSC911X is not set # CONFIG_DNET is not set # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set @@ -800,6 +892,7 @@ CONFIG_MII=y # CONFIG_NET_PCI is not set # CONFIG_B44 is not set # CONFIG_KS8842 is not set +# CONFIG_KS8851_MLL is not set # CONFIG_ATL2 is not set CONFIG_NETDEV_1000=y # CONFIG_ACENIC is not set @@ -829,6 +922,8 @@ CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_CHELSIO_T3 is not set +CONFIG_CHELSIO_T4_DEPENDS=y +# CONFIG_CHELSIO_T4 is not set # CONFIG_ENIC is not set # CONFIG_IXGBE is not set # CONFIG_IXGB is not set @@ -841,16 +936,12 @@ CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_MLX4_CORE is not set # CONFIG_TEHUTI is not set # CONFIG_BNX2X is not set +# CONFIG_QLCNIC is not set # CONFIG_QLGE is not set # CONFIG_SFC is not set # CONFIG_BE2NET is not set # CONFIG_TR is not set - -# -# Wireless LAN -# -# CONFIG_WLAN_PRE80211 is not set -# CONFIG_WLAN_80211 is not set +# CONFIG_WLAN is not set # # Enable WiMAX (Networking options) to see the WiMAX drivers @@ -864,6 +955,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_USB_PEGASUS is not set CONFIG_USB_RTL8150=y # CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -873,6 +965,7 @@ CONFIG_USB_RTL8150=y # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_VMXNET3 is not set # CONFIG_ISDN is not set # CONFIG_PHONE is not set @@ -882,6 +975,7 @@ CONFIG_USB_RTL8150=y CONFIG_INPUT=y # CONFIG_INPUT_FF_MEMLESS is not set # CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set # # Userland interfaces @@ -913,6 +1007,7 @@ CONFIG_INPUT_EVDEV=y # CONFIG_VT is not set # CONFIG_DEVKMEM is not set # CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set # CONFIG_NOZOMI is not set # @@ -924,6 +1019,9 @@ CONFIG_INPUT_EVDEV=y # Non-8250 serial port support # # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_LEGACY_PTYS is not set @@ -934,6 +1032,7 @@ CONFIG_UNIX98_PTYS=y # CONFIG_RAW_DRIVER is not set # CONFIG_TCG_TPM is not set CONFIG_DEVPORT=y +# CONFIG_RAMOOPS is not set # CONFIG_I2C is not set # CONFIG_SPI is not set @@ -945,7 +1044,6 @@ CONFIG_DEVPORT=y # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set -# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set CONFIG_SSB_POSSIBLE=y @@ -953,20 +1051,14 @@ CONFIG_SSB_POSSIBLE=y # Sonics Silicon Backplane # # CONFIG_SSB is not set - -# -# Multifunction device drivers -# -# CONFIG_MFD_CORE is not set -# CONFIG_MFD_SM501 is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_SUPPORT is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set # # Graphics support # +# CONFIG_VGA_ARB is not set # CONFIG_DRM is not set # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set @@ -980,7 +1072,6 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_SOUND is not set CONFIG_HID_SUPPORT=y CONFIG_HID=y -# CONFIG_HID_DEBUG is not set # CONFIG_HIDRAW is not set # @@ -993,31 +1084,43 @@ CONFIG_USB_HIDDEV=y # # Special HID drivers # +# CONFIG_HID_3M_PCT is not set # CONFIG_HID_A4TECH is not set # CONFIG_HID_APPLE is not set # CONFIG_HID_BELKIN is not set +# CONFIG_HID_CANDO is not set # CONFIG_HID_CHERRY is not set # CONFIG_HID_CHICONY is not set # CONFIG_HID_CYPRESS is not set # CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EGALAX is not set # CONFIG_HID_EZKEY is not set # CONFIG_HID_KYE is not set # CONFIG_HID_GYRATION is not set +# CONFIG_HID_TWINHAN is not set # CONFIG_HID_KENSINGTON is not set # CONFIG_HID_LOGITECH is not set # CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MOSART is not set # CONFIG_HID_MONTEREY is not set # CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set # CONFIG_HID_PANTHERLORD is not set # CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_QUANTA is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_ROCCAT_KONE is not set # CONFIG_HID_SAMSUNG is not set # CONFIG_HID_SONY is not set +# CONFIG_HID_STANTUM is not set # CONFIG_HID_SUNPLUS is not set # CONFIG_HID_GREENASIA is not set # CONFIG_HID_SMARTJOYPLUS is not set # CONFIG_HID_TOPSEED is not set # CONFIG_HID_THRUSTMASTER is not set # CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y @@ -1032,7 +1135,6 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_DEVICEFS=y # CONFIG_USB_DEVICE_CLASS is not set # CONFIG_USB_DYNAMIC_MINORS is not set -# CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set # CONFIG_USB_MON is not set @@ -1050,6 +1152,7 @@ CONFIG_USB_EHCI_HCD=y # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set @@ -1133,6 +1236,7 @@ CONFIG_USB_SERIAL_CP210X=y # CONFIG_USB_SERIAL_NAVMAN is not set # CONFIG_USB_SERIAL_PL2303 is not set # CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_QCAUX is not set # CONFIG_USB_SERIAL_QUALCOMM is not set # CONFIG_USB_SERIAL_SPCP8X5 is not set # CONFIG_USB_SERIAL_HP4X is not set @@ -1146,6 +1250,8 @@ CONFIG_USB_SERIAL_CP210X=y # CONFIG_USB_SERIAL_OPTION is not set # CONFIG_USB_SERIAL_OMNINET is not set # CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set +# CONFIG_USB_SERIAL_ZIO is not set # CONFIG_USB_SERIAL_DEBUG is not set # @@ -1158,7 +1264,6 @@ CONFIG_USB_SERIAL_CP210X=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -1171,7 +1276,6 @@ CONFIG_USB_SERIAL_CP210X=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # @@ -1189,10 +1293,6 @@ CONFIG_RTC_LIB=y # CONFIG_DMADEVICES is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set - -# -# TI VLYNQ -# # CONFIG_STAGING is not set # @@ -1214,6 +1314,7 @@ CONFIG_JBD=y # CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set CONFIG_FILE_LOCKING=y CONFIG_FSNOTIFY=y # CONFIG_DNOTIFY is not set @@ -1274,6 +1375,7 @@ CONFIG_JFFS2_ZLIB=y # CONFIG_JFFS2_LZO is not set CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set CONFIG_CRAMFS=y # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1284,7 +1386,6 @@ CONFIG_CRAMFS=y # CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set -# CONFIG_NILFS2_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y @@ -1299,6 +1400,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1360,6 +1462,7 @@ CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y CONFIG_FRAME_WARN=1024 # CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set # CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set @@ -1393,15 +1496,25 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_LKDTM is not set # CONFIG_FAULT_INJECTION is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set # CONFIG_PAGE_POISONING is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_TRACING_SUPPORT=y CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set # CONFIG_IRQSOFF_TRACER is not set # CONFIG_PREEMPT_TRACER is not set # CONFIG_SCHED_TRACER is not set @@ -1410,19 +1523,22 @@ CONFIG_FTRACE=y CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set # CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set -# CONFIG_KMEMCHECK is not set +# CONFIG_EARLY_PRINTK is not set CONFIG_CMDLINE_BOOL=y -CONFIG_CMDLINE="rw dhash_entries=1024 ihash_entries=1024 ip=10.0.1.3:10.0.1.1:10.0.1.1:255.255.255.0:zeus:eth0: root=/dev/nfs nfsroot=/nfsroot/cramfs,wsize=512,rsize=512,tcp nokgdb console=ttyUSB0,115200 memsize=252M" +CONFIG_CMDLINE="" # CONFIG_CMDLINE_OVERRIDE is not set # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_RUNTIME_DEBUG is not set +# CONFIG_SPINLOCK_TEST is not set # # Security options @@ -1430,13 +1546,16 @@ CONFIG_CMDLINE="rw dhash_entries=1024 ihash_entries=1024 ip=10.0.1.3:10.0.1.1:10 # CONFIG_KEYS is not set # CONFIG_SECURITY is not set # CONFIG_SECURITYFS is not set -# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_DEFAULT_SECURITY_SELINUX is not set +# CONFIG_DEFAULT_SECURITY_SMACK is not set +# CONFIG_DEFAULT_SECURITY_TOMOYO is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" CONFIG_CRYPTO=y # # Crypto core or helper # -# CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=y CONFIG_CRYPTO_ALGAPI2=y CONFIG_CRYPTO_AEAD=y @@ -1479,11 +1598,13 @@ CONFIG_CRYPTO_CBC=y # CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set # # Digest # # CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set # CONFIG_CRYPTO_MD4 is not set CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_MICHAEL_MIC is not set diff --git a/arch/mips/powertv/init.c b/arch/mips/powertv/init.c index 0afe227..8355228 100644 --- a/arch/mips/powertv/init.c +++ b/arch/mips/powertv/init.c @@ -117,8 +117,10 @@ void __init prom_init(void) board_nmi_handler_setup = mips_nmi_setup; board_ejtag_handler_setup = mips_ejtag_setup; - if (prom_argc == 1) + if (prom_argc == 1) { + strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE); strlcat(arcs_cmdline, prom_argv, COMMAND_LINE_SIZE); + } configure_platform(); prom_meminit(); -- cgit v0.10.2 From d16f7093b6eb4f3859856f6ee4ab504cbeeea0b9 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Mon, 5 Jul 2010 21:11:26 +0100 Subject: MIPS: AR7: rewrite of cpmac_get_mac() Shamelessly stealing wisdom from pasemi_mac.c, I found char2hex() could be replaced with a single call to sscanf(), looks cleaner to me at least. The result is 100 bytes trimmed off the size of a compiled cpmac_get_mac() and as an extra bonus it grumbles and gracefully fails over to using random_ether_addr() when an attempt to parse an invalid MAC address is made. Signed-off-by: Alexander Clouter To: linux-mips@linux-mips.org Cc: florian@openwrt.org Signed-off-by: Ralf Baechle diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c index 8f31d1d..0da5b2b 100644 --- a/arch/mips/ar7/platform.c +++ b/arch/mips/ar7/platform.c @@ -292,40 +292,28 @@ static struct platform_device cpmac_high = { .num_resources = ARRAY_SIZE(cpmac_high_res), }; -static inline unsigned char char2hex(char h) +static void __init cpmac_get_mac(int instance, unsigned char *dev_addr) { - switch (h) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - return h - '0'; - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - return h - 'A' + 10; - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - return h - 'a' + 10; - default: - return 0; - } -} - -static void cpmac_get_mac(int instance, unsigned char *dev_addr) -{ - int i; - char name[5], default_mac[ETH_ALEN], *mac; + char name[5], *mac; - mac = NULL; sprintf(name, "mac%c", 'a' + instance); mac = prom_getenv(name); - if (!mac) { + if (!mac && instance) { sprintf(name, "mac%c", 'a'); mac = prom_getenv(name); } - if (!mac) { - random_ether_addr(default_mac); - mac = default_mac; - } - for (i = 0; i < 6; i++) - dev_addr[i] = (char2hex(mac[i * 3]) << 4) + - char2hex(mac[i * 3 + 1]); + + if (mac) { + if (sscanf(mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + &dev_addr[0], &dev_addr[1], + &dev_addr[2], &dev_addr[3], + &dev_addr[4], &dev_addr[5]) != 6) { + pr_warning("cannot parse mac address, " + "using random address\n"); + random_ether_addr(dev_addr); + } + } else + random_ether_addr(dev_addr); } /***************************************************************************** -- cgit v0.10.2 From 1a403d1d2e549bc7d280001503867321572717f6 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 25 Jun 2010 16:46:07 -0700 Subject: MIPS: Create and use asm/arch_hweight.h Some MIPS ISA processor varients can do hweight operations efficiently. Split arch_hweight.h into a seperate file, and implement the operations with __builtin_popcount{,ll} if supported. Signed-off-by: David Daney To: linux-mips@linux-mips.org Cc: David Daney Patchwork: https://patchwork.linux-mips.org/patch/1430/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/arch_hweight.h b/arch/mips/include/asm/arch_hweight.h new file mode 100644 index 0000000..712a744 --- /dev/null +++ b/arch/mips/include/asm/arch_hweight.h @@ -0,0 +1,38 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + */ +#ifndef _ASM_ARCH_HWEIGHT_H +#define _ASM_ARCH_HWEIGHT_H + +#ifdef ARCH_HAS_USABLE_BUILTIN_POPCOUNT + +#include + +static inline unsigned int __arch_hweight32(unsigned int w) +{ + return __builtin_popcount(w); +} + +static inline unsigned int __arch_hweight16(unsigned int w) +{ + return __builtin_popcount(w & 0xffff); +} + +static inline unsigned int __arch_hweight8(unsigned int w) +{ + return __builtin_popcount(w & 0xff); +} + +static inline unsigned long __arch_hweight64(__u64 w) +{ + return __builtin_popcountll(w); +} + +#else +#include +#endif + +#endif /* _ASM_ARCH_HWEIGHT_H */ diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h index 9255cfb..b0ce7ca 100644 --- a/arch/mips/include/asm/bitops.h +++ b/arch/mips/include/asm/bitops.h @@ -700,7 +700,10 @@ static inline int ffs(int word) #ifdef __KERNEL__ #include -#include + +#include +#include + #include #include #include -- cgit v0.10.2 From 1d1929c7662d5da3badcf0df2ca5c9b2dc15db97 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 25 Jun 2010 16:46:08 -0700 Subject: MIPS: Octeon: Define ARCH_HAS_USABLE_BUILTIN_POPCOUNT for OCTEON. OCTEON implements __builtin_popcount with a single instruction, so lets use it. Signed-off-by: David Daney To: linux-mips@linux-mips.org Cc: David Daney Patchwork: https://patchwork.linux-mips.org/patch/1431/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h index bbf0540..2a7ea90 100644 --- a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h @@ -77,6 +77,14 @@ static inline int read_current_timer(unsigned long *result) return 0; } +#ifdef __OCTEON__ +/* + * All gcc versions that have OCTEON support define __OCTEON__ and have the + * __builtin_popcount support. + */ +#define ARCH_HAS_USABLE_BUILTIN_POPCOUNT 1 +#endif + static inline int octeon_has_saa(void) { int id; -- cgit v0.10.2 From eebacda40f2f9818c92f61b2228c7888e1f4926c Mon Sep 17 00:00:00 2001 From: Shinya Kuribayashi Date: Thu, 17 Jun 2010 20:35:58 +0900 Subject: MIPS: EMMA2RH: Remove useless CPU_IRQ_BASE For historical reasons, we used to put MIPS CPU IRQs behind SoC-specific IRQs in the queue, and have been using CPU_IRQ_BASE as MIPS_CPU_IRQ_BASE. In recent years, however, we've brought it back to normal order, and now CPU_IRQ_BASE just redefines the generic MIPS_CPU_IRQ_BASE. At the same time, NUM_CPU_IRQ is also removed as useless. Signed-off-by: Shinya Kuribayashi To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1387/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/emma/markeins/irq.c b/arch/mips/emma/markeins/irq.c index 9504b7e..1d1c806 100644 --- a/arch/mips/emma/markeins/irq.c +++ b/arch/mips/emma/markeins/irq.c @@ -301,7 +301,7 @@ void __init arch_init_irq(void) /* setup cascade interrupts */ setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_SW_CASCADE, &irq_cascade); setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_GPIO_CASCADE, &irq_cascade); - setup_irq(CPU_IRQ_BASE + CPU_EMMA2RH_CASCADE, &irq_cascade); + setup_irq(MIPS_CPU_IRQ_BASE + CPU_EMMA2RH_CASCADE, &irq_cascade); } asmlinkage void plat_irq_dispatch(void) @@ -309,13 +309,13 @@ asmlinkage void plat_irq_dispatch(void) unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; if (pending & STATUSF_IP7) - do_IRQ(CPU_IRQ_BASE + 7); + do_IRQ(MIPS_CPU_IRQ_BASE + 7); else if (pending & STATUSF_IP2) emma2rh_irq_dispatch(); else if (pending & STATUSF_IP1) - do_IRQ(CPU_IRQ_BASE + 1); + do_IRQ(MIPS_CPU_IRQ_BASE + 1); else if (pending & STATUSF_IP0) - do_IRQ(CPU_IRQ_BASE + 0); + do_IRQ(MIPS_CPU_IRQ_BASE + 0); else spurious_interrupt(); } diff --git a/arch/mips/include/asm/emma/emma2rh.h b/arch/mips/include/asm/emma/emma2rh.h index 2afb2fe..fcc0064 100644 --- a/arch/mips/include/asm/emma/emma2rh.h +++ b/arch/mips/include/asm/emma/emma2rh.h @@ -99,12 +99,10 @@ #define EMMA2RH_PCI_CONFIG_BASE EMMA2RH_PCI_IO_BASE #define EMMA2RH_PCI_CONFIG_SIZE EMMA2RH_PCI_IO_SIZE -#define NUM_CPU_IRQ 8 #define NUM_EMMA2RH_IRQ 96 #define CPU_EMMA2RH_CASCADE 2 -#define CPU_IRQ_BASE MIPS_CPU_IRQ_BASE -#define EMMA2RH_IRQ_BASE (CPU_IRQ_BASE + NUM_CPU_IRQ) +#define EMMA2RH_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8) /* * emma2rh irq defs -- cgit v0.10.2 From 9e6f39698ac66e08017114a51600bf633becd011 Mon Sep 17 00:00:00 2001 From: Shinya Kuribayashi Date: Thu, 17 Jun 2010 20:36:13 +0900 Subject: MIPS: EMMA2RH: Remove EMMA2RH_CPU_CASCADE Although all EMMAxxx SoCs can support IP2 and IP3 hardware interrupts, current EMMA2RH plat_irq_dispatch() supports IP2 only. We can make it configurable in the future, but for the time being, would like to make things explicitly allcated to IP2 in accordance with plat_irq_dispatch(). Signed-off-by: Shinya Kuribayashi To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1388/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/emma/markeins/irq.c b/arch/mips/emma/markeins/irq.c index 1d1c806..3a96799 100644 --- a/arch/mips/emma/markeins/irq.c +++ b/arch/mips/emma/markeins/irq.c @@ -301,7 +301,7 @@ void __init arch_init_irq(void) /* setup cascade interrupts */ setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_SW_CASCADE, &irq_cascade); setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_GPIO_CASCADE, &irq_cascade); - setup_irq(MIPS_CPU_IRQ_BASE + CPU_EMMA2RH_CASCADE, &irq_cascade); + setup_irq(MIPS_CPU_IRQ_BASE + 2, &irq_cascade); } asmlinkage void plat_irq_dispatch(void) diff --git a/arch/mips/include/asm/emma/emma2rh.h b/arch/mips/include/asm/emma/emma2rh.h index fcc0064..95d0b7e 100644 --- a/arch/mips/include/asm/emma/emma2rh.h +++ b/arch/mips/include/asm/emma/emma2rh.h @@ -101,7 +101,6 @@ #define NUM_EMMA2RH_IRQ 96 -#define CPU_EMMA2RH_CASCADE 2 #define EMMA2RH_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8) /* -- cgit v0.10.2 From 4040703fffbb6b120253b2fe69f743466af69778 Mon Sep 17 00:00:00 2001 From: Shinya Kuribayashi Date: Thu, 17 Jun 2010 20:36:32 +0900 Subject: MIPS: EMMA2RH: Replace EMMA2RH_IRQ_INTxx with EMMA2RH_IRQ_INT(n) Don't duplicate worthless lines. Signed-off-by: Shinya Kuribayashi To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1389/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/emma/emma2rh.h b/arch/mips/include/asm/emma/emma2rh.h index 95d0b7e..c1449d2 100644 --- a/arch/mips/include/asm/emma/emma2rh.h +++ b/arch/mips/include/asm/emma/emma2rh.h @@ -107,77 +107,14 @@ * emma2rh irq defs */ -#define EMMA2RH_IRQ_INT0 (0 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT1 (1 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT2 (2 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT3 (3 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT4 (4 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT5 (5 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT6 (6 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT7 (7 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT8 (8 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT9 (9 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT10 (10 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT11 (11 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT12 (12 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT13 (13 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT14 (14 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT15 (15 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT16 (16 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT17 (17 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT18 (18 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT19 (19 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT20 (20 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT21 (21 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT22 (22 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT23 (23 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT24 (24 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT25 (25 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT26 (26 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT27 (27 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT28 (28 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT29 (29 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT30 (30 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT31 (31 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT32 (32 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT33 (33 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT34 (34 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT35 (35 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT36 (36 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT37 (37 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT38 (38 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT39 (39 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT40 (40 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT41 (41 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT42 (42 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT43 (43 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT44 (44 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT45 (45 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT46 (46 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT47 (47 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT48 (48 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT49 (49 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT50 (50 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT51 (51 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT52 (52 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT53 (53 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT54 (54 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT55 (55 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT56 (56 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT57 (57 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT58 (58 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT59 (59 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT60 (60 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT61 (61 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT62 (62 + EMMA2RH_IRQ_BASE) -#define EMMA2RH_IRQ_INT63 (63 + EMMA2RH_IRQ_BASE) - -#define EMMA2RH_IRQ_PFUR0 EMMA2RH_IRQ_INT49 -#define EMMA2RH_IRQ_PFUR1 EMMA2RH_IRQ_INT50 -#define EMMA2RH_IRQ_PFUR2 EMMA2RH_IRQ_INT51 -#define EMMA2RH_IRQ_PIIC0 EMMA2RH_IRQ_INT56 -#define EMMA2RH_IRQ_PIIC1 EMMA2RH_IRQ_INT57 -#define EMMA2RH_IRQ_PIIC2 EMMA2RH_IRQ_INT58 +#define EMMA2RH_IRQ_INT(n) (EMMA2RH_IRQ_BASE + (n)) + +#define EMMA2RH_IRQ_PFUR0 EMMA2RH_IRQ_INT(49) +#define EMMA2RH_IRQ_PFUR1 EMMA2RH_IRQ_INT(50) +#define EMMA2RH_IRQ_PFUR2 EMMA2RH_IRQ_INT(51) +#define EMMA2RH_IRQ_PIIC0 EMMA2RH_IRQ_INT(56) +#define EMMA2RH_IRQ_PIIC1 EMMA2RH_IRQ_INT(57) +#define EMMA2RH_IRQ_PIIC2 EMMA2RH_IRQ_INT(58) /* * EMMA2RH Register Access diff --git a/arch/mips/include/asm/emma/markeins.h b/arch/mips/include/asm/emma/markeins.h index 2618bf2..507f125 100644 --- a/arch/mips/include/asm/emma/markeins.h +++ b/arch/mips/include/asm/emma/markeins.h @@ -25,8 +25,8 @@ #define NUM_EMMA2RH_IRQ_SW 32 #define NUM_EMMA2RH_IRQ_GPIO 32 -#define EMMA2RH_SW_CASCADE (EMMA2RH_IRQ_INT7 - EMMA2RH_IRQ_INT0) -#define EMMA2RH_GPIO_CASCADE (EMMA2RH_IRQ_INT46 - EMMA2RH_IRQ_INT0) +#define EMMA2RH_SW_CASCADE (EMMA2RH_IRQ_INT(7) - EMMA2RH_IRQ_INT(0)) +#define EMMA2RH_GPIO_CASCADE (EMMA2RH_IRQ_INT(46) - EMMA2RH_IRQ_INT(0)) #define EMMA2RH_SW_IRQ_BASE (EMMA2RH_IRQ_BASE + NUM_EMMA2RH_IRQ) #define EMMA2RH_GPIO_IRQ_BASE (EMMA2RH_SW_IRQ_BASE + NUM_EMMA2RH_IRQ_SW) -- cgit v0.10.2 From 1f1f4e7dbc0c0312e9e7fe3cadd07340ea62070f Mon Sep 17 00:00:00 2001 From: Shinya Kuribayashi Date: Thu, 17 Jun 2010 20:37:13 +0900 Subject: MIPS: EMMA2RH: Replace EMMA2RH_SW_IRQ_INTxx with EMMA2RH_SW_IRQ(n) Don't duplicate worthless lines. Signed-off-by: Shinya Kuribayashi To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1390/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/emma/markeins.h b/arch/mips/include/asm/emma/markeins.h index 507f125..bf2d229 100644 --- a/arch/mips/include/asm/emma/markeins.h +++ b/arch/mips/include/asm/emma/markeins.h @@ -31,38 +31,7 @@ #define EMMA2RH_SW_IRQ_BASE (EMMA2RH_IRQ_BASE + NUM_EMMA2RH_IRQ) #define EMMA2RH_GPIO_IRQ_BASE (EMMA2RH_SW_IRQ_BASE + NUM_EMMA2RH_IRQ_SW) -#define EMMA2RH_SW_IRQ_INT0 (0+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT1 (1+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT2 (2+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT3 (3+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT4 (4+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT5 (5+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT6 (6+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT7 (7+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT8 (8+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT9 (9+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT10 (10+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT11 (11+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT12 (12+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT13 (13+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT14 (14+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT15 (15+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT16 (16+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT17 (17+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT18 (18+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT19 (19+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT20 (20+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT21 (21+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT22 (22+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT23 (23+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT24 (24+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT25 (25+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT26 (26+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT27 (27+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT28 (28+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT29 (29+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT30 (30+EMMA2RH_SW_IRQ_BASE) -#define EMMA2RH_SW_IRQ_INT31 (31+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT(n) (EMMA2RH_SW_IRQ_BASE + (n)) #define MARKEINS_PCI_IRQ_INTA EMMA2RH_GPIO_IRQ_BASE+15 #define MARKEINS_PCI_IRQ_INTB EMMA2RH_GPIO_IRQ_BASE+16 -- cgit v0.10.2 From f5c1ca77a3b2f9b424c4f39bd71143d0ac308924 Mon Sep 17 00:00:00 2001 From: Shinya Kuribayashi Date: Sun, 27 Jun 2010 22:52:01 +0900 Subject: MIPS: Loongson: irq.c: Misc cleanups * Remove unnecessary 'if (int_status & (1 <<10))' statement * s/if (foo != 0)/if (foo)/ * Remove unused 'inst_status &= ~(1 << i);' line Signed-off-by: Shinya Kuribayashi To: wuzhangjin@gmail.com CC: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1433/ Acked-by: Wu Zhangjin Signed-off-by: Ralf Baechle diff --git a/arch/mips/loongson/common/irq.c b/arch/mips/loongson/common/irq.c index 20e7328..25a11df 100644 --- a/arch/mips/loongson/common/irq.c +++ b/arch/mips/loongson/common/irq.c @@ -21,19 +21,16 @@ void bonito_irqdispatch(void) /* workaround the IO dma problem: let cpu looping to allow DMA finish */ int_status = LOONGSON_INTISR; - if (int_status & (1 << 10)) { - while (int_status & (1 << 10)) { - udelay(1); - int_status = LOONGSON_INTISR; - } + while (int_status & (1 << 10)) { + udelay(1); + int_status = LOONGSON_INTISR; } /* Get pending sources, masked by current enables */ int_status = LOONGSON_INTISR & LOONGSON_INTEN; - if (int_status != 0) { + if (int_status) { i = __ffs(int_status); - int_status &= ~(1 << i); do_IRQ(LOONGSON_IRQ_BASE + i); } } -- cgit v0.10.2 From b3b3c176d9150af542d9ba5e5b292d233883ff85 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Mon, 12 Jul 2010 00:40:38 +0900 Subject: MIPS: MTX-1: cleanup and comments Add some comments about mtx1_pci_idsel() and remove a dead block of old code. Signed-off-by: Bruno Randolf To: linux-mips@linux-mips.org To: manuel.lauss@googlemail.com Cc: florian@openwrt.org Patchwork: https://patchwork.linux-mips.org/patch/1449/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/alchemy/mtx-1/board_setup.c b/arch/mips/alchemy/mtx-1/board_setup.c index def1a75..ff36973 100644 --- a/arch/mips/alchemy/mtx-1/board_setup.c +++ b/arch/mips/alchemy/mtx-1/board_setup.c @@ -108,14 +108,10 @@ void __init board_setup(void) int mtx1_pci_idsel(unsigned int devsel, int assert) { -#define MTX_IDSEL_ONLY_0_AND_3 0 -#if MTX_IDSEL_ONLY_0_AND_3 - if (devsel != 0 && devsel != 3) { - printk(KERN_ERR "*** not 0 or 3\n"); - return 0; - } -#endif - + /* This function is only necessary to support a proprietary Cardbus + * adapter on the mtx-1 "singleboard" variant. It triggers a custom + * logic chip connected to EXT_IO3 (GPIO1) to suppress IDSEL signals. + */ if (assert && devsel != 0) /* Suppress signal to Cardbus */ alchemy_gpio_set_value(1, 0); /* set EXT_IO3 OFF */ -- cgit v0.10.2 From 1091458d09e1a0788268578001f279250d2c0844 Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 19 Jul 2010 13:14:56 -0700 Subject: MIPS: Randomize mmap if randomize_va_space is set Fairly straight forward: For 32-bit address spaces randomize within a 16MB space, for 64-bit within a 256MB space. Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1480/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index 5d33b72..24d91f8 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -34,6 +34,11 @@ extern void (*cpu_wait)(void); extern unsigned int vced_count, vcei_count; /* + * MIPS does have an arch_pick_mmap_layout() + */ +#define HAVE_ARCH_PICK_MMAP_LAYOUT 1 + +/* * A special page (the vdso) is mapped into all processes at the very * top of the virtual memory space. */ @@ -52,6 +57,9 @@ extern unsigned int vced_count, vcei_count; * space during mmap's. */ #define TASK_UNMAPPED_BASE ((TASK_SIZE / 3) & ~(PAGE_SIZE)) + +#define TASK_IS_32BIT_ADDR 1 + #endif #ifdef CONFIG_64BIT @@ -77,6 +85,9 @@ extern unsigned int vced_count, vcei_count; PAGE_ALIGN(TASK_SIZE32 / 3) : PAGE_ALIGN(TASK_SIZE / 3)) #define TASK_SIZE_OF(tsk) \ (test_tsk_thread_flag(tsk, TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE) + +#define TASK_IS_32BIT_ADDR test_thread_flag(TIF_32BIT_ADDR) + #endif #ifdef __KERNEL__ diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index dd81b0f..9824a82 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -116,7 +117,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, (!vmm || addr + len <= vmm->vm_start)) return addr; } - addr = TASK_UNMAPPED_BASE; + addr = current->mm->mmap_base; if (do_color_align) addr = COLOUR_ALIGN(addr, pgoff); else @@ -134,6 +135,24 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, } } +void arch_pick_mmap_layout(struct mm_struct *mm) +{ + unsigned long random_factor = 0UL; + + if (current->flags & PF_RANDOMIZE) { + random_factor = get_random_int(); + random_factor = random_factor << PAGE_SHIFT; + if (TASK_IS_32BIT_ADDR) + random_factor &= 0xfffffful; + else + random_factor &= 0xffffffful; + } + + mm->mmap_base = TASK_UNMAPPED_BASE + random_factor; + mm->get_unmapped_area = arch_get_unmapped_area; + mm->unmap_area = arch_unmap_area; +} + SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, off_t, offset) -- cgit v0.10.2 From 652b14aa84961fa391184ccbaf559a537d33b28c Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 19 Jul 2010 13:14:57 -0700 Subject: MIPS: Enable heap randomization. Based somewhat on the PPC implementation. 32-bit processes have the heap randomized in an 8MB space, 256MB for 64-bit processes. Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1479/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index ea77a42..fd1d39e 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -372,4 +372,9 @@ extern const char *__elf_platform; struct linux_binprm; extern int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp); + +struct mm_struct; +extern unsigned long arch_randomize_brk(struct mm_struct *mm); +#define arch_randomize_brk arch_randomize_brk + #endif /* _ASM_ELF_H */ diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 9824a82..58bab2e 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -153,6 +154,33 @@ void arch_pick_mmap_layout(struct mm_struct *mm) mm->unmap_area = arch_unmap_area; } +static inline unsigned long brk_rnd(void) +{ + unsigned long rnd = get_random_int(); + + rnd = rnd << PAGE_SHIFT; + /* 8MB for 32bit, 256MB for 64bit */ + if (TASK_IS_32BIT_ADDR) + rnd = rnd & 0x7ffffful; + else + rnd = rnd & 0xffffffful; + + return rnd; +} + +unsigned long arch_randomize_brk(struct mm_struct *mm) +{ + unsigned long base = mm->brk; + unsigned long ret; + + ret = PAGE_ALIGN(base + brk_rnd()); + + if (ret < mm->brk) + return mm->brk; + + return ret; +} + SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, off_t, offset) -- cgit v0.10.2 From 65ab2826c4185fc949c3a720186bd09d75ea14a4 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Sun, 18 Jul 2010 03:10:51 +0800 Subject: MIPS: tracing: Fix the indentation of mcount.S The commit "MIPS: Tracing: Cleanup the arguments passing of prepare_ftrace_return" has moved the "jal prepare_ftrace_return" instruction after the handling of the 3rd argument but forgot to remove the superfluous space before the related instructions. Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1475/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S index 6bfcb7a..4c968e7 100644 --- a/arch/mips/kernel/mcount.S +++ b/arch/mips/kernel/mcount.S @@ -165,12 +165,12 @@ NESTED(ftrace_graph_caller, PT_SIZE, ra) /* arg3: Get frame pointer of current stack */ #ifdef CONFIG_FRAME_POINTER - move a2, fp + move a2, fp #else /* ! CONFIG_FRAME_POINTER */ #ifdef CONFIG_64BIT - PTR_LA a2, PT_SIZE(sp) + PTR_LA a2, PT_SIZE(sp) #else - PTR_LA a2, (PT_SIZE+8)(sp) + PTR_LA a2, (PT_SIZE+8)(sp) #endif #endif -- cgit v0.10.2 From 58a6d45193a4f5af9d55f243779ea485656e3a22 Mon Sep 17 00:00:00 2001 From: Ricardo Mendoza Date: Mon, 19 Jul 2010 04:59:59 +0100 Subject: MIPS: RM7000: Make use of cache_op() instead of inline asm Small cleanup of the cache code to get rid of inline asm, in preparation to give tertiary cache support. Signed-off-by: Ricardo Mendoza To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1476/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c index de69bfb..5363439 100644 --- a/arch/mips/mm/sc-rm7k.c +++ b/arch/mips/mm/sc-rm7k.c @@ -95,16 +95,8 @@ static __cpuinit void __rm7k_sc_enable(void) write_c0_taglo(0); write_c0_taghi(0); - for (i = 0; i < scache_size; i += sc_lsize) { - __asm__ __volatile__ ( - ".set noreorder\n\t" - ".set mips3\n\t" - "cache %1, (%0)\n\t" - ".set mips0\n\t" - ".set reorder" - : - : "r" (CKSEG0ADDR(i)), "i" (Index_Store_Tag_SD)); - } + for (i = 0; i < scache_size; i += sc_lsize) + cache_op(Index_Store_Tag_SD, CKSEG0ADDR(i)); } static __cpuinit void rm7k_sc_enable(void) -- cgit v0.10.2 From 745aef5df1e2277ee9e34d86491084c0d6106338 Mon Sep 17 00:00:00 2001 From: Ricardo Mendoza Date: Mon, 19 Jul 2010 05:00:00 +0100 Subject: MIPS: RM7000: Add support for tertiary cache Add support for the external T-cache interface. Allow for platform independent size probing from 512KB to 8MB in powers of two. Signed-off-by: Ricardo Mendoza To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1477/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/cacheops.h b/arch/mips/include/asm/cacheops.h index 256ad2c..8f99c11 100644 --- a/arch/mips/include/asm/cacheops.h +++ b/arch/mips/include/asm/cacheops.h @@ -62,6 +62,8 @@ * RM7000-specific cacheops */ #define Page_Invalidate_T 0x16 +#define Index_Store_Tag_T 0x0a +#define Index_Load_Tag_T 0x06 /* * R10000-specific cacheops diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c index 5363439..1ef75cd 100644 --- a/arch/mips/mm/sc-rm7k.c +++ b/arch/mips/mm/sc-rm7k.c @@ -16,6 +16,7 @@ #include #include #include +#include #include /* for run_uncached() */ /* Primary cache parameters. */ @@ -25,11 +26,15 @@ /* Secondary cache parameters. */ #define scache_size (256*1024) /* Fixed to 256KiB on RM7000 */ +/* Tertiary cache parameters */ +#define tc_lsize 32 + extern unsigned long icache_way_size, dcache_way_size; +unsigned long tcache_size; #include -static int rm7k_tcache_enabled; +static int rm7k_tcache_init; /* * Writeback and invalidate the primary cache dcache before DMA. @@ -46,7 +51,7 @@ static void rm7k_sc_wback_inv(unsigned long addr, unsigned long size) blast_scache_range(addr, addr + size); - if (!rm7k_tcache_enabled) + if (!rm7k_tcache_init) return; a = addr & ~(tc_pagesize - 1); @@ -70,7 +75,7 @@ static void rm7k_sc_inv(unsigned long addr, unsigned long size) blast_inv_scache_range(addr, addr + size); - if (!rm7k_tcache_enabled) + if (!rm7k_tcache_init) return; a = addr & ~(tc_pagesize - 1); @@ -83,6 +88,45 @@ static void rm7k_sc_inv(unsigned long addr, unsigned long size) } } +static void blast_rm7k_tcache(void) +{ + unsigned long start = CKSEG0ADDR(0); + unsigned long end = start + tcache_size; + + write_c0_taglo(0); + + while (start < end) { + cache_op(Page_Invalidate_T, start); + start += tc_pagesize; + } +} + +/* + * This function is executed in uncached address space. + */ +static __cpuinit void __rm7k_tc_enable(void) +{ + int i; + + set_c0_config(RM7K_CONF_TE); + + write_c0_taglo(0); + write_c0_taghi(0); + + for (i = 0; i < tcache_size; i += tc_lsize) + cache_op(Index_Store_Tag_T, CKSEG0ADDR(i)); +} + +static __cpuinit void rm7k_tc_enable(void) +{ + if (read_c0_config() & RM7K_CONF_TE) + return; + + BUG_ON(tcache_size == 0); + + run_uncached(__rm7k_tc_enable); +} + /* * This function is executed in uncached address space. */ @@ -104,13 +148,29 @@ static __cpuinit void rm7k_sc_enable(void) if (read_c0_config() & RM7K_CONF_SE) return; - printk(KERN_INFO "Enabling secondary cache...\n"); + pr_info("Enabling secondary cache...\n"); run_uncached(__rm7k_sc_enable); + + if (rm7k_tcache_init) + rm7k_tc_enable(); +} + +static void rm7k_tc_disable(void) +{ + unsigned long flags; + + local_irq_save(flags); + blast_rm7k_tcache(); + clear_c0_config(RM7K_CONF_TE); + local_irq_save(flags); } static void rm7k_sc_disable(void) { clear_c0_config(RM7K_CONF_SE); + + if (rm7k_tcache_init) + rm7k_tc_disable(); } static struct bcache_ops rm7k_sc_ops = { @@ -120,6 +180,52 @@ static struct bcache_ops rm7k_sc_ops = { .bc_inv = rm7k_sc_inv }; +/* + * This is a probing function like the one found in c-r4k.c, we look for the + * wrap around point with different addresses. + */ +static __cpuinit void __probe_tcache(void) +{ + unsigned long flags, addr, begin, end, pow2; + + begin = (unsigned long) &_stext; + begin &= ~((8 * 1024 * 1024) - 1); + end = begin + (8 * 1024 * 1024); + + local_irq_save(flags); + + set_c0_config(RM7K_CONF_TE); + + /* Fill size-multiple lines with a valid tag */ + pow2 = (256 * 1024); + for (addr = begin; addr <= end; addr = (begin + pow2)) { + unsigned long *p = (unsigned long *) addr; + __asm__ __volatile__("nop" : : "r" (*p)); + pow2 <<= 1; + } + + /* Load first line with a 0 tag, to check after */ + write_c0_taglo(0); + write_c0_taghi(0); + cache_op(Index_Store_Tag_T, begin); + + /* Look for the wrap-around */ + pow2 = (512 * 1024); + for (addr = begin + (512 * 1024); addr <= end; addr = begin + pow2) { + cache_op(Index_Load_Tag_T, addr); + if (!read_c0_taglo()) + break; + pow2 <<= 1; + } + + addr -= begin; + tcache_size = addr; + + clear_c0_config(RM7K_CONF_TE); + + local_irq_restore(flags); +} + void __cpuinit rm7k_sc_init(void) { struct cpuinfo_mips *c = ¤t_cpu_data; @@ -139,27 +245,26 @@ void __cpuinit rm7k_sc_init(void) if (!(config & RM7K_CONF_SE)) rm7k_sc_enable(); + bcops = &rm7k_sc_ops; + /* * While we're at it let's deal with the tertiary cache. */ - if (!(config & RM7K_CONF_TC)) { - - /* - * We can't enable the L3 cache yet. There may be board-specific - * magic necessary to turn it on, and blindly asking the CPU to - * start using it would may give cache errors. - * - * Also, board-specific knowledge may allow us to use the - * CACHE Flash_Invalidate_T instruction if the tag RAM supports - * it, and may specify the size of the L3 cache so we don't have - * to probe it. - */ - printk(KERN_INFO "Tertiary cache present, %s enabled\n", - (config & RM7K_CONF_TE) ? "already" : "not (yet)"); - - if ((config & RM7K_CONF_TE)) - rm7k_tcache_enabled = 1; - } - bcops = &rm7k_sc_ops; + rm7k_tcache_init = 0; + tcache_size = 0; + + if (config & RM7K_CONF_TC) + return; + + /* + * No efficient way to ask the hardware for the size of the tcache, + * so must probe for it. + */ + run_uncached(__probe_tcache); + rm7k_tc_enable(); + rm7k_tcache_init = 1; + c->tcache.linesz = tc_lsize; + c->tcache.ways = 1; + pr_info("Tertiary cache size %ldK.\n", (tcache_size >> 10)); } -- cgit v0.10.2 From 42a4f17dc356689075263d7c2bd68456676fa62e Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Thu, 15 Jul 2010 21:45:04 +0200 Subject: MIPS: Alchemy: remove SOC_AU1X00 in favor of MIPS_ALCHEMY Remove the CONFIG_SOC_AU1X00 Kconfig symbol since its job can also be done by MACH_ALCHEMY, now renamed to MIPS_ALCHEMY. Signed-off-by: Manuel Lauss To: Linux-MIPS Patchwork: https://patchwork.linux-mips.org/patch/1461/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index b81a6b2..0dd1649 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -23,8 +23,17 @@ choice prompt "System type" default SGI_IP22 -config MACH_ALCHEMY +config MIPS_ALCHEMY bool "Alchemy processor based machines" + select 64BIT_PHYS_ADDR + select CEVT_R4K_LIB + select CSRC_R4K_LIB + select IRQ_CPU + select SYS_HAS_CPU_MIPS32_R1 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_APM_EMULATION + select GENERIC_GPIO + select ARCH_WANT_OPTIONAL_GPIOLIB select SYS_SUPPORTS_ZBOOT config AR7 diff --git a/arch/mips/alchemy/Kconfig b/arch/mips/alchemy/Kconfig index df3b1a7..1179c4d 100644 --- a/arch/mips/alchemy/Kconfig +++ b/arch/mips/alchemy/Kconfig @@ -11,7 +11,7 @@ config ALCHEMY_GPIO_INDIRECT choice prompt "Machine type" - depends on MACH_ALCHEMY + depends on MIPS_ALCHEMY default MIPS_DB1000 config MIPS_MTX1 @@ -132,37 +132,20 @@ endchoice config SOC_AU1000 bool - select SOC_AU1X00 select ALCHEMY_GPIOINT_AU1000 config SOC_AU1100 bool - select SOC_AU1X00 select ALCHEMY_GPIOINT_AU1000 config SOC_AU1500 bool - select SOC_AU1X00 select ALCHEMY_GPIOINT_AU1000 config SOC_AU1550 bool - select SOC_AU1X00 select ALCHEMY_GPIOINT_AU1000 config SOC_AU1200 bool - select SOC_AU1X00 select ALCHEMY_GPIOINT_AU1000 - -config SOC_AU1X00 - bool - select 64BIT_PHYS_ADDR - select CEVT_R4K_LIB - select CSRC_R4K_LIB - select IRQ_CPU - select SYS_HAS_CPU_MIPS32_R1 - select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_APM_EMULATION - select GENERIC_GPIO - select ARCH_WANT_OPTIONAL_GPIOLIB diff --git a/arch/mips/alchemy/Platform b/arch/mips/alchemy/Platform index 495cc9a..0bf2b09 100644 --- a/arch/mips/alchemy/Platform +++ b/arch/mips/alchemy/Platform @@ -1,7 +1,7 @@ # # Core Alchemy code # -platform-$(CONFIG_MACH_ALCHEMY) += alchemy/common/ +platform-$(CONFIG_MIPS_ALCHEMY) += alchemy/common/ # @@ -106,4 +106,4 @@ load-$(CONFIG_MIPS_XXS1500) += 0xffffffff80100000 # compiler picks the board one. If they don't, it will make sure # the alchemy generic gpio header is picked up. -cflags-$(CONFIG_MACH_ALCHEMY) += -I$(srctree)/arch/mips/include/asm/mach-au1x00 +cflags-$(CONFIG_MIPS_ALCHEMY) += -I$(srctree)/arch/mips/include/asm/mach-au1x00 diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile index 74a52d7..edc48ad 100644 --- a/arch/mips/boot/compressed/Makefile +++ b/arch/mips/boot/compressed/Makefile @@ -40,7 +40,7 @@ vmlinuzobjs-y := $(obj)/head.o $(obj)/decompress.o $(obj)/dbg.o ifdef CONFIG_DEBUG_ZBOOT vmlinuzobjs-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART16550) += $(obj)/uart-16550.o -vmlinuzobjs-$(CONFIG_MACH_ALCHEMY) += $(obj)/uart-alchemy.o +vmlinuzobjs-$(CONFIG_MIPS_ALCHEMY) += $(obj)/uart-alchemy.o endif targets += vmlinux.bin diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig index f66d406..3a9ec6c 100644 --- a/arch/mips/configs/db1000_defconfig +++ b/arch/mips/configs/db1000_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_MIPS_DB1000=y # CONFIG_MIPS_PB1550 is not set # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1000=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig index abb9a58..4589b84 100644 --- a/arch/mips/configs/db1100_defconfig +++ b/arch/mips/configs/db1100_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_MIPS_DB1100=y # CONFIG_MIPS_PB1550 is not set # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1100=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig index 991c20a..9950f2a 100644 --- a/arch/mips/configs/db1200_defconfig +++ b/arch/mips/configs/db1200_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_MIPS_DB1200=y # CONFIG_MIPS_PB1550 is not set # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1200=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig index 5424c91..346ae63 100644 --- a/arch/mips/configs/db1500_defconfig +++ b/arch/mips/configs/db1500_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_MIPS_DB1500=y # CONFIG_MIPS_PB1550 is not set # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1500=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig index 949b6dc..10eafb9 100644 --- a/arch/mips/configs/db1550_defconfig +++ b/arch/mips/configs/db1550_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_MIPS_DB1550=y # CONFIG_MIPS_PB1550 is not set # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1550=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig index cff8f4c..10d20aa 100644 --- a/arch/mips/configs/mtx1_defconfig +++ b/arch/mips/configs/mtx1_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_MIPS_MTX1=y # CONFIG_MIPS_PB1550 is not set # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1500=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig index 97382b6..778f726 100644 --- a/arch/mips/configs/pb1100_defconfig +++ b/arch/mips/configs/pb1100_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_MIPS_PB1100=y # CONFIG_MIPS_PB1550 is not set # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1100=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/configs/pb1200_defconfig b/arch/mips/configs/pb1200_defconfig index e9ad773..0f908c6 100644 --- a/arch/mips/configs/pb1200_defconfig +++ b/arch/mips/configs/pb1200_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_MIPS_PB1200=y # CONFIG_MIPS_PB1550 is not set # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1200=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig index 7497d33..1c5fe6f 100644 --- a/arch/mips/configs/pb1500_defconfig +++ b/arch/mips/configs/pb1500_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_MIPS_PB1500=y # CONFIG_MIPS_PB1550 is not set # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1500=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig index aa526f5..49494b0 100644 --- a/arch/mips/configs/pb1550_defconfig +++ b/arch/mips/configs/pb1550_defconfig @@ -8,7 +8,7 @@ CONFIG_MIPS=y # # Machine selection # -CONFIG_MACH_ALCHEMY=y +CONFIG_MIPS_ALCHEMY=y # CONFIG_AR7 is not set # CONFIG_BCM47XX is not set # CONFIG_BCM63XX is not set @@ -64,7 +64,6 @@ CONFIG_ALCHEMY_GPIOINT_AU1000=y CONFIG_MIPS_PB1550=y # CONFIG_MIPS_XXS1500 is not set CONFIG_SOC_AU1550=y -CONFIG_SOC_AU1X00=y CONFIG_LOONGSON_UART_BASE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set diff --git a/arch/mips/include/asm/hazards.h b/arch/mips/include/asm/hazards.h index 0eaf77f..4e33216 100644 --- a/arch/mips/include/asm/hazards.h +++ b/arch/mips/include/asm/hazards.h @@ -87,7 +87,7 @@ do { \ : "=r" (tmp)); \ } while (0) -#elif defined(CONFIG_CPU_MIPSR1) && !defined(CONFIG_MACH_ALCHEMY) +#elif defined(CONFIG_CPU_MIPSR1) && !defined(CONFIG_MIPS_ALCHEMY) /* * These are slightly complicated by the fact that we guarantee R1 kernels to @@ -138,7 +138,7 @@ do { \ __instruction_hazard(); \ } while (0) -#elif defined(CONFIG_MACH_ALCHEMY) || defined(CONFIG_CPU_CAVIUM_OCTEON) || \ +#elif defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_CPU_CAVIUM_OCTEON) || \ defined(CONFIG_CPU_LOONGSON2) || defined(CONFIG_CPU_R10000) || \ defined(CONFIG_CPU_R5500) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ce2fcdd..adead30 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -484,7 +484,7 @@ config XTENSA_XT2000_SONIC config MIPS_AU1X00_ENET tristate "MIPS AU1000 Ethernet support" - depends on SOC_AU1X00 + depends on MIPS_ALCHEMY select PHYLIB select CRC32 help diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index d0f5ad3..c988514 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -157,11 +157,11 @@ config PCMCIA_M8XX config PCMCIA_AU1X00 tristate "Au1x00 pcmcia support" - depends on SOC_AU1X00 && PCMCIA + depends on MIPS_ALCHEMY && PCMCIA config PCMCIA_ALCHEMY_DEVBOARD tristate "Alchemy Db/Pb1xxx PCMCIA socket services" - depends on SOC_AU1X00 && PCMCIA + depends on MIPS_ALCHEMY && PCMCIA select 64BIT_PHYS_ADDR help Enable this driver of you want PCMCIA support on your Alchemy diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 10ba12c..9d6952e 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -774,7 +774,7 @@ config RTC_DRV_AT91SAM9_GPBR config RTC_DRV_AU1XXX tristate "Au1xxx Counter0 RTC support" - depends on SOC_AU1X00 + depends on MIPS_ALCHEMY help This is a driver for the Au1xxx on-chip Counter0 (Time-Of-Year counter) to be used as a RTC. diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 8b23165..1acc7b3 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -260,7 +260,7 @@ config SERIAL_8250_ACORN config SERIAL_8250_AU1X00 bool "Au1x00 serial port support" - depends on SERIAL_8250 != n && SOC_AU1X00 + depends on SERIAL_8250 != n && MIPS_ALCHEMY help If you have an Au1x00 SOC based board and want to use the serial port, say Y to this option. The driver can handle up to 4 serial ports, diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 6a58cb1..c2ddab1 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -45,7 +45,7 @@ config USB_ARCH_HAS_OHCI default y if STB03xxx default y if PPC_MPC52xx # MIPS: - default y if SOC_AU1X00 + default y if MIPS_ALCHEMY # SH: default y if CPU_SUBTYPE_SH7720 default y if CPU_SUBTYPE_SH7721 diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index fc57655..ba6b0a5 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1031,7 +1031,7 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ohci_hcd_ep93xx_driver #endif -#ifdef CONFIG_SOC_AU1X00 +#ifdef CONFIG_MIPS_ALCHEMY #include "ohci-au1xxx.c" #define PLATFORM_DRIVER ohci_hcd_au1xxx_driver #endif -- cgit v0.10.2 From 12bf3f24e07d18ab6c42619be604e269f6738614 Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Thu, 15 Jul 2010 21:45:05 +0200 Subject: SERIAL: 8250: Remove SERIAL_8250_AU1X00 Remove the SERIAL_8250_AU1X00 config symbol. Instead, use the MIPS_ALCHEMY one which is always defined when building an Au1x00-based platform. Signed-off-by: Manuel Lauss To: Linux-MIPS Cc: Linux-serial Patchwork: https://patchwork.linux-mips.org/patch/1461/ Signed-off-by: Ralf Baechle This one depends on a previous patch (which removes SOC_AU1X00 and changes MACH_ALCHEMY) to apply cleanly (and then actually work), so I'd love for this to go in via the mips tree. diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c index f9e5622..c233d64 100644 --- a/arch/mips/alchemy/common/platform.c +++ b/arch/mips/alchemy/common/platform.c @@ -33,7 +33,6 @@ } static struct plat_serial8250_port au1x00_uart_data[] = { -#if defined(CONFIG_SERIAL_8250_AU1X00) #if defined(CONFIG_SOC_AU1000) PORT(UART0_PHYS_ADDR, AU1000_UART0_INT), PORT(UART1_PHYS_ADDR, AU1000_UART1_INT), @@ -54,7 +53,6 @@ static struct plat_serial8250_port au1x00_uart_data[] = { PORT(UART0_PHYS_ADDR, AU1200_UART0_INT), PORT(UART1_PHYS_ADDR, AU1200_UART1_INT), #endif -#endif /* CONFIG_SERIAL_8250_AU1X00 */ { }, }; diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 891e1dd..09ef570 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -302,7 +302,7 @@ static const struct serial8250_config uart_config[] = { }, }; -#if defined (CONFIG_SERIAL_8250_AU1X00) +#if defined(CONFIG_MIPS_ALCHEMY) /* Au1x00 UART hardware has a weird register layout */ static const u8 au_io_in_map[] = { @@ -422,7 +422,6 @@ static unsigned int mem32_serial_in(struct uart_port *p, int offset) return readl(p->membase + offset); } -#ifdef CONFIG_SERIAL_8250_AU1X00 static unsigned int au_serial_in(struct uart_port *p, int offset) { offset = map_8250_in_reg(p, offset) << p->regshift; @@ -434,7 +433,6 @@ static void au_serial_out(struct uart_port *p, int offset, int value) offset = map_8250_out_reg(p, offset) << p->regshift; __raw_writel(value, p->membase + offset); } -#endif static unsigned int tsi_serial_in(struct uart_port *p, int offset) { @@ -503,12 +501,11 @@ static void set_io_from_upio(struct uart_port *p) p->serial_out = mem32_serial_out; break; -#ifdef CONFIG_SERIAL_8250_AU1X00 case UPIO_AU: p->serial_in = au_serial_in; p->serial_out = au_serial_out; break; -#endif + case UPIO_TSI: p->serial_in = tsi_serial_in; p->serial_out = tsi_serial_out; @@ -535,9 +532,7 @@ serial_out_sync(struct uart_8250_port *up, int offset, int value) switch (p->iotype) { case UPIO_MEM: case UPIO_MEM32: -#ifdef CONFIG_SERIAL_8250_AU1X00 case UPIO_AU: -#endif case UPIO_DWAPB: p->serial_out(p, offset, value); p->serial_in(p, UART_LCR); /* safe, no side-effects */ @@ -573,7 +568,7 @@ static inline void _serial_dl_write(struct uart_8250_port *up, int value) serial_outp(up, UART_DLM, value >> 8 & 0xff); } -#if defined(CONFIG_SERIAL_8250_AU1X00) +#if defined(CONFIG_MIPS_ALCHEMY) /* Au1x00 haven't got a standard divisor latch */ static int serial_dl_read(struct uart_8250_port *up) { @@ -2596,11 +2591,9 @@ static void serial8250_config_port(struct uart_port *port, int flags) if (flags & UART_CONFIG_TYPE) autoconfig(up, probeflags); -#ifdef CONFIG_SERIAL_8250_AU1X00 /* if access method is AU, it is a 16550 with a quirk */ if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU) up->bugs |= UART_BUG_NOMSR; -#endif if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ) autoconfig_irq(up); diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 1acc7b3..e437ce8 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -258,14 +258,6 @@ config SERIAL_8250_ACORN system, say Y to this option. The driver can handle 1, 2, or 3 port cards. If unsure, say N. -config SERIAL_8250_AU1X00 - bool "Au1x00 serial port support" - depends on SERIAL_8250 != n && MIPS_ALCHEMY - help - If you have an Au1x00 SOC based board and want to use the serial port, - say Y to this option. The driver can handle up to 4 serial ports, - depending on the SOC. If unsure, say N. - config SERIAL_8250_RM9K bool "Support for MIPS RM9xxx integrated serial port" depends on SERIAL_8250 != n && SERIAL_RM9000 -- cgit v0.10.2 From f66736532a6bc593a2d7cda68835a79c23836f1b Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Wed, 21 Jul 2010 14:30:50 +0200 Subject: MIPS: au1000_eth: Get ethernet address from platform_data au1000_eth uses firmware calls to get a valid MAC address, and changes it depending on platform device id. This patch moves this logic out of the driver into the platform device registration part, where boards with supported chips can use whatever firmware interface they need; the default implementation maintains compatibility with existing, YAMON-based firmware. Tested-by: Wolfgang Grandegger Acked-by: Florian Fainelli Signed-off-by: Manuel Lauss To: Linux-MIPS Cc: netdev@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1481/ Acked-by: David S. Miller Signed-off-by: Ralf Baechle diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c index c233d64..1dc55ee 100644 --- a/arch/mips/alchemy/common/platform.c +++ b/arch/mips/alchemy/common/platform.c @@ -12,6 +12,7 @@ */ #include +#include #include #include #include @@ -21,6 +22,8 @@ #include #include +#include + #define PORT(_base, _irq) \ { \ .mapbase = _base, \ @@ -434,17 +437,27 @@ static int __init au1xxx_platform_init(void) { unsigned int uartclk = get_au1x00_uart_baud_base() * 16; int err, i; + unsigned char ethaddr[6]; /* Fill up uartclk. */ for (i = 0; au1x00_uart_data[i].flags; i++) au1x00_uart_data[i].uartclk = uartclk; + /* use firmware-provided mac addr if available and necessary */ + i = prom_get_ethernet_addr(ethaddr); + if (!i && !is_valid_ether_addr(au1xxx_eth0_platform_data.mac)) + memcpy(au1xxx_eth0_platform_data.mac, ethaddr, 6); + err = platform_add_devices(au1xxx_platform_devices, ARRAY_SIZE(au1xxx_platform_devices)); #ifndef CONFIG_SOC_AU1100 + ethaddr[5] += 1; /* next addr for 2nd MAC */ + if (!i && !is_valid_ether_addr(au1xxx_eth1_platform_data.mac)) + memcpy(au1xxx_eth1_platform_data.mac, ethaddr, 6); + /* Register second MAC if enabled in pinfunc */ if (!err && !(au_readl(SYS_PINFUNC) & (u32)SYS_PF_NI2)) - platform_device_register(&au1xxx_eth1_device); + err = platform_device_register(&au1xxx_eth1_device); #endif return err; diff --git a/arch/mips/include/asm/mach-au1x00/au1xxx_eth.h b/arch/mips/include/asm/mach-au1x00/au1xxx_eth.h index bae9b75..49dc8d9 100644 --- a/arch/mips/include/asm/mach-au1x00/au1xxx_eth.h +++ b/arch/mips/include/asm/mach-au1x00/au1xxx_eth.h @@ -9,6 +9,7 @@ struct au1000_eth_platform_data { int phy_addr; int phy_busid; int phy_irq; + char mac[6]; }; void __init au1xxx_override_eth_cfg(unsigned port, diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index ece6128..17e7e27 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -104,14 +104,6 @@ MODULE_VERSION(DRV_VERSION); * complete immediately. */ -/* These addresses are only used if yamon doesn't tell us what - * the mac address is, and the mac address is not passed on the - * command line. - */ -static unsigned char au1000_mac_addr[6] __devinitdata = { - 0x00, 0x50, 0xc2, 0x0c, 0x30, 0x00 -}; - struct au1000_private *au_macs[NUM_ETH_INTERFACES]; /* @@ -1002,7 +994,6 @@ static int __devinit au1000_probe(struct platform_device *pdev) db_dest_t *pDB, *pDBfree; int irq, i, err = 0; struct resource *base, *macen; - char ethaddr[6]; base = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!base) { @@ -1079,24 +1070,13 @@ static int __devinit au1000_probe(struct platform_device *pdev) } aup->mac_id = pdev->id; - if (pdev->id == 0) { - if (prom_get_ethernet_addr(ethaddr) == 0) - memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr)); - else { - netdev_info(dev, "No MAC address found\n"); - /* Use the hard coded MAC addresses */ - } - + if (pdev->id == 0) au1000_setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR); - } else if (pdev->id == 1) + else if (pdev->id == 1) au1000_setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR); - /* - * Assign to the Ethernet ports two consecutive MAC addresses - * to match those that are printed on their stickers - */ - memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr)); - dev->dev_addr[5] += pdev->id; + /* set a random MAC now in case platform_data doesn't provide one */ + random_ether_addr(dev->dev_addr); *aup->enable = 0; aup->mac_enabled = 0; @@ -1106,6 +1086,9 @@ static int __devinit au1000_probe(struct platform_device *pdev) dev_info(&pdev->dev, "no platform_data passed, PHY search on MAC0\n"); aup->phy1_search_mac0 = 1; } else { + if (is_valid_ether_addr(pd->mac)) + memcpy(dev->dev_addr, pd->mac, 6); + aup->phy_static_config = pd->phy_static_config; aup->phy_search_highest_addr = pd->phy_search_highest_addr; aup->phy1_search_mac0 = pd->phy1_search_mac0; -- cgit v0.10.2 From cb8f55b9207df96ccc332748eb3d154cd2e8014f Mon Sep 17 00:00:00 2001 From: Wolfgang Grandegger Date: Thu, 15 Jul 2010 11:21:23 +0200 Subject: MIPS: Alchemy: Add basic support for the GPR board From: Wolfgang Grandegger Add basic support for the General Purpose Router (GPR) board from Trapeze ITS. Signed-off-by: Wolfgang Grandegger To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1460/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/alchemy/Kconfig b/arch/mips/alchemy/Kconfig index 1179c4d..2ccfd4a 100644 --- a/arch/mips/alchemy/Kconfig +++ b/arch/mips/alchemy/Kconfig @@ -128,6 +128,15 @@ config MIPS_XXS1500 select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_HAS_EARLY_PRINTK +config MIPS_GPR + bool "Trapeze ITS GPR board" + select SOC_AU1550 + select HW_HAS_PCI + select DMA_NONCOHERENT + select MIPS_DISABLE_OBSOLETE_IDE + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_HAS_EARLY_PRINTK + endchoice config SOC_AU1000 diff --git a/arch/mips/alchemy/Platform b/arch/mips/alchemy/Platform index 0bf2b09..96e9e41 100644 --- a/arch/mips/alchemy/Platform +++ b/arch/mips/alchemy/Platform @@ -100,6 +100,11 @@ load-$(CONFIG_MIPS_MTX1) += 0xffffffff80100000 platform-$(CONFIG_MIPS_XXS1500) += alchemy/xxs1500/ load-$(CONFIG_MIPS_XXS1500) += 0xffffffff80100000 +# +# Trapeze ITS GRP board +# +platform-$(CONFIG_MIPS_GPR) += alchemy/gpr/ +load-$(CONFIG_MIPS_GPR) += 0xffffffff80100000 # boards can specify their own in one of their include dirs. # If they do, placing this line here at the end will make sure the diff --git a/arch/mips/alchemy/gpr/Makefile b/arch/mips/alchemy/gpr/Makefile new file mode 100644 index 0000000..cb73fe2 --- /dev/null +++ b/arch/mips/alchemy/gpr/Makefile @@ -0,0 +1,8 @@ +# +# Copyright 2003 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# +# Makefile for Trapeze ITS GPR board. +# + +obj-y += board_setup.o init.o platform.o diff --git a/arch/mips/alchemy/gpr/board_setup.c b/arch/mips/alchemy/gpr/board_setup.c new file mode 100644 index 0000000..ad2e3f1 --- /dev/null +++ b/arch/mips/alchemy/gpr/board_setup.c @@ -0,0 +1,93 @@ +/* + * Copyright 2010 Wolfgang Grandegger + * + * Copyright 2000-2003, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define UART1_ADDR KSEG1ADDR(UART1_PHYS_ADDR) +#define UART3_ADDR KSEG1ADDR(UART3_PHYS_ADDR) + +char irq_tab_alchemy[][5] __initdata = { + [0] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, 0xff, 0xff }, +}; + +static void gpr_reset(char *c) +{ + /* switch System-LED to orange (red# and green# on) */ + alchemy_gpio_direction_output(4, 0); + alchemy_gpio_direction_output(5, 0); + + /* trigger watchdog to reset board in 200ms */ + printk(KERN_EMERG "Triggering watchdog soft reset...\n"); + raw_local_irq_disable(); + alchemy_gpio_direction_output(1, 0); + udelay(1); + alchemy_gpio_set_value(1, 1); + while (1) + cpu_wait(); +} + +static void gpr_power_off(void) +{ + while (1) + cpu_wait(); +} + +void __init board_setup(void) +{ + printk(KERN_INFO "Tarpeze ITS GPR board\n"); + + pm_power_off = gpr_power_off; + _machine_halt = gpr_power_off; + _machine_restart = gpr_reset; + + /* Enable UART3 */ + au_writel(0x1, UART3_ADDR + UART_MOD_CNTRL);/* clock enable (CE) */ + au_writel(0x3, UART3_ADDR + UART_MOD_CNTRL); /* CE and "enable" */ + /* Enable UART1 */ + au_writel(0x1, UART1_ADDR + UART_MOD_CNTRL); /* clock enable (CE) */ + au_writel(0x3, UART1_ADDR + UART_MOD_CNTRL); /* CE and "enable" */ + + /* Take away Reset of UMTS-card */ + alchemy_gpio_direction_output(215, 1); + +#ifdef CONFIG_PCI +#if defined(__MIPSEB__) + au_writel(0xf | (2 << 6) | (1 << 4), Au1500_PCI_CFG); +#else + au_writel(0xf, Au1500_PCI_CFG); +#endif +#endif +} diff --git a/arch/mips/alchemy/gpr/init.c b/arch/mips/alchemy/gpr/init.c new file mode 100644 index 0000000..f044f4c --- /dev/null +++ b/arch/mips/alchemy/gpr/init.c @@ -0,0 +1,63 @@ +/* + * Copyright 2010 Wolfgang Grandegger + * + * Copyright 2003, 2008 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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. + */ + +#include +#include + +#include +#include + +#include + +const char *get_system_type(void) +{ + return "GPR"; +} + +void __init prom_init(void) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = fw_arg0; + prom_argv = (char **)fw_arg1; + prom_envp = (char **)fw_arg2; + + prom_init_cmdline(); + + memsize_str = prom_getenv("memsize"); + if (!memsize_str) + memsize = 0x04000000; + else + strict_strtoul(memsize_str, 0, &memsize); + add_memory_region(0, memsize, BOOT_MEM_RAM); +} + +void prom_putchar(unsigned char c) +{ + alchemy_uart_putchar(UART0_PHYS_ADDR, c); +} diff --git a/arch/mips/alchemy/gpr/platform.c b/arch/mips/alchemy/gpr/platform.c new file mode 100644 index 0000000..14b4662 --- /dev/null +++ b/arch/mips/alchemy/gpr/platform.c @@ -0,0 +1,183 @@ +/* + * GPR board platform device registration + * + * Copyright (C) 2010 Wolfgang Grandegger + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * Watchdog + */ +static struct resource gpr_wdt_resource[] = { + [0] = { + .start = 1, + .end = 1, + .name = "gpr-adm6320-wdt", + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device gpr_wdt_device = { + .name = "adm6320-wdt", + .id = 0, + .num_resources = ARRAY_SIZE(gpr_wdt_resource), + .resource = gpr_wdt_resource, +}; + +/* + * FLASH + * + * 0x00000000-0x00200000 : "kernel" + * 0x00200000-0x00a00000 : "rootfs" + * 0x01d00000-0x01f00000 : "config" + * 0x01c00000-0x01d00000 : "yamon" + * 0x01d00000-0x01d40000 : "yamon env vars" + * 0x00000000-0x00a00000 : "kernel+rootfs" + */ +static struct mtd_partition gpr_mtd_partitions[] = { + { + .name = "kernel", + .size = 0x00200000, + .offset = 0, + }, + { + .name = "rootfs", + .size = 0x00800000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, + }, + { + .name = "config", + .size = 0x00200000, + .offset = 0x01d00000, + }, + { + .name = "yamon", + .size = 0x00100000, + .offset = 0x01c00000, + }, + { + .name = "yamon env vars", + .size = 0x00040000, + .offset = MTDPART_OFS_APPEND, + }, + { + .name = "kernel+rootfs", + .size = 0x00a00000, + .offset = 0, + }, +}; + +static struct physmap_flash_data gpr_flash_data = { + .width = 4, + .nr_parts = ARRAY_SIZE(gpr_mtd_partitions), + .parts = gpr_mtd_partitions, +}; + +static struct resource gpr_mtd_resource = { + .start = 0x1e000000, + .end = 0x1fffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device gpr_mtd_device = { + .name = "physmap-flash", + .dev = { + .platform_data = &gpr_flash_data, + }, + .num_resources = 1, + .resource = &gpr_mtd_resource, +}; + +/* + * LEDs + */ +static struct gpio_led gpr_gpio_leds[] = { + { /* green */ + .name = "gpr:green", + .gpio = 4, + .active_low = 1, + }, + { /* red */ + .name = "gpr:red", + .gpio = 5, + .active_low = 1, + } +}; + +static struct gpio_led_platform_data gpr_led_data = { + .num_leds = ARRAY_SIZE(gpr_gpio_leds), + .leds = gpr_gpio_leds, +}; + +static struct platform_device gpr_led_devices = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &gpr_led_data, + } +}; + +/* + * I2C + */ +static struct i2c_gpio_platform_data gpr_i2c_data = { + .sda_pin = 209, + .sda_is_open_drain = 1, + .scl_pin = 210, + .scl_is_open_drain = 1, + .udelay = 2, /* ~100 kHz */ + .timeout = HZ, + }; + +static struct platform_device gpr_i2c_device = { + .name = "i2c-gpio", + .id = -1, + .dev.platform_data = &gpr_i2c_data, +}; + +static struct i2c_board_info gpr_i2c_info[] __initdata = { + { + I2C_BOARD_INFO("lm83", 0x18), + .type = "lm83" + } +}; + +static struct platform_device *gpr_devices[] __initdata = { + &gpr_wdt_device, + &gpr_mtd_device, + &gpr_i2c_device, + &gpr_led_devices, +}; + +static int __init gpr_dev_init(void) +{ + i2c_register_board_info(0, gpr_i2c_info, ARRAY_SIZE(gpr_i2c_info)); + + return platform_add_devices(gpr_devices, ARRAY_SIZE(gpr_devices)); +} +device_initcall(gpr_dev_init); diff --git a/arch/mips/configs/gpr_defconfig b/arch/mips/configs/gpr_defconfig new file mode 100644 index 0000000..17e2e62 --- /dev/null +++ b/arch/mips/configs/gpr_defconfig @@ -0,0 +1,2060 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.35-rc6 +# Fri Jul 23 19:28:52 2010 +# +CONFIG_MIPS=y + +# +# Machine selection +# +CONFIG_MIPS_ALCHEMY=y +# CONFIG_AR7 is not set +# CONFIG_BCM47XX is not set +# CONFIG_BCM63XX is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_LASAT is not set +# CONFIG_MACH_LOONGSON is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SIM is not set +# CONFIG_NEC_MARKEINS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_NXP_STB220 is not set +# CONFIG_NXP_STB225 is not set +# CONFIG_PNX8550_JBS is not set +# CONFIG_PNX8550_STB810 is not set +# CONFIG_PMC_MSP is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_POWERTV is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP28 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_SWARM is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SNI_RM is not set +# CONFIG_MACH_TX39XX is not set +# CONFIG_MACH_TX49XX is not set +# CONFIG_MIKROTIK_RB532 is not set +# CONFIG_WR_PPMC is not set +# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set +# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set +CONFIG_ALCHEMY_GPIOINT_AU1000=y +# CONFIG_ALCHEMY_GPIO_INDIRECT is not set +# CONFIG_MIPS_MTX1 is not set +# CONFIG_MIPS_BOSPORUS is not set +# CONFIG_MIPS_DB1000 is not set +# CONFIG_MIPS_DB1100 is not set +# CONFIG_MIPS_DB1200 is not set +# CONFIG_MIPS_DB1500 is not set +# CONFIG_MIPS_DB1550 is not set +# CONFIG_MIPS_MIRAGE is not set +# CONFIG_MIPS_PB1000 is not set +# CONFIG_MIPS_PB1100 is not set +# CONFIG_MIPS_PB1200 is not set +# CONFIG_MIPS_PB1500 is not set +# CONFIG_MIPS_PB1550 is not set +# CONFIG_MIPS_XXS1500 is not set +CONFIG_MIPS_GPR=y +CONFIG_SOC_AU1550=y +CONFIG_LOONGSON_UART_BASE=y +# CONFIG_LOONGSON_MC146818 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_SUPPORTS_OPROFILE=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_CEVT_R4K_LIB=y +CONFIG_CSRC_R4K_LIB=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_MIPS_DISABLE_OBSOLETE_IDE=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_GPIO=y +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 + +# +# CPU selection +# +# CONFIG_CPU_LOONGSON2E is not set +# CONFIG_CPU_LOONGSON2F is not set +CONFIG_CPU_MIPS32_R1=y +# CONFIG_CPU_MIPS32_R2 is not set +# CONFIG_CPU_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R5500 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_CAVIUM_OCTEON is not set +CONFIG_SYS_SUPPORTS_ZBOOT=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_CPU_MIPS32=y +CONFIG_CPU_MIPSR1=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_HARDWARE_WATCHPOINTS=y + +# +# Kernel type +# +CONFIG_32BIT=y +# CONFIG_64BIT is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_32KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_MIPS_MT_DISABLED=y +# CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_MT_SMTC is not set +CONFIG_64BIT_PHYS_ADDR=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_256 is not set +# CONFIG_HZ_1000 is not set +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=250 +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +# CONFIG_KEXEC is not set +CONFIG_SECCOMP=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_BZIP2=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_BZIP2 is not set +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_TINY_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_CGROUPS is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +CONFIG_RELAY=y +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EMBEDDED=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_PCSPKR_PLATFORM=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y + +# +# Kernel Performance Events And Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +# CONFIG_OPROFILE is not set +CONFIG_HAVE_OPROFILE=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_INLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +# CONFIG_FREEZER is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_HW_HAS_PCI=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_IOV is not set +CONFIG_MMU=y +# CONFIG_PCCARD is not set +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set +CONFIG_BINFMT_MISC=m +CONFIG_TRAD_SIGNALS=y + +# +# Power management options +# +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_PM is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +# CONFIG_NF_CONNTRACK is not set +# CONFIG_NETFILTER_TPROXY is not set +CONFIG_NETFILTER_XTABLES=m + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=m + +# +# Xtables targets +# +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m +# CONFIG_NETFILTER_XT_TARGET_LED is not set +CONFIG_NETFILTER_XT_TARGET_MARK=m +# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +# CONFIG_NETFILTER_XT_TARGET_TEE is not set +# CONFIG_NETFILTER_XT_TARGET_TRACE is not set +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set + +# +# Xtables matches +# +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set +CONFIG_NETFILTER_XT_MATCH_HL=m +# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +# CONFIG_NETFILTER_XT_MATCH_OSF is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +CONFIG_NETFILTER_XT_MATCH_REALM=m +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +# CONFIG_NETFILTER_XT_MATCH_TIME is not set +# CONFIG_NETFILTER_XT_MATCH_U32 is not set +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_AH_ESP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +# CONFIG_IP_VS_PROTO_SCTP is not set + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m + +# +# IP: Netfilter Configuration +# +# CONFIG_NF_DEFRAG_IPV4 is not set +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# DECnet: Netfilter Configuration +# +CONFIG_DECNET_NF_GRABULATOR=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m +# CONFIG_BRIDGE_EBT_NFLOG is not set +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP_CCID2_DEBUG is not set +CONFIG_IP_DCCP_CCID3=y +# CONFIG_IP_DCCP_CCID3_DEBUG is not set +CONFIG_IP_DCCP_CCID3_RTO=100 +CONFIG_IP_DCCP_TFRC_LIB=y +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y +# CONFIG_RDS is not set +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=y +CONFIG_ATM_CLIP=y +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +# CONFIG_L2TP is not set +CONFIG_STP=m +CONFIG_BRIDGE=m +CONFIG_BRIDGE_IGMP_SNOOPING=y +# CONFIG_NET_DSA is not set +CONFIG_VLAN_8021Q=m +# CONFIG_VLAN_8021Q_GVRP is not set +CONFIG_DECNET=m +# CONFIG_DECNET_ROUTER is not set +CONFIG_LLC=m +CONFIG_LLC2=m +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +CONFIG_X25=m +CONFIG_LAPB=m +CONFIG_ECONET=m +CONFIG_ECONET_AUNUDP=y +CONFIG_ECONET_NATIVE=y +CONFIG_WAN_ROUTER=m +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +# CONFIG_NET_SCH_MULTIQ is not set +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +# CONFIG_NET_SCH_DRR is not set +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +# CONFIG_CLS_U32_PERF is not set +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +# CONFIG_NET_CLS_FLOW is not set +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +# CONFIG_NET_ACT_GACT is not set +# CONFIG_NET_ACT_MIRRED is not set +# CONFIG_NET_ACT_IPT is not set +# CONFIG_NET_ACT_NAT is not set +# CONFIG_NET_ACT_PEDIT is not set +# CONFIG_NET_ACT_SIMP is not set +# CONFIG_NET_ACT_SKBEDIT is not set +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +CONFIG_HAMRADIO=y + +# +# Packet Radio protocols +# +CONFIG_AX25=m +# CONFIG_AX25_DAMA_SLAVE is not set +CONFIG_NETROM=m +CONFIG_ROSE=m + +# +# AX.25 network device drivers +# +CONFIG_MKISS=m +CONFIG_6PACK=m +CONFIG_BPQETHER=m +CONFIG_BAYCOM_SER_FDX=m +CONFIG_BAYCOM_SER_HDX=m +CONFIG_YAM=m +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_CFG80211=y +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_CFG80211_INTERNAL_REGDB is not set +CONFIG_CFG80211_WEXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +# CONFIG_LIB80211 is not set +CONFIG_MAC80211=y +CONFIG_MAC80211_HAS_RC=y +# CONFIG_MAC80211_RC_PID is not set +CONFIG_MAC80211_RC_MINSTREL=y +# CONFIG_MAC80211_RC_DEFAULT_PID is not set +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel" +# CONFIG_MAC80211_MESH is not set +CONFIG_MAC80211_LEDS=y +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_RAM=m +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +# CONFIG_MTD_PCI is not set +# CONFIG_MTD_GPIO_ADDR is not set +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set + +# +# DRBD disabled because PROC_FS, INET or CONNECTOR not selected +# +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=65536 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_MISC_DEVICES=y +# CONFIG_AD525X_DPOT is not set +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +CONFIG_TIFM_CORE=m +CONFIG_TIFM_7XX1=m +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_ISL29003 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_DS1682 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_CB710_CORE is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=m +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=m +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +CONFIG_SCSI_NETLINK=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=m +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +CONFIG_SCSI_LOGGING=y +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m +CONFIG_SCSI_SAS_LIBSAS=m +CONFIG_SCSI_SAS_HOST_SMP=y +# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# You can enable one or both FireWire driver stacks. +# + +# +# The newer stack is recommended. +# +# CONFIG_FIREWIRE is not set +# CONFIG_IEEE1394 is not set +# CONFIG_I2O is not set +CONFIG_NETDEVICES=y +# CONFIG_IFB is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_ARCNET is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +CONFIG_MIPS_AU1X00_ENET=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_ETHOC is not set +# CONFIG_SMSC911X is not set +# CONFIG_DNET is not set +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_NET_PCI is not set +# CONFIG_B44 is not set +# CONFIG_KS8842 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_ATL2 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_TR is not set +CONFIG_WLAN=y +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_ATMEL is not set +# CONFIG_AT76C50X_USB is not set +# CONFIG_PRISM54 is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_RTL8180 is not set +# CONFIG_RTL8187 is not set +# CONFIG_ADM8211 is not set +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_MWL8K is not set +CONFIG_ATH_COMMON=y +CONFIG_ATH_DEBUG=y +CONFIG_ATH5K=y +CONFIG_ATH5K_DEBUG=y +# CONFIG_ATH9K is not set +# CONFIG_ATH9K_HTC is not set +# CONFIG_AR9170_USB is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_HOSTAP is not set +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +# CONFIG_IWLWIFI is not set +# CONFIG_LIBERTAS is not set +# CONFIG_HERMES is not set +# CONFIG_P54_COMMON is not set +# CONFIG_RT2X00 is not set +# CONFIG_WL12XX is not set +# CONFIG_ZD1211RW is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set +CONFIG_WAN=y +CONFIG_LANMEDIA=m +CONFIG_HDLC=m +CONFIG_HDLC_RAW=m +CONFIG_HDLC_RAW_ETH=m +CONFIG_HDLC_CISCO=m +CONFIG_HDLC_FR=m +CONFIG_HDLC_PPP=m +CONFIG_HDLC_X25=m +CONFIG_PCI200SYN=m +CONFIG_WANXL=m +# CONFIG_PC300TOO is not set +CONFIG_FARSYNC=m +CONFIG_DSCC4=m +CONFIG_DSCC4_PCISYNC=y +CONFIG_DSCC4_PCI_RST=y +CONFIG_DLCI=m +CONFIG_DLCI_MAX=8 +CONFIG_WAN_ROUTER_DRIVERS=m +CONFIG_CYCLADES_SYNC=m +CONFIG_CYCLOMX_X25=y +CONFIG_LAPBETHER=m +CONFIG_X25_ASY=m +CONFIG_ATM_DRIVERS=y +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +CONFIG_ATM_ZATM=m +# CONFIG_ATM_ZATM_DEBUG is not set +CONFIG_ATM_NICSTAR=m +# CONFIG_ATM_NICSTAR_USE_SUNI is not set +# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +CONFIG_ATM_IA=m +# CONFIG_ATM_IA_DEBUG is not set +CONFIG_ATM_FORE200E=m +# CONFIG_ATM_FORE200E_USE_TASKLET is not set +CONFIG_ATM_FORE200E_TX_RETRY=16 +CONFIG_ATM_FORE200E_DEBUG=0 +CONFIG_ATM_HE=m +CONFIG_ATM_HE_USE_SUNI=y +# CONFIG_ATM_SOLOS is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLHC=m +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y +CONFIG_NET_FC=y +CONFIG_NETCONSOLE=m +# CONFIG_NETCONSOLE_DYNAMIC is not set +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y +# CONFIG_VMXNET3 is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_NOZOMI is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_PCI is not set +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +# CONFIG_RAMOOPS is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_AU1550 is not set +CONFIG_I2C_GPIO=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_SPI is not set + +# +# PPS support +# +# CONFIG_PPS is not set +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# +# CONFIG_GPIO_IT8761E is not set +# CONFIG_GPIO_SCH is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# +# CONFIG_GPIO_CS5535 is not set +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_LANGWELL is not set +# CONFIG_GPIO_RDC321X is not set + +# +# SPI GPIO expanders: +# + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +CONFIG_SENSORS_LM83=y +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_LIS3_I2C is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_ALIM7101_WDT is not set + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +CONFIG_SSB=m +CONFIG_SSB_SPROM=y +CONFIG_SSB_PCIHOST_POSSIBLE=y +CONFIG_SSB_PCIHOST=y +# CONFIG_SSB_B43_PCI_BRIDGE is not set +# CONFIG_SSB_SILENT is not set +# CONFIG_SSB_DEBUG is not set +CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y +CONFIG_SSB_DRIVER_PCICORE=y +# CONFIG_SSB_DRIVER_MIPS is not set +CONFIG_MFD_SUPPORT=y +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_TC35892 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_TIMBERDALE is not set +# CONFIG_LPC_SCH is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGA_ARB is not set +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_GENERIC is not set +# CONFIG_BACKLIGHT_ADP8860 is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=m +# CONFIG_HID_PID is not set +CONFIG_USB_HIDDEV=y + +# +# USB HID Boot Protocol drivers +# +CONFIG_USB_KBD=m +CONFIG_USB_MOUSE=m + +# +# Special HID drivers +# +# CONFIG_HID_3M_PCT is not set +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CANDO is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EGALAX is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LOGITECH is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MOSART is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_QUANTA is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_ROCCAT_KONE is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_STANTUM is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +# CONFIG_USB_DEVICE_CLASS is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_XHCI_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_WHCI_HCD is not set +# CONFIG_USB_HWA_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +CONFIG_USB_LIBUSUAL=y + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=y +# CONFIG_USB_SERIAL_CONSOLE is not set +CONFIG_USB_EZUSB=y +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_CP210X is not set +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_FUNSOFT is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MOTOROLA is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_QCAUX is not set +# CONFIG_USB_SERIAL_QUALCOMM is not set +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_HP4X is not set +# CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_SIEMENS_MPI is not set +CONFIG_USB_SERIAL_SIERRAWIRELESS=y +# CONFIG_USB_SERIAL_SYMBOL is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OPTION is not set +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set +# CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_DEBUG is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_ATM is not set +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_UWB is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_GPIO_PLATFORM=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +CONFIG_LEDS_TRIGGERS=y + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_GPIO is not set +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FILE_LOCKING=y +# CONFIG_FSNOTIFY is not set +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY is not set +# CONFIG_INOTIFY_USER is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +CONFIG_JFFS2_RUBIN=y +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +# CONFIG_JFFS2_CMODE_FAVOURLZO is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFS_V4_1 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=y +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +CONFIG_RCU_CPU_STALL_DETECTOR=y +# CONFIG_LKDTM is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_EARLY_PRINTK=y +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs rw ip=auto" +# CONFIG_CMDLINE_OVERRIDE is not set +# CONFIG_SPINLOCK_TEST is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_DEFAULT_SECURITY_SELINUX is not set +# CONFIG_DEFAULT_SECURITY_SMACK is not set +# CONFIG_DEFAULT_SECURITY_TOMOYO is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=m +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_GF128MUL is not set +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_TEST=m + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_GHASH is not set +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=m +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_BLOWFISH=m +# CONFIG_CRYPTO_CAMELLIA is not set +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +CONFIG_CRYPTO_KHAZAD=m +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_TWOFISH_COMMON=m + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=m +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=m +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +# CONFIG_CRC_T10DIF is not set +CONFIG_CRC_ITU_T=m +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y -- cgit v0.10.2 From a894f14d7ebe9e278b496b1e653ae57f2eff514e Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 23 Jul 2010 10:43:45 -0700 Subject: MIPS: Octeon: Move MSI code out of octeon-irq.c. Put all the MSI code in one place (msi-octeon.c). This simplifies octeon-irq.c and gets rid of some ugly #ifdefs Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1484/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index c424cd1..f4b901a 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -10,8 +10,6 @@ #include #include -#include -#include static DEFINE_RAW_SPINLOCK(octeon_irq_ciu0_lock); static DEFINE_RAW_SPINLOCK(octeon_irq_ciu1_lock); @@ -528,90 +526,6 @@ static struct irq_chip octeon_irq_chip_ciu1 = { #endif }; -#ifdef CONFIG_PCI_MSI - -static DEFINE_RAW_SPINLOCK(octeon_irq_msi_lock); - -static void octeon_irq_msi_ack(unsigned int irq) -{ - if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) { - /* These chips have PCI */ - cvmx_write_csr(CVMX_NPI_NPI_MSI_RCV, - 1ull << (irq - OCTEON_IRQ_MSI_BIT0)); - } else { - /* - * These chips have PCIe. Thankfully the ACK doesn't - * need any locking. - */ - cvmx_write_csr(CVMX_PEXP_NPEI_MSI_RCV0, - 1ull << (irq - OCTEON_IRQ_MSI_BIT0)); - } -} - -static void octeon_irq_msi_eoi(unsigned int irq) -{ - /* Nothing needed */ -} - -static void octeon_irq_msi_enable(unsigned int irq) -{ - if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) { - /* - * Octeon PCI doesn't have the ability to mask/unmask - * MSI interrupts individually. Instead of - * masking/unmasking them in groups of 16, we simple - * assume MSI devices are well behaved. MSI - * interrupts are always enable and the ACK is assumed - * to be enough. - */ - } else { - /* These chips have PCIe. Note that we only support - * the first 64 MSI interrupts. Unfortunately all the - * MSI enables are in the same register. We use - * MSI0's lock to control access to them all. - */ - uint64_t en; - unsigned long flags; - raw_spin_lock_irqsave(&octeon_irq_msi_lock, flags); - en = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); - en |= 1ull << (irq - OCTEON_IRQ_MSI_BIT0); - cvmx_write_csr(CVMX_PEXP_NPEI_MSI_ENB0, en); - cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); - raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags); - } -} - -static void octeon_irq_msi_disable(unsigned int irq) -{ - if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) { - /* See comment in enable */ - } else { - /* - * These chips have PCIe. Note that we only support - * the first 64 MSI interrupts. Unfortunately all the - * MSI enables are in the same register. We use - * MSI0's lock to control access to them all. - */ - uint64_t en; - unsigned long flags; - raw_spin_lock_irqsave(&octeon_irq_msi_lock, flags); - en = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); - en &= ~(1ull << (irq - OCTEON_IRQ_MSI_BIT0)); - cvmx_write_csr(CVMX_PEXP_NPEI_MSI_ENB0, en); - cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); - raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags); - } -} - -static struct irq_chip octeon_irq_chip_msi = { - .name = "MSI", - .enable = octeon_irq_msi_enable, - .disable = octeon_irq_msi_disable, - .ack = octeon_irq_msi_ack, - .eoi = octeon_irq_msi_eoi, -}; -#endif - void __init arch_init_irq(void) { int irq; @@ -672,13 +586,6 @@ void __init arch_init_irq(void) set_irq_chip_and_handler(irq, chip1, handle_percpu_irq); } -#ifdef CONFIG_PCI_MSI - /* 152 - 215 PCI/PCIe MSI interrupts */ - for (irq = OCTEON_IRQ_MSI_BIT0; irq <= OCTEON_IRQ_MSI_BIT63; irq++) { - set_irq_chip_and_handler(irq, &octeon_irq_chip_msi, - handle_percpu_irq); - } -#endif set_c0_status(0x300 << 2); } diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c index 03742e6..1e31526 100644 --- a/arch/mips/pci/msi-octeon.c +++ b/arch/mips/pci/msi-octeon.c @@ -249,12 +249,99 @@ static irqreturn_t octeon_msi_interrupt(int cpl, void *dev_id) return IRQ_NONE; } +static DEFINE_RAW_SPINLOCK(octeon_irq_msi_lock); + +static void octeon_irq_msi_ack(unsigned int irq) +{ + if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) { + /* These chips have PCI */ + cvmx_write_csr(CVMX_NPI_NPI_MSI_RCV, + 1ull << (irq - OCTEON_IRQ_MSI_BIT0)); + } else { + /* + * These chips have PCIe. Thankfully the ACK doesn't + * need any locking. + */ + cvmx_write_csr(CVMX_PEXP_NPEI_MSI_RCV0, + 1ull << (irq - OCTEON_IRQ_MSI_BIT0)); + } +} + +static void octeon_irq_msi_eoi(unsigned int irq) +{ + /* Nothing needed */ +} + +static void octeon_irq_msi_enable(unsigned int irq) +{ + if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) { + /* + * Octeon PCI doesn't have the ability to mask/unmask + * MSI interrupts individually. Instead of + * masking/unmasking them in groups of 16, we simple + * assume MSI devices are well behaved. MSI + * interrupts are always enable and the ACK is assumed + * to be enough. + */ + } else { + /* These chips have PCIe. Note that we only support + * the first 64 MSI interrupts. Unfortunately all the + * MSI enables are in the same register. We use + * MSI0's lock to control access to them all. + */ + uint64_t en; + unsigned long flags; + raw_spin_lock_irqsave(&octeon_irq_msi_lock, flags); + en = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); + en |= 1ull << (irq - OCTEON_IRQ_MSI_BIT0); + cvmx_write_csr(CVMX_PEXP_NPEI_MSI_ENB0, en); + cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); + raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags); + } +} + +static void octeon_irq_msi_disable(unsigned int irq) +{ + if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) { + /* See comment in enable */ + } else { + /* + * These chips have PCIe. Note that we only support + * the first 64 MSI interrupts. Unfortunately all the + * MSI enables are in the same register. We use + * MSI0's lock to control access to them all. + */ + uint64_t en; + unsigned long flags; + raw_spin_lock_irqsave(&octeon_irq_msi_lock, flags); + en = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); + en &= ~(1ull << (irq - OCTEON_IRQ_MSI_BIT0)); + cvmx_write_csr(CVMX_PEXP_NPEI_MSI_ENB0, en); + cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); + raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags); + } +} + +static struct irq_chip octeon_irq_chip_msi = { + .name = "MSI", + .enable = octeon_irq_msi_enable, + .disable = octeon_irq_msi_disable, + .ack = octeon_irq_msi_ack, + .eoi = octeon_irq_msi_eoi, +}; /* * Initializes the MSI interrupt handling code */ -int octeon_msi_initialize(void) +static int __init octeon_msi_initialize(void) { + int irq; + + for (irq = OCTEON_IRQ_MSI_BIT0; irq <= OCTEON_IRQ_MSI_BIT63; irq++) { + set_irq_chip_and_handler(irq, &octeon_irq_chip_msi, + handle_percpu_irq); + } + if (octeon_has_feature(OCTEON_FEATURE_PCIE)) { if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt, IRQF_SHARED, @@ -284,5 +371,4 @@ int octeon_msi_initialize(void) } return 0; } - subsys_initcall(octeon_msi_initialize); -- cgit v0.10.2 From 5aae1fd4d41ea69da845e11d4766ab61666494ed Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 23 Jul 2010 10:43:46 -0700 Subject: MIPS: Octeon: Improve interrupt handling. The main change is to change most of the IRQs from handle_percpu_irq to handle_fasteoi_irq. This necessitates extracting all the .ack code to common functions that are not exposed to the irq core. The affinity code now acts more sanely, by doing round-robin distribution instead of broadcasting. Because of the change to handle_fasteoi_irq and affinity, some of the IRQs had to be split into separate groups with their own struct irq_chip to prevent undefined operations on specific IRQ lines. Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1485/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index f4b901a..8fb9fb6 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2004-2008 Cavium Networks + * Copyright (C) 2004-2008, 2009, 2010 Cavium Networks */ #include #include @@ -39,14 +39,14 @@ static void octeon_irq_core_ack(unsigned int irq) static void octeon_irq_core_eoi(unsigned int irq) { - struct irq_desc *desc = irq_desc + irq; + struct irq_desc *desc = irq_to_desc(irq); unsigned int bit = irq - OCTEON_IRQ_SW0; /* * If an IRQ is being processed while we are disabling it the * handler will attempt to unmask the interrupt after it has * been disabled. */ - if (desc->status & IRQ_DISABLED) + if ((unlikely(desc->status & IRQ_DISABLED))) return; /* * We don't need to disable IRQs to make these atomic since @@ -104,6 +104,29 @@ static struct irq_chip octeon_irq_chip_core = { static void octeon_irq_ciu0_ack(unsigned int irq) { + switch (irq) { + case OCTEON_IRQ_GMX_DRP0: + case OCTEON_IRQ_GMX_DRP1: + case OCTEON_IRQ_IPD_DRP: + case OCTEON_IRQ_KEY_ZERO: + case OCTEON_IRQ_TIMER0: + case OCTEON_IRQ_TIMER1: + case OCTEON_IRQ_TIMER2: + case OCTEON_IRQ_TIMER3: + { + int index = cvmx_get_core_num() * 2; + u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); + /* + * CIU timer type interrupts must be acknoleged by + * writing a '1' bit to their sum0 bit. + */ + cvmx_write_csr(CVMX_CIU_INTX_SUM0(index), mask); + break; + } + default: + break; + } + /* * In order to avoid any locking accessing the CIU, we * acknowledge CIU interrupts by disabling all of them. This @@ -128,8 +151,54 @@ static void octeon_irq_ciu0_eoi(unsigned int irq) set_c0_status(0x100 << 2); } +static int next_coreid_for_irq(struct irq_desc *desc) +{ + +#ifdef CONFIG_SMP + int coreid; + int weight = cpumask_weight(desc->affinity); + + if (weight > 1) { + int cpu = smp_processor_id(); + for (;;) { + cpu = cpumask_next(cpu, desc->affinity); + if (cpu >= nr_cpu_ids) { + cpu = -1; + continue; + } else if (cpumask_test_cpu(cpu, cpu_online_mask)) { + break; + } + } + coreid = octeon_coreid_for_cpu(cpu); + } else if (weight == 1) { + coreid = octeon_coreid_for_cpu(cpumask_first(desc->affinity)); + } else { + coreid = cvmx_get_core_num(); + } + return coreid; +#else + return cvmx_get_core_num(); +#endif +} + static void octeon_irq_ciu0_enable(unsigned int irq) { + struct irq_desc *desc = irq_to_desc(irq); + int coreid = next_coreid_for_irq(desc); + unsigned long flags; + uint64_t en0; + int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */ + + raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags); + en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); + en0 |= 1ull << bit; + cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0); + cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); + raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags); +} + +static void octeon_irq_ciu0_enable_mbox(unsigned int irq) +{ int coreid = cvmx_get_core_num(); unsigned long flags; uint64_t en0; @@ -165,63 +234,76 @@ static void octeon_irq_ciu0_disable(unsigned int irq) } /* - * Enable the irq on the current core for chips that have the EN*_W1{S,C} - * registers. + * Enable the irq on the next core in the affinity set for chips that + * have the EN*_W1{S,C} registers. */ static void octeon_irq_ciu0_enable_v2(unsigned int irq) { - int index = cvmx_get_core_num() * 2; + int index; u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); + struct irq_desc *desc = irq_to_desc(irq); - cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); + if ((desc->status & IRQ_DISABLED) == 0) { + index = next_coreid_for_irq(desc) * 2; + cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); + } } /* - * Disable the irq on the current core for chips that have the EN*_W1{S,C} - * registers. + * Enable the irq on the current CPU for chips that + * have the EN*_W1{S,C} registers. */ -static void octeon_irq_ciu0_ack_v2(unsigned int irq) +static void octeon_irq_ciu0_enable_mbox_v2(unsigned int irq) { - int index = cvmx_get_core_num() * 2; + int index; u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); - cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask); + index = cvmx_get_core_num() * 2; + cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); } /* - * CIU timer type interrupts must be acknoleged by writing a '1' bit - * to their sum0 bit. + * Disable the irq on the current core for chips that have the EN*_W1{S,C} + * registers. */ -static void octeon_irq_ciu0_timer_ack(unsigned int irq) +static void octeon_irq_ciu0_ack_v2(unsigned int irq) { int index = cvmx_get_core_num() * 2; - uint64_t mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); - cvmx_write_csr(CVMX_CIU_INTX_SUM0(index), mask); -} + u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); -static void octeon_irq_ciu0_timer_ack_v1(unsigned int irq) -{ - octeon_irq_ciu0_timer_ack(irq); - octeon_irq_ciu0_ack(irq); -} + switch (irq) { + case OCTEON_IRQ_GMX_DRP0: + case OCTEON_IRQ_GMX_DRP1: + case OCTEON_IRQ_IPD_DRP: + case OCTEON_IRQ_KEY_ZERO: + case OCTEON_IRQ_TIMER0: + case OCTEON_IRQ_TIMER1: + case OCTEON_IRQ_TIMER2: + case OCTEON_IRQ_TIMER3: + /* + * CIU timer type interrupts must be acknoleged by + * writing a '1' bit to their sum0 bit. + */ + cvmx_write_csr(CVMX_CIU_INTX_SUM0(index), mask); + break; + default: + break; + } -static void octeon_irq_ciu0_timer_ack_v2(unsigned int irq) -{ - octeon_irq_ciu0_timer_ack(irq); - octeon_irq_ciu0_ack_v2(irq); + cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask); } /* * Enable the irq on the current core for chips that have the EN*_W1{S,C} * registers. */ -static void octeon_irq_ciu0_eoi_v2(unsigned int irq) +static void octeon_irq_ciu0_eoi_mbox_v2(unsigned int irq) { - struct irq_desc *desc = irq_desc + irq; + struct irq_desc *desc = irq_to_desc(irq); int index = cvmx_get_core_num() * 2; u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); - if ((desc->status & IRQ_DISABLED) == 0) + if (likely((desc->status & IRQ_DISABLED) == 0)) cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); } @@ -244,18 +326,30 @@ static void octeon_irq_ciu0_disable_all_v2(unsigned int irq) static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *dest) { int cpu; + struct irq_desc *desc = irq_to_desc(irq); + int enable_one = (desc->status & IRQ_DISABLED) == 0; unsigned long flags; int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */ + /* + * For non-v2 CIU, we will allow only single CPU affinity. + * This removes the need to do locking in the .ack/.eoi + * functions. + */ + if (cpumask_weight(dest) != 1) + return -EINVAL; + raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags); for_each_online_cpu(cpu) { int coreid = octeon_coreid_for_cpu(cpu); uint64_t en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); - if (cpumask_test_cpu(cpu, dest)) + if (cpumask_test_cpu(cpu, dest) && enable_one) { + enable_one = 0; en0 |= 1ull << bit; - else + } else { en0 &= ~(1ull << bit); + } cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0); } /* @@ -277,13 +371,18 @@ static int octeon_irq_ciu0_set_affinity_v2(unsigned int irq, { int cpu; int index; + struct irq_desc *desc = irq_to_desc(irq); + int enable_one = (desc->status & IRQ_DISABLED) == 0; u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); + for_each_online_cpu(cpu) { index = octeon_coreid_for_cpu(cpu) * 2; - if (cpumask_test_cpu(cpu, dest)) + if (cpumask_test_cpu(cpu, dest) && enable_one) { + enable_one = 0; cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); - else + } else { cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask); + } } return 0; } @@ -296,8 +395,7 @@ static struct irq_chip octeon_irq_chip_ciu0_v2 = { .name = "CIU0", .enable = octeon_irq_ciu0_enable_v2, .disable = octeon_irq_ciu0_disable_all_v2, - .ack = octeon_irq_ciu0_ack_v2, - .eoi = octeon_irq_ciu0_eoi_v2, + .eoi = octeon_irq_ciu0_enable_v2, #ifdef CONFIG_SMP .set_affinity = octeon_irq_ciu0_set_affinity_v2, #endif @@ -307,36 +405,27 @@ static struct irq_chip octeon_irq_chip_ciu0 = { .name = "CIU0", .enable = octeon_irq_ciu0_enable, .disable = octeon_irq_ciu0_disable, - .ack = octeon_irq_ciu0_ack, .eoi = octeon_irq_ciu0_eoi, #ifdef CONFIG_SMP .set_affinity = octeon_irq_ciu0_set_affinity, #endif }; -static struct irq_chip octeon_irq_chip_ciu0_timer_v2 = { - .name = "CIU0-T", - .enable = octeon_irq_ciu0_enable_v2, - .disable = octeon_irq_ciu0_disable_all_v2, - .ack = octeon_irq_ciu0_timer_ack_v2, - .eoi = octeon_irq_ciu0_eoi_v2, -#ifdef CONFIG_SMP - .set_affinity = octeon_irq_ciu0_set_affinity_v2, -#endif +/* The mbox versions don't do any affinity or round-robin. */ +static struct irq_chip octeon_irq_chip_ciu0_mbox_v2 = { + .name = "CIU0-M", + .enable = octeon_irq_ciu0_enable_mbox_v2, + .disable = octeon_irq_ciu0_disable, + .eoi = octeon_irq_ciu0_eoi_mbox_v2, }; -static struct irq_chip octeon_irq_chip_ciu0_timer = { - .name = "CIU0-T", - .enable = octeon_irq_ciu0_enable, +static struct irq_chip octeon_irq_chip_ciu0_mbox = { + .name = "CIU0-M", + .enable = octeon_irq_ciu0_enable_mbox, .disable = octeon_irq_ciu0_disable, - .ack = octeon_irq_ciu0_timer_ack_v1, .eoi = octeon_irq_ciu0_eoi, -#ifdef CONFIG_SMP - .set_affinity = octeon_irq_ciu0_set_affinity, -#endif }; - static void octeon_irq_ciu1_ack(unsigned int irq) { /* @@ -363,7 +452,8 @@ static void octeon_irq_ciu1_eoi(unsigned int irq) static void octeon_irq_ciu1_enable(unsigned int irq) { - int coreid = cvmx_get_core_num(); + struct irq_desc *desc = irq_to_desc(irq); + int coreid = next_coreid_for_irq(desc); unsigned long flags; uint64_t en1; int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */ @@ -376,6 +466,25 @@ static void octeon_irq_ciu1_enable(unsigned int irq) raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags); } +/* + * Watchdog interrupts are special. They are associated with a single + * core, so we hardwire the affinity to that core. + */ +static void octeon_irq_ciu1_wd_enable(unsigned int irq) +{ + unsigned long flags; + uint64_t en1; + int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */ + int coreid = bit; + + raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags); + en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); + en1 |= 1ull << bit; + cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1); + cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); + raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags); +} + static void octeon_irq_ciu1_disable(unsigned int irq) { int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */ @@ -403,36 +512,43 @@ static void octeon_irq_ciu1_disable(unsigned int irq) */ static void octeon_irq_ciu1_enable_v2(unsigned int irq) { - int index = cvmx_get_core_num() * 2 + 1; + int index; u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0); + struct irq_desc *desc = irq_to_desc(irq); - cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask); + if ((desc->status & IRQ_DISABLED) == 0) { + index = next_coreid_for_irq(desc) * 2 + 1; + cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask); + } } /* - * Disable the irq on the current core for chips that have the EN*_W1{S,C} - * registers. + * Watchdog interrupts are special. They are associated with a single + * core, so we hardwire the affinity to that core. */ -static void octeon_irq_ciu1_ack_v2(unsigned int irq) +static void octeon_irq_ciu1_wd_enable_v2(unsigned int irq) { - int index = cvmx_get_core_num() * 2 + 1; + int index; + int coreid = irq - OCTEON_IRQ_WDOG0; u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0); + struct irq_desc *desc = irq_to_desc(irq); - cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask); + if ((desc->status & IRQ_DISABLED) == 0) { + index = coreid * 2 + 1; + cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask); + } } /* - * Enable the irq on the current core for chips that have the EN*_W1{S,C} + * Disable the irq on the current core for chips that have the EN*_W1{S,C} * registers. */ -static void octeon_irq_ciu1_eoi_v2(unsigned int irq) +static void octeon_irq_ciu1_ack_v2(unsigned int irq) { - struct irq_desc *desc = irq_desc + irq; int index = cvmx_get_core_num() * 2 + 1; u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0); - if ((desc->status & IRQ_DISABLED) == 0) - cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask); + cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask); } /* @@ -455,19 +571,30 @@ static int octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask *dest) { int cpu; + struct irq_desc *desc = irq_to_desc(irq); + int enable_one = (desc->status & IRQ_DISABLED) == 0; unsigned long flags; int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */ + /* + * For non-v2 CIU, we will allow only single CPU affinity. + * This removes the need to do locking in the .ack/.eoi + * functions. + */ + if (cpumask_weight(dest) != 1) + return -EINVAL; + raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags); for_each_online_cpu(cpu) { int coreid = octeon_coreid_for_cpu(cpu); uint64_t en1 = - cvmx_read_csr(CVMX_CIU_INTX_EN1 - (coreid * 2 + 1)); - if (cpumask_test_cpu(cpu, dest)) + cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); + if (cpumask_test_cpu(cpu, dest) && enable_one) { + enable_one = 0; en1 |= 1ull << bit; - else + } else { en1 &= ~(1ull << bit); + } cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1); } /* @@ -489,13 +616,17 @@ static int octeon_irq_ciu1_set_affinity_v2(unsigned int irq, { int cpu; int index; + struct irq_desc *desc = irq_to_desc(irq); + int enable_one = (desc->status & IRQ_DISABLED) == 0; u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0); for_each_online_cpu(cpu) { index = octeon_coreid_for_cpu(cpu) * 2 + 1; - if (cpumask_test_cpu(cpu, dest)) + if (cpumask_test_cpu(cpu, dest) && enable_one) { + enable_one = 0; cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask); - else + } else { cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask); + } } return 0; } @@ -505,11 +636,10 @@ static int octeon_irq_ciu1_set_affinity_v2(unsigned int irq, * Newer octeon chips have support for lockless CIU operation. */ static struct irq_chip octeon_irq_chip_ciu1_v2 = { - .name = "CIU0", + .name = "CIU1", .enable = octeon_irq_ciu1_enable_v2, .disable = octeon_irq_ciu1_disable_all_v2, - .ack = octeon_irq_ciu1_ack_v2, - .eoi = octeon_irq_ciu1_eoi_v2, + .eoi = octeon_irq_ciu1_enable_v2, #ifdef CONFIG_SMP .set_affinity = octeon_irq_ciu1_set_affinity_v2, #endif @@ -519,19 +649,36 @@ static struct irq_chip octeon_irq_chip_ciu1 = { .name = "CIU1", .enable = octeon_irq_ciu1_enable, .disable = octeon_irq_ciu1_disable, - .ack = octeon_irq_ciu1_ack, .eoi = octeon_irq_ciu1_eoi, #ifdef CONFIG_SMP .set_affinity = octeon_irq_ciu1_set_affinity, #endif }; +static struct irq_chip octeon_irq_chip_ciu1_wd_v2 = { + .name = "CIU1-W", + .enable = octeon_irq_ciu1_wd_enable_v2, + .disable = octeon_irq_ciu1_disable_all_v2, + .eoi = octeon_irq_ciu1_wd_enable_v2, +}; + +static struct irq_chip octeon_irq_chip_ciu1_wd = { + .name = "CIU1-W", + .enable = octeon_irq_ciu1_wd_enable, + .disable = octeon_irq_ciu1_disable, + .eoi = octeon_irq_ciu1_eoi, +}; + +static void (*octeon_ciu0_ack)(unsigned int); +static void (*octeon_ciu1_ack)(unsigned int); + void __init arch_init_irq(void) { - int irq; + unsigned int irq; struct irq_chip *chip0; - struct irq_chip *chip0_timer; + struct irq_chip *chip0_mbox; struct irq_chip *chip1; + struct irq_chip *chip1_wd; #ifdef CONFIG_SMP /* Set the default affinity to the boot cpu. */ @@ -545,13 +692,19 @@ void __init arch_init_irq(void) if (OCTEON_IS_MODEL(OCTEON_CN58XX_PASS2_X) || OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) || OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X)) { + octeon_ciu0_ack = octeon_irq_ciu0_ack_v2; + octeon_ciu1_ack = octeon_irq_ciu1_ack_v2; chip0 = &octeon_irq_chip_ciu0_v2; - chip0_timer = &octeon_irq_chip_ciu0_timer_v2; + chip0_mbox = &octeon_irq_chip_ciu0_mbox_v2; chip1 = &octeon_irq_chip_ciu1_v2; + chip1_wd = &octeon_irq_chip_ciu1_wd_v2; } else { + octeon_ciu0_ack = octeon_irq_ciu0_ack; + octeon_ciu1_ack = octeon_irq_ciu1_ack; chip0 = &octeon_irq_chip_ciu0; - chip0_timer = &octeon_irq_chip_ciu0_timer; + chip0_mbox = &octeon_irq_chip_ciu0_mbox; chip1 = &octeon_irq_chip_ciu1; + chip1_wd = &octeon_irq_chip_ciu1_wd; } /* 0 - 15 reserved for i8259 master and slave controller. */ @@ -565,26 +718,22 @@ void __init arch_init_irq(void) /* 24 - 87 CIU_INT_SUM0 */ for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_BOOTDMA; irq++) { switch (irq) { - case OCTEON_IRQ_GMX_DRP0: - case OCTEON_IRQ_GMX_DRP1: - case OCTEON_IRQ_IPD_DRP: - case OCTEON_IRQ_KEY_ZERO: - case OCTEON_IRQ_TIMER0: - case OCTEON_IRQ_TIMER1: - case OCTEON_IRQ_TIMER2: - case OCTEON_IRQ_TIMER3: - set_irq_chip_and_handler(irq, chip0_timer, handle_percpu_irq); + case OCTEON_IRQ_MBOX0: + case OCTEON_IRQ_MBOX1: + set_irq_chip_and_handler(irq, chip0_mbox, handle_percpu_irq); break; default: - set_irq_chip_and_handler(irq, chip0, handle_percpu_irq); + set_irq_chip_and_handler(irq, chip0, handle_fasteoi_irq); break; } } /* 88 - 151 CIU_INT_SUM1 */ - for (irq = OCTEON_IRQ_WDOG0; irq <= OCTEON_IRQ_RESERVED151; irq++) { - set_irq_chip_and_handler(irq, chip1, handle_percpu_irq); - } + for (irq = OCTEON_IRQ_WDOG0; irq <= OCTEON_IRQ_WDOG15; irq++) + set_irq_chip_and_handler(irq, chip1_wd, handle_fasteoi_irq); + + for (irq = OCTEON_IRQ_UART2; irq <= OCTEON_IRQ_RESERVED151; irq++) + set_irq_chip_and_handler(irq, chip1, handle_fasteoi_irq); set_c0_status(0x300 << 2); } @@ -600,6 +749,7 @@ asmlinkage void plat_irq_dispatch(void) unsigned long cop0_status; uint64_t ciu_en; uint64_t ciu_sum; + unsigned int irq; while (1) { cop0_cause = read_c0_cause(); @@ -611,18 +761,24 @@ asmlinkage void plat_irq_dispatch(void) ciu_sum = cvmx_read_csr(ciu_sum0_address); ciu_en = cvmx_read_csr(ciu_en0_address); ciu_sum &= ciu_en; - if (likely(ciu_sum)) - do_IRQ(fls64(ciu_sum) + OCTEON_IRQ_WORKQ0 - 1); - else + if (likely(ciu_sum)) { + irq = fls64(ciu_sum) + OCTEON_IRQ_WORKQ0 - 1; + octeon_ciu0_ack(irq); + do_IRQ(irq); + } else { spurious_interrupt(); + } } else if (unlikely(cop0_cause & STATUSF_IP3)) { ciu_sum = cvmx_read_csr(ciu_sum1_address); ciu_en = cvmx_read_csr(ciu_en1_address); ciu_sum &= ciu_en; - if (likely(ciu_sum)) - do_IRQ(fls64(ciu_sum) + OCTEON_IRQ_WDOG0 - 1); - else + if (likely(ciu_sum)) { + irq = fls64(ciu_sum) + OCTEON_IRQ_WDOG0 - 1; + octeon_ciu1_ack(irq); + do_IRQ(irq); + } else { spurious_interrupt(); + } } else if (likely(cop0_cause)) { do_IRQ(fls(cop0_cause) - 9 + MIPS_CPU_IRQ_BASE); } else { -- cgit v0.10.2 From 3508920f5811fcb8bdbf02943eb5ed531834bbc4 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 23 Jul 2010 10:43:47 -0700 Subject: MIPS: Octeon: Fix fixup_irqs for HOTPLUG_CPU The original version went behind the back of everything, leaving things in an inconsistent state. Now we use the irq_set_affinity() to do the work for us. This has the advantage that the IRQ core's view of the affinity stays consistent. Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1486/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index 8fb9fb6..ce7500c 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -788,54 +788,84 @@ asmlinkage void plat_irq_dispatch(void) } #ifdef CONFIG_HOTPLUG_CPU -static int is_irq_enabled_on_cpu(unsigned int irq, unsigned int cpu) -{ - unsigned int isset; - int coreid = octeon_coreid_for_cpu(cpu); - int bit = (irq < OCTEON_IRQ_WDOG0) ? - irq - OCTEON_IRQ_WORKQ0 : irq - OCTEON_IRQ_WDOG0; - if (irq < 64) { - isset = (cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)) & - (1ull << bit)) >> bit; - } else { - isset = (cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)) & - (1ull << bit)) >> bit; - } - return isset; -} void fixup_irqs(void) { - int irq; + int irq; + struct irq_desc *desc; + cpumask_t new_affinity; + unsigned long flags; + int do_set_affinity; + int cpu; + + cpu = smp_processor_id(); for (irq = OCTEON_IRQ_SW0; irq <= OCTEON_IRQ_TIMER; irq++) octeon_irq_core_disable_local(irq); - for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_GPIO15; irq++) { - if (is_irq_enabled_on_cpu(irq, smp_processor_id())) { - /* ciu irq migrates to next cpu */ - octeon_irq_chip_ciu0.disable(irq); - octeon_irq_ciu0_set_affinity(irq, &cpu_online_map); - } - } + for (irq = OCTEON_IRQ_WORKQ0; irq < OCTEON_IRQ_LAST; irq++) { + desc = irq_to_desc(irq); + switch (irq) { + case OCTEON_IRQ_MBOX0: + case OCTEON_IRQ_MBOX1: + /* The eoi function will disable them on this CPU. */ + desc->chip->eoi(irq); + break; + case OCTEON_IRQ_WDOG0: + case OCTEON_IRQ_WDOG1: + case OCTEON_IRQ_WDOG2: + case OCTEON_IRQ_WDOG3: + case OCTEON_IRQ_WDOG4: + case OCTEON_IRQ_WDOG5: + case OCTEON_IRQ_WDOG6: + case OCTEON_IRQ_WDOG7: + case OCTEON_IRQ_WDOG8: + case OCTEON_IRQ_WDOG9: + case OCTEON_IRQ_WDOG10: + case OCTEON_IRQ_WDOG11: + case OCTEON_IRQ_WDOG12: + case OCTEON_IRQ_WDOG13: + case OCTEON_IRQ_WDOG14: + case OCTEON_IRQ_WDOG15: + /* + * These have special per CPU semantics and + * are handled in the watchdog driver. + */ + break; + default: + raw_spin_lock_irqsave(&desc->lock, flags); + /* + * If this irq has an action, it is in use and + * must be migrated if it has affinity to this + * cpu. + */ + if (desc->action && cpumask_test_cpu(cpu, desc->affinity)) { + if (cpumask_weight(desc->affinity) > 1) { + /* + * It has multi CPU affinity, + * just remove this CPU from + * the affinity set. + */ + cpumask_copy(&new_affinity, desc->affinity); + cpumask_clear_cpu(cpu, &new_affinity); + } else { + /* + * Otherwise, put it on lowest + * numbered online CPU. + */ + cpumask_clear(&new_affinity); + cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity); + } + do_set_affinity = 1; + } else { + do_set_affinity = 0; + } + raw_spin_unlock_irqrestore(&desc->lock, flags); -#if 0 - for (irq = OCTEON_IRQ_MBOX0; irq <= OCTEON_IRQ_MBOX1; irq++) - octeon_irq_mailbox_mask(irq); -#endif - for (irq = OCTEON_IRQ_UART0; irq <= OCTEON_IRQ_BOOTDMA; irq++) { - if (is_irq_enabled_on_cpu(irq, smp_processor_id())) { - /* ciu irq migrates to next cpu */ - octeon_irq_chip_ciu0.disable(irq); - octeon_irq_ciu0_set_affinity(irq, &cpu_online_map); - } - } + if (do_set_affinity) + irq_set_affinity(irq, &new_affinity); - for (irq = OCTEON_IRQ_UART2; irq <= OCTEON_IRQ_RESERVED135; irq++) { - if (is_irq_enabled_on_cpu(irq, smp_processor_id())) { - /* ciu irq migrates to next cpu */ - octeon_irq_chip_ciu1.disable(irq); - octeon_irq_ciu1_set_affinity(irq, &cpu_online_map); + break; } } } -- cgit v0.10.2 From a5decf700be1123c2da6bdab5099bce072c55cc2 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 23 Jul 2010 10:43:48 -0700 Subject: MIPS: Octeon: Get rid of a bunch of MSI IRQ number definitions. MSI IRQ numbers are allocated dynamically, so there is no reason to have all these static definitions. Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1487/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-cavium-octeon/irq.h b/arch/mips/include/asm/mach-cavium-octeon/irq.h index d32220f..783dae7 100644 --- a/arch/mips/include/asm/mach-cavium-octeon/irq.h +++ b/arch/mips/include/asm/mach-cavium-octeon/irq.h @@ -172,71 +172,9 @@ #ifdef CONFIG_PCI_MSI /* 152 - 215 represent the MSI interrupts 0-63 */ #define OCTEON_IRQ_MSI_BIT0 152 -#define OCTEON_IRQ_MSI_BIT1 153 -#define OCTEON_IRQ_MSI_BIT2 154 -#define OCTEON_IRQ_MSI_BIT3 155 -#define OCTEON_IRQ_MSI_BIT4 156 -#define OCTEON_IRQ_MSI_BIT5 157 -#define OCTEON_IRQ_MSI_BIT6 158 -#define OCTEON_IRQ_MSI_BIT7 159 -#define OCTEON_IRQ_MSI_BIT8 160 -#define OCTEON_IRQ_MSI_BIT9 161 -#define OCTEON_IRQ_MSI_BIT10 162 -#define OCTEON_IRQ_MSI_BIT11 163 -#define OCTEON_IRQ_MSI_BIT12 164 -#define OCTEON_IRQ_MSI_BIT13 165 -#define OCTEON_IRQ_MSI_BIT14 166 -#define OCTEON_IRQ_MSI_BIT15 167 -#define OCTEON_IRQ_MSI_BIT16 168 -#define OCTEON_IRQ_MSI_BIT17 169 -#define OCTEON_IRQ_MSI_BIT18 170 -#define OCTEON_IRQ_MSI_BIT19 171 -#define OCTEON_IRQ_MSI_BIT20 172 -#define OCTEON_IRQ_MSI_BIT21 173 -#define OCTEON_IRQ_MSI_BIT22 174 -#define OCTEON_IRQ_MSI_BIT23 175 -#define OCTEON_IRQ_MSI_BIT24 176 -#define OCTEON_IRQ_MSI_BIT25 177 -#define OCTEON_IRQ_MSI_BIT26 178 -#define OCTEON_IRQ_MSI_BIT27 179 -#define OCTEON_IRQ_MSI_BIT28 180 -#define OCTEON_IRQ_MSI_BIT29 181 -#define OCTEON_IRQ_MSI_BIT30 182 -#define OCTEON_IRQ_MSI_BIT31 183 -#define OCTEON_IRQ_MSI_BIT32 184 -#define OCTEON_IRQ_MSI_BIT33 185 -#define OCTEON_IRQ_MSI_BIT34 186 -#define OCTEON_IRQ_MSI_BIT35 187 -#define OCTEON_IRQ_MSI_BIT36 188 -#define OCTEON_IRQ_MSI_BIT37 189 -#define OCTEON_IRQ_MSI_BIT38 190 -#define OCTEON_IRQ_MSI_BIT39 191 -#define OCTEON_IRQ_MSI_BIT40 192 -#define OCTEON_IRQ_MSI_BIT41 193 -#define OCTEON_IRQ_MSI_BIT42 194 -#define OCTEON_IRQ_MSI_BIT43 195 -#define OCTEON_IRQ_MSI_BIT44 196 -#define OCTEON_IRQ_MSI_BIT45 197 -#define OCTEON_IRQ_MSI_BIT46 198 -#define OCTEON_IRQ_MSI_BIT47 199 -#define OCTEON_IRQ_MSI_BIT48 200 -#define OCTEON_IRQ_MSI_BIT49 201 -#define OCTEON_IRQ_MSI_BIT50 202 -#define OCTEON_IRQ_MSI_BIT51 203 -#define OCTEON_IRQ_MSI_BIT52 204 -#define OCTEON_IRQ_MSI_BIT53 205 -#define OCTEON_IRQ_MSI_BIT54 206 -#define OCTEON_IRQ_MSI_BIT55 207 -#define OCTEON_IRQ_MSI_BIT56 208 -#define OCTEON_IRQ_MSI_BIT57 209 -#define OCTEON_IRQ_MSI_BIT58 210 -#define OCTEON_IRQ_MSI_BIT59 211 -#define OCTEON_IRQ_MSI_BIT60 212 -#define OCTEON_IRQ_MSI_BIT61 213 -#define OCTEON_IRQ_MSI_BIT62 214 -#define OCTEON_IRQ_MSI_BIT63 215 +#define OCTEON_IRQ_MSI_LAST (OCTEON_IRQ_MSI_BIT0 + 63) -#define OCTEON_IRQ_LAST 216 +#define OCTEON_IRQ_LAST (OCTEON_IRQ_MSI_LAST + 1) #else #define OCTEON_IRQ_LAST 152 #endif diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c index 1e31526..5ce1a6a 100644 --- a/arch/mips/pci/msi-octeon.c +++ b/arch/mips/pci/msi-octeon.c @@ -181,7 +181,7 @@ void arch_teardown_msi_irq(unsigned int irq) int number_irqs; uint64_t bitmask; - if ((irq < OCTEON_IRQ_MSI_BIT0) || (irq > OCTEON_IRQ_MSI_BIT63)) + if ((irq < OCTEON_IRQ_MSI_BIT0) || (irq > OCTEON_IRQ_MSI_LAST)) panic("arch_teardown_msi_irq: Attempted to teardown illegal " "MSI interrupt (%d)", irq); irq -= OCTEON_IRQ_MSI_BIT0; @@ -337,7 +337,7 @@ static int __init octeon_msi_initialize(void) { int irq; - for (irq = OCTEON_IRQ_MSI_BIT0; irq <= OCTEON_IRQ_MSI_BIT63; irq++) { + for (irq = OCTEON_IRQ_MSI_BIT0; irq <= OCTEON_IRQ_MSI_LAST; irq++) { set_irq_chip_and_handler(irq, &octeon_irq_chip_msi, handle_percpu_irq); } -- cgit v0.10.2 From 7d9eee6e52e817c006666b0efc5068aa219dbecb Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 23 Jul 2010 10:43:49 -0700 Subject: MIPS: Octeon: Make MSI use handle_simple_irq(). The use of handle_percpu_irq() is not really what we want for MSI, use handle_simple_irq() instead. This is probably the prototypical case for using handle_simple_irq(), because all the MSIs are dispatched from the root interrupt service routine. Also since the base IRQ is not shared, don't pass IRQF_SHARED. Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1488/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c index 5ce1a6a..83ceb52 100644 --- a/arch/mips/pci/msi-octeon.c +++ b/arch/mips/pci/msi-octeon.c @@ -228,22 +228,20 @@ static irqreturn_t octeon_msi_interrupt(int cpl, void *dev_id) irq = fls64(msi_bits); if (irq) { irq += OCTEON_IRQ_MSI_BIT0 - 1; + if (octeon_has_feature(OCTEON_FEATURE_PCIE)) { + /* These chips have PCIe */ + cvmx_write_csr(CVMX_PEXP_NPEI_MSI_RCV0, + 1ull << (irq - OCTEON_IRQ_MSI_BIT0)); + } else { + /* These chips have PCI */ + cvmx_write_csr(CVMX_NPI_NPI_MSI_RCV, + 1ull << (irq - OCTEON_IRQ_MSI_BIT0)); + } if (irq_desc[irq].action) { do_IRQ(irq); return IRQ_HANDLED; } else { pr_err("Spurious MSI interrupt %d\n", irq); - if (octeon_has_feature(OCTEON_FEATURE_PCIE)) { - /* These chips have PCIe */ - cvmx_write_csr(CVMX_PEXP_NPEI_MSI_RCV0, - 1ull << (irq - - OCTEON_IRQ_MSI_BIT0)); - } else { - /* These chips have PCI */ - cvmx_write_csr(CVMX_NPI_NPI_MSI_RCV, - 1ull << (irq - - OCTEON_IRQ_MSI_BIT0)); - } } } return IRQ_NONE; @@ -251,27 +249,6 @@ static irqreturn_t octeon_msi_interrupt(int cpl, void *dev_id) static DEFINE_RAW_SPINLOCK(octeon_irq_msi_lock); -static void octeon_irq_msi_ack(unsigned int irq) -{ - if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) { - /* These chips have PCI */ - cvmx_write_csr(CVMX_NPI_NPI_MSI_RCV, - 1ull << (irq - OCTEON_IRQ_MSI_BIT0)); - } else { - /* - * These chips have PCIe. Thankfully the ACK doesn't - * need any locking. - */ - cvmx_write_csr(CVMX_PEXP_NPEI_MSI_RCV0, - 1ull << (irq - OCTEON_IRQ_MSI_BIT0)); - } -} - -static void octeon_irq_msi_eoi(unsigned int irq) -{ - /* Nothing needed */ -} - static void octeon_irq_msi_enable(unsigned int irq) { if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) { @@ -326,8 +303,6 @@ static struct irq_chip octeon_irq_chip_msi = { .name = "MSI", .enable = octeon_irq_msi_enable, .disable = octeon_irq_msi_disable, - .ack = octeon_irq_msi_ack, - .eoi = octeon_irq_msi_eoi, }; /* @@ -338,34 +313,28 @@ static int __init octeon_msi_initialize(void) int irq; for (irq = OCTEON_IRQ_MSI_BIT0; irq <= OCTEON_IRQ_MSI_LAST; irq++) { - set_irq_chip_and_handler(irq, &octeon_irq_chip_msi, - handle_percpu_irq); + set_irq_chip_and_handler(irq, &octeon_irq_chip_msi, handle_simple_irq); } if (octeon_has_feature(OCTEON_FEATURE_PCIE)) { if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt, - IRQF_SHARED, - "MSI[0:63]", octeon_msi_interrupt)) + 0, "MSI[0:63]", octeon_msi_interrupt)) panic("request_irq(OCTEON_IRQ_PCI_MSI0) failed"); } else if (octeon_is_pci_host()) { if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt, - IRQF_SHARED, - "MSI[0:15]", octeon_msi_interrupt)) + 0, "MSI[0:15]", octeon_msi_interrupt)) panic("request_irq(OCTEON_IRQ_PCI_MSI0) failed"); if (request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt, - IRQF_SHARED, - "MSI[16:31]", octeon_msi_interrupt)) + 0, "MSI[16:31]", octeon_msi_interrupt)) panic("request_irq(OCTEON_IRQ_PCI_MSI1) failed"); if (request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt, - IRQF_SHARED, - "MSI[32:47]", octeon_msi_interrupt)) + 0, "MSI[32:47]", octeon_msi_interrupt)) panic("request_irq(OCTEON_IRQ_PCI_MSI2) failed"); if (request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt, - IRQF_SHARED, - "MSI[48:63]", octeon_msi_interrupt)) + 0, "MSI[48:63]", octeon_msi_interrupt)) panic("request_irq(OCTEON_IRQ_PCI_MSI3) failed"); } -- cgit v0.10.2 From edfcbb8cac13d679c0d656fd4576b3945429f3c0 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 23 Jul 2010 10:57:49 -0700 Subject: MIPS: Octeon: Clean up SMP CPU numbering. Also number offline CPUs that could potentially be brought on-line later. Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1489/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 6d99b9d..8ff2c7b 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2004-2008 Cavium Networks + * Copyright (C) 2004-2008, 2009, 2010 Cavium Networks */ #include #include @@ -102,24 +102,47 @@ static void octeon_smp_setup(void) const int coreid = cvmx_get_core_num(); int cpus; int id; - int core_mask = octeon_get_boot_coremask(); +#ifdef CONFIG_HOTPLUG_CPU + unsigned int num_cores = cvmx_octeon_num_cores(); +#endif + + /* The present CPUs are initially just the boot cpu (CPU 0). */ + for (id = 0; id < NR_CPUS; id++) { + set_cpu_possible(id, id == 0); + set_cpu_present(id, id == 0); + } - cpus_clear(cpu_possible_map); __cpu_number_map[coreid] = 0; __cpu_logical_map[0] = coreid; - cpu_set(0, cpu_possible_map); + /* The present CPUs get the lowest CPU numbers. */ cpus = 1; - for (id = 0; id < 16; id++) { + for (id = 0; id < NR_CPUS; id++) { if ((id != coreid) && (core_mask & (1 << id))) { - cpu_set(cpus, cpu_possible_map); + set_cpu_possible(cpus, true); + set_cpu_present(cpus, true); __cpu_number_map[id] = cpus; __cpu_logical_map[cpus] = id; cpus++; } } - cpu_present_map = cpu_possible_map; + +#ifdef CONFIG_HOTPLUG_CPU + /* + * The possible CPUs are all those present on the chip. We + * will assign CPU numbers for possible cores as well. Cores + * are always consecutively numberd from 0. + */ + for (id = 0; id < num_cores && id < NR_CPUS; id++) { + if (!(core_mask & (1 << id))) { + set_cpu_possible(cpus, true); + __cpu_number_map[id] = cpus; + __cpu_logical_map[cpus] = id; + cpus++; + } + } +#endif octeon_smp_hotplug_setup(); } -- cgit v0.10.2 From 442f201286bfbbcd5ba5acb616914004be3e6268 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 23 Jul 2010 10:57:50 -0700 Subject: MIPS: Octeon: Simplify hotcpu_notifier registration. Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1490/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 8ff2c7b..ceb7649 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -428,17 +428,11 @@ static int __cpuinit octeon_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata octeon_cpu_notifier = { - .notifier_call = octeon_cpu_callback, -}; - static int __cpuinit register_cavium_notifier(void) { - register_hotcpu_notifier(&octeon_cpu_notifier); - + hotcpu_notifier(octeon_cpu_callback, 0); return 0; } - late_initcall(register_cavium_notifier); #endif /* CONFIG_HOTPLUG_CPU */ -- cgit v0.10.2 From babba4f11379fb3804de802a3d0bc6b96c59d547 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 23 Jul 2010 10:57:51 -0700 Subject: MIPS: Octeon: HOTPLUG_CPU fixes. * Rename camel-case InitTLBStart_addr to octeon_bootloader_entry_addr. * Convert calls to cvmx_read64_uint32(), to simple pointer dereferences. * Set proper ebase. * Don't confuse coreid and cpu numbers. * Try to maintain consistent bootloader coremask. * Update the signature and boot_init_vector of supported bootloaders. Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1491/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/cavium-octeon/octeon_boot.h b/arch/mips/cavium-octeon/octeon_boot.h index 0f7f84a..428864b 100644 --- a/arch/mips/cavium-octeon/octeon_boot.h +++ b/arch/mips/cavium-octeon/octeon_boot.h @@ -23,14 +23,16 @@ #include struct boot_init_vector { - uint32_t stack_addr; - uint32_t code_addr; + /* First stage address - in ram instead of flash */ + uint64_t code_addr; + /* Setup code for application, NOT application entry point */ uint32_t app_start_func_addr; + /* k0 is used for global data - needs to be passed to other cores */ uint32_t k0_val; - uint32_t flags; - uint32_t boot_info_addr; + /* Address of boot info block structure */ + uint64_t boot_info_addr; + uint32_t flags; /* flags */ uint32_t pad; - uint32_t pad2; }; /* similar to bootloader's linux_app_boot_info but without global data */ @@ -40,7 +42,7 @@ struct linux_app_boot_info { uint32_t avail_coremask; uint32_t pci_console_active; uint32_t icache_prefetch_disable; - uint32_t InitTLBStart_addr; + uint64_t InitTLBStart_addr; uint32_t start_app_addr; uint32_t cur_exception_base; uint32_t no_mark_private_data; @@ -58,7 +60,7 @@ struct linux_app_boot_info { #define LINUX_APP_BOOT_BLOCK_NAME "linux-app-boot" -#define LABI_SIGNATURE 0xAABBCCDD +#define LABI_SIGNATURE 0xAABBCC01 /* from uboot-headers/octeon_mem_map.h */ #define EXCEPTION_BASE_INCR (4 * 1024) diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index ceb7649..391cefe 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -27,7 +27,8 @@ volatile unsigned long octeon_processor_sp; volatile unsigned long octeon_processor_gp; #ifdef CONFIG_HOTPLUG_CPU -static unsigned int InitTLBStart_addr; +uint64_t octeon_bootloader_entry_addr; +EXPORT_SYMBOL(octeon_bootloader_entry_addr); #endif static irqreturn_t mailbox_interrupt(int irq, void *dev_id) @@ -80,20 +81,13 @@ static inline void octeon_send_ipi_mask(const struct cpumask *mask, static void octeon_smp_hotplug_setup(void) { #ifdef CONFIG_HOTPLUG_CPU - uint32_t labi_signature; - - labi_signature = - cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, - LABI_ADDR_IN_BOOTLOADER + - offsetof(struct linux_app_boot_info, - labi_signature))); - if (labi_signature != LABI_SIGNATURE) - pr_err("The bootloader version on this board is incorrect\n"); - InitTLBStart_addr = - cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, - LABI_ADDR_IN_BOOTLOADER + - offsetof(struct linux_app_boot_info, - InitTLBStart_addr))); + struct linux_app_boot_info *labi; + + labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER); + if (labi->labi_signature != LABI_SIGNATURE) + panic("The bootloader version on this board is incorrect."); + + octeon_bootloader_entry_addr = labi->InitTLBStart_addr; #endif } @@ -181,18 +175,21 @@ static void octeon_init_secondary(void) { const int coreid = cvmx_get_core_num(); union cvmx_ciu_intx_sum0 interrupt_enable; + unsigned int sr; #ifdef CONFIG_HOTPLUG_CPU - unsigned int cur_exception_base; - - cur_exception_base = cvmx_read64_uint32( - CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, - LABI_ADDR_IN_BOOTLOADER + - offsetof(struct linux_app_boot_info, - cur_exception_base))); - /* cur_exception_base is incremented in bootloader after setting */ - write_c0_ebase((unsigned int)(cur_exception_base - EXCEPTION_BASE_INCR)); + struct linux_app_boot_info *labi; + + labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER); + + if (labi->labi_signature != LABI_SIGNATURE) + panic("The bootloader version on this board is incorrect."); #endif + + sr = set_c0_status(ST0_BEV); + write_c0_ebase((u32)ebase); + write_c0_status(sr); + octeon_check_cpu_bist(); octeon_init_cvmcount(); /* @@ -299,8 +296,8 @@ static int octeon_cpu_disable(void) static void octeon_cpu_die(unsigned int cpu) { int coreid = cpu_logical_map(cpu); - uint32_t avail_coremask; - struct cvmx_bootmem_named_block_desc *block_desc; + uint32_t mask, new_mask; + const struct cvmx_bootmem_named_block_desc *block_desc; while (per_cpu(cpu_state, cpu) != CPU_DEAD) cpu_relax(); @@ -309,52 +306,40 @@ static void octeon_cpu_die(unsigned int cpu) * This is a bit complicated strategics of getting/settig available * cores mask, copied from bootloader */ + + mask = 1 << coreid; /* LINUX_APP_BOOT_BLOCK is initialized in bootoct binary */ block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME); if (!block_desc) { - avail_coremask = - cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, - LABI_ADDR_IN_BOOTLOADER + - offsetof - (struct linux_app_boot_info, - avail_coremask))); - } else { /* alternative, already initialized */ - avail_coremask = - cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, - block_desc->base_addr + - AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK)); - } + struct linux_app_boot_info *labi; - avail_coremask |= 1 << coreid; + labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER); - /* Setting avail_coremask for bootoct binary */ - if (!block_desc) { - cvmx_write64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, - LABI_ADDR_IN_BOOTLOADER + - offsetof(struct linux_app_boot_info, - avail_coremask)), - avail_coremask); - } else { - cvmx_write64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, - block_desc->base_addr + - AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK), - avail_coremask); + labi->avail_coremask |= mask; + new_mask = labi->avail_coremask; + } else { /* alternative, already initialized */ + uint32_t *p = (uint32_t *)PHYS_TO_XKSEG_CACHED(block_desc->base_addr + + AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK); + *p |= mask; + new_mask = *p; } - pr_info("Reset core %d. Available Coremask = %x\n", coreid, - avail_coremask); + pr_info("Reset core %d. Available Coremask = 0x%x \n", coreid, new_mask); + mb(); cvmx_write_csr(CVMX_CIU_PP_RST, 1 << coreid); cvmx_write_csr(CVMX_CIU_PP_RST, 0); } void play_dead(void) { - int coreid = cvmx_get_core_num(); + int cpu = cpu_number_map(cvmx_get_core_num()); idle_task_exit(); octeon_processor_boot = 0xff; - per_cpu(cpu_state, coreid) = CPU_DEAD; + per_cpu(cpu_state, cpu) = CPU_DEAD; + + mb(); while (1) /* core will be reset here */ ; @@ -367,29 +352,27 @@ static void start_after_reset(void) kernel_entry(0, 0, 0); /* set a2 = 0 for secondary core */ } -int octeon_update_boot_vector(unsigned int cpu) +static int octeon_update_boot_vector(unsigned int cpu) { int coreid = cpu_logical_map(cpu); - unsigned int avail_coremask; - struct cvmx_bootmem_named_block_desc *block_desc; + uint32_t avail_coremask; + const struct cvmx_bootmem_named_block_desc *block_desc; struct boot_init_vector *boot_vect = - (struct boot_init_vector *) cvmx_phys_to_ptr(0x0 + - BOOTLOADER_BOOT_VECTOR); + (struct boot_init_vector *)PHYS_TO_XKSEG_CACHED(BOOTLOADER_BOOT_VECTOR); block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME); if (!block_desc) { - avail_coremask = - cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, - LABI_ADDR_IN_BOOTLOADER + - offsetof(struct linux_app_boot_info, - avail_coremask))); + struct linux_app_boot_info *labi; + + labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER); + + avail_coremask = labi->avail_coremask; + labi->avail_coremask &= ~(1 << coreid); } else { /* alternative, already initialized */ - avail_coremask = - cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, - block_desc->base_addr + - AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK)); + avail_coremask = *(uint32_t *)PHYS_TO_XKSEG_CACHED( + block_desc->base_addr + AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK); } if (!(avail_coremask & (1 << coreid))) { @@ -400,9 +383,9 @@ int octeon_update_boot_vector(unsigned int cpu) boot_vect[coreid].app_start_func_addr = (uint32_t) (unsigned long) start_after_reset; - boot_vect[coreid].code_addr = InitTLBStart_addr; + boot_vect[coreid].code_addr = octeon_bootloader_entry_addr; - CVMX_SYNC; + mb(); cvmx_write_csr(CVMX_CIU_NMI, (1 << coreid) & avail_coremask); diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h index ca6214b..c29debe 100644 --- a/arch/mips/include/asm/octeon/octeon.h +++ b/arch/mips/include/asm/octeon/octeon.h @@ -253,4 +253,6 @@ static inline uint32_t octeon_npi_read32(uint64_t address) extern struct cvmx_bootinfo *octeon_bootinfo; +extern uint64_t octeon_bootloader_entry_addr; + #endif /* __ASM_OCTEON_OCTEON_H */ -- cgit v0.10.2 From 83ccf69d8f118306e90af703f32109edb6c1e4a1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 17 Jul 2010 11:07:51 +0000 Subject: MIPS: JZ4740: Add base support for Ingenic JZ4740 System-on-a-Chip Adds a new cpu type for the JZ4740 to the Linux MIPS architecture code. It also adds the iomem addresses for the different components found on a JZ4740 SoC. Signed-off-by: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1464/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h index 09eee09..15a8ef0 100644 --- a/arch/mips/include/asm/bootinfo.h +++ b/arch/mips/include/asm/bootinfo.h @@ -71,6 +71,12 @@ #define MACH_LEMOTE_LL2F 7 #define MACH_LOONGSON_END 8 +/* + * Valid machtype for group INGENIC + */ +#define MACH_INGENIC_JZ4730 0 /* JZ4730 SOC */ +#define MACH_INGENIC_JZ4740 1 /* JZ4740 SOC */ + extern char *system_type; const char *get_system_type(void); diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index a5acda4..b201a8f 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -34,7 +34,7 @@ #define PRID_COMP_LSI 0x080000 #define PRID_COMP_LEXRA 0x0b0000 #define PRID_COMP_CAVIUM 0x0d0000 - +#define PRID_COMP_INGENIC 0xd00000 /* * Assigned values for the product ID register. In order to detect a @@ -133,6 +133,12 @@ #define PRID_IMP_CAVIUM_CN52XX 0x0700 /* + * These are the PRID's for when 23:16 == PRID_COMP_INGENIC + */ + +#define PRID_IMP_JZRISC 0x0200 + +/* * Definitions for 7:0 on legacy processors */ @@ -219,6 +225,7 @@ enum cpu_type_enum { CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K, CPU_ALCHEMY, CPU_PR4450, CPU_BCM3302, CPU_BCM4710, CPU_BCM6338, CPU_BCM6345, CPU_BCM6348, CPU_BCM6358, + CPU_JZRISC, /* * MIPS64 class processors diff --git a/arch/mips/include/asm/mach-jz4740/base.h b/arch/mips/include/asm/mach-jz4740/base.h new file mode 100644 index 0000000..f373186 --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/base.h @@ -0,0 +1,26 @@ +#ifndef __ASM_MACH_JZ4740_BASE_H__ +#define __ASM_MACH_JZ4740_BASE_H__ + +#define JZ4740_CPM_BASE_ADDR 0x10000000 +#define JZ4740_INTC_BASE_ADDR 0x10001000 +#define JZ4740_WDT_BASE_ADDR 0x10002000 +#define JZ4740_TCU_BASE_ADDR 0x10002010 +#define JZ4740_RTC_BASE_ADDR 0x10003000 +#define JZ4740_GPIO_BASE_ADDR 0x10010000 +#define JZ4740_AIC_BASE_ADDR 0x10020000 +#define JZ4740_MSC_BASE_ADDR 0x10021000 +#define JZ4740_UART0_BASE_ADDR 0x10030000 +#define JZ4740_UART1_BASE_ADDR 0x10031000 +#define JZ4740_I2C_BASE_ADDR 0x10042000 +#define JZ4740_SSI_BASE_ADDR 0x10043000 +#define JZ4740_SADC_BASE_ADDR 0x10070000 +#define JZ4740_EMC_BASE_ADDR 0x13010000 +#define JZ4740_DMAC_BASE_ADDR 0x13020000 +#define JZ4740_UHC_BASE_ADDR 0x13030000 +#define JZ4740_UDC_BASE_ADDR 0x13040000 +#define JZ4740_LCD_BASE_ADDR 0x13050000 +#define JZ4740_SLCD_BASE_ADDR 0x13050000 +#define JZ4740_CIM_BASE_ADDR 0x13060000 +#define JZ4740_IPU_BASE_ADDR 0x13080000 + +#endif diff --git a/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h b/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h new file mode 100644 index 0000000..d12e5c6 --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h @@ -0,0 +1,51 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + */ +#ifndef __ASM_MACH_JZ4740_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_JZ4740_CPU_FEATURE_OVERRIDES_H + +#define cpu_has_tlb 1 +#define cpu_has_4kex 1 +#define cpu_has_3k_cache 0 +#define cpu_has_4k_cache 1 +#define cpu_has_tx39_cache 0 +#define cpu_has_fpu 0 +#define cpu_has_32fpr 0 +#define cpu_has_counter 0 +#define cpu_has_watch 1 +#define cpu_has_divec 1 +#define cpu_has_vce 0 +#define cpu_has_cache_cdex_p 0 +#define cpu_has_cache_cdex_s 0 +#define cpu_has_prefetch 1 +#define cpu_has_mcheck 1 +#define cpu_has_ejtag 1 +#define cpu_has_llsc 1 +#define cpu_has_mips16 0 +#define cpu_has_mdmx 0 +#define cpu_has_mips3d 0 +#define cpu_has_smartmips 0 +#define kernel_uses_llsc 1 +#define cpu_has_vtag_icache 1 +#define cpu_has_dc_aliases 0 +#define cpu_has_ic_fills_f_dc 0 +#define cpu_has_pindexed_dcache 0 +#define cpu_has_mips32r1 1 +#define cpu_has_mips32r2 0 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 +#define cpu_has_dsp 0 +#define cpu_has_mipsmt 0 +#define cpu_has_userlocal 0 +#define cpu_has_nofpuex 0 +#define cpu_has_64bits 0 +#define cpu_has_64bit_zero_reg 0 +#define cpu_has_inclusive_pcaches 0 + +#define cpu_dcache_line_size() 32 +#define cpu_icache_line_size() 32 + +#endif diff --git a/arch/mips/include/asm/mach-jz4740/war.h b/arch/mips/include/asm/mach-jz4740/war.h new file mode 100644 index 0000000..3a5bc17 --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_JZ4740_WAR_H +#define __ASM_MIPS_MACH_JZ4740_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_JZ4740_WAR_H */ diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 3562b85..9b663317 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -187,6 +187,7 @@ void __init check_wait(void) case CPU_BCM6358: case CPU_CAVIUM_OCTEON: case CPU_CAVIUM_OCTEON_PLUS: + case CPU_JZRISC: cpu_wait = r4k_wait; break; @@ -956,6 +957,22 @@ platform: } } +static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu) +{ + decode_configs(c); + /* JZRISC does not implement the CP0 counter. */ + c->options &= ~MIPS_CPU_COUNTER; + switch (c->processor_id & 0xff00) { + case PRID_IMP_JZRISC: + c->cputype = CPU_JZRISC; + __cpu_name[cpu] = "Ingenic JZRISC"; + break; + default: + panic("Unknown Ingenic Processor ID!"); + break; + } +} + const char *__cpu_name[NR_CPUS]; const char *__elf_platform; @@ -994,6 +1011,9 @@ __cpuinit void cpu_probe(void) case PRID_COMP_CAVIUM: cpu_probe_cavium(c, cpu); break; + case PRID_COMP_INGENIC: + cpu_probe_ingenic(c, cpu); + break; } BUG_ON(!__cpu_name[cpu]); diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 86f004d..4510e61 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -409,6 +409,11 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l, tlbw(p); break; + case CPU_JZRISC: + tlbw(p); + uasm_i_nop(p); + break; + default: panic("No TLB refill handler yet (CPU type: %d)", current_cpu_data.cputype); -- cgit v0.10.2 From 570a0bb82f0b5c2c6324153010e72c3f0c26a7a3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 17 Jul 2010 11:10:00 +0000 Subject: MIPS: JZ4740: Add clock API support. Add support for managing the clocks found on JZ4740 SoC through the Linux clock API. Signed-off-by: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1466/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-jz4740/clock.h b/arch/mips/include/asm/mach-jz4740/clock.h new file mode 100644 index 0000000..1b7408d --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/clock.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * + * 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. + * + * 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_JZ4740_CLOCK_H__ +#define __ASM_JZ4740_CLOCK_H__ + +enum jz4740_wait_mode { + JZ4740_WAIT_MODE_IDLE, + JZ4740_WAIT_MODE_SLEEP, +}; + +void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode); + +void jz4740_clock_udc_enable_auto_suspend(void); +void jz4740_clock_udc_disable_auto_suspend(void); + +#endif diff --git a/arch/mips/jz4740/clock-debugfs.c b/arch/mips/jz4740/clock-debugfs.c new file mode 100644 index 0000000..330a0f2 --- /dev/null +++ b/arch/mips/jz4740/clock-debugfs.c @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * JZ4740 SoC clock support debugfs entries + * + * 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. + * + * 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. + * + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include "clock.h" + +static struct dentry *jz4740_clock_debugfs; + +static int jz4740_clock_debugfs_show_enabled(void *data, uint64_t *value) +{ + struct clk *clk = data; + *value = clk_is_enabled(clk); + + return 0; +} + +static int jz4740_clock_debugfs_set_enabled(void *data, uint64_t value) +{ + struct clk *clk = data; + + if (value) + return clk_enable(clk); + else + clk_disable(clk); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(jz4740_clock_debugfs_ops_enabled, + jz4740_clock_debugfs_show_enabled, + jz4740_clock_debugfs_set_enabled, + "%llu\n"); + +static int jz4740_clock_debugfs_show_rate(void *data, uint64_t *value) +{ + struct clk *clk = data; + *value = clk_get_rate(clk); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(jz4740_clock_debugfs_ops_rate, + jz4740_clock_debugfs_show_rate, + NULL, + "%llu\n"); + +void jz4740_clock_debugfs_add_clk(struct clk *clk) +{ + if (!jz4740_clock_debugfs) + return; + + clk->debugfs_entry = debugfs_create_dir(clk->name, jz4740_clock_debugfs); + debugfs_create_file("rate", S_IWUGO | S_IRUGO, clk->debugfs_entry, clk, + &jz4740_clock_debugfs_ops_rate); + debugfs_create_file("enabled", S_IRUGO, clk->debugfs_entry, clk, + &jz4740_clock_debugfs_ops_enabled); + + if (clk->parent) { + char parent_path[100]; + snprintf(parent_path, 100, "../%s", clk->parent->name); + clk->debugfs_parent_entry = debugfs_create_symlink("parent", + clk->debugfs_entry, + parent_path); + } +} + +/* TODO: Locking */ +void jz4740_clock_debugfs_update_parent(struct clk *clk) +{ + if (clk->debugfs_parent_entry) + debugfs_remove(clk->debugfs_parent_entry); + + if (clk->parent) { + char parent_path[100]; + snprintf(parent_path, 100, "../%s", clk->parent->name); + clk->debugfs_parent_entry = debugfs_create_symlink("parent", + clk->debugfs_entry, + parent_path); + } else { + clk->debugfs_parent_entry = NULL; + } +} + +void jz4740_clock_debugfs_init(void) +{ + jz4740_clock_debugfs = debugfs_create_dir("jz4740-clock", NULL); + if (IS_ERR(jz4740_clock_debugfs)) + jz4740_clock_debugfs = NULL; +} diff --git a/arch/mips/jz4740/clock.c b/arch/mips/jz4740/clock.c new file mode 100644 index 0000000..118a8a5 --- /dev/null +++ b/arch/mips/jz4740/clock.c @@ -0,0 +1,924 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * JZ4740 SoC clock support + * + * 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. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "clock.h" + +#define JZ_REG_CLOCK_CTRL 0x00 +#define JZ_REG_CLOCK_LOW_POWER 0x04 +#define JZ_REG_CLOCK_PLL 0x10 +#define JZ_REG_CLOCK_GATE 0x20 +#define JZ_REG_CLOCK_SLEEP_CTRL 0x24 +#define JZ_REG_CLOCK_I2S 0x60 +#define JZ_REG_CLOCK_LCD 0x64 +#define JZ_REG_CLOCK_MMC 0x68 +#define JZ_REG_CLOCK_UHC 0x6C +#define JZ_REG_CLOCK_SPI 0x74 + +#define JZ_CLOCK_CTRL_I2S_SRC_PLL BIT(31) +#define JZ_CLOCK_CTRL_KO_ENABLE BIT(30) +#define JZ_CLOCK_CTRL_UDC_SRC_PLL BIT(29) +#define JZ_CLOCK_CTRL_UDIV_MASK 0x1f800000 +#define JZ_CLOCK_CTRL_CHANGE_ENABLE BIT(22) +#define JZ_CLOCK_CTRL_PLL_HALF BIT(21) +#define JZ_CLOCK_CTRL_LDIV_MASK 0x001f0000 +#define JZ_CLOCK_CTRL_UDIV_OFFSET 23 +#define JZ_CLOCK_CTRL_LDIV_OFFSET 16 +#define JZ_CLOCK_CTRL_MDIV_OFFSET 12 +#define JZ_CLOCK_CTRL_PDIV_OFFSET 8 +#define JZ_CLOCK_CTRL_HDIV_OFFSET 4 +#define JZ_CLOCK_CTRL_CDIV_OFFSET 0 + +#define JZ_CLOCK_GATE_UART0 BIT(0) +#define JZ_CLOCK_GATE_TCU BIT(1) +#define JZ_CLOCK_GATE_RTC BIT(2) +#define JZ_CLOCK_GATE_I2C BIT(3) +#define JZ_CLOCK_GATE_SPI BIT(4) +#define JZ_CLOCK_GATE_AIC BIT(5) +#define JZ_CLOCK_GATE_I2S BIT(6) +#define JZ_CLOCK_GATE_MMC BIT(7) +#define JZ_CLOCK_GATE_ADC BIT(8) +#define JZ_CLOCK_GATE_CIM BIT(9) +#define JZ_CLOCK_GATE_LCD BIT(10) +#define JZ_CLOCK_GATE_UDC BIT(11) +#define JZ_CLOCK_GATE_DMAC BIT(12) +#define JZ_CLOCK_GATE_IPU BIT(13) +#define JZ_CLOCK_GATE_UHC BIT(14) +#define JZ_CLOCK_GATE_UART1 BIT(15) + +#define JZ_CLOCK_I2S_DIV_MASK 0x01ff + +#define JZ_CLOCK_LCD_DIV_MASK 0x01ff + +#define JZ_CLOCK_MMC_DIV_MASK 0x001f + +#define JZ_CLOCK_UHC_DIV_MASK 0x000f + +#define JZ_CLOCK_SPI_SRC_PLL BIT(31) +#define JZ_CLOCK_SPI_DIV_MASK 0x000f + +#define JZ_CLOCK_PLL_M_MASK 0x01ff +#define JZ_CLOCK_PLL_N_MASK 0x001f +#define JZ_CLOCK_PLL_OD_MASK 0x0003 +#define JZ_CLOCK_PLL_STABLE BIT(10) +#define JZ_CLOCK_PLL_BYPASS BIT(9) +#define JZ_CLOCK_PLL_ENABLED BIT(8) +#define JZ_CLOCK_PLL_STABLIZE_MASK 0x000f +#define JZ_CLOCK_PLL_M_OFFSET 23 +#define JZ_CLOCK_PLL_N_OFFSET 18 +#define JZ_CLOCK_PLL_OD_OFFSET 16 + +#define JZ_CLOCK_LOW_POWER_MODE_DOZE BIT(2) +#define JZ_CLOCK_LOW_POWER_MODE_SLEEP BIT(0) + +#define JZ_CLOCK_SLEEP_CTRL_SUSPEND_UHC BIT(7) +#define JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC BIT(6) + +static void __iomem *jz_clock_base; +static spinlock_t jz_clock_lock; +static LIST_HEAD(jz_clocks); + +struct main_clk { + struct clk clk; + uint32_t div_offset; +}; + +struct divided_clk { + struct clk clk; + uint32_t reg; + uint32_t mask; +}; + +struct static_clk { + struct clk clk; + unsigned long rate; +}; + +static uint32_t jz_clk_reg_read(int reg) +{ + return readl(jz_clock_base + reg); +} + +static void jz_clk_reg_write_mask(int reg, uint32_t val, uint32_t mask) +{ + uint32_t val2; + + spin_lock(&jz_clock_lock); + val2 = readl(jz_clock_base + reg); + val2 &= ~mask; + val2 |= val; + writel(val2, jz_clock_base + reg); + spin_unlock(&jz_clock_lock); +} + +static void jz_clk_reg_set_bits(int reg, uint32_t mask) +{ + uint32_t val; + + spin_lock(&jz_clock_lock); + val = readl(jz_clock_base + reg); + val |= mask; + writel(val, jz_clock_base + reg); + spin_unlock(&jz_clock_lock); +} + +static void jz_clk_reg_clear_bits(int reg, uint32_t mask) +{ + uint32_t val; + + spin_lock(&jz_clock_lock); + val = readl(jz_clock_base + reg); + val &= ~mask; + writel(val, jz_clock_base + reg); + spin_unlock(&jz_clock_lock); +} + +static int jz_clk_enable_gating(struct clk *clk) +{ + if (clk->gate_bit == JZ4740_CLK_NOT_GATED) + return -EINVAL; + + jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, clk->gate_bit); + return 0; +} + +static int jz_clk_disable_gating(struct clk *clk) +{ + if (clk->gate_bit == JZ4740_CLK_NOT_GATED) + return -EINVAL; + + jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, clk->gate_bit); + return 0; +} + +static int jz_clk_is_enabled_gating(struct clk *clk) +{ + if (clk->gate_bit == JZ4740_CLK_NOT_GATED) + return 1; + + return !(jz_clk_reg_read(JZ_REG_CLOCK_GATE) & clk->gate_bit); +} + +static unsigned long jz_clk_static_get_rate(struct clk *clk) +{ + return ((struct static_clk *)clk)->rate; +} + +static int jz_clk_ko_enable(struct clk *clk) +{ + jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE); + return 0; +} + +static int jz_clk_ko_disable(struct clk *clk) +{ + jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE); + return 0; +} + +static int jz_clk_ko_is_enabled(struct clk *clk) +{ + return !!(jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_KO_ENABLE); +} + +static const int pllno[] = {1, 2, 2, 4}; + +static unsigned long jz_clk_pll_get_rate(struct clk *clk) +{ + uint32_t val; + int m; + int n; + int od; + + val = jz_clk_reg_read(JZ_REG_CLOCK_PLL); + + if (val & JZ_CLOCK_PLL_BYPASS) + return clk_get_rate(clk->parent); + + m = ((val >> 23) & 0x1ff) + 2; + n = ((val >> 18) & 0x1f) + 2; + od = (val >> 16) & 0x3; + + return ((clk_get_rate(clk->parent) / n) * m) / pllno[od]; +} + +static unsigned long jz_clk_pll_half_get_rate(struct clk *clk) +{ + uint32_t reg; + + reg = jz_clk_reg_read(JZ_REG_CLOCK_CTRL); + if (reg & JZ_CLOCK_CTRL_PLL_HALF) + return jz_clk_pll_get_rate(clk->parent); + return jz_clk_pll_get_rate(clk->parent) >> 1; +} + +static const int jz_clk_main_divs[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; + +static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate) +{ + unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent); + int div; + + div = parent_rate / rate; + if (div > 32) + return parent_rate / 32; + else if (div < 1) + return parent_rate; + + div &= (0x3 << (ffs(div) - 1)); + + return parent_rate / div; +} + +static unsigned long jz_clk_main_get_rate(struct clk *clk) +{ + struct main_clk *mclk = (struct main_clk *)clk; + uint32_t div; + + div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL); + + div >>= mclk->div_offset; + div &= 0xf; + + if (div >= ARRAY_SIZE(jz_clk_main_divs)) + div = ARRAY_SIZE(jz_clk_main_divs) - 1; + + return jz_clk_pll_get_rate(clk->parent) / jz_clk_main_divs[div]; +} + +static int jz_clk_main_set_rate(struct clk *clk, unsigned long rate) +{ + struct main_clk *mclk = (struct main_clk *)clk; + int i; + int div; + unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent); + + rate = jz_clk_main_round_rate(clk, rate); + + div = parent_rate / rate; + + i = (ffs(div) - 1) << 1; + if (i > 0 && !(div & BIT(i-1))) + i -= 1; + + jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, i << mclk->div_offset, + 0xf << mclk->div_offset); + + return 0; +} + +static struct clk_ops jz_clk_static_ops = { + .get_rate = jz_clk_static_get_rate, + .enable = jz_clk_enable_gating, + .disable = jz_clk_disable_gating, + .is_enabled = jz_clk_is_enabled_gating, +}; + +static struct static_clk jz_clk_ext = { + .clk = { + .name = "ext", + .gate_bit = JZ4740_CLK_NOT_GATED, + .ops = &jz_clk_static_ops, + }, +}; + +static struct clk_ops jz_clk_pll_ops = { + .get_rate = jz_clk_pll_get_rate, +}; + +static struct clk jz_clk_pll = { + .name = "pll", + .parent = &jz_clk_ext.clk, + .ops = &jz_clk_pll_ops, +}; + +static struct clk_ops jz_clk_pll_half_ops = { + .get_rate = jz_clk_pll_half_get_rate, +}; + +static struct clk jz_clk_pll_half = { + .name = "pll half", + .parent = &jz_clk_pll, + .ops = &jz_clk_pll_half_ops, +}; + +static const struct clk_ops jz_clk_main_ops = { + .get_rate = jz_clk_main_get_rate, + .set_rate = jz_clk_main_set_rate, + .round_rate = jz_clk_main_round_rate, +}; + +static struct main_clk jz_clk_cpu = { + .clk = { + .name = "cclk", + .parent = &jz_clk_pll, + .ops = &jz_clk_main_ops, + }, + .div_offset = JZ_CLOCK_CTRL_CDIV_OFFSET, +}; + +static struct main_clk jz_clk_memory = { + .clk = { + .name = "mclk", + .parent = &jz_clk_pll, + .ops = &jz_clk_main_ops, + }, + .div_offset = JZ_CLOCK_CTRL_MDIV_OFFSET, +}; + +static struct main_clk jz_clk_high_speed_peripheral = { + .clk = { + .name = "hclk", + .parent = &jz_clk_pll, + .ops = &jz_clk_main_ops, + }, + .div_offset = JZ_CLOCK_CTRL_HDIV_OFFSET, +}; + + +static struct main_clk jz_clk_low_speed_peripheral = { + .clk = { + .name = "pclk", + .parent = &jz_clk_pll, + .ops = &jz_clk_main_ops, + }, + .div_offset = JZ_CLOCK_CTRL_PDIV_OFFSET, +}; + +static const struct clk_ops jz_clk_ko_ops = { + .enable = jz_clk_ko_enable, + .disable = jz_clk_ko_disable, + .is_enabled = jz_clk_ko_is_enabled, +}; + +static struct clk jz_clk_ko = { + .name = "cko", + .parent = &jz_clk_memory.clk, + .ops = &jz_clk_ko_ops, +}; + +static int jz_clk_spi_set_parent(struct clk *clk, struct clk *parent) +{ + if (parent == &jz_clk_pll) + jz_clk_reg_set_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI); + else if (parent == &jz_clk_ext.clk) + jz_clk_reg_clear_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI); + else + return -EINVAL; + + clk->parent = parent; + + return 0; +} + +static int jz_clk_i2s_set_parent(struct clk *clk, struct clk *parent) +{ + if (parent == &jz_clk_pll_half) + jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL); + else if (parent == &jz_clk_ext.clk) + jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL); + else + return -EINVAL; + + clk->parent = parent; + + return 0; +} + +static int jz_clk_udc_enable(struct clk *clk) +{ + jz_clk_reg_set_bits(JZ_REG_CLOCK_SLEEP_CTRL, + JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC); + + return 0; +} + +static int jz_clk_udc_disable(struct clk *clk) +{ + jz_clk_reg_clear_bits(JZ_REG_CLOCK_SLEEP_CTRL, + JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC); + + return 0; +} + +static int jz_clk_udc_is_enabled(struct clk *clk) +{ + return !!(jz_clk_reg_read(JZ_REG_CLOCK_SLEEP_CTRL) & + JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC); +} + +static int jz_clk_udc_set_parent(struct clk *clk, struct clk *parent) +{ + if (parent == &jz_clk_pll_half) + jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL); + else if (parent == &jz_clk_ext.clk) + jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL); + else + return -EINVAL; + + clk->parent = parent; + + return 0; +} + +static int jz_clk_udc_set_rate(struct clk *clk, unsigned long rate) +{ + int div; + + if (clk->parent == &jz_clk_ext.clk) + return -EINVAL; + + div = clk_get_rate(clk->parent) / rate - 1; + + if (div < 0) + div = 0; + else if (div > 63) + div = 63; + + jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_UDIV_OFFSET, + JZ_CLOCK_CTRL_UDIV_MASK); + return 0; +} + +static unsigned long jz_clk_udc_get_rate(struct clk *clk) +{ + int div; + + if (clk->parent == &jz_clk_ext.clk) + return clk_get_rate(clk->parent); + + div = (jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_UDIV_MASK); + div >>= JZ_CLOCK_CTRL_UDIV_OFFSET; + div += 1; + + return clk_get_rate(clk->parent) / div; +} + +static unsigned long jz_clk_divided_get_rate(struct clk *clk) +{ + struct divided_clk *dclk = (struct divided_clk *)clk; + int div; + + if (clk->parent == &jz_clk_ext.clk) + return clk_get_rate(clk->parent); + + div = (jz_clk_reg_read(dclk->reg) & dclk->mask) + 1; + + return clk_get_rate(clk->parent) / div; +} + +static int jz_clk_divided_set_rate(struct clk *clk, unsigned long rate) +{ + struct divided_clk *dclk = (struct divided_clk *)clk; + int div; + + if (clk->parent == &jz_clk_ext.clk) + return -EINVAL; + + div = clk_get_rate(clk->parent) / rate - 1; + + if (div < 0) + div = 0; + else if (div > dclk->mask) + div = dclk->mask; + + jz_clk_reg_write_mask(dclk->reg, div, dclk->mask); + + return 0; +} + +static unsigned long jz_clk_ldclk_round_rate(struct clk *clk, unsigned long rate) +{ + int div; + unsigned long parent_rate = jz_clk_pll_half_get_rate(clk->parent); + + if (rate > 150000000) + return 150000000; + + div = parent_rate / rate; + if (div < 1) + div = 1; + else if (div > 32) + div = 32; + + return parent_rate / div; +} + +static int jz_clk_ldclk_set_rate(struct clk *clk, unsigned long rate) +{ + int div; + + if (rate > 150000000) + return -EINVAL; + + div = jz_clk_pll_half_get_rate(clk->parent) / rate - 1; + if (div < 0) + div = 0; + else if (div > 31) + div = 31; + + jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_LDIV_OFFSET, + JZ_CLOCK_CTRL_LDIV_MASK); + + return 0; +} + +static unsigned long jz_clk_ldclk_get_rate(struct clk *clk) +{ + int div; + + div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_LDIV_MASK; + div >>= JZ_CLOCK_CTRL_LDIV_OFFSET; + + return jz_clk_pll_half_get_rate(clk->parent) / (div + 1); +} + +static const struct clk_ops jz_clk_ops_ld = { + .set_rate = jz_clk_ldclk_set_rate, + .get_rate = jz_clk_ldclk_get_rate, + .round_rate = jz_clk_ldclk_round_rate, + .enable = jz_clk_enable_gating, + .disable = jz_clk_disable_gating, + .is_enabled = jz_clk_is_enabled_gating, +}; + +static struct clk jz_clk_ld = { + .name = "lcd", + .gate_bit = JZ_CLOCK_GATE_LCD, + .parent = &jz_clk_pll_half, + .ops = &jz_clk_ops_ld, +}; + +static const struct clk_ops jz_clk_i2s_ops = { + .set_rate = jz_clk_divided_set_rate, + .get_rate = jz_clk_divided_get_rate, + .enable = jz_clk_enable_gating, + .disable = jz_clk_disable_gating, + .is_enabled = jz_clk_is_enabled_gating, + .set_parent = jz_clk_i2s_set_parent, +}; + +static const struct clk_ops jz_clk_spi_ops = { + .set_rate = jz_clk_divided_set_rate, + .get_rate = jz_clk_divided_get_rate, + .enable = jz_clk_enable_gating, + .disable = jz_clk_disable_gating, + .is_enabled = jz_clk_is_enabled_gating, + .set_parent = jz_clk_spi_set_parent, +}; + +static const struct clk_ops jz_clk_divided_ops = { + .set_rate = jz_clk_divided_set_rate, + .get_rate = jz_clk_divided_get_rate, + .enable = jz_clk_enable_gating, + .disable = jz_clk_disable_gating, + .is_enabled = jz_clk_is_enabled_gating, +}; + +static struct divided_clk jz4740_clock_divided_clks[] = { + [0] = { + .clk = { + .name = "i2s", + .parent = &jz_clk_ext.clk, + .gate_bit = JZ_CLOCK_GATE_I2S, + .ops = &jz_clk_i2s_ops, + }, + .reg = JZ_REG_CLOCK_I2S, + .mask = JZ_CLOCK_I2S_DIV_MASK, + }, + [1] = { + .clk = { + .name = "spi", + .parent = &jz_clk_ext.clk, + .gate_bit = JZ_CLOCK_GATE_SPI, + .ops = &jz_clk_spi_ops, + }, + .reg = JZ_REG_CLOCK_SPI, + .mask = JZ_CLOCK_SPI_DIV_MASK, + }, + [2] = { + .clk = { + .name = "lcd_pclk", + .parent = &jz_clk_pll_half, + .gate_bit = JZ4740_CLK_NOT_GATED, + .ops = &jz_clk_divided_ops, + }, + .reg = JZ_REG_CLOCK_LCD, + .mask = JZ_CLOCK_LCD_DIV_MASK, + }, + [3] = { + .clk = { + .name = "mmc", + .parent = &jz_clk_pll_half, + .gate_bit = JZ_CLOCK_GATE_MMC, + .ops = &jz_clk_divided_ops, + }, + .reg = JZ_REG_CLOCK_MMC, + .mask = JZ_CLOCK_MMC_DIV_MASK, + }, + [4] = { + .clk = { + .name = "uhc", + .parent = &jz_clk_pll_half, + .gate_bit = JZ_CLOCK_GATE_UHC, + .ops = &jz_clk_divided_ops, + }, + .reg = JZ_REG_CLOCK_UHC, + .mask = JZ_CLOCK_UHC_DIV_MASK, + }, +}; + +static const struct clk_ops jz_clk_udc_ops = { + .set_parent = jz_clk_udc_set_parent, + .set_rate = jz_clk_udc_set_rate, + .get_rate = jz_clk_udc_get_rate, + .enable = jz_clk_udc_enable, + .disable = jz_clk_udc_disable, + .is_enabled = jz_clk_udc_is_enabled, +}; + +static const struct clk_ops jz_clk_simple_ops = { + .enable = jz_clk_enable_gating, + .disable = jz_clk_disable_gating, + .is_enabled = jz_clk_is_enabled_gating, +}; + +static struct clk jz4740_clock_simple_clks[] = { + [0] = { + .name = "udc", + .parent = &jz_clk_ext.clk, + .ops = &jz_clk_udc_ops, + }, + [1] = { + .name = "uart0", + .parent = &jz_clk_ext.clk, + .gate_bit = JZ_CLOCK_GATE_UART0, + .ops = &jz_clk_simple_ops, + }, + [2] = { + .name = "uart1", + .parent = &jz_clk_ext.clk, + .gate_bit = JZ_CLOCK_GATE_UART1, + .ops = &jz_clk_simple_ops, + }, + [3] = { + .name = "dma", + .parent = &jz_clk_high_speed_peripheral.clk, + .gate_bit = JZ_CLOCK_GATE_UART0, + .ops = &jz_clk_simple_ops, + }, + [4] = { + .name = "ipu", + .parent = &jz_clk_high_speed_peripheral.clk, + .gate_bit = JZ_CLOCK_GATE_IPU, + .ops = &jz_clk_simple_ops, + }, + [5] = { + .name = "adc", + .parent = &jz_clk_ext.clk, + .gate_bit = JZ_CLOCK_GATE_ADC, + .ops = &jz_clk_simple_ops, + }, + [6] = { + .name = "i2c", + .parent = &jz_clk_ext.clk, + .gate_bit = JZ_CLOCK_GATE_I2C, + .ops = &jz_clk_simple_ops, + }, + [7] = { + .name = "aic", + .parent = &jz_clk_ext.clk, + .gate_bit = JZ_CLOCK_GATE_AIC, + .ops = &jz_clk_simple_ops, + }, +}; + +static struct static_clk jz_clk_rtc = { + .clk = { + .name = "rtc", + .gate_bit = JZ_CLOCK_GATE_RTC, + .ops = &jz_clk_static_ops, + }, + .rate = 32768, +}; + +int clk_enable(struct clk *clk) +{ + if (!clk->ops->enable) + return -EINVAL; + + return clk->ops->enable(clk); +} +EXPORT_SYMBOL_GPL(clk_enable); + +void clk_disable(struct clk *clk) +{ + if (clk->ops->disable) + clk->ops->disable(clk); +} +EXPORT_SYMBOL_GPL(clk_disable); + +int clk_is_enabled(struct clk *clk) +{ + if (clk->ops->is_enabled) + return clk->ops->is_enabled(clk); + + return 1; +} + +unsigned long clk_get_rate(struct clk *clk) +{ + if (clk->ops->get_rate) + return clk->ops->get_rate(clk); + if (clk->parent) + return clk_get_rate(clk->parent); + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(clk_get_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + if (!clk->ops->set_rate) + return -EINVAL; + return clk->ops->set_rate(clk, rate); +} +EXPORT_SYMBOL_GPL(clk_set_rate); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + if (clk->ops->round_rate) + return clk->ops->round_rate(clk, rate); + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(clk_round_rate); + +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + int ret; + int enabled; + + if (!clk->ops->set_parent) + return -EINVAL; + + enabled = clk_is_enabled(clk); + if (enabled) + clk_disable(clk); + ret = clk->ops->set_parent(clk, parent); + if (enabled) + clk_enable(clk); + + jz4740_clock_debugfs_update_parent(clk); + + return ret; +} +EXPORT_SYMBOL_GPL(clk_set_parent); + +struct clk *clk_get(struct device *dev, const char *name) +{ + struct clk *clk; + + list_for_each_entry(clk, &jz_clocks, list) { + if (strcmp(clk->name, name) == 0) + return clk; + } + return ERR_PTR(-ENXIO); +} +EXPORT_SYMBOL_GPL(clk_get); + +void clk_put(struct clk *clk) +{ +} +EXPORT_SYMBOL_GPL(clk_put); + +static inline void clk_add(struct clk *clk) +{ + list_add_tail(&clk->list, &jz_clocks); + + jz4740_clock_debugfs_add_clk(clk); +} + +static void clk_register_clks(void) +{ + size_t i; + + clk_add(&jz_clk_ext.clk); + clk_add(&jz_clk_pll); + clk_add(&jz_clk_pll_half); + clk_add(&jz_clk_cpu.clk); + clk_add(&jz_clk_high_speed_peripheral.clk); + clk_add(&jz_clk_low_speed_peripheral.clk); + clk_add(&jz_clk_ko); + clk_add(&jz_clk_ld); + clk_add(&jz_clk_rtc.clk); + + for (i = 0; i < ARRAY_SIZE(jz4740_clock_divided_clks); ++i) + clk_add(&jz4740_clock_divided_clks[i].clk); + + for (i = 0; i < ARRAY_SIZE(jz4740_clock_simple_clks); ++i) + clk_add(&jz4740_clock_simple_clks[i]); +} + +void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode) +{ + switch (mode) { + case JZ4740_WAIT_MODE_IDLE: + jz_clk_reg_clear_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP); + break; + case JZ4740_WAIT_MODE_SLEEP: + jz_clk_reg_set_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP); + break; + } +} + +void jz4740_clock_udc_disable_auto_suspend(void) +{ + jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC); +} +EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend); + +void jz4740_clock_udc_enable_auto_suspend(void) +{ + jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC); +} +EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend); + +void jz4740_clock_suspend(void) +{ + jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, + JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0); + + jz_clk_reg_clear_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED); +} + +void jz4740_clock_resume(void) +{ + uint32_t pll; + + jz_clk_reg_set_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED); + + do { + pll = jz_clk_reg_read(JZ_REG_CLOCK_PLL); + } while (!(pll & JZ_CLOCK_PLL_STABLE)); + + jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, + JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0); +} + +static int jz4740_clock_init(void) +{ + uint32_t val; + + jz_clock_base = ioremap(JZ4740_CPM_BASE_ADDR, 0x100); + if (!jz_clock_base) + return -EBUSY; + + spin_lock_init(&jz_clock_lock); + + jz_clk_ext.rate = jz4740_clock_bdata.ext_rate; + jz_clk_rtc.rate = jz4740_clock_bdata.rtc_rate; + + val = jz_clk_reg_read(JZ_REG_CLOCK_SPI); + + if (val & JZ_CLOCK_SPI_SRC_PLL) + jz4740_clock_divided_clks[1].clk.parent = &jz_clk_pll_half; + + val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL); + + if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL) + jz4740_clock_divided_clks[0].clk.parent = &jz_clk_pll_half; + + if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL) + jz4740_clock_simple_clks[0].parent = &jz_clk_pll_half; + + jz4740_clock_debugfs_init(); + + clk_register_clks(); + + return 0; +} +arch_initcall(jz4740_clock_init); diff --git a/arch/mips/jz4740/clock.h b/arch/mips/jz4740/clock.h new file mode 100644 index 0000000..5d07499 --- /dev/null +++ b/arch/mips/jz4740/clock.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * JZ4740 SoC clock support + * + * 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. + * + * 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 __MIPS_JZ4740_CLOCK_H__ +#define __MIPS_JZ4740_CLOCK_H__ + +#include + +struct jz4740_clock_board_data { + unsigned long ext_rate; + unsigned long rtc_rate; +}; + +extern struct jz4740_clock_board_data jz4740_clock_bdata; + +void jz4740_clock_suspend(void); +void jz4740_clock_resume(void); + +struct clk; + +struct clk_ops { + unsigned long (*get_rate)(struct clk *clk); + unsigned long (*round_rate)(struct clk *clk, unsigned long rate); + int (*set_rate)(struct clk *clk, unsigned long rate); + int (*enable)(struct clk *clk); + int (*disable)(struct clk *clk); + int (*is_enabled)(struct clk *clk); + + int (*set_parent)(struct clk *clk, struct clk *parent); + +}; + +struct clk { + const char *name; + struct clk *parent; + + uint32_t gate_bit; + + const struct clk_ops *ops; + + struct list_head list; + +#ifdef CONFIG_DEBUG_FS + struct dentry *debugfs_entry; + struct dentry *debugfs_parent_entry; +#endif + +}; + +#define JZ4740_CLK_NOT_GATED ((uint32_t)-1) + +int clk_is_enabled(struct clk *clk); + +#ifdef CONFIG_DEBUG_FS +void jz4740_clock_debugfs_init(void); +void jz4740_clock_debugfs_add_clk(struct clk *clk); +void jz4740_clock_debugfs_update_parent(struct clk *clk); +#else +static inline void jz4740_clock_debugfs_init(void) {}; +static inline void jz4740_clock_debugfs_add_clk(struct clk *clk) {}; +static inline void jz4740_clock_debugfs_update_parent(struct clk *clk) {}; +#endif + +#endif -- cgit v0.10.2 From 9869848d12601cdddf097a36aebe0b10dc5d177b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 17 Jul 2010 11:08:43 +0000 Subject: MIPS: JZ4740: Add IRQ handler code Add support for IRQ handling on a JZ4740 SoC. Signed-off-by: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1465/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-jz4740/irq.h b/arch/mips/include/asm/mach-jz4740/irq.h new file mode 100644 index 0000000..a865c98 --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/irq.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * JZ4740 IRQ definitions + * + * 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. + * + * 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_MACH_JZ4740_IRQ_H__ +#define __ASM_MACH_JZ4740_IRQ_H__ + +#define MIPS_CPU_IRQ_BASE 0 +#define JZ4740_IRQ_BASE 8 + +/* 1st-level interrupts */ +#define JZ4740_IRQ(x) (JZ4740_IRQ_BASE + (x)) +#define JZ4740_IRQ_I2C JZ4740_IRQ(1) +#define JZ4740_IRQ_UHC JZ4740_IRQ(3) +#define JZ4740_IRQ_UART1 JZ4740_IRQ(8) +#define JZ4740_IRQ_UART0 JZ4740_IRQ(9) +#define JZ4740_IRQ_SADC JZ4740_IRQ(12) +#define JZ4740_IRQ_MSC JZ4740_IRQ(14) +#define JZ4740_IRQ_RTC JZ4740_IRQ(15) +#define JZ4740_IRQ_SSI JZ4740_IRQ(16) +#define JZ4740_IRQ_CIM JZ4740_IRQ(17) +#define JZ4740_IRQ_AIC JZ4740_IRQ(18) +#define JZ4740_IRQ_ETH JZ4740_IRQ(19) +#define JZ4740_IRQ_DMAC JZ4740_IRQ(20) +#define JZ4740_IRQ_TCU2 JZ4740_IRQ(21) +#define JZ4740_IRQ_TCU1 JZ4740_IRQ(22) +#define JZ4740_IRQ_TCU0 JZ4740_IRQ(23) +#define JZ4740_IRQ_UDC JZ4740_IRQ(24) +#define JZ4740_IRQ_GPIO3 JZ4740_IRQ(25) +#define JZ4740_IRQ_GPIO2 JZ4740_IRQ(26) +#define JZ4740_IRQ_GPIO1 JZ4740_IRQ(27) +#define JZ4740_IRQ_GPIO0 JZ4740_IRQ(28) +#define JZ4740_IRQ_IPU JZ4740_IRQ(29) +#define JZ4740_IRQ_LCD JZ4740_IRQ(30) + +/* 2nd-level interrupts */ +#define JZ4740_IRQ_DMA(x) (JZ4740_IRQ(32) + (X)) + +#define JZ4740_IRQ_INTC_GPIO(x) (JZ4740_IRQ_GPIO0 - (x)) +#define JZ4740_IRQ_GPIO(x) (JZ4740_IRQ(48) + (x)) + +#define JZ4740_IRQ_ADC_BASE JZ4740_IRQ(176) + +#define NR_IRQS (JZ4740_IRQ_ADC_BASE + 6) + +#endif diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c new file mode 100644 index 0000000..7d33ff8 --- /dev/null +++ b/arch/mips/jz4740/irq.c @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * JZ4740 platform IRQ support + * + * 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. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +static void __iomem *jz_intc_base; +static uint32_t jz_intc_wakeup; +static uint32_t jz_intc_saved; + +#define JZ_REG_INTC_STATUS 0x00 +#define JZ_REG_INTC_MASK 0x04 +#define JZ_REG_INTC_SET_MASK 0x08 +#define JZ_REG_INTC_CLEAR_MASK 0x0c +#define JZ_REG_INTC_PENDING 0x10 + +#define IRQ_BIT(x) BIT((x) - JZ4740_IRQ_BASE) + +static void intc_irq_unmask(unsigned int irq) +{ + writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_CLEAR_MASK); +} + +static void intc_irq_mask(unsigned int irq) +{ + writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_SET_MASK); +} + +static int intc_irq_set_wake(unsigned int irq, unsigned int on) +{ + if (on) + jz_intc_wakeup |= IRQ_BIT(irq); + else + jz_intc_wakeup &= ~IRQ_BIT(irq); + + return 0; +} + +static struct irq_chip intc_irq_type = { + .name = "INTC", + .mask = intc_irq_mask, + .mask_ack = intc_irq_mask, + .unmask = intc_irq_unmask, + .set_wake = intc_irq_set_wake, +}; + +static irqreturn_t jz4740_cascade(int irq, void *data) +{ + uint32_t irq_reg; + + irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING); + + if (irq_reg) + generic_handle_irq(__fls(irq_reg) + JZ4740_IRQ_BASE); + + return IRQ_HANDLED; +} + +static struct irqaction jz4740_cascade_action = { + .handler = jz4740_cascade, + .name = "JZ4740 cascade interrupt", +}; + +void __init arch_init_irq(void) +{ + int i; + mips_cpu_irq_init(); + + jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14); + + for (i = JZ4740_IRQ_BASE; i < JZ4740_IRQ_BASE + 32; i++) { + intc_irq_mask(i); + set_irq_chip_and_handler(i, &intc_irq_type, handle_level_irq); + } + + setup_irq(2, &jz4740_cascade_action); +} + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; + if (pending & STATUSF_IP2) + do_IRQ(2); + else if (pending & STATUSF_IP3) + do_IRQ(3); + else + spurious_interrupt(); +} + +void jz4740_intc_suspend(void) +{ + jz_intc_saved = readl(jz_intc_base + JZ_REG_INTC_MASK); + writel(~jz_intc_wakeup, jz_intc_base + JZ_REG_INTC_SET_MASK); + writel(jz_intc_wakeup, jz_intc_base + JZ_REG_INTC_CLEAR_MASK); +} + +void jz4740_intc_resume(void) +{ + writel(~jz_intc_saved, jz_intc_base + JZ_REG_INTC_CLEAR_MASK); + writel(jz_intc_saved, jz_intc_base + JZ_REG_INTC_SET_MASK); +} + +#ifdef CONFIG_DEBUG_FS + +static inline void intc_seq_reg(struct seq_file *s, const char *name, + unsigned int reg) +{ + seq_printf(s, "%s:\t\t%08x\n", name, readl(jz_intc_base + reg)); +} + +static int intc_regs_show(struct seq_file *s, void *unused) +{ + intc_seq_reg(s, "Status", JZ_REG_INTC_STATUS); + intc_seq_reg(s, "Mask", JZ_REG_INTC_MASK); + intc_seq_reg(s, "Pending", JZ_REG_INTC_PENDING); + + return 0; +} + +static int intc_regs_open(struct inode *inode, struct file *file) +{ + return single_open(file, intc_regs_show, NULL); +} + +static const struct file_operations intc_regs_operations = { + .open = intc_regs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init intc_debugfs_init(void) +{ + (void) debugfs_create_file("jz_regs_intc", S_IFREG | S_IRUGO, + NULL, NULL, &intc_regs_operations); + return 0; +} +subsys_initcall(intc_debugfs_init); + +#endif diff --git a/arch/mips/jz4740/irq.h b/arch/mips/jz4740/irq.h new file mode 100644 index 0000000..56b5ead --- /dev/null +++ b/arch/mips/jz4740/irq.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * + * 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. + * + * 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 __MIPS_JZ4740_IRQ_H__ +#define __MIPS_JZ4740_IRQ_H__ + +extern void jz4740_intc_suspend(void); +extern void jz4740_intc_resume(void); + +#endif -- cgit v0.10.2 From 544a7324198972716d486e04e77bc2622e12245b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 19 Jun 2010 04:08:09 +0000 Subject: MIPS: JZ4740: Add timer support Add support for the timer/counter unit on a JZ4740 SoC. This code is used as a common base for the JZ4740 clocksource/clockevent implementation and PWM support. Signed-off-by: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1396/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-jz4740/timer.h b/arch/mips/include/asm/mach-jz4740/timer.h new file mode 100644 index 0000000..9baa03c --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/timer.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * JZ4740 platform timer support + * + * 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. + * + * 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_MACH_JZ4740_TIMER +#define __ASM_MACH_JZ4740_TIMER + +void jz4740_timer_enable_watchdog(void); +void jz4740_timer_disable_watchdog(void); + +#endif diff --git a/arch/mips/jz4740/timer.c b/arch/mips/jz4740/timer.c new file mode 100644 index 0000000..b2c0151 --- /dev/null +++ b/arch/mips/jz4740/timer.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * JZ4740 platform timer support + * + * 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. + * + * 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. + * + */ + +#include +#include +#include + +#include "timer.h" + +#include + +void __iomem *jz4740_timer_base; + +void jz4740_timer_enable_watchdog(void) +{ + writel(BIT(16), jz4740_timer_base + JZ_REG_TIMER_STOP_CLEAR); +} + +void jz4740_timer_disable_watchdog(void) +{ + writel(BIT(16), jz4740_timer_base + JZ_REG_TIMER_STOP_SET); +} + +void __init jz4740_timer_init(void) +{ + jz4740_timer_base = ioremap(JZ4740_TCU_BASE_ADDR, 0x100); + + if (!jz4740_timer_base) + panic("Failed to ioremap timer registers"); + + /* Disable all timer clocks except for those used as system timers */ + writel(0x000100fc, jz4740_timer_base + JZ_REG_TIMER_STOP_SET); + + /* Timer irqs are unmasked by default, mask them */ + writel(0x00ff00ff, jz4740_timer_base + JZ_REG_TIMER_MASK_SET); +} diff --git a/arch/mips/jz4740/timer.h b/arch/mips/jz4740/timer.h new file mode 100644 index 0000000..fca3994 --- /dev/null +++ b/arch/mips/jz4740/timer.h @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * JZ4740 platform timer support + * + * 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. + * + * 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 __MIPS_JZ4740_TIMER_H__ +#define __MIPS_JZ4740_TIMER_H__ + +#include +#include + +#define JZ_REG_TIMER_STOP 0x0C +#define JZ_REG_TIMER_STOP_SET 0x1C +#define JZ_REG_TIMER_STOP_CLEAR 0x2C +#define JZ_REG_TIMER_ENABLE 0x00 +#define JZ_REG_TIMER_ENABLE_SET 0x04 +#define JZ_REG_TIMER_ENABLE_CLEAR 0x08 +#define JZ_REG_TIMER_FLAG 0x10 +#define JZ_REG_TIMER_FLAG_SET 0x14 +#define JZ_REG_TIMER_FLAG_CLEAR 0x18 +#define JZ_REG_TIMER_MASK 0x20 +#define JZ_REG_TIMER_MASK_SET 0x24 +#define JZ_REG_TIMER_MASK_CLEAR 0x28 + +#define JZ_REG_TIMER_DFR(x) (((x) * 0x10) + 0x30) +#define JZ_REG_TIMER_DHR(x) (((x) * 0x10) + 0x34) +#define JZ_REG_TIMER_CNT(x) (((x) * 0x10) + 0x38) +#define JZ_REG_TIMER_CTRL(x) (((x) * 0x10) + 0x3C) + +#define JZ_TIMER_IRQ_HALF(x) BIT((x) + 0x10) +#define JZ_TIMER_IRQ_FULL(x) BIT(x) + +#define JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN BIT(9) +#define JZ_TIMER_CTRL_PWM_ACTIVE_LOW BIT(8) +#define JZ_TIMER_CTRL_PWM_ENABLE BIT(7) +#define JZ_TIMER_CTRL_PRESCALE_MASK 0x1c +#define JZ_TIMER_CTRL_PRESCALE_OFFSET 0x3 +#define JZ_TIMER_CTRL_PRESCALE_1 (0 << 3) +#define JZ_TIMER_CTRL_PRESCALE_4 (1 << 3) +#define JZ_TIMER_CTRL_PRESCALE_16 (2 << 3) +#define JZ_TIMER_CTRL_PRESCALE_64 (3 << 3) +#define JZ_TIMER_CTRL_PRESCALE_256 (4 << 3) +#define JZ_TIMER_CTRL_PRESCALE_1024 (5 << 3) + +#define JZ_TIMER_CTRL_PRESCALER(x) ((x) << JZ_TIMER_CTRL_PRESCALE_OFFSET) + +#define JZ_TIMER_CTRL_SRC_EXT BIT(2) +#define JZ_TIMER_CTRL_SRC_RTC BIT(1) +#define JZ_TIMER_CTRL_SRC_PCLK BIT(0) + +extern void __iomem *jz4740_timer_base; +void __init jz4740_timer_init(void); + +static inline void jz4740_timer_stop(unsigned int timer) +{ + writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_SET); +} + +static inline void jz4740_timer_start(unsigned int timer) +{ + writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_CLEAR); +} + +static inline bool jz4740_timer_is_enabled(unsigned int timer) +{ + return readb(jz4740_timer_base + JZ_REG_TIMER_ENABLE) & BIT(timer); +} + +static inline void jz4740_timer_enable(unsigned int timer) +{ + writeb(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_ENABLE_SET); +} + +static inline void jz4740_timer_disable(unsigned int timer) +{ + writeb(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_ENABLE_CLEAR); +} + + +static inline void jz4740_timer_set_period(unsigned int timer, uint16_t period) +{ + writew(period, jz4740_timer_base + JZ_REG_TIMER_DFR(timer)); +} + +static inline void jz4740_timer_set_duty(unsigned int timer, uint16_t duty) +{ + writew(duty, jz4740_timer_base + JZ_REG_TIMER_DHR(timer)); +} + +static inline void jz4740_timer_set_count(unsigned int timer, uint16_t count) +{ + writew(count, jz4740_timer_base + JZ_REG_TIMER_CNT(timer)); +} + +static inline uint16_t jz4740_timer_get_count(unsigned int timer) +{ + return readw(jz4740_timer_base + JZ_REG_TIMER_CNT(timer)); +} + +static inline void jz4740_timer_ack_full(unsigned int timer) +{ + writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_FLAG_CLEAR); +} + +static inline void jz4740_timer_irq_full_enable(unsigned int timer) +{ + writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_FLAG_CLEAR); + writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_CLEAR); +} + +static inline void jz4740_timer_irq_full_disable(unsigned int timer) +{ + writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_SET); +} + +static inline void jz4740_timer_set_ctrl(unsigned int timer, uint16_t ctrl) +{ + writew(ctrl, jz4740_timer_base + JZ_REG_TIMER_CTRL(timer)); +} + +static inline uint16_t jz4740_timer_get_ctrl(unsigned int timer) +{ + return readw(jz4740_timer_base + JZ_REG_TIMER_CTRL(timer)); +} + +#endif -- cgit v0.10.2 From b200eff6d16cf53dfaf14eb6f1934890d2db2237 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 19 Jun 2010 04:08:10 +0000 Subject: MIPS: JZ4740: Add clocksource/clockevent support. Add clocksource and clockevent support for the timer/counter unit on JZ4740 SoCs. Signed-off-by: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1397/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c new file mode 100644 index 0000000..fe01678 --- /dev/null +++ b/arch/mips/jz4740/time.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * JZ4740 platform time support + * + * 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. + * + * 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. + * + */ + +#include +#include +#include + +#include + +#include +#include + +#include "clock.h" +#include "timer.h" + +#define TIMER_CLOCKEVENT 0 +#define TIMER_CLOCKSOURCE 1 + +static uint16_t jz4740_jiffies_per_tick; + +static cycle_t jz4740_clocksource_read(struct clocksource *cs) +{ + return jz4740_timer_get_count(TIMER_CLOCKSOURCE); +} + +static struct clocksource jz4740_clocksource = { + .name = "jz4740-timer", + .rating = 200, + .read = jz4740_clocksource_read, + .mask = CLOCKSOURCE_MASK(16), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static irqreturn_t jz4740_clockevent_irq(int irq, void *devid) +{ + struct clock_event_device *cd = devid; + + jz4740_timer_ack_full(TIMER_CLOCKEVENT); + + if (cd->mode != CLOCK_EVT_MODE_PERIODIC) + jz4740_timer_disable(TIMER_CLOCKEVENT); + + cd->event_handler(cd); + + return IRQ_HANDLED; +} + +static void jz4740_clockevent_set_mode(enum clock_event_mode mode, + struct clock_event_device *cd) +{ + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + jz4740_timer_set_count(TIMER_CLOCKEVENT, 0); + jz4740_timer_set_period(TIMER_CLOCKEVENT, jz4740_jiffies_per_tick); + case CLOCK_EVT_MODE_RESUME: + jz4740_timer_irq_full_enable(TIMER_CLOCKEVENT); + jz4740_timer_enable(TIMER_CLOCKEVENT); + break; + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_SHUTDOWN: + jz4740_timer_disable(TIMER_CLOCKEVENT); + break; + default: + break; + } +} + +static int jz4740_clockevent_set_next(unsigned long evt, + struct clock_event_device *cd) +{ + jz4740_timer_set_count(TIMER_CLOCKEVENT, 0); + jz4740_timer_set_period(TIMER_CLOCKEVENT, evt); + jz4740_timer_enable(TIMER_CLOCKEVENT); + + return 0; +} + +static struct clock_event_device jz4740_clockevent = { + .name = "jz4740-timer", + .features = CLOCK_EVT_FEAT_PERIODIC, + .set_next_event = jz4740_clockevent_set_next, + .set_mode = jz4740_clockevent_set_mode, + .rating = 200, + .irq = JZ4740_IRQ_TCU0, +}; + +static struct irqaction timer_irqaction = { + .handler = jz4740_clockevent_irq, + .flags = IRQF_PERCPU | IRQF_TIMER, + .name = "jz4740-timerirq", + .dev_id = &jz4740_clockevent, +}; + +void __init plat_time_init(void) +{ + int ret; + uint32_t clk_rate; + uint16_t ctrl; + + jz4740_timer_init(); + + clk_rate = jz4740_clock_bdata.ext_rate >> 4; + jz4740_jiffies_per_tick = DIV_ROUND_CLOSEST(clk_rate, HZ); + + clockevent_set_clock(&jz4740_clockevent, clk_rate); + jz4740_clockevent.min_delta_ns = clockevent_delta2ns(100, &jz4740_clockevent); + jz4740_clockevent.max_delta_ns = clockevent_delta2ns(0xffff, &jz4740_clockevent); + jz4740_clockevent.cpumask = cpumask_of(0); + + clockevents_register_device(&jz4740_clockevent); + + clocksource_set_clock(&jz4740_clocksource, clk_rate); + ret = clocksource_register(&jz4740_clocksource); + + if (ret) + printk(KERN_ERR "Failed to register clocksource: %d\n", ret); + + setup_irq(JZ4740_IRQ_TCU0, &timer_irqaction); + + ctrl = JZ_TIMER_CTRL_PRESCALE_16 | JZ_TIMER_CTRL_SRC_EXT; + + jz4740_timer_set_ctrl(TIMER_CLOCKEVENT, ctrl); + jz4740_timer_set_ctrl(TIMER_CLOCKSOURCE, ctrl); + + jz4740_timer_set_period(TIMER_CLOCKEVENT, jz4740_jiffies_per_tick); + jz4740_timer_irq_full_enable(TIMER_CLOCKEVENT); + + jz4740_timer_set_period(TIMER_CLOCKSOURCE, 0xffff); + + jz4740_timer_enable(TIMER_CLOCKEVENT); + jz4740_timer_enable(TIMER_CLOCKSOURCE); +} -- cgit v0.10.2 From c863a2368ced0e6df07121d13933ee0f5a5ee681 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 19 Jun 2010 04:08:11 +0000 Subject: MIPS: JZ4740: Add power-management and system reset support Add support for suspend/resume and poweroff/reboot on a JZ4740 SoC. Signed-off-by: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1398/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/jz4740/pm.c b/arch/mips/jz4740/pm.c new file mode 100644 index 0000000..a999458 --- /dev/null +++ b/arch/mips/jz4740/pm.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * JZ4740 SoC power management support + * + * 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. + * + * 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. + * + */ + +#include +#include +#include +#include + +#include + +#include "clock.h" +#include "irq.h" + +static int jz4740_pm_enter(suspend_state_t state) +{ + jz4740_intc_suspend(); + jz4740_clock_suspend(); + + jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_SLEEP); + + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); + + jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_IDLE); + + jz4740_clock_resume(); + jz4740_intc_resume(); + + return 0; +} + +static struct platform_suspend_ops jz4740_pm_ops = { + .valid = suspend_valid_only_mem, + .enter = jz4740_pm_enter, +}; + +static int __init jz4740_pm_init(void) +{ + suspend_set_ops(&jz4740_pm_ops); + return 0; + +} +late_initcall(jz4740_pm_init); diff --git a/arch/mips/jz4740/reset.c b/arch/mips/jz4740/reset.c new file mode 100644 index 0000000..5f1fb95 --- /dev/null +++ b/arch/mips/jz4740/reset.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * + * 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. + * + * 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. + * + */ + +#include +#include +#include + +#include + +#include +#include + +static void jz4740_halt(void) +{ + while (1) { + __asm__(".set push;\n" + ".set mips3;\n" + "wait;\n" + ".set pop;\n" + ); + } +} + +#define JZ_REG_WDT_DATA 0x00 +#define JZ_REG_WDT_COUNTER_ENABLE 0x04 +#define JZ_REG_WDT_COUNTER 0x08 +#define JZ_REG_WDT_CTRL 0x0c + +static void jz4740_restart(char *command) +{ + void __iomem *wdt_base = ioremap(JZ4740_WDT_BASE_ADDR, 0x0f); + + jz4740_timer_enable_watchdog(); + + writeb(0, wdt_base + JZ_REG_WDT_COUNTER_ENABLE); + + writew(0, wdt_base + JZ_REG_WDT_COUNTER); + writew(0, wdt_base + JZ_REG_WDT_DATA); + writew(BIT(2), wdt_base + JZ_REG_WDT_CTRL); + + writeb(1, wdt_base + JZ_REG_WDT_COUNTER_ENABLE); + jz4740_halt(); +} + +#define JZ_REG_RTC_CTRL 0x00 +#define JZ_REG_RTC_HIBERNATE 0x20 + +#define JZ_RTC_CTRL_WRDY BIT(7) + +static void jz4740_power_off(void) +{ + void __iomem *rtc_base = ioremap(JZ4740_RTC_BASE_ADDR, 0x24); + uint32_t ctrl; + + do { + ctrl = readl(rtc_base + JZ_REG_RTC_CTRL); + } while (!(ctrl & JZ_RTC_CTRL_WRDY)); + + writel(1, rtc_base + JZ_REG_RTC_HIBERNATE); + jz4740_halt(); +} + +void jz4740_reset_init(void) +{ + _machine_restart = jz4740_restart; + _machine_halt = jz4740_halt; + pm_power_off = jz4740_power_off; +} diff --git a/arch/mips/jz4740/reset.h b/arch/mips/jz4740/reset.h new file mode 100644 index 0000000..5202ab4 --- /dev/null +++ b/arch/mips/jz4740/reset.h @@ -0,0 +1,6 @@ +#ifndef __MIPS_JZ4740_RESET_H__ +#define __MIPS_JZ4740_RESET_H__ + +extern void jz4740_reset_init(void); + +#endif -- cgit v0.10.2 From 713233fbaf8c859f71b246c81baf082c0e6b9625 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 19 Jun 2010 04:08:12 +0000 Subject: MIPS: JZ4740: Add setup code Add plat_mem_setup and get_system_type for JZ4740 SoCs. Signed-off-by: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1399/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c new file mode 100644 index 0000000..6a9e14d --- /dev/null +++ b/arch/mips/jz4740/setup.c @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * JZ4740 setup code + * + * 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. + * + * 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. + * + */ + +#include +#include + +#include "reset.h" + +void __init plat_mem_setup(void) +{ + jz4740_reset_init(); +} + +const char *get_system_type(void) +{ + return "JZ4740"; +} -- cgit v0.10.2 From a55f4506652cbdf23fa1b5fd509d4f3cc01e1843 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 17 Jul 2010 11:11:19 +0000 Subject: MIPS: JZ4740: Add GPIO support Add gpiolib support for JZ4740 SoCs. Signed-off-by: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1467/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-jz4740/gpio.h b/arch/mips/include/asm/mach-jz4740/gpio.h new file mode 100644 index 0000000..7b74703 --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/gpio.h @@ -0,0 +1,398 @@ +/* + * Copyright (C) 2009, Lars-Peter Clausen + * JZ4740 GPIO pin definitions + * + * 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. + * + * 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 _JZ_GPIO_H +#define _JZ_GPIO_H + +#include + +enum jz_gpio_function { + JZ_GPIO_FUNC_NONE, + JZ_GPIO_FUNC1, + JZ_GPIO_FUNC2, + JZ_GPIO_FUNC3, +}; + + +/* + Usually a driver for a SoC component has to request several gpio pins and + configure them as funcion pins. + jz_gpio_bulk_request can be used to ease this process. + Usually one would do something like: + + const static struct jz_gpio_bulk_request i2c_pins[] = { + JZ_GPIO_BULK_PIN(I2C_SDA), + JZ_GPIO_BULK_PIN(I2C_SCK), + }; + + inside the probe function: + + ret = jz_gpio_bulk_request(i2c_pins, ARRAY_SIZE(i2c_pins)); + if (ret) { + ... + + inside the remove function: + + jz_gpio_bulk_free(i2c_pins, ARRAY_SIZE(i2c_pins)); + + +*/ +struct jz_gpio_bulk_request { + int gpio; + const char *name; + enum jz_gpio_function function; +}; + +#define JZ_GPIO_BULK_PIN(pin) { \ + .gpio = JZ_GPIO_ ## pin, \ + .name = #pin, \ + .function = JZ_GPIO_FUNC_ ## pin \ +} + +int jz_gpio_bulk_request(const struct jz_gpio_bulk_request *request, size_t num); +void jz_gpio_bulk_free(const struct jz_gpio_bulk_request *request, size_t num); +void jz_gpio_bulk_suspend(const struct jz_gpio_bulk_request *request, size_t num); +void jz_gpio_bulk_resume(const struct jz_gpio_bulk_request *request, size_t num); +void jz_gpio_enable_pullup(unsigned gpio); +void jz_gpio_disable_pullup(unsigned gpio); +int jz_gpio_set_function(int gpio, enum jz_gpio_function function); + +int jz_gpio_port_direction_input(int port, uint32_t mask); +int jz_gpio_port_direction_output(int port, uint32_t mask); +void jz_gpio_port_set_value(int port, uint32_t value, uint32_t mask); +uint32_t jz_gpio_port_get_value(int port, uint32_t mask); + +#include + +#define JZ_GPIO_PORTA(x) ((x) + 32 * 0) +#define JZ_GPIO_PORTB(x) ((x) + 32 * 1) +#define JZ_GPIO_PORTC(x) ((x) + 32 * 2) +#define JZ_GPIO_PORTD(x) ((x) + 32 * 3) + +/* Port A function pins */ +#define JZ_GPIO_MEM_DATA0 JZ_GPIO_PORTA(0) +#define JZ_GPIO_MEM_DATA1 JZ_GPIO_PORTA(1) +#define JZ_GPIO_MEM_DATA2 JZ_GPIO_PORTA(2) +#define JZ_GPIO_MEM_DATA3 JZ_GPIO_PORTA(3) +#define JZ_GPIO_MEM_DATA4 JZ_GPIO_PORTA(4) +#define JZ_GPIO_MEM_DATA5 JZ_GPIO_PORTA(5) +#define JZ_GPIO_MEM_DATA6 JZ_GPIO_PORTA(6) +#define JZ_GPIO_MEM_DATA7 JZ_GPIO_PORTA(7) +#define JZ_GPIO_MEM_DATA8 JZ_GPIO_PORTA(8) +#define JZ_GPIO_MEM_DATA9 JZ_GPIO_PORTA(9) +#define JZ_GPIO_MEM_DATA10 JZ_GPIO_PORTA(10) +#define JZ_GPIO_MEM_DATA11 JZ_GPIO_PORTA(11) +#define JZ_GPIO_MEM_DATA12 JZ_GPIO_PORTA(12) +#define JZ_GPIO_MEM_DATA13 JZ_GPIO_PORTA(13) +#define JZ_GPIO_MEM_DATA14 JZ_GPIO_PORTA(14) +#define JZ_GPIO_MEM_DATA15 JZ_GPIO_PORTA(15) +#define JZ_GPIO_MEM_DATA16 JZ_GPIO_PORTA(16) +#define JZ_GPIO_MEM_DATA17 JZ_GPIO_PORTA(17) +#define JZ_GPIO_MEM_DATA18 JZ_GPIO_PORTA(18) +#define JZ_GPIO_MEM_DATA19 JZ_GPIO_PORTA(19) +#define JZ_GPIO_MEM_DATA20 JZ_GPIO_PORTA(20) +#define JZ_GPIO_MEM_DATA21 JZ_GPIO_PORTA(21) +#define JZ_GPIO_MEM_DATA22 JZ_GPIO_PORTA(22) +#define JZ_GPIO_MEM_DATA23 JZ_GPIO_PORTA(23) +#define JZ_GPIO_MEM_DATA24 JZ_GPIO_PORTA(24) +#define JZ_GPIO_MEM_DATA25 JZ_GPIO_PORTA(25) +#define JZ_GPIO_MEM_DATA26 JZ_GPIO_PORTA(26) +#define JZ_GPIO_MEM_DATA27 JZ_GPIO_PORTA(27) +#define JZ_GPIO_MEM_DATA28 JZ_GPIO_PORTA(28) +#define JZ_GPIO_MEM_DATA29 JZ_GPIO_PORTA(29) +#define JZ_GPIO_MEM_DATA30 JZ_GPIO_PORTA(30) +#define JZ_GPIO_MEM_DATA31 JZ_GPIO_PORTA(31) + +#define JZ_GPIO_FUNC_MEM_DATA0 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA1 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA2 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA3 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA4 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA5 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA6 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA7 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA8 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA9 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA10 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA11 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA12 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA13 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA14 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA15 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA16 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA17 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA18 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA19 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA20 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA21 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA22 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA23 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA24 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA25 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA26 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA27 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA28 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA29 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA30 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DATA31 JZ_GPIO_FUNC1 + +/* Port B function pins */ +#define JZ_GPIO_MEM_ADDR0 JZ_GPIO_PORTB(0) +#define JZ_GPIO_MEM_ADDR1 JZ_GPIO_PORTB(1) +#define JZ_GPIO_MEM_ADDR2 JZ_GPIO_PORTB(2) +#define JZ_GPIO_MEM_ADDR3 JZ_GPIO_PORTB(3) +#define JZ_GPIO_MEM_ADDR4 JZ_GPIO_PORTB(4) +#define JZ_GPIO_MEM_ADDR5 JZ_GPIO_PORTB(5) +#define JZ_GPIO_MEM_ADDR6 JZ_GPIO_PORTB(6) +#define JZ_GPIO_MEM_ADDR7 JZ_GPIO_PORTB(7) +#define JZ_GPIO_MEM_ADDR8 JZ_GPIO_PORTB(8) +#define JZ_GPIO_MEM_ADDR9 JZ_GPIO_PORTB(9) +#define JZ_GPIO_MEM_ADDR10 JZ_GPIO_PORTB(10) +#define JZ_GPIO_MEM_ADDR11 JZ_GPIO_PORTB(11) +#define JZ_GPIO_MEM_ADDR12 JZ_GPIO_PORTB(12) +#define JZ_GPIO_MEM_ADDR13 JZ_GPIO_PORTB(13) +#define JZ_GPIO_MEM_ADDR14 JZ_GPIO_PORTB(14) +#define JZ_GPIO_MEM_ADDR15 JZ_GPIO_PORTB(15) +#define JZ_GPIO_MEM_ADDR16 JZ_GPIO_PORTB(16) +#define JZ_GPIO_LCD_CLS JZ_GPIO_PORTB(17) +#define JZ_GPIO_LCD_SPL JZ_GPIO_PORTB(18) +#define JZ_GPIO_MEM_DCS JZ_GPIO_PORTB(19) +#define JZ_GPIO_MEM_RAS JZ_GPIO_PORTB(20) +#define JZ_GPIO_MEM_CAS JZ_GPIO_PORTB(21) +#define JZ_GPIO_MEM_SDWE JZ_GPIO_PORTB(22) +#define JZ_GPIO_MEM_CKE JZ_GPIO_PORTB(23) +#define JZ_GPIO_MEM_CKO JZ_GPIO_PORTB(24) +#define JZ_GPIO_MEM_CS0 JZ_GPIO_PORTB(25) +#define JZ_GPIO_MEM_CS1 JZ_GPIO_PORTB(26) +#define JZ_GPIO_MEM_CS2 JZ_GPIO_PORTB(27) +#define JZ_GPIO_MEM_CS3 JZ_GPIO_PORTB(28) +#define JZ_GPIO_MEM_RD JZ_GPIO_PORTB(29) +#define JZ_GPIO_MEM_WR JZ_GPIO_PORTB(30) +#define JZ_GPIO_MEM_WE0 JZ_GPIO_PORTB(31) + +#define JZ_GPIO_FUNC_MEM_ADDR0 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_ADDR1 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_ADDR2 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_ADDR3 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_ADDR4 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_ADDR5 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_ADDR6 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_ADDR7 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_ADDR8 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_ADDR9 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_ADDR10 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_ADDR11 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_ADDR12 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_ADDR13 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_ADDR14 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_ADDR15 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_ADDR16 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_CLS JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_SPL JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_DCS JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_RAS JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_CAS JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_SDWE JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_CKE JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_CKO JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_CS0 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_CS1 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_CS2 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_CS3 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_RD JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_WR JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_WE0 JZ_GPIO_FUNC1 + + +#define JZ_GPIO_MEM_ADDR21 JZ_GPIO_PORTB(17) +#define JZ_GPIO_MEM_ADDR22 JZ_GPIO_PORTB(18) + +#define JZ_GPIO_FUNC_MEM_ADDR21 JZ_GPIO_FUNC2 +#define JZ_GPIO_FUNC_MEM_ADDR22 JZ_GPIO_FUNC2 + +/* Port C function pins */ +#define JZ_GPIO_LCD_DATA0 JZ_GPIO_PORTC(0) +#define JZ_GPIO_LCD_DATA1 JZ_GPIO_PORTC(1) +#define JZ_GPIO_LCD_DATA2 JZ_GPIO_PORTC(2) +#define JZ_GPIO_LCD_DATA3 JZ_GPIO_PORTC(3) +#define JZ_GPIO_LCD_DATA4 JZ_GPIO_PORTC(4) +#define JZ_GPIO_LCD_DATA5 JZ_GPIO_PORTC(5) +#define JZ_GPIO_LCD_DATA6 JZ_GPIO_PORTC(6) +#define JZ_GPIO_LCD_DATA7 JZ_GPIO_PORTC(7) +#define JZ_GPIO_LCD_DATA8 JZ_GPIO_PORTC(8) +#define JZ_GPIO_LCD_DATA9 JZ_GPIO_PORTC(9) +#define JZ_GPIO_LCD_DATA10 JZ_GPIO_PORTC(10) +#define JZ_GPIO_LCD_DATA11 JZ_GPIO_PORTC(11) +#define JZ_GPIO_LCD_DATA12 JZ_GPIO_PORTC(12) +#define JZ_GPIO_LCD_DATA13 JZ_GPIO_PORTC(13) +#define JZ_GPIO_LCD_DATA14 JZ_GPIO_PORTC(14) +#define JZ_GPIO_LCD_DATA15 JZ_GPIO_PORTC(15) +#define JZ_GPIO_LCD_DATA16 JZ_GPIO_PORTC(16) +#define JZ_GPIO_LCD_DATA17 JZ_GPIO_PORTC(17) +#define JZ_GPIO_LCD_PCLK JZ_GPIO_PORTC(18) +#define JZ_GPIO_LCD_HSYNC JZ_GPIO_PORTC(19) +#define JZ_GPIO_LCD_VSYNC JZ_GPIO_PORTC(20) +#define JZ_GPIO_LCD_DE JZ_GPIO_PORTC(21) +#define JZ_GPIO_LCD_PS JZ_GPIO_PORTC(22) +#define JZ_GPIO_LCD_REV JZ_GPIO_PORTC(23) +#define JZ_GPIO_MEM_WE1 JZ_GPIO_PORTC(24) +#define JZ_GPIO_MEM_WE2 JZ_GPIO_PORTC(25) +#define JZ_GPIO_MEM_WE3 JZ_GPIO_PORTC(26) +#define JZ_GPIO_MEM_WAIT JZ_GPIO_PORTC(27) +#define JZ_GPIO_MEM_FRE JZ_GPIO_PORTC(28) +#define JZ_GPIO_MEM_FWE JZ_GPIO_PORTC(29) + +#define JZ_GPIO_FUNC_LCD_DATA0 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_DATA1 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_DATA2 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_DATA3 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_DATA4 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_DATA5 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_DATA6 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_DATA7 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_DATA8 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_DATA9 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_DATA10 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_DATA11 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_DATA12 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_DATA13 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_DATA14 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_DATA15 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_DATA16 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_DATA17 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_PCLK JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_VSYNC JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_HSYNC JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_DE JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_PS JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_LCD_REV JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_WE1 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_WE2 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_WE3 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_WAIT JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_FRE JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MEM_FWE JZ_GPIO_FUNC1 + + +#define JZ_GPIO_MEM_ADDR19 JZ_GPIO_PORTB(22) +#define JZ_GPIO_MEM_ADDR20 JZ_GPIO_PORTB(23) + +#define JZ_GPIO_FUNC_MEM_ADDR19 JZ_GPIO_FUNC2 +#define JZ_GPIO_FUNC_MEM_ADDR20 JZ_GPIO_FUNC2 + +/* Port D function pins */ +#define JZ_GPIO_CIM_DATA0 JZ_GPIO_PORTD(0) +#define JZ_GPIO_CIM_DATA1 JZ_GPIO_PORTD(1) +#define JZ_GPIO_CIM_DATA2 JZ_GPIO_PORTD(2) +#define JZ_GPIO_CIM_DATA3 JZ_GPIO_PORTD(3) +#define JZ_GPIO_CIM_DATA4 JZ_GPIO_PORTD(4) +#define JZ_GPIO_CIM_DATA5 JZ_GPIO_PORTD(5) +#define JZ_GPIO_CIM_DATA6 JZ_GPIO_PORTD(6) +#define JZ_GPIO_CIM_DATA7 JZ_GPIO_PORTD(7) +#define JZ_GPIO_MSC_CMD JZ_GPIO_PORTD(8) +#define JZ_GPIO_MSC_CLK JZ_GPIO_PORTD(9) +#define JZ_GPIO_MSC_DATA0 JZ_GPIO_PORTD(10) +#define JZ_GPIO_MSC_DATA1 JZ_GPIO_PORTD(11) +#define JZ_GPIO_MSC_DATA2 JZ_GPIO_PORTD(12) +#define JZ_GPIO_MSC_DATA3 JZ_GPIO_PORTD(13) +#define JZ_GPIO_CIM_MCLK JZ_GPIO_PORTD(14) +#define JZ_GPIO_CIM_PCLK JZ_GPIO_PORTD(15) +#define JZ_GPIO_CIM_VSYNC JZ_GPIO_PORTD(16) +#define JZ_GPIO_CIM_HSYNC JZ_GPIO_PORTD(17) +#define JZ_GPIO_SPI_CLK JZ_GPIO_PORTD(18) +#define JZ_GPIO_SPI_CE0 JZ_GPIO_PORTD(19) +#define JZ_GPIO_SPI_DT JZ_GPIO_PORTD(20) +#define JZ_GPIO_SPI_DR JZ_GPIO_PORTD(21) +#define JZ_GPIO_SPI_CE1 JZ_GPIO_PORTD(22) +#define JZ_GPIO_PWM0 JZ_GPIO_PORTD(23) +#define JZ_GPIO_PWM1 JZ_GPIO_PORTD(24) +#define JZ_GPIO_PWM2 JZ_GPIO_PORTD(25) +#define JZ_GPIO_PWM3 JZ_GPIO_PORTD(26) +#define JZ_GPIO_PWM4 JZ_GPIO_PORTD(27) +#define JZ_GPIO_PWM5 JZ_GPIO_PORTD(28) +#define JZ_GPIO_PWM6 JZ_GPIO_PORTD(30) +#define JZ_GPIO_PWM7 JZ_GPIO_PORTD(31) + +#define JZ_GPIO_FUNC_CIM_DATA JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_CIM_DATA0 JZ_GPIO_FUNC_CIM_DATA +#define JZ_GPIO_FUNC_CIM_DATA1 JZ_GPIO_FUNC_CIM_DATA +#define JZ_GPIO_FUNC_CIM_DATA2 JZ_GPIO_FUNC_CIM_DATA +#define JZ_GPIO_FUNC_CIM_DATA3 JZ_GPIO_FUNC_CIM_DATA +#define JZ_GPIO_FUNC_CIM_DATA4 JZ_GPIO_FUNC_CIM_DATA +#define JZ_GPIO_FUNC_CIM_DATA5 JZ_GPIO_FUNC_CIM_DATA +#define JZ_GPIO_FUNC_CIM_DATA6 JZ_GPIO_FUNC_CIM_DATA +#define JZ_GPIO_FUNC_CIM_DATA7 JZ_GPIO_FUNC_CIM_DATA +#define JZ_GPIO_FUNC_MSC_CMD JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MSC_CLK JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MSC_DATA JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_MSC_DATA0 JZ_GPIO_FUNC_MSC_DATA +#define JZ_GPIO_FUNC_MSC_DATA1 JZ_GPIO_FUNC_MSC_DATA +#define JZ_GPIO_FUNC_MSC_DATA2 JZ_GPIO_FUNC_MSC_DATA +#define JZ_GPIO_FUNC_MSC_DATA3 JZ_GPIO_FUNC_MSC_DATA +#define JZ_GPIO_FUNC_CIM_MCLK JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_CIM_PCLK JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_CIM_VSYNC JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_CIM_HSYNC JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_SPI_CLK JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_SPI_CE0 JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_SPI_DT JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_SPI_DR JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_SPI_CE1 JZ_GPIO_FUNC1 + +#define JZ_GPIO_FUNC_PWM JZ_GPIO_FUNC1 +#define JZ_GPIO_FUNC_PWM0 JZ_GPIO_FUNC_PWM +#define JZ_GPIO_FUNC_PWM1 JZ_GPIO_FUNC_PWM +#define JZ_GPIO_FUNC_PWM2 JZ_GPIO_FUNC_PWM +#define JZ_GPIO_FUNC_PWM3 JZ_GPIO_FUNC_PWM +#define JZ_GPIO_FUNC_PWM4 JZ_GPIO_FUNC_PWM +#define JZ_GPIO_FUNC_PWM5 JZ_GPIO_FUNC_PWM +#define JZ_GPIO_FUNC_PWM6 JZ_GPIO_FUNC_PWM +#define JZ_GPIO_FUNC_PWM7 JZ_GPIO_FUNC_PWM + +#define JZ_GPIO_MEM_SCLK_RSTN JZ_GPIO_PORTD(18) +#define JZ_GPIO_MEM_BCLK JZ_GPIO_PORTD(19) +#define JZ_GPIO_MEM_SDATO JZ_GPIO_PORTD(20) +#define JZ_GPIO_MEM_SDATI JZ_GPIO_PORTD(21) +#define JZ_GPIO_MEM_SYNC JZ_GPIO_PORTD(22) +#define JZ_GPIO_I2C_SDA JZ_GPIO_PORTD(23) +#define JZ_GPIO_I2C_SCK JZ_GPIO_PORTD(24) +#define JZ_GPIO_UART0_TXD JZ_GPIO_PORTD(25) +#define JZ_GPIO_UART0_RXD JZ_GPIO_PORTD(26) +#define JZ_GPIO_MEM_ADDR17 JZ_GPIO_PORTD(27) +#define JZ_GPIO_MEM_ADDR18 JZ_GPIO_PORTD(28) +#define JZ_GPIO_UART0_CTS JZ_GPIO_PORTD(30) +#define JZ_GPIO_UART0_RTS JZ_GPIO_PORTD(31) + +#define JZ_GPIO_FUNC_MEM_SCLK_RSTN JZ_GPIO_FUNC2 +#define JZ_GPIO_FUNC_MEM_BCLK JZ_GPIO_FUNC2 +#define JZ_GPIO_FUNC_MEM_SDATO JZ_GPIO_FUNC2 +#define JZ_GPIO_FUNC_MEM_SDATI JZ_GPIO_FUNC2 +#define JZ_GPIO_FUNC_MEM_SYNC JZ_GPIO_FUNC2 +#define JZ_GPIO_FUNC_I2C_SDA JZ_GPIO_FUNC2 +#define JZ_GPIO_FUNC_I2C_SCK JZ_GPIO_FUNC2 +#define JZ_GPIO_FUNC_UART0_TXD JZ_GPIO_FUNC2 +#define JZ_GPIO_FUNC_UART0_RXD JZ_GPIO_FUNC2 +#define JZ_GPIO_FUNC_MEM_ADDR17 JZ_GPIO_FUNC2 +#define JZ_GPIO_FUNC_MEM_ADDR18 JZ_GPIO_FUNC2 +#define JZ_GPIO_FUNC_UART0_CTS JZ_GPIO_FUNC2 +#define JZ_GPIO_FUNC_UART0_RTS JZ_GPIO_FUNC2 + +#define JZ_GPIO_UART1_RXD JZ_GPIO_PORTD(30) +#define JZ_GPIO_UART1_TXD JZ_GPIO_PORTD(31) + +#define JZ_GPIO_FUNC_UART1_RXD JZ_GPIO_FUNC3 +#define JZ_GPIO_FUNC_UART1_TXD JZ_GPIO_FUNC3 + +#endif diff --git a/arch/mips/jz4740/gpio.c b/arch/mips/jz4740/gpio.c new file mode 100644 index 0000000..38f60f3 --- /dev/null +++ b/arch/mips/jz4740/gpio.c @@ -0,0 +1,604 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * JZ4740 platform GPIO support + * + * 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. + * + * 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. + * + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define JZ4740_GPIO_BASE_A (32*0) +#define JZ4740_GPIO_BASE_B (32*1) +#define JZ4740_GPIO_BASE_C (32*2) +#define JZ4740_GPIO_BASE_D (32*3) + +#define JZ4740_GPIO_NUM_A 32 +#define JZ4740_GPIO_NUM_B 32 +#define JZ4740_GPIO_NUM_C 31 +#define JZ4740_GPIO_NUM_D 32 + +#define JZ4740_IRQ_GPIO_BASE_A (JZ4740_IRQ_GPIO(0) + JZ4740_GPIO_BASE_A) +#define JZ4740_IRQ_GPIO_BASE_B (JZ4740_IRQ_GPIO(0) + JZ4740_GPIO_BASE_B) +#define JZ4740_IRQ_GPIO_BASE_C (JZ4740_IRQ_GPIO(0) + JZ4740_GPIO_BASE_C) +#define JZ4740_IRQ_GPIO_BASE_D (JZ4740_IRQ_GPIO(0) + JZ4740_GPIO_BASE_D) + +#define JZ_REG_GPIO_PIN 0x00 +#define JZ_REG_GPIO_DATA 0x10 +#define JZ_REG_GPIO_DATA_SET 0x14 +#define JZ_REG_GPIO_DATA_CLEAR 0x18 +#define JZ_REG_GPIO_MASK 0x20 +#define JZ_REG_GPIO_MASK_SET 0x24 +#define JZ_REG_GPIO_MASK_CLEAR 0x28 +#define JZ_REG_GPIO_PULL 0x30 +#define JZ_REG_GPIO_PULL_SET 0x34 +#define JZ_REG_GPIO_PULL_CLEAR 0x38 +#define JZ_REG_GPIO_FUNC 0x40 +#define JZ_REG_GPIO_FUNC_SET 0x44 +#define JZ_REG_GPIO_FUNC_CLEAR 0x48 +#define JZ_REG_GPIO_SELECT 0x50 +#define JZ_REG_GPIO_SELECT_SET 0x54 +#define JZ_REG_GPIO_SELECT_CLEAR 0x58 +#define JZ_REG_GPIO_DIRECTION 0x60 +#define JZ_REG_GPIO_DIRECTION_SET 0x64 +#define JZ_REG_GPIO_DIRECTION_CLEAR 0x68 +#define JZ_REG_GPIO_TRIGGER 0x70 +#define JZ_REG_GPIO_TRIGGER_SET 0x74 +#define JZ_REG_GPIO_TRIGGER_CLEAR 0x78 +#define JZ_REG_GPIO_FLAG 0x80 +#define JZ_REG_GPIO_FLAG_CLEAR 0x14 + +#define GPIO_TO_BIT(gpio) BIT(gpio & 0x1f) +#define GPIO_TO_REG(gpio, reg) (gpio_to_jz_gpio_chip(gpio)->base + (reg)) +#define CHIP_TO_REG(chip, reg) (gpio_chip_to_jz_gpio_chip(chip)->base + (reg)) + +struct jz_gpio_chip { + unsigned int irq; + unsigned int irq_base; + uint32_t wakeup; + uint32_t suspend_mask; + uint32_t edge_trigger_both; + + void __iomem *base; + + spinlock_t lock; + + struct gpio_chip gpio_chip; + struct irq_chip irq_chip; + struct sys_device sysdev; +}; + +static struct jz_gpio_chip jz4740_gpio_chips[]; + +static inline struct jz_gpio_chip *gpio_to_jz_gpio_chip(unsigned int gpio) +{ + return &jz4740_gpio_chips[gpio >> 5]; +} + +static inline struct jz_gpio_chip *gpio_chip_to_jz_gpio_chip(struct gpio_chip *gpio_chip) +{ + return container_of(gpio_chip, struct jz_gpio_chip, gpio_chip); +} + +static inline struct jz_gpio_chip *irq_to_jz_gpio_chip(unsigned int irq) +{ + return get_irq_chip_data(irq); +} + +static inline void jz_gpio_write_bit(unsigned int gpio, unsigned int reg) +{ + writel(GPIO_TO_BIT(gpio), GPIO_TO_REG(gpio, reg)); +} + +int jz_gpio_set_function(int gpio, enum jz_gpio_function function) +{ + if (function == JZ_GPIO_FUNC_NONE) { + jz_gpio_write_bit(gpio, JZ_REG_GPIO_FUNC_CLEAR); + jz_gpio_write_bit(gpio, JZ_REG_GPIO_SELECT_CLEAR); + jz_gpio_write_bit(gpio, JZ_REG_GPIO_TRIGGER_CLEAR); + } else { + jz_gpio_write_bit(gpio, JZ_REG_GPIO_FUNC_SET); + jz_gpio_write_bit(gpio, JZ_REG_GPIO_TRIGGER_CLEAR); + switch (function) { + case JZ_GPIO_FUNC1: + jz_gpio_write_bit(gpio, JZ_REG_GPIO_SELECT_CLEAR); + break; + case JZ_GPIO_FUNC3: + jz_gpio_write_bit(gpio, JZ_REG_GPIO_TRIGGER_SET); + case JZ_GPIO_FUNC2: /* Falltrough */ + jz_gpio_write_bit(gpio, JZ_REG_GPIO_SELECT_SET); + break; + default: + BUG(); + break; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(jz_gpio_set_function); + +int jz_gpio_bulk_request(const struct jz_gpio_bulk_request *request, size_t num) +{ + size_t i; + int ret; + + for (i = 0; i < num; ++i, ++request) { + ret = gpio_request(request->gpio, request->name); + if (ret) + goto err; + jz_gpio_set_function(request->gpio, request->function); + } + + return 0; + +err: + for (--request; i > 0; --i, --request) { + gpio_free(request->gpio); + jz_gpio_set_function(request->gpio, JZ_GPIO_FUNC_NONE); + } + + return ret; +} +EXPORT_SYMBOL_GPL(jz_gpio_bulk_request); + +void jz_gpio_bulk_free(const struct jz_gpio_bulk_request *request, size_t num) +{ + size_t i; + + for (i = 0; i < num; ++i, ++request) { + gpio_free(request->gpio); + jz_gpio_set_function(request->gpio, JZ_GPIO_FUNC_NONE); + } + +} +EXPORT_SYMBOL_GPL(jz_gpio_bulk_free); + +void jz_gpio_bulk_suspend(const struct jz_gpio_bulk_request *request, size_t num) +{ + size_t i; + + for (i = 0; i < num; ++i, ++request) { + jz_gpio_set_function(request->gpio, JZ_GPIO_FUNC_NONE); + jz_gpio_write_bit(request->gpio, JZ_REG_GPIO_DIRECTION_CLEAR); + jz_gpio_write_bit(request->gpio, JZ_REG_GPIO_PULL_SET); + } +} +EXPORT_SYMBOL_GPL(jz_gpio_bulk_suspend); + +void jz_gpio_bulk_resume(const struct jz_gpio_bulk_request *request, size_t num) +{ + size_t i; + + for (i = 0; i < num; ++i, ++request) + jz_gpio_set_function(request->gpio, request->function); +} +EXPORT_SYMBOL_GPL(jz_gpio_bulk_resume); + +void jz_gpio_enable_pullup(unsigned gpio) +{ + jz_gpio_write_bit(gpio, JZ_REG_GPIO_PULL_CLEAR); +} +EXPORT_SYMBOL_GPL(jz_gpio_enable_pullup); + +void jz_gpio_disable_pullup(unsigned gpio) +{ + jz_gpio_write_bit(gpio, JZ_REG_GPIO_PULL_SET); +} +EXPORT_SYMBOL_GPL(jz_gpio_disable_pullup); + +static int jz_gpio_get_value(struct gpio_chip *chip, unsigned gpio) +{ + return !!(readl(CHIP_TO_REG(chip, JZ_REG_GPIO_PIN)) & BIT(gpio)); +} + +static void jz_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value) +{ + uint32_t __iomem *reg = CHIP_TO_REG(chip, JZ_REG_GPIO_DATA_SET); + reg += !value; + writel(BIT(gpio), reg); +} + +static int jz_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, + int value) +{ + writel(BIT(gpio), CHIP_TO_REG(chip, JZ_REG_GPIO_DIRECTION_SET)); + jz_gpio_set_value(chip, gpio, value); + + return 0; +} + +static int jz_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) +{ + writel(BIT(gpio), CHIP_TO_REG(chip, JZ_REG_GPIO_DIRECTION_CLEAR)); + + return 0; +} + +int jz_gpio_port_direction_input(int port, uint32_t mask) +{ + writel(mask, GPIO_TO_REG(port, JZ_REG_GPIO_DIRECTION_CLEAR)); + + return 0; +} +EXPORT_SYMBOL(jz_gpio_port_direction_input); + +int jz_gpio_port_direction_output(int port, uint32_t mask) +{ + writel(mask, GPIO_TO_REG(port, JZ_REG_GPIO_DIRECTION_SET)); + + return 0; +} +EXPORT_SYMBOL(jz_gpio_port_direction_output); + +void jz_gpio_port_set_value(int port, uint32_t value, uint32_t mask) +{ + writel(~value & mask, GPIO_TO_REG(port, JZ_REG_GPIO_DATA_CLEAR)); + writel(value & mask, GPIO_TO_REG(port, JZ_REG_GPIO_DATA_SET)); +} +EXPORT_SYMBOL(jz_gpio_port_set_value); + +uint32_t jz_gpio_port_get_value(int port, uint32_t mask) +{ + uint32_t value = readl(GPIO_TO_REG(port, JZ_REG_GPIO_PIN)); + + return value & mask; +} +EXPORT_SYMBOL(jz_gpio_port_get_value); + +int gpio_to_irq(unsigned gpio) +{ + return JZ4740_IRQ_GPIO(0) + gpio; +} +EXPORT_SYMBOL_GPL(gpio_to_irq); + +int irq_to_gpio(unsigned irq) +{ + return irq - JZ4740_IRQ_GPIO(0); +} +EXPORT_SYMBOL_GPL(irq_to_gpio); + +#define IRQ_TO_BIT(irq) BIT(irq_to_gpio(irq) & 0x1f) + +static void jz_gpio_check_trigger_both(struct jz_gpio_chip *chip, unsigned int irq) +{ + uint32_t value; + void __iomem *reg; + uint32_t mask = IRQ_TO_BIT(irq); + + if (!(chip->edge_trigger_both & mask)) + return; + + reg = chip->base; + + value = readl(chip->base + JZ_REG_GPIO_PIN); + if (value & mask) + reg += JZ_REG_GPIO_DIRECTION_CLEAR; + else + reg += JZ_REG_GPIO_DIRECTION_SET; + + writel(mask, reg); +} + +static void jz_gpio_irq_demux_handler(unsigned int irq, struct irq_desc *desc) +{ + uint32_t flag; + unsigned int gpio_irq; + unsigned int gpio_bank; + struct jz_gpio_chip *chip = get_irq_desc_data(desc); + + gpio_bank = JZ4740_IRQ_GPIO0 - irq; + + flag = readl(chip->base + JZ_REG_GPIO_FLAG); + + if (!flag) + return; + + gpio_irq = __fls(flag); + + jz_gpio_check_trigger_both(chip, irq); + + gpio_irq += (gpio_bank << 5) + JZ4740_IRQ_GPIO(0); + + generic_handle_irq(gpio_irq); +}; + +static inline void jz_gpio_set_irq_bit(unsigned int irq, unsigned int reg) +{ + struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq); + writel(IRQ_TO_BIT(irq), chip->base + reg); +} + +static void jz_gpio_irq_mask(unsigned int irq) +{ + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_MASK_SET); +}; + +static void jz_gpio_irq_unmask(unsigned int irq) +{ + struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq); + + jz_gpio_check_trigger_both(chip, irq); + + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_MASK_CLEAR); +}; + +/* TODO: Check if function is gpio */ +static unsigned int jz_gpio_irq_startup(unsigned int irq) +{ + struct irq_desc *desc = irq_to_desc(irq); + + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_SELECT_SET); + + desc->status &= ~IRQ_MASKED; + jz_gpio_irq_unmask(irq); + + return 0; +} + +static void jz_gpio_irq_shutdown(unsigned int irq) +{ + struct irq_desc *desc = irq_to_desc(irq); + + jz_gpio_irq_mask(irq); + desc->status |= IRQ_MASKED; + + /* Set direction to input */ + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR); + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_SELECT_CLEAR); +} + +static void jz_gpio_irq_ack(unsigned int irq) +{ + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_FLAG_CLEAR); +}; + +static int jz_gpio_irq_set_type(unsigned int irq, unsigned int flow_type) +{ + struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq); + struct irq_desc *desc = irq_to_desc(irq); + + jz_gpio_irq_mask(irq); + + if (flow_type == IRQ_TYPE_EDGE_BOTH) { + uint32_t value = readl(chip->base + JZ_REG_GPIO_PIN); + if (value & IRQ_TO_BIT(irq)) + flow_type = IRQ_TYPE_EDGE_FALLING; + else + flow_type = IRQ_TYPE_EDGE_RISING; + chip->edge_trigger_both |= IRQ_TO_BIT(irq); + } else { + chip->edge_trigger_both &= ~IRQ_TO_BIT(irq); + } + + switch (flow_type) { + case IRQ_TYPE_EDGE_RISING: + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_SET); + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_SET); + break; + case IRQ_TYPE_EDGE_FALLING: + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR); + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_SET); + break; + case IRQ_TYPE_LEVEL_HIGH: + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_SET); + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_CLEAR); + break; + case IRQ_TYPE_LEVEL_LOW: + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR); + jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_CLEAR); + break; + default: + return -EINVAL; + } + + if (!(desc->status & IRQ_MASKED)) + jz_gpio_irq_unmask(irq); + + return 0; +} + +static int jz_gpio_irq_set_wake(unsigned int irq, unsigned int on) +{ + struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq); + spin_lock(&chip->lock); + if (on) + chip->wakeup |= IRQ_TO_BIT(irq); + else + chip->wakeup &= ~IRQ_TO_BIT(irq); + spin_unlock(&chip->lock); + + set_irq_wake(chip->irq, on); + return 0; +} + +/* + * This lock class tells lockdep that GPIO irqs are in a different + * category than their parents, so it won't report false recursion. + */ +static struct lock_class_key gpio_lock_class; + +#define JZ4740_GPIO_CHIP(_bank) { \ + .irq_base = JZ4740_IRQ_GPIO_BASE_ ## _bank, \ + .gpio_chip = { \ + .label = "Bank " # _bank, \ + .owner = THIS_MODULE, \ + .set = jz_gpio_set_value, \ + .get = jz_gpio_get_value, \ + .direction_output = jz_gpio_direction_output, \ + .direction_input = jz_gpio_direction_input, \ + .base = JZ4740_GPIO_BASE_ ## _bank, \ + .ngpio = JZ4740_GPIO_NUM_ ## _bank, \ + }, \ + .irq_chip = { \ + .name = "GPIO Bank " # _bank, \ + .mask = jz_gpio_irq_mask, \ + .unmask = jz_gpio_irq_unmask, \ + .ack = jz_gpio_irq_ack, \ + .startup = jz_gpio_irq_startup, \ + .shutdown = jz_gpio_irq_shutdown, \ + .set_type = jz_gpio_irq_set_type, \ + .set_wake = jz_gpio_irq_set_wake, \ + }, \ +} + +static struct jz_gpio_chip jz4740_gpio_chips[] = { + JZ4740_GPIO_CHIP(A), + JZ4740_GPIO_CHIP(B), + JZ4740_GPIO_CHIP(C), + JZ4740_GPIO_CHIP(D), +}; + +static inline struct jz_gpio_chip *sysdev_to_chip(struct sys_device *dev) +{ + return container_of(dev, struct jz_gpio_chip, sysdev); +} + +static int jz4740_gpio_suspend(struct sys_device *dev, pm_message_t state) +{ + struct jz_gpio_chip *chip = sysdev_to_chip(dev); + + chip->suspend_mask = readl(chip->base + JZ_REG_GPIO_MASK); + writel(~(chip->wakeup), chip->base + JZ_REG_GPIO_MASK_SET); + writel(chip->wakeup, chip->base + JZ_REG_GPIO_MASK_CLEAR); + + return 0; +} + +static int jz4740_gpio_resume(struct sys_device *dev) +{ + struct jz_gpio_chip *chip = sysdev_to_chip(dev); + uint32_t mask = chip->suspend_mask; + + writel(~mask, chip->base + JZ_REG_GPIO_MASK_CLEAR); + writel(mask, chip->base + JZ_REG_GPIO_MASK_SET); + + return 0; +} + +static struct sysdev_class jz4740_gpio_sysdev_class = { + .name = "gpio", + .suspend = jz4740_gpio_suspend, + .resume = jz4740_gpio_resume, +}; + +static int jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id) +{ + int ret, irq; + + chip->sysdev.id = id; + chip->sysdev.cls = &jz4740_gpio_sysdev_class; + ret = sysdev_register(&chip->sysdev); + + if (ret) + return ret; + + spin_lock_init(&chip->lock); + + chip->base = ioremap(JZ4740_GPIO_BASE_ADDR + (id * 0x100), 0x100); + + gpiochip_add(&chip->gpio_chip); + + chip->irq = JZ4740_IRQ_INTC_GPIO(id); + set_irq_data(chip->irq, chip); + set_irq_chained_handler(chip->irq, jz_gpio_irq_demux_handler); + + for (irq = chip->irq_base; irq < chip->irq_base + chip->gpio_chip.ngpio; ++irq) { + lockdep_set_class(&irq_desc[irq].lock, &gpio_lock_class); + set_irq_chip_data(irq, chip); + set_irq_chip_and_handler(irq, &chip->irq_chip, handle_level_irq); + } + + return 0; +} + +static int __init jz4740_gpio_init(void) +{ + unsigned int i; + int ret; + + ret = sysdev_class_register(&jz4740_gpio_sysdev_class); + if (ret) + return ret; + + for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); ++i) + jz4740_gpio_chip_init(&jz4740_gpio_chips[i], i); + + printk(KERN_INFO "JZ4740 GPIO initalized\n"); + + return 0; +} +arch_initcall(jz4740_gpio_init); + +#ifdef CONFIG_DEBUG_FS + +static inline void gpio_seq_reg(struct seq_file *s, struct jz_gpio_chip *chip, + const char *name, unsigned int reg) +{ + seq_printf(s, "\t%s: %08x\n", name, readl(chip->base + reg)); +} + +static int gpio_regs_show(struct seq_file *s, void *unused) +{ + struct jz_gpio_chip *chip = jz4740_gpio_chips; + int i; + + for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); ++i, ++chip) { + seq_printf(s, "==GPIO %d==\n", i); + gpio_seq_reg(s, chip, "Pin", JZ_REG_GPIO_PIN); + gpio_seq_reg(s, chip, "Data", JZ_REG_GPIO_DATA); + gpio_seq_reg(s, chip, "Mask", JZ_REG_GPIO_MASK); + gpio_seq_reg(s, chip, "Pull", JZ_REG_GPIO_PULL); + gpio_seq_reg(s, chip, "Func", JZ_REG_GPIO_FUNC); + gpio_seq_reg(s, chip, "Select", JZ_REG_GPIO_SELECT); + gpio_seq_reg(s, chip, "Direction", JZ_REG_GPIO_DIRECTION); + gpio_seq_reg(s, chip, "Trigger", JZ_REG_GPIO_TRIGGER); + gpio_seq_reg(s, chip, "Flag", JZ_REG_GPIO_FLAG); + } + + return 0; +} + +static int gpio_regs_open(struct inode *inode, struct file *file) +{ + return single_open(file, gpio_regs_show, NULL); +} + +static const struct file_operations gpio_regs_operations = { + .open = gpio_regs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init gpio_debugfs_init(void) +{ + (void) debugfs_create_file("jz_regs_gpio", S_IFREG | S_IRUGO, + NULL, NULL, &gpio_regs_operations); + return 0; +} +subsys_initcall(gpio_debugfs_init); + +#endif -- cgit v0.10.2 From 68fcfe7f82f46cc2d0c28128afafbd3a3ff874f8 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 19 Jun 2010 04:08:14 +0000 Subject: MIPS: JZ4740: Add DMA support. Add support for DMA transfers on JZ4740 SoCs. Signed-off-by: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1401/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-jz4740/dma.h b/arch/mips/include/asm/mach-jz4740/dma.h new file mode 100644 index 0000000..a3be121 --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/dma.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * JZ7420/JZ4740 DMA definitions + * + * 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. + * + * 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_MACH_JZ4740_DMA_H__ +#define __ASM_MACH_JZ4740_DMA_H__ + +struct jz4740_dma_chan; + +enum jz4740_dma_request_type { + JZ4740_DMA_TYPE_AUTO_REQUEST = 8, + JZ4740_DMA_TYPE_UART_TRANSMIT = 20, + JZ4740_DMA_TYPE_UART_RECEIVE = 21, + JZ4740_DMA_TYPE_SPI_TRANSMIT = 22, + JZ4740_DMA_TYPE_SPI_RECEIVE = 23, + JZ4740_DMA_TYPE_AIC_TRANSMIT = 24, + JZ4740_DMA_TYPE_AIC_RECEIVE = 25, + JZ4740_DMA_TYPE_MMC_TRANSMIT = 26, + JZ4740_DMA_TYPE_MMC_RECEIVE = 27, + JZ4740_DMA_TYPE_TCU = 28, + JZ4740_DMA_TYPE_SADC = 29, + JZ4740_DMA_TYPE_SLCD = 30, +}; + +enum jz4740_dma_width { + JZ4740_DMA_WIDTH_32BIT = 0, + JZ4740_DMA_WIDTH_8BIT = 1, + JZ4740_DMA_WIDTH_16BIT = 2, +}; + +enum jz4740_dma_transfer_size { + JZ4740_DMA_TRANSFER_SIZE_4BYTE = 0, + JZ4740_DMA_TRANSFER_SIZE_1BYTE = 1, + JZ4740_DMA_TRANSFER_SIZE_2BYTE = 2, + JZ4740_DMA_TRANSFER_SIZE_16BYTE = 3, + JZ4740_DMA_TRANSFER_SIZE_32BYTE = 4, +}; + +enum jz4740_dma_flags { + JZ4740_DMA_SRC_AUTOINC = 0x2, + JZ4740_DMA_DST_AUTOINC = 0x1, +}; + +enum jz4740_dma_mode { + JZ4740_DMA_MODE_SINGLE = 0, + JZ4740_DMA_MODE_BLOCK = 1, +}; + +struct jz4740_dma_config { + enum jz4740_dma_width src_width; + enum jz4740_dma_width dst_width; + enum jz4740_dma_transfer_size transfer_size; + enum jz4740_dma_request_type request_type; + enum jz4740_dma_flags flags; + enum jz4740_dma_mode mode; +}; + +typedef void (*jz4740_dma_complete_callback_t)(struct jz4740_dma_chan *, int, void *); + +struct jz4740_dma_chan *jz4740_dma_request(void *dev, const char *name); +void jz4740_dma_free(struct jz4740_dma_chan *dma); + +void jz4740_dma_configure(struct jz4740_dma_chan *dma, + const struct jz4740_dma_config *config); + + +void jz4740_dma_enable(struct jz4740_dma_chan *dma); +void jz4740_dma_disable(struct jz4740_dma_chan *dma); + +void jz4740_dma_set_src_addr(struct jz4740_dma_chan *dma, dma_addr_t src); +void jz4740_dma_set_dst_addr(struct jz4740_dma_chan *dma, dma_addr_t dst); +void jz4740_dma_set_transfer_count(struct jz4740_dma_chan *dma, uint32_t count); + +uint32_t jz4740_dma_get_residue(const struct jz4740_dma_chan *dma); + +void jz4740_dma_set_complete_cb(struct jz4740_dma_chan *dma, + jz4740_dma_complete_callback_t cb); + +#endif /* __ASM_JZ4740_DMA_H__ */ diff --git a/arch/mips/jz4740/dma.c b/arch/mips/jz4740/dma.c new file mode 100644 index 0000000..5ebe75a --- /dev/null +++ b/arch/mips/jz4740/dma.c @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * JZ4740 SoC DMA support + * + * 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. + * + * 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. + * + */ + +#include +#include +#include +#include + +#include +#include +#include + +#define JZ_REG_DMA_SRC_ADDR(x) (0x00 + (x) * 0x20) +#define JZ_REG_DMA_DST_ADDR(x) (0x04 + (x) * 0x20) +#define JZ_REG_DMA_TRANSFER_COUNT(x) (0x08 + (x) * 0x20) +#define JZ_REG_DMA_REQ_TYPE(x) (0x0C + (x) * 0x20) +#define JZ_REG_DMA_STATUS_CTRL(x) (0x10 + (x) * 0x20) +#define JZ_REG_DMA_CMD(x) (0x14 + (x) * 0x20) +#define JZ_REG_DMA_DESC_ADDR(x) (0x18 + (x) * 0x20) + +#define JZ_REG_DMA_CTRL 0x300 +#define JZ_REG_DMA_IRQ 0x304 +#define JZ_REG_DMA_DOORBELL 0x308 +#define JZ_REG_DMA_DOORBELL_SET 0x30C + +#define JZ_DMA_STATUS_CTRL_NO_DESC BIT(31) +#define JZ_DMA_STATUS_CTRL_DESC_INV BIT(6) +#define JZ_DMA_STATUS_CTRL_ADDR_ERR BIT(4) +#define JZ_DMA_STATUS_CTRL_TRANSFER_DONE BIT(3) +#define JZ_DMA_STATUS_CTRL_HALT BIT(2) +#define JZ_DMA_STATUS_CTRL_COUNT_TERMINATE BIT(1) +#define JZ_DMA_STATUS_CTRL_ENABLE BIT(0) + +#define JZ_DMA_CMD_SRC_INC BIT(23) +#define JZ_DMA_CMD_DST_INC BIT(22) +#define JZ_DMA_CMD_RDIL_MASK (0xf << 16) +#define JZ_DMA_CMD_SRC_WIDTH_MASK (0x3 << 14) +#define JZ_DMA_CMD_DST_WIDTH_MASK (0x3 << 12) +#define JZ_DMA_CMD_INTERVAL_LENGTH_MASK (0x7 << 8) +#define JZ_DMA_CMD_BLOCK_MODE BIT(7) +#define JZ_DMA_CMD_DESC_VALID BIT(4) +#define JZ_DMA_CMD_DESC_VALID_MODE BIT(3) +#define JZ_DMA_CMD_VALID_IRQ_ENABLE BIT(2) +#define JZ_DMA_CMD_TRANSFER_IRQ_ENABLE BIT(1) +#define JZ_DMA_CMD_LINK_ENABLE BIT(0) + +#define JZ_DMA_CMD_FLAGS_OFFSET 22 +#define JZ_DMA_CMD_RDIL_OFFSET 16 +#define JZ_DMA_CMD_SRC_WIDTH_OFFSET 14 +#define JZ_DMA_CMD_DST_WIDTH_OFFSET 12 +#define JZ_DMA_CMD_TRANSFER_SIZE_OFFSET 8 +#define JZ_DMA_CMD_MODE_OFFSET 7 + +#define JZ_DMA_CTRL_PRIORITY_MASK (0x3 << 8) +#define JZ_DMA_CTRL_HALT BIT(3) +#define JZ_DMA_CTRL_ADDRESS_ERROR BIT(2) +#define JZ_DMA_CTRL_ENABLE BIT(0) + + +static void __iomem *jz4740_dma_base; +static spinlock_t jz4740_dma_lock; + +static inline uint32_t jz4740_dma_read(size_t reg) +{ + return readl(jz4740_dma_base + reg); +} + +static inline void jz4740_dma_write(size_t reg, uint32_t val) +{ + writel(val, jz4740_dma_base + reg); +} + +static inline void jz4740_dma_write_mask(size_t reg, uint32_t val, uint32_t mask) +{ + uint32_t val2; + val2 = jz4740_dma_read(reg); + val2 &= ~mask; + val2 |= val; + jz4740_dma_write(reg, val2); +} + +struct jz4740_dma_chan { + unsigned int id; + void *dev; + const char *name; + + enum jz4740_dma_flags flags; + uint32_t transfer_shift; + + jz4740_dma_complete_callback_t complete_cb; + + unsigned used:1; +}; + +#define JZ4740_DMA_CHANNEL(_id) { .id = _id } + +struct jz4740_dma_chan jz4740_dma_channels[] = { + JZ4740_DMA_CHANNEL(0), + JZ4740_DMA_CHANNEL(1), + JZ4740_DMA_CHANNEL(2), + JZ4740_DMA_CHANNEL(3), + JZ4740_DMA_CHANNEL(4), + JZ4740_DMA_CHANNEL(5), +}; + +struct jz4740_dma_chan *jz4740_dma_request(void *dev, const char *name) +{ + unsigned int i; + struct jz4740_dma_chan *dma = NULL; + + spin_lock(&jz4740_dma_lock); + + for (i = 0; i < ARRAY_SIZE(jz4740_dma_channels); ++i) { + if (!jz4740_dma_channels[i].used) { + dma = &jz4740_dma_channels[i]; + dma->used = 1; + break; + } + } + + spin_unlock(&jz4740_dma_lock); + + if (!dma) + return NULL; + + dma->dev = dev; + dma->name = name; + + return dma; +} +EXPORT_SYMBOL_GPL(jz4740_dma_request); + +void jz4740_dma_configure(struct jz4740_dma_chan *dma, + const struct jz4740_dma_config *config) +{ + uint32_t cmd; + + switch (config->transfer_size) { + case JZ4740_DMA_TRANSFER_SIZE_2BYTE: + dma->transfer_shift = 1; + break; + case JZ4740_DMA_TRANSFER_SIZE_4BYTE: + dma->transfer_shift = 2; + break; + case JZ4740_DMA_TRANSFER_SIZE_16BYTE: + dma->transfer_shift = 4; + break; + case JZ4740_DMA_TRANSFER_SIZE_32BYTE: + dma->transfer_shift = 5; + break; + default: + dma->transfer_shift = 0; + break; + } + + cmd = config->flags << JZ_DMA_CMD_FLAGS_OFFSET; + cmd |= config->src_width << JZ_DMA_CMD_SRC_WIDTH_OFFSET; + cmd |= config->dst_width << JZ_DMA_CMD_DST_WIDTH_OFFSET; + cmd |= config->transfer_size << JZ_DMA_CMD_TRANSFER_SIZE_OFFSET; + cmd |= config->mode << JZ_DMA_CMD_MODE_OFFSET; + cmd |= JZ_DMA_CMD_TRANSFER_IRQ_ENABLE; + + jz4740_dma_write(JZ_REG_DMA_CMD(dma->id), cmd); + jz4740_dma_write(JZ_REG_DMA_STATUS_CTRL(dma->id), 0); + jz4740_dma_write(JZ_REG_DMA_REQ_TYPE(dma->id), config->request_type); +} +EXPORT_SYMBOL_GPL(jz4740_dma_configure); + +void jz4740_dma_set_src_addr(struct jz4740_dma_chan *dma, dma_addr_t src) +{ + jz4740_dma_write(JZ_REG_DMA_SRC_ADDR(dma->id), src); +} +EXPORT_SYMBOL_GPL(jz4740_dma_set_src_addr); + +void jz4740_dma_set_dst_addr(struct jz4740_dma_chan *dma, dma_addr_t dst) +{ + jz4740_dma_write(JZ_REG_DMA_DST_ADDR(dma->id), dst); +} +EXPORT_SYMBOL_GPL(jz4740_dma_set_dst_addr); + +void jz4740_dma_set_transfer_count(struct jz4740_dma_chan *dma, uint32_t count) +{ + count >>= dma->transfer_shift; + jz4740_dma_write(JZ_REG_DMA_TRANSFER_COUNT(dma->id), count); +} +EXPORT_SYMBOL_GPL(jz4740_dma_set_transfer_count); + +void jz4740_dma_set_complete_cb(struct jz4740_dma_chan *dma, + jz4740_dma_complete_callback_t cb) +{ + dma->complete_cb = cb; +} +EXPORT_SYMBOL_GPL(jz4740_dma_set_complete_cb); + +void jz4740_dma_free(struct jz4740_dma_chan *dma) +{ + dma->dev = NULL; + dma->complete_cb = NULL; + dma->used = 0; +} +EXPORT_SYMBOL_GPL(jz4740_dma_free); + +void jz4740_dma_enable(struct jz4740_dma_chan *dma) +{ + jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id), + JZ_DMA_STATUS_CTRL_NO_DESC | JZ_DMA_STATUS_CTRL_ENABLE, + JZ_DMA_STATUS_CTRL_HALT | JZ_DMA_STATUS_CTRL_NO_DESC | + JZ_DMA_STATUS_CTRL_ENABLE); + + jz4740_dma_write_mask(JZ_REG_DMA_CTRL, + JZ_DMA_CTRL_ENABLE, + JZ_DMA_CTRL_HALT | JZ_DMA_CTRL_ENABLE); +} +EXPORT_SYMBOL_GPL(jz4740_dma_enable); + +void jz4740_dma_disable(struct jz4740_dma_chan *dma) +{ + jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id), 0, + JZ_DMA_STATUS_CTRL_ENABLE); +} +EXPORT_SYMBOL_GPL(jz4740_dma_disable); + +uint32_t jz4740_dma_get_residue(const struct jz4740_dma_chan *dma) +{ + uint32_t residue; + residue = jz4740_dma_read(JZ_REG_DMA_TRANSFER_COUNT(dma->id)); + return residue << dma->transfer_shift; +} +EXPORT_SYMBOL_GPL(jz4740_dma_get_residue); + +static void jz4740_dma_chan_irq(struct jz4740_dma_chan *dma) +{ + uint32_t status; + + status = jz4740_dma_read(JZ_REG_DMA_STATUS_CTRL(dma->id)); + + jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id), 0, + JZ_DMA_STATUS_CTRL_ENABLE | JZ_DMA_STATUS_CTRL_TRANSFER_DONE); + + if (dma->complete_cb) + dma->complete_cb(dma, 0, dma->dev); +} + +static irqreturn_t jz4740_dma_irq(int irq, void *dev_id) +{ + uint32_t irq_status; + unsigned int i; + + irq_status = readl(jz4740_dma_base + JZ_REG_DMA_IRQ); + + for (i = 0; i < 6; ++i) { + if (irq_status & (1 << i)) + jz4740_dma_chan_irq(&jz4740_dma_channels[i]); + } + + return IRQ_HANDLED; +} + +static int jz4740_dma_init(void) +{ + unsigned int ret; + + jz4740_dma_base = ioremap(JZ4740_DMAC_BASE_ADDR, 0x400); + + if (!jz4740_dma_base) + return -EBUSY; + + spin_lock_init(&jz4740_dma_lock); + + ret = request_irq(JZ4740_IRQ_DMAC, jz4740_dma_irq, 0, "DMA", NULL); + + if (ret) + printk(KERN_ERR "JZ4740 DMA: Failed to request irq: %d\n", ret); + + return ret; +} +arch_initcall(jz4740_dma_init); -- cgit v0.10.2 From eda0347bf8b449a42b3bf4e0b9754263d853982f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 17 Jul 2010 11:12:20 +0000 Subject: MIPS: JZ4740: Add PWM support Add support for the PWM part of the timer unit on a JZ4740 SoC. Signed-off-by: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1468/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/jz4740/pwm.c b/arch/mips/jz4740/pwm.c new file mode 100644 index 0000000..a26a6fa --- /dev/null +++ b/arch/mips/jz4740/pwm.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * JZ4740 platform PWM support + * + * 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. + * + * 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. + * + */ + +#include + +#include +#include +#include +#include + +#include +#include "timer.h" + +static struct clk *jz4740_pwm_clk; + +DEFINE_MUTEX(jz4740_pwm_mutex); + +struct pwm_device { + unsigned int id; + unsigned int gpio; + bool used; +}; + +static struct pwm_device jz4740_pwm_list[] = { + { 2, JZ_GPIO_PWM2, false }, + { 3, JZ_GPIO_PWM3, false }, + { 4, JZ_GPIO_PWM4, false }, + { 5, JZ_GPIO_PWM5, false }, + { 6, JZ_GPIO_PWM6, false }, + { 7, JZ_GPIO_PWM7, false }, +}; + +struct pwm_device *pwm_request(int id, const char *label) +{ + int ret = 0; + struct pwm_device *pwm; + + if (id < 2 || id > 7 || !jz4740_pwm_clk) + return ERR_PTR(-ENODEV); + + mutex_lock(&jz4740_pwm_mutex); + + pwm = &jz4740_pwm_list[id - 2]; + if (pwm->used) + ret = -EBUSY; + else + pwm->used = true; + + mutex_unlock(&jz4740_pwm_mutex); + + if (ret) + return ERR_PTR(ret); + + ret = gpio_request(pwm->gpio, label); + + if (ret) { + printk(KERN_ERR "Failed to request pwm gpio: %d\n", ret); + pwm->used = false; + return ERR_PTR(ret); + } + + jz_gpio_set_function(pwm->gpio, JZ_GPIO_FUNC_PWM); + + jz4740_timer_start(id); + + return pwm; +} + +void pwm_free(struct pwm_device *pwm) +{ + pwm_disable(pwm); + jz4740_timer_set_ctrl(pwm->id, 0); + + jz_gpio_set_function(pwm->gpio, JZ_GPIO_FUNC_NONE); + gpio_free(pwm->gpio); + + jz4740_timer_stop(pwm->id); + + pwm->used = false; +} + +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) +{ + unsigned long long tmp; + unsigned long period, duty; + unsigned int prescaler = 0; + unsigned int id = pwm->id; + uint16_t ctrl; + bool is_enabled; + + if (duty_ns < 0 || duty_ns > period_ns) + return -EINVAL; + + tmp = (unsigned long long)clk_get_rate(jz4740_pwm_clk) * period_ns; + do_div(tmp, 1000000000); + period = tmp; + + while (period > 0xffff && prescaler < 6) { + period >>= 2; + ++prescaler; + } + + if (prescaler == 6) + return -EINVAL; + + tmp = (unsigned long long)period * duty_ns; + do_div(tmp, period_ns); + duty = period - tmp; + + if (duty >= period) + duty = period - 1; + + is_enabled = jz4740_timer_is_enabled(id); + if (is_enabled) + pwm_disable(pwm); + + jz4740_timer_set_count(id, 0); + jz4740_timer_set_duty(id, duty); + jz4740_timer_set_period(id, period); + + ctrl = JZ_TIMER_CTRL_PRESCALER(prescaler) | JZ_TIMER_CTRL_SRC_EXT | + JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN; + + jz4740_timer_set_ctrl(id, ctrl); + + if (is_enabled) + pwm_enable(pwm); + + return 0; +} + +int pwm_enable(struct pwm_device *pwm) +{ + uint32_t ctrl = jz4740_timer_get_ctrl(pwm->id); + + ctrl |= JZ_TIMER_CTRL_PWM_ENABLE; + jz4740_timer_set_ctrl(pwm->id, ctrl); + jz4740_timer_enable(pwm->id); + + return 0; +} + +void pwm_disable(struct pwm_device *pwm) +{ + uint32_t ctrl = jz4740_timer_get_ctrl(pwm->id); + + ctrl &= ~JZ_TIMER_CTRL_PWM_ENABLE; + jz4740_timer_disable(pwm->id); + jz4740_timer_set_ctrl(pwm->id, ctrl); +} + +static int __init jz4740_pwm_init(void) +{ + int ret = 0; + + jz4740_pwm_clk = clk_get(NULL, "ext"); + + if (IS_ERR(jz4740_pwm_clk)) { + ret = PTR_ERR(jz4740_pwm_clk); + jz4740_pwm_clk = NULL; + } + + return ret; +} +subsys_initcall(jz4740_pwm_init); -- cgit v0.10.2 From c3b9566de89f40557e3a3d041ca08b05978aeb12 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 19 Jun 2010 04:08:16 +0000 Subject: MIPS: JZ4740: Add serial support The JZ4740 UART interface is almost 16550 compatible. The UART module needs to be enabled by setting a bit in the FCR register and it has support for receive timeout interrupts. Instead of adding yet another machine specific quirk to the 8250 serial driver we provide a serial_out implementation which sets the required additional flags. Signed-off-by: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1403/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/jz4740/serial.c b/arch/mips/jz4740/serial.c new file mode 100644 index 0000000..d23de45 --- /dev/null +++ b/arch/mips/jz4740/serial.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * JZ4740 serial support + * + * 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. + * + * 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. + * + */ + +#include +#include +#include + +void jz4740_serial_out(struct uart_port *p, int offset, int value) +{ + switch (offset) { + case UART_FCR: + value |= 0x10; /* Enable uart module */ + break; + case UART_IER: + value |= (value & 0x4) << 2; + break; + default: + break; + } + writeb(value, p->membase + (offset << p->regshift)); +} diff --git a/arch/mips/jz4740/serial.h b/arch/mips/jz4740/serial.h new file mode 100644 index 0000000..b9fe3ad --- /dev/null +++ b/arch/mips/jz4740/serial.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * JZ4740 serial support + * + * 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. + * + * 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 __MIPS_JZ4740_SERIAL_H__ + +void jz4740_serial_out(struct uart_port *p, int offset, int value); + +#endif -- cgit v0.10.2 From a8b7e9e8b08afe97e5b3d9bdd499867ce9a1c913 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 19 Jun 2010 04:08:17 +0000 Subject: MIPS: JZ4740: Add prom support Add support for initializing arcs_cmdline on JZ4740 based machines and provides a prom_putchar implementation. Signed-off-by: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1404/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c new file mode 100644 index 0000000..cfeac15 --- /dev/null +++ b/arch/mips/jz4740/prom.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * JZ4740 SoC prom code + * + * 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. + * + * 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. + * + */ + +#include +#include +#include +#include + +#include + +#include +#include + +void jz4740_init_cmdline(int argc, char *argv[]) +{ + unsigned int count = COMMAND_LINE_SIZE - 1; + int i; + char *dst = &(arcs_cmdline[0]); + char *src; + + for (i = 1; i < argc && count; ++i) { + src = argv[i]; + while (*src && count) { + *dst++ = *src++; + --count; + } + *dst++ = ' '; + } + if (i > 1) + --dst; + + *dst = 0; +} + +void __init prom_init(void) +{ + jz4740_init_cmdline((int)fw_arg0, (char **)fw_arg1); + mips_machtype = MACH_INGENIC_JZ4740; +} + +void __init prom_free_prom_memory(void) +{ +} + +#define UART_REG(_reg) ((void __iomem *)CKSEG1ADDR(JZ4740_UART0_BASE_ADDR + (_reg << 2))) + +void prom_putchar(char c) +{ + uint8_t lsr; + + do { + lsr = readb(UART_REG(UART_LSR)); + } while ((lsr & UART_LSR_TEMT) == 0); + + writeb(c, UART_REG(UART_TX)); +} -- cgit v0.10.2 From c2a529f73de56cb99ae9abcc2c8fb9fe3f2d2039 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 17 Jul 2010 11:13:29 +0000 Subject: MIPS: JZ4740: Add platform devices Add platform devices for all the JZ4740 platform drivers. Signed-off-by: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1469/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-jz4740/platform.h b/arch/mips/include/asm/mach-jz4740/platform.h new file mode 100644 index 0000000..8987a76 --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/platform.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * JZ4740 platform device definitions + * + * 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. + * + * 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 __JZ4740_PLATFORM_H +#define __JZ4740_PLATFORM_H + +#include + +extern struct platform_device jz4740_usb_ohci_device; +extern struct platform_device jz4740_udc_device; +extern struct platform_device jz4740_mmc_device; +extern struct platform_device jz4740_rtc_device; +extern struct platform_device jz4740_i2c_device; +extern struct platform_device jz4740_nand_device; +extern struct platform_device jz4740_framebuffer_device; +extern struct platform_device jz4740_i2s_device; +extern struct platform_device jz4740_pcm_device; +extern struct platform_device jz4740_codec_device; +extern struct platform_device jz4740_adc_device; + +void jz4740_serial_device_register(void); + +#endif diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c new file mode 100644 index 0000000..95bc2b5 --- /dev/null +++ b/arch/mips/jz4740/platform.c @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * JZ4740 platform devices + * + * 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. + * + * 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. + * + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#include "serial.h" +#include "clock.h" + +/* OHCI controller */ +static struct resource jz4740_usb_ohci_resources[] = { + { + .start = JZ4740_UHC_BASE_ADDR, + .end = JZ4740_UHC_BASE_ADDR + 0x1000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = JZ4740_IRQ_UHC, + .end = JZ4740_IRQ_UHC, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device jz4740_usb_ohci_device = { + .name = "jz4740-ohci", + .id = -1, + .dev = { + .dma_mask = &jz4740_usb_ohci_device.dev.coherent_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(jz4740_usb_ohci_resources), + .resource = jz4740_usb_ohci_resources, +}; + +/* UDC (USB gadget controller) */ +static struct resource jz4740_usb_gdt_resources[] = { + { + .start = JZ4740_UDC_BASE_ADDR, + .end = JZ4740_UDC_BASE_ADDR + 0x1000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = JZ4740_IRQ_UDC, + .end = JZ4740_IRQ_UDC, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device jz4740_udc_device = { + .name = "jz-udc", + .id = -1, + .dev = { + .dma_mask = &jz4740_udc_device.dev.coherent_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(jz4740_usb_gdt_resources), + .resource = jz4740_usb_gdt_resources, +}; + +/* MMC/SD controller */ +static struct resource jz4740_mmc_resources[] = { + { + .start = JZ4740_MSC_BASE_ADDR, + .end = JZ4740_MSC_BASE_ADDR + 0x1000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = JZ4740_IRQ_MSC, + .end = JZ4740_IRQ_MSC, + .flags = IORESOURCE_IRQ, + } +}; + +struct platform_device jz4740_mmc_device = { + .name = "jz4740-mmc", + .id = 0, + .dev = { + .dma_mask = &jz4740_mmc_device.dev.coherent_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(jz4740_mmc_resources), + .resource = jz4740_mmc_resources, +}; + +/* RTC controller */ +static struct resource jz4740_rtc_resources[] = { + { + .start = JZ4740_RTC_BASE_ADDR, + .end = JZ4740_RTC_BASE_ADDR + 0x38 - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = JZ4740_IRQ_RTC, + .end = JZ4740_IRQ_RTC, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device jz4740_rtc_device = { + .name = "jz4740-rtc", + .id = -1, + .num_resources = ARRAY_SIZE(jz4740_rtc_resources), + .resource = jz4740_rtc_resources, +}; + +/* I2C controller */ +static struct resource jz4740_i2c_resources[] = { + { + .start = JZ4740_I2C_BASE_ADDR, + .end = JZ4740_I2C_BASE_ADDR + 0x1000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = JZ4740_IRQ_I2C, + .end = JZ4740_IRQ_I2C, + .flags = IORESOURCE_IRQ, + } +}; + +struct platform_device jz4740_i2c_device = { + .name = "jz4740-i2c", + .id = 0, + .num_resources = ARRAY_SIZE(jz4740_i2c_resources), + .resource = jz4740_i2c_resources, +}; + +/* NAND controller */ +static struct resource jz4740_nand_resources[] = { + { + .name = "mmio", + .start = JZ4740_EMC_BASE_ADDR, + .end = JZ4740_EMC_BASE_ADDR + 0x1000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "bank", + .start = 0x18000000, + .end = 0x180C0000 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device jz4740_nand_device = { + .name = "jz4740-nand", + .num_resources = ARRAY_SIZE(jz4740_nand_resources), + .resource = jz4740_nand_resources, +}; + +/* LCD controller */ +static struct resource jz4740_framebuffer_resources[] = { + { + .start = JZ4740_LCD_BASE_ADDR, + .end = JZ4740_LCD_BASE_ADDR + 0x1000 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device jz4740_framebuffer_device = { + .name = "jz4740-fb", + .id = -1, + .num_resources = ARRAY_SIZE(jz4740_framebuffer_resources), + .resource = jz4740_framebuffer_resources, + .dev = { + .dma_mask = &jz4740_framebuffer_device.dev.coherent_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + +/* I2S controller */ +static struct resource jz4740_i2s_resources[] = { + { + .start = JZ4740_AIC_BASE_ADDR, + .end = JZ4740_AIC_BASE_ADDR + 0x38 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device jz4740_i2s_device = { + .name = "jz4740-i2s", + .id = -1, + .num_resources = ARRAY_SIZE(jz4740_i2s_resources), + .resource = jz4740_i2s_resources, +}; + +/* PCM */ +struct platform_device jz4740_pcm_device = { + .name = "jz4740-pcm", + .id = -1, +}; + +/* Codec */ +static struct resource jz4740_codec_resources[] = { + { + .start = JZ4740_AIC_BASE_ADDR + 0x80, + .end = JZ4740_AIC_BASE_ADDR + 0x88 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device jz4740_codec_device = { + .name = "jz4740-codec", + .id = -1, + .num_resources = ARRAY_SIZE(jz4740_codec_resources), + .resource = jz4740_codec_resources, +}; + +/* ADC controller */ +static struct resource jz4740_adc_resources[] = { + { + .start = JZ4740_SADC_BASE_ADDR, + .end = JZ4740_SADC_BASE_ADDR + 0x30, + .flags = IORESOURCE_MEM, + }, + { + .start = JZ4740_IRQ_SADC, + .end = JZ4740_IRQ_SADC, + .flags = IORESOURCE_IRQ, + }, + { + .start = JZ4740_IRQ_ADC_BASE, + .end = JZ4740_IRQ_ADC_BASE, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device jz4740_adc_device = { + .name = "jz4740-adc", + .id = -1, + .num_resources = ARRAY_SIZE(jz4740_adc_resources), + .resource = jz4740_adc_resources, +}; + +/* Serial */ +#define JZ4740_UART_DATA(_id) \ + { \ + .flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE, \ + .iotype = UPIO_MEM, \ + .regshift = 2, \ + .serial_out = jz4740_serial_out, \ + .type = PORT_16550, \ + .mapbase = JZ4740_UART ## _id ## _BASE_ADDR, \ + .irq = JZ4740_IRQ_UART ## _id, \ + } + +static struct plat_serial8250_port jz4740_uart_data[] = { + JZ4740_UART_DATA(0), + JZ4740_UART_DATA(1), + {}, +}; + +static struct platform_device jz4740_uart_device = { + .name = "serial8250", + .id = 0, + .dev = { + .platform_data = jz4740_uart_data, + }, +}; + +void jz4740_serial_device_register(void) +{ + struct plat_serial8250_port *p; + + for (p = jz4740_uart_data; p->flags != 0; ++p) + p->uartclk = jz4740_clock_bdata.ext_rate; + + platform_device_register(&jz4740_uart_device); +} -- cgit v0.10.2 From 5ebabe59807e116976b073ec43327eedb4b357e2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 19 Jun 2010 04:08:19 +0000 Subject: MIPS: JZ4740: Add Kbuild files Add the Kbuild files for the JZ4740 architecture and adds JZ4740 support to the MIPS Kbuild files. Signed-off-by: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1406/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index ea3b96c..78439b8 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -9,6 +9,7 @@ platforms += cobalt platforms += dec platforms += emma platforms += jazz +platforms += jz4740 platforms += lasat platforms += loongson platforms += mipssim diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 0dd1649..295e8c5 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -172,6 +172,18 @@ config MACH_JAZZ Members include the Acer PICA, MIPS Magnum 4000, MIPS Millennium and Olivetti M700-10 workstations. +config MACH_JZ4740 + bool "Ingenic JZ4740 based machines" + select SYS_HAS_CPU_MIPS32_R1 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select DMA_NONCOHERENT + select IRQ_CPU + select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB + select SYS_HAS_EARLY_PRINTK + select HAVE_PWM + config LASAT bool "LASAT Networks platforms" select CEVT_R4K @@ -696,6 +708,7 @@ endchoice source "arch/mips/alchemy/Kconfig" source "arch/mips/bcm63xx/Kconfig" source "arch/mips/jazz/Kconfig" +source "arch/mips/jz4740/Kconfig" source "arch/mips/lasat/Kconfig" source "arch/mips/pmc-sierra/Kconfig" source "arch/mips/powertv/Kconfig" diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig new file mode 100644 index 0000000..8a5e850 --- /dev/null +++ b/arch/mips/jz4740/Kconfig @@ -0,0 +1,8 @@ +choice + prompt "Machine type" + depends on MACH_JZ4740 + +endchoice + +config HAVE_PWM + bool diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile new file mode 100644 index 0000000..a803ccb --- /dev/null +++ b/arch/mips/jz4740/Makefile @@ -0,0 +1,18 @@ +# +# Makefile for the Ingenic JZ4740. +# + +# Object file lists. + +obj-y += prom.o irq.o time.o reset.o setup.o dma.o \ + gpio.o clock.o platform.o timer.o pwm.o serial.o + +obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o + +# board specific support + +# PM support + +obj-$(CONFIG_PM) += pm.o + +EXTRA_CFLAGS += -Werror -Wall diff --git a/arch/mips/jz4740/Platform b/arch/mips/jz4740/Platform new file mode 100644 index 0000000..6a97230 --- /dev/null +++ b/arch/mips/jz4740/Platform @@ -0,0 +1,3 @@ +core-$(CONFIG_MACH_JZ4740) += arch/mips/jz4740/ +cflags-$(CONFIG_MACH_JZ4740) += -I$(srctree)/arch/mips/include/asm/mach-jz4740 +load-$(CONFIG_MACH_JZ4740) += 0xffffffff80010000 -- cgit v0.10.2 From 3bf0eea8942fdcb948dea7e45c38bf7563407c49 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 19 Jun 2010 18:29:50 +0000 Subject: RTC: Add JZ4740 RTC driver Add support for the RTC unit on JZ4740 SoCs. Signed-off-by: Lars-Peter Clausen Cc: Alessandro Zummo Cc: Paul Gortmaker Cc: rtc-linux@googlegroups.com Acked-by: Wan ZongShun Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: Alessandro Zummo , Patchwork: https://patchwork.linux-mips.org/patch/1424/ Signed-off-by: Ralf Baechle diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 9d6952e..4301a6c 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -905,4 +905,15 @@ config RTC_DRV_MPC5121 This driver can also be built as a module. If so, the module will be called rtc-mpc5121. +config RTC_DRV_JZ4740 + tristate "Ingenic JZ4740 SoC" + depends on RTC_CLASS + depends on MACH_JZ4740 + help + If you say yes here you get support for the Ingenic JZ4740 SoC RTC + controller. + + This driver can also be buillt as a module. If so, the module + will be called rtc-jz4740. + endif # RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 5adbba7..fedf9bb 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o +obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c new file mode 100644 index 0000000..2619d57 --- /dev/null +++ b/drivers/rtc/rtc-jz4740.c @@ -0,0 +1,345 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * JZ4740 SoC RTC driver + * + * 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. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include + +#define JZ_REG_RTC_CTRL 0x00 +#define JZ_REG_RTC_SEC 0x04 +#define JZ_REG_RTC_SEC_ALARM 0x08 +#define JZ_REG_RTC_REGULATOR 0x0C +#define JZ_REG_RTC_HIBERNATE 0x20 +#define JZ_REG_RTC_SCRATCHPAD 0x34 + +#define JZ_RTC_CTRL_WRDY BIT(7) +#define JZ_RTC_CTRL_1HZ BIT(6) +#define JZ_RTC_CTRL_1HZ_IRQ BIT(5) +#define JZ_RTC_CTRL_AF BIT(4) +#define JZ_RTC_CTRL_AF_IRQ BIT(3) +#define JZ_RTC_CTRL_AE BIT(2) +#define JZ_RTC_CTRL_ENABLE BIT(0) + +struct jz4740_rtc { + struct resource *mem; + void __iomem *base; + + struct rtc_device *rtc; + + unsigned int irq; + + spinlock_t lock; +}; + +static inline uint32_t jz4740_rtc_reg_read(struct jz4740_rtc *rtc, size_t reg) +{ + return readl(rtc->base + reg); +} + +static int jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc) +{ + uint32_t ctrl; + int timeout = 1000; + + do { + ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); + } while (!(ctrl & JZ_RTC_CTRL_WRDY) && --timeout); + + return timeout ? 0 : -EIO; +} + +static inline int jz4740_rtc_reg_write(struct jz4740_rtc *rtc, size_t reg, + uint32_t val) +{ + int ret; + ret = jz4740_rtc_wait_write_ready(rtc); + if (ret == 0) + writel(val, rtc->base + reg); + + return ret; +} + +static int jz4740_rtc_ctrl_set_bits(struct jz4740_rtc *rtc, uint32_t mask, + bool set) +{ + int ret; + unsigned long flags; + uint32_t ctrl; + + spin_lock_irqsave(&rtc->lock, flags); + + ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); + + /* Don't clear interrupt flags by accident */ + ctrl |= JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF; + + if (set) + ctrl |= mask; + else + ctrl &= ~mask; + + ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_CTRL, ctrl); + + spin_unlock_irqrestore(&rtc->lock, flags); + + return ret; +} + +static int jz4740_rtc_read_time(struct device *dev, struct rtc_time *time) +{ + struct jz4740_rtc *rtc = dev_get_drvdata(dev); + uint32_t secs, secs2; + int timeout = 5; + + /* If the seconds register is read while it is updated, it can contain a + * bogus value. This can be avoided by making sure that two consecutive + * reads have the same value. + */ + secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); + secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); + + while (secs != secs2 && --timeout) { + secs = secs2; + secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); + } + + if (timeout == 0) + return -EIO; + + rtc_time_to_tm(secs, time); + + return rtc_valid_tm(time); +} + +static int jz4740_rtc_set_mmss(struct device *dev, unsigned long secs) +{ + struct jz4740_rtc *rtc = dev_get_drvdata(dev); + + return jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, secs); +} + +static int jz4740_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct jz4740_rtc *rtc = dev_get_drvdata(dev); + uint32_t secs; + uint32_t ctrl; + + secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM); + + ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); + + alrm->enabled = !!(ctrl & JZ_RTC_CTRL_AE); + alrm->pending = !!(ctrl & JZ_RTC_CTRL_AF); + + rtc_time_to_tm(secs, &alrm->time); + + return rtc_valid_tm(&alrm->time); +} + +static int jz4740_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + int ret; + struct jz4740_rtc *rtc = dev_get_drvdata(dev); + unsigned long secs; + + rtc_tm_to_time(&alrm->time, &secs); + + ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, secs); + if (!ret) + ret = jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AE, alrm->enabled); + + return ret; +} + +static int jz4740_rtc_update_irq_enable(struct device *dev, unsigned int enable) +{ + struct jz4740_rtc *rtc = dev_get_drvdata(dev); + return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ_IRQ, enable); +} + +static int jz4740_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) +{ + struct jz4740_rtc *rtc = dev_get_drvdata(dev); + return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AF_IRQ, enable); +} + +static struct rtc_class_ops jz4740_rtc_ops = { + .read_time = jz4740_rtc_read_time, + .set_mmss = jz4740_rtc_set_mmss, + .read_alarm = jz4740_rtc_read_alarm, + .set_alarm = jz4740_rtc_set_alarm, + .update_irq_enable = jz4740_rtc_update_irq_enable, + .alarm_irq_enable = jz4740_rtc_alarm_irq_enable, +}; + +static irqreturn_t jz4740_rtc_irq(int irq, void *data) +{ + struct jz4740_rtc *rtc = data; + uint32_t ctrl; + unsigned long events = 0; + + ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); + + if (ctrl & JZ_RTC_CTRL_1HZ) + events |= (RTC_UF | RTC_IRQF); + + if (ctrl & JZ_RTC_CTRL_AF) + events |= (RTC_AF | RTC_IRQF); + + rtc_update_irq(rtc->rtc, 1, events); + + jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF, false); + + return IRQ_HANDLED; +} + +void jz4740_rtc_poweroff(struct device *dev) +{ + struct jz4740_rtc *rtc = dev_get_drvdata(dev); + jz4740_rtc_reg_write(rtc, JZ_REG_RTC_HIBERNATE, 1); +} +EXPORT_SYMBOL_GPL(jz4740_rtc_poweroff); + +static int __devinit jz4740_rtc_probe(struct platform_device *pdev) +{ + int ret; + struct jz4740_rtc *rtc; + uint32_t scratchpad; + + rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); + if (!rtc) + return -ENOMEM; + + rtc->irq = platform_get_irq(pdev, 0); + if (rtc->irq < 0) { + ret = -ENOENT; + dev_err(&pdev->dev, "Failed to get platform irq\n"); + goto err_free; + } + + rtc->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!rtc->mem) { + ret = -ENOENT; + dev_err(&pdev->dev, "Failed to get platform mmio memory\n"); + goto err_free; + } + + rtc->mem = request_mem_region(rtc->mem->start, resource_size(rtc->mem), + pdev->name); + if (!rtc->mem) { + ret = -EBUSY; + dev_err(&pdev->dev, "Failed to request mmio memory region\n"); + goto err_free; + } + + rtc->base = ioremap_nocache(rtc->mem->start, resource_size(rtc->mem)); + if (!rtc->base) { + ret = -EBUSY; + dev_err(&pdev->dev, "Failed to ioremap mmio memory\n"); + goto err_release_mem_region; + } + + spin_lock_init(&rtc->lock); + + platform_set_drvdata(pdev, rtc); + + rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, &jz4740_rtc_ops, + THIS_MODULE); + if (IS_ERR(rtc->rtc)) { + ret = PTR_ERR(rtc->rtc); + dev_err(&pdev->dev, "Failed to register rtc device: %d\n", ret); + goto err_iounmap; + } + + ret = request_irq(rtc->irq, jz4740_rtc_irq, 0, + pdev->name, rtc); + if (ret) { + dev_err(&pdev->dev, "Failed to request rtc irq: %d\n", ret); + goto err_unregister_rtc; + } + + scratchpad = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SCRATCHPAD); + if (scratchpad != 0x12345678) { + ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678); + ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0); + if (ret) { + dev_err(&pdev->dev, "Could not write write to RTC registers\n"); + goto err_free_irq; + } + } + + return 0; + +err_free_irq: + free_irq(rtc->irq, rtc); +err_unregister_rtc: + rtc_device_unregister(rtc->rtc); +err_iounmap: + platform_set_drvdata(pdev, NULL); + iounmap(rtc->base); +err_release_mem_region: + release_mem_region(rtc->mem->start, resource_size(rtc->mem)); +err_free: + kfree(rtc); + + return ret; +} + +static int __devexit jz4740_rtc_remove(struct platform_device *pdev) +{ + struct jz4740_rtc *rtc = platform_get_drvdata(pdev); + + free_irq(rtc->irq, rtc); + + rtc_device_unregister(rtc->rtc); + + iounmap(rtc->base); + release_mem_region(rtc->mem->start, resource_size(rtc->mem)); + + kfree(rtc); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +struct platform_driver jz4740_rtc_driver = { + .probe = jz4740_rtc_probe, + .remove = __devexit_p(jz4740_rtc_remove), + .driver = { + .name = "jz4740-rtc", + .owner = THIS_MODULE, + }, +}; + +static int __init jz4740_rtc_init(void) +{ + return platform_driver_register(&jz4740_rtc_driver); +} +module_init(jz4740_rtc_init); + +static void __exit jz4740_rtc_exit(void) +{ + platform_driver_unregister(&jz4740_rtc_driver); +} +module_exit(jz4740_rtc_exit); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("RTC driver for the JZ4740 SoC\n"); +MODULE_ALIAS("platform:jz4740-rtc"); -- cgit v0.10.2 From 7a92d54521443450b14d89c413ec2072365da5bc Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 17 Jul 2010 11:14:34 +0000 Subject: FBDEV: JZ4740: Add framebuffer driver Add support for the LCD controller on JZ4740 SoCs. Signed-off-by: Lars-Peter Clausen Cc: Andrew Morton Cc: linux-fbdev@vger.kernel.org Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1470/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-jz4740/jz4740_fb.h b/arch/mips/include/asm/mach-jz4740/jz4740_fb.h new file mode 100644 index 0000000..6a50e6f --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/jz4740_fb.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2009, Lars-Peter Clausen + * + * 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. + * + * 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_MACH_JZ4740_JZ4740_FB_H__ +#define __ASM_MACH_JZ4740_JZ4740_FB_H__ + +#include + +enum jz4740_fb_lcd_type { + JZ_LCD_TYPE_GENERIC_16_BIT = 0, + JZ_LCD_TYPE_GENERIC_18_BIT = 0 | (1 << 4), + JZ_LCD_TYPE_SPECIAL_TFT_1 = 1, + JZ_LCD_TYPE_SPECIAL_TFT_2 = 2, + JZ_LCD_TYPE_SPECIAL_TFT_3 = 3, + JZ_LCD_TYPE_NON_INTERLACED_CCIR656 = 5, + JZ_LCD_TYPE_INTERLACED_CCIR656 = 7, + JZ_LCD_TYPE_SINGLE_COLOR_STN = 8, + JZ_LCD_TYPE_SINGLE_MONOCHROME_STN = 9, + JZ_LCD_TYPE_DUAL_COLOR_STN = 10, + JZ_LCD_TYPE_DUAL_MONOCHROME_STN = 11, + JZ_LCD_TYPE_8BIT_SERIAL = 12, +}; + +#define JZ4740_FB_SPECIAL_TFT_CONFIG(start, stop) (((start) << 16) | (stop)) + +/* +* width: width of the lcd display in mm +* height: height of the lcd display in mm +* num_modes: size of modes +* modes: list of valid video modes +* bpp: bits per pixel for the lcd +* lcd_type: lcd type +*/ + +struct jz4740_fb_platform_data { + unsigned int width; + unsigned int height; + + size_t num_modes; + struct fb_videomode *modes; + + unsigned int bpp; + enum jz4740_fb_lcd_type lcd_type; + + struct { + uint32_t spl; + uint32_t cls; + uint32_t ps; + uint32_t rev; + } special_tft_config; + + unsigned pixclk_falling_edge:1; + unsigned date_enable_active_low:1; +}; + +#endif diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 3d94a14..9e711a1 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2229,6 +2229,15 @@ config FB_BROADSHEET and could also have been called by other names when coupled with a bridge adapter. +config FB_JZ4740 + tristate "JZ4740 LCD framebuffer support" + depends on FB && MACH_JZ4740 + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + help + Framebuffer support for the JZ4740 SoC. + source "drivers/video/omap/Kconfig" source "drivers/video/omap2/Kconfig" diff --git a/drivers/video/Makefile b/drivers/video/Makefile index ddc2af2..f56a9ca 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -131,6 +131,7 @@ obj-$(CONFIG_FB_CARMINE) += carminefb.o obj-$(CONFIG_FB_MB862XX) += mb862xx/ obj-$(CONFIG_FB_MSM) += msm/ obj-$(CONFIG_FB_NUC900) += nuc900fb.o +obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o # Platform or fallback drivers go here obj-$(CONFIG_FB_UVESA) += uvesafb.o diff --git a/drivers/video/jz4740_fb.c b/drivers/video/jz4740_fb.c new file mode 100644 index 0000000..670ecaa --- /dev/null +++ b/drivers/video/jz4740_fb.c @@ -0,0 +1,847 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * JZ4740 SoC LCD framebuffer driver + * + * 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. + * + * 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. + * + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include + +#define JZ_REG_LCD_CFG 0x00 +#define JZ_REG_LCD_VSYNC 0x04 +#define JZ_REG_LCD_HSYNC 0x08 +#define JZ_REG_LCD_VAT 0x0C +#define JZ_REG_LCD_DAH 0x10 +#define JZ_REG_LCD_DAV 0x14 +#define JZ_REG_LCD_PS 0x18 +#define JZ_REG_LCD_CLS 0x1C +#define JZ_REG_LCD_SPL 0x20 +#define JZ_REG_LCD_REV 0x24 +#define JZ_REG_LCD_CTRL 0x30 +#define JZ_REG_LCD_STATE 0x34 +#define JZ_REG_LCD_IID 0x38 +#define JZ_REG_LCD_DA0 0x40 +#define JZ_REG_LCD_SA0 0x44 +#define JZ_REG_LCD_FID0 0x48 +#define JZ_REG_LCD_CMD0 0x4C +#define JZ_REG_LCD_DA1 0x50 +#define JZ_REG_LCD_SA1 0x54 +#define JZ_REG_LCD_FID1 0x58 +#define JZ_REG_LCD_CMD1 0x5C + +#define JZ_LCD_CFG_SLCD BIT(31) +#define JZ_LCD_CFG_PS_DISABLE BIT(23) +#define JZ_LCD_CFG_CLS_DISABLE BIT(22) +#define JZ_LCD_CFG_SPL_DISABLE BIT(21) +#define JZ_LCD_CFG_REV_DISABLE BIT(20) +#define JZ_LCD_CFG_HSYNCM BIT(19) +#define JZ_LCD_CFG_PCLKM BIT(18) +#define JZ_LCD_CFG_INV BIT(17) +#define JZ_LCD_CFG_SYNC_DIR BIT(16) +#define JZ_LCD_CFG_PS_POLARITY BIT(15) +#define JZ_LCD_CFG_CLS_POLARITY BIT(14) +#define JZ_LCD_CFG_SPL_POLARITY BIT(13) +#define JZ_LCD_CFG_REV_POLARITY BIT(12) +#define JZ_LCD_CFG_HSYNC_ACTIVE_LOW BIT(11) +#define JZ_LCD_CFG_PCLK_FALLING_EDGE BIT(10) +#define JZ_LCD_CFG_DE_ACTIVE_LOW BIT(9) +#define JZ_LCD_CFG_VSYNC_ACTIVE_LOW BIT(8) +#define JZ_LCD_CFG_18_BIT BIT(7) +#define JZ_LCD_CFG_PDW (BIT(5) | BIT(4)) +#define JZ_LCD_CFG_MODE_MASK 0xf + +#define JZ_LCD_CTRL_BURST_4 (0x0 << 28) +#define JZ_LCD_CTRL_BURST_8 (0x1 << 28) +#define JZ_LCD_CTRL_BURST_16 (0x2 << 28) +#define JZ_LCD_CTRL_RGB555 BIT(27) +#define JZ_LCD_CTRL_OFUP BIT(26) +#define JZ_LCD_CTRL_FRC_GRAYSCALE_16 (0x0 << 24) +#define JZ_LCD_CTRL_FRC_GRAYSCALE_4 (0x1 << 24) +#define JZ_LCD_CTRL_FRC_GRAYSCALE_2 (0x2 << 24) +#define JZ_LCD_CTRL_PDD_MASK (0xff << 16) +#define JZ_LCD_CTRL_EOF_IRQ BIT(13) +#define JZ_LCD_CTRL_SOF_IRQ BIT(12) +#define JZ_LCD_CTRL_OFU_IRQ BIT(11) +#define JZ_LCD_CTRL_IFU0_IRQ BIT(10) +#define JZ_LCD_CTRL_IFU1_IRQ BIT(9) +#define JZ_LCD_CTRL_DD_IRQ BIT(8) +#define JZ_LCD_CTRL_QDD_IRQ BIT(7) +#define JZ_LCD_CTRL_REVERSE_ENDIAN BIT(6) +#define JZ_LCD_CTRL_LSB_FISRT BIT(5) +#define JZ_LCD_CTRL_DISABLE BIT(4) +#define JZ_LCD_CTRL_ENABLE BIT(3) +#define JZ_LCD_CTRL_BPP_1 0x0 +#define JZ_LCD_CTRL_BPP_2 0x1 +#define JZ_LCD_CTRL_BPP_4 0x2 +#define JZ_LCD_CTRL_BPP_8 0x3 +#define JZ_LCD_CTRL_BPP_15_16 0x4 +#define JZ_LCD_CTRL_BPP_18_24 0x5 + +#define JZ_LCD_CMD_SOF_IRQ BIT(15) +#define JZ_LCD_CMD_EOF_IRQ BIT(16) +#define JZ_LCD_CMD_ENABLE_PAL BIT(12) + +#define JZ_LCD_SYNC_MASK 0x3ff + +#define JZ_LCD_STATE_DISABLED BIT(0) + +struct jzfb_framedesc { + uint32_t next; + uint32_t addr; + uint32_t id; + uint32_t cmd; +} __packed; + +struct jzfb { + struct fb_info *fb; + struct platform_device *pdev; + void __iomem *base; + struct resource *mem; + struct jz4740_fb_platform_data *pdata; + + size_t vidmem_size; + void *vidmem; + dma_addr_t vidmem_phys; + struct jzfb_framedesc *framedesc; + dma_addr_t framedesc_phys; + + struct clk *ldclk; + struct clk *lpclk; + + unsigned is_enabled:1; + struct mutex lock; + + uint32_t pseudo_palette[16]; +}; + +static const struct fb_fix_screeninfo jzfb_fix __devinitdata = { + .id = "JZ4740 FB", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .xpanstep = 0, + .ypanstep = 0, + .ywrapstep = 0, + .accel = FB_ACCEL_NONE, +}; + +static const struct jz_gpio_bulk_request jz_lcd_ctrl_pins[] = { + JZ_GPIO_BULK_PIN(LCD_PCLK), + JZ_GPIO_BULK_PIN(LCD_HSYNC), + JZ_GPIO_BULK_PIN(LCD_VSYNC), + JZ_GPIO_BULK_PIN(LCD_DE), + JZ_GPIO_BULK_PIN(LCD_PS), + JZ_GPIO_BULK_PIN(LCD_REV), + JZ_GPIO_BULK_PIN(LCD_CLS), + JZ_GPIO_BULK_PIN(LCD_SPL), +}; + +static const struct jz_gpio_bulk_request jz_lcd_data_pins[] = { + JZ_GPIO_BULK_PIN(LCD_DATA0), + JZ_GPIO_BULK_PIN(LCD_DATA1), + JZ_GPIO_BULK_PIN(LCD_DATA2), + JZ_GPIO_BULK_PIN(LCD_DATA3), + JZ_GPIO_BULK_PIN(LCD_DATA4), + JZ_GPIO_BULK_PIN(LCD_DATA5), + JZ_GPIO_BULK_PIN(LCD_DATA6), + JZ_GPIO_BULK_PIN(LCD_DATA7), + JZ_GPIO_BULK_PIN(LCD_DATA8), + JZ_GPIO_BULK_PIN(LCD_DATA9), + JZ_GPIO_BULK_PIN(LCD_DATA10), + JZ_GPIO_BULK_PIN(LCD_DATA11), + JZ_GPIO_BULK_PIN(LCD_DATA12), + JZ_GPIO_BULK_PIN(LCD_DATA13), + JZ_GPIO_BULK_PIN(LCD_DATA14), + JZ_GPIO_BULK_PIN(LCD_DATA15), + JZ_GPIO_BULK_PIN(LCD_DATA16), + JZ_GPIO_BULK_PIN(LCD_DATA17), +}; + +static unsigned int jzfb_num_ctrl_pins(struct jzfb *jzfb) +{ + unsigned int num; + + switch (jzfb->pdata->lcd_type) { + case JZ_LCD_TYPE_GENERIC_16_BIT: + num = 4; + break; + case JZ_LCD_TYPE_GENERIC_18_BIT: + num = 4; + break; + case JZ_LCD_TYPE_8BIT_SERIAL: + num = 3; + break; + case JZ_LCD_TYPE_SPECIAL_TFT_1: + case JZ_LCD_TYPE_SPECIAL_TFT_2: + case JZ_LCD_TYPE_SPECIAL_TFT_3: + num = 8; + break; + default: + num = 0; + break; + } + return num; +} + +static unsigned int jzfb_num_data_pins(struct jzfb *jzfb) +{ + unsigned int num; + + switch (jzfb->pdata->lcd_type) { + case JZ_LCD_TYPE_GENERIC_16_BIT: + num = 16; + break; + case JZ_LCD_TYPE_GENERIC_18_BIT: + num = 18; + break; + case JZ_LCD_TYPE_8BIT_SERIAL: + num = 8; + break; + case JZ_LCD_TYPE_SPECIAL_TFT_1: + case JZ_LCD_TYPE_SPECIAL_TFT_2: + case JZ_LCD_TYPE_SPECIAL_TFT_3: + if (jzfb->pdata->bpp == 18) + num = 18; + else + num = 16; + break; + default: + num = 0; + break; + } + return num; +} + +/* Based on CNVT_TOHW macro from skeletonfb.c */ +static inline uint32_t jzfb_convert_color_to_hw(unsigned val, + struct fb_bitfield *bf) +{ + return (((val << bf->length) + 0x7FFF - val) >> 16) << bf->offset; +} + +static int jzfb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, struct fb_info *fb) +{ + uint32_t color; + + if (regno >= 16) + return -EINVAL; + + color = jzfb_convert_color_to_hw(red, &fb->var.red); + color |= jzfb_convert_color_to_hw(green, &fb->var.green); + color |= jzfb_convert_color_to_hw(blue, &fb->var.blue); + color |= jzfb_convert_color_to_hw(transp, &fb->var.transp); + + ((uint32_t *)(fb->pseudo_palette))[regno] = color; + + return 0; +} + +static int jzfb_get_controller_bpp(struct jzfb *jzfb) +{ + switch (jzfb->pdata->bpp) { + case 18: + case 24: + return 32; + case 15: + return 16; + default: + return jzfb->pdata->bpp; + } +} + +static struct fb_videomode *jzfb_get_mode(struct jzfb *jzfb, + struct fb_var_screeninfo *var) +{ + size_t i; + struct fb_videomode *mode = jzfb->pdata->modes; + + for (i = 0; i < jzfb->pdata->num_modes; ++i, ++mode) { + if (mode->xres == var->xres && mode->yres == var->yres) + return mode; + } + + return NULL; +} + +static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb) +{ + struct jzfb *jzfb = fb->par; + struct fb_videomode *mode; + + if (var->bits_per_pixel != jzfb_get_controller_bpp(jzfb) && + var->bits_per_pixel != jzfb->pdata->bpp) + return -EINVAL; + + mode = jzfb_get_mode(jzfb, var); + if (mode == NULL) + return -EINVAL; + + fb_videomode_to_var(var, mode); + + switch (jzfb->pdata->bpp) { + case 8: + break; + case 15: + var->red.offset = 10; + var->red.length = 5; + var->green.offset = 6; + var->green.length = 5; + var->blue.offset = 0; + var->blue.length = 5; + break; + case 16: + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 5; + break; + case 18: + var->red.offset = 16; + var->red.length = 6; + var->green.offset = 8; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 6; + var->bits_per_pixel = 32; + break; + case 32: + case 24: + var->transp.offset = 24; + var->transp.length = 8; + var->red.offset = 16; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + var->bits_per_pixel = 32; + break; + default: + break; + } + + return 0; +} + +static int jzfb_set_par(struct fb_info *info) +{ + struct jzfb *jzfb = info->par; + struct jz4740_fb_platform_data *pdata = jzfb->pdata; + struct fb_var_screeninfo *var = &info->var; + struct fb_videomode *mode; + uint16_t hds, vds; + uint16_t hde, vde; + uint16_t ht, vt; + uint32_t ctrl; + uint32_t cfg; + unsigned long rate; + + mode = jzfb_get_mode(jzfb, var); + if (mode == NULL) + return -EINVAL; + + if (mode == info->mode) + return 0; + + info->mode = mode; + + hds = mode->hsync_len + mode->left_margin; + hde = hds + mode->xres; + ht = hde + mode->right_margin; + + vds = mode->vsync_len + mode->upper_margin; + vde = vds + mode->yres; + vt = vde + mode->lower_margin; + + ctrl = JZ_LCD_CTRL_OFUP | JZ_LCD_CTRL_BURST_16; + + switch (pdata->bpp) { + case 1: + ctrl |= JZ_LCD_CTRL_BPP_1; + break; + case 2: + ctrl |= JZ_LCD_CTRL_BPP_2; + break; + case 4: + ctrl |= JZ_LCD_CTRL_BPP_4; + break; + case 8: + ctrl |= JZ_LCD_CTRL_BPP_8; + break; + case 15: + ctrl |= JZ_LCD_CTRL_RGB555; /* Falltrough */ + case 16: + ctrl |= JZ_LCD_CTRL_BPP_15_16; + break; + case 18: + case 24: + case 32: + ctrl |= JZ_LCD_CTRL_BPP_18_24; + break; + default: + break; + } + + cfg = pdata->lcd_type & 0xf; + + if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT)) + cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW; + + if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT)) + cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW; + + if (pdata->pixclk_falling_edge) + cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE; + + if (pdata->date_enable_active_low) + cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW; + + if (pdata->lcd_type == JZ_LCD_TYPE_GENERIC_18_BIT) + cfg |= JZ_LCD_CFG_18_BIT; + + if (mode->pixclock) { + rate = PICOS2KHZ(mode->pixclock) * 1000; + mode->refresh = rate / vt / ht; + } else { + if (pdata->lcd_type == JZ_LCD_TYPE_8BIT_SERIAL) + rate = mode->refresh * (vt + 2 * mode->xres) * ht; + else + rate = mode->refresh * vt * ht; + + mode->pixclock = KHZ2PICOS(rate / 1000); + } + + mutex_lock(&jzfb->lock); + if (!jzfb->is_enabled) + clk_enable(jzfb->ldclk); + else + ctrl |= JZ_LCD_CTRL_ENABLE; + + switch (pdata->lcd_type) { + case JZ_LCD_TYPE_SPECIAL_TFT_1: + case JZ_LCD_TYPE_SPECIAL_TFT_2: + case JZ_LCD_TYPE_SPECIAL_TFT_3: + writel(pdata->special_tft_config.spl, jzfb->base + JZ_REG_LCD_SPL); + writel(pdata->special_tft_config.cls, jzfb->base + JZ_REG_LCD_CLS); + writel(pdata->special_tft_config.ps, jzfb->base + JZ_REG_LCD_PS); + writel(pdata->special_tft_config.ps, jzfb->base + JZ_REG_LCD_REV); + break; + default: + cfg |= JZ_LCD_CFG_PS_DISABLE; + cfg |= JZ_LCD_CFG_CLS_DISABLE; + cfg |= JZ_LCD_CFG_SPL_DISABLE; + cfg |= JZ_LCD_CFG_REV_DISABLE; + break; + } + + writel(mode->hsync_len, jzfb->base + JZ_REG_LCD_HSYNC); + writel(mode->vsync_len, jzfb->base + JZ_REG_LCD_VSYNC); + + writel((ht << 16) | vt, jzfb->base + JZ_REG_LCD_VAT); + + writel((hds << 16) | hde, jzfb->base + JZ_REG_LCD_DAH); + writel((vds << 16) | vde, jzfb->base + JZ_REG_LCD_DAV); + + writel(cfg, jzfb->base + JZ_REG_LCD_CFG); + + writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL); + + if (!jzfb->is_enabled) + clk_disable(jzfb->ldclk); + + mutex_unlock(&jzfb->lock); + + clk_set_rate(jzfb->lpclk, rate); + clk_set_rate(jzfb->ldclk, rate * 3); + + return 0; +} + +static void jzfb_enable(struct jzfb *jzfb) +{ + uint32_t ctrl; + + clk_enable(jzfb->ldclk); + + jz_gpio_bulk_resume(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); + jz_gpio_bulk_resume(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); + + writel(0, jzfb->base + JZ_REG_LCD_STATE); + + writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0); + + ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL); + ctrl |= JZ_LCD_CTRL_ENABLE; + ctrl &= ~JZ_LCD_CTRL_DISABLE; + writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL); +} + +static void jzfb_disable(struct jzfb *jzfb) +{ + uint32_t ctrl; + + ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL); + ctrl |= JZ_LCD_CTRL_DISABLE; + writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL); + do { + ctrl = readl(jzfb->base + JZ_REG_LCD_STATE); + } while (!(ctrl & JZ_LCD_STATE_DISABLED)); + + jz_gpio_bulk_suspend(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); + jz_gpio_bulk_suspend(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); + + clk_disable(jzfb->ldclk); +} + +static int jzfb_blank(int blank_mode, struct fb_info *info) +{ + struct jzfb *jzfb = info->par; + + switch (blank_mode) { + case FB_BLANK_UNBLANK: + mutex_lock(&jzfb->lock); + if (jzfb->is_enabled) { + mutex_unlock(&jzfb->lock); + return 0; + } + + jzfb_enable(jzfb); + jzfb->is_enabled = 1; + + mutex_unlock(&jzfb->lock); + break; + default: + mutex_lock(&jzfb->lock); + if (!jzfb->is_enabled) { + mutex_unlock(&jzfb->lock); + return 0; + } + + jzfb_disable(jzfb); + jzfb->is_enabled = 0; + + mutex_unlock(&jzfb->lock); + break; + } + + return 0; +} + +static int jzfb_alloc_devmem(struct jzfb *jzfb) +{ + int max_videosize = 0; + struct fb_videomode *mode = jzfb->pdata->modes; + void *page; + int i; + + for (i = 0; i < jzfb->pdata->num_modes; ++mode, ++i) { + if (max_videosize < mode->xres * mode->yres) + max_videosize = mode->xres * mode->yres; + } + + max_videosize *= jzfb_get_controller_bpp(jzfb) >> 3; + + jzfb->framedesc = dma_alloc_coherent(&jzfb->pdev->dev, + sizeof(*jzfb->framedesc), + &jzfb->framedesc_phys, GFP_KERNEL); + + if (!jzfb->framedesc) + return -ENOMEM; + + jzfb->vidmem_size = PAGE_ALIGN(max_videosize); + jzfb->vidmem = dma_alloc_coherent(&jzfb->pdev->dev, + jzfb->vidmem_size, + &jzfb->vidmem_phys, GFP_KERNEL); + + if (!jzfb->vidmem) + goto err_free_framedesc; + + for (page = jzfb->vidmem; + page < jzfb->vidmem + PAGE_ALIGN(jzfb->vidmem_size); + page += PAGE_SIZE) { + SetPageReserved(virt_to_page(page)); + } + + jzfb->framedesc->next = jzfb->framedesc_phys; + jzfb->framedesc->addr = jzfb->vidmem_phys; + jzfb->framedesc->id = 0xdeafbead; + jzfb->framedesc->cmd = 0; + jzfb->framedesc->cmd |= max_videosize / 4; + + return 0; + +err_free_framedesc: + dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc), + jzfb->framedesc, jzfb->framedesc_phys); + return -ENOMEM; +} + +static void jzfb_free_devmem(struct jzfb *jzfb) +{ + dma_free_coherent(&jzfb->pdev->dev, jzfb->vidmem_size, + jzfb->vidmem, jzfb->vidmem_phys); + dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc), + jzfb->framedesc, jzfb->framedesc_phys); +} + +static struct fb_ops jzfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = jzfb_check_var, + .fb_set_par = jzfb_set_par, + .fb_blank = jzfb_blank, + .fb_fillrect = sys_fillrect, + .fb_copyarea = sys_copyarea, + .fb_imageblit = sys_imageblit, + .fb_setcolreg = jzfb_setcolreg, +}; + +static int __devinit jzfb_probe(struct platform_device *pdev) +{ + int ret; + struct jzfb *jzfb; + struct fb_info *fb; + struct jz4740_fb_platform_data *pdata = pdev->dev.platform_data; + struct resource *mem; + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENXIO; + } + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) { + dev_err(&pdev->dev, "Failed to get register memory resource\n"); + return -ENXIO; + } + + mem = request_mem_region(mem->start, resource_size(mem), pdev->name); + if (!mem) { + dev_err(&pdev->dev, "Failed to request register memory region\n"); + return -EBUSY; + } + + fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev); + if (!fb) { + dev_err(&pdev->dev, "Failed to allocate framebuffer device\n"); + ret = -ENOMEM; + goto err_release_mem_region; + } + + fb->fbops = &jzfb_ops; + fb->flags = FBINFO_DEFAULT; + + jzfb = fb->par; + jzfb->pdev = pdev; + jzfb->pdata = pdata; + jzfb->mem = mem; + + jzfb->ldclk = clk_get(&pdev->dev, "lcd"); + if (IS_ERR(jzfb->ldclk)) { + ret = PTR_ERR(jzfb->ldclk); + dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret); + goto err_framebuffer_release; + } + + jzfb->lpclk = clk_get(&pdev->dev, "lcd_pclk"); + if (IS_ERR(jzfb->lpclk)) { + ret = PTR_ERR(jzfb->lpclk); + dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret); + goto err_put_ldclk; + } + + jzfb->base = ioremap(mem->start, resource_size(mem)); + if (!jzfb->base) { + dev_err(&pdev->dev, "Failed to ioremap register memory region\n"); + ret = -EBUSY; + goto err_put_lpclk; + } + + platform_set_drvdata(pdev, jzfb); + + mutex_init(&jzfb->lock); + + fb_videomode_to_modelist(pdata->modes, pdata->num_modes, + &fb->modelist); + fb_videomode_to_var(&fb->var, pdata->modes); + fb->var.bits_per_pixel = pdata->bpp; + jzfb_check_var(&fb->var, fb); + + ret = jzfb_alloc_devmem(jzfb); + if (ret) { + dev_err(&pdev->dev, "Failed to allocate video memory\n"); + goto err_iounmap; + } + + fb->fix = jzfb_fix; + fb->fix.line_length = fb->var.bits_per_pixel * fb->var.xres / 8; + fb->fix.mmio_start = mem->start; + fb->fix.mmio_len = resource_size(mem); + fb->fix.smem_start = jzfb->vidmem_phys; + fb->fix.smem_len = fb->fix.line_length * fb->var.yres; + fb->screen_base = jzfb->vidmem; + fb->pseudo_palette = jzfb->pseudo_palette; + + fb_alloc_cmap(&fb->cmap, 256, 0); + + clk_enable(jzfb->ldclk); + jzfb->is_enabled = 1; + + writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0); + + fb->mode = NULL; + jzfb_set_par(fb); + + jz_gpio_bulk_request(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); + jz_gpio_bulk_request(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); + + ret = register_framebuffer(fb); + if (ret) { + dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret); + goto err_free_devmem; + } + + jzfb->fb = fb; + + return 0; + +err_free_devmem: + jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); + jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); + + fb_dealloc_cmap(&fb->cmap); + jzfb_free_devmem(jzfb); +err_iounmap: + iounmap(jzfb->base); +err_put_lpclk: + clk_put(jzfb->lpclk); +err_put_ldclk: + clk_put(jzfb->ldclk); +err_framebuffer_release: + framebuffer_release(fb); +err_release_mem_region: + release_mem_region(mem->start, resource_size(mem)); + return ret; +} + +static int __devexit jzfb_remove(struct platform_device *pdev) +{ + struct jzfb *jzfb = platform_get_drvdata(pdev); + + jzfb_blank(FB_BLANK_POWERDOWN, jzfb->fb); + + jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); + jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); + + iounmap(jzfb->base); + release_mem_region(jzfb->mem->start, resource_size(jzfb->mem)); + + fb_dealloc_cmap(&jzfb->fb->cmap); + jzfb_free_devmem(jzfb); + + platform_set_drvdata(pdev, NULL); + + clk_put(jzfb->lpclk); + clk_put(jzfb->ldclk); + + framebuffer_release(jzfb->fb); + + return 0; +} + +#ifdef CONFIG_PM + +static int jzfb_suspend(struct device *dev) +{ + struct jzfb *jzfb = dev_get_drvdata(dev); + + acquire_console_sem(); + fb_set_suspend(jzfb->fb, 1); + release_console_sem(); + + mutex_lock(&jzfb->lock); + if (jzfb->is_enabled) + jzfb_disable(jzfb); + mutex_unlock(&jzfb->lock); + + return 0; +} + +static int jzfb_resume(struct device *dev) +{ + struct jzfb *jzfb = dev_get_drvdata(dev); + clk_enable(jzfb->ldclk); + + mutex_lock(&jzfb->lock); + if (jzfb->is_enabled) + jzfb_enable(jzfb); + mutex_unlock(&jzfb->lock); + + acquire_console_sem(); + fb_set_suspend(jzfb->fb, 0); + release_console_sem(); + + return 0; +} + +static const struct dev_pm_ops jzfb_pm_ops = { + .suspend = jzfb_suspend, + .resume = jzfb_resume, + .poweroff = jzfb_suspend, + .restore = jzfb_resume, +}; + +#define JZFB_PM_OPS (&jzfb_pm_ops) + +#else +#define JZFB_PM_OPS NULL +#endif + +static struct platform_driver jzfb_driver = { + .probe = jzfb_probe, + .remove = __devexit_p(jzfb_remove), + .driver = { + .name = "jz4740-fb", + .pm = JZFB_PM_OPS, + }, +}; + +static int __init jzfb_init(void) +{ + return platform_driver_register(&jzfb_driver); +} +module_init(jzfb_init); + +static void __exit jzfb_exit(void) +{ + platform_driver_unregister(&jzfb_driver); +} +module_exit(jzfb_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("JZ4740 SoC LCD framebuffer driver"); +MODULE_ALIAS("platform:jz4740-fb"); -- cgit v0.10.2 From ba01d6ec04f6d1d983101eb527caa96318fc1017 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 17 Jul 2010 11:15:29 +0000 Subject: MTD: Nand: Add JZ4740 NAND driver Add support for the NAND controller on JZ4740 SoCs. Signed-off-by: Lars-Peter Clausen Cc: David Woodhouse Cc: linux-mtd@lists.infradead.org Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1470/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h new file mode 100644 index 0000000..bb5b9a4 --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * JZ4740 SoC NAND controller driver + * + * 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. + * + * 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_MACH_JZ4740_JZ4740_NAND_H__ +#define __ASM_MACH_JZ4740_JZ4740_NAND_H__ + +#include +#include + +struct jz_nand_platform_data { + int num_partitions; + struct mtd_partition *partitions; + + struct nand_ecclayout *ecc_layout; + + unsigned int busy_gpio; + + void (*ident_callback)(struct platform_device *, struct nand_chip *, + struct mtd_partition **, int *num_partitions); +}; + +#endif diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index ffc3720..362d177 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -526,4 +526,10 @@ config MTD_NAND_NUC900 This enables the driver for the NAND Flash on evaluation board based on w90p910 / NUC9xx. +config MTD_NAND_JZ4740 + tristate "Support for JZ4740 SoC NAND controller" + depends on MACH_JZ4740 + help + Enables support for NAND Flash on JZ4740 SoC based boards. + endif # MTD_NAND diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index e8ab884..ac83dcd 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -46,5 +46,6 @@ obj-$(CONFIG_MTD_NAND_NOMADIK) += nomadik_nand.o obj-$(CONFIG_MTD_NAND_BCM_UMI) += bcm_umi_nand.o nand_bcm_umi.o obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o obj-$(CONFIG_MTD_NAND_RICOH) += r852.o +obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o nand-objs := nand_base.o nand_bbt.o diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c new file mode 100644 index 0000000..67343fc --- /dev/null +++ b/drivers/mtd/nand/jz4740_nand.c @@ -0,0 +1,516 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * JZ4740 SoC NAND controller driver + * + * 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. + * + * 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. + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#define JZ_REG_NAND_CTRL 0x50 +#define JZ_REG_NAND_ECC_CTRL 0x100 +#define JZ_REG_NAND_DATA 0x104 +#define JZ_REG_NAND_PAR0 0x108 +#define JZ_REG_NAND_PAR1 0x10C +#define JZ_REG_NAND_PAR2 0x110 +#define JZ_REG_NAND_IRQ_STAT 0x114 +#define JZ_REG_NAND_IRQ_CTRL 0x118 +#define JZ_REG_NAND_ERR(x) (0x11C + ((x) << 2)) + +#define JZ_NAND_ECC_CTRL_PAR_READY BIT(4) +#define JZ_NAND_ECC_CTRL_ENCODING BIT(3) +#define JZ_NAND_ECC_CTRL_RS BIT(2) +#define JZ_NAND_ECC_CTRL_RESET BIT(1) +#define JZ_NAND_ECC_CTRL_ENABLE BIT(0) + +#define JZ_NAND_STATUS_ERR_COUNT (BIT(31) | BIT(30) | BIT(29)) +#define JZ_NAND_STATUS_PAD_FINISH BIT(4) +#define JZ_NAND_STATUS_DEC_FINISH BIT(3) +#define JZ_NAND_STATUS_ENC_FINISH BIT(2) +#define JZ_NAND_STATUS_UNCOR_ERROR BIT(1) +#define JZ_NAND_STATUS_ERROR BIT(0) + +#define JZ_NAND_CTRL_ENABLE_CHIP(x) BIT((x) << 1) +#define JZ_NAND_CTRL_ASSERT_CHIP(x) BIT(((x) << 1) + 1) + +#define JZ_NAND_MEM_ADDR_OFFSET 0x10000 +#define JZ_NAND_MEM_CMD_OFFSET 0x08000 + +struct jz_nand { + struct mtd_info mtd; + struct nand_chip chip; + void __iomem *base; + struct resource *mem; + + void __iomem *bank_base; + struct resource *bank_mem; + + struct jz_nand_platform_data *pdata; + bool is_reading; +}; + +static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd) +{ + return container_of(mtd, struct jz_nand, mtd); +} + +static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) +{ + struct jz_nand *nand = mtd_to_jz_nand(mtd); + struct nand_chip *chip = mtd->priv; + uint32_t reg; + + if (ctrl & NAND_CTRL_CHANGE) { + BUG_ON((ctrl & NAND_ALE) && (ctrl & NAND_CLE)); + if (ctrl & NAND_ALE) + chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_ADDR_OFFSET; + else if (ctrl & NAND_CLE) + chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_CMD_OFFSET; + else + chip->IO_ADDR_W = nand->bank_base; + + reg = readl(nand->base + JZ_REG_NAND_CTRL); + if (ctrl & NAND_NCE) + reg |= JZ_NAND_CTRL_ASSERT_CHIP(0); + else + reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(0); + writel(reg, nand->base + JZ_REG_NAND_CTRL); + } + if (dat != NAND_CMD_NONE) + writeb(dat, chip->IO_ADDR_W); +} + +static int jz_nand_dev_ready(struct mtd_info *mtd) +{ + struct jz_nand *nand = mtd_to_jz_nand(mtd); + return gpio_get_value_cansleep(nand->pdata->busy_gpio); +} + +static void jz_nand_hwctl(struct mtd_info *mtd, int mode) +{ + struct jz_nand *nand = mtd_to_jz_nand(mtd); + uint32_t reg; + + writel(0, nand->base + JZ_REG_NAND_IRQ_STAT); + reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL); + + reg |= JZ_NAND_ECC_CTRL_RESET; + reg |= JZ_NAND_ECC_CTRL_ENABLE; + reg |= JZ_NAND_ECC_CTRL_RS; + + switch (mode) { + case NAND_ECC_READ: + reg &= ~JZ_NAND_ECC_CTRL_ENCODING; + nand->is_reading = true; + break; + case NAND_ECC_WRITE: + reg |= JZ_NAND_ECC_CTRL_ENCODING; + nand->is_reading = false; + break; + default: + break; + } + + writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL); +} + +static int jz_nand_calculate_ecc_rs(struct mtd_info *mtd, const uint8_t *dat, + uint8_t *ecc_code) +{ + struct jz_nand *nand = mtd_to_jz_nand(mtd); + uint32_t reg, status; + int i; + unsigned int timeout = 1000; + static uint8_t empty_block_ecc[] = {0xcd, 0x9d, 0x90, 0x58, 0xf4, + 0x8b, 0xff, 0xb7, 0x6f}; + + if (nand->is_reading) + return 0; + + do { + status = readl(nand->base + JZ_REG_NAND_IRQ_STAT); + } while (!(status & JZ_NAND_STATUS_ENC_FINISH) && --timeout); + + if (timeout == 0) + return -1; + + reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL); + reg &= ~JZ_NAND_ECC_CTRL_ENABLE; + writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL); + + for (i = 0; i < 9; ++i) + ecc_code[i] = readb(nand->base + JZ_REG_NAND_PAR0 + i); + + /* If the written data is completly 0xff, we also want to write 0xff as + * ecc, otherwise we will get in trouble when doing subpage writes. */ + if (memcmp(ecc_code, empty_block_ecc, 9) == 0) + memset(ecc_code, 0xff, 9); + + return 0; +} + +static void jz_nand_correct_data(uint8_t *dat, int index, int mask) +{ + int offset = index & 0x7; + uint16_t data; + + index += (index >> 3); + + data = dat[index]; + data |= dat[index+1] << 8; + + mask ^= (data >> offset) & 0x1ff; + data &= ~(0x1ff << offset); + data |= (mask << offset); + + dat[index] = data & 0xff; + dat[index+1] = (data >> 8) & 0xff; +} + +static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat, + uint8_t *read_ecc, uint8_t *calc_ecc) +{ + struct jz_nand *nand = mtd_to_jz_nand(mtd); + int i, error_count, index; + uint32_t reg, status, error; + uint32_t t; + unsigned int timeout = 1000; + + t = read_ecc[0]; + + if (t == 0xff) { + for (i = 1; i < 9; ++i) + t &= read_ecc[i]; + + t &= dat[0]; + t &= dat[nand->chip.ecc.size / 2]; + t &= dat[nand->chip.ecc.size - 1]; + + if (t == 0xff) { + for (i = 1; i < nand->chip.ecc.size - 1; ++i) + t &= dat[i]; + if (t == 0xff) + return 0; + } + } + + for (i = 0; i < 9; ++i) + writeb(read_ecc[i], nand->base + JZ_REG_NAND_PAR0 + i); + + reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL); + reg |= JZ_NAND_ECC_CTRL_PAR_READY; + writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL); + + do { + status = readl(nand->base + JZ_REG_NAND_IRQ_STAT); + } while (!(status & JZ_NAND_STATUS_DEC_FINISH) && --timeout); + + if (timeout == 0) + return -1; + + reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL); + reg &= ~JZ_NAND_ECC_CTRL_ENABLE; + writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL); + + if (status & JZ_NAND_STATUS_ERROR) { + if (status & JZ_NAND_STATUS_UNCOR_ERROR) + return -1; + + error_count = (status & JZ_NAND_STATUS_ERR_COUNT) >> 29; + + for (i = 0; i < error_count; ++i) { + error = readl(nand->base + JZ_REG_NAND_ERR(i)); + index = ((error >> 16) & 0x1ff) - 1; + if (index >= 0 && index < 512) + jz_nand_correct_data(dat, index, error & 0x1ff); + } + + return error_count; + } + + return 0; +} + + +/* Copy paste of nand_read_page_hwecc_oob_first except for different eccpos + * handling. The ecc area is for 4k chips 72 bytes long and thus does not fit + * into the eccpos array. */ +static int jz_nand_read_page_hwecc_oob_first(struct mtd_info *mtd, + struct nand_chip *chip, uint8_t *buf, int page) +{ + int i, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + uint8_t *p = buf; + unsigned int ecc_offset = chip->page_shift; + + /* Read the OOB area first */ + chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); + + for (i = ecc_offset; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { + int stat; + + chip->ecc.hwctl(mtd, NAND_ECC_READ); + chip->read_buf(mtd, p, eccsize); + + stat = chip->ecc.correct(mtd, p, &chip->oob_poi[i], NULL); + if (stat < 0) + mtd->ecc_stats.failed++; + else + mtd->ecc_stats.corrected += stat; + } + return 0; +} + +/* Copy-and-paste of nand_write_page_hwecc with different eccpos handling. */ +static void jz_nand_write_page_hwecc(struct mtd_info *mtd, + struct nand_chip *chip, const uint8_t *buf) +{ + int i, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + const uint8_t *p = buf; + unsigned int ecc_offset = chip->page_shift; + + for (i = ecc_offset; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { + chip->ecc.hwctl(mtd, NAND_ECC_WRITE); + chip->write_buf(mtd, p, eccsize); + chip->ecc.calculate(mtd, p, &chip->oob_poi[i]); + } + + chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); +} + +#ifdef CONFIG_MTD_CMDLINE_PARTS +static const char *part_probes[] = {"cmdline", NULL}; +#endif + +static int jz_nand_ioremap_resource(struct platform_device *pdev, + const char *name, struct resource **res, void __iomem **base) +{ + int ret; + + *res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); + if (!*res) { + dev_err(&pdev->dev, "Failed to get platform %s memory\n", name); + ret = -ENXIO; + goto err; + } + + *res = request_mem_region((*res)->start, resource_size(*res), + pdev->name); + if (!*res) { + dev_err(&pdev->dev, "Failed to request %s memory region\n", name); + ret = -EBUSY; + goto err; + } + + *base = ioremap((*res)->start, resource_size(*res)); + if (!*base) { + dev_err(&pdev->dev, "Failed to ioremap %s memory region\n", name); + ret = -EBUSY; + goto err_release_mem; + } + + return 0; + +err_release_mem: + release_mem_region((*res)->start, resource_size(*res)); +err: + *res = NULL; + *base = NULL; + return ret; +} + +static int __devinit jz_nand_probe(struct platform_device *pdev) +{ + int ret; + struct jz_nand *nand; + struct nand_chip *chip; + struct mtd_info *mtd; + struct jz_nand_platform_data *pdata = pdev->dev.platform_data; +#ifdef CONFIG_MTD_PARTITIONS + struct mtd_partition *partition_info; + int num_partitions = 0; +#endif + + nand = kzalloc(sizeof(*nand), GFP_KERNEL); + if (!nand) { + dev_err(&pdev->dev, "Failed to allocate device structure.\n"); + return -ENOMEM; + } + + ret = jz_nand_ioremap_resource(pdev, "mmio", &nand->mem, &nand->base); + if (ret) + goto err_free; + ret = jz_nand_ioremap_resource(pdev, "bank", &nand->bank_mem, + &nand->bank_base); + if (ret) + goto err_iounmap_mmio; + + if (pdata && gpio_is_valid(pdata->busy_gpio)) { + ret = gpio_request(pdata->busy_gpio, "NAND busy pin"); + if (ret) { + dev_err(&pdev->dev, + "Failed to request busy gpio %d: %d\n", + pdata->busy_gpio, ret); + goto err_iounmap_mem; + } + } + + mtd = &nand->mtd; + chip = &nand->chip; + mtd->priv = chip; + mtd->owner = THIS_MODULE; + mtd->name = "jz4740-nand"; + + chip->ecc.hwctl = jz_nand_hwctl; + chip->ecc.calculate = jz_nand_calculate_ecc_rs; + chip->ecc.correct = jz_nand_correct_ecc_rs; + chip->ecc.mode = NAND_ECC_HW_OOB_FIRST; + chip->ecc.size = 512; + chip->ecc.bytes = 9; + + chip->ecc.read_page = jz_nand_read_page_hwecc_oob_first; + chip->ecc.write_page = jz_nand_write_page_hwecc; + + if (pdata) + chip->ecc.layout = pdata->ecc_layout; + + chip->chip_delay = 50; + chip->cmd_ctrl = jz_nand_cmd_ctrl; + + if (pdata && gpio_is_valid(pdata->busy_gpio)) + chip->dev_ready = jz_nand_dev_ready; + + chip->IO_ADDR_R = nand->bank_base; + chip->IO_ADDR_W = nand->bank_base; + + nand->pdata = pdata; + platform_set_drvdata(pdev, nand); + + writel(JZ_NAND_CTRL_ENABLE_CHIP(0), nand->base + JZ_REG_NAND_CTRL); + + ret = nand_scan_ident(mtd, 1, NULL); + if (ret) { + dev_err(&pdev->dev, "Failed to scan nand\n"); + goto err_gpio_free; + } + + if (pdata && pdata->ident_callback) { + pdata->ident_callback(pdev, chip, &pdata->partitions, + &pdata->num_partitions); + } + + ret = nand_scan_tail(mtd); + if (ret) { + dev_err(&pdev->dev, "Failed to scan nand\n"); + goto err_gpio_free; + } + +#ifdef CONFIG_MTD_PARTITIONS +#ifdef CONFIG_MTD_CMDLINE_PARTS + num_partitions = parse_mtd_partitions(mtd, part_probes, + &partition_info, 0); +#endif + if (num_partitions <= 0 && pdata) { + num_partitions = pdata->num_partitions; + partition_info = pdata->partitions; + } + + if (num_partitions > 0) + ret = add_mtd_partitions(mtd, partition_info, num_partitions); + else +#endif + ret = add_mtd_device(mtd); + + if (ret) { + dev_err(&pdev->dev, "Failed to add mtd device\n"); + goto err_nand_release; + } + + dev_info(&pdev->dev, "Successfully registered JZ4740 NAND driver\n"); + + return 0; + +err_nand_release: + nand_release(&nand->mtd); +err_gpio_free: + platform_set_drvdata(pdev, NULL); + gpio_free(pdata->busy_gpio); +err_iounmap_mem: + iounmap(nand->bank_base); +err_iounmap_mmio: + iounmap(nand->base); +err_free: + kfree(nand); + return ret; +} + +static int __devexit jz_nand_remove(struct platform_device *pdev) +{ + struct jz_nand *nand = platform_get_drvdata(pdev); + + nand_release(&nand->mtd); + + /* Deassert and disable all chips */ + writel(0, nand->base + JZ_REG_NAND_CTRL); + + iounmap(nand->bank_base); + release_mem_region(nand->bank_mem->start, resource_size(nand->bank_mem)); + iounmap(nand->base); + release_mem_region(nand->mem->start, resource_size(nand->mem)); + + platform_set_drvdata(pdev, NULL); + kfree(nand); + + return 0; +} + +struct platform_driver jz_nand_driver = { + .probe = jz_nand_probe, + .remove = __devexit_p(jz_nand_remove), + .driver = { + .name = "jz4740-nand", + .owner = THIS_MODULE, + }, +}; + +static int __init jz_nand_init(void) +{ + return platform_driver_register(&jz_nand_driver); +} +module_init(jz_nand_init); + +static void __exit jz_nand_exit(void) +{ + platform_driver_unregister(&jz_nand_driver); +} +module_exit(jz_nand_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("NAND controller driver for JZ4740 SoC"); +MODULE_ALIAS("platform:jz4740-nand"); -- cgit v0.10.2 From 61bfbdb856879cff583fe53b2ab6ae907faedee7 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 15 Jul 2010 20:06:04 +0000 Subject: MMC: Add support for the controller on JZ4740 SoCs. Signed-off-by: Lars-Peter Clausen Acked-by: Matt Fleming Cc: Andrew Morton Cc: Matt Fleming Cc: linux-mmc@vger.kernel.org Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1463/ Patchwork: https://patchwork.linux-mips.org/patch/1523/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-jz4740/jz4740_mmc.h b/arch/mips/include/asm/mach-jz4740/jz4740_mmc.h new file mode 100644 index 0000000..8543f43 --- /dev/null +++ b/arch/mips/include/asm/mach-jz4740/jz4740_mmc.h @@ -0,0 +1,15 @@ +#ifndef __LINUX_MMC_JZ4740_MMC +#define __LINUX_MMC_JZ4740_MMC + +struct jz4740_mmc_platform_data { + int gpio_power; + int gpio_card_detect; + int gpio_read_only; + unsigned card_detect_active_low:1; + unsigned read_only_active_low:1; + unsigned power_active_low:1; + + unsigned data_1bit:1; +}; + +#endif diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index f06d06e..d25e22c 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -432,3 +432,12 @@ config MMC_SH_MMCIF This selects the MMC Host Interface controler (MMCIF). This driver supports MMCIF in sh7724/sh7757/sh7372. + +config MMC_JZ4740 + tristate "JZ4740 SD/Multimedia Card Interface support" + depends on MACH_JZ4740 + help + This selects support for the SD/MMC controller on Ingenic JZ4740 + SoCs. + If you have a board based on such a SoC and with a SD/MMC slot, + say Y or M here. diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index e30c2ee..f4e53c9 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_MMC_CB710) += cb710-mmc.o obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o +obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o sdhci-of-y := sdhci-of-core.o diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c new file mode 100644 index 0000000..ad4f987 --- /dev/null +++ b/drivers/mmc/host/jz4740_mmc.c @@ -0,0 +1,1029 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * JZ4740 SD/MMC controller driver + * + * 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. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#define JZ_REG_MMC_STRPCL 0x00 +#define JZ_REG_MMC_STATUS 0x04 +#define JZ_REG_MMC_CLKRT 0x08 +#define JZ_REG_MMC_CMDAT 0x0C +#define JZ_REG_MMC_RESTO 0x10 +#define JZ_REG_MMC_RDTO 0x14 +#define JZ_REG_MMC_BLKLEN 0x18 +#define JZ_REG_MMC_NOB 0x1C +#define JZ_REG_MMC_SNOB 0x20 +#define JZ_REG_MMC_IMASK 0x24 +#define JZ_REG_MMC_IREG 0x28 +#define JZ_REG_MMC_CMD 0x2C +#define JZ_REG_MMC_ARG 0x30 +#define JZ_REG_MMC_RESP_FIFO 0x34 +#define JZ_REG_MMC_RXFIFO 0x38 +#define JZ_REG_MMC_TXFIFO 0x3C + +#define JZ_MMC_STRPCL_EXIT_MULTIPLE BIT(7) +#define JZ_MMC_STRPCL_EXIT_TRANSFER BIT(6) +#define JZ_MMC_STRPCL_START_READWAIT BIT(5) +#define JZ_MMC_STRPCL_STOP_READWAIT BIT(4) +#define JZ_MMC_STRPCL_RESET BIT(3) +#define JZ_MMC_STRPCL_START_OP BIT(2) +#define JZ_MMC_STRPCL_CLOCK_CONTROL (BIT(1) | BIT(0)) +#define JZ_MMC_STRPCL_CLOCK_STOP BIT(0) +#define JZ_MMC_STRPCL_CLOCK_START BIT(1) + + +#define JZ_MMC_STATUS_IS_RESETTING BIT(15) +#define JZ_MMC_STATUS_SDIO_INT_ACTIVE BIT(14) +#define JZ_MMC_STATUS_PRG_DONE BIT(13) +#define JZ_MMC_STATUS_DATA_TRAN_DONE BIT(12) +#define JZ_MMC_STATUS_END_CMD_RES BIT(11) +#define JZ_MMC_STATUS_DATA_FIFO_AFULL BIT(10) +#define JZ_MMC_STATUS_IS_READWAIT BIT(9) +#define JZ_MMC_STATUS_CLK_EN BIT(8) +#define JZ_MMC_STATUS_DATA_FIFO_FULL BIT(7) +#define JZ_MMC_STATUS_DATA_FIFO_EMPTY BIT(6) +#define JZ_MMC_STATUS_CRC_RES_ERR BIT(5) +#define JZ_MMC_STATUS_CRC_READ_ERROR BIT(4) +#define JZ_MMC_STATUS_TIMEOUT_WRITE BIT(3) +#define JZ_MMC_STATUS_CRC_WRITE_ERROR BIT(2) +#define JZ_MMC_STATUS_TIMEOUT_RES BIT(1) +#define JZ_MMC_STATUS_TIMEOUT_READ BIT(0) + +#define JZ_MMC_STATUS_READ_ERROR_MASK (BIT(4) | BIT(0)) +#define JZ_MMC_STATUS_WRITE_ERROR_MASK (BIT(3) | BIT(2)) + + +#define JZ_MMC_CMDAT_IO_ABORT BIT(11) +#define JZ_MMC_CMDAT_BUS_WIDTH_4BIT BIT(10) +#define JZ_MMC_CMDAT_DMA_EN BIT(8) +#define JZ_MMC_CMDAT_INIT BIT(7) +#define JZ_MMC_CMDAT_BUSY BIT(6) +#define JZ_MMC_CMDAT_STREAM BIT(5) +#define JZ_MMC_CMDAT_WRITE BIT(4) +#define JZ_MMC_CMDAT_DATA_EN BIT(3) +#define JZ_MMC_CMDAT_RESPONSE_FORMAT (BIT(2) | BIT(1) | BIT(0)) +#define JZ_MMC_CMDAT_RSP_R1 1 +#define JZ_MMC_CMDAT_RSP_R2 2 +#define JZ_MMC_CMDAT_RSP_R3 3 + +#define JZ_MMC_IRQ_SDIO BIT(7) +#define JZ_MMC_IRQ_TXFIFO_WR_REQ BIT(6) +#define JZ_MMC_IRQ_RXFIFO_RD_REQ BIT(5) +#define JZ_MMC_IRQ_END_CMD_RES BIT(2) +#define JZ_MMC_IRQ_PRG_DONE BIT(1) +#define JZ_MMC_IRQ_DATA_TRAN_DONE BIT(0) + + +#define JZ_MMC_CLK_RATE 24000000 + +enum jz4740_mmc_state { + JZ4740_MMC_STATE_READ_RESPONSE, + JZ4740_MMC_STATE_TRANSFER_DATA, + JZ4740_MMC_STATE_SEND_STOP, + JZ4740_MMC_STATE_DONE, +}; + +struct jz4740_mmc_host { + struct mmc_host *mmc; + struct platform_device *pdev; + struct jz4740_mmc_platform_data *pdata; + struct clk *clk; + + int irq; + int card_detect_irq; + + struct resource *mem; + void __iomem *base; + struct mmc_request *req; + struct mmc_command *cmd; + + unsigned long waiting; + + uint32_t cmdat; + + uint16_t irq_mask; + + spinlock_t lock; + + struct timer_list timeout_timer; + struct sg_mapping_iter miter; + enum jz4740_mmc_state state; +}; + +static void jz4740_mmc_set_irq_enabled(struct jz4740_mmc_host *host, + unsigned int irq, bool enabled) +{ + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + if (enabled) + host->irq_mask &= ~irq; + else + host->irq_mask |= irq; + spin_unlock_irqrestore(&host->lock, flags); + + writew(host->irq_mask, host->base + JZ_REG_MMC_IMASK); +} + +static void jz4740_mmc_clock_enable(struct jz4740_mmc_host *host, + bool start_transfer) +{ + uint16_t val = JZ_MMC_STRPCL_CLOCK_START; + + if (start_transfer) + val |= JZ_MMC_STRPCL_START_OP; + + writew(val, host->base + JZ_REG_MMC_STRPCL); +} + +static void jz4740_mmc_clock_disable(struct jz4740_mmc_host *host) +{ + uint32_t status; + unsigned int timeout = 1000; + + writew(JZ_MMC_STRPCL_CLOCK_STOP, host->base + JZ_REG_MMC_STRPCL); + do { + status = readl(host->base + JZ_REG_MMC_STATUS); + } while (status & JZ_MMC_STATUS_CLK_EN && --timeout); +} + +static void jz4740_mmc_reset(struct jz4740_mmc_host *host) +{ + uint32_t status; + unsigned int timeout = 1000; + + writew(JZ_MMC_STRPCL_RESET, host->base + JZ_REG_MMC_STRPCL); + udelay(10); + do { + status = readl(host->base + JZ_REG_MMC_STATUS); + } while (status & JZ_MMC_STATUS_IS_RESETTING && --timeout); +} + +static void jz4740_mmc_request_done(struct jz4740_mmc_host *host) +{ + struct mmc_request *req; + + req = host->req; + host->req = NULL; + + mmc_request_done(host->mmc, req); +} + +static unsigned int jz4740_mmc_poll_irq(struct jz4740_mmc_host *host, + unsigned int irq) +{ + unsigned int timeout = 0x800; + uint16_t status; + + do { + status = readw(host->base + JZ_REG_MMC_IREG); + } while (!(status & irq) && --timeout); + + if (timeout == 0) { + set_bit(0, &host->waiting); + mod_timer(&host->timeout_timer, jiffies + 5*HZ); + jz4740_mmc_set_irq_enabled(host, irq, true); + return true; + } + + return false; +} + +static void jz4740_mmc_transfer_check_state(struct jz4740_mmc_host *host, + struct mmc_data *data) +{ + int status; + + status = readl(host->base + JZ_REG_MMC_STATUS); + if (status & JZ_MMC_STATUS_WRITE_ERROR_MASK) { + if (status & (JZ_MMC_STATUS_TIMEOUT_WRITE)) { + host->req->cmd->error = -ETIMEDOUT; + data->error = -ETIMEDOUT; + } else { + host->req->cmd->error = -EIO; + data->error = -EIO; + } + } +} + +static bool jz4740_mmc_write_data(struct jz4740_mmc_host *host, + struct mmc_data *data) +{ + struct sg_mapping_iter *miter = &host->miter; + void __iomem *fifo_addr = host->base + JZ_REG_MMC_TXFIFO; + uint32_t *buf; + bool timeout; + size_t i, j; + + while (sg_miter_next(miter)) { + buf = miter->addr; + i = miter->length / 4; + j = i / 8; + i = i & 0x7; + while (j) { + timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_TXFIFO_WR_REQ); + if (unlikely(timeout)) + goto poll_timeout; + + writel(buf[0], fifo_addr); + writel(buf[1], fifo_addr); + writel(buf[2], fifo_addr); + writel(buf[3], fifo_addr); + writel(buf[4], fifo_addr); + writel(buf[5], fifo_addr); + writel(buf[6], fifo_addr); + writel(buf[7], fifo_addr); + buf += 8; + --j; + } + if (unlikely(i)) { + timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_TXFIFO_WR_REQ); + if (unlikely(timeout)) + goto poll_timeout; + + while (i) { + writel(*buf, fifo_addr); + ++buf; + --i; + } + } + data->bytes_xfered += miter->length; + } + sg_miter_stop(miter); + + return false; + +poll_timeout: + miter->consumed = (void *)buf - miter->addr; + data->bytes_xfered += miter->consumed; + sg_miter_stop(miter); + + return true; +} + +static bool jz4740_mmc_read_data(struct jz4740_mmc_host *host, + struct mmc_data *data) +{ + struct sg_mapping_iter *miter = &host->miter; + void __iomem *fifo_addr = host->base + JZ_REG_MMC_RXFIFO; + uint32_t *buf; + uint32_t d; + uint16_t status; + size_t i, j; + unsigned int timeout; + + while (sg_miter_next(miter)) { + buf = miter->addr; + i = miter->length; + j = i / 32; + i = i & 0x1f; + while (j) { + timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_RXFIFO_RD_REQ); + if (unlikely(timeout)) + goto poll_timeout; + + buf[0] = readl(fifo_addr); + buf[1] = readl(fifo_addr); + buf[2] = readl(fifo_addr); + buf[3] = readl(fifo_addr); + buf[4] = readl(fifo_addr); + buf[5] = readl(fifo_addr); + buf[6] = readl(fifo_addr); + buf[7] = readl(fifo_addr); + + buf += 8; + --j; + } + + if (unlikely(i)) { + timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_RXFIFO_RD_REQ); + if (unlikely(timeout)) + goto poll_timeout; + + while (i >= 4) { + *buf++ = readl(fifo_addr); + i -= 4; + } + if (unlikely(i > 0)) { + d = readl(fifo_addr); + memcpy(buf, &d, i); + } + } + data->bytes_xfered += miter->length; + + /* This can go away once MIPS implements + * flush_kernel_dcache_page */ + flush_dcache_page(miter->page); + } + sg_miter_stop(miter); + + /* For whatever reason there is sometime one word more in the fifo then + * requested */ + timeout = 1000; + status = readl(host->base + JZ_REG_MMC_STATUS); + while (!(status & JZ_MMC_STATUS_DATA_FIFO_EMPTY) && --timeout) { + d = readl(fifo_addr); + status = readl(host->base + JZ_REG_MMC_STATUS); + } + + return false; + +poll_timeout: + miter->consumed = (void *)buf - miter->addr; + data->bytes_xfered += miter->consumed; + sg_miter_stop(miter); + + return true; +} + +static void jz4740_mmc_timeout(unsigned long data) +{ + struct jz4740_mmc_host *host = (struct jz4740_mmc_host *)data; + + if (!test_and_clear_bit(0, &host->waiting)) + return; + + jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_END_CMD_RES, false); + + host->req->cmd->error = -ETIMEDOUT; + jz4740_mmc_request_done(host); +} + +static void jz4740_mmc_read_response(struct jz4740_mmc_host *host, + struct mmc_command *cmd) +{ + int i; + uint16_t tmp; + void __iomem *fifo_addr = host->base + JZ_REG_MMC_RESP_FIFO; + + if (cmd->flags & MMC_RSP_136) { + tmp = readw(fifo_addr); + for (i = 0; i < 4; ++i) { + cmd->resp[i] = tmp << 24; + tmp = readw(fifo_addr); + cmd->resp[i] |= tmp << 8; + tmp = readw(fifo_addr); + cmd->resp[i] |= tmp >> 8; + } + } else { + cmd->resp[0] = readw(fifo_addr) << 24; + cmd->resp[0] |= readw(fifo_addr) << 8; + cmd->resp[0] |= readw(fifo_addr) & 0xff; + } +} + +static void jz4740_mmc_send_command(struct jz4740_mmc_host *host, + struct mmc_command *cmd) +{ + uint32_t cmdat = host->cmdat; + + host->cmdat &= ~JZ_MMC_CMDAT_INIT; + jz4740_mmc_clock_disable(host); + + host->cmd = cmd; + + if (cmd->flags & MMC_RSP_BUSY) + cmdat |= JZ_MMC_CMDAT_BUSY; + + switch (mmc_resp_type(cmd)) { + case MMC_RSP_R1B: + case MMC_RSP_R1: + cmdat |= JZ_MMC_CMDAT_RSP_R1; + break; + case MMC_RSP_R2: + cmdat |= JZ_MMC_CMDAT_RSP_R2; + break; + case MMC_RSP_R3: + cmdat |= JZ_MMC_CMDAT_RSP_R3; + break; + default: + break; + } + + if (cmd->data) { + cmdat |= JZ_MMC_CMDAT_DATA_EN; + if (cmd->data->flags & MMC_DATA_WRITE) + cmdat |= JZ_MMC_CMDAT_WRITE; + if (cmd->data->flags & MMC_DATA_STREAM) + cmdat |= JZ_MMC_CMDAT_STREAM; + + writew(cmd->data->blksz, host->base + JZ_REG_MMC_BLKLEN); + writew(cmd->data->blocks, host->base + JZ_REG_MMC_NOB); + } + + writeb(cmd->opcode, host->base + JZ_REG_MMC_CMD); + writel(cmd->arg, host->base + JZ_REG_MMC_ARG); + writel(cmdat, host->base + JZ_REG_MMC_CMDAT); + + jz4740_mmc_clock_enable(host, 1); +} + +static void jz_mmc_prepare_data_transfer(struct jz4740_mmc_host *host) +{ + struct mmc_command *cmd = host->req->cmd; + struct mmc_data *data = cmd->data; + int direction; + + if (data->flags & MMC_DATA_READ) + direction = SG_MITER_TO_SG; + else + direction = SG_MITER_FROM_SG; + + sg_miter_start(&host->miter, data->sg, data->sg_len, direction); +} + + +static irqreturn_t jz_mmc_irq_worker(int irq, void *devid) +{ + struct jz4740_mmc_host *host = (struct jz4740_mmc_host *)devid; + struct mmc_command *cmd = host->req->cmd; + struct mmc_request *req = host->req; + bool timeout = false; + + if (cmd->error) + host->state = JZ4740_MMC_STATE_DONE; + + switch (host->state) { + case JZ4740_MMC_STATE_READ_RESPONSE: + if (cmd->flags & MMC_RSP_PRESENT) + jz4740_mmc_read_response(host, cmd); + + if (!cmd->data) + break; + + jz_mmc_prepare_data_transfer(host); + + case JZ4740_MMC_STATE_TRANSFER_DATA: + if (cmd->data->flags & MMC_DATA_READ) + timeout = jz4740_mmc_read_data(host, cmd->data); + else + timeout = jz4740_mmc_write_data(host, cmd->data); + + if (unlikely(timeout)) { + host->state = JZ4740_MMC_STATE_TRANSFER_DATA; + break; + } + + jz4740_mmc_transfer_check_state(host, cmd->data); + + timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_DATA_TRAN_DONE); + if (unlikely(timeout)) { + host->state = JZ4740_MMC_STATE_SEND_STOP; + break; + } + writew(JZ_MMC_IRQ_DATA_TRAN_DONE, host->base + JZ_REG_MMC_IREG); + + case JZ4740_MMC_STATE_SEND_STOP: + if (!req->stop) + break; + + jz4740_mmc_send_command(host, req->stop); + + timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_PRG_DONE); + if (timeout) { + host->state = JZ4740_MMC_STATE_DONE; + break; + } + case JZ4740_MMC_STATE_DONE: + break; + } + + if (!timeout) + jz4740_mmc_request_done(host); + + return IRQ_HANDLED; +} + +static irqreturn_t jz_mmc_irq(int irq, void *devid) +{ + struct jz4740_mmc_host *host = devid; + struct mmc_command *cmd = host->cmd; + uint16_t irq_reg, status, tmp; + + irq_reg = readw(host->base + JZ_REG_MMC_IREG); + + tmp = irq_reg; + irq_reg &= ~host->irq_mask; + + tmp &= ~(JZ_MMC_IRQ_TXFIFO_WR_REQ | JZ_MMC_IRQ_RXFIFO_RD_REQ | + JZ_MMC_IRQ_PRG_DONE | JZ_MMC_IRQ_DATA_TRAN_DONE); + + if (tmp != irq_reg) + writew(tmp & ~irq_reg, host->base + JZ_REG_MMC_IREG); + + if (irq_reg & JZ_MMC_IRQ_SDIO) { + writew(JZ_MMC_IRQ_SDIO, host->base + JZ_REG_MMC_IREG); + mmc_signal_sdio_irq(host->mmc); + irq_reg &= ~JZ_MMC_IRQ_SDIO; + } + + if (host->req && cmd && irq_reg) { + if (test_and_clear_bit(0, &host->waiting)) { + del_timer(&host->timeout_timer); + + status = readl(host->base + JZ_REG_MMC_STATUS); + + if (status & JZ_MMC_STATUS_TIMEOUT_RES) { + cmd->error = -ETIMEDOUT; + } else if (status & JZ_MMC_STATUS_CRC_RES_ERR) { + cmd->error = -EIO; + } else if (status & (JZ_MMC_STATUS_CRC_READ_ERROR | + JZ_MMC_STATUS_CRC_WRITE_ERROR)) { + if (cmd->data) + cmd->data->error = -EIO; + cmd->error = -EIO; + } else if (status & (JZ_MMC_STATUS_CRC_READ_ERROR | + JZ_MMC_STATUS_CRC_WRITE_ERROR)) { + if (cmd->data) + cmd->data->error = -EIO; + cmd->error = -EIO; + } + + jz4740_mmc_set_irq_enabled(host, irq_reg, false); + writew(irq_reg, host->base + JZ_REG_MMC_IREG); + + return IRQ_WAKE_THREAD; + } + } + + return IRQ_HANDLED; +} + +static int jz4740_mmc_set_clock_rate(struct jz4740_mmc_host *host, int rate) +{ + int div = 0; + int real_rate; + + jz4740_mmc_clock_disable(host); + clk_set_rate(host->clk, JZ_MMC_CLK_RATE); + + real_rate = clk_get_rate(host->clk); + + while (real_rate > rate && div < 7) { + ++div; + real_rate >>= 1; + } + + writew(div, host->base + JZ_REG_MMC_CLKRT); + return real_rate; +} + +static void jz4740_mmc_request(struct mmc_host *mmc, struct mmc_request *req) +{ + struct jz4740_mmc_host *host = mmc_priv(mmc); + + host->req = req; + + writew(0xffff, host->base + JZ_REG_MMC_IREG); + + writew(JZ_MMC_IRQ_END_CMD_RES, host->base + JZ_REG_MMC_IREG); + jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_END_CMD_RES, true); + + host->state = JZ4740_MMC_STATE_READ_RESPONSE; + set_bit(0, &host->waiting); + mod_timer(&host->timeout_timer, jiffies + 5*HZ); + jz4740_mmc_send_command(host, req->cmd); +} + +static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct jz4740_mmc_host *host = mmc_priv(mmc); + if (ios->clock) + jz4740_mmc_set_clock_rate(host, ios->clock); + + switch (ios->power_mode) { + case MMC_POWER_UP: + jz4740_mmc_reset(host); + if (gpio_is_valid(host->pdata->gpio_power)) + gpio_set_value(host->pdata->gpio_power, + !host->pdata->power_active_low); + host->cmdat |= JZ_MMC_CMDAT_INIT; + clk_enable(host->clk); + break; + case MMC_POWER_ON: + break; + default: + if (gpio_is_valid(host->pdata->gpio_power)) + gpio_set_value(host->pdata->gpio_power, + host->pdata->power_active_low); + clk_disable(host->clk); + break; + } + + switch (ios->bus_width) { + case MMC_BUS_WIDTH_1: + host->cmdat &= ~JZ_MMC_CMDAT_BUS_WIDTH_4BIT; + break; + case MMC_BUS_WIDTH_4: + host->cmdat |= JZ_MMC_CMDAT_BUS_WIDTH_4BIT; + break; + default: + break; + } +} + +static int jz4740_mmc_get_ro(struct mmc_host *mmc) +{ + struct jz4740_mmc_host *host = mmc_priv(mmc); + if (!gpio_is_valid(host->pdata->gpio_read_only)) + return -ENOSYS; + + return gpio_get_value(host->pdata->gpio_read_only) ^ + host->pdata->read_only_active_low; +} + +static int jz4740_mmc_get_cd(struct mmc_host *mmc) +{ + struct jz4740_mmc_host *host = mmc_priv(mmc); + if (!gpio_is_valid(host->pdata->gpio_card_detect)) + return -ENOSYS; + + return gpio_get_value(host->pdata->gpio_card_detect) ^ + host->pdata->card_detect_active_low; +} + +static irqreturn_t jz4740_mmc_card_detect_irq(int irq, void *devid) +{ + struct jz4740_mmc_host *host = devid; + + mmc_detect_change(host->mmc, HZ / 2); + + return IRQ_HANDLED; +} + +static void jz4740_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) +{ + struct jz4740_mmc_host *host = mmc_priv(mmc); + jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_SDIO, enable); +} + +static const struct mmc_host_ops jz4740_mmc_ops = { + .request = jz4740_mmc_request, + .set_ios = jz4740_mmc_set_ios, + .get_ro = jz4740_mmc_get_ro, + .get_cd = jz4740_mmc_get_cd, + .enable_sdio_irq = jz4740_mmc_enable_sdio_irq, +}; + +static const struct jz_gpio_bulk_request jz4740_mmc_pins[] = { + JZ_GPIO_BULK_PIN(MSC_CMD), + JZ_GPIO_BULK_PIN(MSC_CLK), + JZ_GPIO_BULK_PIN(MSC_DATA0), + JZ_GPIO_BULK_PIN(MSC_DATA1), + JZ_GPIO_BULK_PIN(MSC_DATA2), + JZ_GPIO_BULK_PIN(MSC_DATA3), +}; + +static int __devinit jz4740_mmc_request_gpio(struct device *dev, int gpio, + const char *name, bool output, int value) +{ + int ret; + + if (!gpio_is_valid(gpio)) + return 0; + + ret = gpio_request(gpio, name); + if (ret) { + dev_err(dev, "Failed to request %s gpio: %d\n", name, ret); + return ret; + } + + if (output) + gpio_direction_output(gpio, value); + else + gpio_direction_input(gpio); + + return 0; +} + +static int __devinit jz4740_mmc_request_gpios(struct platform_device *pdev) +{ + int ret; + struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data; + + if (!pdata) + return 0; + + ret = jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_card_detect, + "MMC detect change", false, 0); + if (ret) + goto err; + + ret = jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_read_only, + "MMC read only", false, 0); + if (ret) + goto err_free_gpio_card_detect; + + ret = jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_power, + "MMC read only", true, pdata->power_active_low); + if (ret) + goto err_free_gpio_read_only; + + return 0; + +err_free_gpio_read_only: + if (gpio_is_valid(pdata->gpio_read_only)) + gpio_free(pdata->gpio_read_only); +err_free_gpio_card_detect: + if (gpio_is_valid(pdata->gpio_card_detect)) + gpio_free(pdata->gpio_card_detect); +err: + return ret; +} + +static int __devinit jz4740_mmc_request_cd_irq(struct platform_device *pdev, + struct jz4740_mmc_host *host) +{ + struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data; + + if (!gpio_is_valid(pdata->gpio_card_detect)) + return 0; + + host->card_detect_irq = gpio_to_irq(pdata->gpio_card_detect); + if (host->card_detect_irq < 0) { + dev_warn(&pdev->dev, "Failed to get card detect irq\n"); + return 0; + } + + return request_irq(host->card_detect_irq, jz4740_mmc_card_detect_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "MMC card detect", host); +} + +static void jz4740_mmc_free_gpios(struct platform_device *pdev) +{ + struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data; + + if (!pdata) + return; + + if (gpio_is_valid(pdata->gpio_power)) + gpio_free(pdata->gpio_power); + if (gpio_is_valid(pdata->gpio_read_only)) + gpio_free(pdata->gpio_read_only); + if (gpio_is_valid(pdata->gpio_card_detect)) + gpio_free(pdata->gpio_card_detect); +} + +static inline size_t jz4740_mmc_num_pins(struct jz4740_mmc_host *host) +{ + size_t num_pins = ARRAY_SIZE(jz4740_mmc_pins); + if (host->pdata && host->pdata->data_1bit) + num_pins -= 3; + + return num_pins; +} + +static int __devinit jz4740_mmc_probe(struct platform_device* pdev) +{ + int ret; + struct mmc_host *mmc; + struct jz4740_mmc_host *host; + struct jz4740_mmc_platform_data *pdata; + + pdata = pdev->dev.platform_data; + + mmc = mmc_alloc_host(sizeof(struct jz4740_mmc_host), &pdev->dev); + if (!mmc) { + dev_err(&pdev->dev, "Failed to alloc mmc host structure\n"); + return -ENOMEM; + } + + host = mmc_priv(mmc); + host->pdata = pdata; + + host->irq = platform_get_irq(pdev, 0); + if (host->irq < 0) { + ret = host->irq; + dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret); + goto err_free_host; + } + + host->clk = clk_get(&pdev->dev, "mmc"); + if (!host->clk) { + ret = -ENOENT; + dev_err(&pdev->dev, "Failed to get mmc clock\n"); + goto err_free_host; + } + + host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!host->mem) { + ret = -ENOENT; + dev_err(&pdev->dev, "Failed to get base platform memory\n"); + goto err_clk_put; + } + + host->mem = request_mem_region(host->mem->start, + resource_size(host->mem), pdev->name); + if (!host->mem) { + ret = -EBUSY; + dev_err(&pdev->dev, "Failed to request base memory region\n"); + goto err_clk_put; + } + + host->base = ioremap_nocache(host->mem->start, resource_size(host->mem)); + if (!host->base) { + ret = -EBUSY; + dev_err(&pdev->dev, "Failed to ioremap base memory\n"); + goto err_release_mem_region; + } + + ret = jz_gpio_bulk_request(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); + if (ret) { + dev_err(&pdev->dev, "Failed to request mmc pins: %d\n", ret); + goto err_iounmap; + } + + ret = jz4740_mmc_request_gpios(pdev); + if (ret) + goto err_gpio_bulk_free; + + mmc->ops = &jz4740_mmc_ops; + mmc->f_min = JZ_MMC_CLK_RATE / 128; + mmc->f_max = JZ_MMC_CLK_RATE; + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + mmc->caps = (pdata && pdata->data_1bit) ? 0 : MMC_CAP_4_BIT_DATA; + mmc->caps |= MMC_CAP_SDIO_IRQ; + + mmc->max_blk_size = (1 << 10) - 1; + mmc->max_blk_count = (1 << 15) - 1; + mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; + + mmc->max_phys_segs = 128; + mmc->max_hw_segs = 128; + mmc->max_seg_size = mmc->max_req_size; + + host->mmc = mmc; + host->pdev = pdev; + spin_lock_init(&host->lock); + host->irq_mask = 0xffff; + + ret = jz4740_mmc_request_cd_irq(pdev, host); + if (ret) { + dev_err(&pdev->dev, "Failed to request card detect irq\n"); + goto err_free_gpios; + } + + ret = request_threaded_irq(host->irq, jz_mmc_irq, jz_mmc_irq_worker, 0, + dev_name(&pdev->dev), host); + if (ret) { + dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); + goto err_free_card_detect_irq; + } + + jz4740_mmc_reset(host); + jz4740_mmc_clock_disable(host); + setup_timer(&host->timeout_timer, jz4740_mmc_timeout, + (unsigned long)host); + /* It is not important when it times out, it just needs to timeout. */ + set_timer_slack(&host->timeout_timer, HZ); + + platform_set_drvdata(pdev, host); + ret = mmc_add_host(mmc); + + if (ret) { + dev_err(&pdev->dev, "Failed to add mmc host: %d\n", ret); + goto err_free_irq; + } + dev_info(&pdev->dev, "JZ SD/MMC card driver registered\n"); + + return 0; + +err_free_irq: + free_irq(host->irq, host); +err_free_card_detect_irq: + if (host->card_detect_irq >= 0) + free_irq(host->card_detect_irq, host); +err_free_gpios: + jz4740_mmc_free_gpios(pdev); +err_gpio_bulk_free: + jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); +err_iounmap: + iounmap(host->base); +err_release_mem_region: + release_mem_region(host->mem->start, resource_size(host->mem)); +err_clk_put: + clk_put(host->clk); +err_free_host: + platform_set_drvdata(pdev, NULL); + mmc_free_host(mmc); + + return ret; +} + +static int __devexit jz4740_mmc_remove(struct platform_device *pdev) +{ + struct jz4740_mmc_host *host = platform_get_drvdata(pdev); + + del_timer_sync(&host->timeout_timer); + jz4740_mmc_set_irq_enabled(host, 0xff, false); + jz4740_mmc_reset(host); + + mmc_remove_host(host->mmc); + + free_irq(host->irq, host); + if (host->card_detect_irq >= 0) + free_irq(host->card_detect_irq, host); + + jz4740_mmc_free_gpios(pdev); + jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); + + iounmap(host->base); + release_mem_region(host->mem->start, resource_size(host->mem)); + + clk_put(host->clk); + + platform_set_drvdata(pdev, NULL); + mmc_free_host(host->mmc); + + return 0; +} + +#ifdef CONFIG_PM + +static int jz4740_mmc_suspend(struct device *dev) +{ + struct jz4740_mmc_host *host = dev_get_drvdata(dev); + + mmc_suspend_host(host->mmc); + + jz_gpio_bulk_suspend(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); + + return 0; +} + +static int jz4740_mmc_resume(struct device *dev) +{ + struct jz4740_mmc_host *host = dev_get_drvdata(dev); + + jz_gpio_bulk_resume(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); + + mmc_resume_host(host->mmc); + + return 0; +} + +const struct dev_pm_ops jz4740_mmc_pm_ops = { + .suspend = jz4740_mmc_suspend, + .resume = jz4740_mmc_resume, + .poweroff = jz4740_mmc_suspend, + .restore = jz4740_mmc_resume, +}; + +#define JZ4740_MMC_PM_OPS (&jz4740_mmc_pm_ops) +#else +#define JZ4740_MMC_PM_OPS NULL +#endif + +static struct platform_driver jz4740_mmc_driver = { + .probe = jz4740_mmc_probe, + .remove = __devexit_p(jz4740_mmc_remove), + .driver = { + .name = "jz4740-mmc", + .owner = THIS_MODULE, + .pm = JZ4740_MMC_PM_OPS, + }, +}; + +static int __init jz4740_mmc_init(void) +{ + return platform_driver_register(&jz4740_mmc_driver); +} +module_init(jz4740_mmc_init); + +static void __exit jz4740_mmc_exit(void) +{ + platform_driver_unregister(&jz4740_mmc_driver); +} +module_exit(jz4740_mmc_exit); + +MODULE_DESCRIPTION("JZ4740 SD/MMC controller driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Lars-Peter Clausen "); -- cgit v0.10.2 From 2249071b3e03747884d0781ab10b0b9ceac5756b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 19 Jun 2010 04:08:24 +0000 Subject: USB: Add JZ4740 OHCI support Add OHCI glue code for JZ4740 SoCs OHCI module. Signed-off-by: Lars-Peter Clausen Cc: Greg Kroah-Hartman Cc: David Brownell Cc: linux-usb@vger.kernel.org Acked-by: Greg Kroah-Hartman Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1411/ Signed-off-by: Ralf Baechle diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index c2ddab1..4aa00e6 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -46,6 +46,7 @@ config USB_ARCH_HAS_OHCI default y if PPC_MPC52xx # MIPS: default y if MIPS_ALCHEMY + default y if MACH_JZ4740 # SH: default y if CPU_SUBTYPE_SH7720 default y if CPU_SUBTYPE_SH7721 diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index ba6b0a5..02864a2 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1095,6 +1095,11 @@ MODULE_LICENSE ("GPL"); #define TMIO_OHCI_DRIVER ohci_hcd_tmio_driver #endif +#ifdef CONFIG_MACH_JZ4740 +#include "ohci-jz4740.c" +#define PLATFORM_DRIVER ohci_hcd_jz4740_driver +#endif + #if !defined(PCI_DRIVER) && \ !defined(PLATFORM_DRIVER) && \ !defined(OMAP1_PLATFORM_DRIVER) && \ diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c new file mode 100644 index 0000000..10e1872 --- /dev/null +++ b/drivers/usb/host/ohci-jz4740.c @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * + * 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. + * + * 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. + * + */ + +#include +#include +#include + +struct jz4740_ohci_hcd { + struct ohci_hcd ohci_hcd; + + struct regulator *vbus; + bool vbus_enabled; + struct clk *clk; +}; + +static inline struct jz4740_ohci_hcd *hcd_to_jz4740_hcd(struct usb_hcd *hcd) +{ + return (struct jz4740_ohci_hcd *)(hcd->hcd_priv); +} + +static inline struct usb_hcd *jz4740_hcd_to_hcd(struct jz4740_ohci_hcd *jz4740_ohci) +{ + return container_of((void *)jz4740_ohci, struct usb_hcd, hcd_priv); +} + +static int ohci_jz4740_start(struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + int ret; + + ret = ohci_init(ohci); + if (ret < 0) + return ret; + + ohci->num_ports = 1; + + ret = ohci_run(ohci); + if (ret < 0) { + dev_err(hcd->self.controller, "Can not start %s", + hcd->self.bus_name); + ohci_stop(hcd); + return ret; + } + return 0; +} + +static int ohci_jz4740_set_vbus_power(struct jz4740_ohci_hcd *jz4740_ohci, + bool enabled) +{ + int ret = 0; + + if (!jz4740_ohci->vbus) + return 0; + + if (enabled && !jz4740_ohci->vbus_enabled) { + ret = regulator_enable(jz4740_ohci->vbus); + if (ret) + dev_err(jz4740_hcd_to_hcd(jz4740_ohci)->self.controller, + "Could not power vbus\n"); + } else if (!enabled && jz4740_ohci->vbus_enabled) { + ret = regulator_disable(jz4740_ohci->vbus); + } + + if (ret == 0) + jz4740_ohci->vbus_enabled = enabled; + + return ret; +} + +static int ohci_jz4740_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, + u16 wIndex, char *buf, u16 wLength) +{ + struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd); + int ret; + + switch (typeReq) { + case SetHubFeature: + if (wValue == USB_PORT_FEAT_POWER) + ret = ohci_jz4740_set_vbus_power(jz4740_ohci, true); + break; + case ClearHubFeature: + if (wValue == USB_PORT_FEAT_POWER) + ret = ohci_jz4740_set_vbus_power(jz4740_ohci, false); + break; + } + + if (ret) + return ret; + + return ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); +} + + +static const struct hc_driver ohci_jz4740_hc_driver = { + .description = hcd_name, + .product_desc = "JZ4740 OHCI", + .hcd_priv_size = sizeof(struct jz4740_ohci_hcd), + + /* + * generic hardware linkage + */ + .irq = ohci_irq, + .flags = HCD_USB11 | HCD_MEMORY, + + /* + * basic lifecycle operations + */ + .start = ohci_jz4740_start, + .stop = ohci_stop, + .shutdown = ohci_shutdown, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ohci_urb_enqueue, + .urb_dequeue = ohci_urb_dequeue, + .endpoint_disable = ohci_endpoint_disable, + + /* + * scheduling support + */ + .get_frame_number = ohci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ohci_hub_status_data, + .hub_control = ohci_jz4740_hub_control, +#ifdef CONFIG_PM + .bus_suspend = ohci_bus_suspend, + .bus_resume = ohci_bus_resume, +#endif + .start_port_reset = ohci_start_port_reset, +}; + + +static __devinit int jz4740_ohci_probe(struct platform_device *pdev) +{ + int ret; + struct usb_hcd *hcd; + struct jz4740_ohci_hcd *jz4740_ohci; + struct resource *res; + int irq; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (!res) { + dev_err(&pdev->dev, "Failed to get platform resource\n"); + return -ENOENT; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "Failed to get platform irq\n"); + return irq; + } + + hcd = usb_create_hcd(&ohci_jz4740_hc_driver, &pdev->dev, "jz4740"); + if (!hcd) { + dev_err(&pdev->dev, "Failed to create hcd.\n"); + return -ENOMEM; + } + + jz4740_ohci = hcd_to_jz4740_hcd(hcd); + + res = request_mem_region(res->start, resource_size(res), hcd_name); + if (!res) { + dev_err(&pdev->dev, "Failed to request mem region.\n"); + ret = -EBUSY; + goto err_free; + } + + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); + hcd->regs = ioremap(res->start, resource_size(res)); + + if (!hcd->regs) { + dev_err(&pdev->dev, "Failed to ioremap registers.\n"); + ret = -EBUSY; + goto err_release_mem; + } + + jz4740_ohci->clk = clk_get(&pdev->dev, "uhc"); + if (IS_ERR(jz4740_ohci->clk)) { + ret = PTR_ERR(jz4740_ohci->clk); + dev_err(&pdev->dev, "Failed to get clock: %d\n", ret); + goto err_iounmap; + } + + jz4740_ohci->vbus = regulator_get(&pdev->dev, "vbus"); + if (IS_ERR(jz4740_ohci->vbus)) + jz4740_ohci->vbus = NULL; + + + clk_set_rate(jz4740_ohci->clk, 48000000); + clk_enable(jz4740_ohci->clk); + if (jz4740_ohci->vbus) + ohci_jz4740_set_vbus_power(jz4740_ohci, true); + + platform_set_drvdata(pdev, hcd); + + ohci_hcd_init(hcd_to_ohci(hcd)); + + ret = usb_add_hcd(hcd, irq, 0); + if (ret) { + dev_err(&pdev->dev, "Failed to add hcd: %d\n", ret); + goto err_disable; + } + + return 0; + +err_disable: + platform_set_drvdata(pdev, NULL); + if (jz4740_ohci->vbus) { + regulator_disable(jz4740_ohci->vbus); + regulator_put(jz4740_ohci->vbus); + } + clk_disable(jz4740_ohci->clk); + + clk_put(jz4740_ohci->clk); +err_iounmap: + iounmap(hcd->regs); +err_release_mem: + release_mem_region(res->start, resource_size(res)); +err_free: + usb_put_hcd(hcd); + + return ret; +} + +static __devexit int jz4740_ohci_remove(struct platform_device *pdev) +{ + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd); + + usb_remove_hcd(hcd); + + platform_set_drvdata(pdev, NULL); + + if (jz4740_ohci->vbus) { + regulator_disable(jz4740_ohci->vbus); + regulator_put(jz4740_ohci->vbus); + } + + clk_disable(jz4740_ohci->clk); + clk_put(jz4740_ohci->clk); + + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + + usb_put_hcd(hcd); + + return 0; +} + +static struct platform_driver ohci_hcd_jz4740_driver = { + .probe = jz4740_ohci_probe, + .remove = __devexit_p(jz4740_ohci_remove), + .driver = { + .name = "jz4740-ohci", + .owner = THIS_MODULE, + }, +}; + +MODULE_ALIAS("platfrom:jz4740-ohci"); -- cgit v0.10.2 From 7f983ba93d449972d5f372f12c6ad32d86ef30b4 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 19 Jun 2010 18:32:58 +0000 Subject: HWMON: Add JZ4740 ADC driver Add support for reading the ADCIN pin of the ADC unit on JZ4740 SoCs. Signed-off-by: Lars-Peter Clausen Cc: lm-sensors@lm-sensors.org Acked-by: Jean Delvare Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1425/ Signed-off-by: Axel Lin Signed-off-by: Ralf Baechle diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index e19cf8e..c57e530 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -446,6 +446,16 @@ config SENSORS_IT87 This driver can also be built as a module. If so, the module will be called it87. +config SENSORS_JZ4740 + tristate "Ingenic JZ4740 SoC ADC driver" + depends on MACH_JZ4740 && MFD_JZ4740_ADC + help + If you say yes here you get support for reading adc values from the ADCIN + pin on Ingenic JZ4740 SoC based boards. + + This driver can also be build as a module. If so, the module will be + called jz4740-hwmon. + config SENSORS_LM63 tristate "National Semiconductor LM63 and LM64" depends on I2C diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 2138ceb..c505774 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o obj-$(CONFIG_SENSORS_IT87) += it87.o +obj-$(CONFIG_SENSORS_JZ4740) += jz4740-hwmon.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o obj-$(CONFIG_SENSORS_K10TEMP) += k10temp.o obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o diff --git a/drivers/hwmon/jz4740-hwmon.c b/drivers/hwmon/jz4740-hwmon.c new file mode 100644 index 0000000..1c8b3d9 --- /dev/null +++ b/drivers/hwmon/jz4740-hwmon.c @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * JZ4740 SoC HWMON driver + * + * 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. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +struct jz4740_hwmon { + struct resource *mem; + void __iomem *base; + + int irq; + + struct mfd_cell *cell; + struct device *hwmon; + + struct completion read_completion; + + struct mutex lock; +}; + +static ssize_t jz4740_hwmon_show_name(struct device *dev, + struct device_attribute *dev_attr, char *buf) +{ + return sprintf(buf, "jz4740\n"); +} + +static irqreturn_t jz4740_hwmon_irq(int irq, void *data) +{ + struct jz4740_hwmon *hwmon = data; + + complete(&hwmon->read_completion); + return IRQ_HANDLED; +} + +static ssize_t jz4740_hwmon_read_adcin(struct device *dev, + struct device_attribute *dev_attr, char *buf) +{ + struct jz4740_hwmon *hwmon = dev_get_drvdata(dev); + struct completion *completion = &hwmon->read_completion; + unsigned long t; + unsigned long val; + int ret; + + mutex_lock(&hwmon->lock); + + INIT_COMPLETION(*completion); + + enable_irq(hwmon->irq); + hwmon->cell->enable(to_platform_device(dev)); + + t = wait_for_completion_interruptible_timeout(completion, HZ); + + if (t > 0) { + val = readw(hwmon->base) & 0xfff; + val = (val * 3300) >> 12; + ret = sprintf(buf, "%lu\n", val); + } else { + ret = t ? t : -ETIMEDOUT; + } + + hwmon->cell->disable(to_platform_device(dev)); + disable_irq(hwmon->irq); + + mutex_unlock(&hwmon->lock); + + return ret; +} + +static DEVICE_ATTR(name, S_IRUGO, jz4740_hwmon_show_name, NULL); +static DEVICE_ATTR(in0_input, S_IRUGO, jz4740_hwmon_read_adcin, NULL); + +static struct attribute *jz4740_hwmon_attributes[] = { + &dev_attr_name.attr, + &dev_attr_in0_input.attr, + NULL +}; + +static const struct attribute_group jz4740_hwmon_attr_group = { + .attrs = jz4740_hwmon_attributes, +}; + +static int __devinit jz4740_hwmon_probe(struct platform_device *pdev) +{ + int ret; + struct jz4740_hwmon *hwmon; + + hwmon = kmalloc(sizeof(*hwmon), GFP_KERNEL); + if (!hwmon) { + dev_err(&pdev->dev, "Failed to allocate driver structure\n"); + return -ENOMEM; + } + + hwmon->cell = pdev->dev.platform_data; + + hwmon->irq = platform_get_irq(pdev, 0); + if (hwmon->irq < 0) { + ret = hwmon->irq; + dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret); + goto err_free; + } + + hwmon->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!hwmon->mem) { + ret = -ENOENT; + dev_err(&pdev->dev, "Failed to get platform mmio resource\n"); + goto err_free; + } + + hwmon->mem = request_mem_region(hwmon->mem->start, + resource_size(hwmon->mem), pdev->name); + if (!hwmon->mem) { + ret = -EBUSY; + dev_err(&pdev->dev, "Failed to request mmio memory region\n"); + goto err_free; + } + + hwmon->base = ioremap_nocache(hwmon->mem->start, + resource_size(hwmon->mem)); + if (!hwmon->base) { + ret = -EBUSY; + dev_err(&pdev->dev, "Failed to ioremap mmio memory\n"); + goto err_release_mem_region; + } + + init_completion(&hwmon->read_completion); + mutex_init(&hwmon->lock); + + platform_set_drvdata(pdev, hwmon); + + ret = request_irq(hwmon->irq, jz4740_hwmon_irq, 0, pdev->name, hwmon); + if (ret) { + dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); + goto err_iounmap; + } + disable_irq(hwmon->irq); + + ret = sysfs_create_group(&pdev->dev.kobj, &jz4740_hwmon_attr_group); + if (ret) { + dev_err(&pdev->dev, "Failed to create sysfs group: %d\n", ret); + goto err_free_irq; + } + + hwmon->hwmon = hwmon_device_register(&pdev->dev); + if (IS_ERR(hwmon->hwmon)) { + ret = PTR_ERR(hwmon->hwmon); + goto err_remove_file; + } + + return 0; + +err_remove_file: + sysfs_remove_group(&pdev->dev.kobj, &jz4740_hwmon_attr_group); +err_free_irq: + free_irq(hwmon->irq, hwmon); +err_iounmap: + platform_set_drvdata(pdev, NULL); + iounmap(hwmon->base); +err_release_mem_region: + release_mem_region(hwmon->mem->start, resource_size(hwmon->mem)); +err_free: + kfree(hwmon); + + return ret; +} + +static int __devexit jz4740_hwmon_remove(struct platform_device *pdev) +{ + struct jz4740_hwmon *hwmon = platform_get_drvdata(pdev); + + hwmon_device_unregister(hwmon->hwmon); + sysfs_remove_group(&pdev->dev.kobj, &jz4740_hwmon_attr_group); + + free_irq(hwmon->irq, hwmon); + + iounmap(hwmon->base); + release_mem_region(hwmon->mem->start, resource_size(hwmon->mem)); + + platform_set_drvdata(pdev, NULL); + kfree(hwmon); + + return 0; +} + +struct platform_driver jz4740_hwmon_driver = { + .probe = jz4740_hwmon_probe, + .remove = __devexit_p(jz4740_hwmon_remove), + .driver = { + .name = "jz4740-hwmon", + .owner = THIS_MODULE, + }, +}; + +static int __init jz4740_hwmon_init(void) +{ + return platform_driver_register(&jz4740_hwmon_driver); +} +module_init(jz4740_hwmon_init); + +static void __exit jz4740_hwmon_exit(void) +{ + platform_driver_unregister(&jz4740_hwmon_driver); +} +module_exit(jz4740_hwmon_exit); + +MODULE_DESCRIPTION("JZ4740 SoC HWMON driver"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:jz4740-hwmon"); -- cgit v0.10.2 From f6a21388bd255773cc80d4423afb4c69d4daa173 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 19 Jun 2010 04:08:29 +0000 Subject: POWER: Add JZ4740 battery driver. Add support for the battery voltage measurement part of the JZ4740 ADC unit. Signed-off-by: Lars-Peter Clausen Acked-by: Anton Vorontsov Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1416/ Signed-off-by: Ralf Baechle diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 8e9ba17..1e5506b 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -142,4 +142,15 @@ config CHARGER_PCF50633 help Say Y to include support for NXP PCF50633 Main Battery Charger. +config BATTERY_JZ4740 + tristate "Ingenic JZ4740 battery" + depends on MACH_JZ4740 + depends on MFD_JZ4740_ADC + help + Say Y to enable support for the battery on Ingenic JZ4740 based + boards. + + This driver can be build as a module. If so, the module will be + called jz4740-battery. + endif # POWER_SUPPLY diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 0005080..cf95009 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -34,3 +34,4 @@ obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o obj-$(CONFIG_BATTERY_Z2) += z2_battery.o obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o +obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o diff --git a/drivers/power/jz4740-battery.c b/drivers/power/jz4740-battery.c new file mode 100644 index 0000000..20c4b95 --- /dev/null +++ b/drivers/power/jz4740-battery.c @@ -0,0 +1,445 @@ +/* + * Battery measurement code for Ingenic JZ SOC. + * + * Copyright (C) 2009 Jiejing Zhang + * Copyright (C) 2010, Lars-Peter Clausen + * + * based on tosa_battery.c + * + * Copyright (C) 2008 Marek Vasut +* + * 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 +#include +#include +#include + +#include +#include + +struct jz_battery { + struct jz_battery_platform_data *pdata; + struct platform_device *pdev; + + struct resource *mem; + void __iomem *base; + + int irq; + int charge_irq; + + struct mfd_cell *cell; + + int status; + long voltage; + + struct completion read_completion; + + struct power_supply battery; + struct delayed_work work; +}; + +static inline struct jz_battery *psy_to_jz_battery(struct power_supply *psy) +{ + return container_of(psy, struct jz_battery, battery); +} + +static irqreturn_t jz_battery_irq_handler(int irq, void *devid) +{ + struct jz_battery *battery = devid; + + complete(&battery->read_completion); + return IRQ_HANDLED; +} + +static long jz_battery_read_voltage(struct jz_battery *battery) +{ + unsigned long t; + unsigned long val; + long voltage; + + INIT_COMPLETION(battery->read_completion); + + enable_irq(battery->irq); + battery->cell->enable(battery->pdev); + + t = wait_for_completion_interruptible_timeout(&battery->read_completion, + HZ); + + if (t > 0) { + val = readw(battery->base) & 0xfff; + + if (battery->pdata->info.voltage_max_design <= 2500000) + val = (val * 78125UL) >> 7UL; + else + val = ((val * 924375UL) >> 9UL) + 33000; + voltage = (long)val; + } else { + voltage = t ? t : -ETIMEDOUT; + } + + battery->cell->disable(battery->pdev); + disable_irq(battery->irq); + + return voltage; +} + +static int jz_battery_get_capacity(struct power_supply *psy) +{ + struct jz_battery *jz_battery = psy_to_jz_battery(psy); + struct power_supply_info *info = &jz_battery->pdata->info; + long voltage; + int ret; + int voltage_span; + + voltage = jz_battery_read_voltage(jz_battery); + + if (voltage < 0) + return voltage; + + voltage_span = info->voltage_max_design - info->voltage_min_design; + ret = ((voltage - info->voltage_min_design) * 100) / voltage_span; + + if (ret > 100) + ret = 100; + else if (ret < 0) + ret = 0; + + return ret; +} + +static int jz_battery_get_property(struct power_supply *psy, + enum power_supply_property psp, union power_supply_propval *val) +{ + struct jz_battery *jz_battery = psy_to_jz_battery(psy); + struct power_supply_info *info = &jz_battery->pdata->info; + long voltage; + + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + val->intval = jz_battery->status; + break; + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = jz_battery->pdata->info.technology; + break; + case POWER_SUPPLY_PROP_HEALTH: + voltage = jz_battery_read_voltage(jz_battery); + if (voltage < info->voltage_min_design) + val->intval = POWER_SUPPLY_HEALTH_DEAD; + else + val->intval = POWER_SUPPLY_HEALTH_GOOD; + break; + case POWER_SUPPLY_PROP_CAPACITY: + val->intval = jz_battery_get_capacity(psy); + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = jz_battery_read_voltage(jz_battery); + if (val->intval < 0) + return val->intval; + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + val->intval = info->voltage_max_design; + break; + case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: + val->intval = info->voltage_min_design; + break; + case POWER_SUPPLY_PROP_PRESENT: + val->intval = 1; + break; + default: + return -EINVAL; + } + return 0; +} + +static void jz_battery_external_power_changed(struct power_supply *psy) +{ + struct jz_battery *jz_battery = psy_to_jz_battery(psy); + + cancel_delayed_work(&jz_battery->work); + schedule_delayed_work(&jz_battery->work, 0); +} + +static irqreturn_t jz_battery_charge_irq(int irq, void *data) +{ + struct jz_battery *jz_battery = data; + + cancel_delayed_work(&jz_battery->work); + schedule_delayed_work(&jz_battery->work, 0); + + return IRQ_HANDLED; +} + +static void jz_battery_update(struct jz_battery *jz_battery) +{ + int status; + long voltage; + bool has_changed = false; + int is_charging; + + if (gpio_is_valid(jz_battery->pdata->gpio_charge)) { + is_charging = gpio_get_value(jz_battery->pdata->gpio_charge); + is_charging ^= jz_battery->pdata->gpio_charge_active_low; + if (is_charging) + status = POWER_SUPPLY_STATUS_CHARGING; + else + status = POWER_SUPPLY_STATUS_NOT_CHARGING; + + if (status != jz_battery->status) { + jz_battery->status = status; + has_changed = true; + } + } + + voltage = jz_battery_read_voltage(jz_battery); + if (abs(voltage - jz_battery->voltage) < 50000) { + jz_battery->voltage = voltage; + has_changed = true; + } + + if (has_changed) + power_supply_changed(&jz_battery->battery); +} + +static enum power_supply_property jz_battery_properties[] = { + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_HEALTH, + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, + POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, + POWER_SUPPLY_PROP_PRESENT, +}; + +static void jz_battery_work(struct work_struct *work) +{ + /* Too small interval will increase system workload */ + const int interval = HZ * 30; + struct jz_battery *jz_battery = container_of(work, struct jz_battery, + work.work); + + jz_battery_update(jz_battery); + schedule_delayed_work(&jz_battery->work, interval); +} + +static int __devinit jz_battery_probe(struct platform_device *pdev) +{ + int ret = 0; + struct jz_battery_platform_data *pdata = pdev->dev.parent->platform_data; + struct jz_battery *jz_battery; + struct power_supply *battery; + + jz_battery = kzalloc(sizeof(*jz_battery), GFP_KERNEL); + if (!jz_battery) { + dev_err(&pdev->dev, "Failed to allocate driver structure\n"); + return -ENOMEM; + } + + jz_battery->cell = pdev->dev.platform_data; + + jz_battery->irq = platform_get_irq(pdev, 0); + if (jz_battery->irq < 0) { + ret = jz_battery->irq; + dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret); + goto err_free; + } + + jz_battery->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!jz_battery->mem) { + ret = -ENOENT; + dev_err(&pdev->dev, "Failed to get platform mmio resource\n"); + goto err_free; + } + + jz_battery->mem = request_mem_region(jz_battery->mem->start, + resource_size(jz_battery->mem), pdev->name); + if (!jz_battery->mem) { + ret = -EBUSY; + dev_err(&pdev->dev, "Failed to request mmio memory region\n"); + goto err_free; + } + + jz_battery->base = ioremap_nocache(jz_battery->mem->start, + resource_size(jz_battery->mem)); + if (!jz_battery->base) { + ret = -EBUSY; + dev_err(&pdev->dev, "Failed to ioremap mmio memory\n"); + goto err_release_mem_region; + } + + battery = &jz_battery->battery; + battery->name = pdata->info.name; + battery->type = POWER_SUPPLY_TYPE_BATTERY; + battery->properties = jz_battery_properties; + battery->num_properties = ARRAY_SIZE(jz_battery_properties); + battery->get_property = jz_battery_get_property; + battery->external_power_changed = jz_battery_external_power_changed; + battery->use_for_apm = 1; + + jz_battery->pdata = pdata; + jz_battery->pdev = pdev; + + init_completion(&jz_battery->read_completion); + + INIT_DELAYED_WORK(&jz_battery->work, jz_battery_work); + + ret = request_irq(jz_battery->irq, jz_battery_irq_handler, 0, pdev->name, + jz_battery); + if (ret) { + dev_err(&pdev->dev, "Failed to request irq %d\n", ret); + goto err_iounmap; + } + disable_irq(jz_battery->irq); + + if (gpio_is_valid(pdata->gpio_charge)) { + ret = gpio_request(pdata->gpio_charge, dev_name(&pdev->dev)); + if (ret) { + dev_err(&pdev->dev, "charger state gpio request failed.\n"); + goto err_free_irq; + } + ret = gpio_direction_input(pdata->gpio_charge); + if (ret) { + dev_err(&pdev->dev, "charger state gpio set direction failed.\n"); + goto err_free_gpio; + } + + jz_battery->charge_irq = gpio_to_irq(pdata->gpio_charge); + + if (jz_battery->charge_irq >= 0) { + ret = request_irq(jz_battery->charge_irq, + jz_battery_charge_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + dev_name(&pdev->dev), jz_battery); + if (ret) { + dev_err(&pdev->dev, "Failed to request charge irq: %d\n", ret); + goto err_free_gpio; + } + } + } else { + jz_battery->charge_irq = -1; + } + + if (jz_battery->pdata->info.voltage_max_design <= 2500000) + jz4740_adc_set_config(pdev->dev.parent, JZ_ADC_CONFIG_BAT_MB, + JZ_ADC_CONFIG_BAT_MB); + else + jz4740_adc_set_config(pdev->dev.parent, JZ_ADC_CONFIG_BAT_MB, 0); + + ret = power_supply_register(&pdev->dev, &jz_battery->battery); + if (ret) { + dev_err(&pdev->dev, "power supply battery register failed.\n"); + goto err_free_charge_irq; + } + + platform_set_drvdata(pdev, jz_battery); + schedule_delayed_work(&jz_battery->work, 0); + + return 0; + +err_free_charge_irq: + if (jz_battery->charge_irq >= 0) + free_irq(jz_battery->charge_irq, jz_battery); +err_free_gpio: + if (gpio_is_valid(pdata->gpio_charge)) + gpio_free(jz_battery->pdata->gpio_charge); +err_free_irq: + free_irq(jz_battery->irq, jz_battery); +err_iounmap: + platform_set_drvdata(pdev, NULL); + iounmap(jz_battery->base); +err_release_mem_region: + release_mem_region(jz_battery->mem->start, resource_size(jz_battery->mem)); +err_free: + kfree(jz_battery); + return ret; +} + +static int __devexit jz_battery_remove(struct platform_device *pdev) +{ + struct jz_battery *jz_battery = platform_get_drvdata(pdev); + + cancel_delayed_work_sync(&jz_battery->work); + + if (gpio_is_valid(jz_battery->pdata->gpio_charge)) { + if (jz_battery->charge_irq >= 0) + free_irq(jz_battery->charge_irq, jz_battery); + gpio_free(jz_battery->pdata->gpio_charge); + } + + power_supply_unregister(&jz_battery->battery); + + free_irq(jz_battery->irq, jz_battery); + + iounmap(jz_battery->base); + release_mem_region(jz_battery->mem->start, resource_size(jz_battery->mem)); + + return 0; +} + +#ifdef CONFIG_PM +static int jz_battery_suspend(struct device *dev) +{ + struct jz_battery *jz_battery = dev_get_drvdata(dev); + + cancel_delayed_work_sync(&jz_battery->work); + jz_battery->status = POWER_SUPPLY_STATUS_UNKNOWN; + + return 0; +} + +static int jz_battery_resume(struct device *dev) +{ + struct jz_battery *jz_battery = dev_get_drvdata(dev); + + schedule_delayed_work(&jz_battery->work, 0); + + return 0; +} + +static const struct dev_pm_ops jz_battery_pm_ops = { + .suspend = jz_battery_suspend, + .resume = jz_battery_resume, +}; + +#define JZ_BATTERY_PM_OPS (&jz_battery_pm_ops) +#else +#define JZ_BATTERY_PM_OPS NULL +#endif + +static struct platform_driver jz_battery_driver = { + .probe = jz_battery_probe, + .remove = __devexit_p(jz_battery_remove), + .driver = { + .name = "jz4740-battery", + .owner = THIS_MODULE, + .pm = JZ_BATTERY_PM_OPS, + }, +}; + +static int __init jz_battery_init(void) +{ + return platform_driver_register(&jz_battery_driver); +} +module_init(jz_battery_init); + +static void __exit jz_battery_exit(void) +{ + platform_driver_unregister(&jz_battery_driver); +} +module_exit(jz_battery_exit); + +MODULE_ALIAS("platform:jz4740-battery"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("JZ4740 SoC battery driver"); diff --git a/include/linux/power/jz4740-battery.h b/include/linux/power/jz4740-battery.h new file mode 100644 index 0000000..19c9610 --- /dev/null +++ b/include/linux/power/jz4740-battery.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2009, Jiejing Zhang + * + * 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. + * + * 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 __JZ4740_BATTERY_H +#define __JZ4740_BATTERY_H + +struct jz_battery_platform_data { + struct power_supply_info info; + int gpio_charge; /* GPIO port of Charger state */ + int gpio_charge_active_low; +}; + +#endif -- cgit v0.10.2 From e6b78c4f224925c71cce57033b1e6e30dd56add7 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 17 Jul 2010 11:16:29 +0000 Subject: MIPS: JZ4740: Add qi_lb60 board support Add support for the qi_lb60 (a.k.a QI Ben NanoNote) clamshell device. Signed-off-by: Lars-Peter Clausen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1472/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig index 8a5e850..3e7141f 100644 --- a/arch/mips/jz4740/Kconfig +++ b/arch/mips/jz4740/Kconfig @@ -1,6 +1,10 @@ choice prompt "Machine type" depends on MACH_JZ4740 + default JZ4740_QI_LB60 + +config JZ4740_QI_LB60 + bool "Qi Hardware Ben NanoNote" endchoice diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile index a803ccb..a604eae 100644 --- a/arch/mips/jz4740/Makefile +++ b/arch/mips/jz4740/Makefile @@ -11,6 +11,8 @@ obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o # board specific support +obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o + # PM support obj-$(CONFIG_PM) += pm.o diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c new file mode 100644 index 0000000..5742bb4 --- /dev/null +++ b/arch/mips/jz4740/board-qi_lb60.c @@ -0,0 +1,471 @@ +/* + * linux/arch/mips/jz4740/board-qi_lb60.c + * + * QI_LB60 board support + * + * Copyright (c) 2009 Qi Hardware inc., + * Author: Xiangfu Liu + * Copyright 2010, Lars-Petrer Clausen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or later + * as published by the Free Software Foundation. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include + +#include "clock.h" + +static bool is_avt2; + +/* GPIOs */ +#define QI_LB60_GPIO_SD_CD JZ_GPIO_PORTD(0) +#define QI_LB60_GPIO_SD_VCC_EN_N JZ_GPIO_PORTD(2) + +#define QI_LB60_GPIO_KEYOUT(x) (JZ_GPIO_PORTC(10) + (x)) +#define QI_LB60_GPIO_KEYIN(x) (JZ_GPIO_PORTD(18) + (x)) +#define QI_LB60_GPIO_KEYIN8 JZ_GPIO_PORTD(26) + +/* NAND */ +static struct nand_ecclayout qi_lb60_ecclayout_1gb = { +/* .eccbytes = 36, + .eccpos = { + 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41 + },*/ + .oobfree = { + { .offset = 2, .length = 4 }, + { .offset = 42, .length = 22 } + }, +}; + +/* Early prototypes of the QI LB60 had only 1GB of NAND. + * In order to support these devices aswell the partition and ecc layout is + * initalized depending on the NAND size */ +static struct mtd_partition qi_lb60_partitions_1gb[] = { + { + .name = "NAND BOOT partition", + .offset = 0 * 0x100000, + .size = 4 * 0x100000, + }, + { + .name = "NAND KERNEL partition", + .offset = 4 * 0x100000, + .size = 4 * 0x100000, + }, + { + .name = "NAND ROOTFS partition", + .offset = 8 * 0x100000, + .size = (504 + 512) * 0x100000, + }, +}; + +static struct nand_ecclayout qi_lb60_ecclayout_2gb = { +/* .eccbytes = 72, + .eccpos = { + 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83 + },*/ + .oobfree = { + { .offset = 2, .length = 10 }, + { .offset = 84, .length = 44 }, + }, +}; + +static struct mtd_partition qi_lb60_partitions_2gb[] = { + { + .name = "NAND BOOT partition", + .offset = 0 * 0x100000, + .size = 4 * 0x100000, + }, + { + .name = "NAND KERNEL partition", + .offset = 4 * 0x100000, + .size = 4 * 0x100000, + }, + { + .name = "NAND ROOTFS partition", + .offset = 8 * 0x100000, + .size = (504 + 512 + 1024) * 0x100000, + }, +}; + +static void qi_lb60_nand_ident(struct platform_device *pdev, + struct nand_chip *chip, struct mtd_partition **partitions, + int *num_partitions) +{ + if (chip->page_shift == 12) { + chip->ecc.layout = &qi_lb60_ecclayout_2gb; + *partitions = qi_lb60_partitions_2gb; + *num_partitions = ARRAY_SIZE(qi_lb60_partitions_2gb); + } else { + chip->ecc.layout = &qi_lb60_ecclayout_1gb; + *partitions = qi_lb60_partitions_1gb; + *num_partitions = ARRAY_SIZE(qi_lb60_partitions_1gb); + } +} + +static struct jz_nand_platform_data qi_lb60_nand_pdata = { + .ident_callback = qi_lb60_nand_ident, + .busy_gpio = 94, +}; + +/* Keyboard*/ + +#define KEY_QI_QI KEY_F13 +#define KEY_QI_UPRED KEY_RIGHTALT +#define KEY_QI_VOLUP KEY_VOLUMEUP +#define KEY_QI_VOLDOWN KEY_VOLUMEDOWN +#define KEY_QI_FN KEY_LEFTCTRL + +static const uint32_t qi_lb60_keymap[] = { + KEY(0, 0, KEY_F1), /* S2 */ + KEY(0, 1, KEY_F2), /* S3 */ + KEY(0, 2, KEY_F3), /* S4 */ + KEY(0, 3, KEY_F4), /* S5 */ + KEY(0, 4, KEY_F5), /* S6 */ + KEY(0, 5, KEY_F6), /* S7 */ + KEY(0, 6, KEY_F7), /* S8 */ + + KEY(1, 0, KEY_Q), /* S10 */ + KEY(1, 1, KEY_W), /* S11 */ + KEY(1, 2, KEY_E), /* S12 */ + KEY(1, 3, KEY_R), /* S13 */ + KEY(1, 4, KEY_T), /* S14 */ + KEY(1, 5, KEY_Y), /* S15 */ + KEY(1, 6, KEY_U), /* S16 */ + KEY(1, 7, KEY_I), /* S17 */ + KEY(2, 0, KEY_A), /* S18 */ + KEY(2, 1, KEY_S), /* S19 */ + KEY(2, 2, KEY_D), /* S20 */ + KEY(2, 3, KEY_F), /* S21 */ + KEY(2, 4, KEY_G), /* S22 */ + KEY(2, 5, KEY_H), /* S23 */ + KEY(2, 6, KEY_J), /* S24 */ + KEY(2, 7, KEY_K), /* S25 */ + KEY(3, 0, KEY_ESC), /* S26 */ + KEY(3, 1, KEY_Z), /* S27 */ + KEY(3, 2, KEY_X), /* S28 */ + KEY(3, 3, KEY_C), /* S29 */ + KEY(3, 4, KEY_V), /* S30 */ + KEY(3, 5, KEY_B), /* S31 */ + KEY(3, 6, KEY_N), /* S32 */ + KEY(3, 7, KEY_M), /* S33 */ + KEY(4, 0, KEY_TAB), /* S34 */ + KEY(4, 1, KEY_CAPSLOCK), /* S35 */ + KEY(4, 2, KEY_BACKSLASH), /* S36 */ + KEY(4, 3, KEY_APOSTROPHE), /* S37 */ + KEY(4, 4, KEY_COMMA), /* S38 */ + KEY(4, 5, KEY_DOT), /* S39 */ + KEY(4, 6, KEY_SLASH), /* S40 */ + KEY(4, 7, KEY_UP), /* S41 */ + KEY(5, 0, KEY_O), /* S42 */ + KEY(5, 1, KEY_L), /* S43 */ + KEY(5, 2, KEY_EQUAL), /* S44 */ + KEY(5, 3, KEY_QI_UPRED), /* S45 */ + KEY(5, 4, KEY_SPACE), /* S46 */ + KEY(5, 5, KEY_QI_QI), /* S47 */ + KEY(5, 6, KEY_RIGHTCTRL), /* S48 */ + KEY(5, 7, KEY_LEFT), /* S49 */ + KEY(6, 0, KEY_F8), /* S50 */ + KEY(6, 1, KEY_P), /* S51 */ + KEY(6, 2, KEY_BACKSPACE),/* S52 */ + KEY(6, 3, KEY_ENTER), /* S53 */ + KEY(6, 4, KEY_QI_VOLUP), /* S54 */ + KEY(6, 5, KEY_QI_VOLDOWN), /* S55 */ + KEY(6, 6, KEY_DOWN), /* S56 */ + KEY(6, 7, KEY_RIGHT), /* S57 */ + + KEY(7, 0, KEY_LEFTSHIFT), /* S58 */ + KEY(7, 1, KEY_LEFTALT), /* S59 */ + KEY(7, 2, KEY_QI_FN), /* S60 */ +}; + +static const struct matrix_keymap_data qi_lb60_keymap_data = { + .keymap = qi_lb60_keymap, + .keymap_size = ARRAY_SIZE(qi_lb60_keymap), +}; + +static const unsigned int qi_lb60_keypad_cols[] = { + QI_LB60_GPIO_KEYOUT(0), + QI_LB60_GPIO_KEYOUT(1), + QI_LB60_GPIO_KEYOUT(2), + QI_LB60_GPIO_KEYOUT(3), + QI_LB60_GPIO_KEYOUT(4), + QI_LB60_GPIO_KEYOUT(5), + QI_LB60_GPIO_KEYOUT(6), + QI_LB60_GPIO_KEYOUT(7), +}; + +static const unsigned int qi_lb60_keypad_rows[] = { + QI_LB60_GPIO_KEYIN(0), + QI_LB60_GPIO_KEYIN(1), + QI_LB60_GPIO_KEYIN(2), + QI_LB60_GPIO_KEYIN(3), + QI_LB60_GPIO_KEYIN(4), + QI_LB60_GPIO_KEYIN(5), + QI_LB60_GPIO_KEYIN(7), + QI_LB60_GPIO_KEYIN8, +}; + +static struct matrix_keypad_platform_data qi_lb60_pdata = { + .keymap_data = &qi_lb60_keymap_data, + .col_gpios = qi_lb60_keypad_cols, + .row_gpios = qi_lb60_keypad_rows, + .num_col_gpios = ARRAY_SIZE(qi_lb60_keypad_cols), + .num_row_gpios = ARRAY_SIZE(qi_lb60_keypad_rows), + .col_scan_delay_us = 10, + .debounce_ms = 10, + .wakeup = 1, + .active_low = 1, +}; + +static struct platform_device qi_lb60_keypad = { + .name = "matrix-keypad", + .id = -1, + .dev = { + .platform_data = &qi_lb60_pdata, + }, +}; + +/* Display */ +static struct fb_videomode qi_lb60_video_modes[] = { + { + .name = "320x240", + .xres = 320, + .yres = 240, + .refresh = 30, + .left_margin = 140, + .right_margin = 273, + .upper_margin = 20, + .lower_margin = 2, + .hsync_len = 1, + .vsync_len = 1, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, +}; + +static struct jz4740_fb_platform_data qi_lb60_fb_pdata = { + .width = 60, + .height = 45, + .num_modes = ARRAY_SIZE(qi_lb60_video_modes), + .modes = qi_lb60_video_modes, + .bpp = 24, + .lcd_type = JZ_LCD_TYPE_8BIT_SERIAL, + .pixclk_falling_edge = 1, +}; + +struct spi_gpio_platform_data spigpio_platform_data = { + .sck = JZ_GPIO_PORTC(23), + .mosi = JZ_GPIO_PORTC(22), + .miso = -1, + .num_chipselect = 1, +}; + +static struct platform_device spigpio_device = { + .name = "spi_gpio", + .id = 1, + .dev = { + .platform_data = &spigpio_platform_data, + }, +}; + +static struct spi_board_info qi_lb60_spi_board_info[] = { + { + .modalias = "ili8960", + .controller_data = (void *)JZ_GPIO_PORTC(21), + .chip_select = 0, + .bus_num = 1, + .max_speed_hz = 30 * 1000, + .mode = SPI_3WIRE, + }, +}; + +/* Battery */ +static struct jz_battery_platform_data qi_lb60_battery_pdata = { + .gpio_charge = JZ_GPIO_PORTC(27), + .gpio_charge_active_low = 1, + .info = { + .name = "battery", + .technology = POWER_SUPPLY_TECHNOLOGY_LIPO, + .voltage_max_design = 4200000, + .voltage_min_design = 3600000, + }, +}; + +/* GPIO Key: power */ +static struct gpio_keys_button qi_lb60_gpio_keys_buttons[] = { + [0] = { + .code = KEY_POWER, + .gpio = JZ_GPIO_PORTD(29), + .active_low = 1, + .desc = "Power", + .wakeup = 1, + }, +}; + +static struct gpio_keys_platform_data qi_lb60_gpio_keys_data = { + .nbuttons = ARRAY_SIZE(qi_lb60_gpio_keys_buttons), + .buttons = qi_lb60_gpio_keys_buttons, +}; + +static struct platform_device qi_lb60_gpio_keys = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &qi_lb60_gpio_keys_data, + } +}; + +static struct jz4740_mmc_platform_data qi_lb60_mmc_pdata = { + .gpio_card_detect = QI_LB60_GPIO_SD_CD, + .gpio_read_only = -1, + .gpio_power = QI_LB60_GPIO_SD_VCC_EN_N, + .power_active_low = 1, +}; + +/* OHCI */ +static struct regulator_consumer_supply avt2_usb_regulator_consumer = + REGULATOR_SUPPLY("vbus", "jz4740-ohci"); + +static struct regulator_init_data avt2_usb_regulator_init_data = { + .num_consumer_supplies = 1, + .consumer_supplies = &avt2_usb_regulator_consumer, + .constraints = { + .name = "USB power", + .min_uV = 5000000, + .max_uV = 5000000, + .valid_modes_mask = REGULATOR_MODE_NORMAL, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, +}; + +static struct fixed_voltage_config avt2_usb_regulator_data = { + .supply_name = "USB power", + .microvolts = 5000000, + .gpio = JZ_GPIO_PORTB(17), + .init_data = &avt2_usb_regulator_init_data, +}; + +static struct platform_device avt2_usb_regulator_device = { + .name = "reg-fixed-voltage", + .id = -1, + .dev = { + .platform_data = &avt2_usb_regulator_data, + } +}; + +/* beeper */ +static struct platform_device qi_lb60_pwm_beeper = { + .name = "pwm-beeper", + .id = -1, + .dev = { + .platform_data = (void *)4, + }, +}; + +static struct platform_device *jz_platform_devices[] __initdata = { + &jz4740_udc_device, + &jz4740_mmc_device, + &jz4740_nand_device, + &qi_lb60_keypad, + &spigpio_device, + &jz4740_framebuffer_device, + &jz4740_pcm_device, + &jz4740_i2s_device, + &jz4740_codec_device, + &jz4740_rtc_device, + &jz4740_adc_device, + &qi_lb60_gpio_keys, + &qi_lb60_pwm_beeper, +}; + +static void __init board_gpio_setup(void) +{ + /* We only need to enable/disable pullup here for pins used in generic + * drivers. Everything else is done by the drivers themselfs. */ + jz_gpio_disable_pullup(QI_LB60_GPIO_SD_VCC_EN_N); + jz_gpio_disable_pullup(QI_LB60_GPIO_SD_CD); +} + +static int __init qi_lb60_init_platform_devices(void) +{ + jz4740_framebuffer_device.dev.platform_data = &qi_lb60_fb_pdata; + jz4740_nand_device.dev.platform_data = &qi_lb60_nand_pdata; + jz4740_adc_device.dev.platform_data = &qi_lb60_battery_pdata; + jz4740_mmc_device.dev.platform_data = &qi_lb60_mmc_pdata; + + jz4740_serial_device_register(); + + spi_register_board_info(qi_lb60_spi_board_info, + ARRAY_SIZE(qi_lb60_spi_board_info)); + + if (is_avt2) { + platform_device_register(&avt2_usb_regulator_device); + platform_device_register(&jz4740_usb_ohci_device); + } + + return platform_add_devices(jz_platform_devices, + ARRAY_SIZE(jz_platform_devices)); + +} + +struct jz4740_clock_board_data jz4740_clock_bdata = { + .ext_rate = 12000000, + .rtc_rate = 32768, +}; + +static __init int board_avt2(char *str) +{ + qi_lb60_mmc_pdata.card_detect_active_low = 1; + is_avt2 = true; + + return 1; +} +__setup("avt2", board_avt2); + +static int __init qi_lb60_board_setup(void) +{ + printk(KERN_INFO "Qi Hardware JZ4740 QI %s setup\n", + is_avt2 ? "AVT2" : "LB60"); + + board_gpio_setup(); + + if (qi_lb60_init_platform_devices()) + panic("Failed to initalize platform devices\n"); + + return 0; +} +arch_initcall(qi_lb60_board_setup); -- cgit v0.10.2 From ca148125e6134de334b61822539d220794d8da18 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 1 Jun 2010 13:18:15 -0700 Subject: MIPS: Octeon: Implement delays with cycle counter. Power throttling make deterministic delay loops impossible. Re-implement delays using the cycle counter. This also allows us to get rid of the code that calculates loops per jiffy. Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1317/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/cavium-octeon/csrc-octeon.c b/arch/mips/cavium-octeon/csrc-octeon.c index 36400d2..b6847c8 100644 --- a/arch/mips/cavium-octeon/csrc-octeon.c +++ b/arch/mips/cavium-octeon/csrc-octeon.c @@ -80,3 +80,58 @@ void __init plat_time_init(void) clocksource_set_clock(&clocksource_mips, mips_hpt_frequency); clocksource_register(&clocksource_mips); } + +static u64 octeon_udelay_factor; +static u64 octeon_ndelay_factor; + +void __init octeon_setup_delays(void) +{ + octeon_udelay_factor = octeon_get_clock_rate() / 1000000; + /* + * For __ndelay we divide by 2^16, so the factor is multiplied + * by the same amount. + */ + octeon_ndelay_factor = (octeon_udelay_factor * 0x10000ull) / 1000ull; + + preset_lpj = octeon_get_clock_rate() / HZ; +} + +void __udelay(unsigned long us) +{ + u64 cur, end, inc; + + cur = read_c0_cvmcount(); + + inc = us * octeon_udelay_factor; + end = cur + inc; + + while (end > cur) + cur = read_c0_cvmcount(); +} +EXPORT_SYMBOL(__udelay); + +void __ndelay(unsigned long ns) +{ + u64 cur, end, inc; + + cur = read_c0_cvmcount(); + + inc = ((ns * octeon_ndelay_factor) >> 16); + end = cur + inc; + + while (end > cur) + cur = read_c0_cvmcount(); +} +EXPORT_SYMBOL(__ndelay); + +void __delay(unsigned long loops) +{ + u64 cur, end; + + cur = read_c0_cvmcount(); + end = cur + loops; + + while (end > cur) + cur = read_c0_cvmcount(); +} +EXPORT_SYMBOL(__delay); diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 8c81a5c..7216fbd 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -594,13 +594,13 @@ void __init prom_init(void) * the filesystem. Also specify the calibration delay * to avoid calculating it every time. */ - strcat(arcs_cmdline, " rw root=1f00" - " lpj=60176 slram=root,0x40000000,+1073741824"); + strcat(arcs_cmdline, " rw root=1f00 slram=root,0x40000000,+1073741824"); } mips_hpt_frequency = octeon_get_clock_rate(); octeon_init_cvmcount(); + octeon_setup_delays(); _machine_restart = octeon_restart; _machine_halt = octeon_halt; diff --git a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h index 2a7ea90..b952fc7 100644 --- a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h @@ -61,22 +61,11 @@ #define kernel_uses_smartmips_rixi (cpu_data[0].cputype == CPU_CAVIUM_OCTEON_PLUS) -#define ARCH_HAS_READ_CURRENT_TIMER 1 #define ARCH_HAS_IRQ_PER_CPU 1 #define ARCH_HAS_SPINLOCK_PREFETCH 1 #define spin_lock_prefetch(x) prefetch(x) #define PREFETCH_STRIDE 128 -static inline int read_current_timer(unsigned long *result) -{ - asm volatile ("rdhwr %0,$31\n" -#ifndef CONFIG_64BIT - "\tsll %0, 0" -#endif - : "=r" (*result)); - return 0; -} - #ifdef __OCTEON__ /* * All gcc versions that have OCTEON support define __OCTEON__ and have the diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h index c29debe..917a6c4 100644 --- a/arch/mips/include/asm/octeon/octeon.h +++ b/arch/mips/include/asm/octeon/octeon.h @@ -50,6 +50,7 @@ extern void octeon_crypto_disable(struct octeon_cop2_state *state, extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task); extern void octeon_init_cvmcount(void); +extern void octeon_setup_delays(void); #define OCTEON_ARGV_MAX_ARGS 64 #define OCTOEN_SERIAL_LEN 20 -- cgit v0.10.2 From de6d5b555c1887b5b9b59854a45ebd4805fb4b39 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 23 Jul 2010 18:41:41 -0700 Subject: MIPS: uasm: Add drotr32 and uasm_i_drotr_safe. Signed-off-by: David Daney To: linux-mips@linux-mips.org To: wim@iguana.be Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1495/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 697e40c..3964b2e 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -71,6 +71,7 @@ Ip_u2u1u3(_dsra); Ip_u2u1u3(_dsrl); Ip_u2u1u3(_dsrl32); Ip_u2u1u3(_drotr); +Ip_u2u1u3(_drotr32); Ip_u3u1u2(_dsubu); Ip_0(_eret); Ip_u1(_j); @@ -176,6 +177,15 @@ static inline void uasm_i_dsrl_safe(u32 **p, unsigned int a1, uasm_i_dsrl32(p, a1, a2, a3 - 32); } +static inline void uasm_i_drotr_safe(u32 **p, unsigned int a1, + unsigned int a2, unsigned int a3) +{ + if (a3 < 32) + uasm_i_drotr(p, a1, a2, a3); + else + uasm_i_drotr32(p, a1, a2, a3 - 32); +} + static inline void uasm_i_dsll_safe(u32 **p, unsigned int a1, unsigned int a2, unsigned int a3) { diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 611d564..fe041d5 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -62,11 +62,12 @@ enum opcode { insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, insn_bne, insn_cache, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0, insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, - insn_dsrl32, insn_drotr, insn_dsubu, insn_eret, insn_j, insn_jal, - insn_jr, insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, - insn_mtc0, insn_or, insn_ori, insn_pref, insn_rfe, insn_sc, insn_scd, - insn_sd, insn_sll, insn_sra, insn_srl, insn_rotr, insn_subu, insn_sw, - insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori, + insn_dsrl32, insn_drotr, insn_drotr32, insn_dsubu, insn_eret, + insn_j, insn_jal, insn_jr, insn_ld, insn_ll, insn_lld, + insn_lui, insn_lw, insn_mfc0, insn_mtc0, insn_or, insn_ori, + insn_pref, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll, + insn_sra, insn_srl, insn_rotr, insn_subu, insn_sw, insn_tlbp, + insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori, insn_dins, insn_syscall }; @@ -108,6 +109,7 @@ static struct insn insn_table[] __cpuinitdata = { { insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE }, { insn_dsrl32, M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE }, { insn_drotr, M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE }, + { insn_drotr32, M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE }, { insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD }, { insn_eret, M(cop0_op, cop_op, 0, 0, 0, eret_op), 0 }, { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM }, @@ -375,6 +377,7 @@ I_u2u1u3(_dsra) I_u2u1u3(_dsrl) I_u2u1u3(_dsrl32) I_u2u1u3(_drotr) +I_u2u1u3(_drotr32) I_u3u1u2(_dsubu) I_0(_eret) I_u1(_j) -- cgit v0.10.2 From 5b97c3f7ae0ad0eea1eb90d649420a1a180f2bdf Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 23 Jul 2010 18:41:42 -0700 Subject: MIPS: uasm: Add BBIT0 and BBIT1 instructions These are OCTEON specific instructions. Signed-off-by: David Daney To: linux-mips@linux-mips.org To: wim@iguana.be Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1496/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 3964b2e..db9d449 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -223,3 +223,7 @@ void uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1, void uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); void uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); void uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); +void uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg, + unsigned int bit, int lid); +void uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg, + unsigned int bit, int lid); diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index fe041d5..636b817 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -68,7 +68,7 @@ enum opcode { insn_pref, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll, insn_sra, insn_srl, insn_rotr, insn_subu, insn_sw, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori, - insn_dins, insn_syscall + insn_dins, insn_syscall, insn_bbit0, insn_bbit1 }; struct insn { @@ -143,6 +143,8 @@ static struct insn insn_table[] __cpuinitdata = { { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, { insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE }, { insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM}, + { insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, + { insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, { insn_invalid, 0, 0 } }; @@ -411,6 +413,8 @@ I_u3u1u2(_xor) I_u2u1u3(_xori) I_u2u1msbu3(_dins); I_u1(_syscall); +I_u1u2s3(_bbit0); +I_u1u2s3(_bbit1); /* Handle labels. */ void __cpuinit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid) @@ -620,3 +624,19 @@ uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) uasm_r_mips_pc16(r, *p, lid); uasm_i_bgez(p, reg, 0); } + +void __cpuinit +uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg, + unsigned int bit, int lid) +{ + uasm_r_mips_pc16(r, *p, lid); + uasm_i_bbit0(p, reg, bit, 0); +} + +void __cpuinit +uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg, + unsigned int bit, int lid) +{ + uasm_r_mips_pc16(r, *p, lid); + uasm_i_bbit1(p, reg, bit, 0); +} -- cgit v0.10.2 From 22b0763a2328434ac68cca884e1b7d350ca61332 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 23 Jul 2010 18:41:43 -0700 Subject: MIPS: uasm: Add option to export uasm API. A 'select EXPORT_UASM' in Kconfig will cause the uasm to be exported for use in modules. When it is exported, all the uasm data and code cease to be __init and __initdata. Also daddiu_bug cannot be __cpuinitdata if uasm is exported. The cleanest thing is to just make it normal data. Signed-off-by: David Daney To: linux-mips@linux-mips.org To: wim@iguana.be Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1500/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 295e8c5..aaca439 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -915,6 +915,9 @@ config CPU_LITTLE_ENDIAN endchoice +config EXPORT_UASM + bool + config SYS_SUPPORTS_APM_EMULATION bool diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index db9d449..892062d 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -10,44 +10,55 @@ #include +#ifdef CONFIG_EXPORT_UASM +#include +#define __uasminit +#define __uasminitdata +#define UASM_EXPORT_SYMBOL(sym) EXPORT_SYMBOL(sym) +#else +#define __uasminit __cpuinit +#define __uasminitdata __cpuinitdata +#define UASM_EXPORT_SYMBOL(sym) +#endif + #define Ip_u1u2u3(op) \ -void __cpuinit \ +void __uasminit \ uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u2u1u3(op) \ -void __cpuinit \ +void __uasminit \ uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u3u1u2(op) \ -void __cpuinit \ +void __uasminit \ uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u1u2s3(op) \ -void __cpuinit \ +void __uasminit \ uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c) #define Ip_u2s3u1(op) \ -void __cpuinit \ +void __uasminit \ uasm_i##op(u32 **buf, unsigned int a, signed int b, unsigned int c) #define Ip_u2u1s3(op) \ -void __cpuinit \ +void __uasminit \ uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c) #define Ip_u2u1msbu3(op) \ -void __cpuinit \ +void __uasminit \ uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c, \ unsigned int d) #define Ip_u1u2(op) \ -void __cpuinit uasm_i##op(u32 **buf, unsigned int a, unsigned int b) +void __uasminit uasm_i##op(u32 **buf, unsigned int a, unsigned int b) #define Ip_u1s2(op) \ -void __cpuinit uasm_i##op(u32 **buf, unsigned int a, signed int b) +void __uasminit uasm_i##op(u32 **buf, unsigned int a, signed int b) -#define Ip_u1(op) void __cpuinit uasm_i##op(u32 **buf, unsigned int a) +#define Ip_u1(op) void __uasminit uasm_i##op(u32 **buf, unsigned int a) -#define Ip_0(op) void __cpuinit uasm_i##op(u32 **buf) +#define Ip_0(op) void __uasminit uasm_i##op(u32 **buf) Ip_u2u1s3(_addiu); Ip_u3u1u2(_addu); @@ -112,7 +123,7 @@ struct uasm_label { int lab; }; -void __cpuinit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid); +void __uasminit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid); #ifdef CONFIG_64BIT int uasm_in_compat_space_p(long addr); #endif @@ -122,7 +133,7 @@ void UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr); void UASM_i_LA(u32 **buf, unsigned int rs, long addr); #define UASM_L_LA(lb) \ -static inline void __cpuinit uasm_l##lb(struct uasm_label **lab, u32 *addr) \ +static inline void __uasminit uasm_l##lb(struct uasm_label **lab, u32 *addr) \ { \ uasm_build_label(lab, addr, label##lb); \ } diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c index 408d0a0..b8bb8ba 100644 --- a/arch/mips/kernel/cpu-bugs64.c +++ b/arch/mips/kernel/cpu-bugs64.c @@ -239,7 +239,7 @@ static inline void check_daddi(void) panic(bug64hit, !DADDI_WAR ? daddiwar : nowar); } -int daddiu_bug __cpuinitdata = -1; +int daddiu_bug = -1; static inline void check_daddiu(void) { diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 636b817..d2647a4 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -86,7 +86,7 @@ struct insn { | (e) << RE_SH \ | (f) << FUNC_SH) -static struct insn insn_table[] __cpuinitdata = { +static struct insn insn_table[] __uasminitdata = { { insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD }, { insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD }, @@ -150,7 +150,7 @@ static struct insn insn_table[] __cpuinitdata = { #undef M -static inline __cpuinit u32 build_rs(u32 arg) +static inline __uasminit u32 build_rs(u32 arg) { if (arg & ~RS_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -158,7 +158,7 @@ static inline __cpuinit u32 build_rs(u32 arg) return (arg & RS_MASK) << RS_SH; } -static inline __cpuinit u32 build_rt(u32 arg) +static inline __uasminit u32 build_rt(u32 arg) { if (arg & ~RT_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -166,7 +166,7 @@ static inline __cpuinit u32 build_rt(u32 arg) return (arg & RT_MASK) << RT_SH; } -static inline __cpuinit u32 build_rd(u32 arg) +static inline __uasminit u32 build_rd(u32 arg) { if (arg & ~RD_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -174,7 +174,7 @@ static inline __cpuinit u32 build_rd(u32 arg) return (arg & RD_MASK) << RD_SH; } -static inline __cpuinit u32 build_re(u32 arg) +static inline __uasminit u32 build_re(u32 arg) { if (arg & ~RE_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -182,7 +182,7 @@ static inline __cpuinit u32 build_re(u32 arg) return (arg & RE_MASK) << RE_SH; } -static inline __cpuinit u32 build_simm(s32 arg) +static inline __uasminit u32 build_simm(s32 arg) { if (arg > 0x7fff || arg < -0x8000) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -190,7 +190,7 @@ static inline __cpuinit u32 build_simm(s32 arg) return arg & 0xffff; } -static inline __cpuinit u32 build_uimm(u32 arg) +static inline __uasminit u32 build_uimm(u32 arg) { if (arg & ~IMM_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -198,7 +198,7 @@ static inline __cpuinit u32 build_uimm(u32 arg) return arg & IMM_MASK; } -static inline __cpuinit u32 build_bimm(s32 arg) +static inline __uasminit u32 build_bimm(s32 arg) { if (arg > 0x1ffff || arg < -0x20000) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -209,7 +209,7 @@ static inline __cpuinit u32 build_bimm(s32 arg) return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff); } -static inline __cpuinit u32 build_jimm(u32 arg) +static inline __uasminit u32 build_jimm(u32 arg) { if (arg & ~((JIMM_MASK) << 2)) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -217,7 +217,7 @@ static inline __cpuinit u32 build_jimm(u32 arg) return (arg >> 2) & JIMM_MASK; } -static inline __cpuinit u32 build_scimm(u32 arg) +static inline __uasminit u32 build_scimm(u32 arg) { if (arg & ~SCIMM_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -225,7 +225,7 @@ static inline __cpuinit u32 build_scimm(u32 arg) return (arg & SCIMM_MASK) << SCIMM_SH; } -static inline __cpuinit u32 build_func(u32 arg) +static inline __uasminit u32 build_func(u32 arg) { if (arg & ~FUNC_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -233,7 +233,7 @@ static inline __cpuinit u32 build_func(u32 arg) return arg & FUNC_MASK; } -static inline __cpuinit u32 build_set(u32 arg) +static inline __uasminit u32 build_set(u32 arg) { if (arg & ~SET_MASK) printk(KERN_WARNING "Micro-assembler field overflow\n"); @@ -245,7 +245,7 @@ static inline __cpuinit u32 build_set(u32 arg) * The order of opcode arguments is implicitly left to right, * starting with RS and ending with FUNC or IMM. */ -static void __cpuinit build_insn(u32 **buf, enum opcode opc, ...) +static void __uasminit build_insn(u32 **buf, enum opcode opc, ...) { struct insn *ip = NULL; unsigned int i; @@ -295,67 +295,78 @@ static void __cpuinit build_insn(u32 **buf, enum opcode opc, ...) Ip_u1u2u3(op) \ { \ build_insn(buf, insn##op, a, b, c); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_u2u1u3(op) \ Ip_u2u1u3(op) \ { \ build_insn(buf, insn##op, b, a, c); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_u3u1u2(op) \ Ip_u3u1u2(op) \ { \ build_insn(buf, insn##op, b, c, a); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_u1u2s3(op) \ Ip_u1u2s3(op) \ { \ build_insn(buf, insn##op, a, b, c); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_u2s3u1(op) \ Ip_u2s3u1(op) \ { \ build_insn(buf, insn##op, c, a, b); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_u2u1s3(op) \ Ip_u2u1s3(op) \ { \ build_insn(buf, insn##op, b, a, c); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_u2u1msbu3(op) \ Ip_u2u1msbu3(op) \ { \ build_insn(buf, insn##op, b, a, c+d-1, c); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_u1u2(op) \ Ip_u1u2(op) \ { \ build_insn(buf, insn##op, a, b); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_u1s2(op) \ Ip_u1s2(op) \ { \ build_insn(buf, insn##op, a, b); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_u1(op) \ Ip_u1(op) \ { \ build_insn(buf, insn##op, a); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); #define I_0(op) \ Ip_0(op) \ { \ build_insn(buf, insn##op); \ -} +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); I_u2u1s3(_addiu) I_u3u1u2(_addu) @@ -417,14 +428,15 @@ I_u1u2s3(_bbit0); I_u1u2s3(_bbit1); /* Handle labels. */ -void __cpuinit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid) +void __uasminit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid) { (*lab)->addr = addr; (*lab)->lab = lid; (*lab)++; } +UASM_EXPORT_SYMBOL(uasm_build_label); -int __cpuinit uasm_in_compat_space_p(long addr) +int __uasminit uasm_in_compat_space_p(long addr) { /* Is this address in 32bit compat space? */ #ifdef CONFIG_64BIT @@ -433,8 +445,9 @@ int __cpuinit uasm_in_compat_space_p(long addr) return 1; #endif } +UASM_EXPORT_SYMBOL(uasm_in_compat_space_p); -static int __cpuinit uasm_rel_highest(long val) +static int __uasminit uasm_rel_highest(long val) { #ifdef CONFIG_64BIT return ((((val + 0x800080008000L) >> 48) & 0xffff) ^ 0x8000) - 0x8000; @@ -443,7 +456,7 @@ static int __cpuinit uasm_rel_highest(long val) #endif } -static int __cpuinit uasm_rel_higher(long val) +static int __uasminit uasm_rel_higher(long val) { #ifdef CONFIG_64BIT return ((((val + 0x80008000L) >> 32) & 0xffff) ^ 0x8000) - 0x8000; @@ -452,17 +465,19 @@ static int __cpuinit uasm_rel_higher(long val) #endif } -int __cpuinit uasm_rel_hi(long val) +int __uasminit uasm_rel_hi(long val) { return ((((val + 0x8000L) >> 16) & 0xffff) ^ 0x8000) - 0x8000; } +UASM_EXPORT_SYMBOL(uasm_rel_hi); -int __cpuinit uasm_rel_lo(long val) +int __uasminit uasm_rel_lo(long val) { return ((val & 0xffff) ^ 0x8000) - 0x8000; } +UASM_EXPORT_SYMBOL(uasm_rel_lo); -void __cpuinit UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr) +void __uasminit UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr) { if (!uasm_in_compat_space_p(addr)) { uasm_i_lui(buf, rs, uasm_rel_highest(addr)); @@ -477,8 +492,9 @@ void __cpuinit UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr) } else uasm_i_lui(buf, rs, uasm_rel_hi(addr)); } +UASM_EXPORT_SYMBOL(UASM_i_LA_mostly); -void __cpuinit UASM_i_LA(u32 **buf, unsigned int rs, long addr) +void __uasminit UASM_i_LA(u32 **buf, unsigned int rs, long addr) { UASM_i_LA_mostly(buf, rs, addr); if (uasm_rel_lo(addr)) { @@ -488,9 +504,10 @@ void __cpuinit UASM_i_LA(u32 **buf, unsigned int rs, long addr) uasm_i_addiu(buf, rs, rs, uasm_rel_lo(addr)); } } +UASM_EXPORT_SYMBOL(UASM_i_LA); /* Handle relocations. */ -void __cpuinit +void __uasminit uasm_r_mips_pc16(struct uasm_reloc **rel, u32 *addr, int lid) { (*rel)->addr = addr; @@ -498,8 +515,9 @@ uasm_r_mips_pc16(struct uasm_reloc **rel, u32 *addr, int lid) (*rel)->lab = lid; (*rel)++; } +UASM_EXPORT_SYMBOL(uasm_r_mips_pc16); -static inline void __cpuinit +static inline void __uasminit __resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) { long laddr = (long)lab->addr; @@ -516,7 +534,7 @@ __resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) } } -void __cpuinit +void __uasminit uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) { struct uasm_label *l; @@ -526,24 +544,27 @@ uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) if (rel->lab == l->lab) __resolve_relocs(rel, l); } +UASM_EXPORT_SYMBOL(uasm_resolve_relocs); -void __cpuinit +void __uasminit uasm_move_relocs(struct uasm_reloc *rel, u32 *first, u32 *end, long off) { for (; rel->lab != UASM_LABEL_INVALID; rel++) if (rel->addr >= first && rel->addr < end) rel->addr += off; } +UASM_EXPORT_SYMBOL(uasm_move_relocs); -void __cpuinit +void __uasminit uasm_move_labels(struct uasm_label *lab, u32 *first, u32 *end, long off) { for (; lab->lab != UASM_LABEL_INVALID; lab++) if (lab->addr >= first && lab->addr < end) lab->addr += off; } +UASM_EXPORT_SYMBOL(uasm_move_labels); -void __cpuinit +void __uasminit uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab, u32 *first, u32 *end, u32 *target) { @@ -554,8 +575,9 @@ uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab, u32 *first, uasm_move_relocs(rel, first, end, off); uasm_move_labels(lab, first, end, off); } +UASM_EXPORT_SYMBOL(uasm_copy_handler); -int __cpuinit uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr) +int __uasminit uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr) { for (; rel->lab != UASM_LABEL_INVALID; rel++) { if (rel->addr == addr @@ -566,77 +588,88 @@ int __cpuinit uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr) return 0; } +UASM_EXPORT_SYMBOL(uasm_insn_has_bdelay); /* Convenience functions for labeled branches. */ -void __cpuinit +void __uasminit uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_bltz(p, reg, 0); } +UASM_EXPORT_SYMBOL(uasm_il_bltz); -void __cpuinit +void __uasminit uasm_il_b(u32 **p, struct uasm_reloc **r, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_b(p, 0); } +UASM_EXPORT_SYMBOL(uasm_il_b); -void __cpuinit +void __uasminit uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_beqz(p, reg, 0); } +UASM_EXPORT_SYMBOL(uasm_il_beqz); -void __cpuinit +void __uasminit uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_beqzl(p, reg, 0); } +UASM_EXPORT_SYMBOL(uasm_il_beqzl); -void __cpuinit +void __uasminit uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1, unsigned int reg2, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_bne(p, reg1, reg2, 0); } +UASM_EXPORT_SYMBOL(uasm_il_bne); -void __cpuinit +void __uasminit uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_bnez(p, reg, 0); } +UASM_EXPORT_SYMBOL(uasm_il_bnez); -void __cpuinit +void __uasminit uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_bgezl(p, reg, 0); } +UASM_EXPORT_SYMBOL(uasm_il_bgezl); -void __cpuinit +void __uasminit uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_bgez(p, reg, 0); } +UASM_EXPORT_SYMBOL(uasm_il_bgez); -void __cpuinit +void __uasminit uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg, unsigned int bit, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_bbit0(p, reg, bit, 0); } +UASM_EXPORT_SYMBOL(uasm_il_bbit0); -void __cpuinit +void __uasminit uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg, unsigned int bit, int lid) { uasm_r_mips_pc16(r, *p, lid); uasm_i_bbit1(p, reg, bit, 0); } +UASM_EXPORT_SYMBOL(uasm_il_bbit1); -- cgit v0.10.2 From ea435464a14af37b9384e96b2f5a1f76a605b048 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 23 Jul 2010 18:41:44 -0700 Subject: MIPS: Octeon: Export prom_putchar(). The forthcoming watchdog driver will use it. Signed-off-by: David Daney To: linux-mips@linux-mips.org To: wim@iguana.be Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1499/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 7216fbd..041326e 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -687,7 +687,10 @@ void __init plat_mem_setup(void) "cvmx_bootmem_phy_alloc\n"); } - +/* + * Emit one character to the boot UART. Exported for use by the + * watchdog timer. + */ int prom_putchar(char c) { uint64_t lsrval; @@ -701,6 +704,7 @@ int prom_putchar(char c) cvmx_write_csr(CVMX_MIO_UARTX_THR(octeon_uart), c & 0xffull); return 1; } +EXPORT_SYMBOL(prom_putchar); void prom_free_prom_memory(void) { -- cgit v0.10.2 From 2dc2ae344e0e655fb4296266036d2ac5064634ae Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 23 Jul 2010 18:41:45 -0700 Subject: MIPS: Export __cpu_number_map and __cpu_logical_map. The forthcoming Octeon watchdog driver will use them. Signed-off-by: David Daney To: linux-mips@linux-mips.org To: wim@iguana.be Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1499/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 6cdca19..383aeb9 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -47,8 +47,12 @@ #endif /* CONFIG_MIPS_MT_SMTC */ volatile cpumask_t cpu_callin_map; /* Bitmask of started secondaries */ + int __cpu_number_map[NR_CPUS]; /* Map physical to logical */ +EXPORT_SYMBOL(__cpu_number_map); + int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */ +EXPORT_SYMBOL(__cpu_logical_map); /* Number of TCs (or siblings in Intel speak) per CPU core */ int smp_num_siblings = 1; -- cgit v0.10.2 From 96ffa02d219f50a52e0482ad85130858c61efc63 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 23 Jul 2010 18:41:46 -0700 Subject: MIPS: Define ST0_NMI in asm/mipsregs.h This is used by the forthcoming OCTEON watchdog patch. Signed-off-by: David Daney To: linux-mips@linux-mips.org To: wim@iguana.be Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1498/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index c6e3c93..335474c 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -408,6 +408,7 @@ #define STATUSB_IP15 7 #define STATUSF_IP15 (_ULCAST_(1) << 7) #define ST0_CH 0x00040000 +#define ST0_NMI 0x00080000 #define ST0_SR 0x00100000 #define ST0_TS 0x00200000 #define ST0_BEV 0x00400000 -- cgit v0.10.2 From 4c076fb41ac93bc0cbd55f2a731cc31337804acb Mon Sep 17 00:00:00 2001 From: David Daney Date: Sat, 24 Jul 2010 10:16:05 -0700 Subject: WATCHDOG: Add watchdog driver for OCTEON SOCs The OCTEON is a MIPS64 based SOC family with an on chip watchdog unit. The driver is split into two source files one for the C code and one for assembly. Assembly is needed to handle the NMI and then print the machine state before the reboot is triggered. Signed-off-by: David Daney Cc: Wim Van Sebroeck Cc: Andrew Morton Cc: Russell King Cc: Tony Lindgren Cc: Marc Zyngier Cc: Thierry Reding Cc: Sam Ravnborg To: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org, Patchwork: https://patchwork.linux-mips.org/patch/1503/ Signed-off-by: Wim Van Sebroeck Signed-off-by: Ralf Baechle create mode 100644 drivers/watchdog/octeon-wdt-main.c create mode 100644 drivers/watchdog/octeon-wdt-nmi.S diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index afcfacc..b04b184 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -875,6 +875,24 @@ config TXX9_WDT help Hardware driver for the built-in watchdog timer on TXx9 MIPS SoCs. +config OCTEON_WDT + tristate "Cavium OCTEON SOC family Watchdog Timer" + depends on CPU_CAVIUM_OCTEON + default y + select EXPORT_UASM if OCTEON_WDT = m + help + Hardware driver for OCTEON's on chip watchdog timer. + Enables the watchdog for all cores running Linux. It + installs a NMI handler and pokes the watchdog based on an + interrupt. On first expiration of the watchdog, the + interrupt handler pokes it. The second expiration causes an + NMI that prints a message. The third expiration causes a + global soft reset. + + When userspace has /dev/watchdog open, no poking is done + from the first interrupt, it is then only poked when the + device is written. + # PARISC Architecture # POWERPC Architecture diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 72f3e20..e30289a 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -114,6 +114,8 @@ obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o obj-$(CONFIG_AR7_WDT) += ar7_wdt.o obj-$(CONFIG_TXX9_WDT) += txx9wdt.o +obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o +octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o # PARISC Architecture diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c new file mode 100644 index 0000000..2a41017 --- /dev/null +++ b/drivers/watchdog/octeon-wdt-main.c @@ -0,0 +1,745 @@ +/* + * Octeon Watchdog driver + * + * Copyright (C) 2007, 2008, 2009, 2010 Cavium Networks + * + * Some parts derived from wdt.c + * + * (c) Copyright 1996-1997 Alan Cox , + * 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 + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 1995 Alan Cox + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * + * The OCTEON watchdog has a maximum timeout of 2^32 * io_clock. + * For most systems this is less than 10 seconds, so to allow for + * software to request longer watchdog heartbeats, we maintain software + * counters to count multiples of the base rate. If the system locks + * up in such a manner that we can not run the software counters, the + * only result is a watchdog reset sooner than was requested. But + * that is OK, because in this case userspace would likely not be able + * to do anything anyhow. + * + * The hardware watchdog interval we call the period. The OCTEON + * watchdog goes through several stages, after the first period an + * irq is asserted, then if it is not reset, after the next period NMI + * is asserted, then after an additional period a chip wide soft reset. + * So for the software counters, we reset watchdog after each period + * and decrement the counter. But for the last two periods we need to + * let the watchdog progress to the NMI stage so we disable the irq + * and let it proceed. Once in the NMI, we print the register state + * to the serial port and then wait for the reset. + * + * A watchdog is maintained for each CPU in the system, that way if + * one CPU suffers a lockup, we also get a register dump and reset. + * The userspace ping resets the watchdog on all CPUs. + * + * Before userspace opens the watchdog device, we still run the + * watchdogs to catch any lockups that may be kernel related. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +/* The count needed to achieve timeout_sec. */ +static unsigned int timeout_cnt; + +/* The maximum period supported. */ +static unsigned int max_timeout_sec; + +/* The current period. */ +static unsigned int timeout_sec; + +/* Set to non-zero when userspace countdown mode active */ +static int do_coundown; +static unsigned int countdown_reset; +static unsigned int per_cpu_countdown[NR_CPUS]; + +static cpumask_t irq_enabled_cpus; + +#define WD_TIMO 60 /* Default heartbeat = 60 seconds */ + +static int heartbeat = WD_TIMO; +module_param(heartbeat, int, S_IRUGO); +MODULE_PARM_DESC(heartbeat, + "Watchdog heartbeat in seconds. (0 < heartbeat, default=" + __MODULE_STRING(WD_TIMO) ")"); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, int, S_IRUGO); +MODULE_PARM_DESC(nowayout, + "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +static unsigned long octeon_wdt_is_open; +static char expect_close; + +static u32 __initdata nmi_stage1_insns[64]; +/* We need one branch and therefore one relocation per target label. */ +static struct uasm_label __initdata labels[5]; +static struct uasm_reloc __initdata relocs[5]; + +enum lable_id { + label_enter_bootloader = 1 +}; + +/* Some CP0 registers */ +#define K0 26 +#define C0_CVMMEMCTL 11, 7 +#define C0_STATUS 12, 0 +#define C0_EBASE 15, 1 +#define C0_DESAVE 31, 0 + +void octeon_wdt_nmi_stage2(void); + +static void __init octeon_wdt_build_stage1(void) +{ + int i; + int len; + u32 *p = nmi_stage1_insns; +#ifdef CONFIG_HOTPLUG_CPU + struct uasm_label *l = labels; + struct uasm_reloc *r = relocs; +#endif + + /* + * For the next few instructions running the debugger may + * cause corruption of k0 in the saved registers. Since we're + * about to crash, nobody probably cares. + * + * Save K0 into the debug scratch register + */ + uasm_i_dmtc0(&p, K0, C0_DESAVE); + + uasm_i_mfc0(&p, K0, C0_STATUS); +#ifdef CONFIG_HOTPLUG_CPU + uasm_il_bbit0(&p, &r, K0, ilog2(ST0_NMI), label_enter_bootloader); +#endif + /* Force 64-bit addressing enabled */ + uasm_i_ori(&p, K0, K0, ST0_UX | ST0_SX | ST0_KX); + uasm_i_mtc0(&p, K0, C0_STATUS); + +#ifdef CONFIG_HOTPLUG_CPU + uasm_i_mfc0(&p, K0, C0_EBASE); + /* Coreid number in K0 */ + uasm_i_andi(&p, K0, K0, 0xf); + /* 8 * coreid in bits 16-31 */ + uasm_i_dsll_safe(&p, K0, K0, 3 + 16); + uasm_i_ori(&p, K0, K0, 0x8001); + uasm_i_dsll_safe(&p, K0, K0, 16); + uasm_i_ori(&p, K0, K0, 0x0700); + uasm_i_drotr_safe(&p, K0, K0, 32); + /* + * Should result in: 0x8001,0700,0000,8*coreid which is + * CVMX_CIU_WDOGX(coreid) - 0x0500 + * + * Now ld K0, CVMX_CIU_WDOGX(coreid) + */ + uasm_i_ld(&p, K0, 0x500, K0); + /* + * If bit one set handle the NMI as a watchdog event. + * otherwise transfer control to bootloader. + */ + uasm_il_bbit0(&p, &r, K0, 1, label_enter_bootloader); + uasm_i_nop(&p); +#endif + + /* Clear Dcache so cvmseg works right. */ + uasm_i_cache(&p, 1, 0, 0); + + /* Use K0 to do a read/modify/write of CVMMEMCTL */ + uasm_i_dmfc0(&p, K0, C0_CVMMEMCTL); + /* Clear out the size of CVMSEG */ + uasm_i_dins(&p, K0, 0, 0, 6); + /* Set CVMSEG to its largest value */ + uasm_i_ori(&p, K0, K0, 0x1c0 | 54); + /* Store the CVMMEMCTL value */ + uasm_i_dmtc0(&p, K0, C0_CVMMEMCTL); + + /* Load the address of the second stage handler */ + UASM_i_LA(&p, K0, (long)octeon_wdt_nmi_stage2); + uasm_i_jr(&p, K0); + uasm_i_dmfc0(&p, K0, C0_DESAVE); + +#ifdef CONFIG_HOTPLUG_CPU + uasm_build_label(&l, p, label_enter_bootloader); + /* Jump to the bootloader and restore K0 */ + UASM_i_LA(&p, K0, (long)octeon_bootloader_entry_addr); + uasm_i_jr(&p, K0); + uasm_i_dmfc0(&p, K0, C0_DESAVE); +#endif + uasm_resolve_relocs(relocs, labels); + + len = (int)(p - nmi_stage1_insns); + pr_debug("Synthesized NMI stage 1 handler (%d instructions).\n", len); + + pr_debug("\t.set push\n"); + pr_debug("\t.set noreorder\n"); + for (i = 0; i < len; i++) + pr_debug("\t.word 0x%08x\n", nmi_stage1_insns[i]); + pr_debug("\t.set pop\n"); + + if (len > 32) + panic("NMI stage 1 handler exceeds 32 instructions, was %d\n", len); +} + +static int cpu2core(int cpu) +{ +#ifdef CONFIG_SMP + return cpu_logical_map(cpu); +#else + return cvmx_get_core_num(); +#endif +} + +static int core2cpu(int coreid) +{ +#ifdef CONFIG_SMP + return cpu_number_map(coreid); +#else + return 0; +#endif +} + +/** + * Poke the watchdog when an interrupt is received + * + * @cpl: + * @dev_id: + * + * Returns + */ +static irqreturn_t octeon_wdt_poke_irq(int cpl, void *dev_id) +{ + unsigned int core = cvmx_get_core_num(); + int cpu = core2cpu(core); + + if (do_coundown) { + if (per_cpu_countdown[cpu] > 0) { + /* We're alive, poke the watchdog */ + cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1); + per_cpu_countdown[cpu]--; + } else { + /* Bad news, you are about to reboot. */ + disable_irq_nosync(cpl); + cpumask_clear_cpu(cpu, &irq_enabled_cpus); + } + } else { + /* Not open, just ping away... */ + cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1); + } + return IRQ_HANDLED; +} + +/* From setup.c */ +extern int prom_putchar(char c); + +/** + * Write a string to the uart + * + * @str: String to write + */ +static void octeon_wdt_write_string(const char *str) +{ + /* Just loop writing one byte at a time */ + while (*str) + prom_putchar(*str++); +} + +/** + * Write a hex number out of the uart + * + * @value: Number to display + * @digits: Number of digits to print (1 to 16) + */ +static void octeon_wdt_write_hex(u64 value, int digits) +{ + int d; + int v; + for (d = 0; d < digits; d++) { + v = (value >> ((digits - d - 1) * 4)) & 0xf; + if (v >= 10) + prom_putchar('a' + v - 10); + else + prom_putchar('0' + v); + } +} + +const char *reg_name[] = { + "$0", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra" +}; + +/** + * NMI stage 3 handler. NMIs are handled in the following manner: + * 1) The first NMI handler enables CVMSEG and transfers from + * the bootbus region into normal memory. It is careful to not + * destroy any registers. + * 2) The second stage handler uses CVMSEG to save the registers + * and create a stack for C code. It then calls the third level + * handler with one argument, a pointer to the register values. + * 3) The third, and final, level handler is the following C + * function that prints out some useful infomration. + * + * @reg: Pointer to register state before the NMI + */ +void octeon_wdt_nmi_stage3(u64 reg[32]) +{ + u64 i; + + unsigned int coreid = cvmx_get_core_num(); + /* + * Save status and cause early to get them before any changes + * might happen. + */ + u64 cp0_cause = read_c0_cause(); + u64 cp0_status = read_c0_status(); + u64 cp0_error_epc = read_c0_errorepc(); + u64 cp0_epc = read_c0_epc(); + + /* Delay so output from all cores output is not jumbled together. */ + __delay(100000000ull * coreid); + + octeon_wdt_write_string("\r\n*** NMI Watchdog interrupt on Core 0x"); + octeon_wdt_write_hex(coreid, 1); + octeon_wdt_write_string(" ***\r\n"); + for (i = 0; i < 32; i++) { + octeon_wdt_write_string("\t"); + octeon_wdt_write_string(reg_name[i]); + octeon_wdt_write_string("\t0x"); + octeon_wdt_write_hex(reg[i], 16); + if (i & 1) + octeon_wdt_write_string("\r\n"); + } + octeon_wdt_write_string("\terr_epc\t0x"); + octeon_wdt_write_hex(cp0_error_epc, 16); + + octeon_wdt_write_string("\tepc\t0x"); + octeon_wdt_write_hex(cp0_epc, 16); + octeon_wdt_write_string("\r\n"); + + octeon_wdt_write_string("\tstatus\t0x"); + octeon_wdt_write_hex(cp0_status, 16); + octeon_wdt_write_string("\tcause\t0x"); + octeon_wdt_write_hex(cp0_cause, 16); + octeon_wdt_write_string("\r\n"); + + octeon_wdt_write_string("\tsum0\t0x"); + octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_SUM0(coreid * 2)), 16); + octeon_wdt_write_string("\ten0\t0x"); + octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)), 16); + octeon_wdt_write_string("\r\n"); + + octeon_wdt_write_string("*** Chip soft reset soon ***\r\n"); +} + +static void octeon_wdt_disable_interrupt(int cpu) +{ + unsigned int core; + unsigned int irq; + union cvmx_ciu_wdogx ciu_wdog; + + core = cpu2core(cpu); + + irq = OCTEON_IRQ_WDOG0 + core; + + /* Poke the watchdog to clear out its state */ + cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1); + + /* Disable the hardware. */ + ciu_wdog.u64 = 0; + cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64); + + free_irq(irq, octeon_wdt_poke_irq); +} + +static void octeon_wdt_setup_interrupt(int cpu) +{ + unsigned int core; + unsigned int irq; + union cvmx_ciu_wdogx ciu_wdog; + + core = cpu2core(cpu); + + /* Disable it before doing anything with the interrupts. */ + ciu_wdog.u64 = 0; + cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64); + + per_cpu_countdown[cpu] = countdown_reset; + + irq = OCTEON_IRQ_WDOG0 + core; + + if (request_irq(irq, octeon_wdt_poke_irq, + IRQF_DISABLED, "octeon_wdt", octeon_wdt_poke_irq)) + panic("octeon_wdt: Couldn't obtain irq %d", irq); + + cpumask_set_cpu(cpu, &irq_enabled_cpus); + + /* Poke the watchdog to clear out its state */ + cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1); + + /* Finally enable the watchdog now that all handlers are installed */ + ciu_wdog.u64 = 0; + ciu_wdog.s.len = timeout_cnt; + ciu_wdog.s.mode = 3; /* 3 = Interrupt + NMI + Soft-Reset */ + cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64); +} + +static int octeon_wdt_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + + switch (action) { + case CPU_DOWN_PREPARE: + octeon_wdt_disable_interrupt(cpu); + break; + case CPU_ONLINE: + case CPU_DOWN_FAILED: + octeon_wdt_setup_interrupt(cpu); + break; + default: + break; + } + return NOTIFY_OK; +} + +static void octeon_wdt_ping(void) +{ + int cpu; + int coreid; + + for_each_online_cpu(cpu) { + coreid = cpu2core(cpu); + cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1); + per_cpu_countdown[cpu] = countdown_reset; + if ((countdown_reset || !do_coundown) && + !cpumask_test_cpu(cpu, &irq_enabled_cpus)) { + /* We have to enable the irq */ + int irq = OCTEON_IRQ_WDOG0 + coreid; + enable_irq(irq); + cpumask_set_cpu(cpu, &irq_enabled_cpus); + } + } +} + +static void octeon_wdt_calc_parameters(int t) +{ + unsigned int periods; + + timeout_sec = max_timeout_sec; + + + /* + * Find the largest interrupt period, that can evenly divide + * the requested heartbeat time. + */ + while ((t % timeout_sec) != 0) + timeout_sec--; + + periods = t / timeout_sec; + + /* + * The last two periods are after the irq is disabled, and + * then to the nmi, so we subtract them off. + */ + + countdown_reset = periods > 2 ? periods - 2 : 0; + heartbeat = t; + timeout_cnt = ((octeon_get_clock_rate() >> 8) * timeout_sec) >> 8; +} + +static int octeon_wdt_set_heartbeat(int t) +{ + int cpu; + int coreid; + union cvmx_ciu_wdogx ciu_wdog; + + if (t <= 0) + return -1; + + octeon_wdt_calc_parameters(t); + + for_each_online_cpu(cpu) { + coreid = cpu2core(cpu); + cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1); + ciu_wdog.u64 = 0; + ciu_wdog.s.len = timeout_cnt; + ciu_wdog.s.mode = 3; /* 3 = Interrupt + NMI + Soft-Reset */ + cvmx_write_csr(CVMX_CIU_WDOGX(coreid), ciu_wdog.u64); + cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1); + } + octeon_wdt_ping(); /* Get the irqs back on. */ + return 0; +} + +/** + * octeon_wdt_write: + * @file: file handle to the watchdog + * @buf: buffer to write (unused as data does not matter here + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ + +static ssize_t octeon_wdt_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + if (count) { + if (!nowayout) { + size_t i; + + /* In case it was set long ago */ + expect_close = 0; + + for (i = 0; i != count; i++) { + char c; + if (get_user(c, buf + i)) + return -EFAULT; + if (c == 'V') + expect_close = 1; + } + } + octeon_wdt_ping(); + } + return count; +} + +/** + * octeon_wdt_ioctl: + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all + * watchdogs according to their available features. We only + * actually usefully support querying capabilities and setting + * the timeout. + */ + +static long octeon_wdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int __user *p = argp; + int new_heartbeat; + + static struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT| + WDIOF_MAGICCLOSE| + WDIOF_KEEPALIVEPING, + .firmware_version = 1, + .identity = "OCTEON", + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); + case WDIOC_KEEPALIVE: + octeon_wdt_ping(); + return 0; + case WDIOC_SETTIMEOUT: + if (get_user(new_heartbeat, p)) + return -EFAULT; + if (octeon_wdt_set_heartbeat(new_heartbeat)) + return -EINVAL; + /* Fall through. */ + case WDIOC_GETTIMEOUT: + return put_user(heartbeat, p); + default: + return -ENOTTY; + } +} + +/** + * octeon_wdt_open: + * @inode: inode of device + * @file: file handle to device + * + * The watchdog device has been opened. The watchdog device is single + * open and on opening we do a ping to reset the counters. + */ + +static int octeon_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(0, &octeon_wdt_is_open)) + return -EBUSY; + /* + * Activate + */ + octeon_wdt_ping(); + do_coundown = 1; + return nonseekable_open(inode, file); +} + +/** + * octeon_wdt_release: + * @inode: inode to board + * @file: file handle to board + * + * The watchdog has a configurable API. There is a religious dispute + * between people who want their watchdog to be able to shut down and + * those who want to be sure if the watchdog manager dies the machine + * reboots. In the former case we disable the counters, in the latter + * case you have to open it again very soon. + */ + +static int octeon_wdt_release(struct inode *inode, struct file *file) +{ + if (expect_close) { + do_coundown = 0; + octeon_wdt_ping(); + } else { + pr_crit("octeon_wdt: WDT device closed unexpectedly. WDT will not stop!\n"); + } + clear_bit(0, &octeon_wdt_is_open); + expect_close = 0; + return 0; +} + +static const struct file_operations octeon_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = octeon_wdt_write, + .unlocked_ioctl = octeon_wdt_ioctl, + .open = octeon_wdt_open, + .release = octeon_wdt_release, +}; + +static struct miscdevice octeon_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &octeon_wdt_fops, +}; + +static struct notifier_block octeon_wdt_cpu_notifier = { + .notifier_call = octeon_wdt_cpu_callback, +}; + + +/** + * Module/ driver initialization. + * + * Returns Zero on success + */ +static int __init octeon_wdt_init(void) +{ + int i; + int ret; + int cpu; + u64 *ptr; + + /* + * Watchdog time expiration length = The 16 bits of LEN + * represent the most significant bits of a 24 bit decrementer + * that decrements every 256 cycles. + * + * Try for a timeout of 5 sec, if that fails a smaller number + * of even seconds, + */ + max_timeout_sec = 6; + do { + max_timeout_sec--; + timeout_cnt = ((octeon_get_clock_rate() >> 8) * max_timeout_sec) >> 8; + } while (timeout_cnt > 65535); + + BUG_ON(timeout_cnt == 0); + + octeon_wdt_calc_parameters(heartbeat); + + pr_info("octeon_wdt: Initial granularity %d Sec.\n", timeout_sec); + + ret = misc_register(&octeon_wdt_miscdev); + if (ret) { + pr_err("octeon_wdt: cannot register miscdev on minor=%d (err=%d)\n", + WATCHDOG_MINOR, ret); + goto out; + } + + /* Build the NMI handler ... */ + octeon_wdt_build_stage1(); + + /* ... and install it. */ + ptr = (u64 *) nmi_stage1_insns; + for (i = 0; i < 16; i++) { + cvmx_write_csr(CVMX_MIO_BOOT_LOC_ADR, i * 8); + cvmx_write_csr(CVMX_MIO_BOOT_LOC_DAT, ptr[i]); + } + cvmx_write_csr(CVMX_MIO_BOOT_LOC_CFGX(0), 0x81fc0000); + + cpumask_clear(&irq_enabled_cpus); + + for_each_online_cpu(cpu) + octeon_wdt_setup_interrupt(cpu); + + register_hotcpu_notifier(&octeon_wdt_cpu_notifier); +out: + return ret; +} + +/** + * Module / driver shutdown + */ +static void __exit octeon_wdt_cleanup(void) +{ + int cpu; + + misc_deregister(&octeon_wdt_miscdev); + + unregister_hotcpu_notifier(&octeon_wdt_cpu_notifier); + + for_each_online_cpu(cpu) { + int core = cpu2core(cpu); + /* Disable the watchdog */ + cvmx_write_csr(CVMX_CIU_WDOGX(core), 0); + /* Free the interrupt handler */ + free_irq(OCTEON_IRQ_WDOG0 + core, octeon_wdt_poke_irq); + } + /* + * Disable the boot-bus memory, the code it points to is soon + * to go missing. + */ + cvmx_write_csr(CVMX_MIO_BOOT_LOC_CFGX(0), 0); +} + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Cavium Networks "); +MODULE_DESCRIPTION("Cavium Networks Octeon Watchdog driver."); +module_init(octeon_wdt_init); +module_exit(octeon_wdt_cleanup); diff --git a/drivers/watchdog/octeon-wdt-nmi.S b/drivers/watchdog/octeon-wdt-nmi.S new file mode 100644 index 0000000..8a900a5 --- /dev/null +++ b/drivers/watchdog/octeon-wdt-nmi.S @@ -0,0 +1,64 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2007 Cavium Networks + */ +#include +#include + +#define SAVE_REG(r) sd $r, -32768+6912-(32-r)*8($0) + + NESTED(octeon_wdt_nmi_stage2, 0, sp) + .set push + .set noreorder + .set noat + /* Save all registers to the top CVMSEG. This shouldn't + * corrupt any state used by the kernel. Also all registers + * should have the value right before the NMI. */ + SAVE_REG(0) + SAVE_REG(1) + SAVE_REG(2) + SAVE_REG(3) + SAVE_REG(4) + SAVE_REG(5) + SAVE_REG(6) + SAVE_REG(7) + SAVE_REG(8) + SAVE_REG(9) + SAVE_REG(10) + SAVE_REG(11) + SAVE_REG(12) + SAVE_REG(13) + SAVE_REG(14) + SAVE_REG(15) + SAVE_REG(16) + SAVE_REG(17) + SAVE_REG(18) + SAVE_REG(19) + SAVE_REG(20) + SAVE_REG(21) + SAVE_REG(22) + SAVE_REG(23) + SAVE_REG(24) + SAVE_REG(25) + SAVE_REG(26) + SAVE_REG(27) + SAVE_REG(28) + SAVE_REG(29) + SAVE_REG(30) + SAVE_REG(31) + /* Set the stack to begin right below the registers */ + li sp, -32768+6912-32*8 + /* Load the address of the third stage handler */ + dla a0, octeon_wdt_nmi_stage3 + /* Call the third stage handler */ + jal a0 + /* a0 is the address of the saved registers */ + move a0, sp + /* Loop forvever if we get here. */ +1: b 1b + nop + .set pop + END(octeon_wdt_nmi_stage2) -- cgit v0.10.2 From b8c7428af023c4cc37b8651e309713c1f4d9a18e Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Sat, 24 Jul 2010 09:22:13 +0800 Subject: MIPS: Loongson: Remove set_irq_trigger_mode() set_irq_trigger_mode() is not needed on all platforms so remove it and move the related source code to mach_init_irq(). This will allow gdium to share the common irq.c without adding an empty set_irq_trigger_mode(). Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1493/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h index fcdbe3a..53ee881 100644 --- a/arch/mips/include/asm/mach-loongson/loongson.h +++ b/arch/mips/include/asm/mach-loongson/loongson.h @@ -45,7 +45,6 @@ static inline void prom_init_uart_base(void) /* irq operation functions */ extern void bonito_irqdispatch(void); extern void __init bonito_irq_init(void); -extern void __init set_irq_trigger_mode(void); extern void __init mach_init_irq(void); extern void mach_irq_dispatch(unsigned int pending); extern int mach_i8259_irq(void); diff --git a/arch/mips/loongson/common/irq.c b/arch/mips/loongson/common/irq.c index 25a11df..5897471 100644 --- a/arch/mips/loongson/common/irq.c +++ b/arch/mips/loongson/common/irq.c @@ -53,9 +53,6 @@ void __init arch_init_irq(void) */ clear_c0_status(ST0_IM | ST0_BEV); - /* setting irq trigger mode */ - set_irq_trigger_mode(); - /* no steer */ LOONGSON_INTSTEER = 0; diff --git a/arch/mips/loongson/fuloong-2e/irq.c b/arch/mips/loongson/fuloong-2e/irq.c index 320e937..99e08c3 100644 --- a/arch/mips/loongson/fuloong-2e/irq.c +++ b/arch/mips/loongson/fuloong-2e/irq.c @@ -44,13 +44,6 @@ static struct irqaction cascade_irqaction = { .name = "cascade", }; -void __init set_irq_trigger_mode(void) -{ - /* most bonito irq should be level triggered */ - LOONGSON_INTEDGE = LOONGSON_ICU_SYSTEMERR | LOONGSON_ICU_MASTERERR | - LOONGSON_ICU_RETRYERR | LOONGSON_ICU_MBOXES; -} - void __init mach_init_irq(void) { /* init all controller @@ -59,6 +52,10 @@ void __init mach_init_irq(void) * 32-63 ------> bonito irq */ + /* most bonito irq should be level triggered */ + LOONGSON_INTEDGE = LOONGSON_ICU_SYSTEMERR | LOONGSON_ICU_MASTERERR | + LOONGSON_ICU_RETRYERR | LOONGSON_ICU_MBOXES; + /* Sets the first-level interrupt dispatcher. */ mips_cpu_irq_init(); init_i8259_irqs(); diff --git a/arch/mips/loongson/lemote-2f/irq.c b/arch/mips/loongson/lemote-2f/irq.c index 1d8b4d2..c6db7e7 100644 --- a/arch/mips/loongson/lemote-2f/irq.c +++ b/arch/mips/loongson/lemote-2f/irq.c @@ -91,13 +91,6 @@ void mach_irq_dispatch(unsigned int pending) spurious_interrupt(); } -void __init set_irq_trigger_mode(void) -{ - /* setup cs5536 as high level trigger */ - LOONGSON_INTPOL = LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1; - LOONGSON_INTEDGE &= ~(LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1); -} - static irqreturn_t ip6_action(int cpl, void *dev_id) { return IRQ_HANDLED; @@ -122,6 +115,10 @@ void __init mach_init_irq(void) * 32-63 ------> bonito irq */ + /* setup cs5536 as high level trigger */ + LOONGSON_INTPOL = LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1; + LOONGSON_INTEDGE &= ~(LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1); + /* Sets the first-level interrupt dispatcher. */ mips_cpu_irq_init(); init_i8259_irqs(); -- cgit v0.10.2 From de3bc0e7ba5e89d63cb2dbac4e49a5c4b18669b5 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Sat, 24 Jul 2010 09:22:14 +0800 Subject: MIPS: Loongson: Oprofile: add a new do_perfcnt_IRQ() On FuLoong-2F IP6 is shared by the performance counter overflow interrupt and the Bonito northbridge interrupt. To reduce overhead only call do_IRQ() when oprofile is enabled to reduce overhead. This patch adds an inline function do_perfcnt_IRQ() to hide the #if's , which can be shared by the other Loongson machines, i.e. gdium. Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1492/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h index 53ee881..cb6985f 100644 --- a/arch/mips/include/asm/mach-loongson/loongson.h +++ b/arch/mips/include/asm/mach-loongson/loongson.h @@ -62,6 +62,14 @@ extern int mach_i8259_irq(void); #define LOONGSON_IRQ_BASE 32 #define LOONGSON2_PERFCNT_IRQ (MIPS_CPU_IRQ_BASE + 6) /* cpu perf counter */ +#include +static inline void do_perfcnt_IRQ(void) +{ +#if defined(CONFIG_OPROFILE) || defined(CONFIG_OPROFILE_MODULE) + do_IRQ(LOONGSON2_PERFCNT_IRQ); +#endif +} + #define LOONGSON_FLASH_BASE 0x1c000000 #define LOONGSON_FLASH_SIZE 0x02000000 /* 32M */ #define LOONGSON_FLASH_TOP (LOONGSON_FLASH_BASE+LOONGSON_FLASH_SIZE-1) diff --git a/arch/mips/loongson/fuloong-2e/irq.c b/arch/mips/loongson/fuloong-2e/irq.c index 99e08c3..d61a042 100644 --- a/arch/mips/loongson/fuloong-2e/irq.c +++ b/arch/mips/loongson/fuloong-2e/irq.c @@ -30,7 +30,7 @@ asmlinkage void mach_irq_dispatch(unsigned int pending) if (pending & CAUSEF_IP7) do_IRQ(MIPS_CPU_IRQ_BASE + 7); else if (pending & CAUSEF_IP6) /* perf counter loverflow */ - do_IRQ(LOONGSON2_PERFCNT_IRQ); + do_perfcnt_IRQ(); else if (pending & CAUSEF_IP5) i8259_irqdispatch(); else if (pending & CAUSEF_IP2) diff --git a/arch/mips/loongson/lemote-2f/irq.c b/arch/mips/loongson/lemote-2f/irq.c index c6db7e7..71347d7 100644 --- a/arch/mips/loongson/lemote-2f/irq.c +++ b/arch/mips/loongson/lemote-2f/irq.c @@ -79,9 +79,7 @@ void mach_irq_dispatch(unsigned int pending) if (pending & CAUSEF_IP7) do_IRQ(LOONGSON_TIMER_IRQ); else if (pending & CAUSEF_IP6) { /* North Bridge, Perf counter */ -#if defined(CONFIG_OPROFILE) || defined(CONFIG_OPROFILE_MODULE) - do_IRQ(LOONGSON2_PERFCNT_IRQ); -#endif + do_perfcnt_IRQ(); bonito_irqdispatch(); } else if (pending & CAUSEF_IP3) /* CPU UART */ do_IRQ(LOONGSON_UART_IRQ); -- cgit v0.10.2 From e608aadd17b2430ad9f6c412311bfcc120222ae3 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Sat, 24 Jul 2010 09:22:15 +0800 Subject: MIPS: Loongson: Remove unused macro LOONGSON_PERFCNT_IRQ LOONGSON2_PERFCNT_IRQ is used for the irq number of the performance overflow interrupts; LOONGSON_PERFCNT_IRQ is unused so remove it. Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1494/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/loongson/lemote-2f/irq.c b/arch/mips/loongson/lemote-2f/irq.c index 71347d7..081db10 100644 --- a/arch/mips/loongson/lemote-2f/irq.c +++ b/arch/mips/loongson/lemote-2f/irq.c @@ -19,7 +19,6 @@ #include #define LOONGSON_TIMER_IRQ (MIPS_CPU_IRQ_BASE + 7) /* cpu timer */ -#define LOONGSON_PERFCNT_IRQ (MIPS_CPU_IRQ_BASE + 6) /* cpu perf counter */ #define LOONGSON_NORTH_BRIDGE_IRQ (MIPS_CPU_IRQ_BASE + 6) /* bonito */ #define LOONGSON_UART_IRQ (MIPS_CPU_IRQ_BASE + 3) /* cpu serial port */ #define LOONGSON_SOUTH_BRIDGE_IRQ (MIPS_CPU_IRQ_BASE + 2) /* i8259 */ -- cgit v0.10.2 From fa90c87297a1bebd8356e41d71518b37ada56583 Mon Sep 17 00:00:00 2001 From: Kulikov Vasiliy Date: Wed, 14 Jul 2010 22:01:42 +0400 Subject: MIPS: SMTC: Use %p to format pointers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While at it, drop 0x prefix. Signed-off-by: Kulikov Vasiliy To: kernel-janitors@vger.kernel.org Cc: Chris Dearman Cc: "Robert P. J. Day" Cc: Rusty Russell Cc: André Goddard Rosa Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1458/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index a95dea5..cfeb2c1 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -975,8 +975,7 @@ void ipi_decode(struct smtc_ipi *pipi) ipi_call_interrupt(); break; default: - printk("Impossible SMTC IPI Argument 0x%x\n", - (int)arg_copy); + printk("Impossible SMTC IPI Argument %p\n", arg_copy); break; } break; -- cgit v0.10.2 From 0c2f4551df3880083e4733b5d928d2758b71162c Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 26 Jul 2010 14:29:37 -0700 Subject: MIPS: Decode core number for R2 CPUs. The struct cpuinfo_mips.core field should be populated with the physical core number. For R2 CPUs, this is carried in the low 10 bits of Ebase. Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1505/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 9b663317..b1b304e 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -761,6 +761,9 @@ static void __cpuinit decode_configs(struct cpuinfo_mips *c) ok = decode_config4(c); mips_probe_watch_registers(c); + + if (cpu_has_mips_r2) + c->core = read_c0_ebase() & 0x3ff; } static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu) -- cgit v0.10.2 From 1aa2b2782a056b9bb0a19fae5a04624d8dcd8379 Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 26 Jul 2010 18:14:15 -0700 Subject: MIPS: Octeon: Support 256 MSI on PCIe Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/1507/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-cavium-octeon/irq.h b/arch/mips/include/asm/mach-cavium-octeon/irq.h index 783dae7..6ddab8a 100644 --- a/arch/mips/include/asm/mach-cavium-octeon/irq.h +++ b/arch/mips/include/asm/mach-cavium-octeon/irq.h @@ -172,7 +172,7 @@ #ifdef CONFIG_PCI_MSI /* 152 - 215 represent the MSI interrupts 0-63 */ #define OCTEON_IRQ_MSI_BIT0 152 -#define OCTEON_IRQ_MSI_LAST (OCTEON_IRQ_MSI_BIT0 + 63) +#define OCTEON_IRQ_MSI_LAST (OCTEON_IRQ_MSI_BIT0 + 255) #define OCTEON_IRQ_LAST (OCTEON_IRQ_MSI_LAST + 1) #else diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c index 83ceb52..7c75640 100644 --- a/arch/mips/pci/msi-octeon.c +++ b/arch/mips/pci/msi-octeon.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2005-2009 Cavium Networks + * Copyright (C) 2005-2009, 2010 Cavium Networks */ #include #include @@ -22,7 +22,7 @@ * Each bit in msi_free_irq_bitmask represents a MSI interrupt that is * in use. */ -static uint64_t msi_free_irq_bitmask; +static u64 msi_free_irq_bitmask[4]; /* * Each bit in msi_multiple_irq_bitmask tells that the device using @@ -30,7 +30,7 @@ static uint64_t msi_free_irq_bitmask; * is used so we can disable all of the MSI interrupts when a device * uses multiple. */ -static uint64_t msi_multiple_irq_bitmask; +static u64 msi_multiple_irq_bitmask[4]; /* * This lock controls updates to msi_free_irq_bitmask and @@ -38,6 +38,11 @@ static uint64_t msi_multiple_irq_bitmask; */ static DEFINE_SPINLOCK(msi_free_irq_bitmask_lock); +/* + * Number of MSI IRQs used. This variable is set up in + * the module init time. + */ +static int msi_irq_size; /** * Called when a driver request MSI interrupts instead of the @@ -54,12 +59,13 @@ static DEFINE_SPINLOCK(msi_free_irq_bitmask_lock); int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) { struct msi_msg msg; - uint16_t control; + u16 control; int configured_private_bits; int request_private_bits; - int irq; + int irq = 0; int irq_step; - uint64_t search_mask; + u64 search_mask; + int index; /* * Read the MSI config to figure out how many IRQs this device @@ -111,29 +117,31 @@ try_only_one: * use. */ spin_lock(&msi_free_irq_bitmask_lock); - for (irq = 0; irq < 64; irq += irq_step) { - if ((msi_free_irq_bitmask & (search_mask << irq)) == 0) { - msi_free_irq_bitmask |= search_mask << irq; - msi_multiple_irq_bitmask |= (search_mask >> 1) << irq; - break; + for (index = 0; index < msi_irq_size/64; index++) { + for (irq = 0; irq < 64; irq += irq_step) { + if ((msi_free_irq_bitmask[index] & (search_mask << irq)) == 0) { + msi_free_irq_bitmask[index] |= search_mask << irq; + msi_multiple_irq_bitmask[index] |= (search_mask >> 1) << irq; + goto msi_irq_allocated; + } } } +msi_irq_allocated: spin_unlock(&msi_free_irq_bitmask_lock); /* Make sure the search for available interrupts didn't fail */ if (irq >= 64) { if (request_private_bits) { - pr_err("arch_setup_msi_irq: Unable to find %d free " - "interrupts, trying just one", + pr_err("arch_setup_msi_irq: Unable to find %d free interrupts, trying just one", 1 << request_private_bits); request_private_bits = 0; goto try_only_one; } else - panic("arch_setup_msi_irq: Unable to find a free MSI " - "interrupt"); + panic("arch_setup_msi_irq: Unable to find a free MSI interrupt"); } /* MSI interrupts start at logical IRQ OCTEON_IRQ_MSI_BIT0 */ + irq += index*64; irq += OCTEON_IRQ_MSI_BIT0; switch (octeon_dma_bar_type) { @@ -179,12 +187,18 @@ try_only_one: void arch_teardown_msi_irq(unsigned int irq) { int number_irqs; - uint64_t bitmask; + u64 bitmask; + int index = 0; + int irq0; - if ((irq < OCTEON_IRQ_MSI_BIT0) || (irq > OCTEON_IRQ_MSI_LAST)) + if ((irq < OCTEON_IRQ_MSI_BIT0) + || (irq > msi_irq_size + OCTEON_IRQ_MSI_BIT0)) panic("arch_teardown_msi_irq: Attempted to teardown illegal " "MSI interrupt (%d)", irq); + irq -= OCTEON_IRQ_MSI_BIT0; + index = irq / 64; + irq0 = irq % 64; /* * Count the number of IRQs we need to free by looking at the @@ -192,151 +206,197 @@ void arch_teardown_msi_irq(unsigned int irq) * IRQ is also owned by this device. */ number_irqs = 0; - while ((irq+number_irqs < 64) && - (msi_multiple_irq_bitmask & (1ull << (irq + number_irqs)))) + while ((irq0 + number_irqs < 64) && + (msi_multiple_irq_bitmask[index] + & (1ull << (irq0 + number_irqs)))) number_irqs++; number_irqs++; /* Mask with one bit for each IRQ */ bitmask = (1 << number_irqs) - 1; /* Shift the mask to the correct bit location */ - bitmask <<= irq; - if ((msi_free_irq_bitmask & bitmask) != bitmask) + bitmask <<= irq0; + if ((msi_free_irq_bitmask[index] & bitmask) != bitmask) panic("arch_teardown_msi_irq: Attempted to teardown MSI " "interrupt (%d) not in use", irq); /* Checks are done, update the in use bitmask */ spin_lock(&msi_free_irq_bitmask_lock); - msi_free_irq_bitmask &= ~bitmask; - msi_multiple_irq_bitmask &= ~bitmask; + msi_free_irq_bitmask[index] &= ~bitmask; + msi_multiple_irq_bitmask[index] &= ~bitmask; spin_unlock(&msi_free_irq_bitmask_lock); } +static DEFINE_RAW_SPINLOCK(octeon_irq_msi_lock); -/* - * Called by the interrupt handling code when an MSI interrupt - * occurs. - */ -static irqreturn_t octeon_msi_interrupt(int cpl, void *dev_id) +static u64 msi_rcv_reg[4]; +static u64 mis_ena_reg[4]; + +static void octeon_irq_msi_enable_pcie(unsigned int irq) { - uint64_t msi_bits; - int irq; + u64 en; + unsigned long flags; + int msi_number = irq - OCTEON_IRQ_MSI_BIT0; + int irq_index = msi_number >> 6; + int irq_bit = msi_number & 0x3f; + + raw_spin_lock_irqsave(&octeon_irq_msi_lock, flags); + en = cvmx_read_csr(mis_ena_reg[irq_index]); + en |= 1ull << irq_bit; + cvmx_write_csr(mis_ena_reg[irq_index], en); + cvmx_read_csr(mis_ena_reg[irq_index]); + raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags); +} - if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE) - msi_bits = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_RCV0); - else - msi_bits = cvmx_read_csr(CVMX_NPI_NPI_MSI_RCV); - irq = fls64(msi_bits); - if (irq) { - irq += OCTEON_IRQ_MSI_BIT0 - 1; - if (octeon_has_feature(OCTEON_FEATURE_PCIE)) { - /* These chips have PCIe */ - cvmx_write_csr(CVMX_PEXP_NPEI_MSI_RCV0, - 1ull << (irq - OCTEON_IRQ_MSI_BIT0)); - } else { - /* These chips have PCI */ - cvmx_write_csr(CVMX_NPI_NPI_MSI_RCV, - 1ull << (irq - OCTEON_IRQ_MSI_BIT0)); - } - if (irq_desc[irq].action) { - do_IRQ(irq); - return IRQ_HANDLED; - } else { - pr_err("Spurious MSI interrupt %d\n", irq); - } - } - return IRQ_NONE; +static void octeon_irq_msi_disable_pcie(unsigned int irq) +{ + u64 en; + unsigned long flags; + int msi_number = irq - OCTEON_IRQ_MSI_BIT0; + int irq_index = msi_number >> 6; + int irq_bit = msi_number & 0x3f; + + raw_spin_lock_irqsave(&octeon_irq_msi_lock, flags); + en = cvmx_read_csr(mis_ena_reg[irq_index]); + en &= ~(1ull << irq_bit); + cvmx_write_csr(mis_ena_reg[irq_index], en); + cvmx_read_csr(mis_ena_reg[irq_index]); + raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags); } -static DEFINE_RAW_SPINLOCK(octeon_irq_msi_lock); +static struct irq_chip octeon_irq_chip_msi_pcie = { + .name = "MSI", + .enable = octeon_irq_msi_enable_pcie, + .disable = octeon_irq_msi_disable_pcie, +}; -static void octeon_irq_msi_enable(unsigned int irq) +static void octeon_irq_msi_enable_pci(unsigned int irq) { - if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) { - /* - * Octeon PCI doesn't have the ability to mask/unmask - * MSI interrupts individually. Instead of - * masking/unmasking them in groups of 16, we simple - * assume MSI devices are well behaved. MSI - * interrupts are always enable and the ACK is assumed - * to be enough. - */ - } else { - /* These chips have PCIe. Note that we only support - * the first 64 MSI interrupts. Unfortunately all the - * MSI enables are in the same register. We use - * MSI0's lock to control access to them all. - */ - uint64_t en; - unsigned long flags; - raw_spin_lock_irqsave(&octeon_irq_msi_lock, flags); - en = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); - en |= 1ull << (irq - OCTEON_IRQ_MSI_BIT0); - cvmx_write_csr(CVMX_PEXP_NPEI_MSI_ENB0, en); - cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); - raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags); - } + /* + * Octeon PCI doesn't have the ability to mask/unmask MSI + * interrupts individually. Instead of masking/unmasking them + * in groups of 16, we simple assume MSI devices are well + * behaved. MSI interrupts are always enable and the ACK is + * assumed to be enough + */ } -static void octeon_irq_msi_disable(unsigned int irq) +static void octeon_irq_msi_disable_pci(unsigned int irq) { - if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) { - /* See comment in enable */ - } else { - /* - * These chips have PCIe. Note that we only support - * the first 64 MSI interrupts. Unfortunately all the - * MSI enables are in the same register. We use - * MSI0's lock to control access to them all. - */ - uint64_t en; - unsigned long flags; - raw_spin_lock_irqsave(&octeon_irq_msi_lock, flags); - en = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); - en &= ~(1ull << (irq - OCTEON_IRQ_MSI_BIT0)); - cvmx_write_csr(CVMX_PEXP_NPEI_MSI_ENB0, en); - cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); - raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags); - } + /* See comment in enable */ } -static struct irq_chip octeon_irq_chip_msi = { +static struct irq_chip octeon_irq_chip_msi_pci = { .name = "MSI", - .enable = octeon_irq_msi_enable, - .disable = octeon_irq_msi_disable, + .enable = octeon_irq_msi_enable_pci, + .disable = octeon_irq_msi_disable_pci, }; /* - * Initializes the MSI interrupt handling code + * Called by the interrupt handling code when an MSI interrupt + * occurs. */ -static int __init octeon_msi_initialize(void) +static irqreturn_t __octeon_msi_do_interrupt(int index, u64 msi_bits) { int irq; + int bit; - for (irq = OCTEON_IRQ_MSI_BIT0; irq <= OCTEON_IRQ_MSI_LAST; irq++) { - set_irq_chip_and_handler(irq, &octeon_irq_chip_msi, handle_simple_irq); + bit = fls64(msi_bits); + if (bit) { + bit--; + /* Acknowledge it first. */ + cvmx_write_csr(msi_rcv_reg[index], 1ull << bit); + + irq = bit + OCTEON_IRQ_MSI_BIT0 + 64 * index; + do_IRQ(irq); + return IRQ_HANDLED; } + return IRQ_NONE; +} + +#define OCTEON_MSI_INT_HANDLER_X(x) \ +static irqreturn_t octeon_msi_interrupt##x(int cpl, void *dev_id) \ +{ \ + u64 msi_bits = cvmx_read_csr(msi_rcv_reg[(x)]); \ + return __octeon_msi_do_interrupt((x), msi_bits); \ +} + +/* + * Create octeon_msi_interrupt{0-3} function body + */ +OCTEON_MSI_INT_HANDLER_X(0); +OCTEON_MSI_INT_HANDLER_X(1); +OCTEON_MSI_INT_HANDLER_X(2); +OCTEON_MSI_INT_HANDLER_X(3); + +/* + * Initializes the MSI interrupt handling code + */ +int __init octeon_msi_initialize(void) +{ + int irq; + struct irq_chip *msi; + + if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE) { + msi_rcv_reg[0] = CVMX_PEXP_NPEI_MSI_RCV0; + msi_rcv_reg[1] = CVMX_PEXP_NPEI_MSI_RCV1; + msi_rcv_reg[2] = CVMX_PEXP_NPEI_MSI_RCV2; + msi_rcv_reg[3] = CVMX_PEXP_NPEI_MSI_RCV3; + mis_ena_reg[0] = CVMX_PEXP_NPEI_MSI_ENB0; + mis_ena_reg[1] = CVMX_PEXP_NPEI_MSI_ENB1; + mis_ena_reg[2] = CVMX_PEXP_NPEI_MSI_ENB2; + mis_ena_reg[3] = CVMX_PEXP_NPEI_MSI_ENB3; + msi = &octeon_irq_chip_msi_pcie; + } else { + msi_rcv_reg[0] = CVMX_NPI_NPI_MSI_RCV; +#define INVALID_GENERATE_ADE 0x8700000000000000ULL; + msi_rcv_reg[1] = INVALID_GENERATE_ADE; + msi_rcv_reg[2] = INVALID_GENERATE_ADE; + msi_rcv_reg[3] = INVALID_GENERATE_ADE; + mis_ena_reg[0] = INVALID_GENERATE_ADE; + mis_ena_reg[1] = INVALID_GENERATE_ADE; + mis_ena_reg[2] = INVALID_GENERATE_ADE; + mis_ena_reg[3] = INVALID_GENERATE_ADE; + msi = &octeon_irq_chip_msi_pci; + } + + for (irq = OCTEON_IRQ_MSI_BIT0; irq <= OCTEON_IRQ_MSI_LAST; irq++) + set_irq_chip_and_handler(irq, msi, handle_simple_irq); if (octeon_has_feature(OCTEON_FEATURE_PCIE)) { - if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt, - 0, "MSI[0:63]", octeon_msi_interrupt)) + if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt0, + 0, "MSI[0:63]", octeon_msi_interrupt0)) panic("request_irq(OCTEON_IRQ_PCI_MSI0) failed"); + + if (request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt1, + 0, "MSI[64:127]", octeon_msi_interrupt1)) + panic("request_irq(OCTEON_IRQ_PCI_MSI1) failed"); + + if (request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt2, + 0, "MSI[127:191]", octeon_msi_interrupt2)) + panic("request_irq(OCTEON_IRQ_PCI_MSI2) failed"); + + if (request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt3, + 0, "MSI[192:255]", octeon_msi_interrupt3)) + panic("request_irq(OCTEON_IRQ_PCI_MSI3) failed"); + + msi_irq_size = 256; } else if (octeon_is_pci_host()) { - if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt, - 0, "MSI[0:15]", octeon_msi_interrupt)) + if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt0, + 0, "MSI[0:15]", octeon_msi_interrupt0)) panic("request_irq(OCTEON_IRQ_PCI_MSI0) failed"); - if (request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt, - 0, "MSI[16:31]", octeon_msi_interrupt)) + if (request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt0, + 0, "MSI[16:31]", octeon_msi_interrupt0)) panic("request_irq(OCTEON_IRQ_PCI_MSI1) failed"); - if (request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt, - 0, "MSI[32:47]", octeon_msi_interrupt)) + if (request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt0, + 0, "MSI[32:47]", octeon_msi_interrupt0)) panic("request_irq(OCTEON_IRQ_PCI_MSI2) failed"); - if (request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt, - 0, "MSI[48:63]", octeon_msi_interrupt)) + if (request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt0, + 0, "MSI[48:63]", octeon_msi_interrupt0)) panic("request_irq(OCTEON_IRQ_PCI_MSI3) failed"); - + msi_irq_size = 64; } return 0; } -- cgit v0.10.2 From 52a0f00b50ea360e3cf7e3281523c6a8aafc5761 Mon Sep 17 00:00:00 2001 From: Chandrakala Chavva Date: Mon, 26 Jul 2010 18:14:16 -0700 Subject: MIPS: Octeon: Disallow MSI-X interrupt and fall back to MSI interrupts. MSI-X interrupts are not supported yet for Octeon, return error if MSI-X interrupts are requested by driver so that the driver will fall back to use MSI interrupts. Signed-off-by: Chandrakala Chavva To: linux-mips@linux-mips.org Cc: David Daney Patchwork: https://patchwork.linux-mips.org/patch/1506/ Signed-off-by: Ralf Baechle Signed-off-by: David Daney diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h index 3beea14..576397c 100644 --- a/arch/mips/include/asm/pci.h +++ b/arch/mips/include/asm/pci.h @@ -140,6 +140,11 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) return channel ? 15 : 14; } +#ifdef CONFIG_CPU_CAVIUM_OCTEON +/* MSI arch hook for OCTEON */ +#define arch_setup_msi_irqs arch_setup_msi_irqs +#endif + extern int pci_probe_only; extern char * (*pcibios_plat_setup)(char *str); diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c index 7c75640..d808049 100644 --- a/arch/mips/pci/msi-octeon.c +++ b/arch/mips/pci/msi-octeon.c @@ -177,6 +177,34 @@ msi_irq_allocated: return 0; } +int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) +{ + struct msi_desc *entry; + int ret; + + /* + * MSI-X is not supported. + */ + if (type == PCI_CAP_ID_MSIX) + return -EINVAL; + + /* + * If an architecture wants to support multiple MSI, it needs to + * override arch_setup_msi_irqs() + */ + if (type == PCI_CAP_ID_MSI && nvec > 1) + return 1; + + list_for_each_entry(entry, &dev->msi_list, list) { + ret = arch_setup_msi_irq(dev, entry); + if (ret < 0) + return ret; + if (ret > 0) + return -ENOSPC; + } + + return 0; +} /** * Called when a device no longer needs its MSI interrupts. All -- cgit v0.10.2 From d7674c4f5899712a262d4946ca6edaa947148f52 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 5 Aug 2010 13:26:27 +0100 Subject: MIPS: Ritually kill stupid printk. This belongs into userland. Signed-off-by: Ralf Baechle diff --git a/arch/mips/alchemy/devboards/db1x00/board_setup.c b/arch/mips/alchemy/devboards/db1x00/board_setup.c index 50c9bef..9e45971 100644 --- a/arch/mips/alchemy/devboards/db1x00/board_setup.c +++ b/arch/mips/alchemy/devboards/db1x00/board_setup.c @@ -79,7 +79,6 @@ static struct au1000_eth_platform_data eth0_pdata = { static void bosporus_power_off(void) { - printk(KERN_INFO "It's now safe to turn off power\n"); while (1) asm volatile (".set mips3 ; wait ; .set mips0"); } diff --git a/arch/mips/alchemy/devboards/pb1000/board_setup.c b/arch/mips/alchemy/devboards/pb1000/board_setup.c index 46fdc8c..f6540ec 100644 --- a/arch/mips/alchemy/devboards/pb1000/board_setup.c +++ b/arch/mips/alchemy/devboards/pb1000/board_setup.c @@ -47,7 +47,6 @@ static void board_reset(char *c) static void board_power_off(void) { - printk(KERN_ALERT "It's now safe to remove power\n"); while (1) asm volatile ( " .set mips32 \n" diff --git a/arch/mips/alchemy/mtx-1/board_setup.c b/arch/mips/alchemy/mtx-1/board_setup.c index ff36973..6398fa9 100644 --- a/arch/mips/alchemy/mtx-1/board_setup.c +++ b/arch/mips/alchemy/mtx-1/board_setup.c @@ -60,7 +60,6 @@ static void mtx1_reset(char *c) static void mtx1_power_off(void) { - printk(KERN_ALERT "It's now safe to remove power\n"); while (1) asm volatile ( " .set mips32 \n" diff --git a/arch/mips/alchemy/xxs1500/board_setup.c b/arch/mips/alchemy/xxs1500/board_setup.c index 7868aea..b43c918 100644 --- a/arch/mips/alchemy/xxs1500/board_setup.c +++ b/arch/mips/alchemy/xxs1500/board_setup.c @@ -42,7 +42,6 @@ static void xxs1500_reset(char *c) static void xxs1500_power_off(void) { - printk(KERN_ALERT "It's now safe to remove power\n"); while (1) asm volatile ( " .set mips32 \n" diff --git a/arch/mips/emma/markeins/setup.c b/arch/mips/emma/markeins/setup.c index 9b3f51e..feceebc 100644 --- a/arch/mips/emma/markeins/setup.c +++ b/arch/mips/emma/markeins/setup.c @@ -52,7 +52,6 @@ static void markeins_machine_halt(void) static void markeins_machine_power_off(void) { - printk("EMMA2RH Mark-eins halted. Please turn off the power.\n"); markeins_led("poweroff."); while (1) ; } -- cgit v0.10.2 From ef771ad4ad59c88ffd1e313aa9e943751f83d3a2 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 3 Aug 2010 13:53:24 -0700 Subject: MIPS: kprobes: Define regs_return_value() Signed-off-by: David Daney To: linux-mips@linux-mips.org To: ananth@in.ibm.com To: anil.s.keshavamurthy@intel.com To: davem@davemloft.net To: masami.hiramatsu.pt@hitachi.com Cc: linux-kernel@vger.kernel.org, Cc: hschauhan@nulltrace.org Patchwork: https://patchwork.linux-mips.org/patch/1529/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h index cdc6a46..9f1b8db 100644 --- a/arch/mips/include/asm/ptrace.h +++ b/arch/mips/include/asm/ptrace.h @@ -137,6 +137,7 @@ extern int ptrace_set_watch_regs(struct task_struct *child, */ #define user_mode(regs) (((regs)->cp0_status & KU_MASK) == KU_USER) +#define regs_return_value(_regs) ((_regs)->regs[2]) #define instruction_pointer(regs) ((regs)->cp0_epc) #define profile_pc(regs) instruction_pointer(regs) -- cgit v0.10.2 From 2ea6399f553bf9a47260723b44d50f747e310218 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 3 Aug 2010 11:22:19 -0700 Subject: MIPS: Add instrunction format for BREAK and SYSCALL Signed-off-by: David Daney To: linux-mips@linux-mips.org To: ananth@in.ibm.com To: anil.s.keshavamurthy@intel.com To: davem@davemloft.net To: masami.hiramatsu.pt@hitachi.com Cc: linux-kernel@vger.kernel.org Cc: hschauhan@nulltrace.org Patchwork: https://patchwork.linux-mips.org/patch/1524/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/inst.h b/arch/mips/include/asm/inst.h index 6489f00..444ff71 100644 --- a/arch/mips/include/asm/inst.h +++ b/arch/mips/include/asm/inst.h @@ -247,6 +247,12 @@ struct ma_format { /* FPU multipy and add format (MIPS IV) */ unsigned int fmt : 2; }; +struct b_format { /* BREAK and SYSCALL */ + unsigned int opcode:6; + unsigned int code:20; + unsigned int func:6; +}; + #elif defined(__MIPSEL__) struct j_format { /* Jump format */ @@ -314,6 +320,12 @@ struct ma_format { /* FPU multipy and add format (MIPS IV) */ unsigned int opcode : 6; }; +struct b_format { /* BREAK and SYSCALL */ + unsigned int func:6; + unsigned int code:20; + unsigned int opcode:6; +}; + #else /* !defined (__MIPSEB__) && !defined (__MIPSEL__) */ #error "MIPS but neither __MIPSEL__ nor __MIPSEB__?" #endif @@ -328,7 +340,8 @@ union mips_instruction { struct c_format c_format; struct r_format r_format; struct f_format f_format; - struct ma_format ma_format; + struct ma_format ma_format; + struct b_format b_format; }; /* HACHACHAHCAHC ... */ -- cgit v0.10.2 From c1bf207d6ee1eb72e9c10365edbdc7c9ff7fb9b0 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 3 Aug 2010 11:22:20 -0700 Subject: MIPS: kprobe: Add support. This patch is based on previous work by Sony and Himanshu Chauhan. I have done some cleanup and implemented JProbes and KRETPROBES. The KRETPROBES part is pretty much copied verbatim from powerpc. A possible future enhance might be to factor out the common code. Signed-off-by: David Daney Cc: Himanshu Chauhan To: linux-mips@linux-mips.org To: ananth@in.ibm.com, To: anil.s.keshavamurthy@intel.com To: davem@davemloft.net To: masami.hiramatsu.pt@hitachi.com Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1525/ Patchwork: https://patchwork.linux-mips.org/patch/1530/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index aaca439..36642df 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -10,6 +10,8 @@ config MIPS select HAVE_DYNAMIC_FTRACE select HAVE_FTRACE_MCOUNT_RECORD select HAVE_FUNCTION_GRAPH_TRACER + select HAVE_KPROBES + select HAVE_KRETPROBES select RTC_LIB if !MACH_LOONGSON mainmenu "Linux/MIPS Kernel Configuration" diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 9296cbf..f0d1960 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -259,6 +259,9 @@ endif vmlinux.32: vmlinux $(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@ + +#obj-$(CONFIG_KPROBES) += kprobes.o + # # The 64-bit ELF tools are pretty broken so at this time we generate 64-bit # ELF files from 32-bit files by conversion. diff --git a/arch/mips/include/asm/break.h b/arch/mips/include/asm/break.h index 44437ed..9161e68 100644 --- a/arch/mips/include/asm/break.h +++ b/arch/mips/include/asm/break.h @@ -30,6 +30,8 @@ #define BRK_BUG 512 /* Used by BUG() */ #define BRK_KDB 513 /* Used in KDB_ENTER() */ #define BRK_MEMU 514 /* Used by FPU emulator */ +#define BRK_KPROBE_BP 515 /* Kprobe break */ +#define BRK_KPROBE_SSTEPBP 516 /* Kprobe single step software implementation */ #define BRK_MULOVF 1023 /* Multiply overflow */ #endif /* __ASM_BREAK_H */ diff --git a/arch/mips/include/asm/kdebug.h b/arch/mips/include/asm/kdebug.h index 5bf62aa..6a9af5f 100644 --- a/arch/mips/include/asm/kdebug.h +++ b/arch/mips/include/asm/kdebug.h @@ -8,6 +8,9 @@ enum die_val { DIE_FP, DIE_TRAP, DIE_RI, + DIE_PAGE_FAULT, + DIE_BREAK, + DIE_SSTEPBP }; #endif /* _ASM_MIPS_KDEBUG_H */ diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h new file mode 100644 index 0000000..e6ea4d4 --- /dev/null +++ b/arch/mips/include/asm/kprobes.h @@ -0,0 +1,92 @@ +/* + * Kernel Probes (KProbes) + * include/asm-mips/kprobes.h + * + * Copyright 2006 Sony Corp. + * Copyright 2010 Cavium Networks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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_KPROBES_H +#define _ASM_KPROBES_H + +#include +#include + +#include +#include +#include + +#define __ARCH_WANT_KPROBES_INSN_SLOT + +struct kprobe; +struct pt_regs; + +typedef union mips_instruction kprobe_opcode_t; + +#define MAX_INSN_SIZE 2 + +#define flush_insn_slot(p) \ +do { \ + flush_icache_range((unsigned long)p->addr, \ + (unsigned long)p->addr + \ + (MAX_INSN_SIZE * sizeof(kprobe_opcode_t))); \ +} while (0) + + +#define kretprobe_blacklist_size 0 + +void arch_remove_kprobe(struct kprobe *p); + +/* Architecture specific copy of original instruction*/ +struct arch_specific_insn { + /* copy of the original instruction */ + kprobe_opcode_t *insn; +}; + +struct prev_kprobe { + struct kprobe *kp; + unsigned long status; + unsigned long old_SR; + unsigned long saved_SR; + unsigned long saved_epc; +}; + +#define MAX_JPROBES_STACK_SIZE 128 +#define MAX_JPROBES_STACK_ADDR \ + (((unsigned long)current_thread_info()) + THREAD_SIZE - 32 - sizeof(struct pt_regs)) + +#define MIN_JPROBES_STACK_SIZE(ADDR) \ + ((((ADDR) + MAX_JPROBES_STACK_SIZE) > MAX_JPROBES_STACK_ADDR) \ + ? MAX_JPROBES_STACK_ADDR - (ADDR) \ + : MAX_JPROBES_STACK_SIZE) + + +/* per-cpu kprobe control block */ +struct kprobe_ctlblk { + unsigned long kprobe_status; + unsigned long kprobe_old_SR; + unsigned long kprobe_saved_SR; + unsigned long kprobe_saved_epc; + unsigned long jprobe_saved_sp; + struct pt_regs jprobe_saved_regs; + u8 jprobes_stack[MAX_JPROBES_STACK_SIZE]; + struct prev_kprobe prev_kprobe; +}; + +extern int kprobe_exceptions_notify(struct notifier_block *self, + unsigned long val, void *data); + +#endif /* _ASM_KPROBES_H */ diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index ff5ec2e..06f8482 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_IRQ_TXX9) += irq_txx9.o obj-$(CONFIG_IRQ_GT641XX) += irq-gt641xx.o obj-$(CONFIG_IRQ_GIC) += irq-gic.o +obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_32BIT) += scall32-o32.o obj-$(CONFIG_64BIT) += scall64-64.o obj-$(CONFIG_MIPS32_COMPAT) += linux32.o ptrace32.o signal32.o diff --git a/arch/mips/kernel/kprobes.c b/arch/mips/kernel/kprobes.c new file mode 100644 index 0000000..ee28683 --- /dev/null +++ b/arch/mips/kernel/kprobes.c @@ -0,0 +1,557 @@ +/* + * Kernel Probes (KProbes) + * arch/mips/kernel/kprobes.c + * + * Copyright 2006 Sony Corp. + * Copyright 2010 Cavium Networks + * + * Some portions copied from the powerpc version. + * + * Copyright (C) IBM Corporation, 2002, 2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 + */ + +#include +#include +#include +#include + +#include +#include +#include + +static const union mips_instruction breakpoint_insn = { + .b_format = { + .opcode = spec_op, + .code = BRK_KPROBE_BP, + .func = break_op + } +}; + +static const union mips_instruction breakpoint2_insn = { + .b_format = { + .opcode = spec_op, + .code = BRK_KPROBE_SSTEPBP, + .func = break_op + } +}; + +DEFINE_PER_CPU(struct kprobe *, current_kprobe); +DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); + +static int __kprobes insn_has_delayslot(union mips_instruction insn) +{ + switch (insn.i_format.opcode) { + + /* + * This group contains: + * jr and jalr are in r_format format. + */ + case spec_op: + switch (insn.r_format.func) { + case jr_op: + case jalr_op: + break; + default: + goto insn_ok; + } + + /* + * This group contains: + * bltz_op, bgez_op, bltzl_op, bgezl_op, + * bltzal_op, bgezal_op, bltzall_op, bgezall_op. + */ + case bcond_op: + + /* + * These are unconditional and in j_format. + */ + case jal_op: + case j_op: + + /* + * These are conditional and in i_format. + */ + case beq_op: + case beql_op: + case bne_op: + case bnel_op: + case blez_op: + case blezl_op: + case bgtz_op: + case bgtzl_op: + + /* + * These are the FPA/cp1 branch instructions. + */ + case cop1_op: + +#ifdef CONFIG_CPU_CAVIUM_OCTEON + case lwc2_op: /* This is bbit0 on Octeon */ + case ldc2_op: /* This is bbit032 on Octeon */ + case swc2_op: /* This is bbit1 on Octeon */ + case sdc2_op: /* This is bbit132 on Octeon */ +#endif + return 1; + default: + break; + } +insn_ok: + return 0; +} + +int __kprobes arch_prepare_kprobe(struct kprobe *p) +{ + union mips_instruction insn; + union mips_instruction prev_insn; + int ret = 0; + + prev_insn = p->addr[-1]; + insn = p->addr[0]; + + if (insn_has_delayslot(insn) || insn_has_delayslot(prev_insn)) { + pr_notice("Kprobes for branch and jump instructions are not supported\n"); + ret = -EINVAL; + goto out; + } + + /* insn: must be on special executable page on mips. */ + p->ainsn.insn = get_insn_slot(); + if (!p->ainsn.insn) { + ret = -ENOMEM; + goto out; + } + + /* + * In the kprobe->ainsn.insn[] array we store the original + * instruction at index zero and a break trap instruction at + * index one. + */ + + memcpy(&p->ainsn.insn[0], p->addr, sizeof(kprobe_opcode_t)); + p->ainsn.insn[1] = breakpoint2_insn; + p->opcode = *p->addr; + +out: + return ret; +} + +void __kprobes arch_arm_kprobe(struct kprobe *p) +{ + *p->addr = breakpoint_insn; + flush_insn_slot(p); +} + +void __kprobes arch_disarm_kprobe(struct kprobe *p) +{ + *p->addr = p->opcode; + flush_insn_slot(p); +} + +void __kprobes arch_remove_kprobe(struct kprobe *p) +{ + free_insn_slot(p->ainsn.insn, 0); +} + +static void save_previous_kprobe(struct kprobe_ctlblk *kcb) +{ + kcb->prev_kprobe.kp = kprobe_running(); + kcb->prev_kprobe.status = kcb->kprobe_status; + kcb->prev_kprobe.old_SR = kcb->kprobe_old_SR; + kcb->prev_kprobe.saved_SR = kcb->kprobe_saved_SR; + kcb->prev_kprobe.saved_epc = kcb->kprobe_saved_epc; +} + +static void restore_previous_kprobe(struct kprobe_ctlblk *kcb) +{ + __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; + kcb->kprobe_status = kcb->prev_kprobe.status; + kcb->kprobe_old_SR = kcb->prev_kprobe.old_SR; + kcb->kprobe_saved_SR = kcb->prev_kprobe.saved_SR; + kcb->kprobe_saved_epc = kcb->prev_kprobe.saved_epc; +} + +static void set_current_kprobe(struct kprobe *p, struct pt_regs *regs, + struct kprobe_ctlblk *kcb) +{ + __get_cpu_var(current_kprobe) = p; + kcb->kprobe_saved_SR = kcb->kprobe_old_SR = (regs->cp0_status & ST0_IE); + kcb->kprobe_saved_epc = regs->cp0_epc; +} + +static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) +{ + regs->cp0_status &= ~ST0_IE; + + /* single step inline if the instruction is a break */ + if (p->opcode.word == breakpoint_insn.word || + p->opcode.word == breakpoint2_insn.word) + regs->cp0_epc = (unsigned long)p->addr; + else + regs->cp0_epc = (unsigned long)&p->ainsn.insn[0]; +} + +static int __kprobes kprobe_handler(struct pt_regs *regs) +{ + struct kprobe *p; + int ret = 0; + kprobe_opcode_t *addr; + struct kprobe_ctlblk *kcb; + + addr = (kprobe_opcode_t *) regs->cp0_epc; + + /* + * We don't want to be preempted for the entire + * duration of kprobe processing + */ + preempt_disable(); + kcb = get_kprobe_ctlblk(); + + /* Check we're not actually recursing */ + if (kprobe_running()) { + p = get_kprobe(addr); + if (p) { + if (kcb->kprobe_status == KPROBE_HIT_SS && + p->ainsn.insn->word == breakpoint_insn.word) { + regs->cp0_status &= ~ST0_IE; + regs->cp0_status |= kcb->kprobe_saved_SR; + goto no_kprobe; + } + /* + * We have reentered the kprobe_handler(), since + * another probe was hit while within the handler. + * We here save the original kprobes variables and + * just single step on the instruction of the new probe + * without calling any user handlers. + */ + save_previous_kprobe(kcb); + set_current_kprobe(p, regs, kcb); + kprobes_inc_nmissed_count(p); + prepare_singlestep(p, regs); + kcb->kprobe_status = KPROBE_REENTER; + return 1; + } else { + if (addr->word != breakpoint_insn.word) { + /* + * The breakpoint instruction was removed by + * another cpu right after we hit, no further + * handling of this interrupt is appropriate + */ + ret = 1; + goto no_kprobe; + } + p = __get_cpu_var(current_kprobe); + if (p->break_handler && p->break_handler(p, regs)) + goto ss_probe; + } + goto no_kprobe; + } + + p = get_kprobe(addr); + if (!p) { + if (addr->word != breakpoint_insn.word) { + /* + * The breakpoint instruction was removed right + * after we hit it. Another cpu has removed + * either a probepoint or a debugger breakpoint + * at this address. In either case, no further + * handling of this interrupt is appropriate. + */ + ret = 1; + } + /* Not one of ours: let kernel handle it */ + goto no_kprobe; + } + + set_current_kprobe(p, regs, kcb); + kcb->kprobe_status = KPROBE_HIT_ACTIVE; + + if (p->pre_handler && p->pre_handler(p, regs)) { + /* handler has already set things up, so skip ss setup */ + return 1; + } + +ss_probe: + prepare_singlestep(p, regs); + kcb->kprobe_status = KPROBE_HIT_SS; + return 1; + +no_kprobe: + preempt_enable_no_resched(); + return ret; + +} + +/* + * Called after single-stepping. p->addr is the address of the + * instruction whose first byte has been replaced by the "break 0" + * instruction. To avoid the SMP problems that can occur when we + * temporarily put back the original opcode to single-step, we + * single-stepped a copy of the instruction. The address of this + * copy is p->ainsn.insn. + * + * This function prepares to return from the post-single-step + * breakpoint trap. + */ +static void __kprobes resume_execution(struct kprobe *p, + struct pt_regs *regs, + struct kprobe_ctlblk *kcb) +{ + unsigned long orig_epc = kcb->kprobe_saved_epc; + regs->cp0_epc = orig_epc + 4; +} + +static inline int post_kprobe_handler(struct pt_regs *regs) +{ + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (!cur) + return 0; + + if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) { + kcb->kprobe_status = KPROBE_HIT_SSDONE; + cur->post_handler(cur, regs, 0); + } + + resume_execution(cur, regs, kcb); + + regs->cp0_status |= kcb->kprobe_saved_SR; + + /* Restore back the original saved kprobes variables and continue. */ + if (kcb->kprobe_status == KPROBE_REENTER) { + restore_previous_kprobe(kcb); + goto out; + } + reset_current_kprobe(); +out: + preempt_enable_no_resched(); + + return 1; +} + +static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) +{ + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) + return 1; + + if (kcb->kprobe_status & KPROBE_HIT_SS) { + resume_execution(cur, regs, kcb); + regs->cp0_status |= kcb->kprobe_old_SR; + + reset_current_kprobe(); + preempt_enable_no_resched(); + } + return 0; +} + +/* + * Wrapper routine for handling exceptions. + */ +int __kprobes kprobe_exceptions_notify(struct notifier_block *self, + unsigned long val, void *data) +{ + + struct die_args *args = (struct die_args *)data; + int ret = NOTIFY_DONE; + + switch (val) { + case DIE_BREAK: + if (kprobe_handler(args->regs)) + ret = NOTIFY_STOP; + break; + case DIE_SSTEPBP: + if (post_kprobe_handler(args->regs)) + ret = NOTIFY_STOP; + break; + + case DIE_PAGE_FAULT: + /* kprobe_running() needs smp_processor_id() */ + preempt_disable(); + + if (kprobe_running() + && kprobe_fault_handler(args->regs, args->trapnr)) + ret = NOTIFY_STOP; + preempt_enable(); + break; + default: + break; + } + return ret; +} + +int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) +{ + struct jprobe *jp = container_of(p, struct jprobe, kp); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + kcb->jprobe_saved_regs = *regs; + kcb->jprobe_saved_sp = regs->regs[29]; + + memcpy(kcb->jprobes_stack, (void *)kcb->jprobe_saved_sp, + MIN_JPROBES_STACK_SIZE(kcb->jprobe_saved_sp)); + + regs->cp0_epc = (unsigned long)(jp->entry); + + return 1; +} + +/* Defined in the inline asm below. */ +void jprobe_return_end(void); + +void __kprobes jprobe_return(void) +{ + /* Assembler quirk necessitates this '0,code' business. */ + asm volatile( + "break 0,%0\n\t" + ".globl jprobe_return_end\n" + "jprobe_return_end:\n" + : : "n" (BRK_KPROBE_BP) : "memory"); +} + +int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) +{ + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (regs->cp0_epc >= (unsigned long)jprobe_return && + regs->cp0_epc <= (unsigned long)jprobe_return_end) { + *regs = kcb->jprobe_saved_regs; + memcpy((void *)kcb->jprobe_saved_sp, kcb->jprobes_stack, + MIN_JPROBES_STACK_SIZE(kcb->jprobe_saved_sp)); + preempt_enable_no_resched(); + + return 1; + } + return 0; +} + +/* + * Function return probe trampoline: + * - init_kprobes() establishes a probepoint here + * - When the probed function returns, this probe causes the + * handlers to fire + */ +static void __used kretprobe_trampoline_holder(void) +{ + asm volatile( + ".set push\n\t" + /* Keep the assembler from reordering and placing JR here. */ + ".set noreorder\n\t" + "nop\n\t" + ".global kretprobe_trampoline\n" + "kretprobe_trampoline:\n\t" + "nop\n\t" + ".set pop" + : : : "memory"); +} + +void kretprobe_trampoline(void); + +void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, + struct pt_regs *regs) +{ + ri->ret_addr = (kprobe_opcode_t *) regs->regs[31]; + + /* Replace the return addr with trampoline addr */ + regs->regs[31] = (unsigned long)kretprobe_trampoline; +} + +/* + * Called when the probe at kretprobe trampoline is hit + */ +static int __kprobes trampoline_probe_handler(struct kprobe *p, + struct pt_regs *regs) +{ + struct kretprobe_instance *ri = NULL; + struct hlist_head *head, empty_rp; + struct hlist_node *node, *tmp; + unsigned long flags, orig_ret_address = 0; + unsigned long trampoline_address = (unsigned long)kretprobe_trampoline; + + INIT_HLIST_HEAD(&empty_rp); + kretprobe_hash_lock(current, &head, &flags); + + /* + * It is possible to have multiple instances associated with a given + * task either because an multiple functions in the call path + * have a return probe installed on them, and/or more than one return + * return probe was registered for a target function. + * + * We can handle this because: + * - instances are always inserted at the head of the list + * - when multiple return probes are registered for the same + * function, the first instance's ret_addr will point to the + * real return address, and all the rest will point to + * kretprobe_trampoline + */ + hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { + if (ri->task != current) + /* another task is sharing our hash bucket */ + continue; + + if (ri->rp && ri->rp->handler) + ri->rp->handler(ri, regs); + + orig_ret_address = (unsigned long)ri->ret_addr; + recycle_rp_inst(ri, &empty_rp); + + if (orig_ret_address != trampoline_address) + /* + * This is the real return address. Any other + * instances associated with this task are for + * other calls deeper on the call stack + */ + break; + } + + kretprobe_assert(ri, orig_ret_address, trampoline_address); + instruction_pointer(regs) = orig_ret_address; + + reset_current_kprobe(); + kretprobe_hash_unlock(current, &flags); + preempt_enable_no_resched(); + + hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { + hlist_del(&ri->hlist); + kfree(ri); + } + /* + * By returning a non-zero value, we are telling + * kprobe_handler() that we don't want the post_handler + * to run (and have re-enabled preemption) + */ + return 1; +} + +int __kprobes arch_trampoline_kprobe(struct kprobe *p) +{ + if (p->addr == (kprobe_opcode_t *)kretprobe_trampoline) + return 1; + + return 0; +} + +static struct kprobe trampoline_p = { + .addr = (kprobe_opcode_t *)kretprobe_trampoline, + .pre_handler = trampoline_probe_handler +}; + +int __init arch_init_kprobes(void) +{ + return register_kprobe(&trampoline_p); +} diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 1515b67..4c6079f 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -334,7 +335,7 @@ void show_regs(struct pt_regs *regs) __show_regs((struct pt_regs *)regs); } -void show_registers(const struct pt_regs *regs) +void show_registers(struct pt_regs *regs) { const int field = 2 * sizeof(unsigned long); @@ -783,6 +784,25 @@ asmlinkage void do_bp(struct pt_regs *regs) if (bcode >= (1 << 10)) bcode >>= 10; + /* + * notify the kprobe handlers, if instruction is likely to + * pertain to them. + */ + switch (bcode) { + case BRK_KPROBE_BP: + if (notify_die(DIE_BREAK, "debug", regs, bcode, 0, 0) == NOTIFY_STOP) + return; + else + break; + case BRK_KPROBE_SSTEPBP: + if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode, 0, 0) == NOTIFY_STOP) + return; + else + break; + default: + break; + } + do_trap_or_bp(regs, bcode, "Break"); return; diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index b4aac42..783ad00 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -24,13 +25,14 @@ #include #include #include /* For VMALLOC_END */ +#include /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate * routines. */ -asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, +asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long write, unsigned long address) { struct vm_area_struct * vma = NULL; @@ -46,6 +48,17 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, field, regs->cp0_epc); #endif +#ifdef CONFIG_KPROBES + /* + * This is to notify the fault handler of the kprobes. The + * exception code is redundant as it is also carried in REGS, + * but we pass it anyhow. + */ + if (notify_die(DIE_PAGE_FAULT, "page fault", regs, -1, + (regs->cp0_cause >> 2) & 0x1f, SIGSEGV) == NOTIFY_STOP) + return; +#endif + info.si_code = SEGV_MAPERR; /* -- cgit v0.10.2 From 8a1492370b493cf680b86885286f07cb9b967716 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 3 Aug 2010 11:22:21 -0700 Subject: SAMPLES: kprobe_example: Make it print something on MIPS. This KProbes example is a little useless if it doesn't print anything. For MIPS print similar messages to those produced on x86 and PPC. Signed-off-by: David Daney To: linux-mips@linux-mips.org To: ananth@in.ibm.com To: anil.s.keshavamurthy@intel.com To: davem@davemloft.net To: masami.hiramatsu.pt@hitachi.com Cc: linux-kernel@vger.kernel.org Cc: hschauhan@nulltrace.org Patchwork: https://patchwork.linux-mips.org/patch/1528/ Signed-off-by: Ralf Baechle diff --git a/samples/kprobes/kprobe_example.c b/samples/kprobes/kprobe_example.c index a681998..ebf5e0c 100644 --- a/samples/kprobes/kprobe_example.c +++ b/samples/kprobes/kprobe_example.c @@ -32,6 +32,11 @@ static int handler_pre(struct kprobe *p, struct pt_regs *regs) " msr = 0x%lx\n", p->addr, regs->nip, regs->msr); #endif +#ifdef CONFIG_MIPS + printk(KERN_INFO "pre_handler: p->addr = 0x%p, epc = 0x%lx," + " status = 0x%lx\n", + p->addr, regs->cp0_epc, regs->cp0_status); +#endif /* A dump_stack() here will give a stack backtrace */ return 0; @@ -49,6 +54,10 @@ static void handler_post(struct kprobe *p, struct pt_regs *regs, printk(KERN_INFO "post_handler: p->addr = 0x%p, msr = 0x%lx\n", p->addr, regs->msr); #endif +#ifdef CONFIG_MIPS + printk(KERN_INFO "post_handler: p->addr = 0x%p, status = 0x%lx\n", + p->addr, regs->cp0_status); +#endif } /* -- cgit v0.10.2 From 9bb4d9dfd890372092338cc460b3f921c8be8e31 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 3 Aug 2010 11:22:22 -0700 Subject: Documentation: Mention that KProbes is supported on MIPS MIPS now has KProbes support, so kprobes.txt should reflect it. Signed-off-by: David Daney To: linux-mips@linux-mips.org To: ananth@in.ibm.com To: anil.s.keshavamurthy@intel.com To: davem@davemloft.net To: masami.hiramatsu.pt@hitachi.com Cc: linux-kernel@vger.kernel.org Cc: hschauhan@nulltrace.org Patchwork: https://patchwork.linux-mips.org/patch/1527/ Signed-off-by: Ralf Baechle diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt index 6653017..1762b81 100644 --- a/Documentation/kprobes.txt +++ b/Documentation/kprobes.txt @@ -285,6 +285,7 @@ architectures: - sparc64 (Return probes not yet implemented.) - arm - ppc +- mips 3. Configuring Kprobes -- cgit v0.10.2 From 7281cd22973008a782860e48ed8d85d00204168c Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 3 Aug 2010 14:57:39 -0700 Subject: MIPS: Remove unused task_struct.trap_no field. It is initialized to zero and only ever read. Remove it, and pass zero in its place. Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1531/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index 24d91f8..0d629bb 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -229,7 +229,6 @@ struct thread_struct { unsigned long cp0_badvaddr; /* Last user fault */ unsigned long cp0_baduaddr; /* Last kernel fault accessing USEG */ unsigned long error_code; - unsigned long trap_no; unsigned long irix_trampoline; /* Wheee... */ unsigned long irix_oldctx; #ifdef CONFIG_CPU_CAVIUM_OCTEON @@ -301,7 +300,6 @@ struct thread_struct { .cp0_badvaddr = 0, \ .cp0_baduaddr = 0, \ .error_code = 0, \ - .trap_no = 0, \ .irix_trampoline = 0, \ .irix_oldctx = 0, \ /* \ diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index ca6c832..6b30fb2 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -126,7 +126,6 @@ void output_thread_defines(void) thread.cp0_baduaddr); OFFSET(THREAD_ECODE, task_struct, \ thread.error_code); - OFFSET(THREAD_TRAPNO, task_struct, thread.trap_no); OFFSET(THREAD_TRAMP, task_struct, \ thread.irix_trampoline); OFFSET(THREAD_OLDCTX, task_struct, \ diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 4c6079f..6019e9e 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -376,7 +376,7 @@ void __noreturn die(const char * str, struct pt_regs * regs) mips_mt_regdump(dvpret); #endif /* CONFIG_MIPS_MT_SMTC */ - if (notify_die(DIE_OOPS, str, regs, 0, current->thread.trap_no, SIGSEGV) == NOTIFY_STOP) + if (notify_die(DIE_OOPS, str, regs, 0, 0, SIGSEGV) == NOTIFY_STOP) sig = 0; printk("%s[#%d]:\n", str, ++die_counter); -- cgit v0.10.2 From 70dc6f045fce6907b5d10377850a78ada6837ffb Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 3 Aug 2010 15:44:43 -0700 Subject: MIPS: Clean up notify_die() usage. The sixth argument of notify_die() is a signal number, the fifth is a trap number. Instead of passing a signal number in a randomly selected argument, pass it in the sixth. Extract the exception code from regs and pass that as the trap number. Get rid of redundant cast, and remove some gratuitous spaces. Nobody actually does anything with the signal number or trap number, but we might as well populate them with sensible values. Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1532/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 6019e9e..03ec001 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -357,9 +357,14 @@ void show_registers(struct pt_regs *regs) printk("\n"); } +static int regs_to_trapnr(struct pt_regs *regs) +{ + return (regs->cp0_cause >> 2) & 0x1f; +} + static DEFINE_SPINLOCK(die_lock); -void __noreturn die(const char * str, struct pt_regs * regs) +void __noreturn die(const char *str, struct pt_regs *regs) { static int die_counter; int sig = SIGSEGV; @@ -367,7 +372,7 @@ void __noreturn die(const char * str, struct pt_regs * regs) unsigned long dvpret = dvpe(); #endif /* CONFIG_MIPS_MT_SMTC */ - notify_die(DIE_OOPS, str, (struct pt_regs *)regs, SIGSEGV, 0, 0); + notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV); console_verbose(); spin_lock_irq(&die_lock); @@ -376,7 +381,7 @@ void __noreturn die(const char * str, struct pt_regs * regs) mips_mt_regdump(dvpret); #endif /* CONFIG_MIPS_MT_SMTC */ - if (notify_die(DIE_OOPS, str, regs, 0, 0, SIGSEGV) == NOTIFY_STOP) + if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV) == NOTIFY_STOP) sig = 0; printk("%s[#%d]:\n", str, ++die_counter); @@ -450,7 +455,7 @@ asmlinkage void do_be(struct pt_regs *regs) printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n", data ? "Data" : "Instruction", field, regs->cp0_epc, field, regs->regs[31]); - if (notify_die(DIE_OOPS, "bus error", regs, SIGBUS, 0, 0) + if (notify_die(DIE_OOPS, "bus error", regs, 0, regs_to_trapnr(regs), SIGBUS) == NOTIFY_STOP) return; @@ -651,7 +656,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) { siginfo_t info; - if (notify_die(DIE_FP, "FP exception", regs, SIGFPE, 0, 0) + if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE) == NOTIFY_STOP) return; die_if_kernel("FP exception in kernel code", regs); @@ -714,11 +719,11 @@ static void do_trap_or_bp(struct pt_regs *regs, unsigned int code, char b[40]; #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP - if (kgdb_ll_trap(DIE_TRAP, str, regs, code, 0, 0) == NOTIFY_STOP) + if (kgdb_ll_trap(DIE_TRAP, str, regs, code, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) return; #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ - if (notify_die(DIE_TRAP, str, regs, code, 0, 0) == NOTIFY_STOP) + if (notify_die(DIE_TRAP, str, regs, code, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) return; /* @@ -790,12 +795,12 @@ asmlinkage void do_bp(struct pt_regs *regs) */ switch (bcode) { case BRK_KPROBE_BP: - if (notify_die(DIE_BREAK, "debug", regs, bcode, 0, 0) == NOTIFY_STOP) + if (notify_die(DIE_BREAK, "debug", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) return; else break; case BRK_KPROBE_SSTEPBP: - if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode, 0, 0) == NOTIFY_STOP) + if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) return; else break; @@ -835,7 +840,7 @@ asmlinkage void do_ri(struct pt_regs *regs) unsigned int opcode = 0; int status = -1; - if (notify_die(DIE_RI, "RI Fault", regs, SIGSEGV, 0, 0) + if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs), SIGILL) == NOTIFY_STOP) return; -- cgit v0.10.2 From 2b5987abaf2dd6c3934e0376b7d9f64411cdcf03 Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 4 Aug 2010 14:53:57 -0700 Subject: MIPS: Octeon: Allow more than 3.75GB of memory with PCIe We reserve the 3.75GB - 4GB region of PCIe address space for device to device transfers, making the corresponding physical memory under direct mapping unavailable for DMA. To allow for PCIe DMA to all physical memory we map this chunk of physical memory with BAR1. Because of the resulting discontinuity in the mapping function, we remove a page of memory at each end of the range so multi-page DMA buffers can never be allocated that span the range. Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1535/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c index be531ec..d22b5a2 100644 --- a/arch/mips/cavium-octeon/dma-octeon.c +++ b/arch/mips/cavium-octeon/dma-octeon.c @@ -99,13 +99,16 @@ dma_addr_t octeon_map_dma_mem(struct device *dev, void *ptr, size_t size) panic("dma_map_single: " "Attempt to map illegal memory address 0x%llx\n", physical); - else if ((physical + size >= - (4ull<<30) - (OCTEON_PCI_BAR1_HOLE_SIZE<<20)) - && physical < (4ull<<30)) - pr_warning("dma_map_single: Warning: " - "Mapping memory address that might " - "conflict with devices 0x%llx-0x%llx\n", - physical, physical+size-1); + else if (physical >= CVMX_PCIE_BAR1_PHYS_BASE && + physical + size < (CVMX_PCIE_BAR1_PHYS_BASE + CVMX_PCIE_BAR1_PHYS_SIZE)) { + result = physical - CVMX_PCIE_BAR1_PHYS_BASE + CVMX_PCIE_BAR1_RC_BASE; + + if (((result+size-1) & dma_mask) != result+size-1) + panic("dma_map_single: Attempt to map address 0x%llx-0x%llx, which can't be accessed according to the dma mask 0x%llx\n", + physical, physical+size-1, dma_mask); + goto done; + } + /* The 2nd 256MB is mapped at 256<<20 instead of 0x410000000 */ if ((physical >= 0x410000000ull) && physical < 0x420000000ull) result = physical - 0x400000000ull; diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 041326e..69197cb 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -32,6 +32,7 @@ #include #include +#include #ifdef CONFIG_CAVIUM_DECODE_RSL extern void cvmx_interrupt_rsl_decode(void); @@ -609,6 +610,22 @@ void __init prom_init(void) register_smp_ops(&octeon_smp_ops); } +/* Exclude a single page from the regions obtained in plat_mem_setup. */ +static __init void memory_exclude_page(u64 addr, u64 *mem, u64 *size) +{ + if (addr > *mem && addr < *mem + *size) { + u64 inc = addr - *mem; + add_memory_region(*mem, inc, BOOT_MEM_RAM); + *mem += inc; + *size -= inc; + } + + if (addr == *mem && *size > PAGE_SIZE) { + *mem += PAGE_SIZE; + *size -= PAGE_SIZE; + } +} + void __init plat_mem_setup(void) { uint64_t mem_alloc_size; @@ -659,12 +676,27 @@ void __init plat_mem_setup(void) CVMX_BOOTMEM_FLAG_NO_LOCKING); #endif if (memory >= 0) { + u64 size = mem_alloc_size; + + /* + * exclude a page at the beginning and end of + * the 256MB PCIe 'hole' so the kernel will not + * try to allocate multi-page buffers that + * span the discontinuity. + */ + memory_exclude_page(CVMX_PCIE_BAR1_PHYS_BASE, + &memory, &size); + memory_exclude_page(CVMX_PCIE_BAR1_PHYS_BASE + + CVMX_PCIE_BAR1_PHYS_SIZE, + &memory, &size); + /* * This function automatically merges address * regions next to each other if they are * received in incrementing order. */ - add_memory_region(memory, mem_alloc_size, BOOT_MEM_RAM); + if (size) + add_memory_region(memory, size, BOOT_MEM_RAM); total += mem_alloc_size; } else { break; diff --git a/arch/mips/include/asm/octeon/pci-octeon.h b/arch/mips/include/asm/octeon/pci-octeon.h index 6ac5d3e..ece7804 100644 --- a/arch/mips/include/asm/octeon/pci-octeon.h +++ b/arch/mips/include/asm/octeon/pci-octeon.h @@ -15,6 +15,19 @@ #define PCI_CONFIG_SPACE_DELAY 10000 /* + * The physical memory base mapped by BAR1. 256MB at the end of the + * first 4GB. + */ +#define CVMX_PCIE_BAR1_PHYS_BASE ((1ull << 32) - (1ull << 28)) +#define CVMX_PCIE_BAR1_PHYS_SIZE (1ull << 28) + +/* + * The RC base of BAR1. gen1 has a 39-bit BAR2, gen2 has 41-bit BAR2, + * place BAR1 so it is the same for both. + */ +#define CVMX_PCIE_BAR1_RC_BASE (1ull << 41) + +/* * pcibios_map_irq() is defined inside pci-octeon.c. All it does is * call the Octeon specific version pointed to by this variable. This * function needs to change for PCI or PCIe based hosts. diff --git a/arch/mips/pci/pcie-octeon.c b/arch/mips/pci/pcie-octeon.c index 6aa5c54..861361e 100644 --- a/arch/mips/pci/pcie-octeon.c +++ b/arch/mips/pci/pcie-octeon.c @@ -402,6 +402,10 @@ static void __cvmx_pcie_rc_initialize_config_space(int pcie_port) npei_ctl_status2.s.mps = 0; /* Max read request size = 128 bytes for best Octeon DMA performance */ npei_ctl_status2.s.mrrs = 0; + if (pcie_port) + npei_ctl_status2.s.c1_b1_s = 3; /* Port1 BAR1 Size 256MB */ + else + npei_ctl_status2.s.c0_b1_s = 3; /* Port0 BAR1 Size 256MB */ cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS2, npei_ctl_status2.u64); /* ECRC Generation (PCIE*_CFG070[GE,CE]) */ @@ -666,6 +670,8 @@ static int __cvmx_pcie_rc_initialize_link(int pcie_port) static int cvmx_pcie_rc_initialize(int pcie_port) { int i; + int base; + u64 addr_swizzle; union cvmx_ciu_soft_prst ciu_soft_prst; union cvmx_pescx_bist_status pescx_bist_status; union cvmx_pescx_bist_status2 pescx_bist_status2; @@ -674,6 +680,7 @@ static int cvmx_pcie_rc_initialize(int pcie_port) union cvmx_npei_mem_access_subidx mem_access_subid; union cvmx_npei_dbg_data npei_dbg_data; union cvmx_pescx_ctl_status2 pescx_ctl_status2; + union cvmx_npei_bar1_indexx bar1_index; /* * Make sure we aren't trying to setup a target mode interface @@ -918,12 +925,30 @@ static int cvmx_pcie_rc_initialize(int pcie_port) /* Set Octeon's BAR0 to decode 0-16KB. It overlaps with Bar2 */ cvmx_write_csr(CVMX_PESCX_P2N_BAR0_START(pcie_port), 0); - /* - * Disable Octeon's BAR1. It isn't needed in RC mode since - * BAR2 maps all of memory. BAR2 also maps 256MB-512MB into - * the 2nd 256MB of memory. - */ - cvmx_write_csr(CVMX_PESCX_P2N_BAR1_START(pcie_port), -1); + /* BAR1 follows BAR2 with a gap. */ + cvmx_write_csr(CVMX_PESCX_P2N_BAR1_START(pcie_port), CVMX_PCIE_BAR1_RC_BASE); + + bar1_index.u32 = 0; + bar1_index.s.addr_idx = (CVMX_PCIE_BAR1_PHYS_BASE >> 22); + bar1_index.s.ca = 1; /* Not Cached */ + bar1_index.s.end_swp = 1; /* Endian Swap mode */ + bar1_index.s.addr_v = 1; /* Valid entry */ + + base = pcie_port ? 16 : 0; + + /* Big endian swizzle for 32-bit PEXP_NCB register. */ +#ifdef __MIPSEB__ + addr_swizzle = 4; +#else + addr_swizzle = 0; +#endif + for (i = 0; i < 16; i++) { + cvmx_write64_uint32((CVMX_PEXP_NPEI_BAR1_INDEXX(base) ^ addr_swizzle), + bar1_index.u32); + base++; + /* 256MB / 16 >> 22 == 4 */ + bar1_index.s.addr_idx += (((1ull << 28) / 16ull) >> 22); + } /* * Set Octeon's BAR2 to decode 0-2^39. Bar0 and Bar1 take -- cgit v0.10.2 From 47a348614492987ef307aad299c09163344e4eaf Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Mon, 2 Aug 2010 23:56:22 +0200 Subject: MIPS: BCM47xx: Fix nvram_getenv return value. Nvram_getenv should behave like cfe_getenv. cfe_getenv returns 0 on success and -9 if the value was not found. If the input was wrong -8 will be returned by cfe_getenv. Change nvram_getenv to do the same. Signed-off-by: Hauke Mehrtens Cc: Waldemar Brodkorb Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1520/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c index 06e03b2..e5b6615 100644 --- a/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c @@ -69,7 +69,7 @@ int nvram_getenv(char *name, char *val, size_t val_len) char *var, *value, *end, *eq; if (!name) - return 1; + return NVRAM_ERR_INV_PARAM; if (!nvram_buf[0]) early_nvram_init(); @@ -89,6 +89,6 @@ int nvram_getenv(char *name, char *val, size_t val_len) return 0; } } - return 1; + return NVRAM_ERR_ENVNOTFOUND; } EXPORT_SYMBOL(nvram_getenv); diff --git a/arch/mips/include/asm/mach-bcm47xx/nvram.h b/arch/mips/include/asm/mach-bcm47xx/nvram.h index 0d8cc14..c58ebd8 100644 --- a/arch/mips/include/asm/mach-bcm47xx/nvram.h +++ b/arch/mips/include/asm/mach-bcm47xx/nvram.h @@ -31,6 +31,9 @@ struct nvram_header { #define NVRAM_MAX_VALUE_LEN 255 #define NVRAM_MAX_PARAM_LEN 64 +#define NVRAM_ERR_INV_PARAM -8 +#define NVRAM_ERR_ENVNOTFOUND -9 + extern int nvram_getenv(char *name, char *val, size_t val_len); #endif -- cgit v0.10.2 From 51f1336d4dbd0935d873761f7f267c3f5abc9bd6 Mon Sep 17 00:00:00 2001 From: David VomLehn Date: Mon, 2 Aug 2010 11:44:00 -0700 Subject: MIPS: PowerTV: Add Gaia platform definitions. Define ASIC address, memory preallocations, and initialization code for the Gaia platform. Signed-off-by: David VomLehn To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1519/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-powertv/asic.h b/arch/mips/include/asm/mach-powertv/asic.h index bcad43a..df33d93 100644 --- a/arch/mips/include/asm/mach-powertv/asic.h +++ b/arch/mips/include/asm/mach-powertv/asic.h @@ -40,19 +40,23 @@ enum family_type { FAMILY_8600VZB, FAMILY_1500VZE, FAMILY_1500VZF, + FAMILY_8700, FAMILIES }; /* Register maps for each ASIC */ extern const struct register_map calliope_register_map; extern const struct register_map cronus_register_map; +extern const struct register_map gaia_register_map; extern const struct register_map zeus_register_map; extern struct resource dvr_cronus_resources[]; +extern struct resource dvr_gaia_resources[]; extern struct resource dvr_zeus_resources[]; extern struct resource non_dvr_calliope_resources[]; extern struct resource non_dvr_cronus_resources[]; extern struct resource non_dvr_cronuslite_resources[]; +extern struct resource non_dvr_gaia_resources[]; extern struct resource non_dvr_vz_calliope_resources[]; extern struct resource non_dvr_vze_calliope_resources[]; extern struct resource non_dvr_vzf_calliope_resources[]; diff --git a/arch/mips/include/asm/mach-powertv/asic_regs.h b/arch/mips/include/asm/mach-powertv/asic_regs.h index 1e11236..2657ae6 100644 --- a/arch/mips/include/asm/mach-powertv/asic_regs.h +++ b/arch/mips/include/asm/mach-powertv/asic_regs.h @@ -27,7 +27,8 @@ enum asic_type { ASIC_CALLIOPE, ASIC_CRONUS, ASIC_CRONUSLITE, - ASICS + ASIC_GAIA, + ASICS /* Number of supported ASICs */ }; /* hardcoded values read from Chip Version registers */ @@ -37,6 +38,7 @@ enum asic_type { #define NAND_FLASH_BASE 0x03000000 #define CALLIOPE_IO_BASE 0x08000000 +#define GAIA_IO_BASE 0x09000000 #define CRONUS_IO_BASE 0x09000000 #define ZEUS_IO_BASE 0x09000000 diff --git a/arch/mips/powertv/asic/Makefile b/arch/mips/powertv/asic/Makefile index bebfdcf..f0e95dc 100644 --- a/arch/mips/powertv/asic/Makefile +++ b/arch/mips/powertv/asic/Makefile @@ -16,8 +16,8 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -obj-y += asic-calliope.o asic-cronus.o asic-zeus.o asic_devices.o asic_int.o \ - irq_asic.o prealloc-calliope.o prealloc-cronus.o \ - prealloc-cronuslite.o prealloc-zeus.o +obj-y += asic-calliope.o asic-cronus.o asic-gaia.o asic-zeus.o \ + asic_devices.o asic_int.o irq_asic.o prealloc-calliope.o \ + prealloc-cronus.o prealloc-cronuslite.o prealloc-gaia.o prealloc-zeus.o EXTRA_CFLAGS += -Wall -Werror diff --git a/arch/mips/powertv/asic/asic-gaia.c b/arch/mips/powertv/asic/asic-gaia.c new file mode 100644 index 0000000..91dda68 --- /dev/null +++ b/arch/mips/powertv/asic/asic-gaia.c @@ -0,0 +1,96 @@ +/* + * Locations of devices in the Gaia ASIC + * + * Copyright (C) 2005-2009 Scientific-Atlanta, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: David VomLehn + */ + +#include +#include + +const struct register_map gaia_register_map __initdata = { + .eic_slow0_strt_add = {.phys = GAIA_IO_BASE + 0x000000}, + .eic_cfg_bits = {.phys = GAIA_IO_BASE + 0x000038}, + .eic_ready_status = {.phys = GAIA_IO_BASE + 0x00004C}, + + .chipver3 = {.phys = GAIA_IO_BASE + 0x2A0800}, + .chipver2 = {.phys = GAIA_IO_BASE + 0x2A0804}, + .chipver1 = {.phys = GAIA_IO_BASE + 0x2A0808}, + .chipver0 = {.phys = GAIA_IO_BASE + 0x2A080C}, + + /* The registers of IRBlaster */ + .uart1_intstat = {.phys = GAIA_IO_BASE + 0x2A1800}, + .uart1_inten = {.phys = GAIA_IO_BASE + 0x2A1804}, + .uart1_config1 = {.phys = GAIA_IO_BASE + 0x2A1808}, + .uart1_config2 = {.phys = GAIA_IO_BASE + 0x2A180C}, + .uart1_divisorhi = {.phys = GAIA_IO_BASE + 0x2A1810}, + .uart1_divisorlo = {.phys = GAIA_IO_BASE + 0x2A1814}, + .uart1_data = {.phys = GAIA_IO_BASE + 0x2A1818}, + .uart1_status = {.phys = GAIA_IO_BASE + 0x2A181C}, + + .int_stat_3 = {.phys = GAIA_IO_BASE + 0x2A2800}, + .int_stat_2 = {.phys = GAIA_IO_BASE + 0x2A2804}, + .int_stat_1 = {.phys = GAIA_IO_BASE + 0x2A2808}, + .int_stat_0 = {.phys = GAIA_IO_BASE + 0x2A280C}, + .int_config = {.phys = GAIA_IO_BASE + 0x2A2810}, + .int_int_scan = {.phys = GAIA_IO_BASE + 0x2A2818}, + .ien_int_3 = {.phys = GAIA_IO_BASE + 0x2A2830}, + .ien_int_2 = {.phys = GAIA_IO_BASE + 0x2A2834}, + .ien_int_1 = {.phys = GAIA_IO_BASE + 0x2A2838}, + .ien_int_0 = {.phys = GAIA_IO_BASE + 0x2A283C}, + .int_level_3_3 = {.phys = GAIA_IO_BASE + 0x2A2880}, + .int_level_3_2 = {.phys = GAIA_IO_BASE + 0x2A2884}, + .int_level_3_1 = {.phys = GAIA_IO_BASE + 0x2A2888}, + .int_level_3_0 = {.phys = GAIA_IO_BASE + 0x2A288C}, + .int_level_2_3 = {.phys = GAIA_IO_BASE + 0x2A2890}, + .int_level_2_2 = {.phys = GAIA_IO_BASE + 0x2A2894}, + .int_level_2_1 = {.phys = GAIA_IO_BASE + 0x2A2898}, + .int_level_2_0 = {.phys = GAIA_IO_BASE + 0x2A289C}, + .int_level_1_3 = {.phys = GAIA_IO_BASE + 0x2A28A0}, + .int_level_1_2 = {.phys = GAIA_IO_BASE + 0x2A28A4}, + .int_level_1_1 = {.phys = GAIA_IO_BASE + 0x2A28A8}, + .int_level_1_0 = {.phys = GAIA_IO_BASE + 0x2A28AC}, + .int_level_0_3 = {.phys = GAIA_IO_BASE + 0x2A28B0}, + .int_level_0_2 = {.phys = GAIA_IO_BASE + 0x2A28B4}, + .int_level_0_1 = {.phys = GAIA_IO_BASE + 0x2A28B8}, + .int_level_0_0 = {.phys = GAIA_IO_BASE + 0x2A28BC}, + .int_docsis_en = {.phys = GAIA_IO_BASE + 0x2A28F4}, + + .mips_pll_setup = {.phys = GAIA_IO_BASE + 0x1C0000}, + .fs432x4b4_usb_ctl = {.phys = GAIA_IO_BASE + 0x1C0024}, + .test_bus = {.phys = GAIA_IO_BASE + 0x1C00CC}, + .crt_spare = {.phys = GAIA_IO_BASE + 0x1c0108}, + .usb2_ohci_int_mask = {.phys = GAIA_IO_BASE + 0x20000C}, + .usb2_strap = {.phys = GAIA_IO_BASE + 0x200014}, + .ehci_hcapbase = {.phys = GAIA_IO_BASE + 0x21FE00}, + .ohci_hc_revision = {.phys = GAIA_IO_BASE + 0x21fc00}, + .bcm1_bs_lmi_steer = {.phys = GAIA_IO_BASE + 0x2E0004}, + .usb2_control = {.phys = GAIA_IO_BASE + 0x2E004C}, + .usb2_stbus_obc = {.phys = GAIA_IO_BASE + 0x21FF00}, + .usb2_stbus_mess_size = {.phys = GAIA_IO_BASE + 0x21FF04}, + .usb2_stbus_chunk_size = {.phys = GAIA_IO_BASE + 0x21FF08}, + + .pcie_regs = {.phys = GAIA_IO_BASE + 0x220000}, + .tim_ch = {.phys = GAIA_IO_BASE + 0x2A2C10}, + .tim_cl = {.phys = GAIA_IO_BASE + 0x2A2C14}, + .gpio_dout = {.phys = GAIA_IO_BASE + 0x2A2C20}, + .gpio_din = {.phys = GAIA_IO_BASE + 0x2A2C24}, + .gpio_dir = {.phys = GAIA_IO_BASE + 0x2A2C2C}, + .watchdog = {.phys = GAIA_IO_BASE + 0x2A2C30}, + .front_panel = {.phys = GAIA_IO_BASE + 0x2A3800}, +}; diff --git a/arch/mips/powertv/asic/asic_devices.c b/arch/mips/powertv/asic/asic_devices.c index 006285c..095a887 100644 --- a/arch/mips/powertv/asic/asic_devices.c +++ b/arch/mips/powertv/asic/asic_devices.c @@ -1,7 +1,6 @@ /* - * ASIC Device List Intialization * - * Description: Defines the platform resources for the SA settop. + * Description: Defines the platform resources for Gaia-based settops. * * Copyright (C) 2005-2009 Scientific-Atlanta, Inc. * @@ -19,11 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * - * Author: Ken Eppinett - * David Schleef - * - * Description: Defines the platform resources for the SA settop. - * * NOTE: The bootloader allocates persistent memory at an address which is * 16 MiB below the end of the highest address in KSEG0. All fixed * address memory reservations must avoid this region. @@ -289,6 +283,9 @@ static __init noinline void platform_set_family(void) case BOOTLDRFAMILY('F', '1'): platform_family = FAMILY_1500VZF; break; + case BOOTLDRFAMILY('8', '7'): + platform_family = FAMILY_8700; + break; default: platform_family = -1; } @@ -526,6 +523,15 @@ void __init configure_platform(void) "DVR_CAPABLE\n"); break; + case FAMILY_8700: + platform_features = FFS_CAPABLE | PCIE_CAPABLE; + asic = ASIC_GAIA; + set_register_map(GAIA_IO_BASE, &gaia_register_map); + gp_resources = dvr_gaia_resources; + + pr_info("Platform: 8700 - GAIA, DVR_CAPABLE\n"); + break; + default: pr_crit("Platform: UNKNOWN PLATFORM\n"); break; diff --git a/arch/mips/powertv/asic/prealloc-gaia.c b/arch/mips/powertv/asic/prealloc-gaia.c new file mode 100644 index 0000000..8ac8c7a --- /dev/null +++ b/arch/mips/powertv/asic/prealloc-gaia.c @@ -0,0 +1,589 @@ +/* + * Memory pre-allocations for Gaia boxes. + * + * Copyright (C) 2005-2009 Scientific-Atlanta, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: David VomLehn + */ + +#include +#include + +/* + * DVR_CAPABLE GAIA RESOURCES + */ +struct resource dvr_gaia_resources[] __initdata = { + /* + * + * VIDEO1 / LX1 + * + */ + { + .name = "ST231aImage", /* Delta-Mu 1 image and ram */ + .start = 0x24000000, + .end = 0x241FFFFF, /* 2MiB */ + .flags = IORESOURCE_MEM, + }, + { + .name = "ST231aMonitor", /* 8KiB block ST231a monitor */ + .start = 0x24200000, + .end = 0x24201FFF, + .flags = IORESOURCE_MEM, + }, + { + .name = "MediaMemory1", + .start = 0x24202000, + .end = 0x25FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */ + .flags = IORESOURCE_MEM, + }, + /* + * + * VIDEO2 / LX2 + * + */ + { + .name = "ST231bImage", /* Delta-Mu 2 image and ram */ + .start = 0x60000000, + .end = 0x601FFFFF, /* 2MiB */ + .flags = IORESOURCE_IO, + }, + { + .name = "ST231bMonitor", /* 8KiB block ST231b monitor */ + .start = 0x60200000, + .end = 0x60201FFF, + .flags = IORESOURCE_IO, + }, + { + .name = "MediaMemory2", + .start = 0x60202000, + .end = 0x61FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */ + .flags = IORESOURCE_IO, + }, + /* + * + * Sysaudio Driver + * + * This driver requires: + * + * Arbitrary Based Buffers: + * DSP_Image_Buff - DSP code and data images (1MB) + * ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB) + * ADSC_AUX_Buff - ADSC AUX buffer (16KB) + * ADSC_Main_Buff - ADSC Main buffer (16KB) + * + */ + { + .name = "DSP_Image_Buff", + .start = 0x00000000, + .end = 0x000FFFFF, + .flags = IORESOURCE_MEM, + }, + { + .name = "ADSC_CPU_PCM_Buff", + .start = 0x00000000, + .end = 0x00009FFF, + .flags = IORESOURCE_MEM, + }, + { + .name = "ADSC_AUX_Buff", + .start = 0x00000000, + .end = 0x00003FFF, + .flags = IORESOURCE_MEM, + }, + { + .name = "ADSC_Main_Buff", + .start = 0x00000000, + .end = 0x00003FFF, + .flags = IORESOURCE_MEM, + }, + /* + * + * STAVEM driver/STAPI + * + * This driver requires: + * + * Arbitrary Based Buffers: + * This memory area is used for allocating buffers for Video decoding + * purposes. Allocation/De-allocation within this buffer is managed + * by the STAVMEM driver of the STAPI. They could be Decimated + * Picture Buffers, Intermediate Buffers, as deemed necessary for + * video decoding purposes, for any video decoders on Zeus. + * + */ + { + .name = "AVMEMPartition0", + .start = 0x63580000, + .end = 0x64180000 - 1, /* 12 MB total */ + .flags = IORESOURCE_IO, + }, + /* + * + * DOCSIS Subsystem + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Docsis - + * + */ + { + .name = "Docsis", + .start = 0x62000000, + .end = 0x62700000 - 1, /* 7 MB total */ + .flags = IORESOURCE_IO, + }, + /* + * + * GHW HAL Driver + * + * This driver requires: + * + * Arbitrary Based Buffers: + * GraphicsHeap - PowerTV Graphics Heap + * + */ + { + .name = "GraphicsHeap", + .start = 0x62700000, + .end = 0x63500000 - 1, /* 14 MB total */ + .flags = IORESOURCE_IO, + }, + /* + * + * multi com buffer area + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Docsis - + * + */ + { + .name = "MulticomSHM", + .start = 0x26000000, + .end = 0x26020000 - 1, + .flags = IORESOURCE_MEM, + }, + /* + * + * DMA Ring buffer + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Docsis - + * + */ + { + .name = "BMM_Buffer", + .start = 0x00000000, + .end = 0x00280000 - 1, + .flags = IORESOURCE_MEM, + }, + /* + * + * Display bins buffer for unit0 + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Display Bins for unit0 + * + */ + { + .name = "DisplayBins0", + .start = 0x00000000, + .end = 0x00000FFF, /* 4 KB total */ + .flags = IORESOURCE_MEM, + }, + /* + * + * Display bins buffer + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Display Bins for unit1 + * + */ + { + .name = "DisplayBins1", + .start = 0x64AD4000, + .end = 0x64AD5000 - 1, /* 4 KB total */ + .flags = IORESOURCE_IO, + }, + /* + * + * ITFS + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Docsis - + * + */ + { + .name = "ITFS", + .start = 0x64180000, + /* 815,104 bytes each for 2 ITFS partitions. */ + .end = 0x6430DFFF, + .flags = IORESOURCE_IO, + }, + /* + * + * AVFS + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Docsis - + * + */ + { + .name = "AvfsDmaMem", + .start = 0x6430E000, + /* (945K * 8) = (128K *3) 5 playbacks / 3 server */ + .end = 0x64AD0000 - 1, + .flags = IORESOURCE_IO, + }, + { + .name = "AvfsFileSys", + .start = 0x64AD0000, + .end = 0x64AD1000 - 1, /* 4K */ + .flags = IORESOURCE_IO, + }, + /* + * + * Smartcard + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Read and write buffers for Internal/External cards + * + */ + { + .name = "SmartCardInfo", + .start = 0x64AD1000, + .end = 0x64AD3800 - 1, + .flags = IORESOURCE_IO, + }, + /* + * + * KAVNET + * NP Reset Vector - must be of the form xxCxxxxx + * NP Image - must be video bank 1 + * NP IPC - must be video bank 2 + */ + { + .name = "NP_Reset_Vector", + .start = 0x27c00000, + .end = 0x27c01000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "NP_Image", + .start = 0x27020000, + .end = 0x27060000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "NP_IPC", + .start = 0x63500000, + .end = 0x63580000 - 1, + .flags = IORESOURCE_IO, + }, + /* + * Add other resources here + */ + { }, +}; + +/* + * NON_DVR_CAPABLE GAIA RESOURCES + */ +struct resource non_dvr_gaia_resources[] __initdata = { + /* + * + * VIDEO1 / LX1 + * + */ + { + .name = "ST231aImage", /* Delta-Mu 1 image and ram */ + .start = 0x24000000, + .end = 0x241FFFFF, /* 2MiB */ + .flags = IORESOURCE_MEM, + }, + { + .name = "ST231aMonitor", /* 8KiB block ST231a monitor */ + .start = 0x24200000, + .end = 0x24201FFF, + .flags = IORESOURCE_MEM, + }, + { + .name = "MediaMemory1", + .start = 0x24202000, + .end = 0x25FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */ + .flags = IORESOURCE_MEM, + }, + /* + * + * VIDEO2 / LX2 + * + */ + { + .name = "ST231bImage", /* Delta-Mu 2 image and ram */ + .start = 0x60000000, + .end = 0x601FFFFF, /* 2MiB */ + .flags = IORESOURCE_IO, + }, + { + .name = "ST231bMonitor", /* 8KiB block ST231b monitor */ + .start = 0x60200000, + .end = 0x60201FFF, + .flags = IORESOURCE_IO, + }, + { + .name = "MediaMemory2", + .start = 0x60202000, + .end = 0x61FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */ + .flags = IORESOURCE_IO, + }, + /* + * + * Sysaudio Driver + * + * This driver requires: + * + * Arbitrary Based Buffers: + * DSP_Image_Buff - DSP code and data images (1MB) + * ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB) + * ADSC_AUX_Buff - ADSC AUX buffer (16KB) + * ADSC_Main_Buff - ADSC Main buffer (16KB) + * + */ + { + .name = "DSP_Image_Buff", + .start = 0x00000000, + .end = 0x000FFFFF, + .flags = IORESOURCE_MEM, + }, + { + .name = "ADSC_CPU_PCM_Buff", + .start = 0x00000000, + .end = 0x00009FFF, + .flags = IORESOURCE_MEM, + }, + { + .name = "ADSC_AUX_Buff", + .start = 0x00000000, + .end = 0x00003FFF, + .flags = IORESOURCE_MEM, + }, + { + .name = "ADSC_Main_Buff", + .start = 0x00000000, + .end = 0x00003FFF, + .flags = IORESOURCE_MEM, + }, + /* + * + * STAVEM driver/STAPI + * + * This driver requires: + * + * Arbitrary Based Buffers: + * This memory area is used for allocating buffers for Video decoding + * purposes. Allocation/De-allocation within this buffer is managed + * by the STAVMEM driver of the STAPI. They could be Decimated + * Picture Buffers, Intermediate Buffers, as deemed necessary for + * video decoding purposes, for any video decoders on Zeus. + * + */ + { + .name = "AVMEMPartition0", + .start = 0x63580000, + .end = 0x64180000 - 1, /* 12 MB total */ + .flags = IORESOURCE_IO, + }, + /* + * + * DOCSIS Subsystem + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Docsis - + * + */ + { + .name = "Docsis", + .start = 0x62000000, + .end = 0x62700000 - 1, /* 7 MB total */ + .flags = IORESOURCE_IO, + }, + /* + * + * GHW HAL Driver + * + * This driver requires: + * + * Arbitrary Based Buffers: + * GraphicsHeap - PowerTV Graphics Heap + * + */ + { + .name = "GraphicsHeap", + .start = 0x62700000, + .end = 0x63500000 - 1, /* 14 MB total */ + .flags = IORESOURCE_IO, + }, + /* + * + * multi com buffer area + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Docsis - + * + */ + { + .name = "MulticomSHM", + .start = 0x26000000, + .end = 0x26020000 - 1, + .flags = IORESOURCE_MEM, + }, + /* + * + * DMA Ring buffer + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Docsis - + * + */ + { + .name = "BMM_Buffer", + .start = 0x00000000, + .end = 0x000AA000 - 1, + .flags = IORESOURCE_MEM, + }, + /* + * + * Display bins buffer for unit0 + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Display Bins for unit0 + * + */ + { + .name = "DisplayBins0", + .start = 0x00000000, + .end = 0x00000FFF, /* 4 KB total */ + .flags = IORESOURCE_MEM, + }, + /* + * + * Display bins buffer + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Display Bins for unit1 + * + */ + { + .name = "DisplayBins1", + .start = 0x64AD4000, + .end = 0x64AD5000 - 1, /* 4 KB total */ + .flags = IORESOURCE_IO, + }, + /* + * + * AVFS: player HAL memory + * + * + */ + { + .name = "AvfsDmaMem", + .start = 0x6430E000, + .end = 0x645D2C00 - 1, /* 945K * 3 for playback */ + .flags = IORESOURCE_IO, + }, + /* + * + * PMEM + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Persistent memory for diagnostics. + * + */ + { + .name = "DiagPersistentMemory", + .start = 0x00000000, + .end = 0x10000 - 1, + .flags = IORESOURCE_MEM, + }, + /* + * + * Smartcard + * + * This driver requires: + * + * Arbitrary Based Buffers: + * Read and write buffers for Internal/External cards + * + */ + { + .name = "SmartCardInfo", + .start = 0x64AD1000, + .end = 0x64AD3800 - 1, + .flags = IORESOURCE_IO, + }, + /* + * + * KAVNET + * NP Reset Vector - must be of the form xxCxxxxx + * NP Image - must be video bank 1 + * NP IPC - must be video bank 2 + */ + { + .name = "NP_Reset_Vector", + .start = 0x27c00000, + .end = 0x27c01000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "NP_Image", + .start = 0x27020000, + .end = 0x27060000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "NP_IPC", + .start = 0x63500000, + .end = 0x63580000 - 1, + .flags = IORESOURCE_IO, + }, + { }, +}; -- cgit v0.10.2 From c853d945d3e0cadf60da03106f7d9bbf1346a518 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Wed, 2 Jun 2010 16:35:24 +0800 Subject: MIPS: Unify the suffix of compressed vmlinux.bin The compressed vmlinux.bin is only a temp file so it's ok to use the same suffix .z for them (.gz,.lzo,.lzma...) to remove several lines and simpify the maintenance (no need to add the "suffix_$(xxx) := suffix" line). Signed-off-by: Wu Zhangjin To: linux-mips Cc: Alexander Clouter Cc: Manuel Lauss Cc: Sam Ravnborg Patchwork: https://patchwork.linux-mips.org/patch/1323/ Signed-off-by: Ralf Baechle --- diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile index edc48ad..3bdbeef 100644 --- a/arch/mips/boot/compressed/Makefile +++ b/arch/mips/boot/compressed/Makefile @@ -48,23 +48,19 @@ OBJCOPYFLAGS_vmlinux.bin := $(OBJCOPYFLAGS) -O binary -R .comment -S $(obj)/vmlinux.bin: $(KBUILD_IMAGE) FORCE $(call if_changed,objcopy) -suffix_$(CONFIG_KERNEL_GZIP) = gz -suffix_$(CONFIG_KERNEL_BZIP2) = bz2 -suffix_$(CONFIG_KERNEL_LZMA) = lzma -suffix_$(CONFIG_KERNEL_LZO) = lzo tool_$(CONFIG_KERNEL_GZIP) = gzip tool_$(CONFIG_KERNEL_BZIP2) = bzip2 tool_$(CONFIG_KERNEL_LZMA) = lzma tool_$(CONFIG_KERNEL_LZO) = lzo -targets += vmlinux.gz vmlinux.bz2 vmlinux.lzma vmlinux.lzo -$(obj)/vmlinux.$(suffix_y): $(obj)/vmlinux.bin FORCE +targets += vmlinux.bin.z +$(obj)/vmlinux.bin.z: $(obj)/vmlinux.bin FORCE $(call if_changed,$(tool_y)) targets += piggy.o -OBJCOPYFLAGS_piggy.o := --add-section=.image=$(obj)/vmlinux.$(suffix_y) \ +OBJCOPYFLAGS_piggy.o := --add-section=.image=$(obj)/vmlinux.bin.z \ --set-section-flags=.image=contents,alloc,load,readonly,data -$(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.$(suffix_y) FORCE +$(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.bin.z FORCE $(call if_changed,objcopy) LDFLAGS_vmlinuz := $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T diff --git a/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c new file mode 100644 index 0000000..88c9d963 --- /dev/null +++ b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2010 "Wu Zhangjin" + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + struct stat sb; + uint64_t vmlinux_size, vmlinux_load_addr, vmlinuz_load_addr; + + if (argc != 3) { + fprintf(stderr, "Usage: %s \n", + argv[0]); + return EXIT_FAILURE; + } + + if (stat(argv[1], &sb) == -1) { + perror("stat"); + return EXIT_FAILURE; + } + + /* Convert hex characters to dec number */ + errno = 0; + if (sscanf(argv[2], "%llx", &vmlinux_load_addr) != 1) { + if (errno != 0) + perror("sscanf"); + else + fprintf(stderr, "No matching characters\n"); + + return EXIT_FAILURE; + } + + vmlinux_size = (uint64_t)sb.st_size; + vmlinuz_load_addr = vmlinux_load_addr + vmlinux_size; + + /* + * Align with 16 bytes: "greater than that used for any standard data + * types by a MIPS compiler." -- See MIPS Run Linux (Second Edition). + */ + + vmlinuz_load_addr += (16 - vmlinux_size % 16); + + printf("0x%llx\n", vmlinuz_load_addr); + + return EXIT_SUCCESS; +} -- cgit v0.10.2 From bdbffd9b8d565fa7e011def532d3770be8d8091b Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Wed, 16 Jun 2010 15:52:19 +0800 Subject: MIPS: Clean up arch/mips/boot/compressed/ld.script - Remove unused symbols: _fdata, _text; only _edata and _end are needed by head.S - Remove unused sections: .sbss, .stab, .gptab.sdata, .gptab.sbss - Change the alignment to 16 bytes to ensure it is greater than any fundamental type of a MIPS compiler. - Clean up comments Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1381/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/boot/compressed/ld.script b/arch/mips/boot/compressed/ld.script index 613a35b..8e6b07c 100644 --- a/arch/mips/boot/compressed/ld.script +++ b/arch/mips/boot/compressed/ld.script @@ -2,61 +2,44 @@ * ld.script for compressed kernel support of MIPS * * Copyright (C) 2009 Lemote Inc. - * Author: Wu Zhangjin + * Author: Wu Zhangjin + * Copyright (C) 2010 "Wu Zhangjin" */ OUTPUT_ARCH(mips) ENTRY(start) SECTIONS { - /* . = VMLINUZ_LOAD_ADDRESS */ - /* read-only */ - _text = .; /* Text and read-only data */ - .text : { - _ftext = . ; + /* Text and read-only data */ + /* . = VMLINUZ_LOAD_ADDRESS; */ + .text : { *(.text) *(.rodata) - } = 0 - _etext = .; /* End of text section */ + } + /* End of text section */ - /* writable */ - .data : { /* Data */ - _fdata = . ; + /* Writable data */ + .data : { *(.data) - /* Put the compressed image here, so bss is on the end. */ + /* Put the compressed image here */ __image_begin = .; *(.image) __image_end = .; CONSTRUCTORS } - .sdata : { *(.sdata) } - . = ALIGN(4); - _edata = .; /* End of data section */ + . = ALIGN(16); + _edata = .; + /* End of data section */ /* BSS */ - __bss_start = .; - _fbss = .; - .sbss : { *(.sbss) *(.scommon) } - .bss : { - *(.dynbss) + .bss : { *(.bss) - *(COMMON) } - . = ALIGN(4); - _end = . ; - - /* These are needed for ELF backends which have not yet been converted - * to the new style linker. */ - - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - - /* These must appear regardless of . */ - .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } - .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } + . = ALIGN(16); + _end = .; /* Sections to be discarded */ - /DISCARD/ : { + /DISCARD/ : { *(.MIPS.options) *(.options) *(.pdr) -- cgit v0.10.2 From 1e1a77d6984a0010a2225de97009ae22f1ffa026 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Wed, 16 Jun 2010 15:52:20 +0800 Subject: MIPS: Clean up arch/mips/boot/compressed/decompress.c - Remove several outdated comments - Clearify the definition of zimage_start and zimage_size and the their usage Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1382/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c index 5db43c5..5cad0fa 100644 --- a/arch/mips/boot/compressed/decompress.c +++ b/arch/mips/boot/compressed/decompress.c @@ -1,9 +1,6 @@ /* - * Misc. bootloader code for many machines. - * * Copyright 2001 MontaVista Software Inc. - * Author: Matt Porter Derived from - * arch/ppc/boot/prep/misc.c + * Author: Matt Porter * * Copyright (C) 2009 Lemote, Inc. * Author: Wu Zhangjin @@ -19,12 +16,12 @@ #include -/* These two variables specify the free mem region +/* + * These two variables specify the free mem region * that can be used for temporary malloc area */ unsigned long free_mem_ptr; unsigned long free_mem_end_ptr; -char *zimage_start; /* The linker tells us where the image is. */ extern unsigned char __image_begin, __image_end; @@ -83,38 +80,31 @@ void *memset(void *s, int c, size_t n) void decompress_kernel(unsigned long boot_heap_start) { - int zimage_size; - - /* - * We link ourself to an arbitrary low address. When we run, we - * relocate outself to that address. __image_beign points to - * the part of the image where the zImage is. -- Tom - */ - zimage_start = (char *)(unsigned long)(&__image_begin); + unsigned long zimage_start, zimage_size; + + zimage_start = (unsigned long)(&__image_begin); zimage_size = (unsigned long)(&__image_end) - (unsigned long)(&__image_begin); - /* - * The zImage and initrd will be between start and _end, so they've - * already been moved once. We're good to go now. -- Tom - */ puts("zimage at: "); - puthex((unsigned long)zimage_start); + puthex(zimage_start); puts(" "); - puthex((unsigned long)(zimage_size + zimage_start)); + puthex(zimage_size + zimage_start); puts("\n"); - /* this area are prepared for mallocing when decompressing */ + /* This area are prepared for mallocing when decompressing */ free_mem_ptr = boot_heap_start; free_mem_end_ptr = boot_heap_start + BOOT_HEAP_SIZE; - /* Display standard Linux/MIPS boot prompt for kernel args */ + /* Display standard Linux/MIPS boot prompt */ puts("Uncompressing Linux at load address "); puthex(VMLINUX_LOAD_ADDRESS_ULL); puts("\n"); + /* Decompress the kernel with according algorithm */ - decompress(zimage_start, zimage_size, 0, 0, + decompress((char *)zimage_start, zimage_size, 0, 0, (void *)VMLINUX_LOAD_ADDRESS_ULL, 0, error); - /* FIXME: is there a need to flush cache here? */ + + /* FIXME: should we flush cache here? */ puts("Now, booting the kernel...\n"); } -- cgit v0.10.2 From 3c4b7fde941639bd96c7d0429b4da925f07be75f Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Wed, 2 Jun 2010 16:35:25 +0800 Subject: MIPS: Clean up the calculation of VMLINUZ_LOAD_ADDRESS We have calculated VMLINUZ_LOAD_ADDRESS in shell, which is indecipherable. This patch rewrites it in C. Signed-off-by: Wu Zhangjin To: linux-mips Cc: Alexander Clouter Cc: Manuel Lauss Cc: Sam Ravnborg Acked-by: Sam Ravnborg Reviewed-by: Alexander Clouter Patchwork: https://patchwork.linux-mips.org/patch/1324/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/boot/.gitignore b/arch/mips/boot/.gitignore index 4667a5f..f210b09 100644 --- a/arch/mips/boot/.gitignore +++ b/arch/mips/boot/.gitignore @@ -3,3 +3,4 @@ elf2ecoff vmlinux.* zImage zImage.tmp +calc_vmlinuz_load_addr diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile index 3bdbeef..5831490 100644 --- a/arch/mips/boot/compressed/Makefile +++ b/arch/mips/boot/compressed/Makefile @@ -12,14 +12,6 @@ # Author: Wu Zhangjin # -# compressed kernel load addr: VMLINUZ_LOAD_ADDRESS > VMLINUX_LOAD_ADDRESS + VMLINUX_SIZE -VMLINUX_SIZE := $(shell wc -c $(objtree)/$(KBUILD_IMAGE) 2>/dev/null | cut -d' ' -f1) -VMLINUX_SIZE := $(shell [ -n "$(VMLINUX_SIZE)" ] && echo -n $$(($(VMLINUX_SIZE) + (65536 - $(VMLINUX_SIZE) % 65536)))) -# VMLINUZ_LOAD_ADDRESS = concat "high32 of VMLINUX_LOAD_ADDRESS" and "(low32 of VMLINUX_LOAD_ADDRESS) + VMLINUX_SIZE" -HIGH32 := $(shell A=$(VMLINUX_LOAD_ADDRESS); [ $${\#A} -gt 10 ] && expr substr "$(VMLINUX_LOAD_ADDRESS)" 3 $$(($${\#A} - 10))) -LOW32 := $(shell [ -n "$(HIGH32)" ] && A=11 || A=3; expr substr "$(VMLINUX_LOAD_ADDRESS)" $${A} 8) -VMLINUZ_LOAD_ADDRESS := 0x$(shell [ -n "$(VMLINUX_SIZE)" -a -n "$(LOW32)" ] && printf "$(HIGH32)%08x" $$(($(VMLINUX_SIZE) + 0x$(LOW32)))) - # set the default size of the mallocing area for decompressing BOOT_HEAP_SIZE := 0x400000 @@ -63,10 +55,18 @@ OBJCOPYFLAGS_piggy.o := --add-section=.image=$(obj)/vmlinux.bin.z \ $(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.bin.z FORCE $(call if_changed,objcopy) -LDFLAGS_vmlinuz := $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T -vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/piggy.o - $(call cmd,ld) - $(Q)$(OBJCOPY) $(OBJCOPYFLAGS) $@ +# Calculate the load address of the compressed kernel image +hostprogs-y := calc_vmlinuz_load_addr + +VMLINUZ_LOAD_ADDRESS = $(shell $(obj)/calc_vmlinuz_load_addr \ + $(objtree)/$(KBUILD_IMAGE) $(VMLINUX_LOAD_ADDRESS)) + +vmlinuzobjs-y += $(obj)/piggy.o + +quiet_cmd_zld = LD $@ + cmd_zld = $(LD) $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T $< $(vmlinuzobjs-y) -o $@ +vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/calc_vmlinuz_load_addr + $(call cmd,zld) # # Some DECstations need all possible sections of an ECOFF executable @@ -76,7 +76,7 @@ ifdef CONFIG_MACH_DECSTATION endif # elf2ecoff can only handle 32bit image -hostprogs-y := ../elf2ecoff +hostprogs-y += ../elf2ecoff ifdef CONFIG_32BIT VMLINUZ = vmlinuz -- cgit v0.10.2 From 5089ca9d31b0250f42ccd0e0a41b3547f22a20a0 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Wed, 16 Jun 2010 15:52:21 +0800 Subject: MIPS: strip the un-needed sections of vmlinuz This patch use "strip -s" to strip the .symtab and .strtab sections of vmlinuz. Note: This patch is based on http://patchwork.linux-mips.org/patch/1324/ Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1383/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile index 5831490..ed9bb70 100644 --- a/arch/mips/boot/compressed/Makefile +++ b/arch/mips/boot/compressed/Makefile @@ -65,8 +65,11 @@ vmlinuzobjs-y += $(obj)/piggy.o quiet_cmd_zld = LD $@ cmd_zld = $(LD) $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T $< $(vmlinuzobjs-y) -o $@ +quiet_cmd_strip = STRIP $@ + cmd_strip = $(STRIP) -s $@ vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/calc_vmlinuz_load_addr $(call cmd,zld) + $(call cmd,strip) # # Some DECstations need all possible sections of an ECOFF executable -- cgit v0.10.2 From 0d365753d0b7c26043fdfa97790411606fb40112 Mon Sep 17 00:00:00 2001 From: David VomLehn Date: Mon, 2 Aug 2010 18:40:58 -0700 Subject: MIPS: PowerTV: Separate PowerTV USB support from non-USB code Separate USB code into a file separate from asic/asic_devices. Separating the USB code from everything else in asic/asic_devices.c goes a long way toward reducing the use of that file as a dumping ground for everything that didn't seem to fit anywhere else. Signed-off-by: David VomLehn To: linux-mips@linux-mips.org Cc: greg@kroah.com Cc: linux-usb@vger.kernel.org Patchwork: http://patchwork.linux-mips.org/patch/1522/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-powertv/asic.h b/arch/mips/include/asm/mach-powertv/asic.h index df33d93..c7077a6 100644 --- a/arch/mips/include/asm/mach-powertv/asic.h +++ b/arch/mips/include/asm/mach-powertv/asic.h @@ -20,6 +20,7 @@ #define _ASM_MACH_POWERTV_ASIC_H #include +#include #include #define DVR_CAPABLE (1<<0) @@ -71,16 +72,24 @@ extern int platform_supports_ffs(void); extern int platform_supports_pcie(void); extern int platform_supports_display(void); extern void configure_platform(void); -extern void platform_configure_usb_ehci(void); -extern void platform_unconfigure_usb_ehci(void); -extern void platform_configure_usb_ohci(void); -extern void platform_unconfigure_usb_ohci(void); /* Platform Resources */ #define ASIC_RESOURCE_GET_EXISTS 1 extern struct resource *asic_resource_get(const char *name); extern void platform_release_memory(void *baddr, int size); +/* USB configuration */ +struct usb_hcd; /* Forward reference */ +extern void platform_configure_usb_ehci(void); +extern void platform_unconfigure_usb_ehci(void); +extern void platform_configure_usb_ohci(void); +extern void platform_unconfigure_usb_ohci(void); + +/* Resource for ASIC registers */ +extern struct resource asic_resource; +extern int platform_usb_devices_init(struct platform_device **echi_dev, + struct platform_device **ohci_dev); + /* Reboot Cause */ extern void set_reboot_cause(char code, unsigned int data, unsigned int data2); extern void set_locked_reboot_cause(char code, unsigned int data, diff --git a/arch/mips/include/asm/mach-powertv/asic_regs.h b/arch/mips/include/asm/mach-powertv/asic_regs.h index 2657ae6..deecb26 100644 --- a/arch/mips/include/asm/mach-powertv/asic_regs.h +++ b/arch/mips/include/asm/mach-powertv/asic_regs.h @@ -101,6 +101,7 @@ static inline void register_map_virtualize(struct register_map *map) } extern struct register_map _asic_register_map; +extern unsigned long asic_phy_base; /* * Macros to interface to registers through their ioremapped address diff --git a/arch/mips/powertv/Makefile b/arch/mips/powertv/Makefile index 506c4ca..baf6e90 100644 --- a/arch/mips/powertv/Makefile +++ b/arch/mips/powertv/Makefile @@ -26,4 +26,6 @@ obj-y += init.o ioremap.o memory.o powertv_setup.o reset.o time.o \ asic/ pci/ +obj-$(CONFIG_USB) += powertv-usb.o + EXTRA_CFLAGS += -Wall diff --git a/arch/mips/powertv/asic/asic_devices.c b/arch/mips/powertv/asic/asic_devices.c index 095a887..e56fa61 100644 --- a/arch/mips/powertv/asic/asic_devices.c +++ b/arch/mips/powertv/asic/asic_devices.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -68,7 +67,6 @@ unsigned long asic_phy_base; unsigned long asic_base; EXPORT_SYMBOL(asic_base); /* Exported for testing */ struct resource *gp_resources; -static bool usb_configured; /* * Don't recommend to use it directly, it is usually used by kernel internally. @@ -91,101 +89,19 @@ struct resource asic_resource = { }; /* - * - * USB Host Resource Definition - * - */ - -static struct resource ehci_resources[] = { - { - .parent = &asic_resource, - .start = 0, - .end = 0xff, - .flags = IORESOURCE_MEM, - }, - { - .start = irq_usbehci, - .end = irq_usbehci, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 ehci_dmamask = DMA_BIT_MASK(32); - -static struct platform_device ehci_device = { - .name = "powertv-ehci", - .id = 0, - .num_resources = 2, - .resource = ehci_resources, - .dev = { - .dma_mask = &ehci_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - -static struct resource ohci_resources[] = { - { - .parent = &asic_resource, - .start = 0, - .end = 0xff, - .flags = IORESOURCE_MEM, - }, - { - .start = irq_usbohci, - .end = irq_usbohci, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 ohci_dmamask = DMA_BIT_MASK(32); - -static struct platform_device ohci_device = { - .name = "powertv-ohci", - .id = 0, - .num_resources = 2, - .resource = ohci_resources, - .dev = { - .dma_mask = &ohci_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - -static struct platform_device *platform_devices[] = { - &ehci_device, - &ohci_device, -}; - -/* - * - * Platform Configuration and Device Initialization - * - */ -static void __init fs_update(int pe, int md, int sdiv, int disable_div_by_3) -{ - int en_prg, byp, pwr, nsb, val; - int sout; - - sout = 1; - en_prg = 1; - byp = 0; - nsb = 1; - pwr = 1; - - val = ((sdiv << 29) | (md << 24) | (pe<<8) | (sout<<3) | (byp<<2) | - (nsb<<1) | (disable_div_by_3<<5)); - - asic_write(val, fs432x4b4_usb_ctl); - asic_write(val | (en_prg<<4), fs432x4b4_usb_ctl); - asic_write(val | (en_prg<<4) | pwr, fs432x4b4_usb_ctl); -} - -/* * Allow override of bootloader-specified model + * Returns zero on success, a negative errno value on failure. This parameter + * allows overriding of the bootloader-specified model. */ static char __initdata cmdline[COMMAND_LINE_SIZE]; #define FORCEFAMILY_PARAM "forcefamily" +/* + * check_forcefamily - check for, and parse, forcefamily command line parameter + * @forced_family: Pointer to two-character array in which to store the + * value of the forcedfamily parameter, if any. + */ static __init int check_forcefamily(unsigned char forced_family[2]) { const char *p; @@ -225,14 +141,10 @@ static __init int check_forcefamily(unsigned char forced_family[2]) */ static __init noinline void platform_set_family(void) { -#define BOOTLDRFAMILY(byte1, byte0) (((byte1) << 8) | (byte0)) - unsigned char forced_family[2]; unsigned short bootldr_family; - check_forcefamily(forced_family); - - if (forced_family[0] != '\0' && forced_family[1] != '\0') + if (check_forcefamily(forced_family) == 0) bootldr_family = BOOTLDRFAMILY(forced_family[0], forced_family[1]); else { @@ -298,24 +210,9 @@ unsigned int platform_get_family(void) EXPORT_SYMBOL(platform_get_family); /* - * \brief usb_eye_configure() for optimizing the USB eye on Calliope. - * - * \param unsigned int value saved to the register. - * - * \return none - * - */ -static void __init usb_eye_configure(unsigned int value) -{ - asic_write(asic_read(crt_spare) | value, crt_spare); -} - -/* * platform_get_asic - determine the ASIC type. * - * \param none - * - * \return ASIC type; ASIC_UNKNOWN if none + * Returns the ASIC type, or ASIC_UNKNOWN if unknown * */ enum asic_type platform_get_asic(void) @@ -325,93 +222,10 @@ enum asic_type platform_get_asic(void) EXPORT_SYMBOL(platform_get_asic); /* - * platform_configure_usb - usb configuration based on platform type. - * @bcm1_usb2_ctl: value for the BCM1_USB2_CTL register, which is - * quirky - */ -static void __init platform_configure_usb(void) -{ - u32 bcm1_usb2_ctl; - - if (usb_configured) - return; - - switch (asic) { - case ASIC_ZEUS: - case ASIC_CRONUS: - case ASIC_CRONUSLITE: - fs_update(0x0000, 0x11, 0x02, 0); - bcm1_usb2_ctl = 0x803; - break; - - case ASIC_CALLIOPE: - fs_update(0x0000, 0x11, 0x02, 1); - - switch (platform_family) { - case FAMILY_1500VZE: - break; - - case FAMILY_1500VZF: - usb_eye_configure(0x003c0000); - break; - - default: - usb_eye_configure(0x00300000); - break; - } - - bcm1_usb2_ctl = 0x803; - break; - - default: - pr_err("Unknown ASIC type: %d\n", asic); - break; - } - - /* turn on USB power */ - asic_write(0, usb2_strap); - /* Enable all OHCI interrupts */ - asic_write(bcm1_usb2_ctl, usb2_control); - /* USB2_STBUS_OBC store32/load32 */ - asic_write(3, usb2_stbus_obc); - /* USB2_STBUS_MESS_SIZE 2 packets */ - asic_write(1, usb2_stbus_mess_size); - /* USB2_STBUS_CHUNK_SIZE 2 packets */ - asic_write(1, usb2_stbus_chunk_size); - - usb_configured = true; -} - -/* - * Set up the USB EHCI interface - */ -void platform_configure_usb_ehci() -{ - platform_configure_usb(); -} - -/* - * Set up the USB OHCI interface - */ -void platform_configure_usb_ohci() -{ - platform_configure_usb(); -} - -/* - * Shut the USB EHCI interface down--currently a NOP + * set_register_map - set ASIC register configuration + * @phys_base: Physical address of the base of the ASIC registers + * @map: Description of key ASIC registers */ -void platform_unconfigure_usb_ehci() -{ -} - -/* - * Shut the USB OHCI interface down--currently a NOP - */ -void platform_unconfigure_usb_ohci() -{ -} - static void __init set_register_map(unsigned long phys_base, const struct register_map *map) { @@ -560,34 +374,8 @@ void __init configure_platform(void) } } -/** - * platform_devices_init - sets up USB device resourse. - */ -static int __init platform_devices_init(void) -{ - pr_notice("%s: ----- Initializing USB resources -----\n", __func__); - - asic_resource.start = asic_phy_base; - asic_resource.end += asic_resource.start; - - ehci_resources[0].start = asic_reg_phys_addr(ehci_hcapbase); - ehci_resources[0].end += ehci_resources[0].start; - - ohci_resources[0].start = asic_reg_phys_addr(ohci_hc_revision); - ohci_resources[0].end += ohci_resources[0].start; - - set_io_port_base(0); - - platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); - - return 0; -} - -arch_initcall(platform_devices_init); - /* - * - * BOOTMEM ALLOCATION + * RESOURCE ALLOCATION * */ /* diff --git a/arch/mips/powertv/powertv-usb.c b/arch/mips/powertv/powertv-usb.c new file mode 100644 index 0000000..6ac85cf --- /dev/null +++ b/arch/mips/powertv/powertv-usb.c @@ -0,0 +1,403 @@ +/* + * powertv-usb.c + * + * Description: ASIC-specific USB device setup and shutdown + * + * Copyright (C) 2005-2009 Scientific-Atlanta, Inc. + * Copyright (C) 2009 Cisco Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: Ken Eppinett + * David Schleef + * + * NOTE: The bootloader allocates persistent memory at an address which is + * 16 MiB below the end of the highest address in KSEG0. All fixed + * address memory reservations must avoid this region. + */ + +#include +#include +#include +#include +#include + +/* misc_clk_ctl1 values */ +#define MCC1_30MHZ_POWERUP_SELECT (1 << 14) +#define MCC1_DIV9 (1 << 13) +#define MCC1_ETHMIPS_POWERUP_SELECT (1 << 11) +#define MCC1_USB_POWERUP_SELECT (1 << 1) +#define MCC1_CLOCK108_POWERUP_SELECT (1 << 0) + +/* Possible values for clock select */ +#define MCC1_USB_CLOCK_HIGH_Z (0 << 4) +#define MCC1_USB_CLOCK_48MHZ (1 << 4) +#define MCC1_USB_CLOCK_24MHZ (2 << 4) +#define MCC1_USB_CLOCK_6MHZ (3 << 4) + +#define MCC1_CONFIG (MCC1_30MHZ_POWERUP_SELECT | \ + MCC1_DIV9 | \ + MCC1_ETHMIPS_POWERUP_SELECT | \ + MCC1_USB_POWERUP_SELECT | \ + MCC1_CLOCK108_POWERUP_SELECT) + +/* misc_clk_ctl2 values */ +#define MCC2_GMII_GCLK_TO_PAD (1 << 31) +#define MCC2_ETHER125_0_CLOCK_SELECT (1 << 29) +#define MCC2_RMII_0_CLOCK_SELECT (1 << 28) +#define MCC2_GMII_TX0_CLOCK_SELECT (1 << 27) +#define MCC2_GMII_RX0_CLOCK_SELECT (1 << 26) +#define MCC2_ETHER125_1_CLOCK_SELECT (1 << 24) +#define MCC2_RMII_1_CLOCK_SELECT (1 << 23) +#define MCC2_GMII_TX1_CLOCK_SELECT (1 << 22) +#define MCC2_GMII_RX1_CLOCK_SELECT (1 << 21) +#define MCC2_ETHER125_2_CLOCK_SELECT (1 << 19) +#define MCC2_RMII_2_CLOCK_SELECT (1 << 18) +#define MCC2_GMII_TX2_CLOCK_SELECT (1 << 17) +#define MCC2_GMII_RX2_CLOCK_SELECT (1 << 16) + +#define ETHER_CLK_CONFIG (MCC2_GMII_GCLK_TO_PAD | \ + MCC2_ETHER125_0_CLOCK_SELECT | \ + MCC2_RMII_0_CLOCK_SELECT | \ + MCC2_GMII_TX0_CLOCK_SELECT | \ + MCC2_GMII_RX0_CLOCK_SELECT | \ + MCC2_ETHER125_1_CLOCK_SELECT | \ + MCC2_RMII_1_CLOCK_SELECT | \ + MCC2_GMII_TX1_CLOCK_SELECT | \ + MCC2_GMII_RX1_CLOCK_SELECT | \ + MCC2_ETHER125_2_CLOCK_SELECT | \ + MCC2_RMII_2_CLOCK_SELECT | \ + MCC2_GMII_TX2_CLOCK_SELECT | \ + MCC2_GMII_RX2_CLOCK_SELECT) + +/* misc_clk_ctl2 definitions for Gaia */ +#define FSX4A_REF_SELECT (1 << 16) +#define FSX4B_REF_SELECT (1 << 17) +#define FSX4C_REF_SELECT (1 << 18) +#define DDR_PLL_REF_SELECT (1 << 19) +#define MIPS_PLL_REF_SELECT (1 << 20) + +/* Definitions for the QAM frequency select register FS432X4A4_QAM_CTL */ +#define QAM_FS_SDIV_SHIFT 29 +#define QAM_FS_MD_SHIFT 24 +#define QAM_FS_MD_MASK 0x1f /* Cut down to 5 bits */ +#define QAM_FS_PE_SHIFT 8 + +#define QAM_FS_DISABLE_DIVIDE_BY_3 (1 << 5) +#define QAM_FS_ENABLE_PROGRAM (1 << 4) +#define QAM_FS_ENABLE_OUTPUT (1 << 3) +#define QAM_FS_SELECT_TEST_BYPASS (1 << 2) +#define QAM_FS_DISABLE_DIGITAL_STANDBY (1 << 1) +#define QAM_FS_CHOOSE_FS (1 << 0) + +/* Definitions for fs432x4a_ctl register */ +#define QAM_FS_NSDIV_54MHZ (1 << 2) + +/* Definitions for bcm1_usb2_ctl register */ +#define BCM1_USB2_CTL_BISTOK (1 << 11) +#define BCM1_USB2_CTL_PORT2_SHIFT_JK (1 << 7) +#define BCM1_USB2_CTL_PORT1_SHIFT_JK (1 << 6) +#define BCM1_USB2_CTL_PORT2_FAST_EDGE (1 << 5) +#define BCM1_USB2_CTL_PORT1_FAST_EDGE (1 << 4) +#define BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH (1 << 1) +#define BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH (1 << 0) + +/* Definitions for crt_spare register */ +#define CRT_SPARE_PORT2_SHIFT_JK (1 << 21) +#define CRT_SPARE_PORT1_SHIFT_JK (1 << 20) +#define CRT_SPARE_PORT2_FAST_EDGE (1 << 19) +#define CRT_SPARE_PORT1_FAST_EDGE (1 << 18) +#define CRT_SPARE_DIVIDE_BY_9_FROM_432 (1 << 17) +#define CRT_SPARE_USB_DIVIDE_BY_9 (1 << 16) + +/* Definitions for usb2_stbus_obc register */ +#define USB_STBUS_OBC_STORE32_LOAD32 0x3 + +/* Definitions for usb2_stbus_mess_size register */ +#define USB2_STBUS_MESS_SIZE_2 0x1 /* 2 packets */ + +/* Definitions for usb2_stbus_chunk_size register */ +#define USB2_STBUS_CHUNK_SIZE_2 0x1 /* 2 packets */ + +/* Definitions for usb2_strap register */ +#define USB2_STRAP_HFREQ_SELECT 0x1 + +/* + * USB Host Resource Definition + */ + +static struct resource ehci_resources[] = { + { + .parent = &asic_resource, + .start = 0, + .end = 0xff, + .flags = IORESOURCE_MEM, + }, + { + .start = irq_usbehci, + .end = irq_usbehci, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 ehci_dmamask = 0xffffffffULL; + +static struct platform_device ehci_device = { + .name = "powertv-ehci", + .id = 0, + .num_resources = 2, + .resource = ehci_resources, + .dev = { + .dma_mask = &ehci_dmamask, + .coherent_dma_mask = 0xffffffff, + }, +}; + +static struct resource ohci_resources[] = { + { + .parent = &asic_resource, + .start = 0, + .end = 0xff, + .flags = IORESOURCE_MEM, + }, + { + .start = irq_usbohci, + .end = irq_usbohci, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 ohci_dmamask = 0xffffffffULL; + +static struct platform_device ohci_device = { + .name = "powertv-ohci", + .id = 0, + .num_resources = 2, + .resource = ohci_resources, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = 0xffffffff, + }, +}; + +static unsigned usb_users; +static DEFINE_SPINLOCK(usb_regs_lock); + +/* + * + * fs_update - set frequency synthesizer for USB + * @pe_bits Phase tap setting + * @md_bits Coarse selector bus for algorithm of phase tap + * @sdiv_bits Output divider setting + * @disable_div_by_3 Either QAM_FS_DISABLE_DIVIDE_BY_3 or zero + * @standby Either QAM_FS_DISABLE_DIGITAL_STANDBY or zero + * + * QAM frequency selection code, which affects the frequency at which USB + * runs. The frequency is calculated as: + * 2^15 * ndiv * Fin + * Fout = ------------------------------------------------------------ + * (sdiv * (ipe * (1 + md/32) - (ipe - 2^15)*(1 + (md + 1)/32))) + * where: + * Fin 54 MHz + * ndiv QAM_FS_NSDIV_54MHZ ? 8 : 16 + * sdiv 1 << (sdiv_bits + 1) + * ipe Same as pe_bits + * md A five-bit, two's-complement integer (range [-16, 15]), which + * is the lower 5 bits of md_bits. + */ +static void fs_update(u32 pe_bits, int md_bits, u32 sdiv_bits, + u32 disable_div_by_3, u32 standby) +{ + u32 val; + + val = ((sdiv_bits << QAM_FS_SDIV_SHIFT) | + ((md_bits & QAM_FS_MD_MASK) << QAM_FS_MD_SHIFT) | + (pe_bits << QAM_FS_PE_SHIFT) | + QAM_FS_ENABLE_OUTPUT | + standby | + disable_div_by_3); + asic_write(val, fs432x4b4_usb_ctl); + asic_write(val | QAM_FS_ENABLE_PROGRAM, fs432x4b4_usb_ctl); + asic_write(val | QAM_FS_ENABLE_PROGRAM | QAM_FS_CHOOSE_FS, + fs432x4b4_usb_ctl); +} + +/* + * usb_eye_configure - for optimizing the shape USB eye waveform + * @set: Bits to set in the register + * @clear: Bits to clear in the register; each bit with a one will + * be set in the register, zero bits will not be modified + */ +static void usb_eye_configure(u32 set, u32 clear) +{ + u32 old; + + old = asic_read(crt_spare); + old |= set; + old &= ~clear; + asic_write(old, crt_spare); +} + +/* + * platform_configure_usb - usb configuration based on platform type. + */ +static void platform_configure_usb(void) +{ + u32 bcm1_usb2_ctl_value; + enum asic_type asic_type; + unsigned long flags; + + spin_lock_irqsave(&usb_regs_lock, flags); + usb_users++; + + if (usb_users != 1) { + spin_unlock_irqrestore(&usb_regs_lock, flags); + return; + } + + asic_type = platform_get_asic(); + + switch (asic_type) { + case ASIC_ZEUS: + fs_update(0x0000, -15, 0x02, 0, 0); + bcm1_usb2_ctl_value = BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH | + BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH; + break; + + case ASIC_CRONUS: + case ASIC_CRONUSLITE: + usb_eye_configure(0, CRT_SPARE_USB_DIVIDE_BY_9); + fs_update(0x8000, -14, 0x03, QAM_FS_DISABLE_DIVIDE_BY_3, + QAM_FS_DISABLE_DIGITAL_STANDBY); + bcm1_usb2_ctl_value = BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH | + BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH; + break; + + case ASIC_CALLIOPE: + fs_update(0x0000, -15, 0x02, QAM_FS_DISABLE_DIVIDE_BY_3, + QAM_FS_DISABLE_DIGITAL_STANDBY); + + switch (platform_get_family()) { + case FAMILY_1500VZE: + break; + + case FAMILY_1500VZF: + usb_eye_configure(CRT_SPARE_PORT2_SHIFT_JK | + CRT_SPARE_PORT1_SHIFT_JK | + CRT_SPARE_PORT2_FAST_EDGE | + CRT_SPARE_PORT1_FAST_EDGE, 0); + break; + + default: + usb_eye_configure(CRT_SPARE_PORT2_SHIFT_JK | + CRT_SPARE_PORT1_SHIFT_JK, 0); + break; + } + + bcm1_usb2_ctl_value = BCM1_USB2_CTL_BISTOK | + BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH | + BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH; + break; + + case ASIC_GAIA: + fs_update(0x8000, -14, 0x03, QAM_FS_DISABLE_DIVIDE_BY_3, + QAM_FS_DISABLE_DIGITAL_STANDBY); + bcm1_usb2_ctl_value = BCM1_USB2_CTL_BISTOK | + BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH | + BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH; + break; + + default: + pr_err("Unknown ASIC type: %d\n", asic_type); + bcm1_usb2_ctl_value = 0; + break; + } + + /* turn on USB power */ + asic_write(0, usb2_strap); + /* Enable all OHCI interrupts */ + asic_write(bcm1_usb2_ctl_value, usb2_control); + /* usb2_stbus_obc store32/load32 */ + asic_write(USB_STBUS_OBC_STORE32_LOAD32, usb2_stbus_obc); + /* usb2_stbus_mess_size 2 packets */ + asic_write(USB2_STBUS_MESS_SIZE_2, usb2_stbus_mess_size); + /* usb2_stbus_chunk_size 2 packets */ + asic_write(USB2_STBUS_CHUNK_SIZE_2, usb2_stbus_chunk_size); + spin_unlock_irqrestore(&usb_regs_lock, flags); +} + +static void platform_unconfigure_usb(void) +{ + unsigned long flags; + + spin_lock_irqsave(&usb_regs_lock, flags); + usb_users--; + if (usb_users == 0) + asic_write(USB2_STRAP_HFREQ_SELECT, usb2_strap); + spin_unlock_irqrestore(&usb_regs_lock, flags); +} + +/* + * Set up the USB EHCI interface + */ +void platform_configure_usb_ehci() +{ + platform_configure_usb(); +} +EXPORT_SYMBOL(platform_configure_usb_ehci); + +/* + * Set up the USB OHCI interface + */ +void platform_configure_usb_ohci() +{ + platform_configure_usb(); +} +EXPORT_SYMBOL(platform_configure_usb_ohci); + +/* + * Shut the USB EHCI interface down + */ +void platform_unconfigure_usb_ehci() +{ + platform_unconfigure_usb(); +} +EXPORT_SYMBOL(platform_unconfigure_usb_ehci); + +/* + * Shut the USB OHCI interface down + */ +void platform_unconfigure_usb_ohci() +{ + platform_unconfigure_usb(); +} +EXPORT_SYMBOL(platform_unconfigure_usb_ohci); + +/** + * platform_devices_init - sets up USB device resourse. + */ +int __init platform_usb_devices_init(struct platform_device **ehci_dev, + struct platform_device **ohci_dev) +{ + *ehci_dev = &ehci_device; + ehci_resources[0].start = asic_reg_phys_addr(ehci_hcapbase); + ehci_resources[0].end += ehci_resources[0].start; + + *ohci_dev = &ohci_device; + ohci_resources[0].start = asic_reg_phys_addr(ohci_hc_revision); + ohci_resources[0].end += ohci_resources[0].start; + + return 0; +} -- cgit v0.10.2