summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--arch/sh/include/asm/io.h4
-rw-r--r--arch/sh/include/asm/pgtable.h6
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7723.c6
-rw-r--r--arch/sh/kernel/early_printk.c3
-rw-r--r--arch/sh/kernel/timers/timer-tmu.c2
-rw-r--r--arch/sh/lib/copy_page.S11
-rw-r--r--arch/sh/mm/Makefile_322
-rw-r--r--arch/sh/mm/Makefile_642
-rw-r--r--arch/sh/mm/init.c12
-rw-r--r--arch/sh/mm/mmap.c31
-rw-r--r--arch/sh/mm/pg-sh4.c17
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c3
-rw-r--r--drivers/serial/sh-sci.c22
-rw-r--r--drivers/serial/sh-sci.h16
-rw-r--r--include/linux/serial_core.h3
15 files changed, 108 insertions, 32 deletions
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index 436c28539577..65eaae34e753 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -293,6 +293,10 @@ __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags)
  */
 #define xlate_dev_kmem_ptr(p)	p
 
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+int valid_phys_addr_range(unsigned long addr, size_t size);
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
+
 #endif /* __KERNEL__ */
 
 #endif /* __ASM_SH_IO_H */
diff --git a/arch/sh/include/asm/pgtable.h b/arch/sh/include/asm/pgtable.h
index 52220d70a096..b517ae08b9c0 100644
--- a/arch/sh/include/asm/pgtable.h
+++ b/arch/sh/include/asm/pgtable.h
@@ -148,6 +148,12 @@ extern void paging_init(void);
 extern void page_table_range_init(unsigned long start, unsigned long end,
 				  pgd_t *pgd);
 
