]> git.hungrycats.org Git - linux/commitdiff
[PATCH] sh: SH7705 subtype cleanup + 32k cache support
authorPaul Mundt <paul.mundt@nokia.com>
Mon, 18 Oct 2004 15:58:17 +0000 (08:58 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 18 Oct 2004 15:58:17 +0000 (08:58 -0700)
This fixes up the existing SH7705 support and enables the 32k cache mode for
the processor.

Signed-off-by: Alex Song <songqf9@yahoo.ca>
Signed-off-by: Paul Mundt <paul.mundt@nokia.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
12 files changed:
arch/sh/boards/se/770x/irq.c
arch/sh/boards/se/770x/mach.c
arch/sh/kernel/traps.c
arch/sh/mm/Makefile
arch/sh/mm/cache-sh7705.c [new file with mode: 0644]
arch/sh/mm/pg-sh7705.c [new file with mode: 0644]
arch/sh/mm/tlb-sh3.c
include/asm-sh/cpu-sh3/cache.h
include/asm-sh/cpu-sh3/cacheflush.h
include/asm-sh/page.h
include/asm-sh/pgtable.h
include/asm-sh/se/se.h

index dff4fbd8640f0eef81999631da06af7c137b25f6..210897b315f4fa8fe6bbccca72a265e3d14151d6 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id: irq.c,v 1.4 2004/02/22 22:44:36 kkojima Exp $
- * 
+/*
  * linux/arch/sh/boards/se/770x/irq.c
  *
  * Copyright (C) 2000  Kazumoto Kojima
@@ -12,6 +11,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <asm/irq.h>
+#include <asm/io.h>
 #include <asm/se/se.h>
 
 /*
@@ -30,6 +30,32 @@ void __init init_se_IRQ(void)
          * 12: mouse
          * 14: ide0
          */
+#if defined(CONFIG_CPU_SUBTYPE_SH7705)
+       /* Disable all interrupts */
+       ctrl_outw(0, BCR_ILCRA);
+       ctrl_outw(0, BCR_ILCRB);
+       ctrl_outw(0, BCR_ILCRC);
+       ctrl_outw(0, BCR_ILCRD);
+       ctrl_outw(0, BCR_ILCRE);
+       ctrl_outw(0, BCR_ILCRF);
+       ctrl_outw(0, BCR_ILCRG);
+       /* This is default value */
+       make_ipr_irq(0xf-0x2, BCR_ILCRA, 2, 0x2);
+       make_ipr_irq(0xf-0xa, BCR_ILCRA, 1, 0xa);
+       make_ipr_irq(0xf-0x5, BCR_ILCRB, 0, 0x5);
+       make_ipr_irq(0xf-0x8, BCR_ILCRC, 1, 0x8);
+       make_ipr_irq(0xf-0xc, BCR_ILCRC, 0, 0xc);
+       make_ipr_irq(0xf-0xe, BCR_ILCRD, 3, 0xe);
+       make_ipr_irq(0xf-0x3, BCR_ILCRD, 1, 0x3); /* LAN */
+       make_ipr_irq(0xf-0xd, BCR_ILCRE, 2, 0xd);
+       make_ipr_irq(0xf-0x9, BCR_ILCRE, 1, 0x9);
+       make_ipr_irq(0xf-0x1, BCR_ILCRE, 0, 0x1);
+       make_ipr_irq(0xf-0xf, BCR_ILCRF, 3, 0xf);
+       make_ipr_irq(0xf-0xb, BCR_ILCRF, 1, 0xb);
+       make_ipr_irq(0xf-0x7, BCR_ILCRG, 3, 0x7);
+       make_ipr_irq(0xf-0x6, BCR_ILCRG, 2, 0x6);
+       make_ipr_irq(0xf-0x4, BCR_ILCRG, 1, 0x4);
+#else
         make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-14);
         make_ipr_irq(12, BCR_ILCRA, 1, 0x0f-12);
         make_ipr_irq( 8, BCR_ILCRB, 1, 0x0f- 8);
