diff options
Diffstat (limited to 'nuttx/arch/arm/src/c5471')
-rw-r--r-- | nuttx/arch/arm/src/c5471/Make.defs | 48 | ||||
-rw-r--r-- | nuttx/arch/arm/src/c5471/c5471_doirq.c | 104 | ||||
-rw-r--r-- | nuttx/arch/arm/src/c5471/c5471_irq.c | 242 | ||||
-rw-r--r-- | nuttx/arch/arm/src/c5471/c5471_lowputc.S | 127 | ||||
-rw-r--r-- | nuttx/arch/arm/src/c5471/c5471_serial.c | 811 | ||||
-rw-r--r-- | nuttx/arch/arm/src/c5471/c5471_timerisr.c | 125 | ||||
-rw-r--r-- | nuttx/arch/arm/src/c5471/c5471_vectors.S | 449 | ||||
-rw-r--r-- | nuttx/arch/arm/src/c5471/c5471_watchdog.c | 392 | ||||
-rw-r--r-- | nuttx/arch/arm/src/c5471/chip.h | 323 |
9 files changed, 2621 insertions, 0 deletions
diff --git a/nuttx/arch/arm/src/c5471/Make.defs b/nuttx/arch/arm/src/c5471/Make.defs new file mode 100644 index 000000000..54d337938 --- /dev/null +++ b/nuttx/arch/arm/src/c5471/Make.defs @@ -0,0 +1,48 @@ +############################################################################ +# c5471/Make.defs +# +# Copyright (C) 2007 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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 Gregory Nutt 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. +# +############################################################################ + +HEAD_ASRC = up_nommuhead.S + +CMN_ASRCS = up_saveusercontext.S up_fullcontextrestore.S +CMN_CSRCS = up_allocateheap.c up_assert.c up_blocktask.c up_copystate.c \ + up_createstack.c up_dataabort.c up_delay.c up_exit.c up_idle.c \ + up_initialize.c up_initialstate.c up_interruptcontext.c \ + up_prefetchabort.c up_releasepending.c up_releasestack.c \ + up_reprioritizertr.c up_schedulesigaction.c up_sigdeliver.c \ + up_syscall.c up_unblocktask.c up_undefinedinsn.c up_usestack.c + +CHIP_ASRCS = c5471_lowputc.S c5471_vectors.S +CHIP_CSRCS = c5471_doirq.c c5471_irq.c c5471_serial.c c5471_timerisr.c \ + c5471_watchdog.c diff --git a/nuttx/arch/arm/src/c5471/c5471_doirq.c b/nuttx/arch/arm/src/c5471/c5471_doirq.c new file mode 100644 index 000000000..19d898b4c --- /dev/null +++ b/nuttx/arch/arm/src/c5471/c5471_doirq.c @@ -0,0 +1,104 @@ +/************************************************************ + * c5471/c5471_doirq.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 Gregory Nutt 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 <nuttx/config.h> +#include <sys/types.h> +#include <nuttx/irq.h> +#include <nuttx/arch.h> +#include <assert.h> +#include "up_arch.h" +#include "os_internal.h" +#include "up_internal.h" + +/************************************************************ + * Definitions + ************************************************************/ + +/************************************************************ + * Public Data + ************************************************************/ + +/************************************************************ + * Private Data + ************************************************************/ + +/************************************************************ + * Private Functions + ************************************************************/ + +/************************************************************ + * Public Funtions + ************************************************************/ + +void c5471_doirq(int irq, uint32* regs) +{ + up_ledon(LED_INIRQ); +#ifdef CONFIG_SUPPRESS_INTERRUPTS + PANIC(OSERR_ERREXCEPTION); +#else + if ((unsigned)irq < NR_IRQS) + { + /* Current regs non-zero indicates that we are processing + * an interrupt; current_regs is also used to manage + * interrupt level context switches. + */ + + current_regs = regs; + + /* Mask and acknowledge the interrupt */ + + up_maskack_irq(irq); + + /* Deliver the IRQ */ + + irq_dispatch(irq, regs); + + /* Indicate that we are no long in an interrupt handler */ + + current_regs = NULL; + + /* Unmask the last interrupt (global interrupts are still + * disabled. + */ + + up_enable_irq(irq); + } + up_ledoff(LED_INIRQ); +#endif +} diff --git a/nuttx/arch/arm/src/c5471/c5471_irq.c b/nuttx/arch/arm/src/c5471/c5471_irq.c new file mode 100644 index 000000000..a9ab7b166 --- /dev/null +++ b/nuttx/arch/arm/src/c5471/c5471_irq.c @@ -0,0 +1,242 @@ +/************************************************************ + * c5471/c5471_irq.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 Gregory Nutt 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 <nuttx/config.h> +#include <sys/types.h> +#include <nuttx/irq.h> +#include "up_arch.h" +#include "os_internal.h" +#include "up_internal.h" + +/************************************************************ + * Definitions + ************************************************************/ + +#define ILR_EDGESENSITIVE 0x00000020 +#define ILR_PRIORITY 0x0000001E + +/************************************************************ + * Public Data + ************************************************************/ + +uint32 *current_regs; + +/************************************************************ + * Private Data + ************************************************************/ + +/* The value of _vflashstart is defined in ld.script. It + * could be hard-coded because we know that correct IRAM + * area is 0xffc00000. + */ + +extern int _svectors; /* Type does not matter */ + +/* The C5471 has FLASH at the low end of memory. The + * rrload bootloaer will catch all interrupts and re-vector + * them to vectors stored in IRAM. The following table is + * used to initialize those vectors. + */ + +static up_vector_t g_vectorinittab[] = +{ + (up_vector_t)NULL, + up_vectorundefinsn, + up_vectorswi, + up_vectorprefetch, + up_vectordata, + up_vectoraddrexcptn, + up_vectorirq, + up_vectorfiq +}; +#define NVECTORS ((sizeof(g_vectorinittab)) / sizeof(up_vector_t)) + +/************************************************************ + * Private Functions + ************************************************************/ + +/************************************************************ + * Name: up_ackirq + * + * Description: + * Acknowlede the IRQ.Bit 0 of the Interrupt Control + * Register == New IRQ agreement (NEW_IRQ_AGR). Reset IRQ + * output. Clear source IRQ register. Enables a new IRQ + * generation. Reset by internal logic. + * + ************************************************************/ + +static inline void up_ackirq(unsigned int irq) +{ + uint32 reg; + reg = getreg32(SRC_IRQ_REG); /* Insure appropriate IT_REG bit clears */ + putreg32(reg | 0x00000001, INT_CTRL_REG); /* write the NEW_IRQ_AGR bit. */ +} + +/************************************************************ + * Name: up_ackfiq + * + * Description: + * Acknowledge the FIQ. Bit 1 of the Interrupt Control + * Register == New FIQ agreement (NEW_FIQ_AGR). Reset FIQ + * output. Clear source FIQ register. Enables a new FIQ + * generation. Reset by internal logic. + * + ************************************************************/ + +static inline void up_ackfiq(unsigned int irq) +{ + uint32 reg; + reg = getreg32(SRC_FIQ_REG); /* Insure appropriate IT_REG bit clears */ + putreg32(reg | 0x00000002, INT_CTRL_REG); /* write the NEW_FIQ_AGR bit. */ +} + +/************************************************************ + * Name: up_vectorinitialize + ************************************************************/ + +static inline void up_vectorinitialize(void) +{ + up_vector_t *src = g_vectorinittab; + up_vector_t *dest = (up_vector_t*)&_svectors; + int i; + + for (i = 0; i < NVECTORS; i++) + { + *dest++ = *src++; + } +} + +/************************************************************ + * Public Funtions + ************************************************************/ + +/************************************************************ + * Name: up_irqinitialize + ************************************************************/ + +void up_irqinitialize(void) +{ + /* Disable all interrupts. */ + + putreg32(0x0000ffff, MASK_IT_REG); + + /* Clear any pending interrupts */ + + up_ackirq(0); + up_ackfiq(0); + putreg32(0x00000000, IT_REG); + + /* Override hardware defaults */ + + putreg32(ILR_EDGESENSITIVE | ILR_PRIORITY, ILR_IRQ2_REG); + putreg32(ILR_EDGESENSITIVE | ILR_PRIORITY, ILR_IRQ4_REG); + putreg32(ILR_PRIORITY, ILR_IRQ6_REG); + putreg32(ILR_EDGESENSITIVE | ILR_PRIORITY, ILR_IRQ15_REG); + + /* Initialize hardware interrupt vectors */ + + up_vectorinitialize(); + current_regs = NULL; + + /* And finally, enable interrupts */ + +#ifndef CONFIG_SUPPRESS_INTERRUPTS + irqrestore(SVC_MODE | PSR_F_BIT); +#endif +} + +/************************************************************ + * Name: up_disable_irq + * + * Description: + * Disable the IRQ specified by 'irq' + * + ************************************************************/ + +void up_disable_irq(int irq) +{ + if ((unsigned)irq < NR_IRQS) + { + uint32 reg = getreg32(MASK_IT_REG); + putreg32(reg | (1 << irq), MASK_IT_REG); + } +} + +/************************************************************ + * Name: up_enable_irq + * + * Description: + * Enable the IRQ specified by 'irq' + * + ************************************************************/ + +void up_enable_irq(int irq) +{ + if ((unsigned)irq < NR_IRQS) + { + uint32 reg = getreg32(MASK_IT_REG); + putreg32(reg & ~(1 << irq), MASK_IT_REG); + } +} + +/************************************************************ + * Name: up_maskack_irq + * + * Description: + * Mask the IRQ and acknowledge it + * + ************************************************************/ + +void up_maskack_irq(int irq) +{ + uint32 reg = getreg32(INT_CTRL_REG); + + /* Mask the interrupt */ + + reg = getreg32(MASK_IT_REG); + putreg32(reg | (1 << irq), MASK_IT_REG); + + /* Set the NEW_IRQ_AGR bit. This clears the IRQ src register + * enables generation of a new IRQ. + */ + + reg = getreg32(INT_CTRL_REG); + putreg32(reg | 0x00000001, INT_CTRL_REG); /* write the NEW_IRQ_AGR bit. */ +} diff --git a/nuttx/arch/arm/src/c5471/c5471_lowputc.S b/nuttx/arch/arm/src/c5471/c5471_lowputc.S new file mode 100644 index 000000000..78154fd8c --- /dev/null +++ b/nuttx/arch/arm/src/c5471/c5471_lowputc.S @@ -0,0 +1,127 @@ +/************************************************************************** + * c5471/c5471_lowputc.S + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 Gregory Nutt 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 <nuttx/config.h> +#include "up_internal.h" +#include "up_arch.h" + +/************************************************************************** + * Private Definitions + **************************************************************************/ + +/************************************************************************** + * Private Types + **************************************************************************/ + +/************************************************************************** + * Private Function Prototypes + **************************************************************************/ + +/************************************************************************** + * Global Variables + **************************************************************************/ + +/************************************************************************** + * Private Variables + **************************************************************************/ + +/************************************************************************** + * Private Functions + **************************************************************************/ + +/************************************************************************** + * Public Functions + **************************************************************************/ + +/************************************************************************** + * Name: up_lowputc + **************************************************************************/ + +/* This assembly language version has the advantage that it can does not + * require a C stack and uses only r0-r1. Hence it can be used during + * early boot phases. + */ + + .text + .global up_lowputc + .type up_lowputc, function +up_lowputc: + /* On entry, r0 holds the character to be printed */ + +#ifdef CONFIG_SERIAL_IRDA_CONSOLE + ldr r2, =UART_IRDA_BASE /* r2=IRDA UART base */ +#else + ldr r2, =UART_MODEM_BASE /* r2=Modem UART base */ +#endif + + /* Poll bit 0 of the UART_SSR register. When the bit + * is clear, the TX FIFO is no longer full + */ + +1: ldr r1, [r2, #UART_SSR_OFFS] + tst r1, #UART_SSR_TXFULL + bne 1b + + /* Send the character by writing it into the UART_THR + * register. + */ + + str r0, [r2, #UART_THR_OFFS] + + /* Wait for the tranmsit holding regiser (THR) to be + * emptied. This is detemined when bit 6 of the LSR + * is set. + */ + +2: ldr r1, [r2, #UART_LSR_OFFS] + tst r1, #0x00000020 + beq 2b + + /* If the character that we just sent was a linefeed, + * then send a carriage return as well. + */ + + teq r0, #'\n' + moveq r0, #'\r' + beq 1b + + /* And return */ + + mov pc, lr + diff --git a/nuttx/arch/arm/src/c5471/c5471_serial.c b/nuttx/arch/arm/src/c5471/c5471_serial.c new file mode 100644 index 000000000..13197816b --- /dev/null +++ b/nuttx/arch/arm/src/c5471/c5471_serial.c @@ -0,0 +1,811 @@ +/************************************************************ + * c5471/c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471c5471_serial.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 Gregory Nutt 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 <nuttx/config.h> +#include <sys/types.h> +#include <unistd.h> +#include <semaphore.h> +#include <string.h> +#include <errno.h> +#include <debug.h> +#include <nuttx/irq.h> +#include <nuttx/arch.h> +#include <nuttx/serial.h> +#include <arch/serial.h> +#include "up_arch.h" +#include "os_internal.h" +#include "up_internal.h" + +/************************************************************ + * Definitions + ************************************************************/ + +#define BASE_BAUD 115200 + +#if defined(CONFIG_UART_IRDA_HWFLOWCONTROL) || defined(CONFIG_UART_MODEM_HWFLOWCONTROL) +# define CONFIG_UART_HWFLOWCONTROL +#endif + +/************************************************************ + * Private Types + ************************************************************/ + +struct uart_regs_s +{ + uint32 ier; + uint32 lcr; + uint32 fcr; +#ifdef CONFIG_UART_HWFLOWCONTROL + uint32 efr; + uint32 tcr; +#endif +}; + +struct up_dev_s +{ + unsigned int uartbase; /* Base address of UART + * registers */ + unsigned int baud_base; /* Base baud for conversions */ + unsigned int baud; /* Configured baud */ + ubyte xmit_fifo_size; /* Size of transmit FIFO */ + ubyte irq; /* IRQ associated with + * this UART */ + ubyte parity; /* 0=none, 1=odd, 2=even */ + ubyte bits; /* Number of bits (7 or 8) */ +#ifdef CONFIG_UART_HWFLOWCONTROL + boolean flowcontrol; /* TRUE: Hardware flow control + * is enabled. */ +#endif + boolean stopbits2; /* TRUE: Configure with 2 + * stop bits instead of 1 */ + struct uart_regs_s regs; /* Shadow copy of readonly regs */ +}; + +/************************************************************ + * Private Function Prototypes + ************************************************************/ + +static int up_setup(struct uart_dev_s *dev); +static void up_shutdown(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, unsigned int *status); +static void up_rxint(struct uart_dev_s *dev, boolean enable); +static boolean up_rxfifonotempty(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_txfifonotfull(struct uart_dev_s *dev); +static boolean up_txfifoempty(struct uart_dev_s *dev); + +/************************************************************ + * Private Variables + ************************************************************/ + +struct uart_ops_s g_uart_ops = +{ + .setup = up_setup, + .shutdown = up_shutdown, + .handler = up_interrupt, + .ioctl = up_ioctl, + .receive = up_receive, + .rxint = up_rxint, + .rxfifonotempty = up_rxfifonotempty, + .send = up_send, + .txint = up_txint, + .txfifonotfull = up_txfifonotfull, + .txfifoempty = up_txfifoempty, +}; + +/* I/O buffers */ + +static char g_irdarxbuffer[CONFIG_UART_IRDA_RXBUFSIZE]; +static char g_irdatxbuffer[CONFIG_UART_IRDA_TXBUFSIZE]; +static char g_modemrxbuffer[CONFIG_UART_MODEM_RXBUFSIZE]; +static char g_modemtxbuffer[CONFIG_UART_MODEM_TXBUFSIZE]; + +/* This describes the state of the C5471 serial IRDA port. */ + +static struct up_dev_s g_irdapriv = +{ + .xmit_fifo_size = UART_IRDA_XMIT_FIFO_SIZE, + .baud_base = BASE_BAUD, + .uartbase = UART_IRDA_BASE, + .baud = CONFIG_UART_IRDA_BAUD, + .parity = CONFIG_UART_IRDA_PARITY, + .bits = CONFIG_UART_IRDA_BITS, +#ifdef CONFIG_UART_IRDA_HWFLOWCONTROL + .flowcontrol = TRUE, +#endif + .stopbits2 = CONFIG_UART_IRDA_2STOP, +}; + +static uart_dev_t g_irdaport = +{ + .irq = C5471_IRQ_UART_IRDA, + .recv = + { + .size = CONFIG_UART_IRDA_RXBUFSIZE, + .buffer = g_irdarxbuffer, + }, + .xmit = + { + .size = CONFIG_UART_IRDA_TXBUFSIZE, + .buffer = g_irdatxbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_irdapriv, +}; + +/* This describes the state of the C5471 serial Modem port. */ + +static struct up_dev_s g_modempriv = +{ + .xmit_fifo_size = UART_XMIT_FIFO_SIZE, + .baud_base = BASE_BAUD, + .uartbase = UART_MODEM_BASE, + .baud = CONFIG_UART_MODEM_BAUD, + .parity = CONFIG_UART_MODEM_PARITY, + .bits = CONFIG_UART_MODEM_BITS, +#ifdef CONFIG_UART_MODEM_HWFLOWCONTROL + .flowcontrol = TRUE, +#endif + .stopbits2 = CONFIG_UART_MODEM_2STOP, +}; + +static uart_dev_t g_modemport = +{ + .irq = C5471_IRQ_UART, + .recv = + { + .size = CONFIG_UART_MODEM_RXBUFSIZE, + .buffer = g_modemrxbuffer, + }, + .xmit = + { + .size = CONFIG_UART_MODEM_TXBUFSIZE, + .buffer = g_modemtxbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_modempriv, +}; + +/* Now, which one with be tty0/console and which tty1? */ + +#ifdef CONFIG_SERIAL_IRDA_CONSOLE +# define CONSOLE_DEV g_irdaport +# define TTYS0_DEV g_irdaport +# define TTYS1_DEV g_modemport +#else +# define CONSOLE_DEV g_modemport +# define TTYS0_DEV g_modemport +# define TTYS1_DEV g_irdaport +#endif + +/************************************************************ + * Private Functions + ************************************************************/ + +/************************************************************ + * Name: up_inserial + ************************************************************/ + +static inline uint32 up_inserial(struct up_dev_s *priv, uint32 offset) +{ + return getreg32(priv->uartbase + offset); +} + +/************************************************************ + * Name: up_serialout + ************************************************************/ + +static inline void up_serialout(struct up_dev_s *priv, uint32 offset, uint32 value) +{ + putreg32(value, priv->uartbase + offset); +} + +/************************************************************ + * Name: up_disableuartint + ************************************************************/ + +static inline void up_disableuartint(struct up_dev_s *priv, uint16 *ier) +{ + if (ier) + { + *ier = priv->regs.ier & UART_IER_INTMASK; + } + priv->regs.ier &= ~UART_IER_INTMASK; + up_serialout(priv, UART_IER_OFFS, priv->regs.ier); +} + +/************************************************************ + * Name: up_restoreuartint + ************************************************************/ + +static inline void up_restoreuartint(struct up_dev_s *priv, uint16 ier) +{ + priv->regs.ier |= ier & (UART_IER_RECVINT|UART_IER_XMITINT); + up_serialout(priv, UART_IER_OFFS, priv->regs.ier); +} + +/************************************************************ + * Name: up_waittxfifonotfull + ************************************************************/ + +static inline void up_waittxfifonotfull(struct up_dev_s *priv) +{ + int tmp; + + for (tmp = 1000 ; tmp > 0 ; tmp--) + { + if ((up_inserial(priv, UART_SSR_OFFS) & UART_SSR_TXFULL) == 0) + { + break; + } + } +} +/************************************************************ + * Name: up_disablebreaks + ************************************************************/ + +static inline void up_disablebreaks(struct up_dev_s *priv) +{ + priv->regs.lcr &= ~UART_LCR_BOC; + up_serialout(priv, UART_LCR_OFFS, priv->regs.lcr); +} + +/************************************************************ + * Name: up_enablebreaks + ************************************************************/ + +static inline void up_enablebreaks(struct up_dev_s *priv) +{ + priv->regs.lcr |= UART_LCR_BOC; + up_serialout(priv, UART_LCR_OFFS, priv->regs.lcr); +} + +/************************************************************ + * Name: up_setrate + ************************************************************/ + +static inline void up_setrate(struct up_dev_s *priv, unsigned int rate) +{ + uint32 div_bit_rate; + + switch (rate) + { + case 115200: + div_bit_rate = BAUD_115200; + break; + case 57600: + div_bit_rate = BAUD_57600; + break; + case 38400: + div_bit_rate = BAUD_38400; + break; + case 19200: + div_bit_rate = BAUD_19200; + break; + case 4800: + div_bit_rate = BAUD_4800; + break; + case 2400: + div_bit_rate = BAUD_2400; + break; + case 1200: + div_bit_rate = BAUD_1200; + break; + case 9600: + default: + div_bit_rate = BAUD_9600; + break; + } + + up_serialout(priv, UART_DIV_BIT_RATE_OFFS, div_bit_rate); +} + +/************************************************************ + * Name: up_setup + * + * Description: + * Configure the UART 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) +{ +#ifdef CONFIG_SUPPRESS_UART_CONFIG + struct up_dev_s *priv = dev->priv; + unsigned int cval; + + if (priv->bits == 7) + { + cval = UART_LCR_7BITS; + } + else + { + cval = UART_LCR_8BITS; + } + + if (priv->stopbits2) + { + cval |= UART_LCR_2STOP; + } + + if (priv->parity == 1) /* Odd parity */ + { + cval |= (UART_LCR_PAREN|UART_LCR_PARODD); + } + else if (priv->parity == 2) /* Even parity */ + { + cval |= (UART_LCR_PAREN|UART_LCR_PAREVEN); + } + + /* Both the IrDA and MODEM UARTs support RESET and UART mode. */ + + up_serialout(priv, UART_MDR_OFFS, MDR_RESET_MODE); + up_delay(5); + up_serialout(priv, UART_MDR_OFFS, MDR_UART_MODE); + up_delay(5); + + priv->regs.ier = up_inserial(priv, UART_IER_OFFS); + priv->regs.lcr = up_inserial(priv, UART_LCR_OFFS); +#ifdef CONFIG_UART_HWFLOWCONTROL + if (priv->flowcontrol) + { + priv->regs.efr = up_inserial(priv, UART_EFR_OFFS); + priv->regs.tcr = up_inserial(priv, UART_TCR_OFFS); + } +#endif + + up_disableuartint(priv, NULL); + + up_serialout(priv, UART_EFR_OFFS, 0x0010); /* Enable fifo control */ + up_serialout(priv, UART_TFCR_OFFS, 0); /* Reset to 0 */ + up_serialout(priv, UART_RFCR_OFFS, UART_FCR_RX_CLR); /* Clear RX fifo */ + up_serialout(priv, UART_TFCR_OFFS, UART_FCR_TX_CLR); /* Clear TX fifo */ + up_serialout(priv, UART_TFCR_OFFS, UART_FCR_FIFO_EN); /* Enable RX/TX fifos */ + + up_disablebreaks(priv); + + priv->regs.fcr = (priv->regs.fcr & 0xffffffcf) | (val & 0x30); + up_serialout(priv, UART_RFCR_OFFS, priv->regs.fcr); + + priv->regs.fcr = (priv->regs.fcr & 0xffffff3f) | (val & 0xc0); + up_serialout(priv, UART_RFCR_OFFS, priv->regs.fcr); + + up_setrate(priv, priv->baud); + + priv->regs.lcr &= 0xffffffe0; /* clear original field, and... */ + priv->regs.lcr |= (uint32)mode; /* Set new bits in that field. */ + up_serialout(priv, UART_LCR_OFFS, priv->regs.lcr); + +#ifdef CONFIG_UART_HWFLOWCONTROL + if (priv->flowcontrol) + { + /* Set the FIFO level triggers for flow control + * Halt = 48 bytes, resume = 12 bytes + */ + + priv->regs.tcr = (priv->regs.tcr & 0xffffff00) | 0x0000003c; + up_serialout(priv, UART_TCR_OFFS, priv->regs.tcr); + + /* Enable RTS/CTS flow control */ + + priv->regs.efr |= 0x000000c0; + up_serialout(priv, UART_EFR_OFFS, priv->regs.efr); + } + else + { + /* Disable RTS/CTS flow control */ + + priv->regs.efr &= 0xffffff3f; + up_serialout(priv, UART_EFR_OFFS, priv->regs.efr); + } +#endif +#endif + return OK; +} + +/************************************************************ + * Name: up_shutdown + * + * Description: + * Disable the UART. 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*)CONSOLE_DEV.priv; + up_disableuartint(priv, NULL); +} + +/************************************************************ + * Name: up_interrupt + * + * Description: + * This is the UART 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; + volatile uint32 cause; + + if (g_irdaport.irq == irq) + { + dev = &g_irdaport; + } + else if (g_modemport.irq == irq) + { + dev = &g_modemport; + } + else + { + PANIC(OSERR_INTERNAL); + } + priv = (struct up_dev_s*)dev->priv; + + cause = up_inserial(priv, UART_ISR_OFFS) & 0x0000003f; + + if ((cause & 0x0000000c) == 0x0000000c) + { + uint32 ier_val = 0; + + /* Is this an interrupt from the IrDA UART? */ + + if (irq == C5471_IRQ_UART_IRDA) + { + /* Save the currently enabled IrDA UART interrupts + * so that we can restore the IrDA interrupt state + * below. + */ + + ier_val = up_inserial(priv, UART_IER_OFFS); + + /* Then disable all IrDA UART interrupts */ + + up_serialout(priv, UART_IER_OFFS, 0); + } + + /* Receive characters from the RX fifo */ + + uart_recvchars(dev); + + /* read UART_RHR to clear int condition + * toss = up_inserialchar(priv,&status); + */ + + /* Is this an interrupt from the IrDA UART? */ + + if (irq == C5471_IRQ_UART_IRDA) + { + /* Restore the IrDA UART interrupt enables */ + + up_serialout(priv, UART_IER_OFFS, ier_val); + } + } + else if ((cause & 0x0000000c) == 0x00000004) + { + uart_recvchars(dev); + } + + if ((cause & 0x00000002) != 0) + { + 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; + + case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */ + { + irqstate_t flags = irqsave(); + up_enablebreaks(priv); + irqrestore(flags); + } + break; + + case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */ + { + irqstate_t flags; + flags = irqsave(); + up_disablebreaks(priv); + irqrestore(flags); + } + 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 UART. Error bits associated with the receipt are provided in the + * the return 'status'. + * + ************************************************************/ + +static int up_receive(struct uart_dev_s *dev, unsigned int *status) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + uint32 rhr; + uint32 lsr; + + /* Construct a 16bit status word that uses the high byte to + * hold the status bits associated with framing,parity,break + * and a low byte that holds error bits of LSR for + * conditions such as overflow, etc. + */ + + rhr = up_inserial(priv, UART_RHR_OFFS); + lsr = up_inserial(priv, UART_LSR_OFFS); + + *status = (unsigned int)((rhr & 0x0000ff00) | (lsr & 0x000000ff)); + + return rhr & 0x000000ff; +} + +/************************************************************ + * 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) + { +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + priv->regs.ier |= UART_IER_RECVINT; + up_serialout(priv, UART_IER_OFFS, priv->regs.ier); +#endif + } + else + { + priv->regs.ier &= ~UART_IER_RECVINT; + up_serialout(priv, UART_IER_OFFS, priv->regs.ier); + } +} + +/************************************************************ + * Name: up_rxfifonotempty + * + * Description: + * Return TRUE if the receive fifo is not empty + * + ************************************************************/ + +static boolean up_rxfifonotempty(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + return up_inserial(priv, UART_LSR_OFFS) & UART_RX_FIFO_NOEMPTY; +} + +/************************************************************ + * Name: up_send + * + * Description: + * This method will send one byte on the UART + * + ************************************************************/ + +static void up_send(struct uart_dev_s *dev, int ch) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + up_serialout(priv, UART_THR_OFFS, (ubyte)ch); +} + +/************************************************************ + * 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) + { +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + priv->regs.ier |= UART_IER_XMITINT; + up_serialout(priv, UART_IER_OFFS, priv->regs.ier); +#endif + } + else + { + priv->regs.ier &= ~UART_IER_XMITINT; + up_serialout(priv, UART_IER_OFFS, priv->regs.ier); + } +} + +/************************************************************ + * Name: up_txfifonotfull + * + * Description: + * Return TRUE if the tranmsit fifo is not full + * + ************************************************************/ + +static boolean up_txfifonotfull(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + return (up_inserial(priv, UART_SSR_OFFS) & UART_SSR_TXFULL) == 0; +} + +/************************************************************ + * Name: up_txfifoempty + * + * Description: + * Return TRUE if the transmit fifo is empty + * + ************************************************************/ + +static boolean up_txfifoempty(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + return (up_inserial(priv, UART_LSR_OFFS) & UART_LSR_TREF) != 0; +} + +/************************************************************ + * Public Funtions + ************************************************************/ + +/************************************************************ + * Name: up_serialinit + * + * Description: + * Performs the low level UART 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) +{ + up_disableuartint(TTYS0_DEV.priv, NULL); + up_disableuartint(TTYS1_DEV.priv, NULL); + + CONSOLE_DEV.isconsole = TRUE; + up_setup(&CONSOLE_DEV); +} + +/************************************************************ + * Name: up_serialinit + * + * Description: + * Register serial console and serial ports. This assumes + * that up_earlyserialinit was called previously. + * + ************************************************************/ + +void up_serialinit(void) +{ + (void)uart_register("/dev/console", &CONSOLE_DEV); + (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) +{ + struct up_dev_s *priv = (struct up_dev_s*)CONSOLE_DEV.priv; + uint16 ier; + + up_disableuartint(priv, &ier); + up_waittxfifonotfull(priv); + up_serialout(priv, UART_THR_OFFS, (ubyte)ch); + + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + up_waittxfifonotfull(priv); + up_serialout(priv, UART_THR_OFFS, '\r'); + } + + up_waittxfifonotfull(priv); + up_restoreuartint(priv, ier); + return ch; +} + diff --git a/nuttx/arch/arm/src/c5471/c5471_timerisr.c b/nuttx/arch/arm/src/c5471/c5471_timerisr.c new file mode 100644 index 000000000..e37043173 --- /dev/null +++ b/nuttx/arch/arm/src/c5471/c5471_timerisr.c @@ -0,0 +1,125 @@ +/************************************************************ + * c5471/c5471_timerisr.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 Gregory Nutt 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 <nuttx/config.h> +#include <sys/types.h> +#include <debug.h> +#include <nuttx/arch.h> +#include "clock_internal.h" +#include "up_internal.h" +#include "up_arch.h" + +/************************************************************ + * Definitions + ************************************************************/ + +/* We want the general purpose timer running at the rate + * MSEC_PER_TICK. The C5471 clock is 47.5MHz and we're using + * a timer PTV value of 3 (3 == divide incoming frequency by + * 16) which then yields a 16 bitCLKS_PER_INT value + * of 29687. + * + * 47500000 / 16 = 2968750 clocks/sec + * 2968750 / 100 = 29687 clocks/ 100Hz interrupt + * + */ + +#define CLKS_PER_INT 29687 +#define CLKS_PER_INT_SHIFT 5 +#define AR 0x00000010 +#define ST 0x00000008 +#define PTV 0x00000003 + +/************************************************************ + * Private Types + ************************************************************/ + +/************************************************************ + * Private Function Prototypes + ************************************************************/ + +/************************************************************ + * Global Functions + ************************************************************/ + +/************************************************************ + * Function: up_timerisr + * + * Description: + * The timer ISR will perform a variety of services for + * various portions of the systems. + * + ************************************************************/ + +int up_timerisr(int irq, uint32 *regs) +{ + /* Process timer interrupt */ + + sched_process_timer(); + return 0; +} + +/************************************************************ + * Function: up_timerinit + * + * Description: + * This function is called during start-up to initialize + * the timer interrupt. + * + ************************************************************/ + +void up_timerinit(void) +{ + uint32 val; + + up_disable_irq(C5471_IRQ_SYSTIMER); + + /* Start the general purpose timer running in auto-reload mode + * so that an interrupt is generated at the rate MSEC_PER_TICK. + */ + + val = ((CLKS_PER_INT-1) << CLKS_PER_INT_SHIFT) | AR | ST | PTV; + putreg32(val, C5471_TIMER2_CTRL); + + /* Attach and enable the timer interrupt */ + + irq_attach(C5471_IRQ_SYSTIMER, (xcpt_t)up_timerisr); + up_enable_irq(C5471_IRQ_SYSTIMER); +} + diff --git a/nuttx/arch/arm/src/c5471/c5471_vectors.S b/nuttx/arch/arm/src/c5471/c5471_vectors.S new file mode 100644 index 000000000..328485e17 --- /dev/null +++ b/nuttx/arch/arm/src/c5471/c5471_vectors.S @@ -0,0 +1,449 @@ +/******************************************************************** + * c5471/c5471_vectors.S + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 Gregory Nutt 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 <nuttx/config.h> +#include <nuttx/irq.h> +#include "up_arch.h" + +/******************************************************************** + * Definitions + ********************************************************************/ + +/******************************************************************** + * Global Data + ********************************************************************/ + + .data +g_irqtmp: + .word 0 /* Saved lr */ + .word 0 /* Saved spsr */ +g_undeftmp: + .word 0 /* Saved lr */ + .word 0 /* Saved spsr */ +g_aborttmp: + .word 0 /* Saved lr */ + .word 0 /* Saved spsr */ + +/******************************************************************** + * Assembly Macros + ********************************************************************/ + +/******************************************************************** + * Private Functions + ********************************************************************/ + + .text + +/******************************************************************** + * Public Functions + ********************************************************************/ + + .text + +/******************************************************************** + * Name: up_vectorirq + * + * Description: + * Interrupt excetpion. Entered in IRQ mode with spsr = SVC + * CPSR, lr = SVC PC + ********************************************************************/ + + .globl up_vectorirq + .type up_vectorirq, %function +up_vectorirq: + /* On entry, we are in IRQ mode. We are free to use + * the IRQ mode r13 and r14. + * + */ + + ldr r13, .Lirqtmp + sub lr, lr, #4 + str lr, [r13] @ save lr_IRQ + mrs lr, spsr + str lr, [r13, #4] @ save spsr_IRQ + + /* Then switch back to SVC mode */ + + bic lr, lr, #MODE_MASK /* Keep F and T bits */ + orr lr, lr, #(SVC_MODE | PSR_I_BIT) + msr cpsr_c, lr /* Switch to SVC mode */ + + /* Create a context structure. First set aside a stack frame + * and store r0-r12 into the frame. + */ + + sub sp, sp, #XCPTCONTEXT_SIZE + stmia sp, {r0-r12} /* Save the SVC mode regs */ + + /* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */ + + add r1, sp, #XCPTCONTEXT_SIZE + mov r2, r14 + + /* Get the values for r15(pc) and CPSR in r3 and r4 */ + + ldr r0, .Lirqtmp /* Points to temp storage */ + ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ + + add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ + stmia r0, {r1-r4} + + /* Now decode the interrupt */ + +#if 0 + ldr lr, =SRC_IRQ_BIN_REG /* Fetch encoded IRQ */ + ldr r0, [lr] + and r0, r0, #0x0f /* Valid range is 0..15 */ + + /* Problems here... cannot read SRC_IRQ_BIN_REQ (and/or + * SRC_IRQ_REQ because this will clear edge triggered + * interrupts. Plus, no way to validate spurious + * interrupt. + */ +#else + ldr r6, =SRC_IRQ_REG + ldr r6, [r6] /* Get source IRQ reg */ + mov r0, #0 /* Assume IRQ0_IRQ set */ +.Lmorebits: + tst r6, #1 /* Is IRQ set? */ + bne .Lhaveirq /* Yes... we have the IRQ */ + add r0, r0, #1 /* Setup next IRQ */ + mov r6, r6, lsr #1 /* Shift right one */ + cmp r0, #16 /* Only 16 valid bits */ + bcc .Lmorebits /* Keep until we have looked + * at all bits */ + b .Lnoirqset /* If we get here, there is + * no pending interrupt */ +.Lhaveirq: +#endif + /* Then call the IRQ handler with interrupt disabled. */ + + mov fp, #0 /* Init frame pointer */ + mov r1, sp /* Get r1=xcp */ + bl c5471_doirq /* Call the handler */ + + /* Restore the CPSR, SVC modr registers and return */ +.Lnoirqset: + ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ + msr spsr, r0 + ldmia sp, {r0-r15}^ /* Return */ + +.Lirqtmp: + .word g_irqtmp + + .align 5 + +/******************************************************************** + * Function: up_vectorswi + * + * Description: + * SWI interrupt. We enter the SWI in SVC mode + ********************************************************************/ + + .globl up_vectorswi + .type up_vectorswi, %function +up_vectorswi: + + /* The c547x rrload bootloader intemediates all + * interrupts. For the* case of the SWI, it mucked + * with the stack to create some temporary registers. + * We'll have to recover from this mucking here. + */ + + ldr r14, [sp,#-0x4] /* rrload workaround */ + + /* Create a context structure. First set aside a stack frame + * and store r0-r12 into the frame. + */ + + sub sp, sp, #XCPTCONTEXT_SIZE + stmia sp, {r0-r12} /* Save the SVC mode regs */ + + /* Get the correct values of r13(sp), r14(lr), r15(pc) + * and CPSR in r1-r4 */ + + add r1, sp, #XCPTCONTEXT_SIZE + mov r2, r14 /* R14 is altered on return from SWI */ + mov r3, r14 /* Save r14 as the PC as well */ + mrs r4, spsr /* Get the saved CPSR */ + + add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ + stmia r0, {r1-r4} + + /* Then call the SWI handler with interrupt disabled. + * void up_syscall(struct xcptcontext *xcp) + */ + + mov fp, #0 /* Init frame pointer */ + mov r0, sp /* Get r0=xcp */ + bl up_syscall /* Call the handler */ + + /* Restore the CPSR, SVC modr registers and return */ + + ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ + msr spsr, r0 + ldmia sp, {r0-r15}^ /* Return */ + + .align 5 + +/******************************************************************** + * Name: up_vectordata + * + * Description: + * Data abort Exception dispatcher. Give control to data + * abort handler. This function is entered in ABORT mode + * with spsr = SVC CPSR, lr = SVC PC + * + ********************************************************************/ + + .globl up_vectordata + .type up_vectordata, %function +up_vectordata: + /* On entry we are free to use the ABORT mode registers + * r13 and r14 + */ + + ldr r13, .Ldaborttmp /* Points to temp storage */ + sub lr, lr, #8 /* Fixup return */ + str lr, [r13] /* Save in temp storage */ + mrs lr, spsr /* Get SPSR */ + str lr, [r13, #4] /* Save in temp storage */ + + /* Then switch back to SVC mode */ + + bic lr, lr, #MODE_MASK /* Keep F and T bits */ + orr lr, lr, #(SVC_MODE | PSR_I_BIT) + msr cpsr_c, lr /* Switch to SVC mode */ + + /* Create a context structure. First set aside a stack frame + * and store r0-r12 into the frame. + */ + + sub sp, sp, #XCPTCONTEXT_SIZE + stmia sp, {r0-r12} /* Save the SVC mode regs */ + + /* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */ + + add r1, sp, #XCPTCONTEXT_SIZE + mov r2, r14 + + /* Get the values for r15(pc) and CPSR in r3 and r4 */ + + ldr r0, .Ldaborttmp /* Points to temp storage */ + ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ + + add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ + stmia r0, {r1-r4} + + /* Then call the data abort handler with interrupt disabled. + * void up_dataabort(struct xcptcontext *xcp) + */ + + mov fp, #0 /* Init frame pointer */ + mov r0, sp /* Get r0=xcp */ + bl up_dataabort /* Call the handler */ + + /* Restore the CPSR, SVC modr registers and return */ + + ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ + msr spsr_cxsf, r0 + ldmia sp, {r0-r15}^ /* Return */ + +.Ldaborttmp: + .word g_aborttmp + + .align 5 + +/******************************************************************** + * Name: up_vectorprefetch + * + * Description: + * Prefetch abort exception. Entered in ABT mode with + * spsr = SVC CPSR, lr = SVC PC + ********************************************************************/ + + .globl up_vectorprefetch + .type up_vectorprefetch, %function +up_vectorprefetch: + /* On entry we are free to use the ABORT mode registers + * r13 and r14 + */ + + ldr r13, .Lpaborttmp /* Points to temp storage */ + sub lr, lr, #4 /* Fixup return */ + str lr, [r13] /* Save in temp storage */ + mrs lr, spsr /* Get SPSR */ + str lr, [r13, #4] /* Save in temp storage */ + + /* Then switch back to SVC mode */ + + bic lr, lr, #MODE_MASK /* Keep F and T bits */ + orr lr, lr, #(SVC_MODE | PSR_I_BIT) + msr cpsr_c, lr /* Switch to SVC mode */ + + /* Create a context structure. First set aside a stack frame + * and store r0-r12 into the frame. + */ + + sub sp, sp, #XCPTCONTEXT_SIZE + stmia sp, {r0-r12} /* Save the SVC mode regs */ + + /* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */ + + add r1, sp, #XCPTCONTEXT_SIZE + mov r2, r14 + + /* Get the values for r15(pc) and CPSR in r3 and r4 */ + + ldr r0, .Lpaborttmp /* Points to temp storage */ + ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ + + add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ + stmia r0, {r1-r4} + + /* Then call the prefetch abort handler with interrupt disabled. + * void up_prefetchabort(struct xcptcontext *xcp) + */ + + mov fp, #0 /* Init frame pointer */ + mov r0, sp /* Get r0=xcp */ + bl up_prefetchabort /* Call the handler */ + + /* Restore the CPSR, SVC modr registers and return */ + + ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ + msr spsr_cxsf, r0 + ldmia sp, {r0-r15}^ /* Return */ + +.Lpaborttmp: + .word g_aborttmp + + .align 5 + +/******************************************************************** + * Name: up_vectorundefinsn + * + * Description: + * Undefined instruction entry exception. Entered in + * UND mode, spsr = SVC CPSR, lr = SVC PC + * + ********************************************************************/ + + .globl up_vectorundefinsn + .type up_vectorundefinsn, %function +up_vectorundefinsn: + /* On entry we are free to use the UND mode registers + * r13 and r14 + */ + + ldr r13, .Lundeftmp /* Points to temp storage */ + str lr, [r13] /* Save in temp storage */ + mrs lr, spsr /* Get SPSR */ + str lr, [r13, #4] /* Save in temp storage */ + + /* Then switch back to SVC mode */ + + bic lr, lr, #MODE_MASK /* Keep F and T bits */ + orr lr, lr, #(SVC_MODE | PSR_I_BIT) + msr cpsr_c, lr /* Switch to SVC mode */ + + /* Create a context structure. First set aside a stack frame + * and store r0-r12 into the frame. + */ + + sub sp, sp, #XCPTCONTEXT_SIZE + stmia sp, {r0-r12} /* Save the SVC mode regs */ + + /* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */ + + add r1, sp, #XCPTCONTEXT_SIZE + mov r2, r14 + + /* Get the values for r15(pc) and CPSR in r3 and r4 */ + + ldr r0, .Lundeftmp /* Points to temp storage */ + ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ + + add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */ + stmia r0, {r1-r4} + + /* Then call the undef insn handler with interrupt disabled. + * void up_undefinedinsn(struct xcptcontext *xcp) + */ + + mov fp, #0 /* Init frame pointer */ + mov r0, sp /* Get r0=xcp */ + bl up_undefinedinsn /* Call the handler */ + + /* Restore the CPSR, SVC modr registers and return */ + + ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ + msr spsr_cxsf, r0 + ldmia sp, {r0-r15}^ /* Return */ + +.Lundeftmp: + .word g_undeftmp + + .align 5 + +/******************************************************************** + * Name: up_vectorfiq + * + * Description: + * Shouldn't happen + ********************************************************************/ + + .globl up_vectorfiq + .type up_vectorfiq, %function +up_vectorfiq: + subs pc, lr, #4 + +/******************************************************************** + * Name: up_vectoraddrexcption + * + * Description: + * Shouldn't happen + * + ********************************************************************/ + + .globl up_vectoraddrexcptn + .type up_vectoraddrexcptn, %function +up_vectoraddrexcptn: + b up_vectoraddrexcptn + .end diff --git a/nuttx/arch/arm/src/c5471/c5471_watchdog.c b/nuttx/arch/arm/src/c5471/c5471_watchdog.c new file mode 100644 index 000000000..04b390a5c --- /dev/null +++ b/nuttx/arch/arm/src/c5471/c5471_watchdog.c @@ -0,0 +1,392 @@ +/************************************************************************** + * c5471/c5471_watchdog.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 Gregory Nutt 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 <nuttx/config.h> +#include <sys/types.h> +#include <stdio.h> +#include <debug.h> +#include <errno.h> +#include <nuttx/fs.h> +#include <nuttx/irq.h> +#include <arch/watchdog.h> +#include "up_arch.h" + +/************************************************************************** + * Definitions + **************************************************************************/ + +#undef CONFIG_SOFTWARE_TEST +#undef CONFIG_SOFTWARE_REBOOT +#undef CONFIG_WATCHDOG_STRICT + +#define MAX_WDT_USEC 353200 +#define MAX_PRESCALER 256 +#define C5471_TIMER_STOP 0 + +#define C5471_TIMER_PRESCALER 0x07 /* Bits 0-2: Prescale value */ +#define C5471_TIMER_STARTBIT (1 << 3) /* Bit 3: Start timer bit */ +#define C5471_TIMER_AUTORELOAD (1 << 4) /* Bit 4: Auto-reload timer */ +#define C5471_TIMER_LOADTIM (0xffff << 5) /* Bits 20-5: Load timer value */ +#define C5471_TIMER_MODE (1 << 21) /* Bit 21: Timer mode */ +#define C5471_DISABLE_VALUE1 (0xf5 << 22) /* Bits 29-22: WD disable */ +#define C5471_DISABLE_VALUE2 (0xa0 << 22) + +#define CLOCK_KHZ 47500 +#define CLOCK_MHZx2 95 + +/* Macros to manage access to to watchdog timer macros */ + +#define c5471_wdt_cntl (*(volatile uint32*)C5471_TIMER0_CTRL) +#define c5471_wdt_count (*(volatile uint32*)C5471_TIMER0_CNT) + +/************************************************************************** + * Private Types + **************************************************************************/ + +/************************************************************************** + * Private Function Prototypes + **************************************************************************/ + +/* Local implementation of timer interface */ + +static inline unsigned int wdt_prescaletoptv(unsigned int prescale); + +static int wdt_setusec(uint32 usec); +static int wdt_interrupt(int irq, void *context); + +static int wdt_open(struct file *filep); +static int wdt_close(struct file *filep); +static ssize_t wdt_read(struct file *filep, char *buffer, size_t buflen); +static ssize_t wdt_write(struct file *filep, const char *buffer, size_t buflen); +static int wdt_ioctl(struct file *filep, int cmd, uint32 arg); + +/************************************************************************** + * Private Data + **************************************************************************/ + +static boolean g_wdtopen; + +struct file_operations g_wdtops = +{ + .open = wdt_open, + .close = wdt_close, + .read = wdt_read, + .write = wdt_write, + .ioctl = wdt_ioctl, +}; + +/************************************************************************** + * Private Functions + **************************************************************************/ + +/************************************************************************** + * Name: wdt_prescaletoptv + **************************************************************************/ + +static inline unsigned int wdt_prescaletoptv(unsigned int prescale) +{ + unsigned int ptv = 0; + + if (prescale > 255) + { + ptv = 7; + } + else + { + unsigned int value = prescale >> 1; + + /* 0: 0-2 + * 1: 3-4 + * 2: 5-8 + * 3: 9-16 + * 4: 17-32 + * 5: 33-64 + * 6: 65-128 + * 7: 129- + */ + + while (value > 1) + { + value >>= 1; + ptv++; + } + } + + dbg("prescale=%d -> ptv=%d\n", prescale, ptv); + return ptv; +} + +/************************************************************************** + * Name: wdt_setusec + **************************************************************************/ + +static int wdt_setusec(uint32 usec) +{ + /* prescaler: clock / prescaler = #clock ticks per counter in ptv + * divisor: #counts until the interrupt comes. + */ + + uint32 prescaler = MAX_PRESCALER; + uint32 divisor = 1; + uint32 mode; + + dbg("usec=%d\n", usec); + + /* Calculate a value of prescaler and divisor that will be able + * to count to the usec. It may not be exact or the best + * possible set, but it's a quick and simple algorithm. + * + * divisor max = 0x10000 + * prescaler max = MAX_PRESCALER + */ + + do + { + divisor = (CLOCK_MHZx2 * usec) / (prescaler * 2); + dbg("divisor=0x%x prescaler=0x%x\n", divisor, prescaler); + + if (divisor >= 0x10000) + { + if (prescaler == MAX_PRESCALER) + { + /* This is the max possible ~2.5 seconds. */ + + dbg("prescaler=0x%x too big!\n", prescaler); + return ERROR; + } + + prescaler <<= 1; + if (prescaler > MAX_PRESCALER) + { + prescaler = MAX_PRESCALER; + } + } + } + while (divisor >= 0x10000); + + dbg("prescaler=0x%x divisor=0x%x\n", prescaler, divisor); + + mode = wdt_prescaletoptv(prescaler); + mode &= ~C5471_TIMER_AUTORELOAD; /* One shot mode. */ + mode |= divisor << 5; + dbg("mode=0x%x\n", mode); + + c5471_wdt_cntl = mode; + + /* Now start the watchdog */ + + c5471_wdt_cntl |= C5471_TIMER_STARTBIT; + dbg("cntl_timer=0x%x\n", c5471_wdt_cntl); + + return 0; +} + +/************************************************************************** + * Private Functions + **************************************************************************/ + +/************************************************************************** + * Name: wdt_interrupt + **************************************************************************/ + +static int wdt_interrupt(int irq, void *context) +{ + dbg("expired\n"); + +#if defined(CONFIG_SOFTWARE_REBOOT) +# if defined(CONFIG_SOFTWARE_TEST) + dbg(" Test only\n"); +# else + dbg(" Re-booting\n"); +# warning "Add logic to reset CPU here" +# endif +#else + dbg(" No reboot\n"); +#endif + return OK; +} + +/************************************************************************** + * Name: wdt_read + **************************************************************************/ + +static ssize_t wdt_read(struct file *filep, char *buffer, size_t buflen) +{ + /* We are going to return "NNNNNNNN NNNNNNNN." The followig logic will + * not work if the user provides a buffer smaller than 18 bytes. + */ + + dbg("buflen=%d\n", buflen); + if (buflen >= 18) + { + sprintf(buffer, "#08x %08x\n", c5471_wdt_cntl, c5471_wdt_count); + return 18; + } + return 0; +} + +/************************************************************************** + * Name: wdt_write + **************************************************************************/ + +static ssize_t wdt_write(struct file *filep, const char *buffer, size_t buflen) +{ + dbg("buflen=%d\n", buflen); + if (buflen) + { + /* Reset the timer to the maximum delay */ + + wdt_setusec(MAX_WDT_USEC); + return 1; + } + + return 0; +} + +/************************************************************************** + * Name: wdt_ioctl + **************************************************************************/ + +static int wdt_ioctl(struct file *filep, int cmd, uint32 arg) +{ + dbg("ioctl Call: cmd=0x%x arg=0x%x", cmd, arg); + + /* Process the the IOCTL command (see arch/watchdog.h) */ + + switch(cmd) + { + case WDIOC_KEEPALIVE: + wdt_setusec(MAX_WDT_USEC); + break; + + default: + *get_errno_ptr() = ENOTTY; + return ERROR; + } + + return OK; +} + +/************************************************************************** + * Name: wdt_open + **************************************************************************/ + +static int wdt_open(struct file *filep) +{ + dbg(""); + + if (g_wdtopen) + { + *get_errno_ptr() = EBUSY; + } + + /* This will automatically load the timer with its max + * count and start it running. + */ + + c5471_wdt_cntl = C5471_DISABLE_VALUE1; + c5471_wdt_cntl = C5471_DISABLE_VALUE2; + + g_wdtopen = TRUE; + return OK; +} + +/************************************************************************** + * Name: wdt_close + **************************************************************************/ + +static int wdt_close(struct file *filep) +{ + dbg(""); + + /* The task controlling the watchdog has terminated. Take the timer + * the + * watchdog in interrupt mode -- we are going to reset unless the + * reopened again soon. + */ + +#ifndef CONFIG_WATCHDOG_STRICT + c5471_wdt_cntl = C5471_TIMER_MODE; +#endif + + g_wdtopen = FALSE; + return 0; +} + +/************************************************************************** + * Public Functions + **************************************************************************/ + +/************************************************************************** + * Name: up_wdtinit + **************************************************************************/ + +int up_wdtinit(void) +{ + int ret; + + dbg("C547x Watchdog Driver\n"); + + /* Register as /dev/wdt */ + + ret = register_inode("/dev/wdt", &g_wdtops, 0666, NULL); + if (ret) + { + return ERROR; + } + + /* Register for an interrupt level callback through wdt_interrupt */ + + dbg("Attach to IRQ=%d\n", C5471_IRQ_WATCHDOG); + + /* Make sure that the timer is stopped */ + + c5471_wdt_cntl = C5471_TIMER_STOP; + + /* Request the interrupt. */ + + ret = irq_attach(C5471_IRQ_WATCHDOG, wdt_interrupt); + if (ret) + { + unregister_inode("/dev/wdt"); + return ERROR; + } + + return OK; +} diff --git a/nuttx/arch/arm/src/c5471/chip.h b/nuttx/arch/arm/src/c5471/chip.h new file mode 100644 index 000000000..74ff3c509 --- /dev/null +++ b/nuttx/arch/arm/src/c5471/chip.h @@ -0,0 +1,323 @@ +/************************************************************ + * c5471/chip.h + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 Gregory Nutt 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. + * + ************************************************************/ + +#ifndef __C5471_CHIP_H +#define __C5471_CHIP_H + +/************************************************************ + * Included Files + ************************************************************/ + +/************************************************************ + * Definitions + ************************************************************/ + +/* UARTs ****************************************************/ + +#define UART_IRDA_BASE 0xffff0800 +#define UART_MODEM_BASE 0xffff1000 +#define UARTn_IO_RANGE 0x00000800 + +/* Common UART Registers. Expressed as offsets from the BASE address */ + +#define UART_RHR_OFFS 0x00000000 /* Rcv Holding Register */ +#define UART_THR_OFFS 0x00000004 /* Xmit Holding Register */ +#define UART_FCR_OFFS 0x00000008 /* FIFO Control Register */ +#define UART_RFCR_OFFS 0x00000008 /* Rcv FIFO Control Register */ +#define UART_TFCR_OFFS 0x00000008 /* Xmit FIFO Control Register */ +#define UART_SCR_OFFS 0x0000000c /* Status Control Register */ +#define UART_LCR_OFFS 0x00000010 /* Line Control Register */ +#define UART_LSR_OFFS 0x00000014 /* Line Status Register */ +#define UART_SSR_OFFS 0x00000018 /* Supplementary Status Register */ +#define UART_MCR_OFFS 0x0000001c /* Modem Control Register */ +#define UART_MSR_OFFS 0x00000020 /* Modem Status Register */ +#define UART_IER_OFFS 0x00000024 /* Interrupt Enable Register */ +#define UART_ISR_OFFS 0x00000028 /* Interrupt Status Register */ +#define UART_EFR_OFFS 0x0000002c /* Enhanced Feature Register */ +#define UART_XON1_OFFS 0x00000030 /* XON1 Character Register */ +#define UART_XON2_OFFS 0x00000034 /* XON2 Character Register */ +#define UART_XOFF1_OFFS 0x00000038 /* XOFF1 Character Register */ +#define UART_XOFF2_OFFS 0x0000003c /* XOFF2 Character Register */ +#define UART_SPR_OFFS 0x00000040 /* Scratch-pad Register */ +#define UART_DIV_115K_OFFS 0x00000044 /* Divisor for baud generation */ +#define UART_DIV_BIT_RATE_OFFS 0x00000048 /* For baud rate generation */ +#define UART_TCR_OFFS 0x0000004c /* Transmission Control Register */ +#define UART_TLR_OFFS 0x00000050 /* Trigger Level Register */ +#define UART_MDR_OFFS 0x00000054 /* Mode Definition Register */ + +/* Registers available only for the IrDA UART (absolute address). */ + +#define UART_IRDA_MDR1 0xffff0854 /* Mode Definition Register 1 */ +#define UART_IRDA_MDR2 0xffff0858 /* Mode Definition Register 2 */ +#define UART_IRDA_TXFLL 0xffff085c /* LS Xmit Frame Length Register */ +#define UART_IRDA_TXFLH 0xffff0860 /* MS Xmit Frame Length Register */ +#define UART_IRDA_RXFLL 0xffff0864 /* LS Rcvd Frame Length Register */ +#define UART_IRDA_RXFLH 0xffff0868 /* MS Rcvd Frame Length Register */ +#define UART_IRDA_SFLSR 0xffff086c /* Status FIFO Line Status Reg */ +#define UART_IRDA_SFREGL 0xffff0870 /* LS Status FIFO Register */ +#define UART_IRDA_SFREGH 0xffff0874 /* MS Status FIFO Register */ +#define UART_IRDA_BLR 0xffff0878 /* Begin of File Length Register */ +#define UART_IRDA_PULSE_WIDTH 0xffff087c /* Pulse Width Register */ +#define UART_IRDA_ACREG 0xffff0880 /* Auxiliary Control Register */ +#define UART_IRDA_PULSE_START 0xffff0884 /* Start time of pulse */ +#define UART_IRDA_RX_W_PTR 0xffff0888 /* RX FIFO write pointer */ +#define UART_IRDA_RX_R_PTR 0xffff088c /* RX FIFO read pointer */ +#define UART_IRDA_TX_W_PTR 0xffff0890 /* TX FIFO write pointer */ +#define UART_IRDA_TX_R_PTR 0xffff0894 /* TX FIFO read pointer */ +#define UART_IRDA_STATUS_W_PTR 0xffff0898 /* Write pointer of status FIFO */ +#define UART_IRDA_STATUS_R_PTR 0xffff089c /* Read pointer of status FIFO */ +#define UART_IRDA_RESUME 0xffff08a0 /* Resume register */ +#define UART_IRDA_MUX 0xffff08a4 /* Selects UART_IRDA output mux */ + +/* Registers available for the Modem UART (absolute addresses) */ + +#define UART_MODEM_MDR 0xffff1054 /* Mode Definition Register */ +#define UART_MODEM_UASR 0xffff1058 /* UART Auto-baud Status Register */ +#define UART_MODEM_RDPTR_URX 0xffff105c /* RX FIFO Read Pointer Register */ +#define UART_MODEM_WRPTR_URX 0xffff1060 /* RX FIFO Write Pointer Register */ +#define UART_MODEM_RDPTR_UTX 0xffff1064 /* TX FIFO Read Pointer Register */ +#define UART_MODEM_WRPTR_UTX 0xffff1068 /* TX FIFO Write Pointer Register */ + +/* UART Settings ********************************************/ + +/* Miscellaneous UART settings. */ + +#define UART_RX_FIFO_NOEMPTY 0x00000001 +#define UART_SSR_TXFULL 0x00000001 +#define UART_LSR_TREF 0x00000020 + +#define UART_XMIT_FIFO_SIZE 64 +#define UART_IRDA_XMIT_FIFO_SIZE 64 + +/* UART_LCR Register */ + /* Bits 31-7: Reserved */ +#define UART_LCR_BOC 0x00000040 /* Bit 6: Break Control */ + /* Bit 5: Parity Type 2 */ +#define UART_LCR_PAREVEN 0x00000010 /* Bit 4: Parity Type 1 */ +#define UART_LCR_PARODD 0x00000000 +#define UART_LCR_PAREN 0x00000008 /* Bit 3: Paity Enable */ +#define UART_LCR_PARDIS 0x00000000 +#define UART_LCR_2STOP 0x00000004 /* Bit 2: Number of stop bits */ +#define UART_LCR_1STOP 0x00000000 +#define UART_LCR_5BITS 0x00000000 /* Bits 0-1: Word-length */ +#define UART_LCR_6BITS 0x00000001 +#define UART_LCR_7BITS 0x00000002 +#define UART_LCR_8BITS 0x00000003 + +#define UART_FCR_FTL 0x00000000 +#define UART_FCR_FIFO_EN 0x00000001 +#define UART_FCR_TX_CLR 0x00000002 +#define UART_FCR_RX_CLR 0x00000004 + +#define UART_IER_RECVINT 0x00000001 +#define UART_IER_XMITINT 0x00000002 +#define UART_IER_LINESTSINT 0x00000004 +#define UART_IER_MODEMSTSINT 0x00000008 /* IrDA UART only */ +#define UART_IER_XOFFINT 0x00000020 +#define UART_IER_RTSINT 0x00000040 /* IrDA UART only */ +#define UART_IER_CTSINT 0x00000080 /* IrDA UART only */ +#define UART_IER_INTMASK 0x000000ff + +#define BAUD_115200 0x00000001 +#define BAUD_57600 0x00000002 +#define BAUD_38400 0x00000003 +#define BAUD_19200 0x00000006 +#define BAUD_9600 0x0000000C +#define BAUD_4800 0x00000018 +#define BAUD_2400 0x00000030 +#define BAUD_1200 0x00000060 + +#define MDR_UART_MODE 0x00000000 /* Both IrDA and Modem UARTs */ +#define MDR_SIR_MODE 0x00000001 /* IrDA UART only */ +#define MDR_AUTOBAUDING_MODE 0x00000002 /* Modem UART only */ +#define MDR_RESET_MODE 0x00000007 /* Both IrDA and Modem UARTs */ + +/* SPI ******************************************************/ + +#define MAX_SPI 3 + +#define SPI_REGISTER_BASE 0xffff2000 + +/* GIO ******************************************************/ + +#define MAX_GIO (35) + +#define GIO_REGISTER_BASE 0xffff2800 + +#define GPIO_IO 0xffff2800 /* Writeable when I/O is configured + * as an output; reads value on I/O + * pin when I/O is configured as an + * input */ +#define GPIO_CIO 0xffff2804 /* GPIO configuration register */ +#define GPIO_IRQA 0xffff2808 /* In conjunction with GPIO_IRQB + * determines the behavior when GPIO + * pins configured as input IRQ */ +#define GPIO_IRQB 0xffff280c /* Determines the behavior when GPIO + * pins configured as input IRQ */ +#define GPIO_DDIO 0xffff2810 /* Delta Detect Register + * (detects changes in the I/O pins) */ +#define GPIO_EN 0xffff2814 /* Selects register for muxed GPIOs */ + +#define KGIO_REGISTER_BASE 0xffff2900 + +#define KBGPIO_IO 0xffff2900 /* Keyboard I/O bits: Writeable + * when KBGPIO is configured as an + * output; reads value on I/O pin + * when KBGPIO is configured as an + * input */ +#define KBGPIO_CIO 0xffff2904 /* KBGPIO configuration register */ +#define KBGPIO_IRQA 0xffff2908 /* In conjunction with KBGPIO_IRQB + * determines the behavior when + * KBGPIO pins configured as input + * IRQ */ +#define KBGPIO_IRQB 0xffff290c /* In conjunction with KBGPIO_IRQA + * determines the behavior when + * KBGPIO pins configured as input + * IRQ */ +#define KBGPIO_DDIO 0xffff2910 /* Delta Detect Register (detects + * changes in the KBGPIO pins) */ +#define KBGPIO_EN 0xffff2914 /* Selects register for muxed + * KBGPIOs */ + +/* Timers ***************************************************/ + +#define C5471_TIMER0_CTRL 0xffff2a00 +#define C5471_TIMER0_CNT 0xffff2a04 +#define C5471_TIMER1_CTRL 0xffff2b00 +#define C5471_TIMER1_CNT 0xffff2b04 +#define C5471_TIMER2_CTRL 0xffff2c00 + +#define C5471_TIMER2_CNT 0xffff2c04 + +/* Interrupts */ + +#define HAVE_SRC_IRQ_BIN_REG 0 + +#define INT_FIRST_IO 0xffff2d00 +#define INT_IO_RANGE 0x5C + +#define IT_REG 0xffff2d00 +#define MASK_IT_REG 0xffff2d04 +#define SRC_IRQ_REG 0xffff2d08 +#define SRC_FIQ_REG 0xffff2d0c +#define SRC_IRQ_BIN_REG 0xffff2d10 +#define INT_CTRL_REG 0xffff2d18 + +#define ILR_IRQ0_REG 0xffff2d1C /* 0-Timer 0 */ +#define ILR_IRQ1_REG 0xffff2d20 /* 1-Timer 1 */ +#define ILR_IRQ2_REG 0xffff2d24 /* 2-Timer 2 */ +#define ILR_IRQ3_REG 0xffff2d28 /* 3-GPIO0 */ +#define ILR_IRQ4_REG 0xffff2d2c /* 4-Ethernet */ +#define ILR_IRQ5_REG 0xffff2d30 /* 5-KBGPIO[7:0] */ +#define ILR_IRQ6_REG 0xffff2d34 /* 6-Uart serial */ +#define ILR_IRQ7_REG 0xffff2d38 /* 7-Uart IRDA */ +#define ILR_IRQ8_REG 0xffff2d3c /* 8-KBGPIO[15:8] */ +#define ILR_IRQ9_REG 0xffff2d40 /* 9-GPIO3 */ +#define ILR_IRQ10_REG 0xffff2d44 /* 10-GPIO2 */ +#define ILR_IRQ11_REG 0xffff2d48 /* 11-I2C */ +#define ILR_IRQ12_REG 0xffff2d4c /* 12-GPIO1 */ +#define ILR_IRQ13_REG 0xffff2d50 /* 13-SPI */ +#define ILR_IRQ14_REG 0xffff2d54 /* 14-GPIO[19:4] */ +#define ILR_IRQ15_REG 0xffff2d58 /* 15-API */ + +/* I2C ******************************************************/ + +#define MAX_I2C 1 + +/* API ******************************************************/ + +#define DSPRAM_BASE 0xffe00000 /* DSPRAM base address */ +#define DSPRAM_END 0xffe03fff + +/* This is the API address range in the DSP address space. */ + +#define DSPMEM_DSP_START 0x2000 +#define DSPMEM_DSP_END 0x3fff + +/* This is the API address range in the ARM address space. */ + +#define DSPMEM_ARM_START DSPRAM_BASE /* Defined in hardware.h */ +#define DSPMEM_ARM_END DSPRAM_END + +/* DSPMEM_IN_RANGE is a generic macro to test is a value is within + * a range of values. + */ + +#define DSPMEM_IN_RANGE(addr, start, end) \ + ((((__u32)(addr)) >= (start)) && (((__u32)(addr)) <= (end))) + +/* DSPMEM_ADDR_ALIGNED verifies that a potential DSP address is + * properly word aligned. + */ + +#define DSPMEM_ADDR_ALIGNED(addr, cpu) ((((__u32)(addr)) & 1) == 0) + +/* DSPMEM_DSP_ADDR checks if a DSP address lies in within the + * DSP's API address range. + */ + +#define DSPMEM_DSP_ADDR(addr, cpu) \ + DSPMEM_IN_RANGE(addr, DSPMEM_DSP_START, DSPMEM_DSP_END) + +/* DSPMEM_ARM_ADDR checks if a ARM address lies in within the + * ARM's API address range. + */ + +#define DSPMEM_ARM_ADDR(addr) \ + DSPMEM_IN_RANGE(addr, DSPMEM_ARM_START, DSPMEM_ARM_END) + +/* DSPMEM_DSP_TO_ARM maps a DSP API address into an ARM API address */ + +#define DSPMEM_DSP_TO_ARM(addr, cpu) \ + ((((__u32)(addr) - DSPMEM_DSP_START) << 1) + DSPMEM_ARM_START) + +/* DSPMEM_ARM_TO_DSP maps an ARM API address into a DSP API address */ + +#define DSPMEM_ARM_TO_DSP(addr) \ + ((((__u32)(addr) - DSPMEM_ARM_START) >> 1) + DSPMEM_DSP_START) + +/************************************************************ + * Inline Functions + ************************************************************/ + +/************************************************************ + * Public Function Prototypes + ************************************************************/ + +#ifndef __ASSEMBLY__ +extern void c5471_doirq(int irq, uint32* regs); +#endif + +#endif /* __C5471_CHIP_H */ |