+#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_CPU_SH4) && defined(CONFIG_MMU)
+extern void kmap_coherent_init(void);
+#else
+#define kmap_coherent_init()	do { } while (0)
+#endif
+
 #include <asm-generic/pgtable.h>
 
 #endif /* __ASM_SH_PGTABLE_H */
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
index a7412cede534..6d9e6972cfc9 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
@@ -119,17 +119,17 @@ static struct plat_sci_port sci_platform_data[] = {
 	},{
 		.mapbase	= 0xa4e30000,
 		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCI,
+		.type		= PORT_SCIFA,
 		.irqs		= { 56, 56, 56, 56 },
 	},{
 		.mapbase	= 0xa4e40000,
 		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCI,
+		.type		= PORT_SCIFA,
 		.irqs		= { 88, 88, 88, 88 },
 	},{
 		.mapbase	= 0xa4e50000,
 		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCI,
+		.type		= PORT_SCIFA,
 		.irqs		= { 109, 109, 109, 109 },
 	}, {
 		.flags = 0,
diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c
index 6b7d166694e2..a952dcf9999d 100644
--- a/arch/sh/kernel/early_printk.c
+++ b/arch/sh/kernel/early_printk.c
@@ -75,6 +75,7 @@ static struct console bios_console = {
 #endif
 
 static struct uart_port scif_port = {
+	.type		= PORT_SCIF,
 	.mapbase	= CONFIG_EARLY_SCIF_CONSOLE_PORT,
 	.membase	= (char __iomem *)CONFIG_EARLY_SCIF_CONSOLE_PORT,
 };
@@ -84,9 +85,9 @@ static void scif_sercon_putc(int c)
 	while (((sci_in(&scif_port, SCFDR) & EPK_FIFO_BITS) >= EPK_FIFO_SIZE))
 		;
 
-	sci_out(&scif_port, SCxTDR, c);
 	sci_in(&scif_port, SCxSR);
 	sci_out(&scif_port, SCxSR, 0xf3 & ~(0x20 | 0x40));
+	sci_out(&scif_port, SCxTDR, c);
 
 	while ((sci_in(&scif_port, SCxSR) & 0x40) == 0)
 		;
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c
index aaaf90d06b85..3c61ddd4d43e 100644
--- a/arch/sh/kernel/timers/timer-tmu.c
+++ b/arch/sh/kernel/timers/timer-tmu.c
@@ -120,7 +120,7 @@ static void tmu_set_mode(enum clock_event_mode mode,
 {
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
-		ctrl_outl(ctrl_inl(TMU0_TCNT), TMU0_TCOR);
+		ctrl_outl(tmu_latest_interval[TMU0], TMU0_TCOR);
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
 		ctrl_outl(0, TMU0_TCOR);
diff --git a/arch/sh/lib/copy_page.S b/arch/sh/lib/copy_page.S
index 5d12e657be34..43de7e8e4e17 100644
--- a/arch/sh/lib/copy_page.S
+++ b/arch/sh/lib/copy_page.S
@@ -80,6 +80,11 @@ ENTRY(copy_page)
 	.section __ex_table, "a";	\
 	.long 9999b, 6000f	;	\
 	.previous
+#define EX_NO_POP(...)			\
+	9999: __VA_ARGS__ ;		\
+	.section __ex_table, "a";	\
+	.long 9999b, 6005f	;	\
+	.previous
 ENTRY(__copy_user)
 	! Check if small number of bytes
 	mov	#11,r0
@@ -139,9 +144,9 @@ EX(	mov.b	r1,@r4		)
 	bt	1f
 
 2:
-EX(	mov.b	@r5+,r0		)
+EX_NO_POP(	mov.b	@r5+,r0		)
 	dt	r6
-EX(	mov.b	r0,@r4		)
+EX_NO_POP(	mov.b	r0,@r4		)
 	bf/s	2b
 	 add	#1,r4
 
@@ -150,7 +155,7 @@ EX(	mov.b	r0,@r4		)
 
 # Exception handler:
 .section .fixup, "ax"
-6000:
+6005:
 	mov.l	8000f,r1
 	mov	r3,r0
 	jmp	@r1
diff --git a/arch/sh/mm/Makefile_32 b/arch/sh/mm/Makefile_32
index 70e0906023cc..f066e76da204 100644
--- a/arch/sh/mm/Makefile_32
+++ b/arch/sh/mm/Makefile_32
@@ -2,7 +2,7 @@
 # Makefile for the Linux SuperH-specific parts of the memory manager.
 #
 
-obj-y			:= init.o extable_32.o consistent.o
+obj-y			:= init.o extable_32.o consistent.o mmap.o
 
 ifndef CONFIG_CACHE_OFF
 cache-$(CONFIG_CPU_SH2)		:= cache-sh2.o
diff --git a/arch/sh/mm/Makefile_64 b/arch/sh/mm/Makefile_64
index 0d92a8a3ac9a..9481d0f54efd 100644
--- a/arch/sh/mm/Makefile_64
+++ b/arch/sh/mm/Makefile_64
@@ -2,7 +2,7 @@
 # Makefile for the Linux SuperH-specific parts of the memory manager.
 #
 
-obj-y			:= init.o consistent.o
+obj-y			:= init.o consistent.o mmap.o
 
 mmu-y			:= tlb-nommu.o pg-nommu.o extable_32.o
 mmu-$(CONFIG_MMU)	:= fault_64.o ioremap_64.o tlbflush_64.o tlb-sh5.o \
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 4abf00031dae..6cbef8caeb56 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -137,6 +137,7 @@ void __init page_table_range_init(unsigned long start, unsigned long end,
 void __init paging_init(void)
 {
 	unsigned long max_zone_pfns[MAX_NR_ZONES];
+	unsigned long vaddr;
 	int nid;
 
 	/* We don't need to map the kernel through the TLB, as
@@ -148,10 +149,15 @@ void __init paging_init(void)
 	 * check for a null value. */
 	set_TTB(swapper_pg_dir);
 
-	/* Populate the relevant portions of swapper_pg_dir so that
+	/*
+	 * Populate the relevant portions of swapper_pg_dir so that
 	 * we can use the fixmap entries without calling kmalloc.
-	 * pte's will be filled in by __set_fixmap(). */
-	page_table_range_init(FIXADDR_START, FIXADDR_TOP, swapper_pg_dir);
+	 * pte's will be filled in by __set_fixmap().
+	 */
+	vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
+	page_table_range_init(vaddr, 0, swapper_pg_dir);
+
+	kmap_coherent_init();
 
 	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
 
diff --git a/arch/sh/mm/mmap.c b/arch/sh/mm/mmap.c
new file mode 100644
index 000000000000..8837d511710a
--- /dev/null
+++ b/arch/sh/mm/mmap.c
@@ -0,0 +1,31 @@
+/*
+ * arch/sh/mm/mmap.c
+ *
+ * Copyright (C) 2008  Paul Mundt
+ *
+ * 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/io.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+
+/*
+ * You really shouldn't be using read() or write() on /dev/mem.  This
+ * might go away in the future.
+ */
+int valid_phys_addr_range(unsigned long addr, size_t count)
+{
+	if (addr < __MEMORY_START)
+		return 0;
+	if (addr + count > __pa(high_memory))
+		return 0;
+
+	return 1;
+}
+
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
+{
+	return 1;
+}
diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c
index 38870e0fc182..2fe14da1f839 100644
--- a/arch/sh/mm/pg-sh4.c
+++ b/arch/sh/mm/pg-sh4.c
@@ -7,6 +7,7 @@
  * Released under the terms of the GNU GPL v2.0.
  */
 #include <linux/mm.h>
+#include <linux/init.h>
 #include <linux/mutex.h>
 #include <linux/fs.h>
 #include <linux/highmem.h>
@@ -16,6 +17,20 @@
 
 #define CACHE_ALIAS (current_cpu_data.dcache.alias_mask)
 
+#define kmap_get_fixmap_pte(vaddr)                                     \
+	pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), (vaddr))
+
+static pte_t *kmap_coherent_pte;
+
+void __init kmap_coherent_init(void)
+{
+	unsigned long vaddr;
+
+	/* cache the first coherent kmap pte */
+	vaddr = __fix_to_virt(FIX_CMAP_BEGIN);
+	kmap_coherent_pte = kmap_get_fixmap_pte(vaddr);
+}
+
 static inline void *kmap_coherent(struct page *page, unsigned long addr)
 {
 	enum fixed_addresses idx;
@@ -34,6 +49,8 @@ static inline void *kmap_coherent(struct page *page, unsigned long addr)
 
 	update_mmu_cache(NULL, vaddr, pte);
 
+	set_pte(kmap_coherent_pte - (FIX_CMAP_END - idx), pte);
+
 	return (void *)vaddr;
 }
 
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index 640cbb237328..3384a717fec0 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -318,7 +318,8 @@ static int sh_mobile_i2c_isr_rx(struct sh_mobile_i2c_data *pd)
 		} else
 			data = i2c_op(pd, OP_RX, 0);
 
-		pd->msg->buf[real_pos] = data;
+		if (real_pos >= 0)
+			pd->msg->buf[real_pos] = data;
 	} while (0);
 
 	pd->pos++;
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 5c0f32c7fbf6..165fc010978c 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -144,9 +144,9 @@ static void put_char(struct uart_port *port, char c)
 		status = sci_in(port, SCxSR);
 	} while (!(status & SCxSR_TDxE(port)));
 
-	sci_out(port, SCxTDR, c);
 	sci_in(port, SCxSR);            /* Dummy read */
 	sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
+	sci_out(port, SCxTDR, c);
 
 	spin_unlock_irqrestore(&port->lock, flags);
 }