@@ -50,4 +76,5 @@ void __init init_se_IRQ(void)
         /* NOTE: #2 and #13 are not used on PC */
         make_ipr_irq(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */
         make_ipr_irq( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */
+#endif
 }
index aa5dde2f5dca836e797d5229aee734411d59624b..f9b4c56cc47ea994377cf514479d887777cc090f 100644 (file)
@@ -33,6 +33,8 @@ struct sh_machine_vector mv_se __initmv = {
        .mv_nr_irqs             = 32,
 #elif defined(CONFIG_CPU_SUBTYPE_SH7709)
        .mv_nr_irqs             = 61,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
+       .mv_nr_irqs             = 86,
 #endif
 
        .mv_inb                 = se_inb,
index da5721f4aab72a7269ec7c7f66d74f99fc658b85..7eb06719d844deed72de1c33f3b459cda1286181 100644 (file)
@@ -438,7 +438,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
                case 0x0F00: /* bf/s lab */
                        ret = handle_unaligned_delayslot(regs);
                        if (ret==0) {
-#if defined(CONFIG_CPU_SH4)
+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
                                if ((regs->sr & 0x00000001) != 0)
                                        regs->pc += 4; /* next after slot */
                                else
@@ -451,7 +451,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
                case 0x0D00: /* bt/s lab */
                        ret = handle_unaligned_delayslot(regs);
                        if (ret==0) {
-#if defined(CONFIG_CPU_SH4)
+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
                                if ((regs->sr & 0x00000001) == 0)
                                        regs->pc += 4; /* next after slot */
                                else
index 38e004cff44b8f9e288ce660c37c6f23be1a0a1e..9489a1424644e7368a4ee9d956703987c14ca72d 100644 (file)
@@ -19,5 +19,7 @@ obj-y                 += $(mmu-y)
 ifdef CONFIG_MMU
 obj-$(CONFIG_CPU_SH3)  += tlb-sh3.o
 obj-$(CONFIG_CPU_SH4)  += tlb-sh4.o ioremap.o
+obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o
 endif
 
+obj-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o
diff --git a/arch/sh/mm/cache-sh7705.c b/arch/sh/mm/cache-sh7705.c
new file mode 100644 (file)
index 0000000..3a0508b
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * arch/sh/mm/cache-sh7705.c
+ *
+ * Copyright (C) 1999, 2000  Niibe Yutaka
+ * Copyright (C) 2004  Alex Song
+ *
+ * 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 <linux/init.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/threads.h>
+#include <asm/addrspace.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+/* The 32KB cache on the SH7705 suffers from the same synonym problem
+ * as SH4 CPUs */
+
+#define __pte_offset(address) \
+               ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset(dir, address) ((pte_t *) pmd_page_kernel(*(dir)) + \
+               __pte_offset(address))
+
+static inline void cache_wback_all(void)
+{
+       unsigned long ways, waysize, addrstart;
+
+       ways = cpu_data->dcache.ways;
+       waysize = cpu_data->dcache.sets;
+       waysize <<= cpu_data->dcache.entry_shift;
+
+       addrstart = CACHE_OC_ADDRESS_ARRAY;
+
+       do {
+               unsigned long addr;
+
+               for (addr = addrstart;
+                    addr < addrstart + waysize;
+                    addr += cpu_data->dcache.linesz) {
+                       unsigned long data;
+                       int v = SH_CACHE_UPDATED | SH_CACHE_VALID;
+
+                       data = ctrl_inl(addr);
+
+                       if ((data & v) == v)
+                               ctrl_outl(data & ~v, addr);
+
+               }
+
+               addrstart += cpu_data->dcache.way_incr;
+       } while (--ways);
+}
+
+/*
+ * Write back the range of D-cache, and purge the I-cache.
+ *
+ * Called from kernel/module.c:sys_init_module and routine for a.out format.
+ */
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+       __flush_wback_region((void *)start, end - start);
+}
+
+
+/*
+ * Writeback&Invalidate the D-cache of the page
+ */
+static void __flush_dcache_page(unsigned long phys)
+{
+       unsigned long ways, waysize, addrstart;
+       unsigned long flags;
+
+       phys |= SH_CACHE_VALID;
+
+       /*
+        * Here, phys is the physical address of the page. We check all the
+        * tags in the cache for those with the same page number as this page
+        * (by masking off the lowest 2 bits of the 19-bit tag; these bits are
+        * derived from the offset within in the 4k page). Matching valid
+        * entries are invalidated.
+        *
+        * Since 2 bits of the cache index are derived from the virtual page
+        * number, knowing this would reduce the number of cache entries to be
+        * searched by a factor of 4. However this function exists to deal with
+        * potential cache aliasing, therefore the optimisation is probably not
+        * possible.
+        */
+       local_irq_save(flags);
+       jump_to_P2();
+
+       ways = cpu_data->dcache.ways;
+       waysize = cpu_data->dcache.sets;
+       waysize <<= cpu_data->dcache.entry_shift;
+
+       addrstart = CACHE_OC_ADDRESS_ARRAY;
+
+       do {
+               unsigned long addr;
+
+               for (addr = addrstart;
+                    addr < addrstart + waysize;
+                    addr += cpu_data->dcache.linesz) {
+                       unsigned long data;
+
+                       data = ctrl_inl(addr) & (0x1ffffC00 | SH_CACHE_VALID);
+                       if (data == phys) {
+                               data &= ~(SH_CACHE_VALID | SH_CACHE_UPDATED);
+                               ctrl_outl(data, addr);
+                       }
+               }
+
+               addrstart += cpu_data->dcache.way_incr;
+       } while (--ways);
+
+       back_to_P1();
+       local_irq_restore(flags);
+}
+
+
+/*
+ * Write back & invalidate the D-cache of the page.
+ * (To avoid "alias" issues)
+ */
+void flush_dcache_page(struct page *page)
+{
+       if (test_bit(PG_mapped, &page->flags))
+               __flush_dcache_page(PHYSADDR(page_address(page)));
+}
+
+void flush_cache_all(void)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       jump_to_P2();
+
+       cache_wback_all();
+       back_to_P1();
+       local_irq_restore(flags);
+}
+
+void flush_cache_mm(struct mm_struct *mm)
+{
+       /* Is there any good way? */
+       /* XXX: possibly call flush_cache_range for each vm area */
+       flush_cache_all();
+}
+
+/*
+ * Write back and invalidate D-caches.
+ *
+ * START, END: Virtual Address (U0 address)
+ *
+ * NOTE: We need to flush the _physical_ page entry.
+ * Flushing the cache lines for U0 only isn't enough.
+ * We need to flush for P1 too, which may contain aliases.
+ */
+void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
+                      unsigned long end)
+{
+
+       /*
+        * We could call flush_cache_page for the pages of these range,
+        * but it's not efficient (scan the caches all the time...).
+        *
+        * We can't use A-bit magic, as there's the case we don't have
+        * valid entry on TLB.
+        */
+       flush_cache_all();
+}
+
+/*
+ * Write back and invalidate I/D-caches for the page.
+ *
+ * ADDRESS: Virtual Address (U0 address)
+ */
+void flush_cache_page(struct vm_area_struct *vma, unsigned long address)
+{
+       pgd_t *dir;
+       pmd_t *pmd;
+       pte_t *pte;
+       pte_t entry;
+       unsigned long phys;
+
+       dir = pgd_offset(vma->vm_mm, address);
+       pmd = pmd_offset(dir, address);
+       if (pmd_none(*pmd) || pmd_bad(*pmd))
+               return;
+       pte = pte_offset(pmd, address);
+       entry = *pte;
+       if (pte_none(entry) || !pte_present(entry))
+               return;
+
+       phys = pte_val(entry)&PTE_PHYS_MASK;
+       __flush_dcache_page(phys);
+}
+
+/*
+ * This is called when a page-cache page is about to be mapped into a
+ * user process' address space.  It offers an opportunity for a
+ * port to ensure d-cache/i-cache coherency if necessary.
+ *
+ * Not entirely sure why this is necessary on SH3 with 32K cache but
+ * without it we get occasional "Memory fault" when loading a program.
+ */
+void flush_icache_page(struct vm_area_struct *vma, struct page *page)
+{
+       __flush_purge_region(page_address(page), PAGE_SIZE);
+}
+
diff --git a/arch/sh/mm/pg-sh7705.c b/arch/sh/mm/pg-sh7705.c
new file mode 100644 (file)
index 0000000..4a6eea8
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * arch/sh/mm/pg-sh7705.c
+ *
+ * Copyright (C) 1999, 2000  Niibe Yutaka
+ * Copyright (C) 2004  Alex Song
+ *
+ * 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 <linux/init.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/threads.h>
+#include <asm/addrspace.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+
+static inline void __flush_purge_virtual_region(void *p1, void *virt, int size)
+{
+       unsigned long v;
+       unsigned long begin, end;
+       unsigned long p1_begin;
+
+
+       begin = L1_CACHE_ALIGN((unsigned long)virt);
+       end = L1_CACHE_ALIGN((unsigned long)virt + size);
+
+       p1_begin = (unsigned long)p1 & ~(L1_CACHE_BYTES - 1);
+
+       /* do this the slow way as we may not have TLB entries
+        * for virt yet. */
+       for (v = begin; v < end; v += L1_CACHE_BYTES) {
+               unsigned long p;
+               unsigned long ways, addr;
+
+               p = __pa(p1_begin);
+
+               ways = cpu_data->dcache.ways;
+               addr = CACHE_OC_ADDRESS_ARRAY;
+
+               do {
+                       unsigned long data;
+
+                       addr |= (v & cpu_data->dcache.entry_mask);
+
+                       data = ctrl_inl(addr);
+                       if ((data & CACHE_PHYSADDR_MASK) ==
+                              (p & CACHE_PHYSADDR_MASK)) {
+                               data &= ~(SH_CACHE_UPDATED|SH_CACHE_VALID);
+                               ctrl_outl(data, addr);
+                       }
+
+                       addr += cpu_data->dcache.way_incr;
+               } while (--ways);
+
+               p1_begin += L1_CACHE_BYTES;
+       }
+}
+
+/*
+ * clear_user_page
+ * @to: P1 address
+ * @address: U0 address to be mapped
+ */
+void clear_user_page(void *to, unsigned long address, struct page *pg)
+{
+       struct page *page = virt_to_page(to);
+
+       __set_bit(PG_mapped, &page->flags);
+       if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) {
+               clear_page(to);
+               __flush_wback_region(to, PAGE_SIZE);
+       } else {
+               __flush_purge_virtual_region(to,
+                                            (void *)(address & 0xfffff000),
+                                            PAGE_SIZE);
+               clear_page(to);
+               __flush_wback_region(to, PAGE_SIZE);
+       }
+}
+
+/*
+ * copy_user_page
+ * @to: P1 address
+ * @from: P1 address
+ * @address: U0 address to be mapped
+ */
+void copy_user_page(void *to, void *from, unsigned long address, struct page *pg)
+{
+       struct page *page = virt_to_page(to);
+
+
+       __set_bit(PG_mapped, &page->flags);
+       if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) {
+               copy_page(to, from);
+               __flush_wback_region(to, PAGE_SIZE);
+       } else {
+               __flush_purge_virtual_region(to,
+                                            (void *)(address & 0xfffff000),
+                                            PAGE_SIZE);
+               copy_page(to, from);
+               __flush_wback_region(to, PAGE_SIZE);
+       }
+}
+
+/*
+ * For SH7705, we have our own implementation for ptep_get_and_clear
+ * Copied from pg-sh4.c
+ */
+inline pte_t ptep_get_and_clear(pte_t *ptep)
+{
+       pte_t pte = *ptep;
+
+       pte_clear(ptep);
+       if (!pte_not_present(pte)) {
+               unsigned long pfn = pte_pfn(pte);
+               if (pfn_valid(pfn)) {
+                       struct page *page = pfn_to_page(pfn);
+                       struct address_space *mapping = page_mapping(page);
+                       if (!mapping || !mapping_writably_mapped(mapping))
+                               __clear_bit(PG_mapped, &page->flags);
+               }
+       }
+
+       return pte;
+}
+
index 4bffcf59cdb7e1da73f6e36a24da9ad94fd24e30..7a0d5c10bf20908dfad7a58fb8f96300f1f61f2e 100644 (file)
@@ -39,6 +39,16 @@ void update_mmu_cache(struct vm_area_struct * vma,
        if (vma && current->active_mm != vma->vm_mm)
                return;
 
+#if defined(CONFIG_SH7705_CACHE_32KB)
+       struct page *page;
+       page = pte_page(pte);
+       if (VALID_PAGE(page) && !test_bit(PG_mapped, &page->flags)) {
+               unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
+               __flush_wback_region((void *)P1SEGADDR(phys), PAGE_SIZE);
+               __set_bit(PG_mapped, &page->flags);
+       }
+#endif
+
        local_irq_save(flags);
 
        /* Set PTEH register */
index 88eb05393a892471744ecfef07c6d4399e773533..406aa8d9b9476ceb93edb0a58d2fbc31b084b3d6 100644 (file)
 #define CCR_CACHE_ENABLE       CCR_CACHE_CE
 #define CCR_CACHE_INVALIDATE   CCR_CACHE_CF
 
+#if defined(CONFIG_CPU_SUBTYPE_SH7705)
+#define CCR3   0xa40000b4
+#define CCR_CACHE_16KB  0x00010000
+#define CCR_CACHE_32KB 0x00020000
+#endif
+
+
 #endif /* __ASM_CPU_SH3_CACHE_H */
 
index e4cbef283a24898eb126a49dc2ff1f623b4157a3..ff4cc74258274d885186f6d02ac65ac6f2917bbe 100644 (file)
  *  Caches are indexed (effectively) by physical address on SH-3, so
  *  we don't need them.
  */
+
+#if defined(CONFIG_SH7705_CACHE_32KB)
+
+/* SH7705 is an SH3 processor with 32KB cache. This has alias issues like the
+ * SH4. Unlike the SH4 this is a unified cache so we need to do some work
+ * in mmap when 'exec'ing a new binary
+ */
+ /* 32KB cache, 4kb PAGE sizes need to check bit 12 */
+#define CACHE_ALIAS 0x00001000
+
+struct page;
+struct mm_struct;
+struct vm_area_struct;
+
+extern void flush_cache_all(void);
+extern void flush_cache_mm(struct mm_struct *mm);
+extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
+                              unsigned long end);
+extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr);
+extern void flush_dcache_page(struct page *pg);
+extern void flush_icache_range(unsigned long start, unsigned long end);
+extern void flush_icache_page(struct vm_area_struct *vma, struct page *page);
+
+#define flush_dcache_mmap_lock(mapping)                do { } while (0)
+#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
+
+/* SH3 has unified cache so no special action needed here */
+#define flush_cache_sigtramp(vaddr)            do { } while (0)
+#define flush_page_to_ram(page)                        do { } while (0)
+#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
+
+#define p3_cache_init()                                do { } while (0)
+
+#define PG_mapped      PG_arch_1
+
+/* We provide our own get_unmapped_area to avoid cache alias issue */
+#define HAVE_ARCH_UNMAPPED_AREA
+
+#else
+
 #define flush_cache_all()                      do { } while (0)
 #define flush_cache_mm(mm)                     do { } while (0)
 #define flush_cache_range(vma, start, end)     do { } while (0)
