From 1e237121324d6032eb64477547c06ee2fee31028 Mon Sep 17 00:00:00 2001 From: patacongo Date: Fri, 7 Nov 2008 16:28:17 +0000 Subject: [PATCH] Basic SCI support git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1152 42af7a65-404d-4744-a932-0658087f49c3 --- arch/sh/include/sh1/irq.h | 202 ++++---- arch/sh/src/common/up_internal.h | 2 +- arch/sh/src/sh1/Make.defs | 2 +- arch/sh/src/sh1/chip.h | 4 + arch/sh/src/sh1/sh1_703x.h | 51 +- arch/sh/src/sh1/sh1_lowputc.c | 154 ++++-- arch/sh/src/sh1/sh1_serial.c | 847 +++++++++++++++++++++++++++++++ 7 files changed, 1107 insertions(+), 155 deletions(-) create mode 100644 arch/sh/src/sh1/sh1_serial.c diff --git a/arch/sh/include/sh1/irq.h b/arch/sh/include/sh1/irq.h index dd3aa3435a..fd738c8f0f 100644 --- a/arch/sh/include/sh1/irq.h +++ b/arch/sh/include/sh1/irq.h @@ -55,68 +55,68 @@ /* Illegal instructions / Address errors */ -#define SH1_INVINSTR_IRQ (0) /* General invalid instruction */ -#define SH1_INVSLOT_IRQ (1) /* Invalid slot instruction */ -#define SH1_BUSERR_IRQ (2) /* CPU bus error */ -#define SH1_DMAERR_IRQ (3) /* DMA bus error */ -#define SH1_NMI_IRQ (4) /* NMI */ -#define SH1_USRBRK_IRQ (6) /* User break */ +#define SH1_INVINSTR_IRQ (0) /* General invalid instruction */ +#define SH1_INVSLOT_IRQ (1) /* Invalid slot instruction */ +#define SH1_BUSERR_IRQ (2) /* CPU bus error */ +#define SH1_DMAERR_IRQ (3) /* DMA bus error */ +#define SH1_NMI_IRQ (4) /* NMI */ +#define SH1_USRBRK_IRQ (6) /* User break */ /* Support for traps can be provided by simply enabling the following and * implementing the stubs to catch the interrupts */ #if 0 -# define SH1_TRAP_IRQ (7) /* TRAPA instruction (user break) */ -# define SH1_TRAP0_IRQ (SH1_TRAP_IRQ+0) /* TRAPA instruction (user break) */ -# define SH1_TRAP1_IRQ (SH1_TRAP_IRQ+1) /* " " " " " " " " */ -# define SH1_TRAP2_IRQ (SH1_TRAP_IRQ+2) /* " " " " " " " " */ -# define SH1_TRAP3_IRQ (SH1_TRAP_IRQ+3) /* " " " " " " " " */ -# define SH1_TRAP4_IRQ (SH1_TRAP_IRQ+4) /* " " " " " " " " */ -# define SH1_TRAP5_IRQ (SH1_TRAP_IRQ+5) /* " " " " " " " " */ -# define SH1_TRAP6_IRQ (SH1_TRAP_IRQ+6) /* " " " " " " " " */ -# define SH1_TRAP7_IRQ (SH1_TRAP_IRQ+7) /* " " " " " " " " */ -# define SH1_TRAP8_IRQ (SH1_TRAP_IRQ+8) /* " " " " " " " " */ -# define SH1_TRAP9_IRQ (SH1_TRAP_IRQ+9) /* " " " " " " " " */ -# define SH1_TRAP10_IRQ (SH1_TRAP_IRQ+10) /* " " " " " " " " */ -# define SH1_TRAP11_IRQ (SH1_TRAP_IRQ+11) /* " " " " " " " " */ -# define SH1_TRAP12_IRQ (SH1_TRAP_IRQ+12) /* " " " " " " " " */ -# define SH1_TRAP13_IRQ (SH1_TRAP_IRQ+13) /* " " " " " " " " */ -# define SH1_TRAP14_IRQ (SH1_TRAP_IRQ+14) /* " " " " " " " " */ -# define SH1_TRAP15_IRQ (SH1_TRAP_IRQ+15) /* " " " " " " " " */ -# define SH1_TRAP16_IRQ (SH1_TRAP_IRQ+16) /* " " " " " " " " */ -# define SH1_TRAP17_IRQ (SH1_TRAP_IRQ+17) /* " " " " " " " " */ -# define SH1_TRAP18_IRQ (SH1_TRAP_IRQ+18) /* " " " " " " " " */ -# define SH1_TRAP19_IRQ (SH1_TRAP_IRQ+19) /* " " " " " " " " */ -# define SH1_TRAP20_IRQ (SH1_TRAP_IRQ+20) /* " " " " " " " " */ -# define SH1_TRAP21_IRQ (SH1_TRAP_IRQ+21) /* " " " " " " " " */ -# define SH1_TRAP22_IRQ (SH1_TRAP_IRQ+22) /* " " " " " " " " */ -# define SH1_TRAP23_IRQ (SH1_TRAP_IRQ+23) /* " " " " " " " " */ -# define SH1_TRAP24_IRQ (SH1_TRAP_IRQ+24) /* " " " " " " " " */ -# define SH1_TRAP25_IRQ (SH1_TRAP_IRQ+25) /* " " " " " " " " */ -# define SH1_TRAP26_IRQ (SH1_TRAP_IRQ+26) /* " " " " " " " " */ -# define SH1_TRAP27_IRQ (SH1_TRAP_IRQ+27) /* " " " " " " " " */ -# define SH1_TRAP28_IRQ (SH1_TRAP_IRQ+28) /* " " " " " " " " */ -# define SH1_TRAP29_IRQ (SH1_TRAP_IRQ+29) /* " " " " " " " " */ -# define SH1_TRAP30_IRQ (SH1_TRAP_IRQ+30) /* " " " " " " " " */ -# define SH1_TRAP31_IRQ (SH1_TRAP_IRQ+31) /* " " " " " " " " */ -# define SH1_LASTTRAP_IRQ SH1_TRAP31_IRQ +# define SH1_TRAP_IRQ (7) /* TRAPA instruction (user break) */ +# define SH1_TRAP0_IRQ (SH1_TRAP_IRQ+0) /* TRAPA instruction (user break) */ +# define SH1_TRAP1_IRQ (SH1_TRAP_IRQ+1) /* " " " " " " " " */ +# define SH1_TRAP2_IRQ (SH1_TRAP_IRQ+2) /* " " " " " " " " */ +# define SH1_TRAP3_IRQ (SH1_TRAP_IRQ+3) /* " " " " " " " " */ +# define SH1_TRAP4_IRQ (SH1_TRAP_IRQ+4) /* " " " " " " " " */ +# define SH1_TRAP5_IRQ (SH1_TRAP_IRQ+5) /* " " " " " " " " */ +# define SH1_TRAP6_IRQ (SH1_TRAP_IRQ+6) /* " " " " " " " " */ +# define SH1_TRAP7_IRQ (SH1_TRAP_IRQ+7) /* " " " " " " " " */ +# define SH1_TRAP8_IRQ (SH1_TRAP_IRQ+8) /* " " " " " " " " */ +# define SH1_TRAP9_IRQ (SH1_TRAP_IRQ+9) /* " " " " " " " " */ +# define SH1_TRAP10_IRQ (SH1_TRAP_IRQ+10) /* " " " " " " " " */ +# define SH1_TRAP11_IRQ (SH1_TRAP_IRQ+11) /* " " " " " " " " */ +# define SH1_TRAP12_IRQ (SH1_TRAP_IRQ+12) /* " " " " " " " " */ +# define SH1_TRAP13_IRQ (SH1_TRAP_IRQ+13) /* " " " " " " " " */ +# define SH1_TRAP14_IRQ (SH1_TRAP_IRQ+14) /* " " " " " " " " */ +# define SH1_TRAP15_IRQ (SH1_TRAP_IRQ+15) /* " " " " " " " " */ +# define SH1_TRAP16_IRQ (SH1_TRAP_IRQ+16) /* " " " " " " " " */ +# define SH1_TRAP17_IRQ (SH1_TRAP_IRQ+17) /* " " " " " " " " */ +# define SH1_TRAP18_IRQ (SH1_TRAP_IRQ+18) /* " " " " " " " " */ +# define SH1_TRAP19_IRQ (SH1_TRAP_IRQ+19) /* " " " " " " " " */ +# define SH1_TRAP20_IRQ (SH1_TRAP_IRQ+20) /* " " " " " " " " */ +# define SH1_TRAP21_IRQ (SH1_TRAP_IRQ+21) /* " " " " " " " " */ +# define SH1_TRAP22_IRQ (SH1_TRAP_IRQ+22) /* " " " " " " " " */ +# define SH1_TRAP23_IRQ (SH1_TRAP_IRQ+23) /* " " " " " " " " */ +# define SH1_TRAP24_IRQ (SH1_TRAP_IRQ+24) /* " " " " " " " " */ +# define SH1_TRAP25_IRQ (SH1_TRAP_IRQ+25) /* " " " " " " " " */ +# define SH1_TRAP26_IRQ (SH1_TRAP_IRQ+26) /* " " " " " " " " */ +# define SH1_TRAP27_IRQ (SH1_TRAP_IRQ+27) /* " " " " " " " " */ +# define SH1_TRAP28_IRQ (SH1_TRAP_IRQ+28) /* " " " " " " " " */ +# define SH1_TRAP29_IRQ (SH1_TRAP_IRQ+29) /* " " " " " " " " */ +# define SH1_TRAP30_IRQ (SH1_TRAP_IRQ+30) /* " " " " " " " " */ +# define SH1_TRAP31_IRQ (SH1_TRAP_IRQ+31) /* " " " " " " " " */ +# define SH1_LASTTRAP_IRQ SH1_TRAP31_IRQ #else -# define SH1_LASTTRAP_IRQ (6) +# define SH1_LASTTRAP_IRQ (6) #endif /* Interrupts */ -#define SH1_IRQ_IRQ (SH1_LASTTRAP_IRQ+1) /* IRQ0-7 */ -#define SH1_IRQ0_IRQ (SH1_IRQ_IRQ+0) /* IRQ0 */ -#define SH1_IRQ1_IRQ (SH1_IRQ_IRQ+1) /* IRQ1 */ -#define SH1_IRQ2_IRQ (SH1_IRQ_IRQ+2) /* IRQ2 */ -#define SH1_IRQ3_IRQ (SH1_IRQ_IRQ+3) /* IRQ3 */ -#define SH1_IRQ4_IRQ (SH1_IRQ_IRQ+4) /* IRQ4 */ -#define SH1_IRQ5_IRQ (SH1_IRQ_IRQ+5) /* IRQ5 */ -#define SH1_IRQ6_IRQ (SH1_IRQ_IRQ+6) /* IRQ6 */ -#define SH1_IRQ7_IRQ (SH1_IRQ_IRQ+7) /* IRQ7 */ -#define SH1_LASTIRQ_IRQ SH1_IRQ7_IRQ +#define SH1_IRQ_IRQ (SH1_LASTTRAP_IRQ+1) /* IRQ0-7 */ +#define SH1_IRQ0_IRQ (SH1_IRQ_IRQ+0) /* IRQ0 */ +#define SH1_IRQ1_IRQ (SH1_IRQ_IRQ+1) /* IRQ1 */ +#define SH1_IRQ2_IRQ (SH1_IRQ_IRQ+2) /* IRQ2 */ +#define SH1_IRQ3_IRQ (SH1_IRQ_IRQ+3) /* IRQ3 */ +#define SH1_IRQ4_IRQ (SH1_IRQ_IRQ+4) /* IRQ4 */ +#define SH1_IRQ5_IRQ (SH1_IRQ_IRQ+5) /* IRQ5 */ +#define SH1_IRQ6_IRQ (SH1_IRQ_IRQ+6) /* IRQ6 */ +#define SH1_IRQ7_IRQ (SH1_IRQ_IRQ+7) /* IRQ7 */ +#define SH1_LASTIRQ_IRQ SH1_IRQ7_IRQ /* On-chip modules -- The following may be unique to the 7032 */ @@ -124,68 +124,74 @@ /* DMAC */ -#define SH1_DMAC0_IRQ (SH1_LASTIRQ_IRQ+1) /* DMAC0 */ -#define SH1_DEI0_IRQ SH1_DMAC0_IRQ /* DEI0 */ -#define SH1_DMAC1_IRQ (SH1_LASTIRQ_IRQ+2) /* DMAC1 */ -#define SH1_DEI1_IRQ SH1_DMAC1_IRQ /* DEI1 */ -#define SH1_DMAC2_IRQ (SH1_LASTIRQ_IRQ+3) /* DMAC2 */ -#define SH1_DEI2_IRQ SH1_DMAC2_IRQ /* DEI2 */ -#define SH1_DMAC3_IRQ (SH1_LASTIRQ_IRQ+4) /* DMAC3 */ -#define SH1_DEI3_IRQ SH1_DMAC3_IRQ /* DEI3 */ -#define SH1_LASTDMAC_IRQ SH1_DEI3_IRQ +#define SH1_DMAC0_IRQ (SH1_LASTIRQ_IRQ+1) /* DMAC0 */ +#define SH1_DEI0_IRQ SH1_DMAC0_IRQ /* DEI0 */ +#define SH1_DMAC1_IRQ (SH1_LASTIRQ_IRQ+2) /* DMAC1 */ +#define SH1_DEI1_IRQ SH1_DMAC1_IRQ /* DEI1 */ +#define SH1_DMAC2_IRQ (SH1_LASTIRQ_IRQ+3) /* DMAC2 */ +#define SH1_DEI2_IRQ SH1_DMAC2_IRQ /* DEI2 */ +#define SH1_DMAC3_IRQ (SH1_LASTIRQ_IRQ+4) /* DMAC3 */ +#define SH1_DEI3_IRQ SH1_DMAC3_IRQ /* DEI3 */ +#define SH1_LASTDMAC_IRQ SH1_DEI3_IRQ /* ITU */ -#define SH1_ITU0_IRQ (SH1_LASTDMAC_IRQ+1) /* ITU0 */ -#define SH1_IMIA0_IRQ (SH1_ITU0_IRQ+0) /* IMIA0 */ -#define SH1_IMIBO_IRQ (SH1_ITU0_IRQ+1) /* IMIB0 */ -#define SH1_OVI0_IRQ (SH1_ITU0_IRQ+2) /* OVI0 */ +#define SH1_ITU0_IRQ (SH1_LASTDMAC_IRQ+1) /* ITU0 */ +#define SH1_IMIA0_IRQ (SH1_ITU0_IRQ+0) /* IMIA0 */ +#define SH1_IMIBO_IRQ (SH1_ITU0_IRQ+1) /* IMIB0 */ +#define SH1_OVI0_IRQ (SH1_ITU0_IRQ+2) /* OVI0 */ -#define SH1_ITU1_IRQ (SH1_LASTDMAC_IRQ+4) /* ITU1 */ -#define SH1_IMIA1_IRQ (SH1_ITU1_IRQ+0) /* IMIA1 */ -#define SH1_IMIB1_IRQ (SH1_ITU1_IRQ+1) /* IMIB1 */ -#define SH1_OVI1_IRQ (SH1_ITU1_IRQ+2) /* OVI1 */ +#define SH1_ITU1_IRQ (SH1_LASTDMAC_IRQ+4) /* ITU1 */ +#define SH1_IMIA1_IRQ (SH1_ITU1_IRQ+0) /* IMIA1 */ +#define SH1_IMIB1_IRQ (SH1_ITU1_IRQ+1) /* IMIB1 */ +#define SH1_OVI1_IRQ (SH1_ITU1_IRQ+2) /* OVI1 */ -#define SH1_ITU2_IRQ (SH1_LASTDMAC_IRQ+7) /* ITU2 */ -#define SH1_IMIA2_IRQ (SH1_ITU2_IRQ+0) /* IMIA2 */ -#define SH1_IMIB2_IRQ (SH1_ITU2_IRQ+1) /* IMIB2 */ -#define SH1_OVI2_IRQ (SH1_ITU2_IRQ+2) /* OVI2 */ +#define SH1_ITU2_IRQ (SH1_LASTDMAC_IRQ+7) /* ITU2 */ +#define SH1_IMIA2_IRQ (SH1_ITU2_IRQ+0) /* IMIA2 */ +#define SH1_IMIB2_IRQ (SH1_ITU2_IRQ+1) /* IMIB2 */ +#define SH1_OVI2_IRQ (SH1_ITU2_IRQ+2) /* OVI2 */ -#define SH1_ITU3_IRQ (SH1_LASTDMAC_IRQ+10) /* ITU3 */ -#define SH1_IMIA3_IRQ (SH1_ITU3_IRQ+0) /* IMIA3 */ -#define SH1_IMIB3_IRQ (SH1_ITU3_IRQ+1) /* IMIB3 */ -#define SH1_OVI3_IRQ (SH1_ITU3_IRQ+2) /* OVI3 */ +#define SH1_ITU3_IRQ (SH1_LASTDMAC_IRQ+10) /* ITU3 */ +#define SH1_IMIA3_IRQ (SH1_ITU3_IRQ+0) /* IMIA3 */ +#define SH1_IMIB3_IRQ (SH1_ITU3_IRQ+1) /* IMIB3 */ +#define SH1_OVI3_IRQ (SH1_ITU3_IRQ+2) /* OVI3 */ -#define SH1_ITU4_IRQ (SH1_LASTDMAC_IRQ+13) /* ITU4 */ -#define SH1_IMIA4_IRQ (SH1_ITU4_IRQ+0) /* IMIA4 */ -#define SH1_IMIB4_IRQ (SH1_ITU4_IRQ+1) /* IMIB4 */ -#define SH1_OVI4_IRQ (SH1_ITU4_IRQ+2) /* OVI4 */ +#define SH1_ITU4_IRQ (SH1_LASTDMAC_IRQ+13) /* ITU4 */ +#define SH1_IMIA4_IRQ (SH1_ITU4_IRQ+0) /* IMIA4 */ +#define SH1_IMIB4_IRQ (SH1_ITU4_IRQ+1) /* IMIB4 */ +#define SH1_OVI4_IRQ (SH1_ITU4_IRQ+2) /* OVI4 */ -#define SH1_LASTITU_IRQ (SH1_LASTDMAC_IRQ+15) +#define SH1_LASTITU_IRQ (SH1_LASTDMAC_IRQ+15) /* SCI */ -#define SH1_SCI0_IRQ (SH1_LASTITU_IRQ+1) /* SCI0 */ -#define SH1_ERI0_IRQ (SH1_SCI0_IRQ+0) /* ERI0 */ -#define SH1_RXI0_IRQ (SH1_SCI0_IRQ+1) /* RxI0 */ -#define SH1_TXI0_IRQ (SH1_SCI0_IRQ+2) /* TxI0 */ -#define SH1_TEI0_IRQ (SH1_SCI0_IRQ+3) /* TEI0 */ +#define SH1_ERI_IRQ_OFFSET (0) /* ERI0 */ +#define SH1_RXI_IRQ_OFFSET (1) /* RxI0 */ +#define SH1_TXI_IRQ_OFFSET (2) /* TxI0 */ +#define SH1_TEI_IRQ_OFFSET (3) /* TEI0 */ +#define SH1_SCI_NIRQS (4) -#define SH1_SCI1_IRQ (SH1_LASTITU_IRQ+5) /* SCI1 */ -#define SH1_ERI1_IRQ (SH1_SCI1_IRQ+0) /* ERI1 */ -#define SH1_RXI1_IRQ (SH1_SCI1_IRQ+1) /* RxI1 */ -#define SH1_TXI1_IRQ (SH1_SCI1_IRQ+2) /* TxI1 */ -#define SH1_TEI1_IRQ (SH1_SCI1_IRQ+3) /* TEI1 */ +#define SH1_SCI0_IRQ (SH1_LASTITU_IRQ+1) /* SCI0 */ +#define SH1_ERI0_IRQ (SH1_SCI0_IRQ+SH1_ERI_IRQ_OFFSET) /* ERI0 */ +#define SH1_RXI0_IRQ (SH1_SCI0_IRQ+SH1_RXI_IRQ_OFFSET) /* RxI0 */ +#define SH1_TXI0_IRQ (SH1_SCI0_IRQ+SH1_TXI_IRQ_OFFSET) /* TxI0 */ +#define SH1_TEI0_IRQ (SH1_SCI0_IRQ+SH1_TEI_IRQ_OFFSET) /* TEI0 */ -#define SH1_LASTSCI_IRQ (SH1_LASTITU_IRQ+9) +#define SH1_SCI1_IRQ (SH1_SCI0_IRQ+SH1_SCI_NIRQS) /* SCI1 */ +#define SH1_ERI1_IRQ (SH1_SCI1_IRQ+SH1_ERI_IRQ_OFFSET) /* ERI1 */ +#define SH1_RXI1_IRQ (SH1_SCI1_IRQ+SH1_RXI_IRQ_OFFSET) /* RxI1 */ +#define SH1_TXI1_IRQ (SH1_SCI1_IRQ+SH1_TXI_IRQ_OFFSET) /* TxI1 */ +#define SH1_TEI1_IRQ (SH1_SCI1_IRQ+SH1_TEI_IRQ_OFFSET) /* TEI1 */ -#define SH1_PEI_IRQ (SH1_LASTSCI_IRQ+1) /* Parity control unit PEI */ -#define SH1_ADITI_IRQ (SH1_LASTSCI_IRQ+2) /* A/D ITI */ -#define SH1_WDTITI_IRQ (SH1_LASTSCI_IRQ+3) /* WDT ITI */ -#define SH1_CMI_IRQ (SH1_LASTSCI_IRQ+4) /* REF CMI */ +#define SH1_LASTSCI_IRQ (SH1_SCI1_IRQ+SH1_SCI_NIRQS) -#define STR71X_IRQ_SYSTIMER STR71X_IRQ_T0TIMI -#define NR_IRQS (SH1_CMI_IRQ+1) +#define SH1_PEI_IRQ (SH1_LASTSCI_IRQ+1) /* Parity control unit PEI */ +#define SH1_ADITI_IRQ (SH1_LASTSCI_IRQ+2) /* A/D ITI */ +#define SH1_WDTITI_IRQ (SH1_LASTSCI_IRQ+3) /* WDT ITI */ +#define SH1_CMI_IRQ (SH1_LASTSCI_IRQ+4) /* REF CMI */ + +#define STR71X_IRQ_SYSTIMER STR71X_IRQ_T0TIMI +#define NR_IRQS (SH1_CMI_IRQ+1) #endif diff --git a/arch/sh/src/common/up_internal.h b/arch/sh/src/common/up_internal.h index 7c071c2d53..31f0160741 100644 --- a/arch/sh/src/common/up_internal.h +++ b/arch/sh/src/common/up_internal.h @@ -52,7 +52,7 @@ #undef CONFIG_SUPPRESS_INTERRUPTS /* DEFINED: Do not enable interrupts */ #undef CONFIG_SUPPRESS_TIMER_INTS /* DEFINED: No timer */ #undef CONFIG_SUPPRESS_SERIAL_INTS /* DEFINED: Console will poll */ -#undef CONFIG_SUPPRESS_UART_CONFIG /* DEFINED: Do not reconfig UART */ +#undef CONFIG_SUPPRESS_SCI_CONFIG /* DEFINED: Do not reconfig SCI */ #undef CONFIG_DUMP_ON_EXIT /* DEFINED: Dump task state on exit */ /* Determine which (if any) console driver to use */ diff --git a/arch/sh/src/sh1/Make.defs b/arch/sh/src/sh1/Make.defs index 945471103b..ae2605c5a5 100644 --- a/arch/sh/src/sh1/Make.defs +++ b/arch/sh/src/sh1/Make.defs @@ -47,7 +47,7 @@ CMN_CSRCS += up_schedulesigaction.c up_sigdeliver.c endif CHIP_ASRCS = -CHIP_CSRCS = sh1_lowputc.c sh1_irq.c sh1_timerisr.c +CHIP_CSRCS = sh1_lowputc.c sh1_irq.c sh1_timerisr.c sh1_serial.c ifeq ($(CONFIG_USBDEV),y) CHIP_CSRCS += diff --git a/arch/sh/src/sh1/chip.h b/arch/sh/src/sh1/chip.h index 7936eb1ffd..bffa19bd94 100644 --- a/arch/sh/src/sh1/chip.h +++ b/arch/sh/src/sh1/chip.h @@ -43,6 +43,10 @@ #include #include +#ifdef CONFIG_ARCH_SH7032 +# include "sh1_703x.h" +#endif + /************************************************************************************ * Definitions ************************************************************************************/ diff --git a/arch/sh/src/sh1/sh1_703x.h b/arch/sh/src/sh1/sh1_703x.h index a4fdcdfef9..37b41e05f2 100644 --- a/arch/sh/src/sh1/sh1_703x.h +++ b/arch/sh/src/sh1/sh1_703x.h @@ -296,12 +296,13 @@ #define SH1_SCISCR_SISOUT2 (0x01) /* Internal clock, SCK pin used for clock output */ #define SH1_SCISCR_SXSIN1 (0x02) /* External clock, SCK pin used for clock input */ #define SH1_SCISCR_SXSIN2 (0x03) /* External clock, SCK pin used for clock input */ -#define SH1_SCISCR_TEIE (0x04) /* Bit 2: Transmit end interrupt enable */ -#define SH1_SCISCR_MPIE (0x08) /* Bit 3: Multiprocessor interrupt enable */ -#define SH1_SCISCR_RE (0x10) /* Bit 4: Receiver enable */ -#define SH1_SCISCR_TE (0x20) /* Bit 5: Transmitter enable */ -#define SH1_SCISCR_RIE (0x40) /* Bit 6: Recieve-data-full interrupt enable */ -#define SH1_SCISCR_TIE (Ox80) /* Bit 7: Transmit-data-empty interrupt enable */ +#define SH1_SCISCR_TEIE (0x04) /* Bit 2: 1=Transmit end interrupt enable */ +#define SH1_SCISCR_MPIE (0x08) /* Bit 3: 1=Multiprocessor interrupt enable */ +#define SH1_SCISCR_RE (0x10) /* Bit 4: 1=Receiver enable */ +#define SH1_SCISCR_TE (0x20) /* Bit 5: 1=Transmitter enable */ +#define SH1_SCISCR_RIE (0x40) /* Bit 6: 1=Recieve-data-full interrupt enable */ +#define SH1_SCISCR_TIE (Ox80) /* Bit 7: 1=Transmit-data-empty interrupt enable */ +#define SH1_SCISCR_ALLINTS (0xcc) #define SH1_SCISSR_MPBT (0x01) /* Bit 0: Multi-processor Bit in Transmit data */ #define SH1_SCISSR_MPB (0x02) /* Bit 1: Multi-processor Bit in receive data */ @@ -314,47 +315,47 @@ /* Interrupt Controller (INTC) */ -#define SH1_IPRA_IRQ3MASK (0x000f) /* Bits 0-3: IRQ3 +#define SH1_IPRA_IRQ3MASK (0x000f) /* Bits 0-3: IRQ3 */ #define SH1_IPRA_IRQ3SHIFT (0) -#define SH1_IPRA_IRQ2MASK (0x00f0) /* Bits 4-7: IRQ2 +#define SH1_IPRA_IRQ2MASK (0x00f0) /* Bits 4-7: IRQ2 */ #define SH1_IPRA_IRQ2SHIFT (4) -#define SH1_IPRA_IRQ1MASK (0x0f00) /* Bits 8-11: IRQ1 +#define SH1_IPRA_IRQ1MASK (0x0f00) /* Bits 8-11: IRQ1 */ #define SH1_IPRA_IRQ1SHIFT (8) -#define SH1_IPRA_IRQ0MASK (0xf000) /* Bits 12-15: IRQ0 +#define SH1_IPRA_IRQ0MASK (0xf000) /* Bits 12-15: IRQ0 */ #define SH1_IPRA_IRQ0SHIFT (12) -#define SH1_IPRB_IRQ7MASK (0x000f) /* Bits 0-3: IRQ7 +#define SH1_IPRB_IRQ7MASK (0x000f) /* Bits 0-3: IRQ7 */ #define SH1_IPRB_IRQ7SHIFT (0) -#define SH1_IPRB_IRQ6MASK (0x00f0) /* Bits 4-7: IRQ6 +#define SH1_IPRB_IRQ6MASK (0x00f0) /* Bits 4-7: IRQ6 */ #define SH1_IPRB_IRQ6SHIFT (4) -#define SH1_IPRB_IRQ5MASK (0x0f00) /* Bits 8-11: IRQ5 +#define SH1_IPRB_IRQ5MASK (0x0f00) /* Bits 8-11: IRQ5 */ #define SH1_IPRB_IRQ5SHIFT (8) -#define SH1_IPRB_IRQ4MASK (0xf000) /* Bits 12-15: IRQ4 +#define SH1_IPRB_IRQ4MASK (0xf000) /* Bits 12-15: IRQ4 */ #define SH1_IPRB_IRQ4SHIFT (12) -#define SH1_IPRC_ITU1MASK (0x000f) /* Bits 0-3: ITU1 +#define SH1_IPRC_ITU1MASK (0x000f) /* Bits 0-3: ITU1 */ #define SH1_IPRC_ITU1SHIFT (0) -#define SH1_IPRC_ITU0MASK (0x00f0) /* Bits 4-7: ITU0 +#define SH1_IPRC_ITU0MASK (0x00f0) /* Bits 4-7: ITU0 */ #define SH1_IPRC_ITU0SHIFT (4) -#define SH1_IPRC_DM23MASK (0x0f00) /* Bits 8-11: DMAC2,3 +#define SH1_IPRC_DM23MASK (0x0f00) /* Bits 8-11: DMAC2,3 */ #define SH1_IPRC_DM23SHIFT (8) -#define SH1_IPRC_DM01MASK (0xf000) /* Bits 12-15: DMAC0,1 +#define SH1_IPRC_DM01MASK (0xf000) /* Bits 12-15: DMAC0,1 */ #define SH1_IPRC_DM01SHIFT (12) -#define SH1_IPRD_SCI0MASK (0x000f) /* Bits 0-3: SCI0 +#define SH1_IPRD_SCI0MASK (0x000f) /* Bits 0-3: SCI0 */ #define SH1_IPRD_SCI0SHIFT (0) -#define SH1_IPRD_ITU4MASK (0x00f0) /* Bits 4-7: ITU4 +#define SH1_IPRD_ITU4MASK (0x00f0) /* Bits 4-7: ITU4 */ #define SH1_IPRD_ITU4SHIFT (4) -#define SH1_IPRD_ITU3MASK (0x0f00) /* Bits 8-11: ITU3 +#define SH1_IPRD_ITU3MASK (0x0f00) /* Bits 8-11: ITU3 */ #define SH1_IPRD_ITU3SHIFT (8) -#define SH1_IPRD_ITU2MASK (0xf000) /* Bits 12-15: ITU2 +#define SH1_IPRD_ITU2MASK (0xf000) /* Bits 12-15: ITU2 */ #define SH1_IPRD_ITU2SHIFT (12) -#define SH1_IPRE_WDRFMASK (0x00f0) /* Bits 4-7: WDT, REF +#define SH1_IPRE_WDRFMASK (0x00f0) /* Bits 4-7: WDT, REF */ #define SH1_IPRE_WDRFSHIFT (4) -#define SH1_IPRE_PRADMASK (0x0f00) /* Bits 8-11: PRT, A/D +#define SH1_IPRE_PRADMASK (0x0f00) /* Bits 8-11: PRT, A/D */ #define SH1_IPRE_PRADSHIFT (8) -#define SH1_IPRE_SCI1MASK (0xf000) /* Bits 12-15: SCI1 +#define SH1_IPRE_SCI1MASK (0xf000) /* Bits 12-15: SCI1 */ #define SH1_IPRE_SCI1SHIFT (12) #define SH1_ICR_IRQ7S (0x0001) /* Bits 0: Interrupt on falling edge of IRQ7 input */ diff --git a/arch/sh/src/sh1/sh1_lowputc.c b/arch/sh/src/sh1/sh1_lowputc.c index 0fd0469844..983c3688bf 100644 --- a/arch/sh/src/sh1/sh1_lowputc.c +++ b/arch/sh/src/sh1/sh1_lowputc.c @@ -40,10 +40,13 @@ #include #include +#include + #include "up_internal.h" #include "up_arch.h" #include "chip.h" +#include "up_internal.h" /************************************************************************** * Private Definitions @@ -53,7 +56,7 @@ /* Is there a serial console? */ -#if defined(CONFIG_UART0_SERIAL_CONSOLE) || defined(CONFIG_UART1_SERIAL_CONSOLE) +#if defined(CONFIG_SCI0_SERIAL_CONSOLE) || defined(CONFIG_SCI1_SERIAL_CONSOLE) # define HAVE_CONSOLE #else # undef HAVE_CONSOLE @@ -61,46 +64,80 @@ /* Select UART parameters for the selected console */ -#if defined(CONFIG_UART0_SERIAL_CONSOLE) -# define SH1_UART_BASE -# define SH1_UART_BAUD CONFIG_UART0_BAUD -# define SH1_UART_BITS CONFIG_UART0_BITS -# define SH1_UART_PARITY CONFIG_UART0_PARITY -# define SH1_UART_2STOP CONFIG_UART0_2STOP -#elif defined(CONFIG_UART1_SERIAL_CONSOLE) -# define SH1_UART_BASE -# define SH1_UART_BAUD CONFIG_UART1_BAUD -# define SH1_UART_BITS CONFIG_UART1_BITS -# define SH1_UART_PARITY CONFIG_UART1_PARITY -# define SH1_UART_2STOP CONFIG_UART1_2STOP +#if defined(CONFIG_SCI0_SERIAL_CONSOLE) +# define SH1_SCI_BASE SH1_SCI0_BASE +# define SH1_SCI_BAUD CONFIG_SCI0_BAUD +# define SH1_SCI_BITS CONFIG_SCI0_BITS +# define SH1_SCI_PARITY CONFIG_SCI0_PARITY +# define SH1_SCI_2STOP CONFIG_SCI0_2STOP +#elif defined(CONFIG_SCI1_SERIAL_CONSOLE) +# define SH1_SCI_BASE SH1_SCI1_BASE +# define SH1_SCI_BAUD CONFIG_SCI1_BAUD +# define SH1_SCI_BITS CONFIG_SCI1_BITS +# define SH1_SCI_PARITY CONFIG_SCI1_PARITY +# define SH1_SCI_2STOP CONFIG_SCI1_2STOP #else -# error "No CONFIG_UARTn_SERIAL_CONSOLE Setting" +# error "No CONFIG_SCIn_SERIAL_CONSOLE Setting" #endif /* Get mode setting */ -#if SH1_UART_BITS == 7 -# define SH1_UARTCR_MODE -#elif SH1_UART_BITS == 8 -# define SH1_UARTCR_MODE SH1_UARTCR_MODE8BITP +#if SH1_SCI_BITS == 7 +# define SH1_SMR_MODE SH1_SCISMR_CHR +#elif SH1_SCI_BITS == 8 +# define SH1_SMR_MODE (0) #else # error "Number of bits not supported" #endif -#if SH1_UART_PARITY == 0 || SH1_UART_PARITY == 2 -# define SH1_UARTCR_PARITY -#elif SH1_UART_PARITY == 1 -# define SH1_UARTCR_PARITY SH1_UARTCR_PARITYODD +#if SH1_SCI_PARITY == 0 +# define SH1_SMR_PARITY (0) +#elif SH1_SCI_PARITY == 1 +# define SH1_SMR_PARITY (SH1_SCISMR_PE|SH1_SCISMR_OE) +#elif SH1_SCI_PARITY == 2 +# define SH1_SMR_PARITY SH1_SCISMR_PE #else # error "Invalid parity selection" #endif -#if SH1_UART_2STOP != 0 -# define SH1_UARTCR_STOP +#if SH1_SCI_2STOP != 0 +# define SH1_SMR_STOP SH1_SCISMR_STOP #else -# define SH1_UARTCR_STOP +# define SH1_SMR_STOP (0) #endif +/* The full SMR setting also includes internal clocking with no divisor, + * aysnchronous operation and multiprocessor disabled: + */ + +#define SH1_SMR_VALUE (SH1_SMR_MODE|SH1_SMR_PARITY|SH1_SMR_STOP) + +/* Clocking ***************************************************************/ + +/* The calculation of the BRR to achieve the desired BAUD is given by the + * following formula: + * + * brr = (f/(64*2**(2n-1)*b))-1 + * + * Where: + * + * b = bit rate + * f = frequency (Hz) + * n = divider setting (0, 1, 2, 3) + * + * For n == 0, this simplifies to: + * + * brr = (f/(32*b))-1 + * + * For example, if the processor is clocked at 10 MHz and 9600 is the + * desired BAUD: + * + * brr = 10,000,000 / (32 * 9600) - 1 = 31.552 (or 32 after rounding) + */ + +#define SH1_DIVISOR (32 * SH1_SCI_BAUD) +#define SH1_BRR (((SH1_CLOCK + (SH1_DIVISOR/2))/SH1_DIVISOR)-1) + /************************************************************************** * Private Types **************************************************************************/ @@ -121,6 +158,19 @@ * Private Functions **************************************************************************/ +/************************************************************************** + * Name: up_txready + * + * Description: + * Return TRUE of the Transmit Data Register is empty + * + **************************************************************************/ + +int inline up_txready(void) +{ + return getreg8(SH1_SCI_BASE + SH1_SCI_SSR_OFFSET) & SH1_SCISSR_TDRE; +} + /************************************************************************** * Public Functions **************************************************************************/ @@ -136,7 +186,21 @@ void up_lowputc(char ch) { #ifdef HAVE_CONSOLE -# warning "To be provided" + ubyte ssr; + + /* Wait until the TDR is avaible */ + + while (!up_txready()); + + /* Write the data to the TDR */ + + putreg8(ch, SH1_SCI_BASE + SH1_SCI_TDR_OFFSET); + + /* Clear the TDRE bit in the SSR */ + + ssr = getreg8(SH1_SCI_BASE + SH1_SCI_SSR_OFFSET); + ssr &= ~SH1_SCISSR_TDRE; + putreg8(ssr, SH1_SCI_BASE + SH1_SCI_SSR_OFFSET); #endif } @@ -152,9 +216,39 @@ void up_lowputc(char ch) void up_lowsetup(void) { -#ifdef HAVE_CONSOLE -# warning "To be provided" +#if defined(HAVE_CONSOLE) && !defined(CONFIG_SUPPRESS_SCI_CONFIG) + ubyte scr; + + /* Disable the transmitter and receiver */ + + scr = getreg8(SH1_SCI_BASE + SH1_SCI_SCR_OFFSET); + scr &= ~(SH1_SCISCR_TE | SH1_SCISCR_RE); + putreg8(scr, SH1_SCI_BASE + SH1_SCI_SCR_OFFSET); + + /* Set communication to be asynchronous with the configured number of data + * bits, parity, and stop bits. Use the internal clock (undivided) + */ + + putreg8(SH1_SMR_VALUE, SH1_SCI_BASE + SH1_SCI_SMR_OFFSET); + + /* Set the baud based on the configured console baud and configured + * system clock. + */ + + putreg8(SH1_BRR, SH1_SCI_BASE + SH1_SCI_BRR_OFFSET); + + /* Select the internal clock source as input */ + + scr &= ~SH1_SCISCR_CKEMASK; + putreg8(scr, SH1_SCI_BASE + SH1_SCI_SCR_OFFSET); + + /* Wait a bit for the clocking to settle */ + + up_udelay(100); + + /* Then enable the transmitter and reciever */ + + scr |= (SH1_SCISCR_TE | SH1_SCISCR_RE); + putreg8(scr, SH1_SCI_BASE + SH1_SCI_SCR_OFFSET); #endif } - - diff --git a/arch/sh/src/sh1/sh1_serial.c b/arch/sh/src/sh1/sh1_serial.c new file mode 100644 index 0000000000..cfdfbe3490 --- /dev/null +++ b/arch/sh/src/sh1/sh1_serial.c @@ -0,0 +1,847 @@ +/**************************************************************************** + * arch/sh/src/sh1/sh1_serial.c + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chip.h" +#include "up_arch.h" +#include "up_internal.h" + +#ifdef CONFIG_USE_SERIALDRIVER + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Some sanity checks *******************************************************/ + +/* Is there a serial console? */ + +#if defined(CONFIG_SCI0_SERIAL_CONSOLE) || defined(CONFIG_SCI1_SERIAL_CONSOLE) +# define HAVE_CONSOLE +#else +# undef HAVE_CONSOLE +#endif + +/* Which SCI with be tty0/console and which tty1? */ + +#if defined(CONFIG_SCI0_SERIAL_CONSOLE) || !defined(CONFIG_SCI1_SERIAL_CONSOLE) +# undef CONFIG_SCI1_SERIAL_CONSOLE +# ifdef CONFIG_SCI0_SERIAL_CONSOLE +# define CONSOLE_DEV g_sci0port /* SCI0 is console */ +# endif +# define TTYS0_DEV g_sci0port /* SCI0 is tty0 */ +# define TTYS1_DEV g_sci1port /* SCI1 is tty1 */ +#else +# define CONSOLE_DEV g_sci1port /* SCI1 is console */ +# define TTYS0_DEV g_sci1port /* SCI1 is tty0 */ +# define TTYS1_DEV g_sci0port /* SCI0 is tty1 */ +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct up_dev_s +{ + uint32 scibase; /* Base address of SCI registers */ + uint32 baud; /* Configured baud */ + ubyte scr; /* Saved SCR value */ + ubyte ssr; /* Saved SR value (only used during interrupt processing) */ + ubyte irq; /* IRQ associated with this SCI */ + ubyte parity; /* 0=none, 1=odd, 2=even */ + ubyte bits; /* Number of bits (7 or 8) */ + boolean stopbits2; /* TRUE: Configure with 2 stop bits instead of 1 */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int up_setup(struct uart_dev_s *dev); +static void up_shutdown(struct uart_dev_s *dev); +static int up_attach(struct uart_dev_s *dev); +static void up_detach(struct uart_dev_s *dev); +static int up_interrupt(int irq, void *context); +static int up_ioctl(struct file *filep, int cmd, unsigned long arg); +static int up_receive(struct uart_dev_s *dev, uint32 *status); +static void up_rxint(struct uart_dev_s *dev, boolean enable); +static boolean up_rxavailable(struct uart_dev_s *dev); +static void up_send(struct uart_dev_s *dev, int ch); +static void up_txint(struct uart_dev_s *dev, boolean enable); +static boolean up_txready(struct uart_dev_s *dev); + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +struct uart_ops_s g_sci_ops = +{ + .setup = up_setup, + .shutdown = up_shutdown, + .attach = up_attach, + .detach = up_detach, + .ioctl = up_ioctl, + .receive = up_receive, + .rxint = up_rxint, + .rxavailable = up_rxavailable, + .send = up_send, + .txint = up_txint, + .txready = up_txready, + .txempty = up_txready, +}; + +/* I/O buffers */ + +static char g_sci0rxbuffer[CONFIG_SCI0_RXBUFSIZE]; +static char g_sci0txbuffer[CONFIG_SCI0_TXBUFSIZE]; +static char g_sci1rxbuffer[CONFIG_SCI1_RXBUFSIZE]; +static char g_sci1txbuffer[CONFIG_SCI1_TXBUFSIZE]; + +/* This describes the state of the SH1 sci0 port. */ + +static struct up_dev_s g_sci0priv = +{ + .scibase = SH1_SCI0_BASE, + .baud = CONFIG_SCI0_BAUD, + .irq = SH1_SCI0_IRQ, + .parity = CONFIG_SCI0_PARITY, + .bits = CONFIG_SCI0_BITS, + .stopbits2 = CONFIG_SCI0_2STOP, +}; + +static uart_dev_t g_sci0port = +{ + .recv = + { + .size = CONFIG_SCI0_RXBUFSIZE, + .buffer = g_sci0rxbuffer, + }, + .xmit = + { + .size = CONFIG_SCI0_TXBUFSIZE, + .buffer = g_sci0txbuffer, + }, + .ops = &g_sci_ops, + .priv = &g_sci0priv, +}; + +/* This describes the state of the SH1 sci1 port. */ + +static struct up_dev_s g_sci1priv = +{ + .scibase = SH1_SCI1_BASE, + .baud = CONFIG_SCI1_BAUD, + .irq = SH1_SCI1_IRQ, + .parity = CONFIG_SCI1_PARITY, + .bits = CONFIG_SCI1_BITS, + .stopbits2 = CONFIG_SCI1_2STOP, +}; + +static uart_dev_t g_sci1port = +{ + .recv = + { + .size = CONFIG_SCI1_RXBUFSIZE, + .buffer = g_sci1rxbuffer, + }, + .xmit = + { + .size = CONFIG_SCI1_TXBUFSIZE, + .buffer = g_sci1txbuffer, + }, + .ops = &g_sci_ops, + .priv = &g_sci1priv, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_serialin + ****************************************************************************/ + +static inline ubyte up_serialin(struct up_dev_s *priv, int offset) +{ + return getreg8(priv->scibase + offset); +} + +/**************************************************************************** + * Name: up_serialout + ****************************************************************************/ + +static inline void up_serialout(struct up_dev_s *priv, int offset, ubyte value) +{ + putreg8(value, priv->scibase + offset); +} + +/**************************************************************************** + * Name: up_disableuartint + ****************************************************************************/ + +static inline void up_disableuartint(struct up_dev_s *priv, ubyte *scr) +{ + /* Return a copy of the current scr settings */ + + if (scr) + { + *scr = priv->scr; + } + + /* The disable all interrupts */ + + priv->scr |= SH1_SCISCR_ALLINTS; + up_serialout(priv, SH1_SCI_SCR_OFFSET, priv->scr); +} + +/**************************************************************************** + * Name: up_restoreuartint + ****************************************************************************/ + +static inline void up_restoreuartint(struct up_dev_s *priv, ubyte scr) +{ + /* Set the interrupt bits in the scr value */ + + priv->scr &= ~SH1_SCISCR_ALLINTS; + priv->scr |= (scr & SH1_SCISCR_ALLINTS); + up_serialout(priv, SH1_SCI_SCR_OFFSET, priv->scr); +} + +/**************************************************************************** + * Name: up_waittxready + ****************************************************************************/ + +#ifdef HAVE_CONSOLE +static inline void up_waittxready(struct up_dev_s *priv) +{ + int tmp; + + /* Limit how long we will wait for the TDR empty condition */ + + for (tmp = 1000 ; tmp > 0 ; tmp--) + { + /* Check if the TDR is empty. The TDR becomes empty when: (1) the + * the chip is reset or enters standby mode, (2) the TE bit in the SCR + * is cleared, or (3) the current TDR contents are loaded in the TSR so + * that new data can be written in the TDR. + */ + + if ((up_serialin(priv, SH1_SCI_SSR_OFFSET) & SH1_SCISSR_TDRE) != 0) + { + /* The TDR is empty... return */ + break; + } + } +} +#endif + +/**************************************************************************** + * Name: up_setbrr + * + * Description: + * Calculate the correct value for the BRR given the configured frequency + * and the desired BAUD settings. + * + ****************************************************************************/ + +static inline void up_setbrr(struct up_dev_s *priv, unsigned int baud) +{ + /* The calculation of the BRR to achieve the desired BAUD is given by the + * following formula: + * + * brr = (f/(64*2**(2n-1)*b))-1 + * + * Where: + * + * b = bit rate + * f = frequency (Hz) + * n = divider setting (0, 1, 2, 3) + * + * For n == 0 and with rounding this becomes: + * + * brr = ((((f+16)/32) +(b/2)) / b) - 1 + * + * For example, if the processor is clocked at 10 MHz and 9600 is the + * desired BAUD: + * + * brr = ((10,000,016/32) + 4800) / 9600 -1 + * = 32 + */ + + uint32 brr = ((((SH1_CLOCK + 16) / 32) + (baud >> 1)) / baud) - 1; + up_serialout(priv, SH1_SCI_BRR_OFFSET, (uint16)brr); +} + +/**************************************************************************** + * Name: up_setup + * + * Description: + * Configure the SCI baud, bits, parity, fifos, etc. This + * method is called the first time that the serial port is + * opened. + * + ****************************************************************************/ + +static int up_setup(struct uart_dev_s *dev) +{ +#ifndef CONFIG_SUPPRESS_SCI_CONFIG + ubyte smr; + + /* Disable the transmitter and receiver */ + + priv->scr = up_serialin(priv, SH1_SCI_SCR_OFFSET); + priv->scr &= ~(SH1_SCISCR_TE | SH1_SCISCR_RE); + up_serialout(priv, SH1_SCI_SCR_OFFSET, priv->scr); + + /* Set communication to be asynchronous with the configured number of data + * bits, parity, and stop bits. Use the internal clock (undivided) + */ + + smr = 0; + if (priv->bits == 7) + { + smr |= SH1_SCISMR_CHR; + } + + if (parity == 1) + { + smr |= (SH1_SCISMR_PE|SH1_SCISMR_OE); + } + else if (parity == 2) + { + smr |= SH1_SCISMR_PE; + } + + if (priv->stopbits2) + { + smr |= SH1_SCISMR_STOP; + } + + up_serialout(priv, SH1_SCI_SMR_OFFSET, smr); + + /* Set the baud based on the configured console baud and configured + * system clock. + */ + + up_setbrr(priv, priv->baud); + + /* Select the internal clock source as input */ + + priv->scr &= ~SH1_SCISCR_CKEMASK; + up_serialout(priv, SH1_SCI_SCR_OFFSET, priv->scr); + + /* Wait a bit for the clocking to settle */ + + up_udelay(100); + + /* Then enable the transmitter and reciever */ + + priv->scr |= (SH1_SCISCR_TE | SH1_SCISCR_RE); + up_serialout(priv, SH1_SCI_SCR_OFFSET, priv->scr); +#endif + return OK; +} + +/**************************************************************************** + * Name: up_shutdown + * + * Description: + * Disable the SCI. This method is called when the serial port is closed + * + ****************************************************************************/ + +static void up_shutdown(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + up_disableuartint(priv, NULL); +} + +/**************************************************************************** + * Name: up_attach + * + * Description: + * Configure the SCI to operation in interrupt driven mode. This method is + * called when the serial port is opened. Normally, this is just after the + * the setup() method is called, however, the serial console may operate in + * a non-interrupt driven mode during the boot phase. + * + * RX and TX interrupts are not enabled when by the attach method (unless the + * hardware supports multiple levels of interrupt enabling). The RX and TX + * interrupts are not enabled until the txint() and rxint() methods are called. + * + ****************************************************************************/ + +static int up_attach(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + int ret; + + /* Attach the RDR full IRQ */ + + ret = irq_attach(priv->irq + , up_interrupt); + if (ret == OK) + { + /* Enable the interrupt + */ + + up_enable_irq(priv->irq); + } + + /* Enable the RDR full and TDR empty interrupts at the interupt controller + * (RX and TX interrupts are still disabled in the SCI) + */ + + if (ret == OK) + { + + up_enable_irq(priv->irq); + up_enable_irq(priv->irq); + } + + return ret; +} + +/**************************************************************************** + * Name: up_detach + * + * Description: + * Detach SCI interrupts. This method is called when the serial port is + * closed normally just before the shutdown method is called. The exception is + * the serial console which is never shutdown. + * + ****************************************************************************/ + +static void up_detach(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + up_disable_irq(priv->irq); + irq_detach(priv->irq); +} + +/**************************************************************************** + * Name: up_interrupt + * + * Description: + * This is the SCI interrupt handler. It will be invoked + * when an interrupt received on the 'irq' It should call + * uart_transmitchars or uart_receivechar to perform the + * appropriate data transfers. The interrupt handling logic\ + * must be able to map the 'irq' number into the approprite + * uart_dev_s structure in order to call these functions. + * + ****************************************************************************/ + +static int up_interrupt(int irq, void *context) +{ + struct uart_dev_s *dev = NULL; + struct up_dev_s *priv; + int passes; + boolean handled; + +#ifdef CONFIG_SH1_SCI0 + if (g_sci0priv.irq == irq) + { + dev = &g_sci0port; + } + else +#endif +#ifdef CONFIG_SH1_SCI1 + if (g_sci1priv.irq == irq) + { + dev = &g_sci1port; + } + else +#endif +#ifdef CONFIG_SH1_SCI2 + if (g_sci2priv.irq == irq) + { + dev = &g_sci2port; + } + else +#endif +#ifdef CONFIG_SH1_SCI3 + if (g_sci3priv.irq == irq) + { + dev = &g_sci3port; + } + else +#endif + { + PANIC(OSERR_INTERNAL); + } + priv = (struct up_dev_s*)dev->priv; + + /* Loop until there are no characters to be transferred or, + * until we have been looping for a long time. + */ + + for (passes = 0; passes < 256 && handled; passes++) + { + handled = FALSE; + + /* Get the current SCI status */ + + priv->ssr = up_serialin(priv, SH1_SCI_SSR_OFFSET); + + /* Handle incoming, receive bytes (with or without timeout) */ + + if ((priv->ssr & SH1_SCISR_RNE) != 0) + { + /* Rx buffer not empty ... process incoming bytes */ + + uart_recvchars(dev); + } + + /* Handle outgoing, transmit bytes */ + + if ((priv->ssr & SH1_SCISR_TF) == 0) + { + /* Tx FIFO not full ... process outgoing bytes */ + + uart_xmitchars(dev); + } + } + return OK; +} + +/**************************************************************************** + * Name: up_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + ****************************************************************************/ + +static int up_ioctl(struct file *filep, int cmd, unsigned long arg) +{ + struct inode *inode = filep->f_inode; + struct uart_dev_s *dev = inode->i_private; + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + int ret = OK; + + switch (cmd) + { + case TIOCSERGSTRUCT: + { + struct up_dev_s *user = (struct up_dev_s*)arg; + if (!user) + { + *get_errno_ptr() = EINVAL; + ret = ERROR; + } + else + { + memcpy(user, dev, sizeof(struct up_dev_s)); + } + } + break; + + default: + *get_errno_ptr() = ENOTTY; + ret = ERROR; + break; + } + + return ret; +} + +/**************************************************************************** + * Name: up_receive + * + * Description: + * Called (usually) from the interrupt level to receive one + * character from the SCI. Error bits associated with the + * receipt are provided in the the return 'status'. + * + ****************************************************************************/ + +static int up_receive(struct uart_dev_s *dev, uint32 *status) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + uint16 rxbufr; + + rxbufr = up_serialin(priv, SH1_SCI_RXBUFR_OFFSET); + *status = (uint32)priv->ssr << 16 | rxbufr; + return rxbufr & 0xff; +} + +/**************************************************************************** + * Name: up_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +static void up_rxint(struct uart_dev_s *dev, boolean enable) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + if (enable) + { + /* Enable the RDR full interrupt */ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + priv->scr |= SH1_SCISCR_RIE; +#endif + } + else + { + /* Disable the RDR full interrupt */ + + priv->scr &= ~SH1_SCISCR_RIE; + } + + /* Write the modified SCR value to hardware */ + + up_serialout(priv, SH1_SCI_SCR_OFFSET, priv->scr); +} + +/**************************************************************************** + * Name: up_rxavailable + * + * Description: + * Return TRUE if the RDR is not empty + * + ****************************************************************************/ + +static boolean up_rxavailable(struct uart_dev_s *dev) +{ + /* Return true if the RDR full bit is set in the SSR */ + + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + return ((up_serialin(priv, SH1_SCI_SSR_OFFSET) & SH1_SCISSR_RDRF) != 0); +} + +/**************************************************************************** + * Name: up_send + * + * Description: + * This method will send one byte on the SCI + * + ****************************************************************************/ + +static void up_send(struct uart_dev_s *dev, int ch) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + + /* Write the data to the TDR */ + + up_serialout(priv, SH1_SCI_BASE + SH1_SCI_TDR_OFFSET, (ubyte)ch); + + /* Clear the TDRE bit in the SSR */ + + ssr = up_serialin(priv, SH1_SCI_SSR_OFFSET); + ssr &= ~SH1_SCISSR_TDRE; + up_serialout(priv, SH1_SCI_BASE + SH1_SCI_SSR_OFFSET, ssr); +} + +/**************************************************************************** + * Name: up_txint + * + * Description: + * Call to enable or disable TX interrupts + * + ****************************************************************************/ + +static void up_txint(struct uart_dev_s *dev, boolean enable) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + if (enable) + { + /* Enable the TDR empty interrupt */ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + priv->scr |= SH1_SCISCR_TIE; +#endif + } + else + { + /* Disable the TDR empty interrupt */ + + priv->scr &= ~SH1_SCISCR_TIE; + } + + /* Write the modified SCR value to hardware */ + + up_serialout(priv, SH1_SCI_SCR_OFFSET, priv->scr); +} + +/**************************************************************************** + * Name: up_txready + * + * Description: + * Return TRUE if the TDR is empty + * + ****************************************************************************/ + +static boolean up_txready(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + return (up_serialin(priv, SH1_SCI_SSR_OFFSET) & SH1_SCISSR_TDRE) != 0; +} + +/**************************************************************************** + * Public Funtions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_serialinit + * + * Description: + * Performs the low level SCI initialization early in + * debug so that the serial console will be available + * during bootup. This must be called before up_serialinit. + * + ****************************************************************************/ + +void up_earlyserialinit(void) +{ + /* NOTE: All GPIO configuration for the SCIs was performed in + * up_lowsetup + */ + + /* Disable all UARTS */ + + up_disableuartint(TTYS0_DEV.priv, NULL); + up_disableuartint(TTYS1_DEV.priv, NULL); + + /* Configuration whichever one is the console */ + +#ifdef HAVE_CONSOLE + CONSOLE_DEV.isconsole = TRUE; + up_setup(&CONSOLE_DEV); +#endif +} + +/**************************************************************************** + * Name: up_serialinit + * + * Description: + * Register serial console and serial ports. This assumes + * that up_earlyserialinit was called previously. + * + ****************************************************************************/ + +void up_serialinit(void) +{ + /* Register the console */ + +#ifdef HAVE_CONSOLE + (void)uart_register("/dev/console", &CONSOLE_DEV); +#endif + + /* Register all SCIs */ + + (void)uart_register("/dev/ttyS0", &TTYS0_DEV); + (void)uart_register("/dev/ttyS1", &TTYS1_DEV); +} + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ +#ifdef HAVE_CONSOLE + struct up_dev_s *priv = (struct up_dev_s*)CONSOLE_DEV.priv; + ubyte scr; + + up_disableuartint(priv, &scr); + up_waittxready(priv); + up_serialout(priv, SH1_SCI_THR_OFFSET, (ubyte)ch); + + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + up_waittxready(priv); + up_serialout(priv, SH1_SCI_THR_OFFSET, '\r'); + } + + up_waittxready(priv); + up_restoreuartint(priv, scr); +#endif + return ch; +} + +#else /* CONFIG_USE_SERIALDRIVER */ + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ +#ifdef HAVE_CONSOLE + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + up_lowputc('\r'); + } + + up_lowputc(ch); +#endif + return ch; +} + +#endif /* CONFIG_USE_SERIALDRIVER */