From: Paul Mundt Date: Tue, 14 Jun 2011 03:40:19 +0000 (+0900) Subject: serial: sh-sci: Abstract register maps. X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=61a6976bf19a6cf5dfcf37c3536665b316f22d49;p=linux.git serial: sh-sci: Abstract register maps. This takes a bit of a sledgehammer to the horribly CPU subtype ifdef-ridden header and abstracts all of the different register layouts in to distinct types which in turn can be overriden on a per-port basis, or permitted to default to the map matching the port type at probe time. In the process this ultimately fixes up inumerable bugs with mismatches on various CPU types (particularly the legacy ones that were obviously broken years ago and no one noticed) and provides a more tightly coupled and consolidated platform for extending and implementing generic features. Signed-off-by: Paul Mundt --- diff --git a/arch/sh/Makefile b/arch/sh/Makefile index e3d8170ad00b9..99385d0b3f3b6 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -173,6 +173,7 @@ core-$(CONFIG_HD6446X_SERIES) += arch/sh/cchips/hd6446x/ cpuincdir-$(CONFIG_CPU_SH2A) += cpu-sh2a cpuincdir-$(CONFIG_CPU_SH2) += cpu-sh2 cpuincdir-$(CONFIG_CPU_SH3) += cpu-sh3 +cpuincdir-$(CONFIG_CPU_SH4A) += cpu-sh4a cpuincdir-$(CONFIG_CPU_SH4) += cpu-sh4 cpuincdir-$(CONFIG_CPU_SH5) += cpu-sh5 cpuincdir-y += cpu-common # Must be last diff --git a/arch/sh/include/cpu-sh3/cpu/serial.h b/arch/sh/include/cpu-sh3/cpu/serial.h new file mode 100644 index 0000000000000..7766329bc1030 --- /dev/null +++ b/arch/sh/include/cpu-sh3/cpu/serial.h @@ -0,0 +1,10 @@ +#ifndef __CPU_SH3_SERIAL_H +#define __CPU_SH3_SERIAL_H + +#include + +extern struct plat_sci_port_ops sh770x_sci_port_ops; +extern struct plat_sci_port_ops sh7710_sci_port_ops; +extern struct plat_sci_port_ops sh7720_sci_port_ops; + +#endif /* __CPU_SH3_SERIAL_H */ diff --git a/arch/sh/include/cpu-sh4a/cpu/serial.h b/arch/sh/include/cpu-sh4a/cpu/serial.h new file mode 100644 index 0000000000000..ff1bc275d2108 --- /dev/null +++ b/arch/sh/include/cpu-sh4a/cpu/serial.h @@ -0,0 +1,7 @@ +#ifndef __CPU_SH4A_SERIAL_H +#define __CPU_SH4A_SERIAL_H + +/* arch/sh/kernel/cpu/sh4a/serial-sh7722.c */ +extern struct plat_sci_port_ops sh7722_sci_port_ops; + +#endif /* __CPU_SH4A_SERIAL_H */ diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile index ecab274141a8b..6f13f33a35ffc 100644 --- a/arch/sh/kernel/cpu/sh3/Makefile +++ b/arch/sh/kernel/cpu/sh3/Makefile @@ -7,15 +7,15 @@ obj-y := ex.o probe.o entry.o setup-sh3.o obj-$(CONFIG_HIBERNATION) += swsusp.o # CPU subtype setup -obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o -obj-$(CONFIG_CPU_SUBTYPE_SH7706) += setup-sh770x.o -obj-$(CONFIG_CPU_SUBTYPE_SH7707) += setup-sh770x.o -obj-$(CONFIG_CPU_SUBTYPE_SH7708) += setup-sh770x.o -obj-$(CONFIG_CPU_SUBTYPE_SH7709) += setup-sh770x.o -obj-$(CONFIG_CPU_SUBTYPE_SH7710) += setup-sh7710.o -obj-$(CONFIG_CPU_SUBTYPE_SH7712) += setup-sh7710.o -obj-$(CONFIG_CPU_SUBTYPE_SH7720) += setup-sh7720.o -obj-$(CONFIG_CPU_SUBTYPE_SH7721) += setup-sh7720.o +obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o serial-sh770x.o +obj-$(CONFIG_CPU_SUBTYPE_SH7706) += setup-sh770x.o serial-sh770x.o +obj-$(CONFIG_CPU_SUBTYPE_SH7707) += setup-sh770x.o serial-sh770x.o +obj-$(CONFIG_CPU_SUBTYPE_SH7708) += setup-sh770x.o serial-sh770x.o +obj-$(CONFIG_CPU_SUBTYPE_SH7709) += setup-sh770x.o serial-sh770x.o +obj-$(CONFIG_CPU_SUBTYPE_SH7710) += setup-sh7710.o serial-sh7710.o +obj-$(CONFIG_CPU_SUBTYPE_SH7712) += setup-sh7710.o serial-sh7710.o +obj-$(CONFIG_CPU_SUBTYPE_SH7720) += setup-sh7720.o serial-sh7720.o +obj-$(CONFIG_CPU_SUBTYPE_SH7721) += setup-sh7720.o serial-sh7720.o # Primary on-chip clocks (common) clock-$(CONFIG_CPU_SH3) := clock-sh3.o diff --git a/arch/sh/kernel/cpu/sh3/serial-sh770x.c b/arch/sh/kernel/cpu/sh3/serial-sh770x.c new file mode 100644 index 0000000000000..4f7242c676b37 --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/serial-sh770x.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include + +#define SCPCR 0xA4000116 +#define SCPDR 0xA4000136 + +static void sh770x_sci_init_pins(struct uart_port *port, unsigned int cflag) +{ + unsigned short data; + + /* We need to set SCPCR to enable RTS/CTS */ + data = __raw_readw(SCPCR); + /* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/ + __raw_writew(data & 0x0fcf, SCPCR); + + if (!(cflag & CRTSCTS)) { + /* We need to set SCPCR to enable RTS/CTS */ + data = __raw_readw(SCPCR); + /* Clear out SCP7MD1,0, SCP4MD1,0, + Set SCP6MD1,0 = {01} (output) */ + __raw_writew((data & 0x0fcf) | 0x1000, SCPCR); + + data = __raw_readb(SCPDR); + /* Set /RTS2 (bit6) = 0 */ + __raw_writeb(data & 0xbf, SCPDR); + } +} + +struct plat_sci_port_ops sh770x_sci_port_ops = { + .init_pins = sh770x_sci_init_pins, +}; diff --git a/arch/sh/kernel/cpu/sh3/serial-sh7710.c b/arch/sh/kernel/cpu/sh3/serial-sh7710.c new file mode 100644 index 0000000000000..42190ef6aebfc --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/serial-sh7710.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +#define PACR 0xa4050100 +#define PBCR 0xa4050102 + +static void sh7710_sci_init_pins(struct uart_port *port, unsigned int cflag) +{ + if (port->mapbase == 0xA4400000) { + __raw_writew(__raw_readw(PACR) & 0xffc0, PACR); + __raw_writew(__raw_readw(PBCR) & 0x0fff, PBCR); + } else if (port->mapbase == 0xA4410000) + __raw_writew(__raw_readw(PBCR) & 0xf003, PBCR); +} + +struct plat_sci_port_ops sh7710_sci_port_ops = { + .init_pins = sh7710_sci_init_pins, +}; diff --git a/arch/sh/kernel/cpu/sh3/serial-sh7720.c b/arch/sh/kernel/cpu/sh3/serial-sh7720.c new file mode 100644 index 0000000000000..8234e1e7abd99 --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/serial-sh7720.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +static void sh7720_sci_init_pins(struct uart_port *port, unsigned int cflag) +{ + unsigned short data; + + if (cflag & CRTSCTS) { + /* enable RTS/CTS */ + if (port->mapbase == 0xa4430000) { /* SCIF0 */ + /* Clear PTCR bit 9-2; enable all scif pins but sck */ + data = __raw_readw(PORT_PTCR); + __raw_writew((data & 0xfc03), PORT_PTCR); + } else if (port->mapbase == 0xa4438000) { /* SCIF1 */ + /* Clear PVCR bit 9-2 */ + data = __raw_readw(PORT_PVCR); + __raw_writew((data & 0xfc03), PORT_PVCR); + } + } else { + if (port->mapbase == 0xa4430000) { /* SCIF0 */ + /* Clear PTCR bit 5-2; enable only tx and rx */ + data = __raw_readw(PORT_PTCR); + __raw_writew((data & 0xffc3), PORT_PTCR); + } else if (port->mapbase == 0xa4438000) { /* SCIF1 */ + /* Clear PVCR bit 5-2 */ + data = __raw_readw(PORT_PVCR); + __raw_writew((data & 0xffc3), PORT_PVCR); + } + } +} + +struct plat_sci_port_ops sh7720_sci_port_ops = { + .init_pins = sh7720_sci_init_pins, +}; diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c index cd2e702feb7e1..2309618c015d0 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7705.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c @@ -15,6 +15,7 @@ #include #include #include +#include enum { UNUSED = 0, @@ -75,6 +76,8 @@ static struct plat_sci_port scif0_platform_data = { .scbrr_algo_id = SCBRR_ALGO_4, .type = PORT_SCIF, .irqs = { 56, 56, 56 }, + .ops = &sh770x_sci_port_ops, + .regtype = SCIx_SH7705_SCIF_REGTYPE, }; static struct platform_device scif0_device = { @@ -92,6 +95,8 @@ static struct plat_sci_port scif1_platform_data = { .scbrr_algo_id = SCBRR_ALGO_4, .type = PORT_SCIF, .irqs = { 52, 52, 52 }, + .ops = &sh770x_sci_port_ops, + .regtype = SCIx_SH7705_SCIF_REGTYPE, }; static struct platform_device scif1_device = { diff --git a/arch/sh/kernel/cpu/sh3/setup-sh770x.c b/arch/sh/kernel/cpu/sh3/setup-sh770x.c index 6d549792f791d..3f3d5fe5892d0 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh770x.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh770x.c @@ -19,6 +19,7 @@ #include #include #include +#include enum { UNUSED = 0, @@ -114,6 +115,8 @@ static struct plat_sci_port scif0_platform_data = { .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCI, .irqs = { 23, 23, 23, 0 }, + .ops = &sh770x_sci_port_ops, + .regshift = 1, }; static struct platform_device scif0_device = { @@ -133,6 +136,8 @@ static struct plat_sci_port scif1_platform_data = { .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, .irqs = { 56, 56, 56, 56 }, + .ops = &sh770x_sci_port_ops, + .regtype = SCIx_SH3_SCIF_REGTYPE, }; static struct platform_device scif1_device = { @@ -147,11 +152,14 @@ static struct platform_device scif1_device = { defined(CONFIG_CPU_SUBTYPE_SH7709) static struct plat_sci_port scif2_platform_data = { .mapbase = 0xa4000140, + .port_reg = SCIx_NOT_SUPPORTED, .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_TE | SCSCR_RE, .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_IRDA, .irqs = { 52, 52, 52, 52 }, + .ops = &sh770x_sci_port_ops, + .regshift = 1, }; static struct platform_device scif2_device = { diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7720.c b/arch/sh/kernel/cpu/sh3/setup-sh7720.c index 365b94a6fcb7d..94920345c14db 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7720.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7720.c @@ -20,6 +20,7 @@ #include #include #include +#include static struct resource rtc_resources[] = { [0] = { @@ -55,6 +56,8 @@ static struct plat_sci_port scif0_platform_data = { .scbrr_algo_id = SCBRR_ALGO_4, .type = PORT_SCIF, .irqs = { 80, 80, 80, 80 }, + .ops = &sh7720_sci_port_ops, + .regtype = SCIx_SH7705_SCIF_REGTYPE, }; static struct platform_device scif0_device = { @@ -72,6 +75,8 @@ static struct plat_sci_port scif1_platform_data = { .scbrr_algo_id = SCBRR_ALGO_4, .type = PORT_SCIF, .irqs = { 81, 81, 81, 81 }, + .ops = &sh7720_sci_port_ops, + .regtype = SCIx_SH7705_SCIF_REGTYPE, }; static struct platform_device scif1_device = { diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c index 8ea26e791187b..c10db5b96e597 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c @@ -1,5 +1,5 @@ /* - * SH7750/SH7751 Setup + * SH7091/SH7750/SH7750S/SH7750R/SH7751/SH7751R Setup * * Copyright (C) 2006 Paul Mundt * Copyright (C) 2006 Jamie Lenehan @@ -44,6 +44,7 @@ static struct plat_sci_port sci_platform_data = { .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCI, .irqs = { 23, 23, 23, 0 }, + .regshift = 2, }; static struct platform_device sci_device = { diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c index 78bbf232e3916..c0b4c774700ec 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c @@ -133,6 +133,7 @@ static struct plat_sci_port scif0_platform_data = { .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, .irqs = { 52, 53, 55, 54 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif0_device = { @@ -150,6 +151,7 @@ static struct plat_sci_port scif1_platform_data = { .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .scbrr_algo_id = SCBRR_ALGO_2, .irqs = { 72, 73, 75, 74 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif1_device = { @@ -167,6 +169,7 @@ static struct plat_sci_port scif2_platform_data = { .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, .irqs = { 76, 77, 79, 78 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif2_device = { @@ -184,6 +187,7 @@ static struct plat_sci_port scif3_platform_data = { .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCI, .irqs = { 80, 81, 82, 0 }, + .regshift = 2, }; static struct platform_device scif3_device = { diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile index cc122b1d30354..c57fb287011e0 100644 --- a/arch/sh/kernel/cpu/sh4a/Makefile +++ b/arch/sh/kernel/cpu/sh4a/Makefile @@ -10,7 +10,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7780) += setup-sh7780.o obj-$(CONFIG_CPU_SUBTYPE_SH7785) += setup-sh7785.o obj-$(CONFIG_CPU_SUBTYPE_SH7786) += setup-sh7786.o intc-shx3.o obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o -obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o +obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o serial-sh7722.o obj-$(CONFIG_CPU_SUBTYPE_SH7723) += setup-sh7723.o obj-$(CONFIG_CPU_SUBTYPE_SH7724) += setup-sh7724.o obj-$(CONFIG_CPU_SUBTYPE_SH7366) += setup-sh7366.o diff --git a/arch/sh/kernel/cpu/sh4a/serial-sh7722.c b/arch/sh/kernel/cpu/sh4a/serial-sh7722.c new file mode 100644 index 0000000000000..59bc3a72702e3 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4a/serial-sh7722.c @@ -0,0 +1,23 @@ +#include +#include +#include + +#define PSCR 0xA405011E + +static void sh7722_sci_init_pins(struct uart_port *port, unsigned int cflag) +{ + unsigned short data; + + if (port->mapbase == 0xffe00000) { + data = __raw_readw(PSCR); + data &= ~0x03cf; + if (!(cflag & CRTSCTS)) + data |= 0x0340; + + __raw_writew(data, PSCR); + } +} + +struct plat_sci_port_ops sh7722_sci_port_ops = { + .init_pins = sh7722_sci_init_pins, +}; diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c index 82616af64d622..87773869a2f3e 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c @@ -20,6 +20,7 @@ static struct plat_sci_port scif0_platform_data = { .mapbase = 0xffe00000, + .port_reg = 0xa405013e, .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .scbrr_algo_id = SCBRR_ALGO_2, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index 5813d8023619d..863249dbf05b7 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c @@ -185,6 +185,8 @@ static struct plat_sci_port scif0_platform_data = { .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, .irqs = { 80, 80, 80, 80 }, + .ops = &sh7722_sci_port_ops, + .regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE, }; static struct platform_device scif0_device = { @@ -202,6 +204,8 @@ static struct plat_sci_port scif1_platform_data = { .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, .irqs = { 81, 81, 81, 81 }, + .ops = &sh7722_sci_port_ops, + .regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE, }; static struct platform_device scif1_device = { @@ -219,6 +223,8 @@ static struct plat_sci_port scif2_platform_data = { .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, .irqs = { 82, 82, 82, 82 }, + .ops = &sh7722_sci_port_ops, + .regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE, }; static struct platform_device scif2_device = { diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c index 072382280f96b..3c2810d8f72e3 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c @@ -23,11 +23,13 @@ /* Serial */ static struct plat_sci_port scif0_platform_data = { .mapbase = 0xffe00000, + .port_reg = 0xa4050160, .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, .irqs = { 80, 80, 80, 80 }, + .regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE, }; static struct platform_device scif0_device = { @@ -40,11 +42,13 @@ static struct platform_device scif0_device = { static struct plat_sci_port scif1_platform_data = { .mapbase = 0xffe10000, + .port_reg = SCIx_NOT_SUPPORTED, .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, .irqs = { 81, 81, 81, 81 }, + .regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE, }; static struct platform_device scif1_device = { @@ -57,11 +61,13 @@ static struct platform_device scif1_device = { static struct plat_sci_port scif2_platform_data = { .mapbase = 0xffe20000, + .port_reg = SCIx_NOT_SUPPORTED, .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, .irqs = { 82, 82, 82, 82 }, + .regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE, }; static struct platform_device scif2_device = { @@ -75,6 +81,7 @@ static struct platform_device scif2_device = { static struct plat_sci_port scif3_platform_data = { .mapbase = 0xa4e30000, .flags = UPF_BOOT_AUTOCONF, + .port_reg = SCIx_NOT_SUPPORTED, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .scbrr_algo_id = SCBRR_ALGO_3, .type = PORT_SCIFA, @@ -91,6 +98,7 @@ static struct platform_device scif3_device = { static struct plat_sci_port scif4_platform_data = { .mapbase = 0xa4e40000, + .port_reg = SCIx_NOT_SUPPORTED, .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .scbrr_algo_id = SCBRR_ALGO_3, @@ -108,6 +116,7 @@ static struct platform_device scif4_device = { static struct plat_sci_port scif5_platform_data = { .mapbase = 0xa4e50000, + .port_reg = SCIx_NOT_SUPPORTED, .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .scbrr_algo_id = SCBRR_ALGO_3, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c index 0333fe9e38819..8c892887ebd74 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c @@ -256,11 +256,13 @@ static struct platform_device dma1_device = { /* Serial */ static struct plat_sci_port scif0_platform_data = { .mapbase = 0xffe00000, + .port_reg = SCIx_NOT_SUPPORTED, .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, .irqs = { 80, 80, 80, 80 }, + .regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE, }; static struct platform_device scif0_device = { @@ -273,11 +275,13 @@ static struct platform_device scif0_device = { static struct plat_sci_port scif1_platform_data = { .mapbase = 0xffe10000, + .port_reg = SCIx_NOT_SUPPORTED, .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, .irqs = { 81, 81, 81, 81 }, + .regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE, }; static struct platform_device scif1_device = { @@ -290,11 +294,13 @@ static struct platform_device scif1_device = { static struct plat_sci_port scif2_platform_data = { .mapbase = 0xffe20000, + .port_reg = SCIx_NOT_SUPPORTED, .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, .irqs = { 82, 82, 82, 82 }, + .regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE, }; static struct platform_device scif2_device = { @@ -307,6 +313,7 @@ static struct platform_device scif2_device = { static struct plat_sci_port scif3_platform_data = { .mapbase = 0xa4e30000, + .port_reg = SCIx_NOT_SUPPORTED, .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_3, @@ -324,6 +331,7 @@ static struct platform_device scif3_device = { static struct plat_sci_port scif4_platform_data = { .mapbase = 0xa4e40000, + .port_reg = SCIx_NOT_SUPPORTED, .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_3, @@ -341,6 +349,7 @@ static struct platform_device scif4_device = { static struct plat_sci_port scif5_platform_data = { .mapbase = 0xa4e50000, + .port_reg = SCIx_NOT_SUPPORTED, .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_3, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c index 593eca6509b55..00113515f2338 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c @@ -23,6 +23,7 @@ static struct plat_sci_port scif0_platform_data = { .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, .irqs = { 40, 40, 40, 40 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif0_device = { @@ -40,6 +41,7 @@ static struct plat_sci_port scif1_platform_data = { .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, .irqs = { 76, 76, 76, 76 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif1_device = { @@ -57,6 +59,7 @@ static struct plat_sci_port scif2_platform_data = { .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, .irqs = { 104, 104, 104, 104 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif2_device = { diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c index 08add7fa68497..3d4d2075c19ad 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c @@ -14,7 +14,6 @@ #include #include #include - #include static struct plat_sci_port scif0_platform_data = { @@ -24,6 +23,7 @@ static struct plat_sci_port scif0_platform_data = { .scbrr_algo_id = SCBRR_ALGO_1, .type = PORT_SCIF, .irqs = { 40, 40, 40, 40 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif0_device = { @@ -41,6 +41,7 @@ static struct plat_sci_port scif1_platform_data = { .scbrr_algo_id = SCBRR_ALGO_1, .type = PORT_SCIF, .irqs = { 76, 76, 76, 76 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif1_device = { diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c index 18d8fc136fb2b..b29e6340414ab 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c @@ -15,9 +15,7 @@ #include #include #include - #include - #include static struct plat_sci_port scif0_platform_data = { @@ -27,6 +25,7 @@ static struct plat_sci_port scif0_platform_data = { .scbrr_algo_id = SCBRR_ALGO_1, .type = PORT_SCIF, .irqs = { 40, 40, 40, 40 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif0_device = { @@ -44,6 +43,7 @@ static struct plat_sci_port scif1_platform_data = { .scbrr_algo_id = SCBRR_ALGO_1, .type = PORT_SCIF, .irqs = { 44, 44, 44, 44 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif1_device = { @@ -61,6 +61,7 @@ static struct plat_sci_port scif2_platform_data = { .scbrr_algo_id = SCBRR_ALGO_1, .type = PORT_SCIF, .irqs = { 60, 60, 60, 60 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif2_device = { @@ -78,6 +79,7 @@ static struct plat_sci_port scif3_platform_data = { .scbrr_algo_id = SCBRR_ALGO_1, .type = PORT_SCIF, .irqs = { 61, 61, 61, 61 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif3_device = { @@ -95,6 +97,7 @@ static struct plat_sci_port scif4_platform_data = { .scbrr_algo_id = SCBRR_ALGO_1, .type = PORT_SCIF, .irqs = { 62, 62, 62, 62 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif4_device = { @@ -112,6 +115,7 @@ static struct plat_sci_port scif5_platform_data = { .scbrr_algo_id = SCBRR_ALGO_1, .type = PORT_SCIF, .irqs = { 63, 63, 63, 63 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif5_device = { diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c index beba32beb6d98..dd5e709f98216 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c @@ -1,7 +1,7 @@ /* * SH7786 Setup * - * Copyright (C) 2009 - 2010 Renesas Solutions Corp. + * Copyright (C) 2009 - 2011 Renesas Solutions Corp. * Kuninori Morimoto * Paul Mundt * @@ -33,6 +33,7 @@ static struct plat_sci_port scif0_platform_data = { .scbrr_algo_id = SCBRR_ALGO_1, .type = PORT_SCIF, .irqs = { 40, 41, 43, 42 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif0_device = { @@ -53,6 +54,7 @@ static struct plat_sci_port scif1_platform_data = { .scbrr_algo_id = SCBRR_ALGO_1, .type = PORT_SCIF, .irqs = { 44, 44, 44, 44 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif1_device = { @@ -70,6 +72,7 @@ static struct plat_sci_port scif2_platform_data = { .scbrr_algo_id = SCBRR_ALGO_1, .type = PORT_SCIF, .irqs = { 50, 50, 50, 50 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif2_device = { @@ -87,6 +90,7 @@ static struct plat_sci_port scif3_platform_data = { .scbrr_algo_id = SCBRR_ALGO_1, .type = PORT_SCIF, .irqs = { 51, 51, 51, 51 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif3_device = { @@ -104,6 +108,7 @@ static struct plat_sci_port scif4_platform_data = { .scbrr_algo_id = SCBRR_ALGO_1, .type = PORT_SCIF, .irqs = { 52, 52, 52, 52 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif4_device = { @@ -121,6 +126,7 @@ static struct plat_sci_port scif5_platform_data = { .scbrr_algo_id = SCBRR_ALGO_1, .type = PORT_SCIF, .irqs = { 53, 53, 53, 53 }, + .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif5_device = { diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 3248ddaa889df..14e1bae503922 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -117,6 +117,255 @@ to_sci_port(struct uart_port *uart) return container_of(uart, struct sci_port, port); } +struct plat_sci_reg { + u8 offset, size; +}; + +/* Helper for invalidating specific entries of an inherited map. */ +#define sci_reg_invalid { .offset = 0, .size = 0 } + +static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { + [SCIx_PROBE_REGTYPE] = { + [0 ... SCIx_NR_REGS - 1] = sci_reg_invalid, + }, + + /* + * Common SCI definitions, dependent on the port's regshift + * value. + */ + [SCIx_SCI_REGTYPE] = { + [SCSMR] = { 0x00, 8 }, + [SCBRR] = { 0x01, 8 }, + [SCSCR] = { 0x02, 8 }, + [SCxTDR] = { 0x03, 8 }, + [SCxSR] = { 0x04, 8 }, + [SCxRDR] = { 0x05, 8 }, + [SCFCR] = sci_reg_invalid, + [SCFDR] = sci_reg_invalid, + [SCTFDR] = sci_reg_invalid, + [SCRFDR] = sci_reg_invalid, + [SCSPTR] = sci_reg_invalid, + [SCLSR] = sci_reg_invalid, + }, + + /* + * Common definitions for legacy IrDA ports, dependent on + * regshift value. + */ + [SCIx_IRDA_REGTYPE] = { + [SCSMR] = { 0x00, 8 }, + [SCBRR] = { 0x01, 8 }, + [SCSCR] = { 0x02, 8 }, + [SCxTDR] = { 0x03, 8 }, + [SCxSR] = { 0x04, 8 }, + [SCxRDR] = { 0x05, 8 }, + [SCFCR] = { 0x06, 8 }, + [SCFDR] = { 0x07, 16 }, + [SCTFDR] = sci_reg_invalid, + [SCRFDR] = sci_reg_invalid, + [SCSPTR] = sci_reg_invalid, + [SCLSR] = sci_reg_invalid, + }, + + /* + * Common SCIFA definitions. + */ + [SCIx_SCIFA_REGTYPE] = { + [SCSMR] = { 0x00, 16 }, + [SCBRR] = { 0x04, 8 }, + [SCSCR] = { 0x08, 16 }, + [SCxTDR] = { 0x20, 8 }, + [SCxSR] = { 0x14, 16 }, + [SCxRDR] = { 0x24, 8 }, + [SCFCR] = { 0x18, 16 }, + [SCFDR] = { 0x1c, 16 }, + [SCTFDR] = sci_reg_invalid, + [SCRFDR] = sci_reg_invalid, + [SCSPTR] = sci_reg_invalid, + [SCLSR] = sci_reg_invalid, + }, + + /* + * Common SCIFB definitions. + */ + [SCIx_SCIFB_REGTYPE] = { + [SCSMR] = { 0x00, 16 }, + [SCBRR] = { 0x04, 8 }, + [SCSCR] = { 0x08, 16 }, + [SCxTDR] = { 0x40, 8 }, + [SCxSR] = { 0x14, 16 }, + [SCxRDR] = { 0x60, 8 }, + [SCFCR] = { 0x18, 16 }, + [SCFDR] = { 0x1c, 16 }, + [SCTFDR] = sci_reg_invalid, + [SCRFDR] = sci_reg_invalid, + [SCSPTR] = sci_reg_invalid, + [SCLSR] = sci_reg_invalid, + }, + + /* + * Common SH-3 SCIF definitions. + */ + [SCIx_SH3_SCIF_REGTYPE] = { + [SCSMR] = { 0x00, 8 }, + [SCBRR] = { 0x02, 8 }, + [SCSCR] = { 0x04, 8 }, + [SCxTDR] = { 0x06, 8 }, + [SCxSR] = { 0x08, 16 }, + [SCxRDR] = { 0x0a, 8 }, + [SCFCR] = { 0x0c, 8 }, + [SCFDR] = { 0x0e, 16 }, + [SCTFDR] = sci_reg_invalid, + [SCRFDR] = sci_reg_invalid, + [SCSPTR] = sci_reg_invalid, + [SCLSR] = sci_reg_invalid, + }, + + /* + * Common SH-4(A) SCIF(B) definitions. + */ + [SCIx_SH4_SCIF_REGTYPE] = { + [SCSMR] = { 0x00, 16 }, + [SCBRR] = { 0x04, 8 }, + [SCSCR] = { 0x08, 16 }, + [SCxTDR] = { 0x0c, 8 }, + [SCxSR] = { 0x10, 16 }, + [SCxRDR] = { 0x14, 8 }, + [SCFCR] = { 0x18, 16 }, + [SCFDR] = { 0x1c, 16 }, + [SCTFDR] = sci_reg_invalid, + [SCRFDR] = sci_reg_invalid, + [SCSPTR] = { 0x20, 16 }, + [SCLSR] = { 0x24, 16 }, + }, + + /* + * Common SH-4(A) SCIF(B) definitions for ports without an SCSPTR + * register. + */ + [SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE] = { + [SCSMR] = { 0x00, 16 }, + [SCBRR] = { 0x04, 8 }, + [SCSCR] = { 0x08, 16 }, + [SCxTDR] = { 0x0c, 8 }, + [SCxSR] = { 0x10, 16 }, + [SCxRDR] = { 0x14, 8 }, + [SCFCR] = { 0x18, 16 }, + [SCFDR] = { 0x1c, 16 }, + [SCTFDR] = sci_reg_invalid, + [SCRFDR] = sci_reg_invalid, + [SCSPTR] = sci_reg_invalid, + [SCLSR] = { 0x24, 16 }, + }, + + /* + * Common SH-4(A) SCIF(B) definitions for ports with FIFO data + * count registers. + */ + [SCIx_SH4_SCIF_FIFODATA_REGTYPE] = { + [SCSMR] = { 0x00, 16 }, + [SCBRR] = { 0x04, 8 }, + [SCSCR] = { 0x08, 16 }, + [SCxTDR] = { 0x0c, 8 }, + [SCxSR] = { 0x10, 16 }, + [SCxRDR] = { 0x14, 8 }, + [SCFCR] = { 0x18, 16 }, + [SCFDR] = { 0x1c, 16 }, + [SCTFDR] = { 0x1c, 16 }, /* aliased to SCFDR */ + [SCRFDR] = { 0x20, 16 }, + [SCSPTR] = { 0x24, 16 }, + [SCLSR] = { 0x28, 16 }, + }, + + /* + * SH7705-style SCIF(B) ports, lacking both SCSPTR and SCLSR + * registers. + */ + [SCIx_SH7705_SCIF_REGTYPE] = { + [SCSMR] = { 0x00, 16 }, + [SCBRR] = { 0x04, 8 }, + [SCSCR] = { 0x08, 16 }, + [SCxTDR] = { 0x20, 8 }, + [SCxSR] = { 0x14, 16 }, + [SCxRDR] = { 0x24, 8 }, + [SCFCR] = { 0x18, 16 }, + [SCFDR] = { 0x1c, 16 }, + [SCTFDR] = sci_reg_invalid, + [SCRFDR] = sci_reg_invalid, + [SCSPTR] = sci_reg_invalid, + [SCLSR] = sci_reg_invalid, + }, +}; + +/* + * The "offset" here is rather misleading, in that it refers to an enum + * value relative to the port mapping rather than the fixed offset + * itself, which needs to be manually retrieved from the platform's + * register map for the given port. + */ +static unsigned int sci_serial_in(struct uart_port *p, int offset) +{ + struct sci_port *s = to_sci_port(p); + struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + offset; + + if (reg->size == 8) + return ioread8(p->membase + (reg->offset << p->regshift)); + else if (reg->size == 16) + return ioread16(p->membase + (reg->offset << p->regshift)); + else + WARN(1, "Invalid register access\n"); + + return 0; +} + +static void sci_serial_out(struct uart_port *p, int offset, int value) +{ + struct sci_port *s = to_sci_port(p); + struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + offset; + + if (reg->size == 8) + iowrite8(value, p->membase + (reg->offset << p->regshift)); + else if (reg->size == 16) + iowrite16(value, p->membase + (reg->offset << p->regshift)); + else + WARN(1, "Invalid register access\n"); +} + +#define sci_in(up, offset) (up->serial_in(up, offset)) +#define sci_out(up, offset, value) (up->serial_out(up, offset, value)) + +static int sci_probe_regmap(struct plat_sci_port *cfg) +{ + switch (cfg->type) { + case PORT_SCI: + cfg->regtype = SCIx_SCI_REGTYPE; + break; + case PORT_IRDA: + cfg->regtype = SCIx_IRDA_REGTYPE; + break; + case PORT_SCIFA: + cfg->regtype = SCIx_SCIFA_REGTYPE; + break; + case PORT_SCIFB: + cfg->regtype = SCIx_SCIFB_REGTYPE; + break; + case PORT_SCIF: + /* + * The SH-4 is a bit of a misnomer here, although that's + * where this particular port layout originated. This + * configuration (or some slight variation thereof) + * remains the dominant model for all SCIFs. + */ + cfg->regtype = SCIx_SH4_SCIF_REGTYPE; + break; + default: + printk(KERN_ERR "Can't probe register map for given port\n"); + return -EINVAL; + } + + return 0; +} + #if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE) #ifdef CONFIG_CONSOLE_POLL @@ -160,103 +409,29 @@ static void sci_poll_put_char(struct uart_port *port, unsigned char c) } #endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */ -#if defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) -static inline void sci_init_pins(struct uart_port *port, unsigned int cflag) -{ - if (port->mapbase == 0xA4400000) { - __raw_writew(__raw_readw(PACR) & 0xffc0, PACR); - __raw_writew(__raw_readw(PBCR) & 0x0fff, PBCR); - } else if (port->mapbase == 0xA4410000) - __raw_writew(__raw_readw(PBCR) & 0xf003, PBCR); -} -#elif defined(CONFIG_CPU_SUBTYPE_SH7720) || defined(CONFIG_CPU_SUBTYPE_SH7721) -static inline void sci_init_pins(struct uart_port *port, unsigned int cflag) -{ - unsigned short data; - - if (cflag & CRTSCTS) { - /* enable RTS/CTS */ - if (port->mapbase == 0xa4430000) { /* SCIF0 */ - /* Clear PTCR bit 9-2; enable all scif pins but sck */ - data = __raw_readw(PORT_PTCR); - __raw_writew((data & 0xfc03), PORT_PTCR); - } else if (port->mapbase == 0xa4438000) { /* SCIF1 */ - /* Clear PVCR bit 9-2 */ - data = __raw_readw(PORT_PVCR); - __raw_writew((data & 0xfc03), PORT_PVCR); - } - } else { - if (port->mapbase == 0xa4430000) { /* SCIF0 */ - /* Clear PTCR bit 5-2; enable only tx and rx */ - data = __raw_readw(PORT_PTCR); - __raw_writew((data & 0xffc3), PORT_PTCR); - } else if (port->mapbase == 0xa4438000) { /* SCIF1 */ - /* Clear PVCR bit 5-2 */ - data = __raw_readw(PORT_PVCR); - __raw_writew((data & 0xffc3), PORT_PVCR); - } - } -} -#elif defined(CONFIG_CPU_SH3) -/* For SH7705, SH7706, SH7707, SH7709, SH7709A, SH7729 */ -static inline void sci_init_pins(struct uart_port *port, unsigned int cflag) +static void sci_init_pins(struct uart_port *port, unsigned int cflag) { - unsigned short data; - - /* We need to set SCPCR to enable RTS/CTS */ - data = __raw_readw(SCPCR); - /* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/ - __raw_writew(data & 0x0fcf, SCPCR); - - if (!(cflag & CRTSCTS)) { - /* We need to set SCPCR to enable RTS/CTS */ - data = __raw_readw(SCPCR); - /* Clear out SCP7MD1,0, SCP4MD1,0, - Set SCP6MD1,0 = {01} (output) */ - __raw_writew((data & 0x0fcf) | 0x1000, SCPCR); + struct sci_port *s = to_sci_port(port); + struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + SCSPTR; - data = __raw_readb(SCPDR); - /* Set /RTS2 (bit6) = 0 */ - __raw_writeb(data & 0xbf, SCPDR); + /* + * Use port-specific handler if provided. + */ + if (s->cfg->ops && s->cfg->ops->init_pins) { + s->cfg->ops->init_pins(port, cflag); + return; } -} -#elif defined(CONFIG_CPU_SUBTYPE_SH7722) -static inline void sci_init_pins(struct uart_port *port, unsigned int cflag) -{ - unsigned short data; - if (port->mapbase == 0xffe00000) { - data = __raw_readw(PSCR); - data &= ~0x03cf; - if (!(cflag & CRTSCTS)) - data |= 0x0340; + /* + * For the generic path SCSPTR is necessary. Bail out if that's + * unavailable, too. + */ + if (!reg->size) + return; - __raw_writew(data, PSCR); - } -} -#elif defined(CONFIG_CPU_SUBTYPE_SH7757) || \ - defined(CONFIG_CPU_SUBTYPE_SH7763) || \ - defined(CONFIG_CPU_SUBTYPE_SH7780) || \ - defined(CONFIG_CPU_SUBTYPE_SH7785) || \ - defined(CONFIG_CPU_SUBTYPE_SH7786) || \ - defined(CONFIG_CPU_SUBTYPE_SHX3) -static inline void sci_init_pins(struct uart_port *port, unsigned int cflag) -{ - if (!(cflag & CRTSCTS)) - __raw_writew(0x0080, SCSPTR0); /* Set RTS = 1 */ -} -#elif defined(CONFIG_CPU_SH4) && !defined(CONFIG_CPU_SH4A) -static inline void sci_init_pins(struct uart_port *port, unsigned int cflag) -{ if (!(cflag & CRTSCTS)) - __raw_writew(0x0080, SCSPTR2); /* Set RTS = 1 */ + sci_out(port, SCSPTR, 0x0080); /* Set RTS = 1 */ } -#else -static inline void sci_init_pins(struct uart_port *port, unsigned int cflag) -{ - /* Nothing to do */ -} -#endif #if defined(CONFIG_CPU_SUBTYPE_SH7760) || \ defined(CONFIG_CPU_SUBTYPE_SH7780) || \ @@ -1752,6 +1927,9 @@ static int __devinit sci_init_single(struct platform_device *dev, break; } + if (p->regtype == SCIx_PROBE_REGTYPE) + BUG_ON(sci_probe_regmap(p) != 0); + if (dev) { sci_port->iclk = clk_get(&dev->dev, "sci_ick"); if (IS_ERR(sci_port->iclk)) { @@ -1812,9 +1990,10 @@ static int __devinit sci_init_single(struct platform_device *dev, port->mapbase = p->mapbase; port->type = p->type; port->flags = p->flags; + port->regshift = p->regshift; /* - * The UART port needs an IRQ value, so we peg this to the TX IRQ + * The UART port needs an IRQ value, so we peg this to the RX IRQ * for the multi-IRQ ports, which is where we are primarily * concerned with the shutdown path synchronization. * @@ -1822,6 +2001,9 @@ static int __devinit sci_init_single(struct platform_device *dev, */ port->irq = p->irqs[SCIx_RXI_IRQ]; + port->serial_in = sci_serial_in; + port->serial_out = sci_serial_out; + if (p->dma_dev) dev_dbg(port->dev, "DMA device %p, tx %d, rx %d\n", p->dma_dev, p->dma_slave_tx, p->dma_slave_rx); diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h index 5834f33d20ffb..26de640a9d013 100644 --- a/drivers/tty/serial/sh-sci.h +++ b/drivers/tty/serial/sh-sci.h @@ -2,69 +2,6 @@ #include #include -#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ - defined(CONFIG_CPU_SUBTYPE_SH7706) || \ - defined(CONFIG_CPU_SUBTYPE_SH7707) || \ - defined(CONFIG_CPU_SUBTYPE_SH7708) || \ - defined(CONFIG_CPU_SUBTYPE_SH7709) -# define SCPCR 0xA4000116 /* 16 bit SCI and SCIF */ -# define SCPDR 0xA4000136 /* 8 bit SCI and SCIF */ -#elif defined(CONFIG_CPU_SUBTYPE_SH7720) || \ - defined(CONFIG_CPU_SUBTYPE_SH7721) || \ - defined(CONFIG_ARCH_SH73A0) || \ - defined(CONFIG_ARCH_SH7367) || \ - defined(CONFIG_ARCH_SH7377) || \ - defined(CONFIG_ARCH_SH7372) -# define PORT_PTCR 0xA405011EUL -# define PORT_PVCR 0xA4050122UL -#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \ - defined(CONFIG_CPU_SUBTYPE_SH7750R) || \ - defined(CONFIG_CPU_SUBTYPE_SH7750S) || \ - defined(CONFIG_CPU_SUBTYPE_SH7091) || \ - defined(CONFIG_CPU_SUBTYPE_SH7751) || \ - defined(CONFIG_CPU_SUBTYPE_SH7751R) || \ - defined(CONFIG_CPU_SUBTYPE_SH4_202) -# define SCSPTR2 0xFFE80020 /* 16 bit SCIF */ -#elif defined(CONFIG_CPU_SUBTYPE_SH7760) -# define SCSPTR0 0xfe600024 /* 16 bit SCIF */ -# define SCSPTR2 0xfe620024 /* 16 bit SCIF */ -#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) -# define SCSPTR0 0xA4400000 /* 16 bit SCIF */ -# define PACR 0xa4050100 -# define PBCR 0xa4050102 -#elif defined(CONFIG_CPU_SUBTYPE_SH7343) -# define SCSPTR0 0xffe00010 /* 16 bit SCIF */ -#elif defined(CONFIG_CPU_SUBTYPE_SH7722) -# define PWDR 0xA4050166 -# define PSCR 0xA405011E -#elif defined(CONFIG_CPU_SUBTYPE_SH7366) -# define SCPDR0 0xA405013E /* 16 bit SCIF0 PSDR */ -# define SCSPTR0 SCPDR0 -#elif defined(CONFIG_CPU_SUBTYPE_SH7723) -# define SCSPTR0 0xa4050160 -#elif defined(CONFIG_CPU_SUBTYPE_SH7757) -# define SCSPTR0 0xfe4b0020 -#elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \ - defined(CONFIG_CPU_SUBTYPE_SH7780) -# define SCSPTR0 0xffe00024 /* 16 bit SCIF */ -#elif defined(CONFIG_CPU_SUBTYPE_SH7770) -# define SCSPTR0 0xff923020 /* 16 bit SCIF */ -#elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \ - defined(CONFIG_CPU_SUBTYPE_SH7786) -# define SCSPTR0 0xffea0024 /* 16 bit SCIF */ -#elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \ - defined(CONFIG_CPU_SUBTYPE_SH7203) || \ - defined(CONFIG_CPU_SUBTYPE_SH7206) || \ - defined(CONFIG_CPU_SUBTYPE_SH7263) -# define SCSPTR0 0xfffe8020 /* 16 bit SCIF */ -#elif defined(CONFIG_CPU_SUBTYPE_SH7619) -# define SCSPTR0 0xf8400020 /* 16 bit SCIF */ -#elif defined(CONFIG_CPU_SUBTYPE_SHX3) -# define SCSPTR0 0xffc30020 /* 16 bit SCIF */ -#else -# error CPU subtype not defined -#endif - #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ defined(CONFIG_CPU_SUBTYPE_SH7720) || \ defined(CONFIG_CPU_SUBTYPE_SH7721) || \ @@ -119,162 +56,3 @@ #define SCI_MAJOR 204 #define SCI_MINOR_START 8 - -#define SCI_IN(size, offset) \ - ioread##size(port->membase + (offset)) - -#define SCI_OUT(size, offset, value) \ - iowrite##size(value, port->membase + (offset)) - -#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_SCIF || port->type == PORT_SCIFB) { \ - return SCI_IN(scif_size, scif_offset); \ - } else { /* PORT_SCI or PORT_SCIFA */ \ - return SCI_IN(sci_size, sci_offset); \ - } \ - } \ - static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \ - { \ - if (port->type == PORT_SCIF || port->type == PORT_SCIFB) { \ - SCI_OUT(scif_size, scif_offset, value); \ - } else { /* PORT_SCI or PORT_SCIFA */ \ - SCI_OUT(sci_size, sci_offset, value); \ - } \ - } - -#define CPU_SCIF_FNS(name, scif_offset, scif_size) \ - static inline unsigned int sci_##name##_in(struct uart_port *port) \ - { \ - return SCI_IN(scif_size, scif_offset); \ - } \ - static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \ - { \ - SCI_OUT(scif_size, scif_offset, value); \ - } - -#if defined(CONFIG_CPU_SH3) || \ - defined(CONFIG_ARCH_SH73A0) || \ - defined(CONFIG_ARCH_SH7367) || \ - defined(CONFIG_ARCH_SH7377) || \ - defined(CONFIG_ARCH_SH7372) -#if defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) -#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \ - sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \ - CPU_SCIx_FNS(name, sh4_sci_offset, sh4_sci_size, sh4_scif_offset, sh4_scif_size) -#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \ - CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) -#elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \ - defined(CONFIG_CPU_SUBTYPE_SH7720) || \ - defined(CONFIG_CPU_SUBTYPE_SH7721) || \ - defined(CONFIG_ARCH_SH7367) -#define SCIF_FNS(name, scif_offset, scif_size) \ - CPU_SCIF_FNS(name, scif_offset, scif_size) -#elif defined(CONFIG_ARCH_SH7377) || \ - defined(CONFIG_ARCH_SH7372) || \ - defined(CONFIG_ARCH_SH73A0) -#define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size) \ - CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size) -#define SCIF_FNS(name, scif_offset, scif_size) \ - CPU_SCIF_FNS(name, scif_offset, scif_size) -#else -#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \ - sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \ - CPU_SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh3_scif_offset, sh3_scif_size) -#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \ - CPU_SCIF_FNS(name, sh3_scif_offset, sh3_scif_size) -#endif -#elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ - defined(CONFIG_CPU_SUBTYPE_SH7724) - #define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) \ - CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) - #define SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) \ - CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) -#else -#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \ - sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \ - CPU_SCIx_FNS(name, sh4_sci_offset, sh4_sci_size, sh4_scif_offset, sh4_scif_size) -#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \ - CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) -#endif - -#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ - defined(CONFIG_CPU_SUBTYPE_SH7720) || \ - defined(CONFIG_CPU_SUBTYPE_SH7721) || \ - defined(CONFIG_ARCH_SH7367) - -SCIF_FNS(SCSMR, 0x00, 16) -SCIF_FNS(SCBRR, 0x04, 8) -SCIF_FNS(SCSCR, 0x08, 16) -SCIF_FNS(SCxSR, 0x14, 16) -SCIF_FNS(SCFCR, 0x18, 16) -SCIF_FNS(SCFDR, 0x1c, 16) -SCIF_FNS(SCxTDR, 0x20, 8) -SCIF_FNS(SCxRDR, 0x24, 8) -SCIF_FNS(SCLSR, 0x00, 0) -#elif defined(CONFIG_ARCH_SH7377) || \ - defined(CONFIG_ARCH_SH7372) || \ - defined(CONFIG_ARCH_SH73A0) -SCIF_FNS(SCSMR, 0x00, 16) -SCIF_FNS(SCBRR, 0x04, 8) -SCIF_FNS(SCSCR, 0x08, 16) -SCIF_FNS(SCTDSR, 0x0c, 16) -SCIF_FNS(SCFER, 0x10, 16) -SCIF_FNS(SCxSR, 0x14, 16) -SCIF_FNS(SCFCR, 0x18, 16) -SCIF_FNS(SCFDR, 0x1c, 16) -SCIF_FNS(SCTFDR, 0x38, 16) -SCIF_FNS(SCRFDR, 0x3c, 16) -SCIx_FNS(SCxTDR, 0x20, 8, 0x40, 8) -SCIx_FNS(SCxRDR, 0x24, 8, 0x60, 8) -SCIF_FNS(SCLSR, 0x00, 0) -#elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ - defined(CONFIG_CPU_SUBTYPE_SH7724) -SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16) -SCIx_FNS(SCBRR, 0x04, 8, 0x04, 8) -SCIx_FNS(SCSCR, 0x08, 16, 0x08, 16) -SCIx_FNS(SCxTDR, 0x20, 8, 0x0c, 8) -SCIx_FNS(SCxSR, 0x14, 16, 0x10, 16) -SCIx_FNS(SCxRDR, 0x24, 8, 0x14, 8) -SCIx_FNS(SCSPTR, 0, 0, 0, 0) -SCIF_FNS(SCFCR, 0x18, 16) -SCIF_FNS(SCFDR, 0x1c, 16) -SCIF_FNS(SCLSR, 0x24, 16) -#else -/* reg SCI/SH3 SCI/SH4 SCIF/SH3 SCIF/SH4 */ -/* name off sz off sz off sz off sz */ -SCIx_FNS(SCSMR, 0x00, 8, 0x00, 8, 0x00, 8, 0x00, 16) -SCIx_FNS(SCBRR, 0x02, 8, 0x04, 8, 0x02, 8, 0x04, 8) -SCIx_FNS(SCSCR, 0x04, 8, 0x08, 8, 0x04, 8, 0x08, 16) -SCIx_FNS(SCxTDR, 0x06, 8, 0x0c, 8, 0x06, 8, 0x0C, 8) -SCIx_FNS(SCxSR, 0x08, 8, 0x10, 8, 0x08, 16, 0x10, 16) -SCIx_FNS(SCxRDR, 0x0a, 8, 0x14, 8, 0x0A, 8, 0x14, 8) -SCIF_FNS(SCFCR, 0x0c, 8, 0x18, 16) -#if defined(CONFIG_CPU_SUBTYPE_SH7760) || \ - defined(CONFIG_CPU_SUBTYPE_SH7780) || \ - defined(CONFIG_CPU_SUBTYPE_SH7785) || \ - defined(CONFIG_CPU_SUBTYPE_SH7786) -SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16) -SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16) -SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16) -SCIF_FNS(SCSPTR, 0, 0, 0x24, 16) -SCIF_FNS(SCLSR, 0, 0, 0x28, 16) -#elif defined(CONFIG_CPU_SUBTYPE_SH7763) -SCIF_FNS(SCFDR, 0, 0, 0x1C, 16) -SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16) -SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16) -SCIF_FNS(SCSPTR, 0, 0, 0x24, 16) -SCIF_FNS(SCLSR, 0, 0, 0x28, 16) -#else -SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16) -#if defined(CONFIG_CPU_SUBTYPE_SH7722) -SCIF_FNS(SCSPTR, 0, 0, 0, 0) -#else -SCIF_FNS(SCSPTR, 0, 0, 0x20, 16) -#endif -SCIF_FNS(SCLSR, 0, 0, 0x24, 16) -#endif -#endif -#define sci_in(port, reg) sci_##reg##_in(port) -#define sci_out(port, reg, value) sci_##reg##_out(port, value) diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index ecefec7c0b670..4ca130a90ea55 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h @@ -58,6 +58,22 @@ enum { SCIx_NR_IRQS, }; +enum { + SCIx_PROBE_REGTYPE, + + SCIx_SCI_REGTYPE, + SCIx_IRDA_REGTYPE, + SCIx_SCIFA_REGTYPE, + SCIx_SCIFB_REGTYPE, + SCIx_SH3_SCIF_REGTYPE, + SCIx_SH4_SCIF_REGTYPE, + SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE, + SCIx_SH4_SCIF_FIFODATA_REGTYPE, + SCIx_SH7705_SCIF_REGTYPE, + + SCIx_NR_REGTYPES, +}; + #define SCIx_IRQ_MUXED(irq) \ { \ [SCIx_ERI_IRQ] = (irq), \ @@ -66,8 +82,24 @@ enum { [SCIx_BRI_IRQ] = (irq), \ } +/* + * SCI register subset common for all port types. + * Not all registers will exist on all parts. + */ +enum { + SCSMR, SCBRR, SCSCR, SCxSR, + SCFCR, SCFDR, SCxTDR, SCxRDR, + SCLSR, SCTFDR, SCRFDR, SCSPTR, + + SCIx_NR_REGS, +}; + struct device; +struct plat_sci_port_ops { + void (*init_pins)(struct uart_port *, unsigned int cflag); +}; + /* * Platform device specific platform_data struct */ @@ -87,6 +119,10 @@ struct plat_sci_port { unsigned int error_mask; int port_reg; + unsigned char regshift; + unsigned char regtype; + + struct plat_sci_port_ops *ops; struct device *dma_dev;