@@ -41,5 +81,7 @@
 
 #define HAVE_ARCH_UNMAPPED_AREA
 
+#endif
+
 #endif /* __ASM_CPU_SH3_CACHEFLUSH_H */
 
index edd29349b5956be0c84429348776b7d41e72442c..4c6d129e7d91e0dbe52657c575b689d5a9fa96a5 100644 (file)
@@ -42,7 +42,13 @@ extern void (*copy_page)(void *to, void *from);
 extern void clear_page_slow(void *to);
 extern void copy_page_slow(void *to, void *from);
 
-#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH3) || !defined(CONFIG_MMU)
+#if defined(CONFIG_SH7705_CACHE_32KB) && defined(CONFIG_MMU)
+struct page;
+extern void clear_user_page(void *to, unsigned long address, struct page *pg);
+extern void copy_user_page(void *to, void *from, unsigned long address, struct page *pg);
+extern void __clear_user_page(void *to, void *orig_to);
+extern void __copy_user_page(void *to, void *from, void *orig_to);
+#elif defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH3) || !defined(CONFIG_MMU)
 #define clear_user_page(page, vaddr, pg)       clear_page(page)
 #define copy_user_page(to, from, vaddr, pg)    copy_page(to, from)
 #elif defined(CONFIG_CPU_SH4)
