patch-2.4.0-test2 linux/drivers/char/sh-sci.h
Next file: linux/drivers/char/stallion.c
Previous file: linux/drivers/char/sh-sci.c
Back to the patch index
Back to the overall index
- Lines: 489
- Date:
Mon Jun 19 17:59:40 2000
- Orig file:
v2.4.0-test1/linux/drivers/char/sh-sci.h
- Orig date:
Tue May 23 15:31:34 2000
diff -u --recursive --new-file v2.4.0-test1/linux/drivers/char/sh-sci.h linux/drivers/char/sh-sci.h
@@ -5,148 +5,135 @@
* SuperH on-chip serial module support. (SCI with no FIFO / with FIFO)
* Copyright (C) 1999, 2000 Niibe Yutaka
* Copyright (C) 2000 Greg Banks
+ * Modified to support multiple serial ports. Stuart Menefy (May 2000).
*
*/
#include <linux/config.h>
-#if defined(CONFIG_SH_SCI_SERIAL)
-#if defined(__sh3__)
-#define SCSMR (volatile unsigned char *)0xfffffe80
-#define SCBRR 0xfffffe82
-#define SCSCR (volatile unsigned char *)0xfffffe84
-#define SC_TDR 0xfffffe86
-#define SC_SR (volatile unsigned char *)0xfffffe88
-#define SC_RDR 0xfffffe8a
-#define SCSPTR 0xffffff7c
-#elif defined(__SH4__)
-#define SCSMR (volatile unsigned char *)0xffe00000
-#define SCBRR 0xffe00004
-#define SCSCR (volatile unsigned char *)0xffe00008
-#define SC_TDR 0xffe0000c
-#define SC_SR (volatile unsigned char *)0xffe00010
-#define SC_RDR 0xffe00014
-#define SCSPTR 0xffe0001c
+/* Values for sci_port->type */
+#define PORT_SCI 0
+#define PORT_SCIF 1
+
+/* Offsets into the sci_port->irqs array */
+#define SCIx_ERI_IRQ 0
+#define SCIx_RXI_IRQ 1
+#define SCIx_TXI_IRQ 2
+
+/* ERI, RXI, TXI, INTC reg, INTC pos */
+#define SCI_IRQS { 23, 24, 25 }, INTC_IPRB, 1
+#define SH3_SCIF_IRQS { 56, 57, 59 }, INTC_IPRE, 1
+#define SH4_SCIF_IRQS { 40, 41, 43 }, INTC_IPRC, 1
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7708)
+# define SCI_NPORTS 1
+# define SCI_INIT { \
+ { {}, PORT_SCI, 0xfffffe80, SCI_IRQS, sci_init_pins_sci } \
+}
+# define SCSPTR 0xffffff7c /* 8 bit */
+# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
+# define SCI_ONLY
+#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
+# define SCI_NPORTS 2
+# define SCI_INIT { \
+ { {}, PORT_SCI, 0xfffffe80, SCI_IRQS, sci_init_pins_sci }, \
+ { {}, PORT_SCIF, 0xA4000150, SH3_SCIF_IRQS, sci_init_pins_scif } \
+}
+# define SCPCR 0xA4000116 /* 16 bit SCI and SCIF */
+# define SCPDR 0xA4000136 /* 8 bit SCI and SCIF */
+# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
+# define SCI_AND_SCIF
+#elif defined(CONFIG_CPU_SUBTYPE_SH7750)
+# define SCI_NPORTS 2
+# define SCI_INIT { \
+ { {}, PORT_SCI, 0xffe00000, SCI_IRQS, sci_init_pins_sci }, \
+ { {}, PORT_SCIF, 0xFFE80000, SH4_SCIF_IRQS, sci_init_pins_scif } \
+}
+# define SCSPTR1 0xffe0001c /* 8 bit SCI */
+# define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
+# define SCLSR2 0xFFE80024 /* 16 bit SCIF */
+# define SCSCR_INIT(port) (((port)->type == PORT_SCI) ? \
+ 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ : \
+ 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ )
+# define SCI_AND_SCIF
+#else
+# error CPU subtype not defined
#endif
-#define SCSCR_INIT 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
-
-#define SCI_TD_E 0x80
-#define SCI_RD_F 0x40
-#define SCI_ORER 0x20
-#define SCI_FER 0x10
-#define SCI_PER 0x08
-#define SCI_TEND 0x04
+/* SCSCR */
+#define SCI_CTRL_FLAGS_TIE 0x80 /* all */
+#define SCI_CTRL_FLAGS_RIE 0x40 /* all */
+#define SCI_CTRL_FLAGS_TE 0x20 /* all */
+#define SCI_CTRL_FLAGS_RE 0x10 /* all */
+/* SCI_CTRL_FLAGS_REIE 0x08 * 7750 SCIF */
+/* SCI_CTRL_FLAGS_MPIE 0x08 * 7708 SCI, 7709 SCI, 7750 SCI */
+/* SCI_CTRL_FLAGS_TEIE 0x04 * 7708 SCI, 7709 SCI, 7750 SCI */
+/* SCI_CTRL_FLAGS_CKE1 0x02 * all */
+/* SCI_CTRL_FLAGS_CKE0 0x01 * 7708 SCI, 7709 SCI/SCIF, 7750 SCI */
+
+/* SCxSR SCI */
+#define SCI_TDRE 0x80 /* 7708 SCI, 7709 SCI, 7750 SCI */
+#define SCI_RDRF 0x40 /* 7708 SCI, 7709 SCI, 7750 SCI */
+#define SCI_ORER 0x20 /* 7708 SCI, 7709 SCI, 7750 SCI */
+#define SCI_FER 0x10 /* 7708 SCI, 7709 SCI, 7750 SCI */
+#define SCI_PER 0x08 /* 7708 SCI, 7709 SCI, 7750 SCI */
+#define SCI_TEND 0x04 /* 7708 SCI, 7709 SCI, 7750 SCI */
+/* SCI_MPB 0x02 * 7708 SCI, 7709 SCI, 7750 SCI */
+/* SCI_MPBT 0x01 * 7708 SCI, 7709 SCI, 7750 SCI */
#define SCI_ERRORS ( SCI_PER | SCI_FER | SCI_ORER)
-#define SCI_TD_E_CLEAR 0x78
-#define SCI_RDRF_CLEAR 0xbc
-#define SCI_ERROR_CLEAR 0xc4
-
-#define SCI_CTRL_FLAGS_TIE 0x80
-#define SCI_CTRL_FLAGS_RIE 0x40
-#define SCI_CTRL_FLAGS_TE 0x20
-#define SCI_CTRL_FLAGS_RE 0x10
-/* TEIE=0x04 */
-#define SCI_CTRL_FLAGS_CKE1 0x02
-#define SCI_CTRL_FLAGS_CKE0 0x01
-
-#define SCI_ERI_IRQ 23
-#define SCI_RXI_IRQ 24
-#define SCI_TXI_IRQ 25
-#define SCI_TEI_IRQ 26
-#define SCI_IRQ_END 27
-
-#define SCI_IPR_ADDR INTC_IPRB
-#define SCI_IPR_POS 1
-#endif
-
-#if defined(CONFIG_SH_SCIF_SERIAL)
-#if defined(__sh3__)
-#define SCSMR (volatile unsigned char *)0xA4000150
-#define SCBRR 0xA4000152
-#define SCSCR (volatile unsigned char *)0xA4000154
-#define SC_TDR 0xA4000156
-#define SC_SR (volatile unsigned short *)0xA4000158
-#define SC_RDR 0xA400015A
-#define SCFCR (volatile unsigned char *)0xA400015C
-#define SCFDR 0xA400015E
-
-#undef SCSPTR /* SH7709 doesn't have SCSPTR */
-#define SCPCR 0xA4000116 /* Instead, it has SCPCR and SCPDR */
-#define SCPDR 0xA4000136
-#undef SCLSR
-
-#define SCSCR_INIT 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
- /* 0x33 when external clock is used */
-#define SCI_IPR_ADDR INTC_IPRE
-#define SCI_IPR_POS 1
-
-#elif defined(__SH4__)
-#define SCSMR (volatile unsigned short *)0xFFE80000
-#define SCBRR 0xFFE80004
-#define SCSCR (volatile unsigned short *)0xFFE80008
-#define SC_TDR 0xFFE8000C
-#define SC_SR (volatile unsigned short *)0xFFE80010
-#define SC_RDR 0xFFE80014
-#define SCFCR (volatile unsigned short *)0xFFE80018
-#define SCFDR 0xFFE8001C
-#define SCSPTR 0xFFE80020
-#define SCLSR 0xFFE80024
-
-#define SCSCR_INIT 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
-#define SCI_IPR_ADDR INTC_IPRC
-#define SCI_IPR_POS 1
+/* SCxSR SCIF */
+#define SCIF_ER 0x0080 /* 7709 SCIF, 7750 SCIF */
+#define SCIF_TEND 0x0040 /* 7709 SCIF, 7750 SCIF */
+#define SCIF_TDFE 0x0020 /* 7709 SCIF, 7750 SCIF */
+#define SCIF_BRK 0x0010 /* 7709 SCIF, 7750 SCIF */
+#define SCIF_FER 0x0008 /* 7709 SCIF, 7750 SCIF */
+#define SCIF_PER 0x0004 /* 7709 SCIF, 7750 SCIF */
+#define SCIF_RDF 0x0002 /* 7709 SCIF, 7750 SCIF */
+#define SCIF_DR 0x0001 /* 7709 SCIF, 7750 SCIF */
+
+#define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
+
+#if defined(SCI_ONLY)
+# define SCxSR_TEND(port) SCI_TEND
+# define SCxSR_ERRORS(port) SCI_ERRORS
+# define SCxSR_RDxF(port) SCI_RDRF
+# define SCxSR_TDxE(port) SCI_TDRE
+# define SCxSR_RDxF_CLEAR(port) 0xbc
+# define SCxSR_ERROR_CLEAR(port) 0xc4
+# define SCxSR_TDxE_CLEAR(port) 0x78
+#elif defined(SCIF_ONLY)
+# define SCxSR_TEND(port) SCIF_TEND
+# define SCxSR_ERRORS(port) SCIF_ERRORS
+# define SCxSR_RDxF(port) SCIF_RDF
+# define SCxSR_TDxE(port) SCIF_TDFE
+# define SCxSR_RDxF_CLEAR(port) 0x00fc
+# define SCxSR_ERROR_CLEAR(port) 0x0063
+# define SCxSR_TDxE_CLEAR(port) 0x00df
+#else
+# define SCxSR_TEND(port) (((port)->type == PORT_SCI) ? SCI_TEND : SCIF_TEND)
+# define SCxSR_ERRORS(port) (((port)->type == PORT_SCI) ? SCI_ERRORS : SCIF_ERRORS)
+# define SCxSR_RDxF(port) (((port)->type == PORT_SCI) ? SCI_RDRF : SCIF_RDF)
+# define SCxSR_TDxE(port) (((port)->type == PORT_SCI) ? SCI_TDRE : SCIF_TDFE)
+# define SCxSR_RDxF_CLEAR(port) (((port)->type == PORT_SCI) ? 0xbc : 0x00fc)
+# define SCxSR_ERROR_CLEAR(port) (((port)->type == PORT_SCI) ? 0xc4 : 0x0063)
+# define SCxSR_TDxE_CLEAR(port) (((port)->type == PORT_SCI) ? 0x78 : 0x00df)
#endif
-#define SCI_ER 0x0080
-#define SCI_TEND 0x0040
-#define SCI_TD_E 0x0020
-#define SCI_BRK 0x0010
-#define SCI_FER 0x0008
-#define SCI_PER 0x0004
-#define SCI_RD_F 0x0002
-#define SCI_DR 0x0001
-
-#define SCI_ERRORS ( SCI_PER | SCI_FER | SCI_ER | SCI_BRK)
-#define SCI_TD_E_CLEAR 0x00df
-#define SCI_TEND_CLEAR 0x00bf
-#define SCI_RDRF_CLEAR 0x00fc
-#define SCI_ERROR_CLEAR 0x0063
-
-#define SCI_CTRL_FLAGS_TIE 0x80
-#define SCI_CTRL_FLAGS_RIE 0x40
-#define SCI_CTRL_FLAGS_TE 0x20
-#define SCI_CTRL_FLAGS_RE 0x10
-#define SCI_CTRL_FLAGS_REIE 0x08
-#define SCI_CTRL_FLAGS_CKE1 0x02
-
-#if defined(__sh3__)
-#define SCI_ERI_IRQ 56
-#define SCI_RXI_IRQ 57
-#define SCI_BRI_IRQ 58
-#define SCI_TXI_IRQ 59
-#define SCI_IRQ_END 60
-#elif defined(__SH4__)
-#define SCI_ERI_IRQ 40
-#define SCI_RXI_IRQ 41
-#define SCI_BRI_IRQ 42
-#define SCI_TXI_IRQ 43
-#define SCI_IRQ_END 44
-#endif
-#endif
-
-#if defined(__sh3__)
-#define RFCR 0xffffff74
-#elif defined(__SH4__)
-#define RFCR 0xFF800028
-#endif
+/* SCFCR */
+#define SCFCR_RFRST 0x0002
+#define SCFCR_TFRST 0x0004
+#define SCFCR_MCE 0x0008
#define SCI_PRIORITY 3
-#define SCI_MINOR_START 64
+#define SCI_MAJOR 204
+#define SCI_MINOR_START 8
+
+/* Generic serial flags */
#define SCI_RX_THROTTLE 0x0000001
+/* generic serial tty */
#define O_OTHER(tty) \
((O_OLCUC(tty)) ||\
(O_ONLCR(tty)) ||\
@@ -173,10 +160,85 @@
struct sci_port {
struct gs_port gs;
+ int type;
+ unsigned int base;
+ unsigned char irqs[3]; /* ERI, RXI, TXI */
+ unsigned int intc_addr, intc_pos;
+ void (*init_pins)(struct sci_port* port, unsigned int cflag);
unsigned int old_cflag;
};
-#define WAIT_RFCR_COUNTER 200
+#define SCI_IN(size, offset) \
+ unsigned int addr = port->base + (offset); \
+ if ((size) == 8) { \
+ return ctrl_inb(addr); \
+ } else { \
+ return ctrl_inw(addr); \
+ }
+#define SCI_OUT(size, offset, value) \
+ unsigned int addr = port->base + (offset); \
+ if ((size) == 8) { \
+ ctrl_outb(value, addr); \
+ } else { \
+ ctrl_outw(value, addr); \
+ }
+
+#define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\
+ static inline unsigned int sci_##name##_in(struct sci_port* port) \
+ { \
+ if (port->type == PORT_SCI) { \
+ SCI_IN(sci_size, sci_offset) \
+ } else { \
+ SCI_IN(scif_size, scif_offset); \
+ } \
+ } \
+ static inline void sci_##name##_out(struct sci_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); \
+ } \
+ }
+
+#define CPU_SCIF_FNS(name, scif_offset, scif_size) \
+ static inline unsigned int sci_##name##_in(struct sci_port* port) \
+ { \
+ SCI_IN(scif_size, scif_offset); \
+ } \
+ static inline void sci_##name##_out(struct sci_port* port, unsigned int value) \
+ { \
+ SCI_OUT(scif_size, scif_offset, value); \
+ }
+
+#ifdef __sh3__
+#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)
+#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
+
+/* 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)
+SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16)
+
+#define sci_in(port, reg) sci_##reg##_in(port)
+#define sci_out(port, reg, value) sci_##reg##_out(port, value)
+
/*
* Values for the BitRate Register (SCBRR)
@@ -191,22 +253,17 @@
* the SCSMR register would also need to be set to non-zero values.
*
* -- Greg Banks 27Feb2000
+ *
+ * Answer: The SCBRR register is only eight bits, and the value in
+ * it gets larger with lower baud rates. At around 2400 (depending on
+ * the peripherial module clock) you run out of bits. However the
+ * lower two bits of SCSMR allow the module clock to be divided down,
+ * scaling the value which is needed in SCBRR.
+ *
+ * -- Stuart Menefy - 23 May 2000
*/
-/*
- * XXX: Well, this is not relevant...
- * Should we have config option for peripheral clock?
- * Or we get the value from time.c.
- */
-#if defined(__sh3__)
-#if defined(CONFIG_CPU_SUBTYPE_SH7709)
-#define PCLK 33333333
-#else
-#define PCLK 14745600 /* Isn't it 15MHz? */
-#endif
-#elif defined(__SH4__)
-#define PCLK 33333333
-#endif
+#define PCLK (current_cpu_data.module_clock)
#define SCBRR_VALUE(bps) (PCLK/(32*bps)-1)
#define BPS_2400 SCBRR_VALUE(2400)
@@ -215,3 +272,107 @@
#define BPS_19200 SCBRR_VALUE(19200)
#define BPS_38400 SCBRR_VALUE(38400)
#define BPS_115200 SCBRR_VALUE(115200)
+
+#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
+/* Taken from sh-stub.c of GDB 4.18 */
+static const char hexchars[] = "0123456789abcdef";
+
+static __inline__ char highhex(int x)
+{
+ return hexchars[(x >> 4) & 0xf];
+}
+
+static __inline__ char lowhex(int x)
+{
+ return hexchars[x & 0xf];
+}
+#endif
+
+static __inline__ void put_char(struct sci_port *port, char c)
+{
+ unsigned long flags;
+ unsigned short status;
+
+ save_and_cli(flags);
+
+ do
+ 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));
+
+ restore_flags(flags);
+}
+
+static __inline__ void handle_error(struct sci_port *port)
+{ /* Clear error flags */
+ sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
+}
+
+static __inline__ int get_char(struct sci_port *port)
+{
+ unsigned long flags;
+ unsigned short status;
+ int c;
+
+ save_and_cli(flags);
+ do {
+ status = sci_in(port, SCxSR);
+ if (status & SCxSR_ERRORS(port)) {
+ handle_error(port);
+ continue;
+ }
+ } while (!(status & SCxSR_RDxF(port)));
+ c = sci_in(port, SCxRDR);
+ sci_in(port, SCxSR); /* Dummy read */
+ sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+ restore_flags(flags);
+
+ return c;
+}
+
+/*
+ * Send the packet in buffer. The host get's one chance to read it.
+ * This routine does not wait for a positive acknowledge.
+ */
+
+static __inline__ void put_string(struct sci_port *port,
+ const char *buffer, int count)
+{
+ int i;
+ const unsigned char *p = buffer;
+#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
+ int checksum;
+
+if (IN_GDB) {
+ /* $<packet info>#<checksum>. */
+ do {
+ unsigned char c;
+ put_char(port, '$');
+ put_char(port, 'O'); /* 'O'utput to console */
+ checksum = 'O';
+
+ for (i=0; i<count; i++) { /* Don't use run length encoding */
+ int h, l;
+
+ c = *p++;
+ h = highhex(c);
+ l = lowhex(c);
+ put_char(port, h);
+ put_char(port, l);
+ checksum += h + l;
+ }
+ put_char(port, '#');
+ put_char(port, highhex(checksum));
+ put_char(port, lowhex(checksum));
+ } while (get_char(port) != '+');
+} else
+#endif
+ for (i=0; i<count; i++) {
+ if (*p == 10)
+ put_char(port, '\r');
+ put_char(port, *p++);
+ }
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)