@@ -478,10 +478,10 @@ static void sci_transmit_chars(struct uart_port *port)
 		return;
 	}
 
-	if (port->type == PORT_SCIF)
-		count = scif_txroom(port);
-	else
+	if (port->type == PORT_SCI)
 		count = sci_txroom(port);
+	else
+		count = scif_txroom(port);
 
 	do {
 		unsigned char c;
@@ -510,7 +510,7 @@ static void sci_transmit_chars(struct uart_port *port)
 	} else {
 		ctrl = sci_in(port, SCSCR);
 
-		if (port->type == PORT_SCIF) {
+		if (port->type != PORT_SCI) {
 			sci_in(port, SCxSR); /* Dummy read */
 			sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
 		}
@@ -536,10 +536,10 @@ static inline void sci_receive_chars(struct uart_port *port)
 		return;
 
 	while (1) {
-		if (port->type == PORT_SCIF)
-			count = scif_rxroom(port);
-		else
+		if (port->type == PORT_SCI)
 			count = sci_rxroom(port);
+		else
+			count = scif_rxroom(port);
 
 		/* Don't copy more bytes than there is room for in the buffer */
 		count = tty_buffer_request_room(tty, count);
@@ -714,7 +714,7 @@ static inline int sci_handle_breaks(struct uart_port *port)
 
 #if defined(SCIF_ORER)
 	/* XXX: Handle SCIF overrun error */
-	if (port->type == PORT_SCIF && (sci_in(port, SCLSR) & SCIF_ORER) != 0) {
+	if (port->type != PORT_SCI && (sci_in(port, SCLSR) & SCIF_ORER) != 0) {
 		sci_out(port, SCLSR, 0);
 		if (tty_insert_flip_char(tty, 0, TTY_OVERRUN)) {
 			copied++;
@@ -1042,7 +1042,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	sci_out(port, SCSCR, 0x00);	/* TE=0, RE=0, CKE1=0 */
 
-	if (port->type == PORT_SCIF)
+	if (port->type != PORT_SCI)
 		sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
 
 	smr_val = sci_in(port, SCSMR) & 3;
@@ -1085,6 +1085,7 @@ static const char *sci_type(struct uart_port *port)
 		case PORT_SCI:	return "sci";
 		case PORT_SCIF:	return "scif";
 		case PORT_IRDA: return "irda";
+		case PORT_SCIFA:	return "scifa";
 	}
 
 	return NULL;
@@ -1112,6 +1113,7 @@ static void sci_config_port(struct uart_port *port, int flags)
 		s->init_pins = sci_init_pins_sci;
 		break;
 	case PORT_SCIF:
+	case PORT_SCIFA:
 		s->init_pins = sci_init_pins_scif;
 		break;
 	case PORT_IRDA:
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index 6163a45f968f..9f33b064172e 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -289,18 +289,18 @@
 #define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\
   static inline unsigned int sci_##name##_in(struct uart_port *port)	\
   {									\
-    if (port->type == PORT_SCI) {					\
-      SCI_IN(sci_size, sci_offset)					\
-    } else {								\
-      SCI_IN(scif_size, scif_offset);					\
+    if (port->type == PORT_SCIF) {					\
+      SCI_IN(scif_size, scif_offset)					\
+    } else {	/* PORT_SCI or PORT_SCIFA */				\
+      SCI_IN(sci_size, sci_offset);					\
     }									\
   }									\
   static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
   {									\
-    if (port->type == PORT_SCI) {					\
-      SCI_OUT(sci_size, sci_offset, value)				\
-    } else {								\
-      SCI_OUT(scif_size, scif_offset, value);				\
+    if (port->type == PORT_SCIF) {					\
+      SCI_OUT(scif_size, scif_offset, value)				\
+    } else {	/* PORT_SCI or PORT_SCIFA */				\
+      SCI_OUT(sci_size, sci_offset, value);				\
     }									\
   }
 
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index e27f216361fc..4e4f1277f3bf 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -155,6 +155,9 @@
 
 #define PORT_SC26XX	82
 
+/* SH-SCI */
+#define PORT_SCIFA	83
+
 #ifdef __KERNEL__
 
 #include <linux/compiler.h>