index 7cbe42971cfba5f889d67c862e69b6aac4e90f05..345b012bb5b0d3f3f8fb62deca0bfff4d9ce933c 100644 (file)
@@ -285,7 +285,7 @@ typedef pte_t *pte_addr_t;
 extern unsigned int kobjsize(const void *objp);
 #endif /* !CONFIG_MMU */
 
-#ifdef CONFIG_CPU_SH4
+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 extern inline pte_t ptep_get_and_clear(pte_t *ptep);
 #endif
index 8aafb71a47e16ad1a4f170150199127601ce1224..791c5da0388a129526e10192b6087f8e8b2cfb27 100644 (file)
 #define PA_DIPSW0      0xb0800000      /* Dip switch 5,6 */
 #define PA_DIPSW1      0xb0800002      /* Dip switch 7,8 */
 #define PA_LED         0xb0c00000      /* LED */
+#if defined(CONFIG_CPU_SUBTYPE_SH7705)
+#define PA_BCR         0xb0e00000
+#else
 #define PA_BCR         0xb1400000      /* FPGA */
+#endif
 
 #define PA_MRSHPC      0xb83fffe0      /* MR-SHPC-01 PCMCIA controller */
 #define PA_MRSHPC_MW1  0xb8400000      /* MR-SHPC-01 memory window base */
 #define BCR_ILCRF      (PA_BCR + 10)
 #define BCR_ILCRG      (PA_BCR + 12)
 
+#if defined(CONFIG_CPU_SUBTYPE_SH7705)
+#define IRQ_STNIC   12
+#else
 #define IRQ_STNIC      10
+#endif
 
 #endif  /* __ASM_SH_HITACHI_SE_H */