diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2b70b7b0a95..42f06bbc22a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -87,6 +87,17 @@ config ARCH_CHIP_KL ---help--- Freescale Kinetis L Architectures (ARM Cortex-M0+) +config ARCH_CHIP_LC823450 + bool "ON Semiconductor LC823450" + select ARCH_CORTEXM3 + select ARCH_HAVE_CMNVECTOR + select ARCH_HAVE_MPU + select ARCH_HAVE_HEAPCHECK + select ARCH_HAVE_MULTICPU + select ARCH_HAVE_I2CRESET + ---help--- + ON Semiconductor LC823450 architectures (ARM dual Cortex-M3) + config ARCH_CHIP_LM bool "TI/Luminary Stellaris" select ARCH_HAVE_CMNVECTOR @@ -435,6 +446,7 @@ config ARCH_CHIP default "imx6" if ARCH_CHIP_IMX6 default "kinetis" if ARCH_CHIP_KINETIS default "kl" if ARCH_CHIP_KL + default "lc823450" if ARCH_CHIP_LC823450 default "tiva" if ARCH_CHIP_LM || ARCH_CHIP_TIVA default "lpc11xx" if ARCH_CHIP_LPC11XX default "lpc17xx" if ARCH_CHIP_LPC17XX @@ -656,6 +668,9 @@ endif if ARCH_CHIP_KL source arch/arm/src/kl/Kconfig endif +if ARCH_CHIP_LC823450 +source arch/arm/src/lc823450/Kconfig +endif if ARCH_CHIP_LM || ARCH_CHIP_TIVA source arch/arm/src/tiva/Kconfig endif diff --git a/arch/arm/include/lc823450/chip.h b/arch/arm/include/lc823450/chip.h new file mode 100644 index 00000000000..8c1b62c424e --- /dev/null +++ b/arch/arm/include/lc823450/chip.h @@ -0,0 +1,121 @@ +/**************************************************************************** + * arch/arm/include/lc823450/chip.h + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * + * 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. + * + ****************************************************************************/ + + +#ifndef __ARCH_ARM_INCLUDE_LC823450_CHIP_H +#define __ARCH_ARM_INCLUDE_LC823450_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + + +/* NVIC priority levels *****************************************************/ + +#define NVIC_SYSH_PRIORITY_MIN 0xf0 /* All bits set in minimum priority */ +#define NVIC_SYSH_PRIORITY_DEFAULT 0x80 /* Midpoint is the default */ +#define NVIC_SYSH_PRIORITY_MAX 0x00 /* Zero is maximum priority */ +#define NVIC_SYSH_PRIORITY_STEP 0x10 /* Four bits of interrupt priority used */ + +/* If CONFIG_ARMV7M_USEBASEPRI is selected, then interrupts will be disabled + * by setting the BASEPRI register to NVIC_SYSH_DISABLE_PRIORITY so that most + * interrupts will not have execution priority. SVCall must have execution + * priority in all cases. + * + * In the normal cases, interrupts are not nest-able and all interrupts run + * at an execution priority between NVIC_SYSH_PRIORITY_MIN and + * NVIC_SYSH_PRIORITY_MAX (with NVIC_SYSH_PRIORITY_MAX reserved for SVCall). + * + * If, in addition, CONFIG_ARCH_HIPRI_INTERRUPT is defined, then special + * high priority interrupts are supported. These are not "nested" in the + * normal sense of the word. These high priority interrupts can interrupt + * normal processing but execute outside of OS (although they can "get back + * into the game" via a PendSV interrupt). + * + * In the normal course of things, interrupts must occasionally be disabled + * using the irqsave() inline function to prevent contention in use of + * resources that may be shared between interrupt level and non-interrupt + * level logic. Now the question arises, if CONFIG_ARCH_HIPRI_INTERRUPT, + * do we disable all interrupts (except SVCall), or do we only disable the + * "normal" interrupts. Since the high priority interrupts cannot interact + * with the OS, you may want to permit the high priority interrupts even if + * interrupts are disabled. The setting CONFIG_ARCH_INT_DISABLEALL can be + * used to select either behavior: + * + * ----------------------------+--------------+---------------------------- + * CONFIG_ARCH_HIPRI_INTERRUPT | NO | YES + * ----------------------------+--------------+--------------+------------- + * CONFIG_ARCH_INT_DISABLEALL | N/A | YES | NO + * ----------------------------+--------------+--------------+------------- + * | | | SVCall + * | SVCall | SVCall | HIGH + * Disable here and below --------> MAXNORMAL ---> HIGH --------> MAXNORMAL + * | | MAXNORMAL | + * ----------------------------+--------------+--------------+------------- + */ + +#if defined(CONFIG_ARCH_HIPRI_INTERRUPT) && defined(CONFIG_ARCH_INT_DISABLEALL) +# define NVIC_SYSH_MAXNORMAL_PRIORITY (NVIC_SYSH_PRIORITY_MAX + 2*NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_HIGH_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_HIGH_PRIORITY +# define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +#else +# define NVIC_SYSH_MAXNORMAL_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_HIGH_PRIORITY NVIC_SYSH_PRIORITY_MAX +# define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_MAXNORMAL_PRIORITY +# define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +#endif + + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#endif /* __ARCH_ARM_INCLUDE_LC823450_CHIP_H */ diff --git a/arch/arm/include/lc823450/clk.h b/arch/arm/include/lc823450/clk.h new file mode 100644 index 00000000000..91e27e743f0 --- /dev/null +++ b/arch/arm/include/lc823450/clk.h @@ -0,0 +1,94 @@ +/**************************************************************************** + * arch/arm/include/lc823450/clk.h + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_INCLUDE_LC823450_CLK_H +#define __ARCH_ARM_INCLUDE_LC823450_CLK_H + + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define LC823450_CLOCKS \ + { \ + {0, "dmac", MCLKCNTBASIC, MCLKCNTBASIC_DMAC_CLKEN}, \ + {0, "mtm0", MCLKCNTEXT1, MCLKCNTEXT1_MTM0_CLKEN}, \ + {0, "mtm0c", MCLKCNTEXT1, MCLKCNTEXT1_MTM0C_CLKEN}, \ + {0, "mtm1", MCLKCNTEXT1, MCLKCNTEXT1_MTM1_CLKEN}, \ + {0, "mtm1c", MCLKCNTEXT1, MCLKCNTEXT1_MTM1C_CLKEN}, \ + } + + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +struct clk_st +{ + int count; + char *name; + uint32_t regaddr; + uint32_t regmask; +}; + +enum clock_e +{ + LC823450_CLOCK_DMA = 0, + LC823450_CLOCK_MTM0, + LC823450_CLOCK_MTM0C, + LC823450_CLOCK_MTM1, + LC823450_CLOCK_MTM1C, + + LC823450_CLOCK_NUM, +}; + + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +void up_enable_clk(enum clock_e clk); +void up_disable_clk(enum clock_e clk); + +#endif /* __ARCH_ARM_INCLUDE_LC823450_CLK_H */ diff --git a/arch/arm/include/lc823450/irq.h b/arch/arm/include/lc823450/irq.h new file mode 100644 index 00000000000..9800946ea02 --- /dev/null +++ b/arch/arm/include/lc823450/irq.h @@ -0,0 +1,317 @@ +/**************************************************************************** + * arch/arm/include/lc823450/irq.h + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * + * 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. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, + * only indirectly through nuttx/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_LC823450_IRQ_H +#define __ARCH_ARM_INCLUDE_LC823450_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + + +/* IRQ numbers. The IRQ number corresponds vector number and hence map directly to + * bits in the NVIC. This does, however, waste several words of memory in the IRQ + * to handle mapping tables. + */ + +/* Processor Exceptions (vectors 0-15) */ + +#define LC823450_IRQ_RESERVED (0) /* Reserved vector (only used with CONFIG_DEBUG) */ + /* Vector 0: Reset stack pointer value */ + /* Vector 1: Reset (not handler as an IRQ) */ +#define LC823450_IRQ_NMI (2) /* Vector 2: Non-Maskable Interrupt (NMI) */ +#define LC823450_IRQ_HARDFAULT (3) /* Vector 3: Hard fault */ +#define LC823450_IRQ_MEMFAULT (4) /* Vector 4: Memory management (MPU) */ +#define LC823450_IRQ_BUSFAULT (5) /* Vector 5: Bus fault */ +#define LC823450_IRQ_USAGEFAULT (6) /* Vector 6: Usage fault */ +#define LC823450_IRQ_SVCALL (11) /* Vector 11: SVC call */ +#define LC823450_IRQ_DBGMONITOR (12) /* Vector 12: Debug Monitor */ + /* Vector 13: Reserved */ +#define LC823450_IRQ_PENDSV (14) /* Vector 14: Pendable system service request */ +#define LC823450_IRQ_SYSTICK (15) /* Vector 15: System tick */ + +/* External interrupts (vectors >= 16). These definitions are chip-specific */ + +#define LC823450_IRQ_INTERRUPTS (16) /* Vector number of the first external interrupt */ + + +/* IRQ numbers. The IRQ number corresponds vector number and hence map directly to + * bits in the NVIC. This does, however, waste several words of memory in the IRQ + * to handle mapping tables. + * + * Processor Exceptions (vectors 0-15). These common definitions can be found + * in nuttx/arch/arm/include/lc823450/irq.h + * + * External interrupts (vectors >= 16) + */ +#define LC823450_IRQ_CTXM3_00 (LC823450_IRQ_INTERRUPTS+0) /* 16: CortexM3_00 interrupt */ +#define LC823450_IRQ_CTXM3_01 (LC823450_IRQ_INTERRUPTS+1) /* 17: CortexM3_01 interrupt */ +#define LC823450_IRQ_CTXM3_02 (LC823450_IRQ_INTERRUPTS+2) /* 18: CortexM3_02 interrupt */ +#define LC823450_IRQ_CTXM3_03 (LC823450_IRQ_INTERRUPTS+3) /* 19: CortexM3_03 interrupt */ +#define LC823450_IRQ_CTXM3_10 (LC823450_IRQ_INTERRUPTS+4) /* 20: CortexM3_00 interrupt */ +#define LC823450_IRQ_CTXM3_11 (LC823450_IRQ_INTERRUPTS+5) /* 21: CortexM3_01 interrupt */ +#define LC823450_IRQ_CTXM3_12 (LC823450_IRQ_INTERRUPTS+6) /* 22: CortexM3_02 interrupt */ +#define LC823450_IRQ_CTXM3_13 (LC823450_IRQ_INTERRUPTS+7) /* 23: CortexM3_03 interrupt */ +#define LC823450_IRQ_LPDSP0 (LC823450_IRQ_INTERRUPTS+8) /* 24: LPDSP0 interrupt */ +#define LC823450_IRQ_LPDSP1 (LC823450_IRQ_INTERRUPTS+9) /* 25: LPDSP1 interrupt */ +#define LC823450_IRQ_LPDSP2 (LC823450_IRQ_INTERRUPTS+10) /* 26: LPDSP2 interrupt */ +#define LC823450_IRQ_LPDSP3 (LC823450_IRQ_INTERRUPTS+11) /* 27: LPDSP3 interrupt */ +#define LC823450_IRQ_WDT0 (LC823450_IRQ_INTERRUPTS+12) /* 28: WatchDogTimer0 interrupt */ +#define LC823450_IRQ_WDT1 (LC823450_IRQ_INTERRUPTS+13) /* 29: WatchDogTimer1 interrupt */ +#define LC823450_IRQ_WDT2 (LC823450_IRQ_INTERRUPTS+14) /* 30: WatchDogTimer2 interrupt */ +#define LC823450_IRQ_BTIMER0 (LC823450_IRQ_INTERRUPTS+15) /* 31: BasicTimer0 interrupt */ +#define LC823450_IRQ_BTIMER1 (LC823450_IRQ_INTERRUPTS+16) /* 32: BasicTimer0 interrupt */ +#define LC823450_IRQ_BTIMER2 (LC823450_IRQ_INTERRUPTS+17) /* 33: BasicTimer0 interrupt */ +#define LC823450_IRQ_MTIMER00 (LC823450_IRQ_INTERRUPTS+18) /* 34: MultipleTimer00 interrupt */ +#define LC823450_IRQ_MTIMER01 (LC823450_IRQ_INTERRUPTS+19) /* 35: MultipleTimer01 interrupt */ +#define LC823450_IRQ_MTIMER10 (LC823450_IRQ_INTERRUPTS+20) /* 36: MultipleTimer10 interrupt */ +#define LC823450_IRQ_MTIMER11 (LC823450_IRQ_INTERRUPTS+21) /* 37: MultipleTimer11 interrupt */ +#define LC823450_IRQ_MTIMER20 (LC823450_IRQ_INTERRUPTS+22) /* 38: MultipleTimer20 interrupt */ +#define LC823450_IRQ_MTIMER21 (LC823450_IRQ_INTERRUPTS+23) /* 39: MultipleTimer21 interrupt */ +#define LC823450_IRQ_MTIMER30 (LC823450_IRQ_INTERRUPTS+24) /* 40: MultipleTimer30 interrupt */ +#define LC823450_IRQ_MTIMER31 (LC823450_IRQ_INTERRUPTS+25) /* 41: MultipleTimer31 interrupt */ +#define LC823450_IRQ_EHCI (LC823450_IRQ_INTERRUPTS+26) /* 42: USB HOST EHCI interrupt */ +#define LC823450_IRQ_OHCI (LC823450_IRQ_INTERRUPTS+27) /* 43: USB HOST OHCI interrupt */ +#define LC823450_IRQ_SERFLASH (LC823450_IRQ_INTERRUPTS+28) /* 44: USB HOST OHCI interrupt */ +#define LC823450_IRQ_DMAC (LC823450_IRQ_INTERRUPTS+29) /* 45: DMA Controller interrupt */ +#define LC823450_IRQ_SDCSYNC0 (LC823450_IRQ_INTERRUPTS+30) /* 46: SDCardSync0 interrupt */ +#define LC823450_IRQ_SDCSYNC1 (LC823450_IRQ_INTERRUPTS+31) /* 47: SDCardSync1 interrupt */ +#define LC823450_IRQ_SDCSYNC2 (LC823450_IRQ_INTERRUPTS+32) /* 48: SDCardSync2 interrupt */ +#define LC823450_IRQ_SDCASYNC0 (LC823450_IRQ_INTERRUPTS+33) /* 49: SDCardAsync0 interrupt */ +#define LC823450_IRQ_SDCASYNC1 (LC823450_IRQ_INTERRUPTS+34) /* 50: SDCardAsync1 interrupt */ +#define LC823450_IRQ_SDCASYNC2 (LC823450_IRQ_INTERRUPTS+35) /* 51: SDCardAsync2 interrupt */ +#define LC823450_IRQ_MEMSTICK (LC823450_IRQ_INTERRUPTS+36) /* 52: MemoryStick interrupt */ +#define LC823450_IRQ_MEMSTICKINS (LC823450_IRQ_INTERRUPTS+37) /* 53: MemoryStick ins interrupt */ +#define LC823450_IRQ_DSPCMD (LC823450_IRQ_INTERRUPTS+38) /* 54: DSP cmd interface interrupt */ +#define LC823450_IRQ_ADC (LC823450_IRQ_INTERRUPTS+39) /* 55: AD Converter interrupt */ +#define LC823450_IRQ_SIO (LC823450_IRQ_INTERRUPTS+40) /* 56: SIO interrupt */ +#define LC823450_IRQ_I2C0 (LC823450_IRQ_INTERRUPTS+41) /* 57: I2C0 interrupt */ +#define LC823450_IRQ_I2C1 (LC823450_IRQ_INTERRUPTS+42) /* 58: I2C1 interrupt */ +#define LC823450_IRQ_UART0 (LC823450_IRQ_INTERRUPTS+43) /* 59: UART0 interrupt */ +#define LC823450_IRQ_UART1 (LC823450_IRQ_INTERRUPTS+44) /* 60: UART1 interrupt */ +#define LC823450_IRQ_UART2 (LC823450_IRQ_INTERRUPTS+45) /* 61: UART2 interrupt */ +#define LC823450_IRQ_RTC (LC823450_IRQ_INTERRUPTS+46) /* 62: RTC interrupt */ +#define LC823450_IRQ_RTCKEY (LC823450_IRQ_INTERRUPTS+47) /* 63: RTCKEY interrupt */ +#define LC823450_IRQ_AUDIOBUF0 (LC823450_IRQ_INTERRUPTS+48) /* 64: AudioBuffer0 interrupt */ +#define LC823450_IRQ_AUDIOBUF1 (LC823450_IRQ_INTERRUPTS+49) /* 65: AudioBuffer1 interrupt */ +#define LC823450_IRQ_AUDIOBUF2 (LC823450_IRQ_INTERRUPTS+50) /* 66: AudioBuffer2 interrupt */ +#define LC823450_IRQ_AUDIOBUF3 (LC823450_IRQ_INTERRUPTS+51) /* 67: AudioBuffer3 interrupt */ +#define LC823450_IRQ_AUDIOSTAT0 (LC823450_IRQ_INTERRUPTS+52) /* 68: AudioStatus0 interrupt */ +#define LC823450_IRQ_AUDIOSTAT1 (LC823450_IRQ_INTERRUPTS+53) /* 69: AudioStatus1 interrupt */ +#define LC823450_IRQ_AUDIOSTAT2 (LC823450_IRQ_INTERRUPTS+54) /* 70: AudioStatus2 interrupt */ +#define LC823450_IRQ_AUDIOSTAT3 (LC823450_IRQ_INTERRUPTS+55) /* 71: AudioStatus3 interrupt */ +#define LC823450_IRQ_AUDIOTM0 (LC823450_IRQ_INTERRUPTS+56) /* 72: AudioTimer0 interrupt */ +#define LC823450_IRQ_AUDIOTM1 (LC823450_IRQ_INTERRUPTS+57) /* 73: AudioTimer1 interrupt */ +#define LC823450_IRQ_USBDEV (LC823450_IRQ_INTERRUPTS+58) /* 74: USB Device interrupt */ +#define LC823450_IRQ_EXTINT0 (LC823450_IRQ_INTERRUPTS+59) /* 75: ExternalINT0 interrupt */ +#define LC823450_IRQ_EXTINT1 (LC823450_IRQ_INTERRUPTS+60) /* 76: ExternalINT1 interrupt */ +#define LC823450_IRQ_EXTINT2 (LC823450_IRQ_INTERRUPTS+61) /* 77: ExternalINT2 interrupt */ +#define LC823450_IRQ_EXTINT3 (LC823450_IRQ_INTERRUPTS+62) /* 78: ExternalINT3 interrupt */ +#define LC823450_IRQ_EXTINT4 (LC823450_IRQ_INTERRUPTS+63) /* 79: ExternalINT4 interrupt */ +#define LC823450_IRQ_EXTINT5 (LC823450_IRQ_INTERRUPTS+64) /* 80: ExternalINT5 interrupt */ + +#define LC823450_IRQ_NIRQS (LC823450_IRQ_EXTINT5 + 1) + +#define LC823450_IRQ_GPIO00 (LC823450_IRQ_NIRQS + 0) /* 81: GPIO00 */ +#define LC823450_IRQ_GPIO01 (LC823450_IRQ_NIRQS + 1) /* 82: GPIO01 */ +#define LC823450_IRQ_GPIO02 (LC823450_IRQ_NIRQS + 2) /* 83: GPIO02 */ +#define LC823450_IRQ_GPIO03 (LC823450_IRQ_NIRQS + 3) /* 84: GPIO03 */ +#define LC823450_IRQ_GPIO04 (LC823450_IRQ_NIRQS + 4) /* 85: GPIO04 */ +#define LC823450_IRQ_GPIO05 (LC823450_IRQ_NIRQS + 5) /* 86: GPIO05 */ +#define LC823450_IRQ_GPIO06 (LC823450_IRQ_NIRQS + 6) /* 87: GPIO06 */ +#define LC823450_IRQ_GPIO07 (LC823450_IRQ_NIRQS + 7) /* 88: GPIO07 */ +#define LC823450_IRQ_GPIO08 (LC823450_IRQ_NIRQS + 8) /* 89: GPIO08 */ +#define LC823450_IRQ_GPIO09 (LC823450_IRQ_NIRQS + 9) /* 90: GPIO09 */ +#define LC823450_IRQ_GPIO0A (LC823450_IRQ_NIRQS + 10) /* 91: GPIO0A */ +#define LC823450_IRQ_GPIO0B (LC823450_IRQ_NIRQS + 11) /* 92: GPIO0B */ +#define LC823450_IRQ_GPIO0C (LC823450_IRQ_NIRQS + 12) /* 93: GPIO0C */ +#define LC823450_IRQ_GPIO0D (LC823450_IRQ_NIRQS + 13) /* 94: GPIO0D */ +#define LC823450_IRQ_GPIO0E (LC823450_IRQ_NIRQS + 14) /* 95: GPIO0E */ +#define LC823450_IRQ_GPIO0F (LC823450_IRQ_NIRQS + 15) /* 96: GPIO0F */ +#define LC823450_IRQ_GPIO10 (LC823450_IRQ_NIRQS + 16) /* 97: GPIO10 */ +#define LC823450_IRQ_GPIO11 (LC823450_IRQ_NIRQS + 17) /* 98: GPIO11 */ +#define LC823450_IRQ_GPIO12 (LC823450_IRQ_NIRQS + 18) /* 99: GPIO12 */ +#define LC823450_IRQ_GPIO13 (LC823450_IRQ_NIRQS + 19) /* 100: GPIO13 */ +#define LC823450_IRQ_GPIO14 (LC823450_IRQ_NIRQS + 20) /* 101: GPIO14 */ +#define LC823450_IRQ_GPIO15 (LC823450_IRQ_NIRQS + 21) /* 102: GPIO15 */ +#define LC823450_IRQ_GPIO16 (LC823450_IRQ_NIRQS + 22) /* 103: GPIO16 */ +#define LC823450_IRQ_GPIO17 (LC823450_IRQ_NIRQS + 23) /* 104: GPIO17 */ +#define LC823450_IRQ_GPIO18 (LC823450_IRQ_NIRQS + 24) /* 105: GPIO18 */ +#define LC823450_IRQ_GPIO19 (LC823450_IRQ_NIRQS + 25) /* 106: GPIO19 */ +#define LC823450_IRQ_GPIO1A (LC823450_IRQ_NIRQS + 26) /* 107: GPIO1A */ +#define LC823450_IRQ_GPIO1B (LC823450_IRQ_NIRQS + 27) /* 108: GPIO1B */ +#define LC823450_IRQ_GPIO1C (LC823450_IRQ_NIRQS + 28) /* 109: GPIO1C */ +#define LC823450_IRQ_GPIO1D (LC823450_IRQ_NIRQS + 29) /* 110: GPIO1D */ +#define LC823450_IRQ_GPIO1E (LC823450_IRQ_NIRQS + 30) /* 111: GPIO1E */ +#define LC823450_IRQ_GPIO1F (LC823450_IRQ_NIRQS + 31) /* 112: GPIO1F */ +#define LC823450_IRQ_GPIO20 (LC823450_IRQ_NIRQS + 32) /* 113: GPIO20 */ +#define LC823450_IRQ_GPIO21 (LC823450_IRQ_NIRQS + 33) /* 114: GPIO21 */ +#define LC823450_IRQ_GPIO22 (LC823450_IRQ_NIRQS + 34) /* 115: GPIO22 */ +#define LC823450_IRQ_GPIO23 (LC823450_IRQ_NIRQS + 35) /* 116: GPIO23 */ +#define LC823450_IRQ_GPIO24 (LC823450_IRQ_NIRQS + 36) /* 117: GPIO24 */ +#define LC823450_IRQ_GPIO25 (LC823450_IRQ_NIRQS + 37) /* 118: GPIO25 */ +#define LC823450_IRQ_GPIO26 (LC823450_IRQ_NIRQS + 38) /* 119: GPIO26 */ +#define LC823450_IRQ_GPIO27 (LC823450_IRQ_NIRQS + 39) /* 120: GPIO27 */ +#define LC823450_IRQ_GPIO28 (LC823450_IRQ_NIRQS + 40) /* 121: GPIO28 */ +#define LC823450_IRQ_GPIO29 (LC823450_IRQ_NIRQS + 41) /* 122: GPIO29 */ +#define LC823450_IRQ_GPIO2A (LC823450_IRQ_NIRQS + 42) /* 123: GPIO2A */ +#define LC823450_IRQ_GPIO2B (LC823450_IRQ_NIRQS + 43) /* 124: GPIO2B */ +#define LC823450_IRQ_GPIO2C (LC823450_IRQ_NIRQS + 44) /* 125: GPIO2C */ +#define LC823450_IRQ_GPIO2D (LC823450_IRQ_NIRQS + 45) /* 126: GPIO2D */ +#define LC823450_IRQ_GPIO2E (LC823450_IRQ_NIRQS + 46) /* 127: GPIO2E */ +#define LC823450_IRQ_GPIO2F (LC823450_IRQ_NIRQS + 47) /* 128: GPIO2F */ +#define LC823450_IRQ_GPIO30 (LC823450_IRQ_NIRQS + 48) /* 129: GPIO30 */ +#define LC823450_IRQ_GPIO31 (LC823450_IRQ_NIRQS + 49) /* 130: GPIO31 */ +#define LC823450_IRQ_GPIO32 (LC823450_IRQ_NIRQS + 50) /* 131: GPIO32 */ +#define LC823450_IRQ_GPIO33 (LC823450_IRQ_NIRQS + 51) /* 132: GPIO33 */ +#define LC823450_IRQ_GPIO34 (LC823450_IRQ_NIRQS + 52) /* 133: GPIO34 */ +#define LC823450_IRQ_GPIO35 (LC823450_IRQ_NIRQS + 53) /* 134: GPIO35 */ +#define LC823450_IRQ_GPIO36 (LC823450_IRQ_NIRQS + 54) /* 135: GPIO36 */ +#define LC823450_IRQ_GPIO37 (LC823450_IRQ_NIRQS + 55) /* 136: GPIO37 */ +#define LC823450_IRQ_GPIO38 (LC823450_IRQ_NIRQS + 56) /* 137: GPIO38 */ +#define LC823450_IRQ_GPIO39 (LC823450_IRQ_NIRQS + 57) /* 138: GPIO39 */ +#define LC823450_IRQ_GPIO3A (LC823450_IRQ_NIRQS + 58) /* 139: GPIO3A */ +#define LC823450_IRQ_GPIO3B (LC823450_IRQ_NIRQS + 59) /* 140: GPIO3B */ +#define LC823450_IRQ_GPIO3C (LC823450_IRQ_NIRQS + 60) /* 141: GPIO3C */ +#define LC823450_IRQ_GPIO3D (LC823450_IRQ_NIRQS + 61) /* 142: GPIO3D */ +#define LC823450_IRQ_GPIO3E (LC823450_IRQ_NIRQS + 62) /* 143: GPIO3E */ +#define LC823450_IRQ_GPIO3F (LC823450_IRQ_NIRQS + 63) /* 144: GPIO3F */ +#define LC823450_IRQ_GPIO40 (LC823450_IRQ_NIRQS + 64) /* 145: GPIO40 */ +#define LC823450_IRQ_GPIO41 (LC823450_IRQ_NIRQS + 65) /* 146: GPIO41 */ +#define LC823450_IRQ_GPIO42 (LC823450_IRQ_NIRQS + 66) /* 147: GPIO42 */ +#define LC823450_IRQ_GPIO43 (LC823450_IRQ_NIRQS + 67) /* 148: GPIO43 */ +#define LC823450_IRQ_GPIO44 (LC823450_IRQ_NIRQS + 68) /* 149: GPIO44 */ +#define LC823450_IRQ_GPIO45 (LC823450_IRQ_NIRQS + 69) /* 150: GPIO45 */ +#define LC823450_IRQ_GPIO46 (LC823450_IRQ_NIRQS + 70) /* 151: GPIO46 */ +#define LC823450_IRQ_GPIO47 (LC823450_IRQ_NIRQS + 71) /* 152: GPIO47 */ +#define LC823450_IRQ_GPIO48 (LC823450_IRQ_NIRQS + 72) /* 153: GPIO48 */ +#define LC823450_IRQ_GPIO49 (LC823450_IRQ_NIRQS + 73) /* 154: GPIO49 */ +#define LC823450_IRQ_GPIO4A (LC823450_IRQ_NIRQS + 74) /* 155: GPIO4A */ +#define LC823450_IRQ_GPIO4B (LC823450_IRQ_NIRQS + 75) /* 156: GPIO4B */ +#define LC823450_IRQ_GPIO4C (LC823450_IRQ_NIRQS + 76) /* 157: GPIO4C */ +#define LC823450_IRQ_GPIO4D (LC823450_IRQ_NIRQS + 77) /* 158: GPIO4D */ +#define LC823450_IRQ_GPIO4E (LC823450_IRQ_NIRQS + 78) /* 159: GPIO4E */ +#define LC823450_IRQ_GPIO4F (LC823450_IRQ_NIRQS + 79) /* 160: GPIO4F */ +#define LC823450_IRQ_GPIO50 (LC823450_IRQ_NIRQS + 80) /* 161: GPIO50 */ +#define LC823450_IRQ_GPIO51 (LC823450_IRQ_NIRQS + 81) /* 162: GPIO51 */ +#define LC823450_IRQ_GPIO52 (LC823450_IRQ_NIRQS + 82) /* 163: GPIO52 */ +#define LC823450_IRQ_GPIO53 (LC823450_IRQ_NIRQS + 83) /* 164: GPIO53 */ +#define LC823450_IRQ_GPIO54 (LC823450_IRQ_NIRQS + 84) /* 165: GPIO54 */ +#define LC823450_IRQ_GPIO55 (LC823450_IRQ_NIRQS + 85) /* 166: GPIO55 */ +#define LC823450_IRQ_GPIO56 (LC823450_IRQ_NIRQS + 86) /* 167: GPIO56 */ +#define LC823450_IRQ_GPIO57 (LC823450_IRQ_NIRQS + 87) /* 168: GPIO57 */ +#define LC823450_IRQ_GPIO58 (LC823450_IRQ_NIRQS + 88) /* 169: GPIO58 */ +#define LC823450_IRQ_GPIO59 (LC823450_IRQ_NIRQS + 89) /* 170: GPIO59 */ + +#define LC823450_IRQ_NGPIOIRQS (90) + +#ifdef CONFIG_LC823450_VIRQ +#define LC823450_IRQ_VIRTUAL (LC823450_IRQ_NIRQS + LC823450_IRQ_NGPIOIRQS) +#define LC823450_IRQ_V00 (LC823450_IRQ_VIRTUAL + 0) /* 171: V00 */ +#define LC823450_IRQ_NVIRTUALIRQS (1) +#else /* CONFIG_LC823450_VIRQ */ +#define LC823450_IRQ_NVIRTUALIRQS (0) +#endif /* CONFIG_LC823450_VIRQ */ + +#define NR_VECTORS (LC823450_IRQ_NIRQS) +#define NR_IRQS (LC823450_IRQ_NIRQS + LC823450_IRQ_NGPIOIRQS + LC823450_IRQ_NVIRTUALIRQS) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +enum lc823450_srctype_e +{ + SRCTYPE_FALLING = 0, /* Falling edge */ + SRCTYPE_LOW, /* Low level */ + SRCTYPE_RISING, /* Rigsing edge */ + SRCTYPE_HIGH, /* High level */ + SRCTYPE_MAX, +}; +#ifdef CONFIG_LC823450_VIRQ +struct lc823450_irq_ops { + void (*enable)(int irq); + void (*disable)(int irq); + int (*srctype)(int irq, enum lc823450_srctype_e type); +}; +#endif /* CONFIG_LC823450_VIRQ */ + +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +EXTERN int lc823450_irq_srctype(int irq, enum lc823450_srctype_e srctype); +#ifdef CONFIG_LC823450_VIRQ +EXTERN int lc823450_irq_register(int irq, struct lc823450_irq_ops *ops); +#endif /* CONFIG_LC823450_VIRQ */ + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_ARM_INCLUDE_LC823450_IRQ_H */ diff --git a/arch/arm/src/lc823450/Kconfig b/arch/arm/src/lc823450/Kconfig new file mode 100644 index 00000000000..f390acc7dd2 --- /dev/null +++ b/arch/arm/src/lc823450/Kconfig @@ -0,0 +1,174 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +comment "LC823450 Configuration Options" + +menu "LC823450 Peripheral Support" + +config SERIAL_TERMIOS + bool "Serial driver TERMIOS supported" + default n + ---help--- + Serial driver supports termios.h interfaces (tcsetattr, tcflush, etc.). + If this is not defined, then the terminal settings (baud, parity, etc). + are not configurable at runtime; serial streams cannot be flushed, etc.. + +config LC823450_UART0 + bool "UART0" + select UART0_SERIALDRIVER + default n + +config LC823450_UART1 + bool "UART1" + select UART1_SERIALDRIVER + default n + +config LC823450_UART2 + bool "UART2" + select UART2_SERIALDRIVER + default n + +config LC823450_WDT + bool "Watchdog" + default n + select WATCHDOG + +config LC823450_SPIFI + bool "SPI Flash Interface (SPIFI)" + default n + depends on MTD + +if LC823450_SPIFI + +config LC823450_SPIFI_DEVNO + int "number in /dev/mtdblk?" + default 0 + +config LC823450_SPIFI_SIZE + int "SPI FLASH size (byte)" + default 4194304 + +config LC823450_SPIFI_QUADIO + bool "SPIFI 4bit access" + default n + +config LC823450_SPIFI_RAMFAT + bool "SPIFI with SRAM FAT" + default n + +config LC823450_SPIFI_RAMFAT_VOLUMELABEL + string "volume label for SRAM FAT" + depends on LC823450_SPIFI_RAMFAT + +config LC823450_SPIFI_BACKUP + bool "power dwon tolerance I/O" + default n + +config LC823450_SPIFI_BACKUP_HEAD_OFFSET + hex "backup header offset" + depends on LC823450_SPIFI_BACKUP + +config LC823450_SPIFI_BACKUP_VAL_OFFSET + hex "backup area offset" + depends on LC823450_SPIFI_BACKUP + +endif + +config LC823450_SDIF + bool "SD/eMMC driver" + default y + +if LC823450_SDIF + +config LC823450_SDIF_SDC + bool "SD card support" + default n + +config LC823450_SDC_DMA + bool "DMA support for eMMC/SD" + default y + select ARCH_DMA + +endif + +config LC823450_I2C_TIMEOSEC + int "I2C timeout (sec)" + default 1 + range 0 2 + depends on I2C + +config LC823450_I2C_TIMEOMS + int "I2C timeout (msec)" + default 500 + range 0 999 + depends on I2C + +config LC823450_I2C0 + bool "I2C0" + default n + depends on I2C + +config LC823450_I2C1 + bool "I2C1" + default n + depends on I2C + +config LC823450_SPI_DMA + bool "DMA for SPI" + default n + select ARCH_DMA + +if PWM + +config LC823450_PWM0_CH0 + bool "MTM0-Ch0 PWM device" + default n + +config LC823450_PWM0_CH1 + bool "MTM0-Ch1 PWM device" + default n + +config LC823450_PWM1_CH0 + bool "MTM1-Ch0 PWM device" + default y + +config LC823450_PWM1_CH1 + bool "MTM1-Ch1 PWM device" + default n + +endif + +choice + prompt "HS driver current boost" + +config LC823450_USBDEV_CUSTOM_HSDSEL_0 + bool "normal" + +config LC823450_USBDEV_CUSTOM_HSDSEL_5 + bool "5% boost" + +config LC823450_USBDEV_CUSTOM_HSDSEL_10 + bool "10% boost" + +endchoice + +config LC823450_LSISTBY + bool "LIS Standby" + default n + +config LC823450_MTM0_TICK + bool "use MTM0 for tick" + default n + +config LC823450_SLEEP_MODE + bool "sleep mode" + default n + + +config HRT_TIMER + bool "High resolution timer" + default n + +endmenu diff --git a/arch/arm/src/lc823450/Make.defs b/arch/arm/src/lc823450/Make.defs new file mode 100644 index 00000000000..6c921736108 --- /dev/null +++ b/arch/arm/src/lc823450/Make.defs @@ -0,0 +1,179 @@ +############################################################################ +# arch/arm/src/lc823450/Make.defs +# +# Copyright (C) 2014-2017 Sony Corporation. All rights reserved. +# Author: Masatoshi Tateishi +# Author: Masayuki Ishikawa +# Author: Yasuhiro Osaki +# +# 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. +# +############################################################################ + +ifeq ($(CONFIG_ARMV7M_CMNVECTOR),y) +HEAD_ASRC = +else +HEAD_ASRC = lc823450_vectors.S +endif + +CMN_UASRCS = +CMN_UCSRCS = + +CMN_ASRCS = up_saveusercontext.S up_fullcontextrestore.S up_switchcontext.S +CMN_ASRCS += vfork.S + + +CMN_CSRCS = up_assert.c up_blocktask.c up_copyfullstate.c +CMN_CSRCS += up_createstack.c up_mdelay.c up_udelay.c up_exit.c +CMN_CSRCS += up_initialize.c up_initialstate.c up_interruptcontext.c +CMN_CSRCS += up_memfault.c up_modifyreg8.c up_modifyreg16.c up_modifyreg32.c +CMN_CSRCS += up_releasepending.c up_releasestack.c up_reprioritizertr.c +CMN_CSRCS += up_schedulesigaction.c up_sigdeliver.c up_systemreset.c +CMN_CSRCS += up_unblocktask.c up_usestack.c up_doirq.c up_hardfault.c +CMN_CSRCS += up_svcall.c up_vfork.c +CMN_CSRCS += up_allocateheap.c + +# CMN_CSRCS += up_dwt.c + +CMN_CSRCS += up_stackframe.c +ifeq ($(CONFIG_ARMV7M_CMNVECTOR),y) +CMN_ASRCS += up_exception.S +CMN_CSRCS += up_vectors.c +endif + +ifeq ($(CONFIG_ARCH_RAMVECTORS),y) +CMN_CSRCS += up_ramvec_initialize.c up_ramvec_attach.c +endif + +ifeq ($(CONFIG_ARCH_MEMCPY),y) +CMN_ASRCS += memcpy-armv7m.S +endif + +ifeq ($(CONFIG_ARCH_MEMMOVE),y) +CMN_CSRCS += up_memmove.c +endif + +ifeq ($(CONFIG_DEBUG_STACK),y) +CMN_CSRCS += up_checkstack.c +endif + +CHIP_ASRCS = + +CHIP_CSRCS = lc823450_start.c lc823450_irq.c lc823450_idle.c +CHIP_CSRCS += lc823450_timerisr.c lc823450_lowputc.c +CHIP_CSRCS += lc823450_serial.c lc823450_clockconfig.c lc823450_syscontrol.c +CHIP_CSRCS += lc823450_gpio.c + +ifeq ($(CONFIG_WATCHDOG),y) +CHIP_CSRCS += lc823450_wdt.c +endif + +ifeq ($(CONFIG_LC823450_SPIFI), y) +CHIP_CSRCS += lc823450_spifi.c +endif + +ifeq ($(CONFIG_LC823450_SDIF), y) +CHIP_CSRCS += lc823450_sdc.c +CHIP_CSRCS += lc823450_sddrv_dep.c +endif + +ifeq ($(CONFIG_PWM), y) +CHIP_CSRCS += lc823450_pwm.c +endif + +ifeq ($(CONFIG_I2C), y) +CHIP_CSRCS += lc823450_i2c.c +endif + +ifeq ($(CONFIG_SPI), y) +CHIP_CSRCS += lc823450_spi.c +endif + +ifeq ($(CONFIG_ARMV7M_MPU),y) +CMN_CSRCS += up_mpu.c lc823450_mpuinit.c +endif + +ifeq ($(CONFIG_ARCH_DMA), y) +CMN_CSRCS += lc823450_dma.c +endif + +ifeq ($(CONFIG_RTC),y) +CHIP_CSRCS += lc823450_rtc.c +endif + +ifeq ($(CONFIG_FS_EVFAT),y) +CHIP_CSRCS += lc823450_evfat.c +endif + +ifeq ($(CONFIG_USBDEV),y) +CHIP_CSRCS += lc823450_usbdev.c +endif + +ifeq ($(CONFIG_ADC),y) +CHIP_CSRCS += lc823450_adc.c +endif + +ifeq ($(CONFIG_IPL2),y) +ifeq ($(CONFIG_SPIFLASH_BOOT),y) +CHIP_CSRCS += lc823450_spif_ipl2.c +else +CHIP_CSRCS += lc823450_ipl2.c +endif +endif + +ifeq ($(CONFIG_DVFS),y) +CHIP_CSRCS += lc823450_dvfs.c +endif + +ifeq ($(CONFIG_PM),y) +CHIP_CSRCS += lc823450_pminitialize.c +CHIP_CSRCS += lc823450_sleep.c +endif + +#CHIP_CSRCS += lc823450_allocateheap.c + +ifeq ($(CONFIG_MM_MULTIHEAP), y) +CHIP_CSRCS += lc823450_mm.c +CHIP_CSRCS += lc823450_sram.c +endif + +ifeq ($(CONFIG_LC823450_SPIFI_RAMFAT), y) +CHIP_CSRCS += lc823450_ramfat.c +endif + +ifeq ($(CONFIG_SMP), y) +CHIP_CSRCS += lc823450_cpuidlestack.c +CHIP_CSRCS += lc823450_cpuindex.c +CHIP_CSRCS += lc823450_cpupause.c +CHIP_CSRCS += lc823450_cpustart.c +CHIP_CSRCS += lc823450_testset.c +endif + +ifeq ($(CONFIG_LC823450_SDRAM), y) +CHIP_CSRCS += lc823450_sdram.c +endif diff --git a/arch/arm/src/lc823450/chip.h b/arch/arm/src/lc823450/chip.h new file mode 100644 index 00000000000..7a59858bd98 --- /dev/null +++ b/arch/arm/src/lc823450/chip.h @@ -0,0 +1,86 @@ +/**************************************************************************** + * arch/arm/src/lc823450/chip.h + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * + * 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. + * + ****************************************************************************/ + +#ifndef _ARCH_ARM_SRC_LC823450_CHIP_H +#define _ARCH_ARM_SRC_LC823450_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + + +#if defined(__cplusplus) +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* _ARCH_ARM_SRC_LC823450_CHIP_H */ diff --git a/arch/arm/src/lc823450/lc823450_clockconfig.c b/arch/arm/src/lc823450/lc823450_clockconfig.c new file mode 100644 index 00000000000..5b90a26f567 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_clockconfig.c @@ -0,0 +1,238 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_clockconfig.c + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * Author: Nobutaka Toyoshima + * + * 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 "up_arch.h" +#include "lc823450_clockconfig.h" +#include "lc823450_syscontrol.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_MAX_CPU_CLOCK_150 +# define SYSCLK 150 /* MHz */ +#else +# define SYSCLK 160 /* MHz */ +#endif + +#ifdef CONFIG_AHB_CLOCK_IS_CPU_CLOCK +# define HCLKDIV 0 /* AHB = system / (HCLKIDV + 1) */ +#else +# define HCLKDIV 3 /* AHB = system / (HCLKIDV + 1) */ +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +unsigned int XT1OSC_CLK; + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lc823450_get_systemfreq + ****************************************************************************/ + +uint32_t lc823450_get_systemfreq(void) +{ + return SYSCLK * 1000000; +} + +/**************************************************************************** + * Name: lc823450_get_apb + ****************************************************************************/ + +#ifndef CONFIG_DVFS +uint32_t lc823450_get_apb(void) +{ + return SYSCLK * 1000000; +} +#endif + +/**************************************************************************** + * Name: lc823450_get_ahb + ****************************************************************************/ + +uint32_t lc823450_get_ahb(void) +{ + return (SYSCLK * 1000000) / (HCLKDIV + 1); +} + +/**************************************************************************** + * Name: lc823450_clockconfig + ****************************************************************************/ + +void lc823450_clockconfig() +{ + uint32_t val; + + val = getreg32(BMODE_DT) & BMODE_DT_XTALINFO_MASK; + + if (val == BMODE_DT_XTALINFO_20) + { + XT1OSC_CLK = (20 * 1000 * 1000); + } + else + { + XT1OSC_CLK = (24 * 1000 * 1000); + } + + /* XT1 enable */ + + modifyreg32(OSCCNT, 0, OSCCNT_XT1EN); + + /* Clear MAINDIV */ + + modifyreg32(OSCCNT, OSCCNT_MAINDIV_MASK, 0); + + /* Select system clock source from MAIN(XT1) */ + + val = getreg32(OSCCNT); + val &= ~OSCCNT_SCKSEL_MASK; + val |= OSCCNT_SCKSEL_MAIN; + putreg32(val, OSCCNT); + +#ifdef CONFIG_IPL2 + /* set the common PLL values */ + /* XTAL / XT1OSC_CLK = 1MHz */ + + putreg32((XT1OSC_CLK / 1000000) - 1, PLL1MDIV); + + /* 1MHz * SYSCLK = system clock */ + + putreg32(SYSCLK * 2 - 1, PLL1NDIV); +#else + if (SYSCLK == 150 && XT1OSC_CLK == 24000000) + { + putreg32(0x01, PLL1MDIV); + putreg32(0x18, PLL1NDIV); + } + else if (SYSCLK == 160 && XT1OSC_CLK == 24000000) + { + putreg32(0x02, PLL1MDIV); + putreg32(0x27, PLL1NDIV); + } + else if (SYSCLK == 160 && XT1OSC_CLK == 20000000) + { + putreg32(0x00, PLL1MDIV); + putreg32(0x0f, PLL1NDIV); + } + else + { + ASSERT(false); + } +#endif + + /* enable PLL */ + + val = getreg32(PLL1CNT); + val |= PLL1CNT_STYB; + val |= PLL1CNT_RSTB; + putreg32(val, PLL1CNT); + + /* wait for lock */ + + up_udelay(10000); + +#if 0 + /* To check basic clock by PHI pin. + * Don't forget to change GPIO09 pinmux. + */ + val = getreg32(FCLKCNT); + val |= (1 << 26); + putreg32(val, FCLKCNT); +#endif + + /* S-Flash fclock = sysclk / 4 */ + + val = getreg32(FCLKCNT); + val |= FCLKCNT_SFDIV4; + putreg32(val, FCLKCNT); + + /* set AHB with HCLKDIV */ + + modifyreg32(PERICLKDIV, + PERICLKDIV_HCLKDIV_MASK, + HCLKDIV); + + /* EXT4 = sysclk / 3 (53.3MHz=18.8n) */ + + val = getreg32(PERICLKDIV); + val |= (3 - 1) << 16; + putreg32(val, PERICLKDIV); + + /* MAIN clock source = PLL */ + + val = getreg32(OSCCNT); + val |= OSCCNT_MCSEL; + putreg32(val, OSCCNT); + + /* Set ROM wait cycle (DSP=1wait, CPU=1wait) */ + + modifyreg32(MEMEN4, 0, MEMEN4_DWAIT | MEMEN4_HWAIT); + + /* Select system clock source from MAIN(PLL) */ + + val = getreg32(OSCCNT); + val &= ~OSCCNT_SCKSEL_MASK; + val |= OSCCNT_SCKSEL_MAIN; + putreg32(val, OSCCNT); +} diff --git a/arch/arm/src/lc823450/lc823450_clockconfig.h b/arch/arm/src/lc823450/lc823450_clockconfig.h new file mode 100644 index 00000000000..1010197303a --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_clockconfig.h @@ -0,0 +1,124 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_clockconfig.h + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * Author: Nobutaka Toyoshima + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_LC823450_LC823450_CLOCKCONFIG_H +#define __ARCH_ARM_SRC_LC823450_LC823450_CLOCKCONFIG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + + +#define LC823450_OSCSYS_REGBASE 0x40040000 + +#define OSCCNT (LC823450_OSCSYS_REGBASE + 0x00) +#define OSCCNT_SCKSEL_MASK (3 << 0) +#define OSCCNT_SCKSEL_RC (0 << 0) +#define OSCCNT_SCKSEL_MAIN (1 << 0) +#define OSCCNT_SCKSEL_RTC (2 << 0) +#define OSCCNT_MCSEL (1 << 2) +#define OSCCNT_XT1EN (1 << 7) +#define OSCCNT_MAINDIV_MASK (7 << 8) +#define OSCCNT_MAINDIV_1 (0 << 8) +#define OSCCNT_MAINDIV_2 (1 << 8) +#define OSCCNT_MAINDIV_4 (2 << 8) +#define OSCCNT_MAINDIV_8 (3 << 8) +#define OSCCNT_MAINDIV_16 (4 << 8) +#define PLLREFCNT (LC823450_OSCSYS_REGBASE + 0x04) +#define PERICLKDIV (LC823450_OSCSYS_REGBASE + 0x08) +#define PERICLKDIV_HCLKDIV_MASK (0x3f << 0) +#define FCLKCNT (LC823450_OSCSYS_REGBASE + 0x0c) +#define FCLKCNT_SFDIV1 (0 << 24) +#define FCLKCNT_SFDIV2 (1 << 24) +#define FCLKCNT_SFDIV4 (2 << 24) +#define FCLKCNT_SFDIV8 (3 << 24) +#define AUDCLKCNT (LC823450_OSCSYS_REGBASE + 0x14) +#define IMCNT (LC823450_OSCSYS_REGBASE + 0x20) +#define CORESTS (LC823450_OSCSYS_REGBASE + 0x40) + +#define LC823450_SYSTEMPLL_BASE 0x40041000 +#define PLL1CNT (LC823450_SYSTEMPLL_BASE + 0x00) +#define PLL1CNT_STYB (1 << 1) +#define PLL1CNT_RSTB (1 << 0) +#define PLL1MDIV (LC823450_SYSTEMPLL_BASE + 0x04) +#define PLL1NDIV (LC823450_SYSTEMPLL_BASE + 0x08) + + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +EXTERN uint32_t lc823450_get_systemfreq(void); + +#ifndef CONFIG_DVFS +EXTERN uint32_t lc823450_get_apb(void); +#endif + +EXTERN uint32_t lc823450_get_ahb(void); +EXTERN void lc823450_clockconfig(void); + + +#if defined(__cplusplus) +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_LC823450_LC823450_CLOCKCONFIG_H */ diff --git a/arch/arm/src/lc823450/lc823450_cpuidlestack.c b/arch/arm/src/lc823450/lc823450_cpuidlestack.c new file mode 100644 index 00000000000..6f2f6b171ee --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_cpuidlestack.c @@ -0,0 +1,118 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_cpuidlestack.c + * + * Copyright (C) 2016-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * + * 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 "up_arch.h" + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + + + +/**************************************************************************** + * Name: up_cpu_idlestack + * + * Description: + * Allocate a stack for the CPU[n] IDLE task (n > 0) if appropriate and + * setup up stack-related information in the IDLE task's TCB. This + * function is always called before up_cpu_start(). This function is + * only called for the CPU's initial IDLE task; up_create_task is used for + * all normal tasks, pthreads, and kernel threads for all CPUs. + * + * The initial IDLE task is a special case because the CPUs can be started + * in different wans in different environments: + * + * 1. The CPU may already have been started and waiting in a low power + * state for up_cpu_start(). In this case, the IDLE thread's stack + * has already been allocated and is already in use. Here + * up_cpu_idlestack() only has to provide information about the + * already allocated stack. + * + * 2. The CPU may be disabled but started when up_cpu_start() is called. + * In this case, a new stack will need to be created for the IDLE + * thread and this function is then equivalent to: + * + * return up_create_stack(tcb, stack_size, TCB_FLAG_TTYPE_KERNEL); + * + * The following TCB fields must be initialized by this function: + * + * - adj_stack_size: Stack size after adjustment for hardware, processor, + * etc. This value is retained only for debug purposes. + * - stack_alloc_ptr: Pointer to allocated stack + * - adj_stack_ptr: Adjusted stack_alloc_ptr for HW. The initial value of + * the stack pointer. + * + * Inputs: + * - cpu: CPU index that indicates which CPU the IDLE task is + * being created for. + * - tcb: The TCB of new CPU IDLE task + * - stack_size: The requested stack size for the IDLE task. At least + * this much must be allocated. This should be + * CONFIG_SMP_STACK_SIZE. + * + ****************************************************************************/ + +int up_cpu_idlestack(int cpu, FAR struct tcb_s *tcb, size_t stack_size) +{ +#if CONFIG_SMP_NCPUS > 1 + (void)up_create_stack(tcb, stack_size, TCB_FLAG_TTYPE_KERNEL); +#endif + return OK; +} diff --git a/arch/arm/src/lc823450/lc823450_cpuindex.c b/arch/arm/src/lc823450/lc823450_cpuindex.c new file mode 100644 index 00000000000..c85ddc7ee54 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_cpuindex.c @@ -0,0 +1,90 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_cpuindex.c + * + * Copyright (C) 2016-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * + * 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 "up_arch.h" + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define LC823450_CORE_BASE 0xe00fe000 +#define CORE_COREID (LC823450_CORE_BASE + 0x0) +#define CORE_COREID_ID (0x1 << 0) + + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + + +/**************************************************************************** + * Name: up_cpu_index + * + * Description: + * Return an index in the range of 0 through (CONFIG_SMP_NCPUS-1) that + * corresponds to the currently executing CPU. + * + * Input Parameters: + * None + * + * Returned Value: + * An integer index in the range of 0 through (CONFIG_SMP_NCPUS-1) that + * corresponds to the currently executing CPU. + * + ****************************************************************************/ + +int up_cpu_index(void) +{ + return getreg32(CORE_COREID) & CORE_COREID_ID; +} diff --git a/arch/arm/src/lc823450/lc823450_cpupause.c b/arch/arm/src/lc823450/lc823450_cpupause.c new file mode 100644 index 00000000000..2c21102f9d1 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_cpupause.c @@ -0,0 +1,364 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_cpupause.c + * + * Copyright (C) 2016-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * + * 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 "up_arch.h" +#include "sched/sched.h" +#include "up_internal.h" +#include "lc823450_intc.h" + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + + +#if 0 +#define DPRINTF(fmt, args...) llinfo(fmt, ##args) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* These spinlocks are used in the SMP configuration in order to implement + * up_cpu_pause(). The protocol for CPUn to pause CPUm is as follows + * + * 1. The up_cpu_pause() implementation on CPUn locks both g_cpu_wait[m] + * and g_cpu_paused[m]. CPUn then waits spinning on g_cpu_paused[m]. + * 2. CPUm receives the interrupt it (1) unlocks g_cpu_paused[m] and + * (2) locks g_cpu_wait[m]. The first unblocks CPUn and the second + * blocks CPUm in the interrupt handler. + * + * When CPUm resumes, CPUn unlocks g_cpu_wait[m] and the interrupt handler + * on CPUm continues. CPUm must, of course, also then unlock g_cpu_wait[m] + * so that it will be ready for the next pause operation. + */ + +volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS]; +volatile spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS]; + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + + + +/**************************************************************************** + * Name: up_cpu_pausereq + * + * Description: + * Return true if a pause request is pending for this CPU. + * + * Input Parameters: + * cpu - The index of the CPU to be queried + * + * Returned Value: + * true = a pause request is pending. + * false = no pasue request is pending. + * + ****************************************************************************/ + +bool up_cpu_pausereq(int cpu) +{ + return spin_islocked(&g_cpu_paused[cpu]); +} + +/**************************************************************************** + * Name: up_cpu_paused + * + * Description: + * Handle a pause request from another CPU. Normally, this logic is + * executed from interrupt handling logic within the architecture-specific + * However, it is sometimes necessary necessary to perform the pending + * pause operation in other contexts where the interrupt cannot be taken + * in order to avoid deadlocks. + * + * This function performs the following operations: + * + * 1. It saves the current task state at the head of the current assigned + * task list. + * 2. It waits on a spinlock, then + * 3. Returns from interrupt, restoring the state of the new task at the + * head of the ready to run list. + * + * Input Parameters: + * cpu - The index of the CPU to be paused + * + * Returned Value: + * On success, OK is returned. Otherwise, a negated errno value indicating + * the nature of the failure is returned. + * + ****************************************************************************/ + +int up_cpu_paused(int cpu) +{ + FAR struct tcb_s *tcb = this_task(); + + /* Update scheduler parameters */ + + sched_suspend_scheduler(tcb); + +#ifdef CONFIG_SCHED_INSTRUMENTATION + /* Notify that we are paused */ + + sched_note_cpu_paused(tcb); +#endif + + /* Save the current context at CURRENT_REGS into the TCB at the head + * of the assigned task list for this CPU. + */ + + up_savestate(tcb->xcp.regs); + + /* Wait for the spinlock to be released */ + + spin_unlock(&g_cpu_paused[cpu]); + spin_lock(&g_cpu_wait[cpu]); + + /* Restore the exception context of the tcb at the (new) head of the + * assigned task list. + */ + + tcb = this_task(); + +#ifdef CONFIG_SCHED_INSTRUMENTATION + /* Notify that we have resumed */ + + sched_note_cpu_resumed(tcb); +#endif + + /* Reset scheduler parameters */ + + sched_resume_scheduler(tcb); + + /* Then switch contexts. Any necessary address environment changes + * will be made when the interrupt returns. + */ + + up_restorestate(tcb->xcp.regs); + + /* FIXME */ + up_udelay(500); + + spin_unlock(&g_cpu_wait[cpu]); + + return OK; +} + + +/**************************************************************************** + * Name: lc823450_pause_handler + * + * Description: + * Inter-CPU interrupt handler + * + * Input Parameters: + * Standard interrupt handler inputs + * + * Returned Value: + * Should always return OK + * + ****************************************************************************/ + +int lc823450_pause_handler(int irq, void *c, FAR void *arg) +{ + int cpu = up_cpu_index(); + + /* Clear : Pause IRQ */ + if (irq == LC823450_IRQ_CTXM3_01) + { + DPRINTF("CPU0 -> CPU1\n"); + putreg32(IPICLR_INTISR0_CLR_1, IPICLR); + } + else + { + DPRINTF("CPU1 -> CPU0\n"); + putreg32(IPICLR_INTISR1_CLR_1, IPICLR); + } + + /* Check for false alarms. Such false could occur as a consequence of + * some deadlock breaking logic that might have already serviced the SG2 + * interrupt by calling up_cpu_paused. + */ + + if (spin_islocked(&g_cpu_paused[cpu])) + { + return up_cpu_paused(cpu); + } + + return OK; +} + + +/**************************************************************************** + * Name: up_cpu_pause + * + * Description: + * Save the state of the current task at the head of the + * g_assignedtasks[cpu] task list and then pause task execution on the + * CPU. + * + * This function is called by the OS when the logic executing on one CPU + * needs to modify the state of the g_assignedtasks[cpu] list for another + * CPU. + * + * Input Parameters: + * cpu - The index of the CPU to be stopped/ + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +int up_cpu_pause(int cpu) +{ + DPRINTF("cpu=%d\n", cpu); + +#ifdef CONFIG_SCHED_INSTRUMENTATION + /* Notify of the pause event */ + + sched_note_cpu_pause(this_task(), cpu); +#endif + + DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu()); + + /* Take the both spinlocks. The g_cpu_wait spinlock will prevent the SGI2 + * handler from returning until up_cpu_resume() is called; g_cpu_paused + * is a handshake that will prefent this function from returning until + * the CPU is actually paused. + */ + + DEBUGASSERT(!spin_islocked(&g_cpu_wait[cpu]) && + !spin_islocked(&g_cpu_paused[cpu])); + + spin_lock(&g_cpu_wait[cpu]); + spin_lock(&g_cpu_paused[cpu]); + + /* Execute Pause IRQ to CPU(cpu) */ + + if (cpu == 1) + { + putreg32(IPIREG_INTISR0_1, IPIREG); + } + else + { + putreg32(IPIREG_INTISR1_1, IPIREG); + } + + /* Wait for the other CPU to unlock g_cpu_paused meaning that + * it is fully paused and ready for up_cpu_resume(); + */ + + spin_lock(&g_cpu_paused[cpu]); + + spin_unlock(&g_cpu_paused[cpu]); + + /* On successful return g_cpu_wait will be locked, the other CPU will be + * spinninf on g_cpu_wait and will not continue until g_cpu_resume() is + * called. g_cpu_paused will be unlocked in any case. + */ + + return 0; +} + +/**************************************************************************** + * Name: up_cpu_resume + * + * Description: + * Restart the cpu after it was paused via up_cpu_pause(), restoring the + * state of the task at the head of the g_assignedtasks[cpu] list, and + * resume normal tasking. + * + * This function is called after up_cpu_pause in order resume operation of + * the CPU after modifying its g_assignedtasks[cpu] list. + * + * Input Parameters: + * cpu - The index of the CPU being re-started. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +int up_cpu_resume(int cpu) +{ + DPRINTF("cpu=%d\n", cpu); + +#ifdef CONFIG_SCHED_INSTRUMENTATION + /* Notify of the resume event */ + + sched_note_cpu_resume(this_task(), cpu); +#endif + + DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu()); + + /* Release the spinlock. Releasing the spinlock will cause the SGI2 + * handler on 'cpu' to continue and return from interrupt to the newly + * established thread. + */ + + DEBUGASSERT(spin_islocked(&g_cpu_wait[cpu]) && + !spin_islocked(&g_cpu_paused[cpu])); + + spin_unlock(&g_cpu_wait[cpu]); + + return 0; +} diff --git a/arch/arm/src/lc823450/lc823450_cpustart.c b/arch/arm/src/lc823450/lc823450_cpustart.c new file mode 100644 index 00000000000..2b1d9f9bbe5 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_cpustart.c @@ -0,0 +1,229 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_cpustart.c + * + * Copyright (C) 2016-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * + * 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. + * + ****************************************************************************/ + +#pragma GCC optimize ("O0") + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "up_arch.h" +#include "nvic.h" +#include "sched/sched.h" +#include "init/init.h" +#include "up_internal.h" + +#include "lc823450_syscontrol.h" + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + + +#if 0 +#define DPRINTF(fmt, args...) llinfo(fmt, ##args) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +#define CPU1_VECTOR_RESETV 0x00000000 +#define CPU1_VECTOR_ISTACK 0x00000004 + + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static uint32_t cpu1_vector_table[]; + + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS]; + + + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +extern int lc823450_pause_handler(int irq, void *c, FAR void *arg); + + +/**************************************************************************** + * Name: cpu1_boot + * + * Description: + * This is the boot vector for Cortex-M3 #1 + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + + +static void cpu1_boot(void) +{ + int cpu = up_cpu_index(); + + DPRINTF("cpu = %d\n", cpu); + + if (cpu == 1) + { + putreg32((uint32_t)&_stext, NVIC_VECTAB); /* use CPU0 vectors */ + + irq_attach(LC823450_IRQ_CTXM3_01, lc823450_pause_handler, NULL); + up_enable_irq(LC823450_IRQ_CTXM3_01); + } + + spin_unlock(&g_cpu_wait[0]); + +#ifdef CONFIG_SCHED_INSTRUMENTATION + /* Notify that this CPU has started */ + + sched_note_cpu_started(this_task()); +#endif + + /* Then transfer control to the IDLE task */ + + (void)os_idle_task(0, NULL); + +} + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + + +/**************************************************************************** + * Name: up_cpu_start + * + * Description: + * In an SMP configution, only one CPU is initially active (CPU 0). System + * initialization occurs on that single thread. At the completion of the + * initialization of the OS, just before beginning normal multitasking, + * the additional CPUs would be started by calling this function. + * + * Each CPU is provided the entry point to is IDLE task when started. A + * TCB for each CPU's IDLE task has been initialized and placed in the + * CPU's g_assignedtasks[cpu] list. Not stack has been alloced or + * initialized. + * + * The OS initialization logic calls this function repeatedly until each + * CPU has been started, 1 through (CONFIG_SMP_NCPUS-1). + * + * Input Parameters: + * cpu - The index of the CPU being started. This will be a numeric + * value in the range of from one to (CONFIG_SMP_NCPUS-1). (CPU + * 0 is already active) + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +int up_cpu_start(int cpu) +{ + struct tcb_s *tcb = current_task(cpu); + uint32_t backup[2]; + + DPRINTF("cpu=%d\n", cpu); + + if (cpu != 1) + { + return -1; + } + + /* create initial vectors for CPU1 */ + + putreg32(0x1, REMAP); /* remap enable */ + backup[0] = getreg32(CPU1_VECTOR_RESETV); + backup[1] = getreg32(CPU1_VECTOR_ISTACK); + putreg32((uint32_t)tcb->adj_stack_ptr, CPU1_VECTOR_RESETV); + putreg32((uint32_t)cpu1_boot, CPU1_VECTOR_ISTACK); + + spin_lock(&g_cpu_wait[0]); + +#ifdef CONFIG_SCHED_INSTRUMENTATION + /* Notify of the start event */ + + sched_note_cpu_start(this_task(), cpu); +#endif + + /* enable clock core #1 */ + + modifyreg32(CORECNT, 0, CORECNT_C1CLKEN); + + /* unreset core #1 */ + + modifyreg32(CORECNT, 0, CORECNT_C1RSTN); + + /* IRQ setup CPU1->CPU0 */ + + irq_attach(LC823450_IRQ_CTXM3_11, lc823450_pause_handler, NULL); + up_enable_irq(LC823450_IRQ_CTXM3_11); + + spin_lock(&g_cpu_wait[0]); + + /* CPU1 boot done */ + + /* restore : after CPU1 boot, CPU1 use normal vectors table. */ + + putreg32(backup[0], CPU1_VECTOR_RESETV); + putreg32(backup[1], CPU1_VECTOR_ISTACK); + putreg32(0x0, REMAP); /* remap disable */ + + spin_unlock(&g_cpu_wait[0]); + + return 0; +} diff --git a/arch/arm/src/lc823450/lc823450_dma.c b/arch/arm/src/lc823450/lc823450_dma.c new file mode 100644 index 00000000000..9d03e9e74a3 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_dma.c @@ -0,0 +1,659 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_dma.c + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * + * 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 "up_arch.h" +#include "lc823450_dma.h" +#include "lc823450_syscontrol.h" +#include + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define DMACBASE 0x40004000 +#define DMACINTSTAT (DMACBASE + 0x00) +#define DMACINTTCSTAT (DMACBASE + 0x04) +#define DMACINTTCCLR (DMACBASE + 0x08) +#define DMACINTERRSTAT (DMACBASE + 0x10) +#define DMACCHENABLE (DMACBASE + 0x1c) +#define DMACINTERRCLR (DMACBASE + 0x08) +#define DMACCONFIG (DMACBASE + 0x30) +#define DMACCONFIG_EN (1 << 0) +#define DMACSRCADDR(ch) (DMACBASE + ((ch) * 0x20) + 0x100) +#define DMACDSTADDR(ch) (DMACBASE + ((ch) * 0x20) + 0x104) +#define DMACLLI(ch) (DMACBASE + ((ch) * 0x20) + 0x108) +#define DMACCTL(ch) (DMACBASE + ((ch) * 0x20) + 0x10c) +#define DMACCTL_INT (1 << 31) +#define DMACCFG(ch) (DMACBASE + ((ch) * 0x20) + 0x110) +#define DMACCFG_H (1 << 18) +#define DMACCFG_ACT (1 << 17) +#define DMACCFG_ITC (1 << 15) +#define DMACCFG_FLOWCTRL_MASK (7 << 11) +#define DMACCFG_FLOWCTRL_M2M_DMA (0 << 11) +#define DMACCFG_FLOWCTRL_M2P_DMA (1 << 11) +#define DMACCFG_FLOWCTRL_P2M_DMA (2 << 11) +#define DMACCFG_FLOWCTRL_M2P_PER (5 << 11) +#define DMACCFG_FLOWCTRL_P2M_PER (6 << 11) +#define DMACCFG_DSTPERI_SHIFT 6 +#define DMACCFG_SRCPERI_SHIFT 1 +#define DMACCFG_E (1 << 0) + +#ifndef MIN +# define MIN(a, b) ((a) > (b) ? (b) : (a)) +#endif /* MIN */ + +#define LC823450_DMA_EN (1 << 26) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct lc823450_phydmach_s +{ + sq_queue_t req_q; /* DMA Request queue */ + bool inprogress; /* True: DMA is in progress on this channel */ +}; + +struct lc823450_dmach_s +{ + sq_entry_t q_ent; + uint8_t chn; + struct lc823450_phydmach_s *phych; + dma_callback_t callback; /* DMA completion callback function */ + void *arg; /* Argument to pass to the callback function */ + uint32_t srcaddr; + uint32_t destaddr; + uint32_t ctrl; + size_t nxfrs; + uint32_t llist; +}; + + +struct lc823450_dma_s +{ + sem_t exclsem; /* For exclusive access to the DMA channel list */ + + /* This is the state of each DMA channel */ + int count; + struct lc823450_phydmach_s phydmach[DMA_CHANNEL_NUM]; + uint32_t reqline_use; +}; + +static int phydmastart(struct lc823450_phydmach_s *pdmach); + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct lc823450_dma_s g_dma; +volatile uint8_t g_dma_inprogress; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: dma_interrupt_core + ****************************************************************************/ + +static int dma_interrupt_core(void *context) +{ + struct lc823450_phydmach_s *pdmach; + struct lc823450_dmach_s *dmach; + sq_entry_t *q_ent; + + pdmach = (struct lc823450_phydmach_s *)context; + + q_ent = pdmach->req_q.tail; + DEBUGASSERT(q_ent); + dmach = (struct lc823450_dmach_s *)q_ent; + + if (dmach->nxfrs == 0) + { + /* finish one transfer */ + sq_remlast(&pdmach->req_q); + + if (dmach->callback) + dmach->callback((DMA_HANDLE)dmach, dmach->arg, 0); + } + up_disable_clk(LC823450_CLOCK_DMA); + phydmastart(pdmach); + + return OK; +} + +/**************************************************************************** + * Name: dma_interrupt + ****************************************************************************/ + +static int dma_interrupt(int irq, FAR void *context, FAR void *arg) +{ + int i; + uint32_t stat, err; + + up_enable_clk(LC823450_CLOCK_DMA); + + stat = getreg32(DMACINTTCSTAT); + err = getreg32(DMACINTERRSTAT); + + putreg32(stat, DMACINTTCCLR); + putreg32(err, DMACINTERRCLR); + + for (i = 0; i < DMA_CHANNEL_NUM; i++) + { + if (stat & (1 << i)) + { + dma_interrupt_core((void *)&g_dma.phydmach[i]); + } + if (err & (1 << i)) + { + _err("ERR %d\n", i); + } + } + + up_disable_clk(LC823450_CLOCK_DMA); + + return OK; +} + +/**************************************************************************** + * Name: phydmastart + ****************************************************************************/ + +static int phydmastart(struct lc823450_phydmach_s *pdmach) +{ + irqstate_t flags; + int trnum; + + struct lc823450_dmach_s *dmach; + sq_entry_t *q_ent; + + flags = enter_critical_section(); + + q_ent = pdmach->req_q.tail; + + if (!q_ent) + { + pdmach->inprogress = 0; + leave_critical_section(flags); + return 0; + } + dmach = (struct lc823450_dmach_s *)q_ent; + + trnum = MIN(dmach->nxfrs, LC823450_DMA_MAX_TRANSSIZE); + + pdmach->inprogress = 1; + up_enable_clk(LC823450_CLOCK_DMA); + /* start DMA */ + putreg32(dmach->srcaddr, DMACSRCADDR(dmach->chn)); + putreg32(dmach->destaddr, DMACDSTADDR(dmach->chn)); + + putreg32(dmach->ctrl | (dmach->llist ? 0 : LC823450_DMA_ITC) | trnum, + DMACCTL(dmach->chn)); + putreg32(dmach->llist, DMACLLI(dmach->chn)); + + dmach->nxfrs -= trnum; + + if (dmach->nxfrs) + { + if (dmach->ctrl & LC823450_DMA_SRCINC) + { + if (dmach->ctrl & LC823450_DMA_SRCWIDTH_WORD) + { + dmach->srcaddr += trnum * 4; + } + else if (dmach->ctrl & LC823450_DMA_SRCWIDTH_HWORD) + { + dmach->srcaddr += trnum * 2; + } + else + { + dmach->srcaddr += trnum; + } + } + + if (dmach->ctrl & LC823450_DMA_DSTINC) + { + if (dmach->ctrl & LC823450_DMA_DSTWIDTH_WORD) + { + dmach->destaddr += trnum * 4; + } + else if (dmach->ctrl & LC823450_DMA_DSTWIDTH_HWORD) + { + dmach->destaddr += trnum * 2; + } + else + { + dmach->destaddr += trnum; + } + } + } + + while (getreg32(DMACCHENABLE) & (1 << dmach->chn)); + + while (getreg32(DMACCFG(dmach->chn)) & (DMACCFG_E | DMACCFG_ACT)); + + modifyreg32(DMACCFG(dmach->chn), 0, DMACCFG_ITC | DMACCFG_E); + + leave_critical_section(flags); + return 0; +} + + +#ifdef DMA_TEST +int test_buf1[4096]; +int test_buf2[4096]; +static volatile int test_done; + +static void dma_done(DMA_HANDLE handle, void *arg, int result) +{ + int i; + for (i = 0; i < 256; i++) + llinfo("test_buf2[%d] = %d\n", i, test_buf2[i]); + test_done = 1; +} + +void lc823450_dma_test() +{ + int i; + for (i = 0; i < 256; i++) + { + test_buf1[i] = i; + test_buf2[i] = 0; + } + DMA_HANDLE hdma; + hdma = lc823450_dmachannel(DMA_CHANNEL_VIRTUAL); + lc823450_dmasetup(hdma, LC823450_DMA_SRCWIDTH_WORD | + LC823450_DMA_DSTWIDTH_WORD | + LC823450_DMA_DSTINC | + LC823450_DMA_SRCINC, + test_buf1, test_buf2, 4084); + lc823450_dmastart(hdma, dma_done, NULL); + while (!test_done); +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_dmainitialize + ****************************************************************************/ + +void up_dmainitialize(void) +{ + int i; + + for (i = 0; i < DMA_CHANNEL_NUM; i++) + { + g_dma.phydmach[i].inprogress = 0; + sq_init(&g_dma.phydmach[i].req_q); + } + + sem_init(&g_dma.exclsem, 0, 1); + + if (irq_attach(LC823450_IRQ_DMAC, dma_interrupt, NULL) != 0) + { + return; + } + up_enable_irq(LC823450_IRQ_DMAC); + + /* Clock & Reset */ + modifyreg32(MCLKCNTBASIC, 0, MCLKCNTBASIC_DMAC_CLKEN); + modifyreg32(MRSTCNTBASIC, 0, MRSTCNTBASIC_DMAC_RSTB); + + /* DMAC enable */ + modifyreg32(DMACCONFIG, 0, DMACCONFIG_EN); + +#ifdef DMA_TEST + lc823450_dma_test(); +#endif + + /* clock disable */ + modifyreg32(MCLKCNTBASIC, MCLKCNTBASIC_DMAC_CLKEN, 0); +} + +/**************************************************************************** + * Name: lc823450_dmaconfigure + * + * Description: + * Configure a DMA request. Each DMA request may have two different DMA + * request sources. This associates one of the sources with a DMA request. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void lc823450_dmaconfigure(uint8_t dmarequest, bool alternate) +{ + return; +} + +/**************************************************************************** + * Name: lc823450_dmarequest + * + * Description: + * Configure a DMA request. + * Returned Value: + * None + * + ****************************************************************************/ + +void lc823450_dmarequest(DMA_HANDLE handle, uint8_t dmarequest) +{ + struct lc823450_dmach_s *dmach = (struct lc823450_dmach_s *)handle; + uint32_t val; + int req_line; + + /* search for free request line */ + for (req_line = 0; req_line < 16; req_line++) + { + if ((g_dma.reqline_use & (1 << req_line)) == 0) + { + g_dma.reqline_use |= 1 << req_line; + break; + } + } + DEBUGASSERT(req_line != 16); + + up_enable_clk(LC823450_CLOCK_DMA); + /* DREQ Select */ + val = getreg32(DREQ0_3 + (req_line / 4) * 4); + val &= ~(0xff << ((req_line % 4) * 8)); + val |= dmarequest << ((req_line % 4) * 8); + putreg32(val, (DREQ0_3 + (req_line / 4) * 4)); + + /* source or dest peri request ? */ + val = getreg32(DMACCFG(dmach->chn)); + switch (dmarequest) + { + case DMA_REQUEST_UART0RX: + case DMA_REQUEST_UART1RX: + case DMA_REQUEST_UART2RX: + case DMA_REQUEST_SIORX: + val &= ~(0xf << DMACCFG_SRCPERI_SHIFT); + val |= req_line << DMACCFG_SRCPERI_SHIFT; + val |= DMACCFG_FLOWCTRL_P2M_DMA; + break; + case DMA_REQUEST_UART0TX: + case DMA_REQUEST_UART1TX: + case DMA_REQUEST_UART2TX: + case DMA_REQUEST_SIOTX: + val &= ~(0xf << DMACCFG_DSTPERI_SHIFT); + val |= req_line << DMACCFG_DSTPERI_SHIFT; + val |= DMACCFG_FLOWCTRL_M2P_DMA; + break; + case DMA_REQUEST_USBDEV: /* ??? */ + val &= ~(0xf << DMACCFG_DSTPERI_SHIFT); + val |= req_line << DMACCFG_DSTPERI_SHIFT; + val |= req_line << DMACCFG_SRCPERI_SHIFT; + val |= DMACCFG_FLOWCTRL_M2P_DMA; + break; + default: + _err("NOT IMP\n"); + DEBUGASSERT(0); + } + putreg32(val, DMACCFG(dmach->chn)); + up_disable_clk(LC823450_CLOCK_DMA); + + return; +} + +/**************************************************************************** + * Name: lc823450_dmareauest_dir + ****************************************************************************/ + +void lc823450_dmareauest_dir(DMA_HANDLE handle, uint8_t dmarequest, int m2p) +{ + struct lc823450_dmach_s *dmach = (struct lc823450_dmach_s *)handle; + uint32_t val; + + up_enable_clk(LC823450_CLOCK_DMA); + + val = getreg32(DMACCFG(dmach->chn)); + + val &= ~DMACCFG_FLOWCTRL_MASK; + if (m2p) + { + val |= DMACCFG_FLOWCTRL_M2P_DMA; + } + else + { + val |= DMACCFG_FLOWCTRL_P2M_DMA; + } + + putreg32(val, DMACCFG(dmach->chn)); + up_disable_clk(LC823450_CLOCK_DMA); +} + +/**************************************************************************** + * Name: lc823450_dmachannel + * + * Description: + * Allocate a DMA channel. This function sets aside a DMA channel and + * gives the caller exclusive access to the DMA channel. + * + * Returned Value: + * One success, this function returns a non-NULL, void* DMA channel + * handle. NULL is returned on any failure. This function can fail only + * if no DMA channel is available. + * + ****************************************************************************/ + +DMA_HANDLE lc823450_dmachannel(int ch) +{ + struct lc823450_dmach_s *dmach = NULL; + + /* Get exclusive access to the GPDMA state structure */ + + dmach = (struct lc823450_dmach_s *) + kmm_zalloc(sizeof(struct lc823450_dmach_s)); + + if (dmach) + { + dmach->chn = ch; + } + + return (DMA_HANDLE)dmach; +} + +/**************************************************************************** + * Name: lc823450_dmafree + * + * Description: + * Release a DMA channel. NOTE: The 'handle' used in this argument must + * NEVER be used again until lc823450_dmachannel() is called again to re-gain + * a valid handle. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void lc823450_dmafree(DMA_HANDLE handle) +{ + struct lc823450_dmach_s *dmach = (DMA_HANDLE)handle; + + DEBUGASSERT(dmach); + + /* Make sure that the DMA channel was properly stopped */ + + lc823450_dmastop(handle); + + /* Mark the channel available. This is an atomic operation and needs no + * special protection. + */ + + kmm_free(handle); +} + +/**************************************************************************** + * Name: lc823450_dmasetup + * + * Description: + * Configure DMA for one transfer. + * + ****************************************************************************/ + +int lc823450_dmasetup(DMA_HANDLE handle, uint32_t control, + uint32_t srcaddr, uint32_t destaddr, size_t nxfrs) +{ + struct lc823450_dmach_s *dmach = (DMA_HANDLE)handle; + + DEBUGASSERT(dmach); + + dmach->srcaddr = srcaddr; + dmach->destaddr = destaddr; + dmach->ctrl = control; + dmach->nxfrs = nxfrs; + dmach->llist = 0; + + return OK; +} + +int lc823450_dmallsetup(DMA_HANDLE handle, uint32_t control, + uint32_t srcaddr, uint32_t destaddr, size_t nxfrs, uint32_t llist) +{ + struct lc823450_dmach_s *dmach = (DMA_HANDLE)handle; + + DEBUGASSERT(dmach); + + dmach->srcaddr = srcaddr; + dmach->destaddr = destaddr; + dmach->ctrl = control; + dmach->nxfrs = nxfrs; + dmach->llist = llist; + + return OK; +} + +/**************************************************************************** + * Name: lc823450_dmaremain + ****************************************************************************/ + +int lc823450_dmaremain(DMA_HANDLE handle) +{ + struct lc823450_dmach_s *dmach = (DMA_HANDLE)handle; + + return getreg32(DMACCTL(dmach->chn)) & 0xfff; +} + + +/**************************************************************************** + * Name: lc823450_dmastart + ****************************************************************************/ + +int lc823450_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg) +{ + struct lc823450_dmach_s *dmach = (DMA_HANDLE)handle; + irqstate_t flags; + + DEBUGASSERT(dmach); + + + /* select physical channel */ + flags = enter_critical_section(); + + sq_addfirst(&dmach->q_ent, &g_dma.phydmach[dmach->chn].req_q); + + dmach->callback = callback; + dmach->arg = arg; + + /* Kick DMAC, if not active */ + if (!g_dma.phydmach[dmach->chn].inprogress) + { + phydmastart(&g_dma.phydmach[dmach->chn]); + } + + leave_critical_section(flags); + + return OK; +} + +/**************************************************************************** + * Name: lc823450_dmastop + ****************************************************************************/ + +void lc823450_dmastop(DMA_HANDLE handle) +{ + struct lc823450_dmach_s *dmach = (DMA_HANDLE)handle; + struct lc823450_phydmach_s *pdmach; + irqstate_t flags; + + DEBUGASSERT(dmach); + + flags = enter_critical_section(); + + modifyreg32(DMACCFG(dmach->chn), DMACCFG_ITC | DMACCFG_E, 0); + + pdmach = &g_dma.phydmach[dmach->chn]; + if (pdmach) + { + if (pdmach->inprogress) + { + up_disable_clk(LC823450_CLOCK_DMA); + } + pdmach->inprogress = 0; + sq_rem(&dmach->q_ent, &pdmach->req_q); + } + + leave_critical_section(flags); + return; +} diff --git a/arch/arm/src/lc823450/lc823450_dma.h b/arch/arm/src/lc823450/lc823450_dma.h new file mode 100644 index 00000000000..6a73236d1d2 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_dma.h @@ -0,0 +1,162 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_dma.h + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_LC823450_LC823450_DMA_H +#define __ARCH_ARM_SRC_LC823450_LC823450_DMA_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define LC823450_DMA_ITC (1 << 31) +#define LC823450_DMA_SRCWIDTH_BYTE (0 << 18) +#define LC823450_DMA_SRCWIDTH_HWORD (1 << 18) +#define LC823450_DMA_SRCWIDTH_WORD (2 << 18) +#define LC823450_DMA_DSTWIDTH_BYTE (0 << 21) +#define LC823450_DMA_DSTWIDTH_HWORD (1 << 21) +#define LC823450_DMA_DSTWIDTH_WORD (2 << 21) +#define LC823450_DMA_SRCINC (1 << 26) +#define LC823450_DMA_DSTINC (1 << 27) +#define LC823450_DMA_SBS_SHIFT 12 +#define LC823450_DMA_DBS_SHIFT 15 +#define LC823450_DMA_BS_1 0 +#define LC823450_DMA_BS_4 1 +#define LC823450_DMA_BS_8 2 +#define LC823450_DMA_BS_16 3 +#define LC823450_DMA_BS_32 4 +#define LC823450_DMA_BS_64 5 +#define LC823450_DMA_BS_128 6 +#define LC823450_DMA_BS_256 7 + +#define LC823450_DMA_TRANSSIZE_MASK (0xfff << 0) +#define LC823450_DMA_MAX_TRANSSIZE 0xff0 + + +/* HighPriority */ +#define DMA_CHANNEL_SIOTX 0 +#define DMA_CHANNEL_UART1RX 1 +#define DMA_CHANNEL_UART1TX 2 +#define DMA_CHANNEL_USBDEV 3 +#define DMA_CHANNEL_AUDIOWR 4 +#define DMA_CHANNEL_AUDIORD 5 +#if 0 +#define DMA_CHANNEL_??? 6 +#endif +#define DMA_CHANNEL_VIRTUAL 7 +#define DMA_CHANNEL_NUM 8 + +#define DMA_REQUEST_UART0RX 0 +#define DMA_REQUEST_UART0TX 1 +#define DMA_REQUEST_UART1RX 2 +#define DMA_REQUEST_UART1TX 3 +#define DMA_REQUEST_UART2RX 4 +#define DMA_REQUEST_UART2TX 5 +#define DMA_REQUEST_SIORX 6 +#define DMA_REQUEST_SIOTX 7 +#define DMA_REQUEST_AUDIOBUF0 8 +#define DMA_REQUEST_AUDIOBUF1 9 +#define DMA_REQUEST_AUDIOBUF2 10 +#define DMA_REQUEST_AUDIOBUF3 11 +#define DMA_REQUEST_AUDIOBUF4 12 +#define DMA_REQUEST_AUDIOBUF5 13 +#define DMA_REQUEST_AUDIOBUF6 14 +#define DMA_REQUEST_AUDIOBUF7 15 +#define DMA_REQUEST_USBDEV 22 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct lc823450_dma_llist +{ + uint32_t srcaddr; + uint32_t dstaddr; + uint32_t nextlli; + uint32_t ctrl; +}; + +typedef void *DMA_HANDLE; +typedef void (*dma_callback_t)(DMA_HANDLE handle, void *arg, int result); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +EXTERN void lc823450_dmaconfigure(uint8_t dmarequest, bool alternate); +EXTERN DMA_HANDLE lc823450_dmachannel(int ch); +EXTERN void lc823450_dmafree(DMA_HANDLE handle); +EXTERN void lc823450_dmarequest(DMA_HANDLE handle, uint8_t dmarequest); +EXTERN int lc823450_dmasetup(DMA_HANDLE handle, uint32_t control, + uint32_t srcaddr, uint32_t destaddr, size_t nxfrs); +EXTERN int lc823450_dmallsetup(DMA_HANDLE handle, uint32_t control, + uint32_t srcaddr, uint32_t destaddr, + size_t nxfrs, uint32_t llist); +EXTERN void lc823450_dmareauest_dir(DMA_HANDLE handle, uint8_t dmarequest, + int m2p); + +EXTERN int lc823450_dmastart(DMA_HANDLE handle, dma_callback_t callback, + void *arg); +EXTERN void lc823450_dmastop(DMA_HANDLE handle); +EXTERN int lc823450_dmaremain(DMA_HANDLE handle); + + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ARCH_ARM_SRC_LC823450_LC823450_DMA_H */ diff --git a/arch/arm/src/lc823450/lc823450_gpio.c b/arch/arm/src/lc823450/lc823450_gpio.c new file mode 100644 index 00000000000..d259e935be1 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_gpio.c @@ -0,0 +1,530 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_gpio.c + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masayuki Ishikawa + * Author: Nobutaka Toyoshima + * Author: Masatoshi Tateishi + * + * 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 "up_arch.h" +#include "lc823450_gpio.h" +#include "lc823450_syscontrol.h" + +#ifdef CONFIG_IOEX +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + + +#define PORTX_OFFSET 0x00001000 +#define PORTX_DRC_OFFSET 0x0 +#define PORTX_DAT_OFFSET 0x4 + + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_IOEX +static FAR struct ioex_dev_s *g_ioex_dev; +#endif + +#ifdef CONFIG_LC823450_VGPIO +#define GPIO_VIRTUAL_NUM 32 +static FAR struct vgpio_ops_s *vgpio_ops[GPIO_VIRTUAL_NUM]; +#endif /* CONFIG_LC823450_VGPIO */ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lc823450_get_gpio_dir + ****************************************************************************/ + +static uintptr_t lc823450_get_gpio_dir(unsigned int port) +{ + uintptr_t regaddr = + PORT0_BASE + + (port * PORTX_OFFSET) + + PORTX_DRC_OFFSET; + + return regaddr; +} + +/**************************************************************************** + * Name: lc823450_get_gpio_data + ****************************************************************************/ + +static uintptr_t lc823450_get_gpio_data(unsigned int port) +{ + uintptr_t regaddr = + PORT0_BASE + + (port * PORTX_OFFSET) + + PORTX_DAT_OFFSET; + + return regaddr; +} + +/**************************************************************************** + * Name: lc823450_get_gpio_pull + ****************************************************************************/ + +static uintptr_t lc823450_get_gpio_pull(unsigned int port) +{ + uintptr_t regaddr = + PUDCNT0 + (4 * port); + + return regaddr; +} + + +/**************************************************************************** + * Name: lc823450_configinput + * + * Description: + * Configure pull up/down for the GPIO pin + * + * Assumptions: + * Interrupts are disabled so that read-modify-write operations are safe. + * + ****************************************************************************/ + +static inline void lc823450_configpull(uint16_t gpiocfg, + unsigned int port, unsigned int pin) +{ + uintptr_t regaddr; + uint32_t regval; + uint32_t pull; + + regaddr = lc823450_get_gpio_pull(port); + pull = gpiocfg & GPIO_PUPD_MASK; + regval = getreg32(regaddr); + regval &= ~(3 << (2 * pin)); /* clear the current setting */ + + switch (pull) + { + case GPIO_FLOAT: + /* do nothing */ + break; + case GPIO_PULLUP: + regval |= (1 << (2 * pin)); + break; + case GPIO_PULLDOWN: + regval |= (2 << (2 * pin)); + break; + } + + putreg32(regval, regaddr); + +} + + +/**************************************************************************** + * Name: lc823450_configinput + * + * Description: + * Configure a GPIO pin as an input + * + * Assumptions: + * Interrupts are disabled so that read-modify-write operations are safe. + * + ****************************************************************************/ + +static inline void lc823450_configinput(uint32_t port, uint32_t pin) +{ + uintptr_t regaddr; + uint32_t regval; + + regaddr = lc823450_get_gpio_dir(port); + + /* Then configure the pin as a normal input by clearing the corresponding + * bit in the rPxDRC register for the port. + */ + + regval = getreg32(regaddr); + regval &= ~(1 << pin); + putreg32(regval, regaddr); +} + +/**************************************************************************** + * Name: lc823450_configoutput + * + * Description: + * Configure a GPIO pin as an output. + * + * Assumptions: + * Interrupts are disabled so that read-modify-write operations are safe. + * + ****************************************************************************/ + +static inline void lc823450_configoutput(uint16_t gpiocfg, uint32_t port, uint32_t pin) +{ + uintptr_t regaddr; + uint32_t regval; + + regaddr = lc823450_get_gpio_dir(port); + + /* Then configure the pin as an output by setting the corresponding + * bit in the rPxDRC register for the port. + */ + + regval = getreg32(regaddr); + regval |= (1 << pin); + putreg32(regval, regaddr); + + /* Set the initial value of the output */ + + lc823450_gpio_write(gpiocfg, GPIO_IS_ONE(gpiocfg)); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + + +/**************************************************************************** + * Name: lc823450_gpio_mux + * + * Description: + * Change a GPIO pin mux. (only PORT0-5 are supported) + * + ****************************************************************************/ + +int lc823450_gpio_mux(uint16_t gpiocfg) +{ + uint32_t port = ((gpiocfg & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT); + uint32_t pin = ((gpiocfg & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT); + uint32_t mux = ((gpiocfg & GPIO_MUX_MASK) >> GPIO_MUX_SHIFT); + uint32_t val; + int ret = 0; + + if (port <= (GPIO_PORT5 >> GPIO_PORT_SHIFT)) + { + irqstate_t flags = enter_critical_section(); + val = getreg32(PMDCNT0 + (port * 4)); + val &= ~(3 << (2 * pin)); + val |= (mux << (2 *pin)); + putreg32(val, PMDCNT0 + (port * 4)); + leave_critical_section(flags); + } + else + { + ret = -1; + } + return ret; +} + + + +/**************************************************************************** + * Name: lc823450_gpio_config + * + * Description: + * Configure a GPIO based on bit-encoded description of the pin. NOTE: + * The pin *must* have first been configured for GPIO usage with a + * corresponding call to lc823450_pin_config(). + * + ****************************************************************************/ + +int lc823450_gpio_config(uint16_t gpiocfg) +{ + uint32_t port = ((gpiocfg & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT); + uint32_t pin = ((gpiocfg & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT); + irqstate_t flags; + int ret = OK; + +#ifdef CONFIG_LC823450_VGPIO + if (port == (GPIO_PORTV >> GPIO_PORT_SHIFT)) + { + return OK; + } +#endif /* CONFIG_LC823450_VGPIO */ + + if (port <= (GPIO_PORT5 >> GPIO_PORT_SHIFT)) + { + DEBUGASSERT(pin < NUM_GPIO_PINS); + + modifyreg32(MCLKCNTAPB, 0, MCLKCNTAPB_PORT0_CLKEN << port); + modifyreg32(MRSTCNTAPB, 0, MRSTCNTAPB_PORT0_RSTB << port); + + /* Handle the GPIO configuration by the basic mode of the pin */ + + flags = enter_critical_section(); + + /* pull up/down specified */ + if (gpiocfg & GPIO_PUPD_MASK) + { + lc823450_configpull(gpiocfg, port, pin); + } + + switch (gpiocfg & GPIO_MODE_MASK) + { + case GPIO_MODE_INPUT: /* GPIO input pin */ + lc823450_configinput(port, pin); + break; + + case GPIO_MODE_OUTPUT: /* GPIO output pin */ + lc823450_configoutput(gpiocfg, port, pin); + break; + + default : + _err("ERROR: Unrecognized pin mode: %04x\n", gpiocfg); + ret = -EINVAL; + break; + } + + leave_critical_section(flags); + } +#ifdef CONFIG_IOEX + else if (port <= (GPIO_PORTEX >> GPIO_PORT_SHIFT)) + { + uint32_t dir; + uint32_t pupd; + DEBUGASSERT(pin < NUM_GPIOEX_PINS); + + if (GPIO_IS_INPUT(gpiocfg)) + { + dir = IOEX_DIR_INPUT; + + switch (gpiocfg & GPIO_PUPD_MASK) + { + case GPIO_FLOAT: + pupd = IOEX_PUPD_FLOAT; + break; + case GPIO_PULLUP: + pupd = IOEX_PUPD_PULLUP; + break; + case GPIO_PULLDOWN: + pupd = IOEX_PUPD_PULLDOWN; + break; + default: + DEBUGASSERT(0); + return -EINVAL; + } + } + else + { + dir = IOEX_DIR_OUTPUT; + pupd = 0; + } + + ret = g_ioex_dev->ops->config(g_ioex_dev, pin, dir, pupd); + if (ret != 0) + { + dbg("Failed to configure I/O expanded port\n"); + } + + g_ioex_dev->ops->write(g_ioex_dev, pin, GPIO_IS_ONE(gpiocfg)); + } +#endif /* CONFIG_IOEX */ + else + { + ret = -EINVAL; + } + + return ret; +} + +/**************************************************************************** + * Name: lc823450_gpio_write + * + * Description: + * Write one or zero to the selected GPIO pin + * + ****************************************************************************/ + +void lc823450_gpio_write(uint16_t gpiocfg, bool value) +{ + uint32_t port = ((gpiocfg & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT); + uint32_t pin = ((gpiocfg & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT); + + uintptr_t regaddr; + uint32_t regval; + irqstate_t flags; + +#ifdef CONFIG_LC823450_VGPIO + if (port == (GPIO_PORTV >> GPIO_PORT_SHIFT)) + { + assert(pin < GPIO_VIRTUAL_NUM); + if (vgpio_ops[pin] && vgpio_ops[pin]->write) + { + vgpio_ops[pin]->write(pin, value); + } + return; + } +#endif /* CONFIG_LC823450_VGPIO */ + + if (port <= (GPIO_PORT5 >> GPIO_PORT_SHIFT)) + { + DEBUGASSERT(pin < NUM_GPIO_PINS); + + regaddr = lc823450_get_gpio_data(port); + + flags = enter_critical_section(); + + /* Write the value (0 or 1). To the data register */ + + regval = getreg32(regaddr); + + if (value) + { + regval |= (1 << pin); + } + else + { + regval &= ~(1 << pin); + } + putreg32(regval, regaddr); + + leave_critical_section(flags); + } +#ifdef CONFIG_IOEX + else if (port <= (GPIO_PORTEX >> GPIO_PORT_SHIFT)) + { + DEBUGASSERT(pin < NUM_GPIOEX_PINS); + + g_ioex_dev->ops->write(g_ioex_dev, pin, value); + } +#endif /* CONFIG_IOEX */ +} + +/**************************************************************************** + * Name: lc823450_gpio_read + * + * Description: + * Read one or zero from the selected GPIO pin + * + ****************************************************************************/ + +bool lc823450_gpio_read(uint16_t gpiocfg) +{ + uint32_t port = ((gpiocfg & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT); + uint32_t pin = ((gpiocfg & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT); + + uintptr_t regaddr; + uint32_t regval; + bool value = false; + +#ifdef CONFIG_LC823450_VGPIO + if (port == (GPIO_PORTV >> GPIO_PORT_SHIFT)) + { + assert(pin < GPIO_VIRTUAL_NUM); + if (vgpio_ops[pin] && vgpio_ops[pin]->read) + { + return vgpio_ops[pin]->read(pin); + } + return 0; + } +#endif /* CONFIG_LC823450_VGPIO */ + + if (port <= (GPIO_PORT5 >> GPIO_PORT_SHIFT)) + { + DEBUGASSERT(pin < NUM_GPIO_PINS); + + /* Get the value of the pin from the pin data register */ + regaddr = lc823450_get_gpio_data(port); + regval = getreg32(regaddr); + value = ((regval >> pin) & 0x01); + } +#ifdef CONFIG_IOEX + else if (port <= (GPIO_PORTEX >> GPIO_PORT_SHIFT)) + { + DEBUGASSERT(pin < NUM_GPIOEX_PINS); + + value = g_ioex_dev->ops->read(g_ioex_dev, pin); + } +#endif /* CONFIG_IOEX */ + else + { + DEBUGASSERT(0); + } + + return value; +} + +/**************************************************************************** + * Name: lc823450_gpio_initialize + * + * Description: + * Initialize GPIO expander driver + * + ****************************************************************************/ + +#ifdef CONFIG_IOEX +int lc823450_gpio_initialize(void) +{ + g_ioex_dev = up_ioexinitialize(1); + if (!g_ioex_dev) + { + dbg("%s: Failed to initialize ioex driver\n", __func__); + return -EIO; + } + return OK; +} +#endif /* CONFIG_IOEX */ + +/**************************************************************************** + * Name: lc823450_vgpio_register + * + * Description: + * Register Virtual GPIO driver + * + ****************************************************************************/ + +#ifdef CONFIG_LC823450_VGPIO +int lc823450_vgpio_register(unsigned int pin, FAR struct vgpio_ops_s *ops) +{ + assert(pin < GPIO_VIRTUAL_NUM); + vgpio_ops[pin] = ops; + return OK; +} +#endif /* CONFIG_LC823450_VGPIO */ diff --git a/arch/arm/src/lc823450/lc823450_gpio.h b/arch/arm/src/lc823450/lc823450_gpio.h new file mode 100644 index 00000000000..20641d87381 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_gpio.h @@ -0,0 +1,287 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_gpio.h + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masayuki Ishikawa + * Author: Nobutaka Toyoshima + * Author: Masatoshi Tateishi + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_LC823450_LC823450_GPIO_H +#define __ARCH_ARM_SRC_LC823450_LC823450_GPIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + + +/* Max number of GPIO ports and the maximum number of pins per port */ + +#ifdef CONFIG_IOEX +# define NUM_GPIO_PORTS 7 +# define NUM_GPIOEX_PINS CONFIG_IOEX_NPINS +#else +# define NUM_GPIO_PORTS 6 +#endif + +#define NUM_GPIO_PINS 16 + + +/* Input/Output mode + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * ---- ---- ---- ---- + * MM.. .... .... .... + */ + +#define GPIO_MODE_SHIFT (14) /* Bits 14-15: Mode of the GPIO pin */ +#define GPIO_MODE_MASK (3 << GPIO_MODE_SHIFT) +# define GPIO_MODE_INPUT (0 << GPIO_MODE_SHIFT) /* GPIO input */ +# define GPIO_MODE_OUTPUT (1 << GPIO_MODE_SHIFT) /* GPIO output */ +# define GPIO_MODE_PININTR (2 << GPIO_MODE_SHIFT) /* GPIO pin interrupt */ + +#define GPIO_IS_OUTPUT(p) (((p) & GPIO_MODE_MASK) == GPIO_MODE_OUTPUT) +#define GPIO_IS_INPUT(p) (((p) & GPIO_MODE_MASK) == GPIO_MODE_INPUT) +#define GPIO_IS_PININT(p) (((p) & GPIO_MODE_MASK) == GPIO_MODE_PININTR) + +/* Initial value (for GPIO outputs only) + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * ---- ---- ---- ---- + * ..V. .... .... .... + */ + +#define GPIO_VALUE_ONE (1 << 13) /* Bit 13: 1=High */ +#define GPIO_VALUE_ZERO (0) /* Bit 13: 0=Low */ + +#define GPIO_IS_ONE(p) (((p) & GPIO_VALUE_ONE) != 0) +#define GPIO_IS_ZERO(p) (((p) & GPIO_VALUE_ONE) == 0) + +/* GPIO pinmux + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * ---- ---- ---- ---- + * .... XX.. .... .... + */ + +#define GPIO_MUX_SHIFT (10) /* Bits 10-11: pinmux */ +#define GPIO_MUX_MASK (3 << GPIO_MUX_SHIFT) +# define GPIO_MUX0 (0 << GPIO_MUX_SHIFT) /* mux mode 0 */ +# define GPIO_MUX1 (1 << GPIO_MUX_SHIFT) /* mux mode 1 */ +# define GPIO_MUX2 (2 << GPIO_MUX_SHIFT) /* mux mode 2 */ +# define GPIO_MUX3 (3 << GPIO_MUX_SHIFT) /* mux mode 3 */ + + +/* GPIO pull-ups/downs + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * ---- ---- ---- ---- + * .... ..UU .... .... + */ + +#define GPIO_PUPD_SHIFT (8) /* Bits 8-9: Pull-up/pull down */ +#define GPIO_PUPD_MASK (3 << GPIO_PUPD_SHIFT) +# define GPIO_DEFAULT (0 << GPIO_PUPD_SHIFT) /* H/W default */ +# define GPIO_PULLUP (1 << GPIO_PUPD_SHIFT) /* Pull-up */ +# define GPIO_PULLDOWN (2 << GPIO_PUPD_SHIFT) /* Pull-down */ +# define GPIO_FLOAT (3 << GPIO_PUPD_SHIFT) /* No pull-up, pull-down */ + + +/* GPIO Port Number: + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * ---- ---- ---- ---- + * .... .... PPP. .... + */ + +#define GPIO_PORT_SHIFT (5) /* Bits 5-7: Port number */ +#define GPIO_PORT_MASK (7 << GPIO_PORT_SHIFT) +# define GPIO_PORT0 (0 << GPIO_PORT_SHIFT) +# define GPIO_PORT1 (1 << GPIO_PORT_SHIFT) +# define GPIO_PORT2 (2 << GPIO_PORT_SHIFT) +# define GPIO_PORT3 (3 << GPIO_PORT_SHIFT) +# define GPIO_PORT4 (4 << GPIO_PORT_SHIFT) +# define GPIO_PORT5 (5 << GPIO_PORT_SHIFT) +#ifdef CONFIG_IOEX +# define GPIO_PORTEX (6 << GPIO_PORT_SHIFT) +#endif +#ifdef CONFIG_LC823450_VGPIO +# define GPIO_PORTV (7 << GPIO_PORT_SHIFT) +#endif /* CONFIG_LC823450_VGPIO */ + +/* GPIO Pin Number: + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * ---- ---- ---- ---- + * .... .... ...B BBBB + */ + +#define GPIO_PIN_SHIFT (0) /* Bits 0-4: Pin number */ +#define GPIO_PIN_MASK (31 << GPIO_PIN_SHIFT) +# define GPIO_PIN0 (0 << GPIO_PIN_SHIFT) +# define GPIO_PIN1 (1 << GPIO_PIN_SHIFT) +# define GPIO_PIN2 (2 << GPIO_PIN_SHIFT) +# define GPIO_PIN3 (3 << GPIO_PIN_SHIFT) +# define GPIO_PIN4 (4 << GPIO_PIN_SHIFT) +# define GPIO_PIN5 (5 << GPIO_PIN_SHIFT) +# define GPIO_PIN6 (6 << GPIO_PIN_SHIFT) +# define GPIO_PIN7 (7 << GPIO_PIN_SHIFT) +# define GPIO_PIN8 (8 << GPIO_PIN_SHIFT) +# define GPIO_PIN9 (9 << GPIO_PIN_SHIFT) +# define GPIO_PINA (10 << GPIO_PIN_SHIFT) +# define GPIO_PINB (11 << GPIO_PIN_SHIFT) +# define GPIO_PINC (12 << GPIO_PIN_SHIFT) +# define GPIO_PIND (13 << GPIO_PIN_SHIFT) +# define GPIO_PINE (14 << GPIO_PIN_SHIFT) +# define GPIO_PINF (15 << GPIO_PIN_SHIFT) +#ifdef CONFIG_IOEX +# define GPIO_PIN10 (16 << GPIO_PIN_SHIFT) +# define GPIO_PIN11 (17 << GPIO_PIN_SHIFT) +# define GPIO_PIN12 (18 << GPIO_PIN_SHIFT) +# define GPIO_PIN13 (19 << GPIO_PIN_SHIFT) +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#ifdef CONFIG_LC823450_VGPIO +struct vgpio_ops_s +{ + void (*write)(uint32_t pin, bool value); + bool (*read)(uint32_t pin); +}; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lc823450_gpio_mux + * + * Description: + * Configure pin mux for a GPIO + * + ****************************************************************************/ + +int lc823450_gpio_mux(uint16_t gpiocfg); + +/**************************************************************************** + * Name: lc823450_gpio_config + * + * Description: + * Configure a GPIO pin based on encoded pin attributes. + * + ****************************************************************************/ + +int lc823450_gpio_config(uint16_t gpiocfg); + +/**************************************************************************** + * Name: lc823450_gpio_write + * + * Description: + * Write one or zero to the selected GPIO pin + * + ****************************************************************************/ + +void lc823450_gpio_write(uint16_t gpiocfg, bool value); + +/**************************************************************************** + * Name: lc823450_gpio_read + * + * Description: + * Read one or zero from the selected GPIO pin + * + ****************************************************************************/ + +bool lc823450_gpio_read(uint16_t gpiocfg); + +/**************************************************************************** + * Function: lc823450_gpio_dump + * + * Description: + * Dump all pin configuration registers + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG +int lc823450_gpio_dump(uint16_t gpiocfg, FAR const char *msg); +#else +# define lc823450_gpio_dump(p,m) +#endif + +/**************************************************************************** + * Name: lc823450_vgpio_register + * + * Description: + * Register Virtual GPIO driver + * + ****************************************************************************/ + +#ifdef CONFIG_LC823450_VGPIO +int lc823450_vgpio_register(unsigned int pin, FAR struct vgpio_ops_s *ops); +#endif /* CONFIG_LC823450_VGPIO */ + + +#if defined(__cplusplus) +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_LC823450_LC823450_GPIO_H */ diff --git a/arch/arm/src/lc823450/lc823450_i2c.c b/arch/arm/src/lc823450/lc823450_i2c.c new file mode 100644 index 00000000000..597d466c392 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_i2c.c @@ -0,0 +1,1235 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_i2c.c + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Nobutaka Toyoshima + * Author: Masayuki Ishikawa + * Author: Masatoshi Tateishi + * + * 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 +#include +#include +#include + +#include + +#include "up_arch.h" + +#include "lc823450_syscontrol.h" +#include "lc823450_clockconfig.h" +#include "lc823450_i2c.h" +#include "lc823450_gpio.h" + +#ifdef CONFIG_I2C + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_LC823450_I2C_TIMEOSEC +# define CONFIG_LC823450_I2C_TIMEOSEC 0 +#endif + +#ifndef CONFIG_LC823450_I2C_TIMEOMS +# define CONFIG_LC823450_I2C_TIMEOMS 500 +#endif + +#ifdef CONFIG_I2C_SLAVE +# error "I2C driver cannot support CONFIG_I2C_SLAVE." +#endif + +#if CONFIG_LC823450_I2C_TIMEOMS >= 1000 +# error "Unsupported value of CONFIG_LC823450_I2C_TIMEOMS" +#endif + +#define GPIO_I2C0_SCL (GPIO_PORT0 | GPIO_PIN7 | GPIO_MODE_OUTPUT | GPIO_VALUE_ZERO) +#define GPIO_I2C0_SDA (GPIO_PORT0 | GPIO_PIN8 | GPIO_MODE_OUTPUT | GPIO_VALUE_ZERO) +#define GPIO_I2C1_SCL (GPIO_PORT2 | GPIO_PINB | GPIO_MODE_OUTPUT | GPIO_VALUE_ZERO) +#define GPIO_I2C1_SDA (GPIO_PORT2 | GPIO_PINC | GPIO_MODE_OUTPUT | GPIO_VALUE_ZERO) + + +#ifdef CONFIG_DEBUG_I2C +# define i2cdbg dbg +# define i2cvdbg vdbg +# define i2cllvdbg llvdbg +#else +# define i2cdbg(x...) +# define i2cvdbg(x...) +# define i2cllvdbg(x...) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Interrupt state */ + +enum lc823450_irqstate_e +{ + IRQSTATE_IDLE = 0, /* No I2C activity */ + IRQSTATE_WSTART, /* Waiting for START Condition */ + IRQSTATE_WSEND, /* Waiting for data transmission */ + IRQSTATE_WRECV, /* Waiting for data reception */ + IRQSTATE_WSTOP, /* Waiting for STOP Condition */ + IRQSTATE_DONE, /* Interrupt activity complete */ +}; + +/* I2C Device hardware configuration */ + +struct lc823450_i2c_config_s +{ + uint32_t base; /* I2C base address */ + uint32_t en_bit; /* I2C controller enable bit (clock/reset) */ +#ifndef CONFIG_I2C_POLLED + int (*isr)(int, void *, void *); /* Interrupt handler */ + int irq; /* IRQ number */ +#endif +}; + +/* I2C Device Private Data */ + +struct lc823450_i2c_priv_s +{ + FAR const struct i2c_ops_s *ops; /* Standard I2C operations */ + FAR const struct lc823450_i2c_config_s *config; /* Port configuration */ + int refs; /* Referernce count */ + sem_t sem_excl; /* Mutual exclusion semaphore */ +#ifndef CONFIG_I2C_POLLED + sem_t sem_isr; /* Interrupt wait semaphore */ +#endif + volatile uint8_t irqstate; /* Interrupt handshake (see enum lc823450_irqstate_e) */ + + uint32_t frequency; /* Current I2C bus furequency */ + uint8_t msgc; /* Message count */ + FAR struct i2c_msg_s *msgv; /* Message list */ + FAR uint8_t *ptr; /* Current message buffer */ + int dcnt; /* Current message length */ + uint16_t flags; /* Current message flags */ + + uint32_t timeoms; /* I2C transfer timeout in msec */ + bool timedout; /* If true, I2C transfer timed-out */ +}; + + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static inline void lc823450_i2c_sem_wait(FAR struct lc823450_i2c_priv_s *priv); +static inline void lc823450_i2c_sem_post(FAR struct lc823450_i2c_priv_s *priv); +static inline int lc823450_i2c_sem_waitdone(FAR struct lc823450_i2c_priv_s *priv); + + +#ifndef CONFIG_I2C_POLLED +static inline void lc823450_i2c_enableirq(FAR struct lc823450_i2c_priv_s *priv); +static inline void lc823450_i2c_disableirq(FAR struct lc823450_i2c_priv_s *priv); +#endif +static inline bool lc823450_i2c_checkirq(FAR struct lc823450_i2c_priv_s *priv); +static inline bool lc823450_i2c_checkbusy(FAR struct lc823450_i2c_priv_s *priv); +static inline void lc823450_i2c_prepxfer(FAR struct lc823450_i2c_priv_s *priv); +static inline void lc823450_i2c_sendstart(FAR struct lc823450_i2c_priv_s *priv); +static inline void lc823450_i2c_sendstop(FAR struct lc823450_i2c_priv_s *priv); +static inline uint32_t lc823450_i2c_readdata(FAR struct lc823450_i2c_priv_s *priv); +static void lc823450_i2c_starttransfer(FAR struct lc823450_i2c_priv_s *priv); + +static int lc823450_i2c_isr(FAR struct lc823450_i2c_priv_s *priv); +#ifndef CONFIG_I2C_POLLED +#ifdef CONFIG_LC823450_I2C0 +static int lc823450_i2c0_isr(int irq, FAR void *context, FAR void *arg); +#endif +#ifdef CONFIG_LC823450_I2C1 +static int lc823450_i2c1_isr(int irq, FAR void *context, FAR void *arg); +#endif +#endif + +static int lc823450_i2c_init(FAR struct lc823450_i2c_priv_s *priv, int port); +static int lc823450_i2c_deinit(FAR struct lc823450_i2c_priv_s *priv, int port); + +static int lc823450_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs, int count); + +#ifdef CONFIG_I2C_RESET +static int lc823450_i2c_reset(FAR struct i2c_master_s *priv); +#endif + + +/**************************************************************************** + * Private Data + ****************************************************************************/ + + +/* I2C interface */ + +struct i2c_ops_s lc823450_i2c_ops = +{ + .transfer = lc823450_i2c_transfer, +#ifdef CONFIG_I2C_RESET + .reset = lc823450_i2c_reset +#endif +}; + + +#ifdef CONFIG_LC823450_I2C0 +static const struct lc823450_i2c_config_s lc823450_i2c0_config = +{ + .base = LC823450_I2C0_REGBASE, + .en_bit = MCLKCNTAPB_I2C0_CLKEN, /* Same as MRSTCNTAPB_I2C0_RSTB */ +#ifndef CONFIG_I2C_POLLED + .isr = lc823450_i2c0_isr, + .irq = LC823450_IRQ_I2C0, +#endif /* CONFIG_I2C_POLLED */ +}; + +static struct lc823450_i2c_priv_s lc823450_i2c0_priv = +{ + .ops = &lc823450_i2c_ops, + .config = &lc823450_i2c0_config, + .refs = 0, + .irqstate = IRQSTATE_IDLE, + .msgc = 0, + .msgv = NULL, + .ptr = NULL, + .dcnt = 0, + .flags = 0, + .timeoms = CONFIG_LC823450_I2C_TIMEOMS, + .timedout = false, +}; +#endif /* CONFIG_LC823450_I2C0 */ + +#ifdef CONFIG_LC823450_I2C1 +static const struct lc823450_i2c_config_s lc823450_i2c1_config = +{ + .base = LC823450_I2C1_REGBASE, + .en_bit = MCLKCNTAPB_I2C1_CLKEN, /* Same as MRSTCNTAPB_I2C1_RSTB */ +#ifndef CONFIG_I2C_POLLED + .isr = lc823450_i2c1_isr, + .irq = LC823450_IRQ_I2C1, +#endif /* CONFIG_I2C_POLLED */ +}; + +static struct lc823450_i2c_priv_s lc823450_i2c1_priv = +{ + .ops = &lc823450_i2c_ops, + .config = &lc823450_i2c1_config, + .refs = 0, + .irqstate = IRQSTATE_IDLE, + .msgc = 0, + .msgv = NULL, + .ptr = NULL, + .dcnt = 0, + .flags = 0, + .timeoms = CONFIG_LC823450_I2C_TIMEOMS, + .timedout = false, +}; +#endif /* CONFIG_LC823450_I2C1 */ + + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lc823450_i2c_sem_wait + * + * Description: + * Take the exclusive access, waiting as necessary + * + ****************************************************************************/ + +static inline void lc823450_i2c_sem_wait(FAR struct lc823450_i2c_priv_s *priv) +{ + while (sem_wait(&priv->sem_excl) != 0) + { + ASSERT(errno == EINTR); + } +} + +/**************************************************************************** + * Name: lc823450_i2c_sem_post + * + * Description: + * Release the mutual exclusion semaphore + * + ****************************************************************************/ + +static inline void lc823450_i2c_sem_post(FAR struct lc823450_i2c_priv_s *priv) +{ + sem_post(&priv->sem_excl); +} + +/**************************************************************************** + * Name: lc823450_i2c_sem_waitdone + * + * Description: + * Wait for a transfer to complete + * + ****************************************************************************/ + +#ifndef CONFIG_I2C_POLLED +static inline int lc823450_i2c_sem_waitdone(FAR struct lc823450_i2c_priv_s *priv) +{ + struct timespec abstime; + int ret; + + do + { + /* Get the current time */ + +#ifdef CONFIG_CLOCK_MONOTONIC + (void)clock_gettime(CLOCK_MONOTONIC, &abstime); +#else + (void)clock_gettime(CLOCK_REALTIME, &abstime); +#endif + + /* Calculate a time in the future */ + +#if CONFIG_LC823450_I2C_TIMEOSEC > 0 + abstime.tv_sec += CONFIG_LC823450_I2C_TIMEOSEC; +#endif + + /* Add a value proportional to the number of bytes in the transfer */ + + abstime.tv_nsec += priv->timeoms * 1000 * 1000; + if (abstime.tv_nsec >= 1000 * 1000 * 1000) + { + abstime.tv_sec++; + abstime.tv_nsec -= 1000 * 1000 * 1000; + } + + /* Wait until either the transfer is complete or the timeout expires */ + +#ifdef CONFIG_CLOCK_MONOTONIC + ret = sem_timedwait_monotonic(&priv->sem_isr, &abstime); +#else + ret = sem_timedwait(&priv->sem_isr, &abstime); +#endif + if (ret != OK && errno != EINTR) + { + + /* Break out of the loop on irrecoverable errors. This would + * include timeouts and mystery errors reported by sem_timedwait. + * NOTE that we try again if we are awakened by a signal (EINTR). + */ + break; + } + } + while (priv->irqstate != IRQSTATE_DONE); + + /* Set the interrupt state back to IDLE */ + + priv->irqstate = IRQSTATE_IDLE; + + return ret; +} +#else +static inline int lc823450_i2c_sem_waitdone(FAR struct lc823450_i2c_priv_s *priv) +{ + uint32_t timeout; + systime_t start; + systime_t elapsed; + int ret; + + /* Get the timeout value */ + + timeout = MSEC2TICK(priv->timeoms + (MSEC_PER_TICK / 2)); + timeout += SEC2TICK(CONFIG_LC823450_I2C_TIMEOSEC); + + /* Signal the interrupt handler that we are waiting. NOTE: Interrupts + * are currently disabled but will be temporarily re-enabled below when + * sem_timedwait() sleeps. + */ + + start = clock_systimer(); + + do + { + /* Poll by simply calling the timer interrupt handler until it + * reports that it is done. + */ + + lc823450_i2c_isr(priv); + + /* Calculate the elapsed time */ + + elapsed = clock_systimer() - start; + + } + while (priv->irqstate != IRQSTATE_DONE && elapsed < timeout); + + i2cvdbg("irqstate: %d elapsed: %d threshold: %d status: %08x\n", + priv->irqstate, elapsed, timeout); + + /* Set the interrupt state back to IDLE */ + + ret = priv->irqstate == IRQSTATE_DONE ? OK : -ETIMEDOUT; + priv->irqstate = IRQSTATE_IDLE; + return ret; +} +#endif + +/**************************************************************************** + * Name: lc823450_i2c_prepxfer + * + * Description: + * Set the I2C clock and slave address + * + ****************************************************************************/ + +static void lc823450_i2c_prepxfer(FAR struct lc823450_i2c_priv_s *priv) +{ + uint32_t base = priv->config->base; + putreg32(((lc823450_get_systemfreq() / priv->msgv->frequency + 7) / 8) & 0xffff, base + I2CCKS); + putreg32((priv->msgv->addr << 1) | (priv->msgv->flags & I2C_M_READ), base + I2CTXD); +} + +/**************************************************************************** + * Name: lc823450_i2c_checkbusy + * + * Description: + * Check if I2C bus is busy. Return true if I2C bus is busy. + * + ****************************************************************************/ + +static inline bool lc823450_i2c_checkbusy(FAR struct lc823450_i2c_priv_s *priv) +{ + return (getreg32(priv->config->base + I2CSTR) & I2C_STR_BBSY) != 0; +} + +/**************************************************************************** + * Name: lc823450_i2c_checkirq + * + * Description: + * Check if interrupt occurred. Return true if irq occurs. + * + ****************************************************************************/ + +static inline bool lc823450_i2c_checkirq(FAR struct lc823450_i2c_priv_s *priv) +{ + return (getreg32(priv->config->base + I2CSTR) & I2C_STR_IREQ) != 0; +} + +/**************************************************************************** + * Name: lc823450_i2c_checkack + * + * Description: + * Check if ACK detected. Return true if ACK detected. + * + ****************************************************************************/ + +static inline bool lc823450_i2c_checkack(FAR struct lc823450_i2c_priv_s *priv) +{ + return (getreg32(priv->config->base + I2CSTR) & I2C_STR_ACKD) != 0; +} + +/**************************************************************************** + * Name: lc823450_i2c_sendstart + * + * Description: + * Send the START condition + * + ****************************************************************************/ + +static inline void lc823450_i2c_sendstart(FAR struct lc823450_i2c_priv_s *priv) +{ + modifyreg32(priv->config->base + I2CCTL, I2C_CTL_TRX, I2C_CTL_TRX); + modifyreg32(priv->config->base + I2CCTL, I2C_CTL_ST, I2C_CTL_ST); +} + +/**************************************************************************** + * Name: lc823450_i2c_sendstop + * + * Description: + * Send the STOP condition + * + ****************************************************************************/ + +static inline void lc823450_i2c_sendstop(FAR struct lc823450_i2c_priv_s *priv) +{ + modifyreg32(priv->config->base + I2CSTR, I2C_STR_IREQ, 0); + modifyreg32(priv->config->base + I2CCTL, I2C_CTL_TRX, I2C_CTL_TRX); + modifyreg32(priv->config->base + I2CCTL, I2C_CTL_ST, 0); +} + +/**************************************************************************** + * Name: lc823450_i2c_clrstop + * + * Description: + * Clear the STOP condition + * + ****************************************************************************/ + +static inline void lc823450_i2c_clrstop(FAR struct lc823450_i2c_priv_s *priv) +{ + modifyreg32(priv->config->base + I2CSTR, I2C_STR_IREQ, 0); +} + +/**************************************************************************** + * Name: lc823450_i2c_reset + * + * Description: + * Reset the I2C peripheral + * + ****************************************************************************/ + +#ifdef CONFIG_I2C_RESET +static int lc823450_i2c_reset(FAR struct i2c_master_s *dev) +{ + FAR struct lc823450_i2c_priv_s *priv = (struct lc823450_i2c_priv_s *)dev; + + modifyreg32(priv->config->base + I2CCTL, I2C_CTL_SRST, I2C_CTL_SRST); + modifyreg32(priv->config->base + I2CCTL, I2C_CTL_IREQEN, 0); + modifyreg32(priv->config->base + I2CCTL, I2C_CTL_FMODE, I2C_CTL_FMODE); + return OK; +} +#endif /* CONFIG_I2C_RESET */ + +/**************************************************************************** + * Name: lc823450_i2c_enableirq + * + * Description: + * Enable I2C interrupt + * + ****************************************************************************/ + +#ifndef CONFIG_I2C_POLLED +static inline void lc823450_i2c_enableirq(FAR struct lc823450_i2c_priv_s *priv) +{ + modifyreg32(priv->config->base + I2CCTL, I2C_CTL_IREQEN, I2C_CTL_IREQEN); +} +#endif + +/**************************************************************************** + * Name: lc823450_i2c_disableirq + * + * Description: + * Disable I2C interrupt + * + ****************************************************************************/ + +#ifndef CONFIG_I2C_POLLED +static inline void lc823450_i2c_disableirq(FAR struct lc823450_i2c_priv_s *priv) +{ + modifyreg32(priv->config->base + I2CCTL, I2C_CTL_IREQEN, 0); +} +#endif + +/**************************************************************************** + * Name: lc823450_i2c_readdata + * + * Description: + * Get data received from transmitter. + * + ****************************************************************************/ + +static inline uint32_t lc823450_i2c_readdata(FAR struct lc823450_i2c_priv_s *priv) +{ + return getreg32(priv->config->base + I2CRXD); +} + +/**************************************************************************** + * Name: lc823450_i2c_starttransfer + * + * Description: + * Start read or write request + * + ****************************************************************************/ + +static void lc823450_i2c_sendnack(FAR struct lc823450_i2c_priv_s *priv) +{ + modifyreg32(priv->config->base + I2CCTL, I2C_CTL_ACK, 0); + modifyreg32(priv->config->base + I2CCTL, I2C_CTL_BTRIG, I2C_CTL_BTRIG); +} + +static void lc823450_i2c_starttransfer(FAR struct lc823450_i2c_priv_s *priv) +{ + if (priv->flags & I2C_M_READ) + { + if (priv->dcnt > 1) + { + /* If the next byte to be received is not final, we have to send ACK. */ + + modifyreg32(priv->config->base + I2CCTL, I2C_CTL_ACK, I2C_CTL_ACK); + modifyreg32(priv->config->base + I2CCTL, I2C_CTL_BTRIG, I2C_CTL_BTRIG); + } + else if (priv->dcnt == 1) + { + /* otherwise, we don't have to send ACK when receiving it. */ + + if (priv->msgc > 0 && priv->msgv->flags & I2C_M_READ) + { + + /* But if there is a next message and the direction is READ, we have + * to send ACK. + */ + + modifyreg32(priv->config->base + I2CCTL, I2C_CTL_ACK, I2C_CTL_ACK); + } + else + { + modifyreg32(priv->config->base + I2CCTL, I2C_CTL_ACK, 0); + } + + modifyreg32(priv->config->base + I2CCTL, I2C_CTL_BTRIG, I2C_CTL_BTRIG); + } + + priv->irqstate = IRQSTATE_WRECV; + } + else + { + if (priv->dcnt > 0) + { + putreg32(*priv->ptr, priv->config->base + I2CTXD); + modifyreg32(priv->config->base + I2CCTL, I2C_CTL_BTRIG, I2C_CTL_BTRIG); + } + priv->irqstate = IRQSTATE_WSEND; + } +} + +/**************************************************************************** + * Name: lc823450_i2c_isr + * + * Description: + * Common Interrupt Service Routine + * + ****************************************************************************/ + +static int lc823450_i2c_isr(FAR struct lc823450_i2c_priv_s *priv) +{ + bool ack; + + if (! lc823450_i2c_checkirq(priv)) + { + return OK; + } + + ack = lc823450_i2c_checkack(priv); + + /* Clear irq status */ + + modifyreg32(priv->config->base + I2CSTR, I2C_STR_IREQ, 0); + + if (priv->timedout) + { + uint16_t flags = priv->msgv ? priv->msgv->flags : priv->flags; + + priv->dcnt = 0; + priv->msgc = 0; + + if (flags & I2C_M_READ) + { + /* When READ transaction, terminate it with NACK and then STOP condition */ + + lc823450_i2c_sendnack(priv); + } + else + { + /* When WRITE transaction, do STOP condition */ + + priv->msgv = NULL; + priv->irqstate = IRQSTATE_WSTOP; + + lc823450_i2c_sendstop(priv); + } + + priv->timedout = false; + + return OK; + } + + if (priv->irqstate == IRQSTATE_WSTART) + { + if (ack) + { + /* Wait until START condition is complete. */ + + if (priv->msgv->length > 0) + { + priv->ptr = priv->msgv->buffer; + priv->dcnt = priv->msgv->length; + priv->flags = priv->msgv->flags; + + priv->msgv++; + priv->msgc--; + i2cllvdbg("WSTART (dcnt=%d flags=%xh msgc=%d)\n", priv->dcnt, priv->flags, priv->msgc); + + lc823450_i2c_starttransfer(priv); + } + } + } + else if (priv->irqstate == IRQSTATE_WSEND) + { + /* Wait until ACK for the request to send is detected. */ + + if (ack) + { + priv->ptr++; + priv->dcnt--; + i2cllvdbg("WSEND (dcnt=%d)\n", priv->dcnt); + + lc823450_i2c_starttransfer(priv); + } + } + else if (priv->irqstate == IRQSTATE_WRECV) + { + /* When the master is receiver, it shall send ACK instead of the slave when + * it receives data. In this case, it don't have to check if ACK comes, + * because the slave does not send ACK. + */ + + *priv->ptr++ = lc823450_i2c_readdata(priv); + priv->dcnt--; + i2cllvdbg("WRECV (dcnt=%d)\n", priv->dcnt); + + lc823450_i2c_starttransfer(priv); + } + else if (priv->irqstate == IRQSTATE_WSTOP) + { + /* Wait until STOP condition is requested. */ + + i2cllvdbg("WSTOP\n"); + + lc823450_i2c_clrstop(priv); + + priv->irqstate = IRQSTATE_DONE; + +#ifndef CONFIG_I2C_POLLED + sem_post(&priv->sem_isr); +#endif + } + + /* Check if a I2C message (struct i2c_msg_s) that has been currently + * handled is complete. + */ + + if (priv->dcnt <= 0) + { + /* The current message is complete */ + + i2cllvdbg("message transferred\n"); + + if (priv->msgc > 0) + { + /* There are other messages remaining. */ + + i2cllvdbg("other message remaining (msgc=%d)\n", priv->msgc); + + if (priv->msgv->flags & I2C_M_NORESTART) + { + /* In this case, we don't have to restart using START condition. */ + + i2cllvdbg("no re-START condition\n"); + + if (priv->msgv->length > 0) + { + priv->ptr = priv->msgv->buffer; + priv->dcnt = priv->msgv->length; + priv->flags = priv->msgv->flags; + + priv->msgv++; + priv->msgc--; + + lc823450_i2c_starttransfer(priv); + } + } + else + { + /* We need restart from START conditon. If transfer direction is different + * between current message and next message, restart is necessary. + */ + + i2cllvdbg("re-START condition\n"); + + /* Reset I2C bus by softreset. There is not description of the reset, + * but in order to recover I2C bus busy, it must be done. + * Please refer to macaron's code. + */ + +#ifdef CONFIG_I2C_RESET + lc823450_i2c_reset((FAR struct i2c_master_s *)priv); +#endif + +#ifndef CONFIG_I2C_POLLED + /* We have to enable interrupt again, because all registers are reset by + * lc823450_i2c_reset(). + */ + lc823450_i2c_enableirq(priv); +#endif + + lc823450_i2c_prepxfer(priv); + lc823450_i2c_sendstart(priv); + + priv->irqstate = IRQSTATE_WSTART; + } + } + else if (priv->msgv) + { + /* There are no other message. We send STOP condition because all messages + * are transferred. + */ + + i2cllvdbg("STOP condition\n"); + + lc823450_i2c_sendstop(priv); + + priv->msgv = NULL; + priv->irqstate = IRQSTATE_WSTOP; + } + } + + return OK; +} + +/**************************************************************************** + * Name: lc823450_i2c_isr + * + * Description: + * Interrupt Service Routine + * + ****************************************************************************/ + +#ifndef CONFIG_I2C_POLLED +#ifdef CONFIG_LC823450_I2C0 +static int lc823450_i2c0_isr(int irq, FAR void *context, FAR void *arg) +{ + return lc823450_i2c_isr(&lc823450_i2c0_priv); +} +#endif +#ifdef CONFIG_LC823450_I2C1 +static int lc823450_i2c1_isr(int irq, FAR void *context, FAR void *arg) +{ + return lc823450_i2c_isr(&lc823450_i2c1_priv); +} +#endif +#endif + +/**************************************************************************** + * Private Initialization and Deinitialization + ****************************************************************************/ + +/**************************************************************************** + * Name: lc823450_i2c_init + * + * Description: + * Setup the I2C hardware, ready for operation with defaults + * + ****************************************************************************/ + +static int lc823450_i2c_init(FAR struct lc823450_i2c_priv_s *priv, int port) +{ + /* Attach ISRs */ + +#ifndef CONFIG_I2C_POLLED + irq_attach(priv->config->irq, priv->config->isr, NULL); + up_enable_irq(priv->config->irq); +#endif + + /* Enable the I2C controller */ + + modifyreg32(MCLKCNTAPB, 0, priv->config->en_bit); + modifyreg32(MRSTCNTAPB, 0, priv->config->en_bit); + + /* I2C port settings */ + + if (port == 0) + { + /* GPIO -> I2C0_SCL, I2C0_SDA */ + + lc823450_gpio_mux(GPIO_I2C0_SCL | GPIO_MUX1); + lc823450_gpio_mux(GPIO_I2C0_SDA | GPIO_MUX1); + +#ifdef CONFIG_LC823450_I2C0_OPENDRAIN + modifyreg32(I2CMODE, I2CMODE0, 0); +#else + /* I2C SCL: PushPull */ + + modifyreg32(I2CMODE, 0, I2CMODE0); +#endif + } +#ifdef CONFIG_LC823450_I2C1 + else if (port == 1) + { + /* GPIO -> I2C1_SCL, I2C1_SDA */ + + lc823450_gpio_mux(GPIO_I2C1_SCL | GPIO_MUX1); + lc823450_gpio_mux(GPIO_I2C1_SDA | GPIO_MUX1); + +#ifdef CONFIG_LC823450_I2C1_OPENDRAIN + modifyreg32(I2CMODE, I2CMODE1, 0); +#else + /* I2C SCL: PushPull */ + + modifyreg32(I2CMODE, 0, I2CMODE1); +#endif + } +#endif + + return OK; +} + +/**************************************************************************** + * Name: lc823450_i2c_deinit + * + * Description: + * Shutdown the I2C hardware + * + ****************************************************************************/ + +static int lc823450_i2c_deinit(FAR struct lc823450_i2c_priv_s *priv, int port) +{ + /* Disable I2C */ + + modifyreg32(priv->config->base + I2CSTR, I2C_STR_IREQ, 0); + modifyreg32(priv->config->base + I2CSTR, I2C_CTL_SCLR, I2C_CTL_SCLR); + modifyreg32(priv->config->base + I2CCTL, I2C_CTL_SRST, I2C_CTL_SRST); + + /* Change pinmux from I2C to GPIO, and i2c mode to Push-Pull to Open Drain */ + + if (port == 0) + { + /* I2C0_SCL -> GPIO(output,low) */ + + lc823450_gpio_mux(GPIO_I2C0_SCL | GPIO_MUX0); + lc823450_gpio_config(GPIO_I2C0_SCL); + modifyreg32(I2CMODE, I2CMODE0, 0); + + /* I2C0_SDA -> GPIO(output,low) */ + + lc823450_gpio_mux(GPIO_I2C0_SDA | GPIO_MUX0); + lc823450_gpio_config(GPIO_I2C0_SDA); + } +#ifdef CONFIG_LC823450_I2C1 + else if (port == 1) + { + /* I2C1_SCL -> GPIO(output,low) */ + + lc823450_gpio_mux(GPIO_I2C1_SCL | GPIO_MUX0); + lc823450_gpio_config(GPIO_I2C1_SCL); + modifyreg32(I2CMODE, I2CMODE1, 0); + + /* I2C1_SDA -> GPIO(output,low) */ + + lc823450_gpio_mux(GPIO_I2C1_SDA | GPIO_MUX0); + lc823450_gpio_config(GPIO_I2C1_SDA); + } +#endif + + /* Disable the I2C controller */ + + modifyreg32(MCLKCNTAPB, priv->config->en_bit, 0); + modifyreg32(MRSTCNTAPB, priv->config->en_bit, 0); + + /* Disable and detach interrupts */ +#ifndef CONFIG_I2C_POLLED + up_disable_irq(priv->config->irq); + irq_detach(priv->config->irq); +#endif + + return OK; +} + +/**************************************************************************** + * Device Driver Operations + ****************************************************************************/ + + +/**************************************************************************** + * Name: lc823450_i2c_transfer + * + * Description: + * Generic I2C transfer function + * + ****************************************************************************/ + +static int lc823450_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs, + int count) +{ + FAR struct lc823450_i2c_priv_s *priv = (struct lc823450_i2c_priv_s *)dev; + + if (!msgs || count == 0) + { + i2cdbg("invalid param, %p %d\n", msgs, count); + return -EINVAL; + } + + /* ensure that address or flags don't change meanwhile */ + + lc823450_i2c_sem_wait(priv); + + irqstate_t irqs; + int ret = 0; + + ASSERT(count); + + priv->timedout = false; + +#ifdef CONFIG_I2C_RESET + /* Clear I2C peripheral */ + + lc823450_i2c_reset(dev); +#endif + +#ifndef CONFIG_I2C_POLLED + /* Enable I2C interrupt */ + + lc823450_i2c_enableirq(priv); +#endif + + /* Check I2C bus state */ + if (lc823450_i2c_checkbusy(priv)) + { + _err("### ERROR I2C bus busy (dev=%02xh)\n", msgs->addr); + ret = -EBUSY; + goto exit; + } + + priv->msgv = msgs; + priv->msgc = count; + + /* Set the frequency and slave address */ + + lc823450_i2c_prepxfer(priv); + + priv->irqstate = IRQSTATE_WSTART; + + /* Trigger START condition, then the process moves into the ISR. */ + + lc823450_i2c_sendstart(priv); + + /* Wait for an ISR, if there was a timeout, fetch latest status to get + * the BUSY flag. + */ + + if (lc823450_i2c_sem_waitdone(priv) < 0) + { + + irqs = enter_critical_section(); + + ret = -ETIMEDOUT; + + if (priv->dcnt != 0 || priv->msgc != 0) + { + /* If there is remaining data to be transferred, terminate it in + * irq handler. + */ + + priv->timedout = true; + + leave_critical_section(irqs); + + /* Wait for irq handler completion. 10msec wait is probably enough + * to terminate i2c transaction, NACK and STOP contition for read + * transaction, STOP condition for write transaction + */ + + usleep(10 * 1000); + } + else + { + i2cerr("No need of timeout handling. It may be done in irq handler\n"); + + leave_critical_section(irqs); + } + +#ifndef CONFIG_IPL2 + _err("### ERROR I2C timed out (dev=%xh)\n", msgs->addr); +#endif + } + +#ifndef CONFIG_I2C_POLLED + /* Disable I2C interrupt */ + + lc823450_i2c_disableirq(priv); +#endif + +#ifdef CONFIG_I2C_RESET + /* Do SRST if I2C transfer is complete */ + + lc823450_i2c_reset(dev); +#endif + +exit: + lc823450_i2c_sem_post(priv); + + return ret; + +} + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lc823450_i2cbus_initialize + * + * Description: + * Initialize one I2C bus + * + ****************************************************************************/ + +FAR struct i2c_master_s *lc823450_i2cbus_initialize(int port) +{ + FAR struct lc823450_i2c_priv_s *priv = NULL; + irqstate_t flags; + + switch (port) + { +#ifdef CONFIG_LC823450_I2C0 + case 0: + priv = &lc823450_i2c0_priv; + break; +#endif +#ifdef CONFIG_LC823450_I2C1 + case 1: + priv = &lc823450_i2c1_priv; + break; +#endif + default: + ASSERT(false); + return NULL; + } + + /* Init private data for the first time, increment refs count, + * power-up hardware and configure GPIOs. + */ + + flags = enter_critical_section(); + + if ((volatile int)priv->refs++ == 0) + { + sem_init(&priv->sem_excl, 0, 1); +#ifndef CONFIG_I2C_POLLED + sem_init(&priv->sem_isr, 0, 0); +#endif + (void)lc823450_i2c_init(priv, port); + } + + leave_critical_section(flags); + return (struct i2c_master_s *)priv; +} + +/**************************************************************************** + * Name: lc823450_i2cbus_uninitialize + * + * Description: + * Uninitialize an I2C bus + * + ****************************************************************************/ + +int lc823450_i2cbus_uninitialize(FAR struct i2c_master_s *dev) +{ + FAR struct lc823450_i2c_priv_s *priv = (struct lc823450_i2c_priv_s *)dev; + irqstate_t flags; + int port = -1; + + ASSERT(dev); + + /* Decrement refs and check for underflow */ + + if (priv->refs == 0) + { + return OK; + } + + flags = enter_critical_section(); + + if (--priv->refs != 0) + { + leave_critical_section(flags); + return OK; + } + + leave_critical_section(flags); + +#ifdef CONFIG_LC823450_I2C0 + if (priv == &lc823450_i2c0_priv) + { + port = 0; + } +#endif + +#ifdef CONFIG_LC823450_I2C1 + if (priv == &lc823450_i2c1_priv) + { + port = 1; + } +#endif + + if (-1 == port) + { + DEBUGASSERT(0); + return -EFAULT; + } + + /* Disable power and other HW resource */ + + lc823450_i2c_deinit(priv, port); + + /* Release unused resources */ + + sem_destroy(&priv->sem_excl); +#ifndef CONFIG_I2C_POLLED + sem_destroy(&priv->sem_isr); +#endif + + return OK; +} + + +/**************************************************************************** + * Name: lc823450_i2cbus_changetimeout + ****************************************************************************/ + +void lc823450_i2cbus_changetimeout(FAR struct i2c_master_s *dev, uint32_t timeoms) +{ + FAR struct lc823450_i2c_priv_s *priv = (struct lc823450_i2c_priv_s *)dev; + priv->timeoms = timeoms; +} + +#endif /* CONFIG_I2C */ diff --git a/arch/arm/src/lc823450/lc823450_i2c.h b/arch/arm/src/lc823450/lc823450_i2c.h new file mode 100644 index 00000000000..c892db80129 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_i2c.h @@ -0,0 +1,119 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_i2c.h + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Nobutaka Toyoshima + * Author: Masayuki Ishikawa + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_LC823450_LC823450_I2C_H +#define __ARCH_ARM_SRC_LC823450_LC823450_I2C_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Addresses *******************************************************/ + +#define LC823450_I2C0_REGBASE 0x40089000 +#define LC823450_I2C1_REGBASE 0x4008A000 + +#define I2CCTL (0x0) +#define I2CSTR (0x4) +#define I2CTXD (0x8) +#define I2CRXD (0xC) +#define I2CCKS (0x10) + +/* Register Bitfield Definitions ********************************************/ + +/* Control register */ + +#define I2C_CTL_SDAD (1 << 0) /* Bit 0: SDA data output */ +#define I2C_CTL_SCLD (1 << 1) /* Bit 1: SCL data output */ +#define I2C_CTL_BC (1 << 2) /* Bit 2: Control I2C Bus forcely */ +#define I2C_CTL_SCLR (1 << 3) /* Bit 3: Clear internal state */ +#define I2C_CTL_IREQEN (1 << 4) /* Bit 4: Interrupt enable */ +#define I2C_CTL_ACK (1 << 5) /* Bit 5: ACK bit output enable */ +#define I2C_CTL_ST (1 << 6) /* Bit 6: Generate Start/Stop condition */ +#define I2C_CTL_TRX (1 << 7) /* Bit 7: TX or RX enable */ +#define I2C_CTL_SRST (1 << 8) /* Bit 8: Reset all registers */ +#define I2C_CTL_BTRIG (1 << 12) /* Bit 12: Trigger starting byte transfer/receive */ +#define I2C_CTL_FMODE (1 << 15) /* Bit 15: Fast or Standard mode enable */ + +/* Status register */ + +#define I2C_STR_SDAB (1 << 0) /* Bit 0: Monitor SDA pin */ +#define I2C_STR_SCLB (1 << 1) /* Bit 1: Monitor SCL pin */ +#define I2C_STR_ACKD (1 << 5) /* Bit 5: ACK detection */ +#define I2C_STR_IREQ (1 << 6) /* Bit 6: Interrupt status */ +#define I2C_STR_BBSY (1 << 7) /* Bit 7: Bus busy */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +FAR struct i2c_master_s *lc823450_i2cbus_initialize(int port); +int lc823450_i2cbus_uninitialize(FAR struct i2c_master_s *dev); +void lc823450_i2cbus_changetimeout(FAR struct i2c_master_s *dev, uint32_t timeoms); + +#if defined(__cplusplus) +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_LC823450_LC823450_I2C_H */ diff --git a/arch/arm/src/lc823450/lc823450_idle.c b/arch/arm/src/lc823450/lc823450_idle.c new file mode 100644 index 00000000000..bfe85a82e6a --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_idle.c @@ -0,0 +1,164 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_idle.c + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masayuki Ishikawa + * Author: Masatoshi Tateishi + * + * 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 "nvic.h" +#include "up_internal.h" +#include "up_arch.h" + +#ifdef CONFIG_DVFS +# include "lc823450_dvfs.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_LC823450_SLEEP_MODE +static int32_t g_in_sleep; +static uint64_t g_sleep_t0; +#endif /* CONFIG_LC823450_SLEEP_MODE */ + + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_get_current_time() + ****************************************************************************/ + +#ifdef CONFIG_LC823450_SLEEP_MODE +static uint64_t up_get_current_time(void) +{ + struct timespec ts; + +#ifdef CONFIG_CLOCK_MONOTONIC + clock_gettime(CLOCK_MONOTONIC, &ts); +#else + clock_gettime(CLOCK_REALTIME, &ts); +#endif + return (uint64_t)ts.tv_sec * NSEC_PER_SEC + (uint64_t)ts.tv_nsec; +} +#endif /* CONFIG_LC823450_SLEEP_MODE */ + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_idle + * + * Description: + * up_idle() is the logic that will be executed when their is no other + * ready-to-run task. This is processor idle time and will continue until + * some interrupt occurs to cause a context switch from the idle task. + * + * Processing in this state may be processor-specific. e.g., this is where + * power management operations might be performed. + * + ****************************************************************************/ + +void up_idle(void) +{ +#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_TIMER_INTS) + /* If the system is idle and there are no timer interrupts, then process + * "fake" timer interrupts. Hopefully, something will wake up. + */ + + sched_process_timer(); +#else + +#ifdef CONFIG_LC823450_SLEEP_MODE + irqstate_t flags; + flags = enter_critical_section(); + + g_sleep_t0 = up_get_current_time(); + g_in_sleep = 1; + + /* Clear SLEEPDEEP flag */ + + uint32_t regval = getreg32(NVIC_SYSCON); + regval &= ~NVIC_SYSCON_SLEEPDEEP; + putreg32(regval, NVIC_SYSCON); + +#ifdef CONFIG_DVFS + lc823450_dvfs_enter_idle(); +#endif + + leave_critical_section(flags); +#endif /* CONFIG_LC823450_SLEEP_MODE */ + + /* Sleep until an interrupt occurs to save power */ + + asm("WFI"); + +#endif +} + +/**************************************************************************** + * Name: up_update_idle_time() + * + * Description: + * up_update_idle_time() is the logic that will update idle time + * + ****************************************************************************/ + +#ifdef CONFIG_LC823450_SLEEP_MODE +void up_update_idle_time(void) +{ + if (g_in_sleep) + { + g_in_sleep = 0; + uint64_t t1 = up_get_current_time(); + sched_add_idl_tm(t1 - g_sleep_t0); + } +} +#endif /* CONFIG_LC823450_SLEEP_MODE */ diff --git a/arch/arm/src/lc823450/lc823450_intc.h b/arch/arm/src/lc823450/lc823450_intc.h new file mode 100644 index 00000000000..6186e14c7b0 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_intc.h @@ -0,0 +1,119 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_intc.h + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Nobutaka Toyoshima + * Author: Masatoshi Tateishi + * + * 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. + * + ****************************************************************************/ + + +#ifndef __ARCH_ARM_SRC_LC823450_LC823450_INTC_H +#define __ARCH_ARM_SRC_LC823450_LC823450_INTC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + + +#define LC823450_INTC_REGBASE 0x40003000 + +#define IPIREG (LC823450_INTC_REGBASE + 0x000) +#define IPIREG_INTISR0_0 (0x1 << 0) +#define IPIREG_INTISR0_1 (0x1 << 1) +#define IPIREG_INTISR0_2 (0x1 << 2) +#define IPIREG_INTISR0_3 (0x1 << 3) +#define IPIREG_INTISR1_0 (0x1 << 8) +#define IPIREG_INTISR1_1 (0x1 << 9) +#define IPIREG_INTISR1_2 (0x1 << 10) +#define IPIREG_INTISR1_3 (0x1 << 11) +#define IPICLR (LC823450_INTC_REGBASE + 0x004) +#define IPICLR_INTISR0_CLR_0 (0x1 << 0) +#define IPICLR_INTISR0_CLR_1 (0x1 << 1) +#define IPICLR_INTISR0_CLR_2 (0x1 << 2) +#define IPICLR_INTISR0_CLR_3 (0x1 << 3) +#define IPICLR_INTISR1_CLR_0 (0x1 << 8) +#define IPICLR_INTISR1_CLR_1 (0x1 << 9) +#define IPICLR_INTISR1_CLR_2 (0x1 << 10) +#define IPICLR_INTISR1_CLR_3 (0x1 << 11) + +#define EXTINTn_BASE (LC823450_INTC_REGBASE + 0x400) +#define EXTINTnS_BASE (LC823450_INTC_REGBASE + 0x418) +#define EXTINTnM_BASE (LC823450_INTC_REGBASE + 0x430) +#define EXTINTnC0_BASE (LC823450_INTC_REGBASE + 0x448) +#define EXTINTnC1_BASE (LC823450_INTC_REGBASE + 0x460) +#define EXTINTnCND_BASE (LC823450_INTC_REGBASE + 0x478) +#define EXTINTnCLR_BASE (LC823450_INTC_REGBASE + 0x490) +#define EXTINTnFEN_BASE (LC823450_INTC_REGBASE + 0x4A8) +#define EXTINTnSET_BASE (LC823450_INTC_REGBASE + 0x4C0) + +#define INTC_REG(base,port) ((base) + 4 * (port)) + + + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + + +#if defined(__cplusplus) +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_LC823450_LC823450_INTC_H */ diff --git a/arch/arm/src/lc823450/lc823450_irq.c b/arch/arm/src/lc823450/lc823450_irq.c new file mode 100644 index 00000000000..9381b18995c --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_irq.c @@ -0,0 +1,832 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_irq.c + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * Author: Nobutaka Toyoshima + * + * 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 "nvic.h" +#include "ram_vectors.h" +#include "up_arch.h" +#include "up_internal.h" +#include "chip.h" +#include "lc823450_intc.h" + +#ifdef CONFIG_DVFS +# include "lc823450_dvfs.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + + +/* Get a 32-bit version of the default priority */ + +#define DEFPRIORITY32 \ + (NVIC_SYSH_PRIORITY_DEFAULT << 24 | \ + NVIC_SYSH_PRIORITY_DEFAULT << 16 | \ + NVIC_SYSH_PRIORITY_DEFAULT << 8 | \ + NVIC_SYSH_PRIORITY_DEFAULT) + +/* Given the address of a NVIC ENABLE register, this is the offset to + * the corresponding CLEAR ENABLE register. + */ + +#define NVIC_ENA_OFFSET (0) +#define NVIC_CLRENA_OFFSET (NVIC_IRQ0_31_CLEAR - NVIC_IRQ0_31_ENABLE) + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef CONFIG_SMP +/* For the case of configurations with multiple CPUs, then there must be one + * such value for each processor that can receive an interrupt. + */ + +volatile uint32_t *g_current_regs[CONFIG_SMP_NCPUS]; +#else +volatile uint32_t *g_current_regs[1]; +#endif + + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_LC823450_VIRQ +static struct lc823450_irq_ops *virq_ops[LC823450_IRQ_NVIRTUALIRQS]; +#endif /* CONFIG_LC823450_VIRQ */ + + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +volatile uint32_t *current_regs; + + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lc823450_dumpnvic + * + * Description: + * Dump some interesting NVIC registers + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG_IRQ) +static void lc823450_dumpnvic(const char *msg, int irq) +{ + irqstate_t flags; + + flags = enter_critical_section(); + _info("NVIC (%s, irq=%d):\n", msg, irq); + _info(" INTCTRL: %08x VECTAB: %08x\n", + getreg32(NVIC_INTCTRL), getreg32(NVIC_VECTAB)); +#if 0 + _info(" SYSH ENABLE MEMFAULT: %08x BUSFAULT: %08x USGFAULT: %08x SYSTICK: %08x\n", + getreg32(NVIC_SYSHCON_MEMFAULTENA), getreg32(NVIC_SYSHCON_BUSFAULTENA), + getreg32(NVIC_SYSHCON_USGFAULTENA), getreg32(NVIC_SYSTICK_CTRL_ENABLE)); +#endif + _info(" IRQ ENABLE: %08x %08x %08x\n", + getreg32(NVIC_IRQ0_31_ENABLE), getreg32(NVIC_IRQ32_63_ENABLE), + getreg32(NVIC_IRQ64_95_ENABLE)); + _info(" SYSH_PRIO: %08x %08x %08x\n", + getreg32(NVIC_SYSH4_7_PRIORITY), getreg32(NVIC_SYSH8_11_PRIORITY), + getreg32(NVIC_SYSH12_15_PRIORITY)); + _info(" IRQ PRIO: %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ0_3_PRIORITY), getreg32(NVIC_IRQ4_7_PRIORITY), + getreg32(NVIC_IRQ8_11_PRIORITY), getreg32(NVIC_IRQ12_15_PRIORITY)); + _info(" %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ16_19_PRIORITY), getreg32(NVIC_IRQ20_23_PRIORITY), + getreg32(NVIC_IRQ24_27_PRIORITY), getreg32(NVIC_IRQ28_31_PRIORITY)); + _info(" %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ32_35_PRIORITY), getreg32(NVIC_IRQ36_39_PRIORITY), + getreg32(NVIC_IRQ40_43_PRIORITY), getreg32(NVIC_IRQ44_47_PRIORITY)); + _info(" %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ48_51_PRIORITY), getreg32(NVIC_IRQ52_55_PRIORITY), + getreg32(NVIC_IRQ56_59_PRIORITY), getreg32(NVIC_IRQ60_63_PRIORITY)); + _info(" %08x\n", + getreg32(NVIC_IRQ64_67_PRIORITY)); + leave_critical_section(flags); +} +#else +# define lc823450_dumpnvic(msg, irq) +#endif + +/**************************************************************************** + * Name: lc823450_nmi, lc823450_busfault, lc823450_usagefault, lc823450_pendsv, + * lc823450_dbgmonitor, lc823450_pendsv, lc823450_reserved + * + * Description: + * Handlers for various execptions. None are handled and all are fatal + * error conditions. The only advantage these provided over the default + * unexpected interrupt handler is that they provide a diagnostic output. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG +static int lc823450_nmi(int irq, FAR void *context, FAR void *arg) +{ + (void)enter_critical_section(); + _info("PANIC!!! NMI received\n"); + PANIC(); + return 0; +} + +static int lc823450_busfault(int irq, FAR void *context, FAR void *arg) +{ + (void)enter_critical_section(); + _info("PANIC!!! Bus fault received: %08x\n", getreg32(NVIC_CFAULTS)); + PANIC(); + return 0; +} + +static int lc823450_usagefault(int irq, FAR void *context, FAR void *arg) +{ + (void)enter_critical_section(); + _info("PANIC!!! Usage fault received: %08x\n", getreg32(NVIC_CFAULTS)); + PANIC(); + return 0; +} + +static int lc823450_pendsv(int irq, FAR void *context, FAR void *arg) +{ + (void)enter_critical_section(); + _info("PANIC!!! PendSV received\n"); + PANIC(); + return 0; +} + +static int lc823450_dbgmonitor(int irq, FAR void *context, FAR void *arg) +{ + (void)enter_critical_section(); + _info("PANIC!!! Debug Monitor receieved\n"); + PANIC(); + return 0; +} + +static int lc823450_reserved(int irq, FAR void *context, FAR void *arg) +{ + (void)enter_critical_section(); + _info("PANIC!!! Reserved interrupt\n"); + PANIC(); + return 0; +} +#endif + +/**************************************************************************** + * Name: lc823450_prioritize_syscall + * + * Description: + * Set the priority of an exception. This function may be needed + * internally even if support for prioritized interrupts is not enabled. + * + ****************************************************************************/ + +#ifdef CONFIG_ARMV7M_USEBASEPRI +static inline void lc823450_prioritize_syscall(int priority) +{ + uint32_t regval; + + /* SVCALL is system handler 11 */ + + regval = getreg32(NVIC_SYSH8_11_PRIORITY); + regval &= ~NVIC_SYSH_PRIORITY_PR11_MASK; + regval |= (priority << NVIC_SYSH_PRIORITY_PR11_SHIFT); + putreg32(regval, NVIC_SYSH8_11_PRIORITY); +} +#endif + +/*********************************************************************** + * Name: lc823450_extint_clr + * + * Description: + * clear irq factor + * + ***********************************************************************/ + +static void lc823450_extint_clr(int irq) +{ + uint32_t regaddr; + int port; + int pin; + + DEBUGASSERT(irq >= LC823450_IRQ_GPIO00 && irq <= LC823450_IRQ_GPIO59); + + irq -= LC823450_IRQ_GPIO00; + + port = (irq & 0x70) >> 4; + pin = irq & 0xf; + + regaddr = INTC_REG(EXTINTnCLR_BASE, port); + putreg32(1 << pin, regaddr); + + return; +} + +/*********************************************************************** + * Name: lc823450_extint_isr + * + * Description: + * Handle external interrupt. + * + ***********************************************************************/ + +static int lc823450_extint_isr(int irq, FAR void *context, FAR void *arg) +{ + uint32_t regaddr; + uint32_t pending; + int port; + + DEBUGASSERT(irq >= LC823450_IRQ_EXTINT0 && irq <= LC823450_IRQ_EXTINT5); + + port = irq - LC823450_IRQ_EXTINT0; + + /* Read irq factor */ + + regaddr = INTC_REG(EXTINTn_BASE, port); + pending = getreg32(regaddr); + + /* Clear irq factor */ + + regaddr = INTC_REG(EXTINTnCLR_BASE, port); + putreg32(pending, regaddr); + + irq = LC823450_IRQ_GPIO00 + (port * 0x10); + + /* Re-deliver the IRQ */ + + for ( ; pending != 0; irq++, pending >>= 1) + { + if ((pending & 1) != 0) + { + irq_dispatch(irq, context); + } + } + + return OK; +} + +/*********************************************************************** + * Name: lc823425_extint_initialize + * + * Description: + * Initialize external interrup. + * + ***********************************************************************/ + +static void lc823450_extint_initialize(void) +{ + int ret; + + ret = irq_attach(LC823450_IRQ_EXTINT0, lc823450_extint_isr, NULL); + DEBUGASSERT(ret == OK); + + ret = irq_attach(LC823450_IRQ_EXTINT1, lc823450_extint_isr, NULL); + DEBUGASSERT(ret == OK); + + ret = irq_attach(LC823450_IRQ_EXTINT2, lc823450_extint_isr, NULL); + DEBUGASSERT(ret == OK); + + ret = irq_attach(LC823450_IRQ_EXTINT3, lc823450_extint_isr, NULL); + DEBUGASSERT(ret == OK); + + ret = irq_attach(LC823450_IRQ_EXTINT4, lc823450_extint_isr, NULL); + DEBUGASSERT(ret == OK); + + ret = irq_attach(LC823450_IRQ_EXTINT5, lc823450_extint_isr, NULL); + DEBUGASSERT(ret == OK); + + up_enable_irq(LC823450_IRQ_EXTINT0); + up_enable_irq(LC823450_IRQ_EXTINT1); + up_enable_irq(LC823450_IRQ_EXTINT2); + up_enable_irq(LC823450_IRQ_EXTINT3); + up_enable_irq(LC823450_IRQ_EXTINT4); + up_enable_irq(LC823450_IRQ_EXTINT5); +} + +/**************************************************************************** + * Name: lc823450_irqinfo + * + * Description: + * Given an IRQ number, provide the register and bit setting to enable or + * disable the irq. + * + ****************************************************************************/ + +static int lc823450_irqinfo(int irq, uintptr_t *regaddr, uint32_t *bit, + uintptr_t offset) +{ + DEBUGASSERT(irq >= LC823450_IRQ_NMI && irq < NR_IRQS); + + /* Check for external interrupt */ + + if (irq >= LC823450_IRQ_NIRQS) + { + int port = ((irq - LC823450_IRQ_GPIO00) & 0x70) >> 4; + + *regaddr = INTC_REG(EXTINTnM_BASE, port); + *bit = 1 << ((irq - LC823450_IRQ_GPIO00) & 0xf); + } + else if (irq >= LC823450_IRQ_INTERRUPTS) + { + if (irq < LC823450_IRQ_INTERRUPTS + 32) + { + *regaddr = (NVIC_IRQ0_31_ENABLE + offset); + *bit = 1 << (irq - LC823450_IRQ_INTERRUPTS); + } + else if (irq < LC823450_IRQ_INTERRUPTS + 64) + { + *regaddr = (NVIC_IRQ32_63_ENABLE + offset); + *bit = 1 << (irq - LC823450_IRQ_INTERRUPTS - 32); + } + else if (irq < NR_IRQS) + { + *regaddr = (NVIC_IRQ64_95_ENABLE + offset); + *bit = 1 << (irq - LC823450_IRQ_INTERRUPTS - 64); + } + else + { + return ERROR; /* Invalid interrupt */ + } + } + + /* Handle processor exceptions. Only a few can be disabled */ + + else + { + *regaddr = NVIC_SYSHCON; + if (irq == LC823450_IRQ_MEMFAULT) + { + *bit = NVIC_SYSHCON_MEMFAULTENA; + } + else if (irq == LC823450_IRQ_BUSFAULT) + { + *bit = NVIC_SYSHCON_BUSFAULTENA; + } + else if (irq == LC823450_IRQ_USAGEFAULT) + { + *bit = NVIC_SYSHCON_USGFAULTENA; + } + else if (irq == LC823450_IRQ_SYSTICK) + { + *regaddr = NVIC_SYSTICK_CTRL; + *bit = NVIC_SYSTICK_CTRL_ENABLE; + } + else + { + return ERROR; /* Invalid or unsupported exception */ + } + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_irqinitialize + ****************************************************************************/ + +void up_irqinitialize(void) +{ + uint32_t regaddr; + int num_priority_registers; + + /* Disable all interrupts */ + + putreg32(0, NVIC_IRQ0_31_ENABLE); + putreg32(0, NVIC_IRQ32_63_ENABLE); + + /* Colorize the interrupt stack for debug purposes */ + +#if defined(CONFIG_STACK_COLORATION) && CONFIG_ARCH_INTERRUPTSTACK > 3 + { + size_t intstack_size = (CONFIG_ARCH_INTERRUPTSTACK & ~3); + up_stack_color((FAR void *)((uintptr_t)&g_intstackbase - intstack_size), + intstack_size); + } +#endif + + /* The standard location for the vector table is at the beginning of FLASH + * at address 0x0800:0000. If we are using the STMicro DFU bootloader, then + * the vector table will be offset to a different location in FLASH and we + * will need to set the NVIC vector location to this alternative location. + * + * If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based + * vector table that requires special initialization. + */ + +#if defined(CONFIG_ARCH_RAMVECTORS) + up_ramvec_initialize(); +#elif defined(CONFIG_LC823450_DFU) + putreg32((uint32_t)_vectors, NVIC_VECTAB); +#endif + + /* Set all interrupts (and exceptions) to the default priority */ + + putreg32(DEFPRIORITY32, NVIC_SYSH4_7_PRIORITY); + putreg32(DEFPRIORITY32, NVIC_SYSH8_11_PRIORITY); + putreg32(DEFPRIORITY32, NVIC_SYSH12_15_PRIORITY); + + /* The NVIC ICTR register (bits 0-4) holds the number of of interrupt + * lines that the NVIC supports: + * + * 0 -> 32 interrupt lines, 8 priority registers + * 1 -> 64 " " " ", 16 priority registers + * 2 -> 96 " " " ", 32 priority registers + * ... + */ + + num_priority_registers = (getreg32(NVIC_ICTR) + 1) * 8; + + /* Now set all of the interrupt lines to the default priority */ + + regaddr = NVIC_IRQ0_3_PRIORITY; + while (num_priority_registers--) + { + putreg32(DEFPRIORITY32, regaddr); + regaddr += 4; + } + + /* currents_regs is non-NULL only while processing an interrupt */ + + CURRENT_REGS = NULL; + + /* Attach the SVCall and Hard Fault exception handlers. The SVCall + * exception is used for performing context switches; The Hard Fault + * must also be caught because a SVCall may show up as a Hard Fault + * under certain conditions. + */ + + irq_attach(LC823450_IRQ_SVCALL, up_svcall, NULL); + irq_attach(LC823450_IRQ_HARDFAULT, up_hardfault, NULL); + + /* Set the priority of the SVCall interrupt */ + +#ifdef CONFIG_ARCH_IRQPRIO +/* up_prioritize_irq(LC823450_IRQ_PENDSV, NVIC_SYSH_PRIORITY_MIN); */ +#endif +#ifdef CONFIG_ARMV7M_USEBASEPRI + lc823450_prioritize_syscall(NVIC_SYSH_SVCALL_PRIORITY); +#endif + + /* If the MPU is enabled, then attach and enable the Memory Management + * Fault handler. + */ + +#ifdef CONFIG_ARMV7M_MPU + irq_attach(LC823450_IRQ_MEMFAULT, up_memfault, NULL); + up_enable_irq(LC823450_IRQ_MEMFAULT); +#endif + + /* Attach all other processor exceptions (except reset and sys tick) */ + +#ifdef CONFIG_DEBUG + irq_attach(LC823450_IRQ_NMI, lc823450_nmi, NULL); +#ifndef CONFIG_ARMV7M_MPU + irq_attach(LC823450_IRQ_MEMFAULT, up_memfault, NULL); +#endif + irq_attach(LC823450_IRQ_BUSFAULT, lc823450_busfault, NULL); + irq_attach(LC823450_IRQ_USAGEFAULT, lc823450_usagefault, NULL); + irq_attach(LC823450_IRQ_PENDSV, lc823450_pendsv, NULL); + irq_attach(LC823450_IRQ_DBGMONITOR, lc823450_dbgmonitor, NULL); + irq_attach(LC823450_IRQ_RESERVED, lc823450_reserved, NULL); +#endif + + /* Initialize external interrupt. */ + + lc823450_extint_initialize(); + + lc823450_dumpnvic("initial", NR_IRQS); + +#define NVIC_CFGCON_DIV_0_TRP (1 << 4) + modifyreg32(NVIC_CFGCON, 0, NVIC_CFGCON_DIV_0_TRP); + +#ifndef CONFIG_SUPPRESS_INTERRUPTS + + /* And finally, enable interrupts */ + + up_irq_enable(); +#endif +} + +/**************************************************************************** + * Name: up_disable_irq + * + * Description: + * Disable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_disable_irq(int irq) +{ + uintptr_t regaddr; + uint32_t regval; + uint32_t bit; + +#ifdef CONFIG_LC823450_VIRQ + if (irq >= LC823450_IRQ_VIRTUAL && + irq < LC823450_IRQ_VIRTUAL + LC823450_IRQ_NVIRTUALIRQS) + { + struct lc823450_irq_ops *ops; + ops = virq_ops[irq - LC823450_IRQ_VIRTUAL]; + if (ops && ops->disable) + { + ops->disable(irq); + } + return; + } +#endif /* CONFIG_LC823450_VIRQ */ + + if (lc823450_irqinfo(irq, ®addr, &bit, NVIC_CLRENA_OFFSET) == 0) + { + /* Modify the appropriate bit in the register to disable the interrupt. + * For normal interrupts, we need to set the bit in the associated + * Interrupt Clear Enable register. For other exceptions, we need to + * clear the bit in the System Handler Control and State Register. + */ + + if (irq >= LC823450_IRQ_NIRQS) + { + regval = getreg32(regaddr); + regval |= bit; + putreg32(regval, regaddr); + } + else if (irq >= LC823450_IRQ_INTERRUPTS) + { + putreg32(bit, regaddr); + } + else + { + regval = getreg32(regaddr); + regval &= ~bit; + putreg32(regval, regaddr); + } + } + + /* lc823450_dumpnvic("disable", irq); */ +} + +/**************************************************************************** + * Name: up_enable_irq + * + * Description: + * Enable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_enable_irq(int irq) +{ + uintptr_t regaddr; + uint32_t regval; + uint32_t bit; + +#ifdef CONFIG_LC823450_VIRQ + if (irq >= LC823450_IRQ_VIRTUAL && + irq < LC823450_IRQ_VIRTUAL + LC823450_IRQ_NVIRTUALIRQS) + { + struct lc823450_irq_ops *ops; + ops = virq_ops[irq - LC823450_IRQ_VIRTUAL]; + if (ops && ops->enable) + { + ops->enable(irq); + } + return; + } +#endif /* CONFIG_LC823450_VIRQ */ + + if (lc823450_irqinfo(irq, ®addr, &bit, NVIC_ENA_OFFSET) == 0) + { + /* Modify the appropriate bit in the register to enable the interrupt. + * For normal interrupts, we need to set the bit in the associated + * Interrupt Set Enable register. For other exceptions, we need to + * set the bit in the System Handler Control and State Register. + */ + + if (irq >= LC823450_IRQ_NIRQS) + { + /* Clear already asserted IRQ */ + + lc823450_extint_clr(irq); + + regval = getreg32(regaddr); + regval &= ~bit; + putreg32(regval, regaddr); + } + else if (irq >= LC823450_IRQ_INTERRUPTS) + { + putreg32(bit, regaddr); + } + else + { + regval = getreg32(regaddr); + regval |= bit; + putreg32(regval, regaddr); + } + } + + /* lc823450_dumpnvic("enable", irq); */ +} + +/**************************************************************************** + * Name: up_ack_irq + * + * Description: + * Acknowledge the IRQ + * + ****************************************************************************/ + +void up_ack_irq(int irq) +{ +#ifdef CONFIG_DVFS + lc823450_dvfs_exit_idle(irq); +#endif + +#ifdef CONFIG_LC823450_SLEEP_MODE + extern void up_update_idle_time(void); + up_update_idle_time(); +#endif +} + +/**************************************************************************** + * Name: up_prioritize_irq + * + * Description: + * Set the priority of an IRQ. + * + * Since this API is not supported on all architectures, it should be + * avoided in common implementations where possible. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_IRQPRIO +int up_prioritize_irq(int irq, int priority) +{ + uint32_t regaddr; + uint32_t regval; + int shift; + + DEBUGASSERT(irq >= LC823450_IRQ_MEMFAULT && irq < NR_IRQS && + (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN); + + if (irq < LC823450_IRQ_INTERRUPTS) + { + /* NVIC_SYSH_PRIORITY() maps {0..15} to one of three priority + * registers (0-3 are invalid) + */ + + regaddr = NVIC_SYSH_PRIORITY(irq); + irq -= 4; + } + else + { + /* NVIC_IRQ_PRIORITY() maps {0..} to one of many priority registers */ + + irq -= LC823450_IRQ_INTERRUPTS; + regaddr = NVIC_IRQ_PRIORITY(irq); + } + + regval = getreg32(regaddr); + shift = ((irq & 3) << 3); + regval &= ~(0xff << shift); + regval |= (priority << shift); + putreg32(regval, regaddr); + + /* lc823450_dumpnvic("prioritize", irq); */ + return OK; +} +#endif + +/**************************************************************************** + * Name: lc823450_irq_srctype + * + * Description: + * Set source type of external interrupt. + * + ****************************************************************************/ + +int lc823450_irq_srctype(int irq, enum lc823450_srctype_e srctype) +{ + irqstate_t flags; + uint32_t regaddr; + uint32_t regval; + int port; + int gpio; + +#ifdef CONFIG_LC823450_VIRQ + if (irq >= LC823450_IRQ_VIRTUAL && + irq < LC823450_IRQ_VIRTUAL + LC823450_IRQ_NVIRTUALIRQS) + { + struct lc823450_irq_ops *ops; + ops = virq_ops[irq - LC823450_IRQ_VIRTUAL]; + if (ops && ops->srctype) + { + return ops->srctype(irq, srctype); + } + return OK; + } +#endif /* CONFIG_LC823450_VIRQ */ + + DEBUGASSERT(srctype < SRCTYPE_MAX); + DEBUGASSERT(irq >= LC823450_IRQ_GPIO00 && irq <= LC823450_IRQ_GPIO59); + + irq -= LC823450_IRQ_GPIO00; + + port = (irq & 0x70) >> 4; + gpio = irq & 0xf; + + flags = enter_critical_section(); + + regaddr = INTC_REG(EXTINTnCND_BASE, port); + regval = getreg32(regaddr); + + regval &= ~(3 << gpio * 2); + regval |= srctype << gpio * 2; + + putreg32(regval, regaddr); + + leave_critical_section(flags); + + return OK; +} + + +/**************************************************************************** + * Name: lc823450_irq_register + * + * Description: + * Register IRQ + * + ****************************************************************************/ + +#ifdef CONFIG_LC823450_VIRQ +int lc823450_irq_register(int irq, struct lc823450_irq_ops *ops) +{ + if (irq >= LC823450_IRQ_VIRTUAL && + irq < LC823450_IRQ_VIRTUAL + LC823450_IRQ_NVIRTUALIRQS) + { + irqstate_t flags; + flags = irqsave(); + virq_ops[irq - LC823450_IRQ_VIRTUAL] = ops; + irqrestore(flags); + } + else + { + return -1; + } + return OK; +} +#endif /* CONFIG_LC823450_VIRQ */ diff --git a/arch/arm/src/lc823450/lc823450_lowputc.c b/arch/arm/src/lc823450/lc823450_lowputc.c new file mode 100644 index 00000000000..e0ac3e1dfb2 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_lowputc.c @@ -0,0 +1,227 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_lowputc.c + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * + * 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 "up_internal.h" +#include "up_arch.h" + +#include "chip.h" + +#include "lc823450_serial.h" +#include "lc823450_syscontrol.h" + +#include + +/************************************************************************** + * Pre-processor Definitions + **************************************************************************/ +/* Configuration **********************************************************/ + +/* Select UART parameters for the selected console */ +#define CTL_CLK XT1OSC_CLK + +#if defined(CONFIG_UART0_SERIAL_CONSOLE) +# define LC823450_CONSOLE_BASE LC823450_UART0_REGBASE +# define LC823450_CONSOLE_BAUD CONFIG_UART0_BAUD +# define LC823450_CONSOLE_PARITY CONFIG_UART0_PARITY +# define LC823450_CONSOLE_BITS CONFIG_UART0_BITS +# define LC823450_CONSOLE_2STOP CONFIG_UART0_2STOP +# define LC823450_UARTCLK_VALUE (MCLKCNTAPB_UART0_CLKEN | \ + MCLKCNTAPB_UART0IF_CLKEN) +# define LC823450_UARTRST_VALUE MRSTCNTAPB_UART0_RSTB +#elif defined(CONFIG_UART1_SERIAL_CONSOLE) +# define LC823450_CONSOLE_BASE LC823450_UART1_REGBASE +# define LC823450_CONSOLE_BAUD CONFIG_UART1_BAUD +# define LC823450_CONSOLE_PARITY CONFIG_UART1_PARITY +# define LC823450_CONSOLE_BITS CONFIG_UART1_BITS +# define LC823450_CONSOLE_2STOP CONFIG_UART1_2STOP +# define LC823450_UARTCLK_VALUE (MCLKCNTAPB_UART1_CLKEN | \ + MCLKCNTAPB_UART1IF_CLKEN) +# define LC823450_UARTRST_VALUE MRSTCNTAPB_UART1_RSTB +#elif defined(CONFIG_UART2_SERIAL_CONSOLE) +# define LC823450_CONSOLE_BASE LC823450_UART2_REGBASE +# define LC823450_CONSOLE_BAUD CONFIG_UART2_BAUD +# define LC823450_CONSOLE_PARITY CONFIG_UART2_PARITY +# define LC823450_CONSOLE_BITS CONFIG_UART2_BITS +# define LC823450_CONSOLE_2STOP CONFIG_UART2_2STOP +# define LC823450_UARTCLK_VALUE (MCLKCNTAPB_UART2_CLKEN | \ + MCLKCNTAPB_UART2IF_CLKEN) +# define LC823450_UARTRST_VALUE MRSTCNTAPB_UART2_RSTB +#else +# error "No CONFIG_UARTn_SERIAL_CONSOLE Setting" +#endif + +/* UDIV settings */ +#define UART_UDIV_N 16 +#define UART_UDIV_VALUE ((UART_UDIV_N - 1) << 0) + +/* UBR settings */ +#define UART_UBR_VALUE \ + (65536 - (CTL_CLK / (UART_UDIV_N * LC823450_CONSOLE_BAUD))) + +/* UMD settings */ +#if LC823450_CONSOLE_BITS == 8 +# define UART_UMD_BIT_VALUE UART_UMD_CL +#else +# define UART_UMD_BIT_VALUE 0 +#endif + +#if LC823450_CONSOLE_2STOP != 0 +# define UART_UMD_2STOP_VALUE UART_UMD_STL +#else +# define UART_UMD_2STOP_VALUE 0 +#endif + +#if LC823450_CONSOLE_PARITY == 1 +# define UART_UMD_PARITY_VALUE UART_UMD_PS0 +#elif LC823450_CONSOLE_PARITY == 2 +# define UART_UMD_PARITY_VALUE UART_UMD_PS1 +#else +# define UART_UMD_PARITY_VALUE 0 +#endif + +#define UART_UMD_VALUE \ + (UART_UMD_BIT_VALUE | UART_UMD_2STOP_VALUE | UART_UMD_PARITY_VALUE) + + +/************************************************************************** + * Private Types + **************************************************************************/ + +/************************************************************************** + * Private Function Prototypes + **************************************************************************/ + +/************************************************************************** + * Public Data + **************************************************************************/ + +/************************************************************************** + * Private Data + **************************************************************************/ + +/************************************************************************** + * Private Functions + **************************************************************************/ + +/************************************************************************** + * Public Functions + **************************************************************************/ + +/************************************************************************** + * Name: up_lowputc + * + * Description: + * Output one byte on the serial console + * + **************************************************************************/ + +void up_lowputc(char ch) +{ + +#ifdef CONFIG_DEV_CONSOLE_SWITCH + if (g_console_disable) + return; +#endif + + /* Wait until the TX FIFO is empty */ + + while (!(getreg32(LC823450_CONSOLE_BASE + UART_USR) & UART_USR_TXEMP)) + ; + + /* Wait until the TX Register is not full */ + + while (getreg32(LC823450_CONSOLE_BASE + UART_USR) & UART_USR_TFF) + ; + + /* Clear SendDone status */ + + putreg32(UART_UINT_UARTTF_INT, LC823450_CONSOLE_BASE + UART_UISR); + + /* Then send the character */ + + putreg32((uint32_t)ch, LC823450_CONSOLE_BASE + UART_USTF); + + /* Wait SendDone */ + + while (!(getreg32(LC823450_CONSOLE_BASE + UART_UISR) & UART_UINT_UARTTF_INT)) + ; +} + +/************************************************************************** + * Name: up_lowsetup + * + * Description: + * This performs basic initialization of the UART used for the serial + * console. Its purpose is to get the console output availabe as soon + * as possible. + * + **************************************************************************/ + +void lc823450_lowsetup(void) +{ + /* Clock & Reset */ + + modifyreg32(MCLKCNTAPB, 0, LC823450_UARTCLK_VALUE); + modifyreg32(MRSTCNTAPB, 0, LC823450_UARTRST_VALUE); + + /* INTC enable */ + + modifyreg32(MRSTCNTBASIC, 0, MRSTCNTBASIC_IRQCNT_RSTB); + + /* baud */ + + putreg32(UART_UBR_VALUE, LC823450_CONSOLE_BASE + UART_UBR); + + /* parity : bits : 2stop */ + + putreg32(UART_UMD_VALUE, LC823450_CONSOLE_BASE + UART_UMD); + + /* Tx FIFO Enable */ + + putreg32(UART_USFC_TXFF_EN, LC823450_CONSOLE_BASE + UART_USFC); + + /* Tx Enable */ + + putreg32(UART_UCM_TE, LC823450_CONSOLE_BASE + UART_UCM); +} diff --git a/arch/arm/src/lc823450/lc823450_lowputc.h b/arch/arm/src/lc823450/lc823450_lowputc.h new file mode 100644 index 00000000000..bb2cdb18317 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_lowputc.h @@ -0,0 +1,76 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_lowputc.h + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_LC823450_LC823450_LOWPUTC_H +#define __ARCH_ARM_SRC_LC823450_LC823450_LOWPUTC_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + + +/************************************************************************************ + * Name: lc823450_lowsetup + * + * Description: + * Called at the very beginning of _start. Performs low level initialization. + * + ************************************************************************************/ + +EXTERN void lc823450_lowsetup(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_LC823450_LC823450_LOWPUTC_H */ diff --git a/arch/arm/src/lc823450/lc823450_rtc.c b/arch/arm/src/lc823450/lc823450_rtc.c new file mode 100644 index 00000000000..b716bde710f --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_rtc.c @@ -0,0 +1,758 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_rtc.c + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * + * 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 + +#ifdef CONFIG_RTC_ALARM +# include +#endif + +#include + +#include +#include +#include +#include + +#include "lc823450_syscontrol.h" +#include "up_arch.h" +#include "clock/clock.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define RTC_REGBASE 0x4008e000 +#define RTC_SEC (RTC_REGBASE + 0x000) +#define RTC_MIN (RTC_REGBASE + 0x004) +#define RTC_HOUR (RTC_REGBASE + 0x008) +#define RTC_WEEK (RTC_REGBASE + 0x00c) +#define RTC_DAY (RTC_REGBASE + 0x010) +#define RTC_MONTH (RTC_REGBASE + 0x014) +#define RTC_YEAR (RTC_REGBASE + 0x018) +#define RTC_CENT (RTC_REGBASE + 0x01c) +#define RTC_SECALM (RTC_REGBASE + 0x020) +#define RTC_MINALM (RTC_REGBASE + 0x024) +#define RTC_HOURALM (RTC_REGBASE + 0x028) +#define RTC_WEEKALM (RTC_REGBASE + 0x02c) +#define RTC_DAYALM (RTC_REGBASE + 0x030) +#define RTC_MONTHALM (RTC_REGBASE + 0x034) +#define RTC_PRSEL (RTC_REGBASE + 0x038) +#define RTC_RTCINT (RTC_REGBASE + 0x03c) +#define RTC_RTCINT_AIE 5 +#define RTC_RTCINT_SET 7 +#define RTC_DST (RTC_REGBASE + 0x040) +#define RTC_RTCSTAT (RTC_REGBASE + 0x044) +#define RTC_RTCSTAT_UIP 0 +#define RTC_RTCSTAT_UF 4 +#define RTC_RTCSTAT_PCLR 7 +#define RTC_TEST (RTC_REGBASE + 0x048) +#define RTC_PTN32BIT0 (RTC_REGBASE + 0x04c) +#define RTC_PTN32BIT1 (RTC_REGBASE + 0x050) +#define RTC_PTN32BIT2 (RTC_REGBASE + 0x054) +#define RTC_PTN32BIT3 (RTC_REGBASE + 0x058) +#define RTC_PTN32BIT0_VAL 0x12 +#define RTC_PTN32BIT1_VAL 0x34 +#define RTC_PTN32BIT2_VAL 0x56 +#define RTC_PTN32BIT3_VAL 0x78 +#define RTC_VPTN32BIT0 (RTC_REGBASE + 0x05c) +#define RTC_VPTN32BIT1 (RTC_REGBASE + 0x060) +#define RTC_VPTN32BIT2 (RTC_REGBASE + 0x064) +#define RTC_VPTN32BIT3 (RTC_REGBASE + 0x068) +#define RTC_VPTN32BIT0_VAL 0xa7 +#define RTC_VPTN32BIT1_VAL 0x58 +#define RTC_VPTN32BIT2_VAL 0x3c +#define RTC_VPTN32BIT3_VAL 0xf1 +#define RTC_VDET (RTC_REGBASE + 0x06c) +#define RTC_VDET_VDET 0x01 +#define RTC_RTCINTCNT (RTC_REGBASE + 0x070) + + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +#ifdef CONFIG_RTC_SAVE_DEFAULT +struct rtc_default +{ + int sig; +#define RTC_DEFAULT_SIGNATURE 0x12345678 + struct tm tm; +}; +#endif + + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +#ifdef CONFIG_RTC_SAVE_DEFAULT +static void rtc_pmnotify(struct pm_callback_s *cb, enum pm_state_e pmstate); +#endif /* CONFIG_RTC_SAVE_DEFAULT */ + + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +static alarmcb_t g_alarmcb; +#endif + +#ifdef CONFIG_RTC_SAVE_DEFAULT +static struct pm_callback_s pm_cb = +{ + .notify = rtc_pmnotify, +}; +#endif /* CONFIG_RTC_SAVE_DEFAULT */ + +#ifdef CONFIG_RTC_DIV +static int cboot = 1; +#endif /* CONFIG_RTC_DIV */ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +volatile bool g_rtc_enabled = false; + + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tm_divider + ****************************************************************************/ + +#ifdef CONFIG_RTC_DIV +static void tm_divider(struct tm *tm, int divn, int divm) +{ + time_t tt; + tt = mktime(tm); + tt = (time_t) ((uint64_t)tt * divn / divm); + gmtime_r(&tt, tm); +} +#endif /* CONFIG_RTC_DIV */ + + +/**************************************************************************** + * Name: rtc_pmnotify + ****************************************************************************/ + +#ifdef CONFIG_RTC_SAVE_DEFAULT +static void rtc_pmnotify(struct pm_callback_s *cb, enum pm_state_e pmstate) +{ + struct tm tm; + + switch (pmstate) + { + case PM_SLEEP: + case PM_SHUTDOWN: + + /* RTC is not set yet. */ + + if (getreg8(RTC_PTN32BIT0) != RTC_PTN32BIT0_VAL || + getreg8(RTC_PTN32BIT1) != RTC_PTN32BIT1_VAL || + getreg8(RTC_PTN32BIT2) != RTC_PTN32BIT2_VAL || + getreg8(RTC_PTN32BIT3) != RTC_PTN32BIT3_VAL) + { + break; + } + (void)up_rtc_getdatetime(&tm); + up_rtc_set_default_datetime(&tm); + break; + + default: + break; + } + return; +} +#endif /* CONFIG_RTC_SAVE_DEFAULT */ + + +/**************************************************************************** + * Name: rtc_interrupt + * + * Description: + * RTC interrupt service routine + * + * Input Parameters: + * irq - The IRQ number that generated the interrupt + * context - Architecture specific register save information. + * + * Returned Value: + * Zero (OK) on success; A negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +static int rtc_interrupt(int irq, void *context, FAR void *arg) +{ + struct tm tm; + up_rtc_getdatetime(&tm); + + _info("RTCSTAT = 0x%02x (%04d/%02d/%02d %02d:%02d:%02d)\n", + getreg8(RTC_RTCSTAT), + tm.tm_year + 1900, + tm.tm_mon + 1, + tm.tm_mday, + tm.tm_hour, + tm.tm_min, + tm.tm_sec); + + /* Disable IRQ */ + + putreg8(0, RTC_RTCINT); + + /* Clear interrupt status */ + + putreg8(0, RTC_RTCSTAT); + putreg8(1 << RTC_RTCSTAT_PCLR, RTC_RTCSTAT); + + if (g_alarmcb) + { + g_alarmcb(); + } + + return OK; +} +#endif /* CONFIG_RTC_ALARM */ + +/**************************************************************************** + * Name: up_rtc_getdatetime + * + * Description: + * Get the current date and time from the date/time RTC. This interface + * is only supported by the date/time RTC hardware implementation. + * It is used to replace the system timer. It is only used by the RTOS during + * intialization to set up the system time when CONFIG_RTC and CONFIG_RTC_DATETIME + * are selected (and CONFIG_RTC_HIRES is not). + * + * NOTE: Some date/time RTC hardware is capability of sub-second accuracy. That + * sub-second accuracy is lost in this interface. However, since the system time + * is reinitialized on each power-up/reset, there will be no timing inaccuracy in + * the long run. + * + * Input Parameters: + * tp - The location to return the high resolution time value. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + + +static int up_rtc_getdatetime_main(FAR struct tm *tp) +{ +#ifdef CONFIG_RTC_DIV + tp->tm_sec = getreg8(RTC_SEC); + tp->tm_min = getreg8(RTC_MIN); + tp->tm_hour = getreg8(RTC_HOUR); + tp->tm_mday = getreg8(RTC_DAY); + + /* this RTC count month from 1 */ + + tp->tm_mon = getreg8(RTC_MONTH) - 1; + + /* int tm_year: years since 1900 */ + + tp->tm_year = getreg8(RTC_YEAR) + (getreg8(RTC_CENT) - 19) * 100; + tm_divider(tp, CONFIG_RTC_DIV_N, CONFIG_RTC_DIV_M); +#else /* CONFIG_RTC_DIV */ + if (getreg8(RTC_PTN32BIT0) != RTC_PTN32BIT0_VAL || + getreg8(RTC_PTN32BIT1) != RTC_PTN32BIT1_VAL || + getreg8(RTC_PTN32BIT2) != RTC_PTN32BIT2_VAL || + getreg8(RTC_PTN32BIT3) != RTC_PTN32BIT3_VAL) + { + tp->tm_sec = 0; + tp->tm_min = 0; + tp->tm_hour = 0; + tp->tm_mday = CONFIG_START_DAY; /* 1 to 31 */ + tp->tm_mon = CONFIG_START_MONTH - 1; /* 0 to 11 */ + tp->tm_year = (CONFIG_START_YEAR - 1900); /* since 1900 */ + } + else + { + tp->tm_sec = getreg8(RTC_SEC); + tp->tm_min = getreg8(RTC_MIN); + tp->tm_hour = getreg8(RTC_HOUR); + tp->tm_mday = getreg8(RTC_DAY); + tp->tm_mon = getreg8(RTC_MONTH) - 1; /* this RTC count month from 1 */ + + /* int tm_year: years since 1900 */ + + tp->tm_year = getreg8(RTC_YEAR) + (getreg8(RTC_CENT) - 19) * 100; + } +#endif /* CONFIG_RTC_DIV */ + + return OK; +} + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + + +/**************************************************************************** + * Name: up_rtcinitialize + * + * Description: + * Initialize the hardware RTC per the selected configuration. This function is + * called once during the OS initialization sequence + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + + +int up_rtc_initialize(void) +{ + /* RTC clock / reset */ + + modifyreg32(MCLKCNTAPB, 0, MCLKCNTAPB_RTC_CLKEN); + modifyreg32(MRSTCNTAPB, 0, MRSTCNTAPB_RTC_RSTB); + + putreg8(0xa7, RTC_VPTN32BIT0); + putreg8(0x58, RTC_VPTN32BIT1); + putreg8(0x3c, RTC_VPTN32BIT2); + putreg8(0xf1, RTC_VPTN32BIT3); + +#ifdef CONFIG_RTC_DIV + struct tm tm; + + /* Stop rtc update */ + + putreg8(1 << RTC_RTCINT_SET, RTC_RTCINT); + + tm.tm_sec = 0; + tm.tm_min = 0; + tm.tm_hour = 0; + tm.tm_mday = CONFIG_START_DAY; + tm.tm_mon = CONFIG_START_MONTH - 1; + tm.tm_year = CONFIG_START_YEAR - 1900; + + tm_divider(&tm, CONFIG_RTC_DIV_M, CONFIG_RTC_DIV_N); + + putreg8(tm.tm_sec, RTC_SEC); + putreg8(tm.tm_min, RTC_MIN); + putreg8(tm.tm_hour, RTC_HOUR); + putreg8(tm.tm_mday, RTC_DAY); + putreg8(tm.tm_mon + 1, RTC_MONTH); + putreg8((tm.tm_year + 1900) / 100, RTC_CENT); + putreg8(tm.tm_year % 100, RTC_YEAR); + +#else /* CONFIG_RTC_DIV */ + + if (!(getreg8(RTC_VDET) & RTC_VDET_VDET)) + { + _info("VDET Detect\n"); + putreg8(0, RTC_PTN32BIT0); + putreg8(0, RTC_PTN32BIT1); + putreg8(0, RTC_PTN32BIT2); + putreg8(0, RTC_PTN32BIT3); + + /* VDET decahtter */ + + putreg8(RTC_VPTN32BIT0_VAL, RTC_VPTN32BIT0); + putreg8(RTC_VPTN32BIT1_VAL, RTC_VPTN32BIT1); + putreg8(RTC_VPTN32BIT2_VAL, RTC_VPTN32BIT2); + putreg8(RTC_VPTN32BIT3_VAL, RTC_VPTN32BIT3); + + /* Reset VDET */ + + putreg32(RTC_VDET_VDET, RTC_VDET); + + /* 32.768kHz * 2 clock */ + + up_udelay(62); + putreg32(0, RTC_VDET); + } + + + if (getreg8(RTC_PTN32BIT0) != RTC_PTN32BIT0_VAL || + getreg8(RTC_PTN32BIT1) != RTC_PTN32BIT1_VAL || + getreg8(RTC_PTN32BIT2) != RTC_PTN32BIT2_VAL || + getreg8(RTC_PTN32BIT3) != RTC_PTN32BIT3_VAL) + { + /* DETECT RTC reset. Set temporary timevalue for RTC alarm */ + + /* Stop rtc update */ + + putreg8(1 << RTC_RTCINT_SET, RTC_RTCINT); + + putreg8(0, RTC_SEC); + putreg8(0, RTC_MIN); + putreg8(0, RTC_HOUR); + putreg8(CONFIG_START_DAY, RTC_DAY); + putreg8(CONFIG_START_MONTH, RTC_MONTH); + putreg8(CONFIG_START_YEAR % 100, RTC_YEAR); + putreg8(CONFIG_START_YEAR / 100, RTC_CENT); + } +#endif /* CONFIG_RTC_DIV */ + + /* RTC start, if not run */ + + putreg8(0, RTC_RTCINT); + + putreg8(0, RTC_RTCSTAT); + putreg8(1 << RTC_RTCSTAT_PCLR, RTC_RTCSTAT); + +#ifdef CONFIG_RTC_ALARM + irq_attach(LC823450_IRQ_RTC, rtc_interrupt, NULL); + up_enable_irq(LC823450_IRQ_RTC); +#endif + +#ifdef CONFIG_RTC_SAVE_DEFAULT + pm_register(&pm_cb); +#endif /* CONFIG_RTC_SAVE_DEFAULT */ + + g_rtc_enabled = true; + + return OK; +} + + +int up_rtc_getdatetime(FAR struct tm *tp) +{ + struct tm tm1, tm2; + +#ifdef CONFIG_RTC_DIV + /* WA: time registers cannot be read within one second(from set) */ + + if (cboot) + { + tp->tm_sec = 0; + tp->tm_min = 0; + tp->tm_hour = 0; + tp->tm_mday = CONFIG_START_DAY; + tp->tm_mon = CONFIG_START_MONTH - 1; + tp->tm_year = CONFIG_START_YEAR - 1900; + cboot = 0; + return OK; + } +#endif /* CONFIG_RTC_DIV */ + + up_rtc_getdatetime_main(&tm1); + up_rtc_getdatetime_main(&tm2); + + if (tm1.tm_sec == tm2.tm_sec) + { + /* if tm1 == tm2, could read registers atomically */ + + *tp = tm1; + } + else + { + /* if tm1 != tm2, can read registers atomically in 1 sec */ + + up_rtc_getdatetime_main(tp); + } + + return OK; +} + +/**************************************************************************** + * Name: up_rtc_settime + * + * Description: + * Set the RTC to the provided time. All RTC implementations must be able to + * set their time based on a standard timespec. + * + * Input Parameters: + * tp - the time to use + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +int up_rtc_settime(FAR const struct timespec *ts) +{ + struct tm *tp; + +#ifdef CONFIG_ALARM_DEV + alarm_before_rtc_change(); +#endif /* CONFIG_ALARM_DEV */ + + tp = gmtime(&ts->tv_sec); + +#ifdef CONFIG_RTC_DIV + tm_divider(tp, CONFIG_RTC_DIV_M, CONFIG_RTC_DIV_N); +#endif /* CONFIG_RTC_DIV */ + + /* Stop rtc update */ + + putreg8(1 << RTC_RTCINT_SET, RTC_RTCINT); + + putreg8(tp->tm_sec, RTC_SEC); + putreg8(tp->tm_min, RTC_MIN); + putreg8(tp->tm_hour, RTC_HOUR); + putreg8(tp->tm_mday, RTC_DAY); + putreg8(tp->tm_mon + 1, RTC_MONTH); /* this RTC count month from 1 */ + + /* int tm_year; years since 1900 */ + + putreg8((tp->tm_year + 1900) / 100, RTC_CENT); + putreg8(tp->tm_year % 100, RTC_YEAR); + + /* mark RTC has valid timevalue */ + + putreg8(RTC_PTN32BIT0_VAL, RTC_PTN32BIT0); + putreg8(RTC_PTN32BIT1_VAL, RTC_PTN32BIT1); + putreg8(RTC_PTN32BIT2_VAL, RTC_PTN32BIT2); + putreg8(RTC_PTN32BIT3_VAL, RTC_PTN32BIT3); + +#ifdef CONFIG_RTC_SAVE_DEFAULT + up_rtc_set_default_datetime(tp); +#endif /* CONFIG_RTC_SAVE_DEFAULT */ + + /* Start rtc update */ + + putreg8(0, RTC_RTCINT); + +#ifdef CONFIG_ALARM_DEV + alarm_after_rtc_change(); +#endif /* CONFIG_ALARM_DEV */ + + return OK; +} + +/**************************************************************************** + * Name: up_rtc_setalarm + * + * Description: + * Set up an alarm. + * NOTE: Only one alarm is supported. + * + * Input Parameters: + * tp - the time to set the alarm + * callback - the function to call when the alarm expires. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +int up_rtc_setalarm(FAR const struct timespec *ts, alarmcb_t callback) +{ + struct tm *tp; + + if (g_alarmcb) + { + return -EBUSY; + } + + tp = gmtime(&ts->tv_sec); +#ifdef CONFIG_RTC_DIV + tm_divider(tp, CONFIG_RTC_DIV_M, CONFIG_RTC_DIV_N); +#endif /* CONFIG_RTC_DIV */ + g_alarmcb = callback; +#if 0 + llinfo("SETALARM (%04d/%02d/%02d %02d:%02d:%02d)\n", + tp->tm_year + 1900, + tp->tm_mon + 1, + tp->tm_mday, + tp->tm_hour, + tp->tm_min, + tp->tm_sec); +#endif + + /* Stop rtc update */ + + putreg8(1 << RTC_RTCINT_SET, RTC_RTCINT); + + putreg8(tp->tm_sec, RTC_SECALM); + putreg8(tp->tm_min, RTC_MINALM); + putreg8(tp->tm_hour, RTC_HOURALM); + putreg8(0, RTC_WEEKALM); /* 0 == not use */ + putreg8(tp->tm_mday, RTC_DAYALM); + putreg8(tp->tm_mon + 1, RTC_MONTHALM); /* this RTC count month from 1 */ + + /* tp->tm_year : this rtc don't support. */ + + putreg8(0, RTC_RTCSTAT); + putreg8(1 << RTC_RTCSTAT_PCLR, RTC_RTCSTAT); + + /* Start rtc update & interrupt enable */ + + modifyreg8(RTC_RTCINT, 1 << RTC_RTCINT_SET, 1 << RTC_RTCINT_AIE); + + return OK; +} + +/**************************************************************************** + * Name: up_rtc_cancelalarm + ****************************************************************************/ + +int up_rtc_cancelalarm(void) +{ + irqstate_t flags; + flags = enter_critical_section(); + g_alarmcb = NULL; + + /* Disable IRQ */ + + putreg8(0, RTC_RTCINT); + + leave_critical_section(flags); + return 0; +} + +#endif + + +/**************************************************************************** + * Name: up_rtc_getrawtime + * + * Description: + * This function is used to get timespec of raw hardware value. + * + ****************************************************************************/ + +int up_rtc_getrawtime(FAR struct timespec *ts) +{ + struct tm tm; + tm.tm_sec = getreg8(RTC_SEC); + tm.tm_min = getreg8(RTC_MIN); + tm.tm_hour = getreg8(RTC_HOUR); + tm.tm_mday = getreg8(RTC_DAY); + tm.tm_mon = getreg8(RTC_MONTH) - 1; /* this RTC count month from 1 */ + tm.tm_year = getreg8(RTC_YEAR) + (getreg8(RTC_CENT) - 19) * 100; + +#ifdef CONFIG_RTC_DIV + tm_divider(&tm, CONFIG_RTC_DIV_N, CONFIG_RTC_DIV_M); +#endif /* CONFIG_RTC_DIV */ + + ts->tv_nsec = 0; + ts->tv_sec = mktime(&tm); + return 0; +} + + +#ifdef CONFIG_RTC_SAVE_DEFAULT + +/**************************************************************************** + * Name: up_rtc_set_default_datetime + ****************************************************************************/ + +void up_rtc_set_default_datetime(struct tm *tp) +{ + int ret; + void *handle; + struct rtc_default rtc_def; + + rtc_def.tm = *tp; + rtc_def.sig = RTC_DEFAULT_SIGNATURE; + + ret = bchlib_setup(CONFIG_RTC_SAVE_BLOCKNAME, true, &handle); + if (ret) + { + llerr("error: %d\n"); + return; + } + + (void)bchlib_write(handle, (void *)&rtc_def, + CONFIG_RTC_SAVE_SECTOR_OFFSET * 512, sizeof(rtc_def)); + bchlib_teardown(handle); +} + +/**************************************************************************** + * Name: up_rtc_get_default_datetime + ****************************************************************************/ + +int up_rtc_get_default_datetime(struct tm *tp) +{ + void *handle; + struct rtc_default rtc_def; + int ret; + + ret = bchlib_setup(CONFIG_RTC_SAVE_BLOCKNAME, true, &handle); + if (ret) + { + llerr("error: %d\n"); + return -1; + } + (void)bchlib_read(handle, (void *)&rtc_def, + CONFIG_RTC_SAVE_SECTOR_OFFSET * 512, sizeof(rtc_def)); + bchlib_teardown(handle); + if (rtc_def.sig != RTC_DEFAULT_SIGNATURE) + { + return -ENOENT; + } + *tp = rtc_def.tm; + return 0; +} + +/**************************************************************************** + * Name: up_rtc_clear_default + ****************************************************************************/ + +void up_rtc_clear_default(void) +{ + int ret; + struct rtc_default rtc_def; + void *handle; + + ret = bchlib_setup(CONFIG_RTC_SAVE_BLOCKNAME, true, &handle); + if (ret) + { + llerr("error: %d\n"); + return; + } + memset(&rtc_def, 0, sizeof(rtc_def)); + (void)bchlib_write(handle, (void *)&rtc_def, + CONFIG_RTC_SAVE_SECTOR_OFFSET * 512, sizeof(rtc_def)); + bchlib_teardown(handle); + return; +} + +#endif /* CONFIG_RTC_SAVE_DEFAULT */ diff --git a/arch/arm/src/lc823450/lc823450_serial.c b/arch/arm/src/lc823450/lc823450_serial.c new file mode 100644 index 00000000000..d09a4515b02 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_serial.c @@ -0,0 +1,1442 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_serial.c + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * + * 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 +#include + +#include +#include + +#include "chip.h" +#include "up_arch.h" +#include "up_internal.h" + +#include "lc823450_dma.h" +#include "lc823450_serial.h" +#include "lc823450_syscontrol.h" +#include "lc823450_gpio.h" + +#ifdef CONFIG_DEV_CONSOLE_SWITCH +int g_console_disable; +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Some sanity checks *******************************************************/ + +#ifdef USE_SERIALDRIVER + +/* Which UART with be tty0/console and which tty1-7? The console will always + * be ttyS0. If there is no console then will use the lowest numbered UART. + */ + +/* First pick the console and ttys0. This could be any of UART0-5 */ + +#if defined(CONFIG_UART0_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart0port /* UART0 is console */ +# define TTYS0_DEV g_uart0port /* UART0 is ttyS0 */ +# define UART0_ASSIGNED 1 +#elif defined(CONFIG_UART1_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart1port /* UART1 is console */ +# define TTYS0_DEV g_uart1port /* UART1 is ttyS0 */ +# define UART1_ASSIGNED 1 +#elif defined(CONFIG_UART2_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart2port /* UART2 is console */ +# define TTYS0_DEV g_uart2port /* UART2 is ttyS0 */ +# define UART2_ASSIGNED 1 +#else +# undef CONSOLE_DEV /* No console */ +# if defined(CONFIG_LC823450_UART0) +# define TTYS0_DEV g_uart0port /* UART0 is ttyS0 */ +# define UART0_ASSIGNED 1 +# elif defined(CONFIG_LC823450_UART1) +# define TTYS0_DEV g_uart1port /* UART1 is ttyS0 */ +# define UART1_ASSIGNED 1 +# elif defined(CONFIG_LC823450_UART2) +# define TTYS0_DEV g_uart2port /* UART2 is ttyS0 */ +# define UART2_ASSIGNED 1 +# endif +#endif + +/* Pick ttys1. This could be any of UART0-7 excluding the console UART. */ + +#if defined(CONFIG_LC823450_UART0) && !defined(UART0_ASSIGNED) +# define TTYS1_DEV g_uart0port /* UART0 is ttyS1 */ +# define UART0_ASSIGNED 1 +#elif defined(CONFIG_LC823450_UART1) && !defined(UART1_ASSIGNED) +# define TTYS1_DEV g_uart1port /* UART1 is ttyS1 */ +# define UART1_ASSIGNED 1 +#elif defined(CONFIG_LC823450_UART2) && !defined(UART2_ASSIGNED) +# define TTYS1_DEV g_uart2port /* UART2 is ttyS1 */ +# define UART2_ASSIGNED 1 +#endif + +/* Pick ttys2. This could be one of UART1-7. It can't be UART0 because that + * was either assigned as ttyS0 or ttys1. One of UART 1-7 could also be the + * console. + */ + +#if defined(CONFIG_LC823450_UART1) && !defined(UART1_ASSIGNED) +# define TTYS2_DEV g_uart1port /* UART1 is ttyS2 */ +# define UART1_ASSIGNED 1 +#elif defined(CONFIG_LC823450_UART2) && !defined(UART2_ASSIGNED) +# define TTYS2_DEV g_uart2port /* UART2 is ttyS2 */ +# define UART2_ASSIGNED 1 +#endif + +/* Pick ttys3. This could be one of UART2-7. It can't be UART0-1 because + * those have already been assigned to ttsyS0, 1, or 2. One of + * UART 2-7 could also be the console. + */ + +#if defined(CONFIG_LC823450_UART2) && !defined(UART2_ASSIGNED) +# define TTYS3_DEV g_uart2port /* UART2 is ttyS3 */ +# define UART2_ASSIGNED 1 +#endif + +#define CTL_CLK XT1OSC_CLK +#define UART_FIFO_SIZE 16 + +#if defined(CONFIG_HSUART) +# define HS_DMAACT_STOP1 0 +# define HS_DMAACT_STOP2 1 +# define HS_DMAACT_ACT1 2 +# define HS_DMAACT_ACT2 3 +#endif + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? a : b) +#endif + +#ifndef MIN +#define MIN(a, b) ((a) > (b) ? b : a) +#endif + + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct up_dev_s +{ + uint32_t uartbase; /* Base address of UART registers */ + uint32_t baud; /* Configured baud */ + uint32_t im; /* Saved IM value */ + uint8_t irq; /* IRQ associated with this UART */ + uint8_t parity; /* 0=none, 1=odd, 2=even */ + uint8_t bits; /* Number of bits (7 or 8) */ + uint8_t cts; + uint8_t rts; + bool stopbits2; /* true: Configure with 2 stop bits instead of 1 */ + uint32_t rowe; /* receive register over write error */ + uint32_t pe; /* parity error */ + uint32_t fe; /* framing error */ + uint32_t rxowe; /* RX FIFO over write error */ +#ifdef CONFIG_HSUART + DMA_HANDLE hrxdma; + DMA_HANDLE htxdma; + sem_t rxdma_wait; + sem_t rxpkt_wait; + sem_t txdma_wait; +#endif /* CONFIG_HSUART */ +}; + +/**************************************************************************** + * 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, FAR void *arg); +static int up_ioctl(struct file *filep, int cmd, unsigned long arg); +static int up_receive(struct uart_dev_s *dev, uint32_t *status); +static void up_rxint(struct uart_dev_s *dev, bool enable); +static bool 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, bool enable); +static bool up_txready(struct uart_dev_s *dev); +static bool up_txempty(struct uart_dev_s *dev); +#ifdef CONFIG_HSUART +static int up_hs_attach(struct uart_dev_s *dev); +static void up_hs_detach(struct uart_dev_s *dev); +static void uart_dma_callback(DMA_HANDLE hdma, void *arg, int result); +static void uart_rxdma_callback(DMA_HANDLE hdma, void *arg, int result); +static void up_hs_dmasetup(void); +static int up_hs_receive(struct uart_dev_s *dev, char *buf, int buflen); +static int up_hs_send(struct uart_dev_s *dev, const char *buf, int buflen); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct uart_ops_s g_uart_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_txempty, +#ifdef CONFIG_HSUART + .hs_attach = up_hs_attach, + .hs_detach = up_hs_detach, + .hs_receive = up_hs_receive, + .hs_send = up_hs_send, +#endif +}; + +/* I/O buffers */ + +#ifdef CONFIG_LC823450_UART0 +static char g_uart0rxbuffer[CONFIG_UART0_RXBUFSIZE]; +static char g_uart0txbuffer[CONFIG_UART0_TXBUFSIZE]; +#endif +#ifdef CONFIG_LC823450_UART1 +static char g_uart1rxbuffer[CONFIG_UART1_RXBUFSIZE]; +static char g_uart1txbuffer[CONFIG_UART1_TXBUFSIZE]; +#endif +#ifdef CONFIG_LC823450_UART2 +static char g_uart2rxbuffer[CONFIG_UART2_RXBUFSIZE]; +static char g_uart2txbuffer[CONFIG_UART2_TXBUFSIZE]; +#endif + +/* This describes the state of the Stellaris uart0 port. */ + +#ifdef CONFIG_LC823450_UART0 +static struct up_dev_s g_uart0priv = +{ + .uartbase = LC823450_UART0_REGBASE, + .baud = CONFIG_UART0_BAUD, + .irq = LC823450_IRQ_UART0, + .parity = CONFIG_UART0_PARITY, + .bits = CONFIG_UART0_BITS, + .stopbits2 = CONFIG_UART0_2STOP, +}; + +static uart_dev_t g_uart0port = +{ + .recv = { + .size = CONFIG_UART0_RXBUFSIZE, + .buffer = g_uart0rxbuffer, + }, + .xmit = { + .size = CONFIG_UART0_TXBUFSIZE, + .buffer = g_uart0txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart0priv, +}; +#endif + +/* This describes the state of the Stellaris uart1 port. */ + +#ifdef CONFIG_LC823450_UART1 +static struct up_dev_s g_uart1priv = +{ + .uartbase = LC823450_UART1_REGBASE, + .baud = CONFIG_UART1_BAUD, + .irq = LC823450_IRQ_UART1, + .parity = CONFIG_UART1_PARITY, + .bits = CONFIG_UART1_BITS, + .stopbits2 = CONFIG_UART1_2STOP, +}; + +static uart_dev_t g_uart1port = +{ + .recv = { + .size = CONFIG_UART1_RXBUFSIZE, + .buffer = g_uart1rxbuffer, + }, + .xmit = { + .size = CONFIG_UART1_TXBUFSIZE, + .buffer = g_uart1txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart1priv, +}; +#endif + +/* This describes the state of the Stellaris uart2 port. */ + +#ifdef CONFIG_LC823450_UART2 +static struct up_dev_s g_uart2priv = +{ + .uartbase = LC823450_UART2_REGBASE, + .baud = CONFIG_UART2_BAUD, + .irq = LC823450_IRQ_UART2, + .parity = CONFIG_UART2_PARITY, + .bits = CONFIG_UART2_BITS, + .stopbits2 = CONFIG_UART2_2STOP, +}; + +static uart_dev_t g_uart2port = +{ + .recv = { + .size = CONFIG_UART2_RXBUFSIZE, + .buffer = g_uart2rxbuffer, + }, + .xmit = { + .size = CONFIG_UART2_TXBUFSIZE, + .buffer = g_uart2txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart2priv, +}; +#endif + +#ifdef CONFIG_HSUART +static int hs_recstart; +static int hs_dmaact; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_serialin + ****************************************************************************/ + +static inline uint32_t up_serialin(struct up_dev_s *priv, int offset) +{ + return getreg32(priv->uartbase + offset); +} + +/**************************************************************************** + * Name: up_serialout + ****************************************************************************/ + +static inline void up_serialout(struct up_dev_s *priv, int offset, uint32_t value) +{ + putreg32(value, priv->uartbase + offset); +} + +/**************************************************************************** + * Name: up_disableuartint + ****************************************************************************/ + +static inline void up_disableuartint(struct up_dev_s *priv, uint32_t *im) +{ + /* Return the current interrupt mask value */ + + if (im) + *im = priv->im; + + /* Disable all interrupts */ + + priv->im = 0; + up_serialout(priv, UART_UIEN, 0); +} + +/**************************************************************************** + * Name: up_restoreuartint + ****************************************************************************/ + +static inline void up_restoreuartint(struct up_dev_s *priv, uint32_t im) +{ + priv->im = im; + up_serialout(priv, UART_UIEN, im); +} + +/**************************************************************************** + * Name: up_waittxnotfull + ****************************************************************************/ + +static inline void up_waittxnotfull(struct up_dev_s *priv) +{ + int tmp; + + /* Limit how long we will wait for the TX available condition */ + + for (tmp = 1000 ; tmp > 0 ; tmp--) + { + /* Check Tx FIFO is full */ + + if ((up_serialin(priv, UART_USR) & UART_USR_TXFULL) == 0) + { + /* The Tx FIFO is not full... return */ + + break; + } + up_udelay(1); + } + + /* If we get here, then the wait has timed out and the Tx FIFO remains + * full. + */ +} + +/**************************************************************************** + * 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) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + uint32_t ctl; + int min_diff = INT_MAX, udiv = -1, tmp_reg, real_baud, i; + + /* Note: The logic here depends on the fact that that the UART module + * was enabled and the GPIOs were configured in up_lowsetup(). + */ + + /* Disable the UART by clearing the UARTEN bit in the UART CTL register */ + + ctl = up_serialin(priv, UART_UCM); + ctl &= ~(UART_UCM_RE | UART_UCM_TE); + up_serialout(priv, UART_UCM, ctl); + + /* Calculate BAUD rate from the SYS clock: + * REGVAL = 65536 - (ControllerCLK / (UDIV(7~15) + 1) * baudrate) + */ + + + /* search best divider setting */ + for (i = 7; i <= 15; i++) + { + tmp_reg = 65536 - (CTL_CLK / ((i + 1) * priv->baud)); + if (tmp_reg >= 65536) + continue; + real_baud = CTL_CLK / ((i + 1) * (65536 - tmp_reg)); + if (min_diff > abs(real_baud - priv->baud)) + { + min_diff = abs(real_baud - priv->baud); + udiv = i; + } + } + if (udiv < 0) + { + _err("ERR: baud = %d\n", priv->baud); + return -EINVAL; + } + + tmp_reg = 65536 - (CTL_CLK / ((udiv + 1) * priv->baud)); + real_baud = CTL_CLK / ((udiv + 1) * (65536 - tmp_reg)); + + up_serialout(priv, UART_UDIV, udiv); + up_serialout(priv, UART_UBR, tmp_reg); + + /* Set up the UMD register */ + + ctl = up_serialin(priv, UART_UMD); + switch (priv->bits) + { + case 7: + ctl &= ~UART_UMD_CL; + break; + case 8: + ctl |= UART_UMD_CL; + break; + default: + _err("ERR: bits = %d\n", priv->bits); + return -EINVAL; + } + + + ctl &= ~(UART_UMD_PS0 | UART_UMD_PS1); + switch (priv->parity) + { + case 0: /* non */ + break; + case 1: /* odd */ + ctl |= UART_UMD_PS0; + break; + case 2: /* even */ + ctl |= UART_UMD_PS1; + break; + default: + _err("ERR: bits = %d\n", priv->bits); + return -EINVAL; + } + + ctl &= ~UART_UMD_STL; + if (priv->stopbits2) + ctl |= UART_UMD_STL; + + if (priv->cts) + ctl |= UART_UMD_CTSEN; + else + ctl &= ~UART_UMD_CTSEN; + + if (priv->rts) + ctl |= UART_UMD_RTSEN; + else + ctl &= ~UART_UMD_RTSEN; + + up_serialout(priv, UART_UMD, ctl); + + /* Set the UART to interrupt whenever the TX FIFO is almost empty or when + * any character is received. + */ + + ctl = up_serialin(priv, UART_UIEN); + ctl |= UART_UIEN_UARTRF_IEN + | UART_UIEN_UARTTF_IEN + | UART_UIEN_ROWE_IEN + | UART_UIEN_PE_IEN + | UART_UIEN_FE_IEN + | UART_UIEN_RXOWE_IEN; + up_serialout(priv, UART_UIEN, ctl); + + /* Enable the FIFOs */ + + ctl = up_serialin(priv, UART_USFC); + ctl |= (UART_USFC_RXFF_EN | UART_USFC_TXFF_EN); + up_serialout(priv, UART_USFC, ctl); + + /* Enable Rx, Tx, and the UART */ + + ctl = up_serialin(priv, UART_UCM); + ctl |= (UART_UCM_RE | UART_UCM_TE); + up_serialout(priv, UART_UCM, ctl); + + 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 *)dev->priv; + up_disableuartint(priv, NULL); +} + +/**************************************************************************** + * Name: up_attach + * + * Description: + * Configure the UART 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 and enable the IRQ */ + + ret = irq_attach(priv->irq, up_interrupt, NULL); + if (ret == OK) + { + /* Enable the interrupt (RX and TX interrupts are still disabled + * in the UART + */ + + up_enable_irq(priv->irq); + } + return ret; +} + +/**************************************************************************** + * Name: up_detach + * + * Description: + * Detach UART 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 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, FAR void *arg) +{ + struct uart_dev_s *dev = NULL; + struct up_dev_s *priv; + uint32_t mis; + +#ifdef CONFIG_LC823450_UART0 + if (g_uart0priv.irq == irq) + { + dev = &g_uart0port; + } + else +#endif +#ifdef CONFIG_LC823450_UART1 + if (g_uart1priv.irq == irq) + { + dev = &g_uart1port; + } + else +#endif +#ifdef CONFIG_LC823450_UART2 + if (g_uart2priv.irq == irq) + { + dev = &g_uart2port; + } + else +#endif + { + PANIC(); + } + + priv = (struct up_dev_s *)dev->priv; + + + /* Get the masked UART status and clear the pending interrupts. */ + + mis = up_serialin(priv, UART_UISR); + + /* Handle incoming, receive bytes (with or without timeout) */ + + /* Rx buffer not empty ... process incoming bytes */ + if (mis & UART_UISR_UARTRF) + uart_recvchars(dev); + + if (mis & UART_UISR_ROWE) + priv->rowe++; + + if (mis & UART_UISR_PE) + priv->pe++; + + if (mis & UART_UISR_FE) + priv->fe++; + + if (mis & UART_UISR_RXOWE) + priv->rxowe++; + + /* Handle outgoing, transmit bytes */ + + /* Tx FIFO not full ... process outgoing bytes */ + if (mis & UART_UISR_UARTTF) + uart_xmitchars(dev); + + up_serialout(priv, UART_UISR, mis); + + return OK; +} + +/**************************************************************************** + * Name: up_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + ****************************************************************************/ +#ifdef CONFIG_SERIAL_TERMIOS +static int up_ioctl(struct file *filep, int cmd, unsigned long arg) +{ + int ret = OK; + 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; + + switch (cmd) + { +#ifdef CONFIG_SERIAL_TIOCSERGSTRUCT + case TIOCSERGSTRUCT: + { + struct up_dev_s *user = (struct up_dev_s *)arg; + if (!user) + ret = -EINVAL; + else + memcpy(user, dev, sizeof(struct up_dev_s)); + } + break; +#endif + + case TCGETS: + { + struct termios *termiosp = (struct termios *)arg; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + cfsetispeed(termiosp, priv->baud); + + /* Note that since we only support 8/9 bit modes and + * there is no way to report 9-bit mode, we always claim 8. + */ + + termiosp->c_cflag = ((priv->parity != 0) ? PARENB : 0) | + ((priv->parity == 1) ? PARODD : 0) | + ((priv->stopbits2) ? CSTOPB : 0) | +#ifdef CONFIG_SERIAL_OFLOWCONTROL + ((priv->oflow) ? CCTS_OFLOW : 0) | +#endif +#ifdef CONFIG_SERIAL_IFLOWCONTROL + ((priv->iflow) ? CRTS_IFLOW : 0) | +#endif + CS8; + + /* TODO: CCTS_IFLOW, CCTS_OFLOW */ + } + break; + + case TCSETS: + { + struct termios *termiosp = (struct termios *)arg; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* Perform some sanity checks before accepting any changes */ + + if (termiosp->c_cflag & PARENB) + priv->parity = (termiosp->c_cflag & PARODD) ? 1 : 2; + else + priv->parity = 0; + + priv->stopbits2 = (termiosp->c_cflag & CSTOPB) != 0; +#ifdef CONFIG_SERIAL_OFLOWCONTROL + priv->cts = (termiosp->c_cflag & CCTS_OFLOW) != 0; +#endif +#ifdef CONFIG_SERIAL_IFLOWCONTROL + priv->rts = (termiosp->c_cflag & CRTS_IFLOW) != 0; +#endif + + /* Note that since there is no way to request 9-bit mode + * and no way to support 5/6/7-bit modes, we ignore them + * all here. + */ + + /* Note that only cfgetispeed is used because we have knowledge + * that only one speed is supported. + */ + + priv->baud = cfgetispeed(termiosp); + + up_setup(dev); + + } + break; + + default: + ret = -ENOTTY; + break; + } + + return ret; +} + +#else +static int up_ioctl(struct file *filep, int cmd, unsigned long arg) +{ + return -ENOTTY; +} +#endif + + + +/**************************************************************************** + * 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 return 'status'. + * + ****************************************************************************/ + +static int up_receive(struct uart_dev_s *dev, uint32_t *status) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + uint32_t rxd; + + /* Get the Rx byte + 4 bits of error information. Return those in status */ + + rxd = up_serialin(priv, UART_USRF); + *status = rxd; + + /* The lower 8bits of the Rx data is the actual recevied byte */ + + return rxd & 0xff; +} + +/**************************************************************************** + * Name: up_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +static void up_rxint(struct uart_dev_s *dev, bool enable) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + if (enable) + { + /* Receive an interrupt when their is anything in the Rx FIFO (or an Rx + * timeout occurs. + */ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + priv->im |= UART_UIEN_UARTRF_IEN; +#endif + } + else + priv->im &= ~UART_UIEN_UARTRF_IEN; + + up_serialout(priv, UART_UIEN, priv->im); +} + +/**************************************************************************** + * Name: up_rxavailable + * + * Description: + * Return true if the receive fifo is not empty + * + ****************************************************************************/ + +static bool up_rxavailable(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + +#ifdef CONFIG_DEV_CONSOLE_SWITCH + if (g_console_disable && dev == &CONSOLE_DEV) + return false; +#endif /* CONFIG_DEV_CONSOLE_SWITCH */ + + return ((up_serialin(priv, UART_USR) & UART_USR_RXEMP) == 0); +} + +/**************************************************************************** + * 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; + +#ifdef CONFIG_DEV_CONSOLE_SWITCH + if (g_console_disable && dev == &CONSOLE_DEV) + return; +#endif /* CONFIG_DEV_CONSOLE_SWITCH */ + + up_serialout(priv, UART_USTF, (uint32_t)ch); +} + +/**************************************************************************** + * Name: up_txint + * + * Description: + * Call to enable or disable TX interrupts + * + ****************************************************************************/ + +static void up_txint(struct uart_dev_s *dev, bool enable) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + irqstate_t flags; + + flags = enter_critical_section(); + if (enable) + { + /* Set to receive an interrupt when the TX fifo is half emptied */ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + priv->im |= UART_UIEN_UARTTF_IEN; + up_serialout(priv, UART_UIEN, priv->im); + + /* The serial driver wants an interrupt here, but will not get get + * one unless we "prime the pump." I believe that this is because + * behave like a level interrupt and the Stellaris interrupts behave + * (at least by default) like edge interrupts. + * + * In any event, faking a TX interrupt here solves the problem; + * Call uart_xmitchars() just as would have been done if we recieved + * the TX interrupt. + */ + + uart_xmitchars(dev); +#endif + } + else + { + /* Disable the TX interrupt */ + priv->im &= ~UART_UIEN_UARTTF_IEN; + up_serialout(priv, UART_UIEN, priv->im); + } + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: up_txready + * + * Description: + * Return true if the tranmsit fifo is not full + * + ****************************************************************************/ + +static bool up_txready(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + +#ifdef CONFIG_DEV_CONSOLE_SWITCH + if (g_console_disable && dev == &CONSOLE_DEV) + return true; +#endif /* CONFIG_DEV_CONSOLE_SWITCH */ + + return ((up_serialin(priv, UART_USR) & UART_USR_TXFULL) == 0); +} + +/**************************************************************************** + * Name: up_txempty + * + * Description: + * Return true if the transmit fifo is empty + * + ****************************************************************************/ + +static bool up_txempty(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + +#ifdef CONFIG_DEV_CONSOLE_SWITCH + if (g_console_disable && dev == &CONSOLE_DEV) + return 0; +#endif /* CONFIG_DEV_CONSOLE_SWITCH */ + + return ((up_serialin(priv, UART_USR) & UART_USR_TXEMP) != 0); +} + +#ifdef CONFIG_HSUART + +/**************************************************************************** + * Name: up_hs_attach + ****************************************************************************/ +static int up_hs_attach(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + dev->recv.tail = 0; + dev->recv.head = 0; + hs_dmaact = HS_DMAACT_STOP1; + + up_hs_dmasetup(); + + hs_recstart = 1; + + return OK; +} + +/**************************************************************************** + * Name: up_hs_detach + ****************************************************************************/ +static void up_hs_detach(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + hs_recstart = 0; + lc823450_dmastop(priv->htxdma); + lc823450_dmastop(priv->hrxdma); + hs_dmaact = 0; + + return; +} + +/**************************************************************************** + * Name: uart_dma_callback + ****************************************************************************/ +static void uart_dma_callback(DMA_HANDLE hdma, void *arg, int result) +{ + struct uart_dev_s *dev = (struct uart_dev_s *)arg; + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + sem_t *waitsem = &priv->txdma_wait; + sem_post(waitsem); + uart_datasent(dev); +} + +/**************************************************************************** + * Name: uart_rxdma_callback + ****************************************************************************/ +static void uart_rxdma_callback(DMA_HANDLE hdma, void *arg, int result) +{ + if (hs_dmaact == HS_DMAACT_ACT1) + hs_dmaact = HS_DMAACT_STOP2; + else + hs_dmaact = HS_DMAACT_STOP1; + + hsuart_wdtimer(); + up_hs_dmasetup(); +} + +/**************************************************************************** + * Name: up_hs_dmasetup + ****************************************************************************/ +static void up_hs_dmasetup() +{ + irqstate_t flags; + + flags = irqsave(); + + switch (hs_dmaact) + { + case HS_DMAACT_ACT1: + case HS_DMAACT_ACT2: + break; + case HS_DMAACT_STOP1: + if (g_uart1port.recv.tail > 0 && + g_uart1port.recv.tail < CONFIG_UART1_RXBUFSIZE / 2) + break; + + lc823450_dmasetup(g_uart1priv.hrxdma, + LC823450_DMA_SRCWIDTH_BYTE | + LC823450_DMA_DSTWIDTH_BYTE | + LC823450_DMA_DSTINC, + LC823450_UART1_REGBASE + UART_USRF, + (uint32_t)g_uart1rxbuffer, + CONFIG_UART1_RXBUFSIZE / 2); + + lc823450_dmastart(g_uart1priv.hrxdma, uart_rxdma_callback, NULL); + hs_dmaact = HS_DMAACT_ACT1; + break; + + case HS_DMAACT_STOP2: + if (g_uart1port.recv.tail > CONFIG_UART1_RXBUFSIZE / 2) + break; + lc823450_dmasetup(g_uart1priv.hrxdma, + LC823450_DMA_SRCWIDTH_BYTE | + LC823450_DMA_DSTWIDTH_BYTE | + LC823450_DMA_DSTINC, + LC823450_UART1_REGBASE + UART_USRF, + (uint32_t)(g_uart1rxbuffer + CONFIG_UART1_RXBUFSIZE / 2) , + CONFIG_UART1_RXBUFSIZE / 2); + + lc823450_dmastart(g_uart1priv.hrxdma, uart_rxdma_callback, NULL); + hs_dmaact = HS_DMAACT_ACT2; + break; + }; + irqrestore(flags); +} + +/**************************************************************************** + * Name: up_hs_receive + ****************************************************************************/ +static int up_hs_receive(struct uart_dev_s *dev, char *buf, int buflen) +{ + int len = 0; + int dmalen; + irqstate_t flags; + + while ((dmalen = up_hsuart_get_rbufsize(dev)) == 0) + ; + len = MIN(dmalen, buflen); + + flags = irqsave(); + if (len + dev->recv.tail > dev->recv.size) + { + int len2; + len2 = dev->recv.size - dev->recv.tail; + memcpy(buf, dev->recv.buffer + dev->recv.tail, len2); + memcpy(buf + len2, dev->recv.buffer, len - len2); + dev->recv.tail = len - len2; + } + else + { + memcpy(buf, dev->recv.buffer + dev->recv.tail, len); + dev->recv.tail += len; + } + up_hs_dmasetup(); + irqrestore(flags); + return len; +} + +/**************************************************************************** + * Name: up_hs_send + ****************************************************************************/ +static int up_hs_send(struct uart_dev_s *dev, const char *buf, int buflen) +{ + int len; + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + +retry: + + sem_wait(&priv->txdma_wait); + + /* If buflen <= FIFO space, write it by PIO. */ + if (buflen <= + UART_FIFO_SIZE - UART_USFS_TXFF_LV(up_serialin(priv, UART_USFS))) + { + int i; + for (i = 0; i < buflen; i++) + up_serialout(priv, UART_USTF, buf[i]); + sem_post(&priv->txdma_wait); + return buflen; + } + len = MIN(buflen, LC823450_DMA_MAX_TRANSSIZE); + len = MIN(len, dev->xmit.size); + + memcpy(dev->xmit.buffer, buf, len); + + lc823450_dmasetup(priv->htxdma, + LC823450_DMA_SRCWIDTH_BYTE | + LC823450_DMA_DSTWIDTH_BYTE | + LC823450_DMA_SRCINC, + (uint32_t)dev->xmit.buffer, priv->uartbase + UART_USTF, len); + lc823450_dmastart(priv->htxdma, uart_dma_callback, dev); + + /* BT stack may not handle to short write */ + if (len != buflen) + { + buflen -= len; + buf += len; + goto retry; + } + + return len; +} +#endif /* CONFIG_HSUART */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * 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) +{ + /* NOTE: All GPIO configuration for the UARTs was performed in + * up_lowsetup + */ + + /* workaround: force clock enable */ +#if defined(CONFIG_LC823450_UART0) + modifyreg32(MCLKCNTAPB, 0, MCLKCNTAPB_UART0_CLKEN | MCLKCNTAPB_UART0IF_CLKEN); + modifyreg32(MRSTCNTAPB, 0, MRSTCNTAPB_UART0_RSTB); +#endif +#if defined(CONFIG_LC823450_UART1) + modifyreg32(MCLKCNTAPB, 0, MCLKCNTAPB_UART1_CLKEN | MCLKCNTAPB_UART1IF_CLKEN); + modifyreg32(MRSTCNTAPB, 0, MRSTCNTAPB_UART1_RSTB); +#endif +#if defined(CONFIG_LC823450_UART2) + modifyreg32(MCLKCNTAPB, 0, MCLKCNTAPB_UART2_CLKEN | MCLKCNTAPB_UART2IF_CLKEN); + modifyreg32(MRSTCNTAPB, 0, MRSTCNTAPB_UART2_RSTB); +#endif + + /* Disable all UARTS */ + + up_disableuartint(TTYS0_DEV.priv, NULL); +#ifdef TTYS1_DEV + up_disableuartint(TTYS1_DEV.priv, NULL); +#endif +#ifdef TTYS2_DEV + up_disableuartint(TTYS2_DEV.priv, NULL); +#endif + + /* Configuration whichever one is the console */ + + 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. + * + ****************************************************************************/ + +int hsuart_register(const char *path, uart_dev_t *dev); + +void up_serialinit(void) +{ + /* Register the console */ + + (void)uart_register("/dev/console", &CONSOLE_DEV); + + /* Register all UARTs */ + + (void)uart_register("/dev/ttyS0", &TTYS0_DEV); +#ifdef TTYS1_DEV + (void)uart_register("/dev/ttyS1", &TTYS1_DEV); +#ifdef CONFIG_HSUART + sem_init(&g_uart1priv.txdma_wait, 0, 1); + g_uart1priv.htxdma = lc823450_dmachannel(DMA_CHANNEL_UART1TX); + lc823450_dmarequest(g_uart1priv.htxdma, DMA_REQUEST_UART1TX); + + + sem_init(&g_uart1priv.rxdma_wait, 0, 0); + g_uart1priv.hrxdma = lc823450_dmachannel(DMA_CHANNEL_UART1RX); + lc823450_dmarequest(g_uart1priv.hrxdma, DMA_REQUEST_UART1RX); + + up_serialout(&g_uart1priv, UART_UDMA, UART_UDMA_RREQ_EN | UART_UDMA_TREQ_EN); + (void)hsuart_register("/dev/ttyHS1", &TTYS1_DEV); +#endif /* CONFIG_HSUART */ +#endif +#ifdef TTYS2_DEV + (void)uart_register("/dev/ttyS2", &TTYS2_DEV); +#endif +} + +/**************************************************************************** + * 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; + uint32_t im; + +#ifdef CONFIG_DEV_CONSOLE_SWITCH + if (g_console_disable) + return ch; +#endif /* CONFIG_DEV_CONSOLE_SWITCH */ + + up_disableuartint(priv, &im); + up_waittxnotfull(priv); + up_serialout(priv, UART_USTF, (uint32_t)ch); + + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + up_waittxnotfull(priv); + up_serialout(priv, UART_USTF, (uint32_t)'\r'); + } + + up_waittxnotfull(priv); + up_restoreuartint(priv, im); + return ch; +} + +#else /* USE_SERIALDRIVER */ + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + up_lowputc('\r'); + } + + up_lowputc(ch); + return ch; +} + +#endif /* USE_SERIALDRIVER */ + +#ifdef CONFIG_DEV_CONSOLE_SWITCH +void up_console_disable(int disable) +{ + uint32_t clkmask; +#if defined(CONFIG_UART0_SERIAL_CONSOLE) + clkmask = MCLKCNTAPB_UART0_CLKEN | MCLKCNTAPB_UART0IF_CLKEN; +#elif defined(CONFIG_UART1_SERIAL_CONSOLE) + clkmask = MCLKCNTAPB_UART1_CLKEN | MCLKCNTAPB_UART1IF_CLKEN; +#elif defined(CONFIG_UART2_SERIAL_CONSOLE) + clkmask = MCLKCNTAPB_UART2_CLKEN | MCLKCNTAPB_UART2IF_CLKEN; +#else + clkmask = 0; +#endif + + if (disable) + { + llinfo("disable console\n"); + g_console_disable = 1; + modifyreg32(MCLKCNTAPB, clkmask, 0); + + /* remux to gpio */ + lc823450_gpio_mux(GPIO_PORT5 | GPIO_PIN6 | GPIO_PULLDOWN | GPIO_MUX0); + lc823450_gpio_mux(GPIO_PORT5 | GPIO_PIN7 | GPIO_PULLDOWN | GPIO_MUX0); + } + else + { + llinfo("enable console\n"); + + /* remux to uart */ + lc823450_gpio_mux(GPIO_PORT5 | GPIO_PIN6 | GPIO_PULLDOWN | GPIO_MUX3); + lc823450_gpio_mux(GPIO_PORT5 | GPIO_PIN7 | GPIO_PULLDOWN | GPIO_MUX3); + + modifyreg32(MCLKCNTAPB, 0, clkmask); + g_console_disable = 0; + } +} +#endif /* CONFIG_DEV_CONSOLE_SWITCH */ + +#ifdef CONFIG_HSUART + +/**************************************************************************** + * Name: hsuart_wdtimer + ****************************************************************************/ +void hsuart_wdtimer(void) +{ + int newhead = 0; + + if (!hs_recstart) + return; + + switch (hs_dmaact) + { + case HS_DMAACT_ACT1: + newhead = CONFIG_UART1_RXBUFSIZE / 2 - lc823450_dmaremain(g_uart1priv.hrxdma); + break; + case HS_DMAACT_ACT2: + newhead = CONFIG_UART1_RXBUFSIZE - lc823450_dmaremain(g_uart1priv.hrxdma); + break; + case HS_DMAACT_STOP1: + newhead = 0; + break; + case HS_DMAACT_STOP2: + newhead = CONFIG_UART1_RXBUFSIZE / 2; + break; + }; + + if (g_uart1port.recv.head != newhead) + { + if (newhead == CONFIG_UART1_RXBUFSIZE) + newhead = 0; + + if (g_uart1port.recv.tail == CONFIG_UART1_RXBUFSIZE) + g_uart1port.recv.tail = 0; + + g_uart1port.recv.head = newhead; + uart_datareceived(&g_uart1port); + } +} + +/**************************************************************************** + * Name: up_hs_get_rbufsize + ****************************************************************************/ +int up_hsuart_get_rbufsize(struct uart_dev_s *dev) +{ + irqstate_t flags; + int ret; + + flags = enter_critical_section(); + if (dev->recv.tail <= dev->recv.head) + ret = dev->recv.head - dev->recv.tail; + else + ret = dev->recv.size - dev->recv.tail + dev->recv.head; + leave_critical_section(flags); + return ret; +} + +#endif /* CONFIG_HSUART */ diff --git a/arch/arm/src/lc823450/lc823450_serial.h b/arch/arm/src/lc823450/lc823450_serial.h new file mode 100644 index 00000000000..e1a68bcfa99 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_serial.h @@ -0,0 +1,102 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_serial.h + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_LC823450_LC823450_SERIAL_H +#define __ARCH_ARM_SRC_LC823450_LC823450_SERIAL_H + +#define LC823450_UART0_REGBASE 0x4008b000 +#define LC823450_UART1_REGBASE 0x4008c000 +#define LC823450_UART2_REGBASE 0x4008d000 + +#define UART_UTR 0x00 +#define UART_URR 0x04 +#define UART_UMD 0x08 +#define UART_UMD_CL (1 << 0) +#define UART_UMD_PS0 (1 << 1) +#define UART_UMD_PS1 (1 << 2) +#define UART_UMD_STL (1 << 3) +#define UART_UMD_RTSEN (1 << 5) +#define UART_UMD_CTSEN (1 << 6) +#define UART_UCM 0x0c +#define UART_UCM_RE (1 << 0) +#define UART_UCM_TE (1 << 1) +#define UART_USR 0x10 +#define UART_USR_TFF (1 << 0) +#define UART_USR_RRF (1 << 1) +#define UART_USR_TXFULL (1 << 8) +#define UART_USR_TXEMP (1 << 9) +#define UART_USR_RXEMP (1 << 13) +#define UART_UBR 0x14 +#define UART_UISR 0x18 +#define UART_UISR_UARTRF (1 << 0) +#define UART_UISR_UARTTF (1 << 1) +#define UART_UISR_PE (1 << 2) +#define UART_UISR_ROWE (1 << 3) +#define UART_UISR_FE (1 << 4) +#define UART_UISR_RXOWE (1 << 12) +#define UART_UDIV 0x1c +#define UART_UIEN 0x20 +#define UART_UIEN_UARTRF_IEN (1 << 0) +#define UART_UIEN_UARTTF_IEN (1 << 1) +#define UART_UIEN_PE_IEN (1 << 2) +#define UART_UIEN_ROWE_IEN (1 << 3) +#define UART_UIEN_FE_IEN (1 << 4) +#define UART_UIEN_RXOWE_IEN (1 << 12) +#define UART_UINT 0x24 +#define UART_UINT_UARTRF_INT (1 << 0) +#define UART_UINT_UARTTF_INT (1 << 1) +#define UART_USTF 0x28 +#define UART_USRF 0x2c +#define UART_USFC 0x30 +#define UART_USFC_RXFF_EN (1 << 3) +#define UART_USFC_TXFF_EN (1 << 7) +#define UART_UDMA 0x34 +#define UART_UDMA_RREQ_EN (1 << 0) +#define UART_UDMA_TREQ_EN (1 << 1) +#define UART_USFS 0x38 +#define UART_USFS_TXFF_LV(v) (((v) >> 8 ) & 0x1f) +#define UART_USFS_RXFF_LV(v) (((v) >> 0 ) & 0x1f) + +#ifdef CONFIG_DEV_CONSOLE_SWITCH +void up_console_disable(int disable); +extern int g_console_disable; +#endif + +#ifdef CONFIG_HSUART +void hsuart_wdtimer(void); +#endif + +#endif /* __ARCH_ARM_SRC_LC823450_LC823450_SERIAL_H */ diff --git a/arch/arm/src/lc823450/lc823450_spi.c b/arch/arm/src/lc823450/lc823450_spi.c new file mode 100644 index 00000000000..19f1b3d2550 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_spi.c @@ -0,0 +1,576 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_spi.c + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Nobutaka Toyoshima + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * + * 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 "up_arch.h" +#include "chip.h" + +#include "lc823450_syscontrol.h" +#include "lc823450_clockconfig.h" +#include "lc823450_dma.h" +#include "lc823450_spi.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#ifdef CONFIG_SPI_EXCHANGE +# error "SPI_EXCHANGE is not supported" +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct lc823450_spidev_s +{ + struct spi_dev_s spidev; /* Externally visible part of the SPI interface */ +#ifndef CONFIG_SPI_OWNBUS + sem_t exclsem; /* Held while chip is selected for mutual exclusion */ + uint32_t frequency; /* Requested clock frequency */ + uint32_t actual; /* Actual clock frequency */ + uint8_t nbits; /* Width of word in bits (8 to 16) */ + uint8_t mode; /* Mode 0,1,2,3 */ +#endif +#ifdef CONFIG_LC823450_SPI_DMA + DMA_HANDLE hdma; + sem_t dma_wait; +#endif /* CONFIG_LC823450_SPI_DMA */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* SPI methods */ + +#ifndef CONFIG_SPI_OWNBUS +static int spi_lock(FAR struct spi_dev_s *dev, bool lock); +#endif +static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency); +static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); +static void spi_setbits(FAR struct spi_dev_s *dev, int nbits); +static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t ch); +#ifndef CONFIG_SPI_EXCHANGE +static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords); +static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct spi_ops_s g_spiops = +{ +#ifndef CONFIG_SPI_OWNBUS + .lock = spi_lock, +#endif + .setfrequency = spi_setfrequency, + .setmode = spi_setmode, + .setbits = spi_setbits, + .select = lc823450_spiselect, +#ifdef CONFIG_SPI_CMDDATA + .cmddata = lc823450_spicmddata, +#endif +#if 0 + .status = lc823450_spistatus, +#endif + .send = spi_send, +#ifndef CONFIG_SPI_EXCHANGE + .sndblock = spi_sndblock, + .recvblock = spi_recvblock, +#endif +}; + +static struct lc823450_spidev_s g_spidev = +{ + .spidev = { &g_spiops }, +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifndef CONFIG_SPI_OWNBUS +static int spi_lock(FAR struct spi_dev_s *dev, bool lock) +{ + FAR struct lc823450_spidev_s *priv = (FAR struct lc823450_spidev_s *)dev; + + if (lock) + { + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&priv->exclsem) != 0) + { + /* The only case that an error should occur here is if the wait was awakened + * by a signal. + */ + + ASSERT(errno == EINTR); + } + } + else + { + (void)sem_post(&priv->exclsem); + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: spi_setfrequency + * + * Description: + * Set the SPI frequency. + * + * Input Parameters: + * dev - Device-specific state data + * frequency - The SPI frequency requested + * + * Returned Value: + * Returns the actual frequency selected + * + ****************************************************************************/ + +static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) +{ + FAR struct lc823450_spidev_s *priv = (FAR struct lc823450_spidev_s *)dev; + unsigned long sysclk = lc823450_get_systemfreq(); + uint32_t actual; + int div; + +#ifndef CONFIG_SPI_OWNBUS + if (priv->frequency == frequency) + { + return priv->actual; + } +#endif + + for (div = 0xFE; div >= 0; div--) + { + if (frequency >= sysclk / (4 * (256 - div))) + { + break; + } + } + _info("Frequency %d -> %d\n", frequency, sysclk / (4 * (256 - div))); + + actual = sysclk / (4 * (256 - div)); + putreg32(div, LC823450_SPI_BRG); + +#ifndef CONFIG_SPI_OWNBUS + priv->frequency = frequency; + priv->actual = actual; +#endif + + return actual; +} + +/**************************************************************************** + * Name: spi_setmode + * + * Description: + * Set the SPI mode. Optional. See enum spi_mode_e for mode definitions + * + * Input Parameters: + * dev - Device-specific state data + * mode - The SPI mode requested + * + * Returned Value: + * none + * + ****************************************************************************/ + +static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode) +{ + FAR struct lc823450_spidev_s *priv = (FAR struct lc823450_spidev_s *)dev; + +#ifndef CONFIG_SPI_OWNBUS + if (priv->mode == mode) + { + return; + } +#endif + + switch (mode) + { + case SPIDEV_MODE0: /* CPOL=0; CPHA=0 */ + DEBUGASSERT(0); + break; + + case SPIDEV_MODE1: /* CPOL=0; CPHA=1 */ + modifyreg32(LC823450_SPI_SMD, 0, SPI_SMD_PO); + break; + + case SPIDEV_MODE2: /* CPOL=1; CPHA=0 */ + DEBUGASSERT(0); + break; + + case SPIDEV_MODE3: /* CPOL=1; CPHA=1 */ + modifyreg32(LC823450_SPI_SMD, SPI_SMD_PO, 0); + break; + + default: + DEBUGASSERT(FALSE); + return; + } + +#ifndef CONFIG_SPI_OWNBUS + priv->mode = mode; +#endif +} + +/**************************************************************************** + * Name: spi_setbits + * + * Description: + * Set the number if bits per word. + * + * Input Parameters: + * dev - Device-specific state data + * nbits - The number of bits requests + * + * Returned Value: + * none + * + ****************************************************************************/ + +static void spi_setbits(FAR struct spi_dev_s *dev, int nbits) +{ + FAR struct lc823450_spidev_s *priv = (FAR struct lc823450_spidev_s *)dev; + +#ifndef CONFIG_SPI_OWNBUS + if (priv->nbits == nbits) + { + return; + } +#endif + + DEBUGASSERT(nbits == 8 || nbits == 16); + + modifyreg32(LC823450_SPI_SMD, SPI_SMD_CHL, nbits == 8 ? 0 : SPI_SMD_CHL); + +#ifndef CONFIG_SPI_OWNBUS + priv->nbits = nbits; +#endif +} + +#ifdef CONFIG_LC823450_SPI_DMA +/**************************************************************************** + * Name: spi_dma_callback + * + ****************************************************************************/ +static void spi_dma_callback(DMA_HANDLE hdma, void *arg, int result) +{ + sem_t *waitsem = (sem_t *)arg; + sem_post(waitsem); +} +#endif /* CONFIG_LC823450_SPI_DMA */ + +/**************************************************************************** + * Name: spi_send + * + * Description: + * Exchange one word on SPI + * + * Input Parameters: + * dev - Device-specific state data + * wd - The word to send. the size of the data is determined by the + * number of bits selected for the SPI interface. + * + * Returned Value: + * response + * + ****************************************************************************/ +#ifdef CONFIG_LC823450_SPI_DMA +static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) +{ + spi_sndblock(dev, &wd, 1); + return 0; +} +#else /* CONFIG_LC823450_SPI_DMA */ +static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) +{ + putreg16(wd, LC823450_SPI_STR); + + modifyreg32(LC823450_SPI_ISR, 0, SPI_ISR_SPIF); + + modifyreg32(LC823450_SPI_SMD, 0, SPI_SMD_SSTR); + + /* Wait for Tranfer done */ + + while ((getreg32(LC823450_SPI_ISR) & SPI_ISR_SPIF) == 0) + ; + + return getreg16(LC823450_SPI_SRR); +} +#endif + +/************************************************************************* + * Name: spi_sndblock + * + * Description: + * Send a block of data on SPI + * + * Input Parameters: + * dev - Device-specific state data + * buffer - A pointer to the buffer of data to be sent + * nwords - the length of data to send from the buffer in number of words. + * The wordsize is determined by the number of bits-per-word + * selected for the SPI interface. If nbits <= 8, the data is + * packed into uint8_t's; if nbits > 8, the data is packed into + * uint16_t's + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifndef CONFIG_SPI_EXCHANGE +static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords) +{ + FAR struct lc823450_spidev_s *priv = (FAR struct lc823450_spidev_s *)dev; + +#ifdef CONFIG_LC823450_SPI_DMA +#ifndef MIN +#define MIN(a, b) ((a) > (b) ? b : a) +#endif + + /* TODO: 16bit */ + + while (nwords) + { + int len; + + len = MIN(nwords, LC823450_DMA_MAX_TRANSSIZE); + lc823450_dmasetup(priv->hdma, + LC823450_DMA_SRCWIDTH_BYTE | + LC823450_DMA_DSTWIDTH_BYTE | + LC823450_DMA_SRCINC, + (uint32_t)buffer, /* LC823450_SPI_STR */ + LC823450_SPI_TxFF, len); + + lc823450_dmastart(priv->hdma, spi_dma_callback, &priv->dma_wait); + + modifyreg32(LC823450_SPI_SMD, 0, SPI_SMD_WTR); + + while (sem_wait(&priv->dma_wait) != 0); + nwords -= len; + buffer += len; + } + + /* Wait for FIFO empty */ + + putreg32(SPI_ISR_TxEMP, LC823450_SPI_ISR); + while ((getreg32(LC823450_SPI_ISR) & SPI_ISR_TxEMP) != 0) + ; + + /* Wait for Tx reg empty */ + + while ((getreg32(LC823450_SPI_SSR) & SPI_SSR_TFF) != 0) + ; + /* Wait for Shift reg empty */ + + while ((getreg32(LC823450_SPI_SSR) & SPI_SSR_SHRF) != 0) + ; + +#else /* CONFIG_LC823450_SPI_DMA */ + int i; + const uint8_t *buf = buffer; + const uint16_t *buf16 = buffer; + + if (priv->nbits == 16) + { + for (i = 0; i < nwords; i++) + { + (void)spi_send(dev, *buf16++); + } + } + else + { + for (i = 0; i < nwords; i++) + { + (void)spi_send(dev, *buf++); + } + } +#endif /* CONFIG_LC823450_SPI_DMA */ +} +#endif + +/**************************************************************************** + * Name: spi_recvblock + * + * Description: + * Revice a block of data from SPI + * + * Input Parameters: + * dev - Device-specific state data + * buffer - A pointer to the buffer in which to recieve data + * nwords - the length of data that can be received in the buffer in number + * of words. The wordsize is determined by the number of bits-per-word + * selected for the SPI interface. If nbits <= 8, the data is + * packed into uint8_t's; if nbits >8, the data is packed into uint16_t's + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifndef CONFIG_SPI_EXCHANGE +static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords) +{ + FAR struct lc823450_spidev_s *priv = (FAR struct lc823450_spidev_s *)dev; + int i; + uint8_t *buf = buffer; + uint16_t *buf16 = buffer; + + if (priv->nbits == 16) + { + for (i = 0; i < nwords; i++) + { + *buf16++ = spi_send(dev, 0xffff); + } + } + else + { + for (i = 0; i < nwords; i++) + { + *buf++ = spi_send(dev, 0xffff); + } + } +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lc823450_spibus_initialize + * + * Description: + * Initialize the selected SPI port. + * + * Input Parameter: + * Port number (for hardware that has mutiple SPI interfaces) + * + * Returned Value: + * Valid SPI device structure reference on succcess; a NULL on failure + * + ****************************************************************************/ + +FAR struct spi_dev_s *lc823450_spibus_initialize(int port) +{ + FAR struct lc823450_spidev_s *priv = &g_spidev; + irqstate_t flags; + + DEBUGASSERT(port == 0); + + flags = enter_critical_section(); + + if ((getreg32(MCLKCNTAPB) & MCLKCNTAPB_SPI_CLKEN) == 0) + { + + /* SPI: clock / reset */ + + modifyreg32(MCLKCNTAPB, 0, MCLKCNTAPB_SPI_CLKEN); + modifyreg32(MRSTCNTAPB, 0, MRSTCNTAPB_SPI_RSTB); + + /* PORT5: clock / reset */ + + modifyreg32(MCLKCNTAPB, 0, MCLKCNTAPB_PORT5_CLKEN); + modifyreg32(MRSTCNTAPB, 0, MRSTCNTAPB_PORT5_RSTB); + +#ifndef CONFIG_SPI_OWNBUS + sem_init(&priv->exclsem, 0, 1); +#endif + + /* Initialize SPI mode. It must be done before starting SPI transfer */ + + /* PO: SPI Mode3 (default) */ + + spi_setmode(&priv->spidev, SPIDEV_MODE3); + + /* LM: MSB first, BGE: Internal clock */ + + modifyreg32(LC823450_SPI_SMD, 0, SPI_SMD_LM | SPI_SMD_BGE); + + priv->frequency = 0; + priv->actual = 0; + + lc823450_spiinitialize(); + +#ifdef CONFIG_LC823450_SPI_DMA + sem_init(&priv->dma_wait, 0, 0); + priv->hdma = lc823450_dmachannel(DMA_CHANNEL_SIOTX); + lc823450_dmarequest(priv->hdma, DMA_REQUEST_SIOTX); + + /* TX request enable */ + + putreg32(SPI_DREQ_DREQ_TX, LC823450_SPI_DREQ); + + /* use FIFO */ + + putreg32(SPI_TxFF_EN | SPI_TxFF_WL8, LC823450_SPI_FFCTL); +#endif /* CONFIG_LC823450_SPI_DMA */ + } + + leave_critical_section(flags); + + return &priv->spidev; +} diff --git a/arch/arm/src/lc823450/lc823450_spi.h b/arch/arm/src/lc823450/lc823450_spi.h new file mode 100644 index 00000000000..8c3ee500339 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_spi.h @@ -0,0 +1,188 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_spi.h + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Nobutaka Toyoshima + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_LC823450_LC823450_SPI_H +#define __ARCH_ARM_SRC_LC823450_LC823450_SPI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Addresses *******************************************************/ + +#define LC823450_SPI_REGBASE 0x40088000 + +#define LC823450_SPI_STR (LC823450_SPI_REGBASE + 0x00) /* Transfer */ +#define LC823450_SPI_SRR (LC823450_SPI_REGBASE + 0x04) /* Receive */ +#define LC823450_SPI_SMD (LC823450_SPI_REGBASE + 0x08) /* Mode */ +#define LC823450_SPI_SSR (LC823450_SPI_REGBASE + 0x0C) /* Status */ +#define LC823450_SPI_BRG (LC823450_SPI_REGBASE + 0x10) /* Baudrate Generator */ +#define LC823450_SPI_ISR (LC823450_SPI_REGBASE + 0x14) /* Interrupt Factor */ +#define LC823450_SPI_DREQ (LC823450_SPI_REGBASE + 0x18) /* DMA Request */ +#define LC823450_SPI_TxFF (LC823450_SPI_REGBASE + 0x1C) /* Transfer FIFO */ +#define LC823450_SPI_RxFF (LC823450_SPI_REGBASE + 0x20) /* Receive FIFO */ +#define LC823450_SPI_FFCTL (LC823450_SPI_REGBASE + 0x24) /* FIFO Control */ +#define LC823450_SPI_MSK (LC823450_SPI_REGBASE + 0x28) /* Interrupt Mask */ +#define LC823450_SPI_INT (LC823450_SPI_REGBASE + 0x2C) /* Interrupt Status */ +#define LC823450_SPI_CSHT (LC823450_SPI_REGBASE + 0x30) /* CS Setup/Hold time (not supported) */ +#define LC823450_SPI_CSMD (LC823450_SPI_REGBASE + 0x34) /* CS Mode (not supported) */ + +/* Register Bitfield Definitions ********************************************/ + +/* SPI Mode Register */ + +#define SPI_SMD_DMS_SHIFT (8) +#define SPI_SMD_DMS_MASK (3 << SPI_SMD_DMS_SHIFT) /* Bits 9:8: Baud Rate Control */ +# define SPI_SMD_DMS_MANU (0 << SPI_SMD_DMS_SHIFT) +# define SPI_SMD_DMS_2TCYC (1 << SPI_SMD_DMS_SHIFT) +# define SPI_SMD_DMS_4TCYC (2 << SPI_SMD_DMS_SHIFT) +#define SPI_SMD_REGCLR (1 << 6) /* Bit 6: Tx/Rx data register clear */ +#define SPI_SMD_WTR (1 << 5) /* Bit 5; Burst transfer enable */ +#define SPI_SMD_CHL (1 << 4) /* Bit 4: Transfer bit length */ +#define SPI_SMD_PO (1 << 3) /* Bit 3: SCK Polarity */ +#define SPI_SMD_LM (1 << 2) /* Bit 2: MSB first selection */ +#define SPI_SMD_BGE (1 << 1) /* Bit 1: Baudrate generator enable */ +#define SPI_SMD_SSTR (1 << 0) /* Bit 0: Frame transfer enable */ + +/* SPI Status Register */ + +#define SPI_SSR_TFF (1 << 2) /* Bit 2: STR register full */ +#define SPI_SSR_SHRF (1 << 1) /* Bit 1: Shift register full */ +#define SPI_SSR_RRF (1 << 0) /* Bit 0: SRR register full */ + +/* SPI Interrupt Factor Register */ + +#define SPI_ISR_CS_END (1 << 14) /* Bit 14: CS completion (not supported) */ +#define SPI_ISR_BURST_END (1 << 13) /* Bit 13: Burst transfer completion */ +#define SPI_ISR_RxORE (1 << 12) /* Bit 12: Rx FIFO overread */ +#define SPI_ISR_TxORE (1 << 11) /* Bit 11: Tx FIFO overread */ +#define SPI_ISR_RxOWE (1 << 10) /* Bit 10: Rx FIFO overwrite */ +#define SPI_ISR_TxOWE (1 << 9) /* Bit 9: Tx FIFO overwrite */ +#define SPI_ISR_RxFULL (1 << 8) /* Bit 8: Rx FIFO full */ +#define SPI_ISR_TxFULL (1 << 7) /* Bit 7: Tx FIFO full */ +#define SPI_ISR_RxEMP (1 << 6) /* Bit 6: Rx FIFO empty */ +#define SPI_ISR_TxEMP (1 << 5) /* Bit 5: Tx FIFO empty */ +#define SPI_ISR_RxWLM (1 << 4) /* Bit 4: Rx FIFO water level match */ +#define SPI_ISR_TxWLM (1 << 3) /* Bit 3: Tx FIFO water level match */ +#define SPI_ISR_ROWE (1 << 2) /* Bit 2: SRR register overwrite */ +#define SPI_ISR_OVE (1 << 1) /* Bit 1: overrun */ +#define SPI_ISR_SPIF (1 << 0) /* Bit 0: Frame transfer completion */ + +/* SPI FIFO contorl Register */ + +#define SPI_TxFF_EN (1 << 0) +#define SPI_TxFF_WL2 (0 << 4) +#define SPI_TxFF_WL4 (1 << 4) +#define SPI_TxFF_WL8 (2 << 4) +#define SPI_TxFF_WL12 (3 << 4) +#define SPI_TxFF_WL14 (4 << 4) + +/* SPI Interrupt Mask Register */ + +#define SPI_MSK_M_CS_END (1 << 14) +#define SPI_MSK_M_BURST_END (1 << 13) +#define SPI_MSK_M_RxORE (1 << 12) +#define SPI_MSK_M_TxORE (1 << 11) +#define SPI_MSK_M_RxOWE (1 << 10) +#define SPI_MSK_M_TxOWE (1 << 9) +#define SPI_MSK_M_RxFULL (1 << 8) +#define SPI_MSK_M_TxFULL (1 << 7) +#define SPI_MSK_M_RxEMP (1 << 6) +#define SPI_MSK_M_TxEMP (1 << 5) +#define SPI_MSK_M_RxWLM (1 << 4) +#define SPI_MSK_M_TxWLM (1 << 3) +#define SPI_MSK_M_ROWE (1 << 2) +#define SPI_MSK_M_OVE (1 << 1) +#define SPI_MSK_M_SPIF (1 << 0) + +/* SPI DMA Request */ + +#define SPI_DREQ_DREQ_RX (3 << 0) +#define SPI_DREQ_DREQ_TX (2 << 0) + +/* SPI Interrupt Status Register */ + +#define SPI_INT_I_CS_END (1 << 14) +#define SPI_INT_I_BURST_END (1 << 13) +#define SPI_INT_I_RxORE (1 << 12) +#define SPI_INT_I_TxORE (1 << 11) +#define SPI_INT_I_RxOWE (1 << 10) +#define SPI_INT_I_TxOWE (1 << 9) +#define SPI_INT_I_RxFULL (1 << 8) +#define SPI_INT_I_TxFULL (1 << 7) +#define SPI_INT_I_RxEMP (1 << 6) +#define SPI_INT_I_TxEMP (1 << 5) +#define SPI_INT_I_RxWLM (1 << 4) +#define SPI_INT_I_TxWLM (1 << 3) +#define SPI_INT_I_ROWE (1 << 2) +#define SPI_INT_I_OVE (1 << 1) +#define SPI_INT_I_SPIF (1 << 0) + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +EXTERN FAR struct spi_dev_s *lc823450_spibus_initialize(int bus); +EXTERN void lc823450_spiinitialize(void); +EXTERN void lc823450_spiselect(FAR struct spi_dev_s *dev, uint32_t devid, bool selected); +EXTERN uint8_t lc823450_spistatus(FAR struct spi_dev_s *dev, uint32_t devid); + +#ifdef CONFIG_SPI_CMDDATA +EXTERN int lc823450_spicmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __ASSEMBLY__ */ + +#endif /* __ARCH_ARM_SRC_LC823450_LC823450_SPI_H */ diff --git a/arch/arm/src/lc823450/lc823450_start.c b/arch/arm/src/lc823450/lc823450_start.c new file mode 100644 index 00000000000..7fdc0375394 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_start.c @@ -0,0 +1,425 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_start.c + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * Author: Yasuhiro Osaki + * + * 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 +#ifdef CONFIG_LASTKMSG +# include +#endif /* CONFIG_LASTKMSG */ +#include +#include + +#include "up_arch.h" +#include "up_internal.h" +#include "nvic.h" +#include + +#ifdef CONFIG_LC823450_SPIFI +# include "lc823450_spifi.h" +#endif +#include "lc823450_lowputc.h" +#include "lc823450_clockconfig.h" +#include "lc823450_syscontrol.h" + +#ifdef CONFIG_ARMV7M_MPU +# include "lc823450_mpuinit.h" +#endif + +#include "lc823450_gpio.h" + +#ifdef CONFIG_MM_MULTIHEAP +# include "lc823450_sram.h" +#endif + +#ifdef CONFIG_LC823450_SDRAM +# include "lc823450_sdram.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +int icx_boot_reason; + +/**************************************************************************** + * Private Function prototypes + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_STACK +static void go_os_start(void *pv, unsigned int nbytes) + __attribute__ ((naked, no_instrument_function, noreturn)); +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: showprogress + * + * Description: + * Print a character on the UART to show boot status. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG +# define showprogress(c) up_lowputc(c) +#else +# define showprogress(c) +#endif + +/**************************************************************************** + * Name: go_os_start + * + * Description: + * Set the IDLE stack to the + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_STACK +static void go_os_start(void *pv, unsigned int nbytes) +{ + /* Set the IDLE stack to the stack coloration value then jump to + * os_start(). We take extreme care here because were currently + * executing on this stack. + * + * We want to avoid sneak stack access generated by the compiler. + */ + + __asm__ __volatile__ + ( + "\tmov r1, r1, lsr #2\n" /* R1 = nwords = nbytes >> 2 */ + "\tbeq 2f\n" /* (should not happen) */ + + "\tbic r0, r0, #3\n" /* R0 = Aligned stackptr */ + "\tmovw r2, #0xbeef\n" /* R2 = STACK_COLOR = 0xdeadbeef */ + "\tmovt r2, #0xdead\n" + + "1:\n" /* Top of the loop */ + "\tsub r1, r1, #1\n" /* R1 nwords-- */ + "\tcmp r1, #0\n" /* Check (nwords == 0) */ + "\tstr r2, [r0], #4\n" /* Save stack color word, increment stackptr */ + "\tbne 1b\n" /* Bottom of the loop */ + + "2:\n" + "\tmov r14, #0\n" /* LR = return address (none) */ + "\tb os_start\n" /* Branch to os_start */ + ); +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: _start + * + * Description: + * This is the reset entry point. + * + ****************************************************************************/ + +#ifdef CONFIG_SPIFLASH_BOOT +__attribute__((section (".start_text"))) void __start_main(void) +#else /* CONFIG_SPIFLASH_BOOT */ +void __start(void) +#endif /* CONFIG_SPIFLASH_BOOT */ +{ + const uint32_t *src; + uint32_t *dest; + + /* Clear .bss. We'll do this inline (vs. calling memset) just to be + * certain that there are no issues with the state of global variables. + */ + +#ifdef CONFIG_FS_EVFAT + /* clear the work area in seg0 */ + + dest = (uint32_t *)0x02000000; + int i; + for (i = 0; i < 0xe00 / sizeof(uint32_t); i++) + { + *dest++ = 0; + } +#endif + + for (dest = &_sbss; dest < &_ebss; ) + { + *dest++ = 0; + } + + /* Move the initialized data section from his temporary holding spot in + * FLASH into the correct place in SRAM. The correct place in SRAM is + * give by _sdata and _edata. The temporary location is in FLASH at the + * end of all of the other read-only data (.text, .rodata) at _eronly. + */ + + for (src = &_eronly, dest = &_sdata; dest < &_edata; ) + { + *dest++ = *src++; + } + + /* run as interrupt context, before scheduler running */ + CURRENT_REGS = (uint32_t *)1; + +#ifdef CONFIG_LASTKMSG_LOWOUTS + + if (g_lastksg_buf.sig == LASTKMSG_SIG_REBOOT) + { + icx_boot_reason |= ICX_BOOT_REASON_REBOOT; + } + + /* clrear kmsg buffer */ + + memset(&g_lastksg_buf, 0, sizeof(g_lastksg_buf)); + + /* set lastkmsg signature */ + + g_lastksg_buf.sig = LASTKMSG_SIG; +#endif /* CONFIG_LASTKMSG */ + +#ifdef CONFIG_SPIFLASH_BOOT + + /* Copy any necessary code sections from FLASH to RAM. The correct + * destination in SRAM is geive by _sramfuncs and _eramfuncs. The + * temporary location is in flash after the data initalization code + * at _framfuncs. + */ + + extern uint32_t _stext_sram, _etext_sram, _ftext, _svect; + + /* copt text & vectors */ + + for (src = &_ftext, dest = &_stext_sram; dest < &_etext_sram; ) + { + *dest++ = *src++; + } + + /* vector offset */ + + putreg32((uint32_t)&_svect, NVIC_VECTAB); + +#else /* CONFIG_SPIFLASH_BOOT */ + /* vector offset */ + +#ifdef CONFIG_IPL2 + putreg32(0x02000e00, 0xe000ed08); + putreg32(0x0, 0x40080008); /* XXX: remap disable */ +#else /* CONFIG_IPL2 */ + putreg32(0x02040000, 0xe000ed08); +#endif /* CONFIG_IPL2 */ +#endif /* CONFIG_SPIFLASH_BOOT */ + + /* Mutex enable */ + modifyreg32(MRSTCNTBASIC, 0, MRSTCNTBASIC_MUTEX_RSTB); + + + /* Configure the uart so that we can get debug output as soon as possible */ + + lc823450_clockconfig(); + + + lc823450_lowsetup(); + + showprogress('A'); + + /* IPL2 don't change mux */ + +#ifdef CONFIG_IPL2 + /* GPIO2F out High in IPL2 */ + + modifyreg32(MCLKCNTAPB, 0, MCLKCNTAPB_PORT2_CLKEN); + modifyreg32(MRSTCNTAPB, 0, MRSTCNTAPB_PORT2_RSTB); + modifyreg32(rP2DT, 0, 1 << 15 /* GPIO2F */); + modifyreg32(rP2DRC, 0, 1 << 15 /* GPIO2F */); +#ifdef CONFIG_DEBUG + + /* enable TXD0 for debug */ + + modifyreg32(PMDCNT5, 0, 3 << 14); +#endif /* CONFIG_DEBUG */ +#else /* CONFIG_IPL2 */ + up_init_default_mux(); +#endif /* CONFIG_IPL2 */ + + showprogress('B'); + +#if defined(CONFIG_LC823450_SPIFI) && !defined(CONFIG_SPIFLASH_BOOT) + lc823450_spiflash_earlyinit(); +#endif /* CONFIG_LC823450_SPIFI */ + +#ifdef CONFIG_LC823450_SDRAM + lc823450_sdram_init(); +#endif /* CONFIG_LC823450_SDRAM */ + + showprogress('C'); + + /* Perform early serial initialization */ + +#ifdef USE_EARLYSERIALINIT + up_earlyserialinit(); +#endif + showprogress('D'); + + /* For the case of the separate user-/kernel-space build, perform whatever + * platform specific initialization of the user memory is required. + * Normally this just means initializing the user space .data and .bss + * segments. + */ + +#ifdef CONFIG_ARMV7M_MPU + lc823450_mpuinitialize(); + showprogress('E'); +#endif + +#ifdef CONFIG_MM_MULTIHEAP + lc823450_sram_initialize(); +#endif + + showprogress('F'); + +#ifndef CONFIG_IPL2 + _info("icx_boot_reason = 0x%x\n", icx_boot_reason); +#endif /* CONFIG_IPL2 */ + +#ifdef CONFIG_POWERBUTTON_LDOWN + if (icx_boot_reason & ICX_BOOT_REASON_POWERBUTTON) + { + int t = 1000; + while (--t && up_board_powerkey()) + { + up_udelay(10 * 1000); + } + + _info("t = %d\n", t); + + if (t) + { + up_board_poweren(0); + up_udelay(1000 * 1000); + _info("VBUS connected ?\n"); + + /* VBUS is connected after powerup by key. + * Resume PowerOn sequence. (cancel shutdown) + */ + up_board_poweren(1); + } + } +#endif /* CONFIG_POWERBUTTON_LDOWN */ + + /* Then start NuttX */ + + showprogress('\r'); + showprogress('\n'); + + (void)get_cpu_ver(); + + /* run as interrupt context, before scheduler running */ + CURRENT_REGS = NULL; + +#ifdef CONFIG_DEBUG_STACK + /* Set the IDLE stack to the coloration value and jump into os_start() */ + + go_os_start((FAR void *)&_ebss, CONFIG_IDLETHREAD_STACKSIZE); +#else + /* Call os_start() */ + + os_start(); + + /* Shoulnd't get here */ + + for (;;); +#endif +} + +#if defined(CONFIG_SPIFLASH_BOOT) +__attribute__((section (".start_gdb"))) void __start(void) +{ + /* XXX: Don't use stack in this function */ + + /* SPIF/CACHE clock */ + + putreg32(0x0402, 0x40080100); + + /* SPIF/CACHE reset */ + + putreg32(0x0402, 0x40080114); + + /* PinMux for QSPI */ + + putreg32(0x540000c0, 0x40080400); + putreg32(0x00000017, 0x40080404); + + /* BusAcc enable */ + + putreg32(0x00000303, 0x40001028); + + /* Stack initialize: */ + + __asm__ __volatile__ + ( + "ldr r0, =_vectors\n" + "bic r0, r0, #1\n" + "ldr sp, [r0, #0]\n" + ); + + __start_main(); + + /* not reached */ +} +#endif /* defined(CONFIG_SPIFLASH_BOOT) */ diff --git a/arch/arm/src/lc823450/lc823450_syscontrol.c b/arch/arm/src/lc823450/lc823450_syscontrol.c new file mode 100644 index 00000000000..b439aa19fac --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_syscontrol.c @@ -0,0 +1,211 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_syscontrol.c + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * Author: Nobutaka Toyoshima + * + * 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 "chip.h" +#include "up_arch.h" +#include "up_internal.h" + +#include "lc823450_gpio.h" +#include "lc823450_syscontrol.h" +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct clk_st lc823450_clocks[] = LC823450_CLOCKS; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +uint8_t cpu_ver; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: get_cpu_ver + ****************************************************************************/ + +uint32_t get_cpu_ver(void) +{ + uint32_t ret = 0; + uint32_t reg = getreg32(MODEM) & MODEM_MAV_MASK; + + switch (reg) + { + case MODEM_MAV_ES1: + _info("ES1 \n"); + break; + + case MODEM_MAV_ES2: + _info("ES2 \n"); + ret = 1; + break; + + default: + _info("??? \n"); + break; + } + cpu_ver = ret; + return ret; +} + + +/**************************************************************************** + * Name: mod_stby_regs + * + * Input parameters: + * enabits : specify regions to be enabled + * disbits : specify regions to be disabled + * + ****************************************************************************/ + +#ifdef CONFIG_LC823450_LSISTBY +void mod_stby_regs(uint32_t enabits, uint32_t disbits) +{ + /* TODO : need to lock */ + + /* isolate first if needed */ + + modifyreg32(ISOCNT, disbits, 0); + + /* then modify LSTSTBY register */ + + modifyreg32(LSISTBY, enabits, disbits); + + if (enabits) + { + /* stand-by to active case */ + /* assumption: the specified blocks are already isolated */ + + up_udelay(100); /* need to wait 100us */ + + /* then disable isolation for the region */ + + modifyreg32(ISOCNT, 0, enabits); + } + + /* _info("ISOCNT=0x%x, LSISTBY=0x%x \n", getreg32(ISOCNT), getreg32(LSISTBY)); */ +} +#endif /* CONFIG_LC823450_LSISTBY */ + + +/**************************************************************************** + * Name: up_enable_clk + ****************************************************************************/ + +void up_enable_clk(enum clock_e clk) +{ + irqstate_t flags; + flags = enter_critical_section(); + + ASSERT(clk < LC823450_CLOCK_NUM); + + if (lc823450_clocks[clk].count++ == 0) + { + modifyreg32(lc823450_clocks[clk].regaddr, + 0, lc823450_clocks[clk].regmask); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: up_disable_clk + ****************************************************************************/ + + +void up_disable_clk(enum clock_e clk) +{ + irqstate_t flags; + flags = enter_critical_section(); + + ASSERT(clk < LC823450_CLOCK_NUM); + + if (--lc823450_clocks[clk].count == 0) + { + modifyreg32(lc823450_clocks[clk].regaddr, + lc823450_clocks[clk].regmask, 0); + } + + /* ASSERT(lc823450_clocks[clk].count >= 0); */ + + if (lc823450_clocks[clk].count < 0) + { + lc823450_clocks[clk].count = 0; + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: lc823450_clock_dump + ****************************************************************************/ + +void lc823450_clock_dump(void) +{ + int i; + for (i = 0; i < LC823450_CLOCK_NUM; i++) + { + _info("%s:%d\n", lc823450_clocks[i].name, + lc823450_clocks[i].count); + } +} diff --git a/arch/arm/src/lc823450/lc823450_syscontrol.h b/arch/arm/src/lc823450/lc823450_syscontrol.h new file mode 100644 index 00000000000..65c869e48e4 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_syscontrol.h @@ -0,0 +1,310 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_syscontrol.h + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * Author: Nobutaka Toyoshima + * + * 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. + * + ****************************************************************************/ + + +#ifndef __ARCH_ARM_SRC_LC823450_LC823450_SYSCONTROL_H +#define __ARCH_ARM_SRC_LC823450_LC823450_SYSCONTROL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + + +#define LC823450_SYSCONTROL_REGBASE 0x40080000 + +#define CORECNT (LC823450_SYSCONTROL_REGBASE + 0x0000) +#define CORECNT_C1CLKEN (1 << 0) +#define CORECNT_C1RSTN (1 << 1) + +#define REMAP (LC823450_SYSCONTROL_REGBASE + 0x0008) + +#define MEMEN4 (LC823450_SYSCONTROL_REGBASE + 0x0024) +#define MEMEN4_HWAIT (1 << 0) +#define MEMEN4_DWAIT (1 << 1) + +#define LSISTBY (LC823450_SYSCONTROL_REGBASE + 0x0028) +#define LSISTBY_STBYA (1 << 0) /* Audio */ +#define LSISTBY_STBYB (1 << 1) /* SRAM */ +#define LSISTBY_STBYC (1 << 2) /* SRAM */ +#define LSISTBY_STBYD (1 << 3) /* SRAM + ROM (DSP) */ +#define LSISTBY_STBYE (1 << 4) /* USB */ +#define LSISTBY_STBYG (1 << 6) /* S-Flash cache */ +#define LSISTBY_STBYH (1 << 7) /* SD/MS */ +#define LSISTBY_STBYI (1 << 8) /* Internal ROM */ + +#define ISOCNT (LC823450_SYSCONTROL_REGBASE + 0x002c) + +#define LOCKUPR (LC823450_SYSCONTROL_REGBASE + 0x0044) +#define LOCKUPR_LOCKUPR0 (1 << 0) +#define LOCKUPR_LOCKUPR1 (1 << 1) + +#define MODEM (LC823450_SYSCONTROL_REGBASE + 0x00FC) +#define MODEM_MAV_MASK (15 << 24) +#define MODEM_MAV_ES1 (1 << 24) +#define MODEM_MAV_ES2 (2 << 24) + +#define MCLKCNTBASIC (LC823450_SYSCONTROL_REGBASE + 0x0100) +#define MCLKCNTBASIC_EXTMEMC_CLKEN (1 << 0) +#define MCLKCNTBASIC_SFIF_CLKEN (1 << 1) +#define MCLKCNTBASIC_USBHOST_CLKEN (1 << 2) +#define MCLKCNTBASIC_DMAC_CLKEN (1 << 4) +#define MCLKCNTBASIC_CACHE_CLKEN (1 << 10) +#define MCLKCNTBASIC_USBDEV_CLKEN (1 << 11) + +#define MCLKCNTEXT1 (LC823450_SYSCONTROL_REGBASE + 0x0104) +#define MCLKCNTEXT1_MTM0_CLKEN (1 << 0) +#define MCLKCNTEXT1_MTM1_CLKEN (1 << 1) +#define MCLKCNTEXT1_MTM2_CLKEN (1 << 2) +#define MCLKCNTEXT1_MTM3_CLKEN (1 << 3) +#define MCLKCNTEXT1_PTM0_CLKEN (1 << 4) +#define MCLKCNTEXT1_PTM1_CLKEN (1 << 5) +#define MCLKCNTEXT1_PTM2_CLKEN (1 << 6) +#define MCLKCNTEXT1_SDIF0_CLKEN (1 << 8) +#define MCLKCNTEXT1_SDIF1_CLKEN (1 << 9) +#define MCLKCNTEXT1_SDIF2_CLKEN (1 << 10) +#define MCLKCNTEXT1_MSHOST_CLKEN (1 << 11) +#define MCLKCNTEXT1_MSPB_CLKEN (1 << 12) +#define MCLKCNTEXT1_MTM0C_CLKEN (1 << 24) +#define MCLKCNTEXT1_MTM1C_CLKEN (1 << 25) +#define MCLKCNTEXT1_MTM2C_CLKEN (1 << 26) +#define MCLKCNTEXT1_MTM3C_CLKEN (1 << 27) +#define MCLKCNTEXT1_PTM0C_CLKEN (1 << 28) +#define MCLKCNTEXT1_PTM1C_CLKEN (1 << 29) +#define MCLKCNTEXT1_PTM2C_CLKEN (1 << 30) + +#define MCLKCNTEXT4 (LC823450_SYSCONTROL_REGBASE + 0x010c) +#define MCLKCNTEXT4_SDRAMC_CLKEN0 (1 << 0) +#define MCLKCNTEXT4_SDRAMC_CLKEN1 (1 << 1) + +#define MCLKCNTAPB (LC823450_SYSCONTROL_REGBASE + 0x0110) +#define MCLKCNTAPB_PORT0_CLKEN (1 << 0) +#define MCLKCNTAPB_PORT1_CLKEN (1 << 1) +#define MCLKCNTAPB_PORT2_CLKEN (1 << 2) +#define MCLKCNTAPB_PORT3_CLKEN (1 << 3) +#define MCLKCNTAPB_PORT4_CLKEN (1 << 4) +#define MCLKCNTAPB_PORT5_CLKEN (1 << 5) +#define MCLKCNTAPB_ADC_CLKEN (1 << 6) +#define MCLKCNTAPB_SPI_CLKEN (1 << 7) +#define MCLKCNTAPB_I2C0_CLKEN (1 << 8) +#define MCLKCNTAPB_I2C1_CLKEN (1 << 9) +#define MCLKCNTAPB_UART0_CLKEN (1 << 10) +#define MCLKCNTAPB_UART1_CLKEN (1 << 11) +#define MCLKCNTAPB_UART2_CLKEN (1 << 12) +#define MCLKCNTAPB_RTC_CLKEN (1 << 13) +#define MCLKCNTAPB_GPO_CLKEN (1 << 14) +#define MCLKCNTAPB_UART0IF_CLKEN (1 << 24) +#define MCLKCNTAPB_UART1IF_CLKEN (1 << 25) +#define MCLKCNTAPB_UART2IF_CLKEN (1 << 26) + +#define MRSTCNTBASIC (LC823450_SYSCONTROL_REGBASE + 0x0114) +#define MRSTCNTBASIC_EXTMEMC_RSTB (1 << 0) +#define MRSTCNTBASIC_SFIF_RSTB (1 << 1) +#define MRSTCNTBASIC_USB_RSTB (1 << 2) +#define MRSTCNTBASIC_IRQCNT_RSTB (1 << 3) +#define MRSTCNTBASIC_DMAC_RSTB (1 << 4) +#define MRSTCNTBASIC_MUTEX_RSTB (1 << 8) +#define MRSTCNTBASIC_DSPCMD_RSTB (1 << 9) +#define MRSTCNTBASIC_CACHE_RSTB (1 << 10) +#define MRSTCNTBASIC_USBDEV_RSTB (1 << 11) + +#define MRSTCNTEXT1 (LC823450_SYSCONTROL_REGBASE + 0x0118) +#define MRSTCNTEXT1_MTM0_RSTB (1 << 0) +#define MRSTCNTEXT1_MTM1_RSTB (1 << 1) +#define MRSTCNTEXT1_MTM2_RSTB (1 << 2) +#define MRSTCNTEXT1_MTM3_RSTB (1 << 3) +#define MRSTCNTEXT1_PTM0_RSTB (1 << 4) +#define MRSTCNTEXT1_PTM1_RSTB (1 << 5) +#define MRSTCNTEXT1_PTM2_RSTB (1 << 6) +#define MRSTCNTEXT1_SDIF0_RSTB (1 << 8) +#define MRSTCNTEXT1_SDIF1_RSTB (1 << 9) +#define MRSTCNTEXT1_SDIF2_RSTB (1 << 10) +#define MRSTCNTEXT1_MSIF_RSTB (1 << 11) + +#define MRSTCNTEXT4 (LC823450_SYSCONTROL_REGBASE + 0x0120) +#define MRSTCNTEXT4_SDRAMC_RSTB (1 << 0) + +#define MRSTCNTAPB (LC823450_SYSCONTROL_REGBASE + 0x0124) +#define MRSTCNTAPB_PORT0_RSTB (1 << 0) +#define MRSTCNTAPB_PORT1_RSTB (1 << 1) +#define MRSTCNTAPB_PORT2_RSTB (1 << 2) +#define MRSTCNTAPB_PORT3_RSTB (1 << 3) +#define MRSTCNTAPB_PORT4_RSTB (1 << 4) +#define MRSTCNTAPB_PORT5_RSTB (1 << 5) +#define MRSTCNTAPB_ADC_RSTB (1 << 6) +#define MRSTCNTAPB_SPI_RSTB (1 << 7) +#define MRSTCNTAPB_I2C0_RSTB (1 << 8) +#define MRSTCNTAPB_I2C1_RSTB (1 << 9) +#define MRSTCNTAPB_UART0_RSTB (1 << 10) +#define MRSTCNTAPB_UART1_RSTB (1 << 11) +#define MRSTCNTAPB_UART2_RSTB (1 << 12) +#define MRSTCNTAPB_RTC_RSTB (1 << 13) + +#define PMDCNT0 (LC823450_SYSCONTROL_REGBASE + 0x0400) +#define PMDCNT1 (LC823450_SYSCONTROL_REGBASE + 0x0404) +#define PMDCNT2 (LC823450_SYSCONTROL_REGBASE + 0x0408) +#define PMDCNT3 (LC823450_SYSCONTROL_REGBASE + 0x040c) +#define PMDCNT4 (LC823450_SYSCONTROL_REGBASE + 0x0410) +#define PMDCNT5 (LC823450_SYSCONTROL_REGBASE + 0x0414) + +#define PUDCNT0 (LC823450_SYSCONTROL_REGBASE + 0x044c) +#define PUDCNT1 (LC823450_SYSCONTROL_REGBASE + 0x0450) +#define PUDCNT2 (LC823450_SYSCONTROL_REGBASE + 0x0454) +#define PUDCNT3 (LC823450_SYSCONTROL_REGBASE + 0x0458) +#define PUDCNT4 (LC823450_SYSCONTROL_REGBASE + 0x045c) +#define PUDCNT5 (LC823450_SYSCONTROL_REGBASE + 0x0460) +#define PUDCNT6 (LC823450_SYSCONTROL_REGBASE + 0x0464) + +#define PTDRVCNT0 (LC823450_SYSCONTROL_REGBASE + 0x0430) +#define PTDRVCNT1 (LC823450_SYSCONTROL_REGBASE + 0x0434) +#define PTDRVCNT2 (LC823450_SYSCONTROL_REGBASE + 0x0438) +#define PTDRVCNT3 (LC823450_SYSCONTROL_REGBASE + 0x043c) +#define PTDRVCNT4 (LC823450_SYSCONTROL_REGBASE + 0x0440) +#define PTDRVCNT5 (LC823450_SYSCONTROL_REGBASE + 0x0444) +#define PTDRVCNT6 (LC823450_SYSCONTROL_REGBASE + 0x0448) + +#define SDCTL (LC823450_SYSCONTROL_REGBASE + 0x0800) +#define SDCTL_COREVLT (1 << 31) +#define SDCTL_MMCVLT0_18V (1 << 4) +#define SDCTL_ACSMODE0_MASK (7 << 1) +#define SDCTL_ACSMODE0_HS (2 << 1) +#define SDCTL_ACSMODE0_MMCDDR (4 << 1) +#define SDCTL_SDMMC0_MMC (1 << 0) + + +#define DREQ0_3 (LC823450_SYSCONTROL_REGBASE + 0x808) +#define DREQ4_7 (LC823450_SYSCONTROL_REGBASE + 0x80c) +#define DREQ8_C (LC823450_SYSCONTROL_REGBASE + 0x810) +#define DREQD_F (LC823450_SYSCONTROL_REGBASE + 0x814) +#define CACHE_CTL (LC823450_SYSCONTROL_REGBASE + 0x0818) +#define CACHE_CTL_USE (1 << 0) +#define BMODE_CNT (LC823450_SYSCONTROL_REGBASE + 0x81c) +#define BMODE_CNT_BMODE0EN (1 << 0) +#define BMODE_DT (LC823450_SYSCONTROL_REGBASE + 0x820) +#define BMODE_DT_BMODE0DT (1 << 0) +#define BMODE_DT_XTALINFO_MASK (3 << 4) +#define BMODE_DT_XTALINFO_20 (2 << 4) +#define BMODE_DT_XTALINFO_24 (0 << 4) +#define USBCNT (LC823450_SYSCONTROL_REGBASE + 0x834) +#define USBCNT_ANPD (1 << 1) +#define USBCNT_CLK24MHZ (1 << 2) +#define USBCNT_CLK20MHZ (6 << 2) +#define USBCNT_CLK_MASK (7 << 2) +#define USBCNT_CRYCNTSW24MHZ (1 << 5) +#define USBCNT_CRYCNTSW20MHZ (1 << 5) +#define USBCNT_CRYCNTSW_MASK (7 << 5) +#define USBCNT_VBUS_VALID (1 << 8) +#define USBCNT_RSM_CONT (1 << 11) +#define USBSTAT (LC823450_SYSCONTROL_REGBASE + 0x838) +#define USBSTAT_LINESTE_MASK (3 << 0) +#define USBSTAT_LINESTE_0 (1 << 0) +#define USBSTAT_LINESTE_1 (1 << 1) + +#define SFIFSEL (LC823450_SYSCONTROL_REGBASE + 0x83c) +#define SDRAMIFSEL (LC823450_SYSCONTROL_REGBASE + 0x840) + +#define I2CMODE (LC823450_SYSCONTROL_REGBASE + 0x844) +#define I2CMODE0 (1 << 0) +#define I2CMODE1 (1 << 1) + +/* GPIO */ +#define PORT0_BASE 0x40081000 +#define rP0DT (PORT0_BASE + 0x0000 + 0x04) +#define rP1DT (PORT0_BASE + 0x1000 + 0x04) +#define rP2DT (PORT0_BASE + 0x2000 + 0x04) +#define rP3DT (PORT0_BASE + 0x3000 + 0x04) +#define rP4DT (PORT0_BASE + 0x4000 + 0x04) +#define rP5DT (PORT0_BASE + 0x5000 + 0x04) + +#define rP0DRC (PORT0_BASE + 0x0000 + 0x00) +#define rP1DRC (PORT0_BASE + 0x1000 + 0x00) +#define rP2DRC (PORT0_BASE + 0x2000 + 0x00) +#define rP3DRC (PORT0_BASE + 0x3000 + 0x00) +#define rP4DRC (PORT0_BASE + 0x4000 + 0x00) +#define rP5DRC (PORT0_BASE + 0x5000 + 0x00) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + + +uint32_t get_cpu_ver(void); +void init_default_mux(void); +void lc823450_clock_dump(void); + +#ifdef CONFIG_LC823450_LSISTBY +void mod_stby_regs(uint32_t clearbits, uint32_t setbits); +void lc823450_mod_stby_regs(uint32_t clearbits, uint32_t setbits); +#else +# define mod_stby_regs(...) +# define lc823450_mod_stby_regs(...) +#endif + + +#if defined(__cplusplus) +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_LC823450_LC823450_SYSCONTROL_H */ diff --git a/arch/arm/src/lc823450/lc823450_testset.c b/arch/arm/src/lc823450/lc823450_testset.c new file mode 100644 index 00000000000..f27aebb1102 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_testset.c @@ -0,0 +1,124 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_testset.c + * + * Copyright (C) 2016-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * + * 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 "up_arch.h" + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define LC823450_MUTEX_REG_BASE 0x40005000 +#define MUTEX_REG_MUTEX0 (LC823450_MUTEX_REG_BASE + 0x00) + + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + + + +/**************************************************************************** + * Name: up_testset + * + * Description: + * Perform and atomic test and set operation on the provided spinlock. + * + * This function must be provided via the architecture-specific logic. + * + * Note: + * LC823450 does not support ldrex/strex. Instead, MUTEX is provided. + * + * Input Parameters: + * lock - The address of spinlock object. + * + * Returned Value: + * The spinlock is always locked upon return. The value of previous value + * of the spinlock variable is returned, either SP_LOCKED if the spinlock + * as previously locked (meaning that the test-and-set operation failed to + * obtain the lock) or SP_UNLOCKED if the spinlock was previously unlocked + * (meaning that we successfully obtained the lock) + * + ****************************************************************************/ + +spinlock_t up_testset(volatile FAR spinlock_t *lock) +{ + uint32_t val; + spinlock_t ret; + irqstate_t flags; + + flags = up_irq_save(); + + val = (up_cpu_index() << 16) | 0x1; + + do + { + putreg32(val, MUTEX_REG_MUTEX0); + } + while (getreg32(MUTEX_REG_MUTEX0) != val); + + ret = *lock; + + if (ret == SP_UNLOCKED) + { + *lock = SP_LOCKED; + } + + val = (up_cpu_index() << 16) | 0x0; + putreg32(val, MUTEX_REG_MUTEX0); + + up_irq_restore(flags); + + return ret; +} diff --git a/arch/arm/src/lc823450/lc823450_timerisr.c b/arch/arm/src/lc823450/lc823450_timerisr.c new file mode 100644 index 00000000000..b14940a3795 --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_timerisr.c @@ -0,0 +1,619 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_timerisr.c + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * Author: Asumi Noguchi + * + * 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 "nvic.h" +#include "clock/clock.h" +#include "up_internal.h" +#include "up_arch.h" + +#include "chip.h" +#include "lc823450_gpio.h" +#ifdef CONFIG_LC823450_MTM0_TICK +# include "lc823450_pwm.h" +#endif +#include "lc823450_syscontrol.h" +#include "lc823450_clockconfig.h" +#include "lc823450_serial.h" + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define SYSTICK_RELOAD ((lc823450_get_systemfreq() / CLK_TCK) - 1) + + +/* TIMER_PIN will be used to check the interval */ +#define TIMER_PIN (GPIO_PORT5|GPIO_PIN7) + +/* #define CHECK_INTERVAL */ + +#ifdef CONFIG_LC823450_MTM0_TICK +# define rMT00STS (LC823450_MTM0_REGBASE + LC823450_MTM_0STS) +# define rMT00A (LC823450_MTM0_REGBASE + LC823450_MTM_0A) +# define rMT00B (LC823450_MTM0_REGBASE + LC823450_MTM_0B) +# define rMT00CTL (LC823450_MTM0_REGBASE + LC823450_MTM_0CTL) +# define rMT00PSCL (LC823450_MTM0_REGBASE + LC823450_MTM_0PSCL) +# define rMT00TIER (LC823450_MTM0_REGBASE + LC823450_MTM_0TIER) +# define rMT00OPR (LC823450_MTM0_REGBASE + LC823450_MTM_OPR) +# define rMT00CNT (LC823450_MTM0_REGBASE + LC823450_MTM_0CNT) +# define MTM_RELOAD (XT1OSC_CLK / (CLK_TCK * 10)) +#endif + +#ifdef CONFIG_HRT_TIMER +# define LC823450_MTM2_REGBASE 0x40045000 +# define rMT20STS (LC823450_MTM2_REGBASE + LC823450_MTM_0STS) +# define rMT20A (LC823450_MTM2_REGBASE + LC823450_MTM_0A) +# define rMT20PSCL (LC823450_MTM2_REGBASE + LC823450_MTM_0PSCL) +# define rMT20TIER (LC823450_MTM2_REGBASE + LC823450_MTM_0TIER) +# define rMT2OPR (LC823450_MTM2_REGBASE + LC823450_MTM_OPR) +# define rMT20CNT (LC823450_MTM2_REGBASE + LC823450_MTM_0CNT) +#endif /* CONFIG_HRT_TIMER */ + +#ifdef CONFIG_PROFILE +# define LC823450_MTM3_REGBASE 0x40046000 +# define rMT30STS (LC823450_MTM3_REGBASE + LC823450_MTM_0STS) +# define rMT30A (LC823450_MTM3_REGBASE + LC823450_MTM_0A) +# define rMT30B (LC823450_MTM3_REGBASE + LC823450_MTM_0B) +# define rMT30CTL (LC823450_MTM3_REGBASE + LC823450_MTM_0CTL) +# define rMT30PSCL (LC823450_MTM3_REGBASE + LC823450_MTM_0PSCL) +# define rMT30TIER (LC823450_MTM3_REGBASE + LC823450_MTM_0TIER) +# define rMT30OPR (LC823450_MTM3_REGBASE + LC823450_MTM_OPR) +# define rMT30CNT (LC823450_MTM3_REGBASE + LC823450_MTM_0CNT) +#endif /* CONFIG_PROFILE */ + + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CHECK_INTERVAL +static bool _timer_val = true; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef CONFIG_PROFILE +uint32_t profile_data[CONFIG_PROFILE_SAMPLES]; +int profile_ptr; +int profile_en; +#endif /* CONFIG_PROFILE */ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + + +/**************************************************************************** + * Name: up_proftimerisr + ****************************************************************************/ + +#ifdef CONFIG_PROFILE +static int dbg; +int up_proftimerisr(int irq, uint32_t *regs, FAR void *arg) +{ + putreg32(1 << 1, rMT30STS); + if (profile_en) + { + if (profile_ptr != CONFIG_PROFILE_SAMPLES) + { + ASSERT(current_regs); + profile_data[profile_ptr++] = current_regs[REG_R15]; + } + else + { + profile_en = 0; + _info("PROFILING DONE\n"); + } + + } + return 0; +} +#endif /* CONFIG_PROFILE */ + + +/**************************************************************************** + * Name: up_timerisr + ****************************************************************************/ + +int up_timerisr(int irq, uint32_t *regs, FAR void *arg) +{ + /* Process timer interrupt */ + +#ifdef CONFIG_DVFS + extern void lc823450_dvfs_tick_callback(void); + lc823450_dvfs_tick_callback(); +#endif + +#ifdef CONFIG_LC823450_MTM0_TICK + /* Clear the interrupt (BEVT) */ + putreg32(1 << 1, rMT00STS); +#endif + + sched_process_timer(); + +#ifdef CONFIG_LCA_SOUNDSKIP_CHECK + extern void lca_check_soundskip(void); + lca_check_soundskip(); +#endif + +#ifdef CHECK_INTERVAL + _timer_val = !_timer_val; + lc823450_gpio_write(TIMER_PIN, _timer_val); +#endif +#ifdef CONFIG_HSUART + hsuart_wdtimer(); +#endif /* CONFIG_HSUART */ + + return 0; +} + + +#ifdef CONFIG_HRT_TIMER + +#include + +struct hrt_s +{ + dq_entry_t ent; + sem_t sem; + int usec; +}; + +static dq_queue_t hrt_timer_queue; +static void hrt_queue_refresh(void); +static void hrt_usleep_setup(void); +static int hrt_interrupt(int irq, FAR void *context, FAR void *arg); +static void hrt_usleep_add(struct hrt_s *phrt); + +static void hrt_queue_refresh(void) +{ + int elapsed; + dq_entry_t *pent; + struct hrt_s *tmp; + irqstate_t flags; + + flags = enter_critical_section(); + elapsed = (uint64_t)getreg32(rMT20CNT) * (1000 * 1000) * 10 / XT1OSC_CLK; + + for (pent = hrt_timer_queue.head; pent; pent = dq_next(pent)) + { + tmp = container_of(pent, struct hrt_s, ent); + tmp->usec -= elapsed; + } + +cont: + /* serch for expired */ + for (pent = hrt_timer_queue.head; pent; pent = dq_next(pent)) + { + tmp = container_of(pent, struct hrt_s, ent); + if (tmp->usec <= 0) + { + dq_rem(pent, &hrt_timer_queue); + sem_post(&tmp->sem); + goto cont; + } + else + { + break; + } + } + + leave_critical_section(flags); +} + +static void hrt_usleep_setup(void) +{ + uint32_t count; + struct hrt_s *head; + irqstate_t flags; + + flags = enter_critical_section(); + head = container_of(hrt_timer_queue.head, struct hrt_s, ent); + if (head == NULL) + { + /* MTM2: disable clocking */ + + modifyreg32(MCLKCNTEXT1, MCLKCNTEXT1_MTM2C_CLKEN, 0x0); + modifyreg32(MCLKCNTEXT1, MCLKCNTEXT1_MTM2_CLKEN, 0x0); + leave_critical_section(flags); + return; + } + + /* MTM2: enable clocking */ + + modifyreg32(MCLKCNTEXT1, 0x0, MCLKCNTEXT1_MTM2_CLKEN); + modifyreg32(MCLKCNTEXT1, 0x0, MCLKCNTEXT1_MTM2C_CLKEN); + + count = (uint64_t)XT1OSC_CLK * head->usec / (1000 * 1000) / 10; + + if (count >= 0x8000) + { + count = 0x7fff; + } + + putreg32(0, rMT20CNT); /* counter */ + putreg32(count, rMT20A); /* AEVT counter */ + + up_enable_irq(LC823450_IRQ_MTIMER20); + + /* Enable MTM2-Ch0 */ + + putreg32(1, rMT2OPR); + leave_critical_section(flags); +} + +static int hrt_interrupt(int irq, FAR void *context, FAR void *arg) +{ + /* Disable MTM2-Ch0 */ + + putreg32(0, rMT2OPR); + + /* clear AEVT Interrupt */ + + putreg32(1 << 0, rMT20STS); + + hrt_queue_refresh(); + hrt_usleep_setup(); + return OK; +} + +static void hrt_usleep_add(struct hrt_s *phrt) +{ + dq_entry_t *pent; + irqstate_t flags; + + /* Disable MTM2-Ch0 */ + + putreg32(0, rMT2OPR); + + hrt_queue_refresh(); + + flags = enter_critical_section(); + + /* add phrt to hrt_timer_queue */ + + for (pent = hrt_timer_queue.head; pent; pent = dq_next(pent)) + { + struct hrt_s *tmp = container_of(pent, struct hrt_s, ent); + if (tmp->usec >= phrt->usec) + { + break; + } + } + if (pent) + { + dq_addbefore(pent, &phrt->ent, &hrt_timer_queue); + } + else + { + dq_addlast(&phrt->ent, &hrt_timer_queue); + } + + leave_critical_section(flags); + + hrt_usleep_setup(); +} + +extern int g_taskid_init; + + +int up_hrttimer_usleep(unsigned int usec) +{ + struct hrt_s hrt; + + sem_init(&hrt.sem, 0, 0); + hrt.usec = usec; + + hrt_usleep_add(&hrt); + sem_wait(&hrt.sem); + + return 0; +} + + +#endif /* CONFIG_HRT_TIMER */ + +/**************************************************************************** + * Name: arm_timer_initialize + ****************************************************************************/ + +void arm_timer_initialize(void) +{ +#ifdef CHECK_INTERVAL + lc823450_gpio_config(TIMER_PIN | + GPIO_MODE_OUTPUT | + GPIO_VALUE_ONE); +#endif + +#ifdef CONFIG_HRT_TIMER + modifyreg32(MCLKCNTEXT1, 0x0, MCLKCNTEXT1_MTM2_CLKEN); + modifyreg32(MCLKCNTEXT1, 0x0, MCLKCNTEXT1_MTM2C_CLKEN); + + /* MTM2: unreset */ + + modifyreg32(MRSTCNTEXT1, 0x0, MRSTCNTEXT1_MTM2_RSTB); + + /* Enable AEVT Interrupt */ + + putreg32(1 << 0, rMT20TIER); + + /* Set prescaler to (1/10) */ + + putreg32(10 - 1, rMT20PSCL); + + modifyreg32(MCLKCNTEXT1, MCLKCNTEXT1_MTM2C_CLKEN, 0); + modifyreg32(MCLKCNTEXT1, MCLKCNTEXT1_MTM2_CLKEN, 0); + + (void)irq_attach(LC823450_IRQ_MTIMER20, (xcpt_t)hrt_interrupt, NULL); +#endif /* CONFIG_HRT_TIMER */ +#ifdef CONFIG_PROFILE + + /* MTM3: enable clocking */ + + modifyreg32(MCLKCNTEXT1, 0x0, MCLKCNTEXT1_MTM3_CLKEN); + modifyreg32(MCLKCNTEXT1, 0x0, MCLKCNTEXT1_MTM3C_CLKEN); + + /* MTM3: unreset */ + + modifyreg32(MRSTCNTEXT1, 0x0, MRSTCNTEXT1_MTM3_RSTB); + + /* Input clock for the MTM3 is XT1 (i.e. 24M or 20M) */ + /* then the clock will be set to 1/10 by the internal divider */ + /* To implement 10ms timer, ADT=0, BDT=MTM_RELOAD */ + + putreg32(0, rMT30A); /* AEVT counter */ + putreg32((XT1OSC_CLK / 1010) - 1, rMT30B); /* BEVT counter */ + + /* Clear the counter by BEVT */ + + putreg32(0x80, rMT30CTL); + + /* Set prescaler to 9 : (1/10) */ + + putreg32(9, rMT30PSCL); + + /* Enable BEVT Interrupt */ + + putreg32(1 << 1, rMT30TIER); + + /* Enable MTM3-Ch0 */ + + putreg32(1, rMT30OPR); + + /* Attach the timer interrupt vector */ + + (void)irq_attach(LC823450_IRQ_MTIMER30, (xcpt_t)up_proftimerisr, NULL); + + /* And enable the system timer interrupt */ + + up_enable_irq(LC823450_IRQ_MTIMER30); + +#endif /* CONFIG_PROFILE */ + +#ifdef CONFIG_LC823450_MTM0_TICK + + /* MTM0: enable clocking */ + + modifyreg32(MCLKCNTEXT1, 0x0, MCLKCNTEXT1_MTM0_CLKEN); + modifyreg32(MCLKCNTEXT1, 0x0, MCLKCNTEXT1_MTM0C_CLKEN); + + /* MTM0: unreset */ + + modifyreg32(MRSTCNTEXT1, 0x0, MRSTCNTEXT1_MTM0_RSTB); + + /* Input clock for the MTM0 is XT1 (i.e. 24M or 20M) */ + /* then the clock will be set to 1/10 by the internal divider */ + /* To implement the tick timer, ADT=0, BDT=MTM_RELOAD-1 */ + + putreg32(0, rMT00A); /* AEVT counter */ + putreg32(MTM_RELOAD - 1, rMT00B); /* BEVT counter */ + + /* Clear the counter by BEVT */ + + putreg32(0x80, rMT00CTL); + + /* Set prescaler to 9 : (1/10) */ + + putreg32(9, rMT00PSCL); + + /* Enable BEVT Interrupt */ + + putreg32(1 << 1, rMT00TIER); + + /* Enable MTM0-Ch0 */ + + putreg32(1, rMT00OPR); + + /* Attach the timer interrupt vector */ + + (void)irq_attach(LC823450_IRQ_MTIMER00, (xcpt_t)up_timerisr, NULL); + + /* And enable the system timer interrupt */ + + up_enable_irq(LC823450_IRQ_MTIMER00); +#else + uint32_t regval; + + /* Set the SysTick interrupt to the default priority */ + + regval = getreg32(NVIC_SYSH12_15_PRIORITY); + regval &= ~NVIC_SYSH_PRIORITY_PR15_MASK; + regval |= (NVIC_SYSH_PRIORITY_DEFAULT << NVIC_SYSH_PRIORITY_PR15_SHIFT); + putreg32(regval, NVIC_SYSH12_15_PRIORITY); + + /* Make sure that the SYSTICK clock source is set correctly */ + +#if 0 /* Does not work. Comes up with HCLK source and I can't change it */ + regval = getreg32(NVIC_SYSTICK_CTRL); +#if CONFIG_LC823450_SYSTICK_HCLKd8 + regval &= ~NVIC_SYSTICK_CTRL_CLKSOURCE; +#else + regval |= NVIC_SYSTICK_CTRL_CLKSOURCE; +#endif + putreg32(regval, NVIC_SYSTICK_CTRL); +#endif + + /* Configure SysTick to interrupt at the requested rate */ + + putreg32(SYSTICK_RELOAD, NVIC_SYSTICK_RELOAD); + + /* Attach the timer interrupt vector */ + + (void)irq_attach(LC823450_IRQ_SYSTICK, (xcpt_t)up_timerisr, NULL); + + /* Enable SysTick interrupts */ + + putreg32((NVIC_SYSTICK_CTRL_CLKSOURCE | + NVIC_SYSTICK_CTRL_TICKINT | + NVIC_SYSTICK_CTRL_ENABLE), + NVIC_SYSTICK_CTRL); + + /* And enable the timer interrupt */ + + up_enable_irq(LC823450_IRQ_SYSTICK); +#endif +} + + +static uint64_t up_get_timer_fraction(void) +{ +#ifdef CONFIG_LC823450_MTM0_TICK + uint32_t regval; + uint64_t nsec; + + /* read the counter */ + + regval = getreg32(rMT00CNT); + + /* check if the timer interrupt is underway */ + + if (getreg32(rMT00STS) & 0x2 && regval < (MTM_RELOAD/10)) + { + return NSEC_PER_TICK; + } + + nsec = ((uint64_t)regval * NSEC_PER_TICK / MTM_RELOAD); + return nsec; +#else + uint32_t cur; + uint64_t nsec; + + /* read the counter */ + + cur = getreg32(NVIC_SYSTICK_CURRENT); + + /* check if the systick interrupt is pending or active */ + + if ((getreg32(0xE000ED04) & (1 << 26) || + getreg32(0xE000ED24) & (1 << 11)) + && (SYSTICK_RELOAD - cur) < (SYSTICK_RELOAD/10)) + { + return NSEC_PER_TICK; + } + + nsec = ((uint64_t)(SYSTICK_RELOAD - cur) * NSEC_PER_TICK / SYSTICK_RELOAD); + return nsec; +#endif +} + + +/**************************************************************************** + * Name: up_hr_gettime + * + * Description: + * This function is used in clock_gettime() to obtain high resolution time. + ****************************************************************************/ + +int up_hr_gettime(FAR struct timespec *tp) +{ + uint64_t secs; + uint64_t nsecs; + uint64_t elapsed; /* in nsec */ + irqstate_t flags; + uint64_t f; + + flags = enter_critical_section(); + + /* Get the elapsed time */ + + elapsed = NSEC_PER_TICK * (uint64_t)g_system_timer; + + /* Add the tiemr fraction in nanoseconds */ + + f = up_get_timer_fraction(); + elapsed += f; + + leave_critical_section(flags); + + _info("elapsed = %lld \n", elapsed); + + /* Convert the elapsed time in seconds and nanoseconds. */ + + secs = elapsed / NSEC_PER_SEC; + nsecs = (elapsed - secs * NSEC_PER_SEC); + + /* And return the result to the caller. */ + + tp->tv_sec = (time_t)secs; + tp->tv_nsec = (long)nsecs; + + _info("Returning tp=(%d,%d)\n", (int)tp->tv_sec, (int)tp->tv_nsec); + return OK; +} diff --git a/arch/arm/src/lc823450/lc823450_vectors.S b/arch/arm/src/lc823450/lc823450_vectors.S new file mode 100644 index 00000000000..9f572b5741c --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_vectors.S @@ -0,0 +1,486 @@ +/**************************************************************************** + * arch/arm/src/lc823450/lc823450_vectors.S + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * + * 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 "chip.h" +#include "exc_return.h" + +/***************************************************************************** + * Configuration + ****************************************************************************/ + +/***************************************************************************** + * Preprocessor Definitions + ****************************************************************************/ +/* Configuration ********************************************************************/ + +#ifdef CONFIG_ARCH_HIPRI_INTERRUPT + /* In kernel mode without an interrupt stack, this interrupt handler will set the + * MSP to the stack pointer of the interrupted thread. If the interrupted thread + * was a privileged thread, that will be the MSP otherwise it will be the PSP. If + * the PSP is used, then the value of the MSP will be invalid when the interrupt + * handler returns because it will be a pointer to an old position in the + * unprivileged stack. Then when the high priority interrupt occurs and uses this + * stale MSP, there will most likely be a system failure. + * + * If the interrupt stack is selected, on the other hand, then the interrupt + * handler will always set the the MSP to the interrupt stack. So when the high + * priority interrupt occurs, it will either use the MSP of the last privileged + * thread to run or, in the case of the nested interrupt, the interrupt stack if + * no privileged task has run. + */ + +# if defined(CONFIG_BUILD_PROTECTED) && CONFIG_ARCH_INTERRUPTSTACK < 4 +# error Interrupt stack must be used with high priority interrupts in kernel mode +# endif + + /* Use the the BASEPRI to control interrupts is required if nested, high + * priority interrupts are supported. + */ + +# ifndef CONFIG_ARMV7M_USEBASEPRI +# error CONFIG_ARMV7M_USEBASEPRI must be used with CONFIG_ARCH_HIPRI_INTERRUPT +# endif +#endif + +/* Memory Map ***********************************************************************/ +/* + * 0x0800:0000 - Beginning of FLASH. Address of vectors (if not using bootloader) + * Mapped to address 0x0000:0000 at boot time. + * 0x0800:3000 - Address of vectors if using bootloader + * 0x0803:ffff - End of flash + * 0x2000:0000 - Start of SRAM and start of .data (_sdata) + * - End of .data (_edata) abd start of .bss (_sbss) + * - End of .bss (_ebss) and bottom of idle stack + * - _ebss + CONFIG_IDLETHREAD_STACKSIZE = end of idle stack, start of heap + * 0x2000:ffff - End of SRAM and end of heap + */ + +#define IDLE_STACK (_ebss+CONFIG_IDLETHREAD_STACKSIZE-4) +#define HEAP_BASE (_ebss+CONFIG_IDLETHREAD_STACKSIZE) + +/***************************************************************************** + * Global Symbols + ****************************************************************************/ + + .syntax unified + .thumb + .file "lc823450_vectors.S" + +/* Check if common ARMv7 interrupt vectoring is used (see arch/arm/src/armv7-m/up_vectors.S) */ + +#ifndef CONFIG_ARMV7M_CMNVECTOR + + .globl __start + +/***************************************************************************** + * Macros + ****************************************************************************/ + +/* On entry into an IRQ, the hardware automatically saves the xPSR, PC, LR, R12, R0-R3 + * registers on the stack, then branches to an instantantiation of the following + * macro. This macro simply loads the IRQ number into R0, then jumps to the common + * IRQ handling logic. + */ + + .macro HANDLER, label, irqno + .thumb_func +\label: + mov r0, #\irqno + b exception_common + .endm + +/***************************************************************************** + * Vectors + ****************************************************************************/ + + .section .vectors, "ax" + .code 16 + .align 2 + .globl _vectors + .type _vectors, function + +_vectors: + +/* Processor Exceptions */ + + .word IDLE_STACK /* Vector 0: Reset stack pointer */ +#ifdef CONFIG_SPIFLASH_BOOT + .word __start_main /* Vector 1: Reset vector */ +#else /* CONFIG_SPIFLASH_BOOT */ + .word __start /* Vector 1: Reset vector */ +#endif /* CONFIG_SPIFLASH_BOOT */ + .word lc823450_nmi /* Vector 2: Non-Maskable Interrupt (NMI) */ + .word lc823450_hardfault /* Vector 3: Hard fault */ + .word lc823450_mpu /* Vector 4: Memory management (MPU) */ + .word lc823450_busfault /* Vector 5: Bus fault */ + .word lc823450_usagefault /* Vector 6: Usage fault */ + .word lc823450_reserved /* Vector 7: Reserved */ + .word lc823450_reserved /* Vector 8: Reserved */ + .word lc823450_reserved /* Vector 9: Reserved */ + .word lc823450_reserved /* Vector 10: Reserved */ + .word lc823450_svcall /* Vector 11: SVC call */ + .word lc823450_dbgmonitor /* Vector 12: Debug monitor */ + .word lc823450_reserved /* Vector 13: Reserved */ + .word lc823450_pendsv /* Vector 14: Pendable system service request */ + .word lc823450_systick /* Vector 15: System tick */ + +/* External Interrupts */ + +#undef VECTOR +#define VECTOR(l,i) .word l + +#undef UNUSED +#define UNUSED(i) .word lc823450_reserved + +#include "lc823450_vectors.h" + + .size _vectors, .-_vectors + +/***************************************************************************** + * .text + ****************************************************************************/ + + .text + .type handlers, function + .thumb_func +handlers: + HANDLER lc823450_reserved, LC823450_IRQ_RESERVED /* Unexpected/reserved vector */ + HANDLER lc823450_nmi, LC823450_IRQ_NMI /* Vector 2: Non-Maskable Interrupt (NMI) */ + HANDLER lc823450_hardfault, LC823450_IRQ_HARDFAULT /* Vector 3: Hard fault */ + HANDLER lc823450_mpu, LC823450_IRQ_MEMFAULT /* Vector 4: Memory management (MPU) */ + HANDLER lc823450_busfault, LC823450_IRQ_BUSFAULT /* Vector 5: Bus fault */ + HANDLER lc823450_usagefault, LC823450_IRQ_USAGEFAULT /* Vector 6: Usage fault */ + HANDLER lc823450_svcall, LC823450_IRQ_SVCALL /* Vector 11: SVC call */ + HANDLER lc823450_dbgmonitor, LC823450_IRQ_DBGMONITOR /* Vector 12: Debug Monitor */ + HANDLER lc823450_pendsv, LC823450_IRQ_PENDSV /* Vector 14: Penable system service request */ + HANDLER lc823450_systick, LC823450_IRQ_SYSTICK /* Vector 15: System tick */ + +#undef VECTOR +#define VECTOR(l,i) HANDLER l, i + +#undef UNUSED +#define UNUSED(i) + +#include "lc823450_vectors.h" + +/* Common IRQ handling logic. On entry here, the return stack is on either + * the PSP or the MSP and looks like the following: + * + * REG_XPSR + * REG_R15 + * REG_R14 + * REG_R12 + * REG_R3 + * REG_R2 + * REG_R1 + * MSP->REG_R0 + * + * And + * R0 contains the IRQ number + * R14 Contains the EXC_RETURN value + * We are in handler mode and the current SP is the MSP + */ + + .globl exception_common + .type exception_common, function + +exception_common: + + /* Complete the context save */ + +#ifdef CONFIG_BUILD_PROTECTED + /* The EXC_RETURN value will be 0xfffffff9 (privileged thread) or 0xfffffff1 + * (handler mode) if the stack is on the MSP. It can only be on the PSP if + * EXC_RETURN is 0xfffffffd (unprivileged thread) + */ + + tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */ + beq 1f /* Branch if context already on the MSP */ + mrs r1, psp /* R1=The process stack pointer (PSP) */ + mov sp, r1 /* Set the MSP to the PSP */ + +1: +#endif + + /* r1 holds the value of the stack pointer AFTER the exception handling logic + * pushed the various registers onto the stack. Get r2 = the value of the + * stack pointer BEFORE the interrupt modified it. + */ + + mov r2, sp /* R2=Copy of the main/process stack pointer */ + add r2, #HW_XCPT_SIZE /* R2=MSP/PSP before the interrupt was taken */ +#ifdef CONFIG_ARMV7M_USEBASEPRI + mrs r3, basepri /* R3=Current BASEPRI setting */ +#else + mrs r3, primask /* R3=Current PRIMASK setting */ +#endif + + /* Save the remaining registers on the stack after the registers pushed + * by the exception handling logic. r2=SP and r3=primask or basepri, r4-r11, + * r14=register values. + */ + +#ifdef CONFIG_BUILD_PROTECTED + stmdb sp!, {r2-r11,r14} /* Save the remaining registers plus the SP value */ +#else + stmdb sp!, {r2-r11} /* Save the remaining registers plus the SP value */ +#endif + +#ifndef CONFIG_ARCH_HIPRI_INTERRUPT + /* Disable interrupts, select the stack to use for interrupt handling + * and call up_doirq to handle the interrupt + */ + + cpsid i /* Disable further interrupts */ + +#else + /* Set the BASEPRI register so that further normal interrupts will be + * masked. Nested, high priority may still occur, however. + */ + + mov r2, #NVIC_SYSH_DISABLE_PRIORITY + msr basepri, r2 /* Set the BASEPRI */ +#endif + + /* There are two arguments to up_doirq: + * + * R0 = The IRQ number + * R1 = The top of the stack points to the saved state + */ + + mov r1, sp + + /* Also save the top of the stack in a preserved register */ + + mov r4, sp + + +#if CONFIG_ARCH_INTERRUPTSTACK > 7 + /* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will set the MSP to use + * a special special interrupt stack pointer. The way that this is done + * here prohibits nested interrupts without some additional logic! + */ + + ldr sp, =g_intstackbase +#ifdef CONFIG_SMP + ldr r2, coreid_reg + ldr r2, [r2, 0] /* r2 = getreg32(coreid_reg) */ + and r2, r2, 1 /* r2 = COREID */ + cmp r2, #0 + beq after_setstack + ldr sp, =g_intstackbase2 +after_setstack: +#endif /* CONFIG_SMP */ + +#else + /* Otherwise, we will re-use the interrupted thread's stack. That may + * mean using either MSP or PSP stack for interrupt level processing (in + * kernel mode). + */ + + bic r2, r4, #7 /* Get the stack pointer with 8-byte alignment */ + mov sp, r2 /* Instantiate the aligned stack */ + +#endif + + bl up_doirq /* R0=IRQ, R1=register save (msp) */ + mov r1, r4 /* Recover R1=main stack pointer */ + + /* On return from up_doirq, R0 will hold a pointer to register context + * array to use for the interrupt return. If that return value is the same + * as current stack pointer, then things are relatively easy. + */ + + cmp r0, r1 /* Context switch? */ + beq 2f /* Branch if no context switch */ + + /* We are returning with a pending context switch. This case is different + * because in this case, the register save structure does not lie in the + * stack but, rather, within a TCB structure. We'll have to copy some + * values to the stack. + */ + + add r1, r0, #SW_XCPT_SIZE /* R1=Address of HW save area in reg array */ + ldmia r1, {r4-r11} /* Fetch eight registers in HW save area */ + ldr r1, [r0, #(4*REG_SP)] /* R1=Value of SP before interrupt */ + stmdb r1!, {r4-r11} /* Store eight registers in HW save area */ +#ifdef CONFIG_BUILD_PROTECTED + ldmia r0, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */ +#else + ldmia r0, {r2-r11} /* Recover R4-R11 + 2 temp values */ +#endif + b 3f /* Re-join common logic */ + + /* We are returning with no context switch. We simply need to "unwind" + * the same stack frame that we created + * + * Here: + * r1 = Address of the return stack (same as r0) + */ + +2: +#ifdef CONFIG_BUILD_PROTECTED + ldmia r1!, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */ +#else + ldmia r1!, {r2-r11} /* Recover R4-R11 + 2 temp values */ +#endif + + /* Set up to return from the exception + * + * Here: + * r1 = Address on the target thread's stack position at the start of + * the registers saved by hardware + * r3 = primask or basepri + * r4-r11 = restored register values + */ + +3: + +#ifdef CONFIG_BUILD_PROTECTED + /* The EXC_RETURN value will be 0xfffffff9 (privileged thread) or 0xfffffff1 + * (handler mode) if the stack is on the MSP. It can only be on the PSP if + * EXC_RETURN is 0xfffffffd (unprivileged thread) + */ + + mrs r2, control /* R2=Contents of the control register */ + tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */ + beq 4f /* Branch if privileged */ + + orr r2, r2, #1 /* Unprivileged mode */ + msr psp, r1 /* R1=The process stack pointer */ + b 5f +4: + bic r2, r2, #1 /* Privileged mode */ + msr msp, r1 /* R1=The main stack pointer */ +5: + msr control, r2 /* Save the updated control register */ +#else + msr msp, r1 /* Recover the return MSP value */ + + /* Preload r14 with the special return value first (so that the return + * actually occurs with interrupts still disabled). + */ + + ldr r14, =EXC_RETURN_PRIVTHR /* Load the special value */ +#endif + + /* Restore the interrupt state */ + +#ifdef CONFIG_ARMV7M_USEBASEPRI + msr basepri, r3 /* Restore interrupts priority masking */ +#ifndef CONFIG_ARCH_HIPRI_INTERRUPT + cpsie i /* Re-enable interrupts */ +#endif + +#else + msr primask, r3 /* Restore interrupts */ +#endif + + /* Always return with R14 containing the special value that will: (1) + * return to thread mode, and (2) continue to use the MSP + */ + + bx r14 /* And return */ + +#ifdef CONFIG_SMP +coreid_reg: + .word 0xe00fe000 +#endif /* CONFIG_SMP */ + + .size handlers, .-handlers +/***************************************************************************** + * Name: g_intstackalloc/g_intstackbase + * + * Description: + * Shouldn't happen + * + ****************************************************************************/ + +#if CONFIG_ARCH_INTERRUPTSTACK > 7 + .bss + .global g_intstackalloc + .global g_intstackbase + .align 8 +g_intstackalloc: + .skip (CONFIG_ARCH_INTERRUPTSTACK & ~7) +g_intstackbase: + .size g_intstackalloc, .-g_intstackalloc + +#ifdef CONFIG_SMP + .bss + .global g_intstackalloc2 + .global g_intstackbase2 + .align 8 +g_intstackalloc2: + .skip (CONFIG_ARCH_INTERRUPTSTACK & ~7) +g_intstackbase2: + .size g_intstackalloc2, .-g_intstackalloc2 +#endif /* CONFIG_SMP */ + +#endif /* CONFIG_ARCH_INTERRUPTSTACK */ + +#endif /* CONFIG_ARMV7M_CMNVECTOR */ + +/***************************************************************************** + * .rodata + ****************************************************************************/ + + .section .rodata, "a" + +/* Variables: _sbss is the start of the BSS region (see ld.script) _ebss is the end + * of the BSS regsion (see ld.script). The idle task stack starts at the end of BSS + * and is of size CONFIG_IDLETHREAD_STACKSIZE. The IDLE thread is the thread that + * the system boots on and, eventually, becomes the idle, do nothing task that runs + * only when there is nothing else to run. The heap continues from there until the + * end of memory. See g_idle_topstack below. + */ + + .globl g_idle_topstack + .type g_idle_topstack, object +g_idle_topstack: + .word HEAP_BASE + .size g_idle_topstack, .-g_idle_topstack + + .end diff --git a/arch/arm/src/lc823450/lc823450_vectors.h b/arch/arm/src/lc823450/lc823450_vectors.h new file mode 100644 index 00000000000..b13c1b275ad --- /dev/null +++ b/arch/arm/src/lc823450/lc823450_vectors.h @@ -0,0 +1,129 @@ +/**************************************************************************** + * arch/arm/src/lc823450/chip/lc823450_vectors.h + * + * Copyright (C) 2014-2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * + * 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. + * + ****************************************************************************/ + + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + + +/* This file is included by lc823450_vectors.S. It provides the macro VECTOR that + * supplies a LC823450 vector in terms of a (lower-case) ISR label and an + * (upper-case) IRQ number as defined in arch/arm/include/lc823450/irq.h. + * lc823450_vectors.S will defined the VECTOR in different ways in order to generate + * the interrupt vectors and handlers in their final form. + */ + + +/* If the common ARMv7-M vector handling is used, then all it needs is the following + * definition that provides the number of supported vectors. + */ + +#ifdef CONFIG_ARMV7M_CMNVECTOR + +/* Reserve interrupt table entries for I/O interrupts. */ + +# define ARMV7M_PERIPHERAL_INTERRUPTS 82 + + +#else +VECTOR(lc823450_ctxm3_00, LC823450_IRQ_CTXM3_00) /* Vector 16+0: CortexM3_00 interrupt */ +VECTOR(lc823450_ctxm3_01, LC823450_IRQ_CTXM3_01) /* Vector 16+1: CortexM3_01 interrupt */ +VECTOR(lc823450_ctxm3_02, LC823450_IRQ_CTXM3_02) /* Vector 16+2: CortexM3_02 interrupt */ +VECTOR(lc823450_ctxm3_03, LC823450_IRQ_CTXM3_03) /* Vector 16+3: CortexM3_03 interrupt */ +VECTOR(lc823450_ctxm3_10, LC823450_IRQ_CTXM3_10) /* Vector 16+4: CortexM3_00 interrupt */ +VECTOR(lc823450_ctxm3_11, LC823450_IRQ_CTXM3_11) /* Vector 16+5: CortexM3_01 interrupt */ +VECTOR(lc823450_ctxm3_12, LC823450_IRQ_CTXM3_12) /* Vector 16+6: CortexM3_02 interrupt */ +VECTOR(lc823450_ctxm3_13, LC823450_IRQ_CTXM3_13) /* Vector 16+7: CortexM3_03 interrupt */ +VECTOR(lc823450_lpdsp0, LC823450_IRQ_LPDSP0) /* Vector 16+8: LPDSP0 interrupt */ +VECTOR(lc823450_lpdsp1, LC823450_IRQ_LPDSP1) /* Vector 16+9: LPDSP1 interrupt */ +VECTOR(lc823450_lpdsp2, LC823450_IRQ_LPDSP2) /* Vector 16+10: LPDSP2 interrupt */ +VECTOR(lc823450_lpdsp3, LC823450_IRQ_LPDSP3) /* Vector 16+11: LPDSP3 interrupt */ +VECTOR(lc823450_wdt0, LC823450_IRQ_WDT0) /* Vector 16+12: WatchDogTimer0 interrupt */ +VECTOR(lc823450_wdt1, LC823450_IRQ_WDT1) /* Vector 16+13: WatchDogTimer1 interrupt */ +VECTOR(lc823450_wdt2, LC823450_IRQ_WDT2) /* Vector 16+14: WatchDogTimer2 interrupt */ +VECTOR(lc823450_btimer0, LC823450_IRQ_BTIMER0) /* Vector 16+15: BasicTimer0 interrupt */ +VECTOR(lc823450_btimer1, LC823450_IRQ_BTIMER1) /* Vector 16+16: BasicTimer0 interrupt */ +VECTOR(lc823450_btimer2, LC823450_IRQ_BTIMER2) /* Vector 16+17: BasicTimer0 interrupt */ +VECTOR(lc823450_mtimer00, LC823450_IRQ_MTIMER00) /* Vector 16+18: MultipleTimer00 interrupt */ +VECTOR(lc823450_mtimer01, LC823450_IRQ_MTIMER01) /* Vector 16+19: MultipleTimer01 interrupt */ +VECTOR(lc823450_mtimer10, LC823450_IRQ_MTIMER10) /* Vector 16+20: MultipleTimer10 interrupt */ +VECTOR(lc823450_mtimer11, LC823450_IRQ_MTIMER11) /* Vector 16+21: MultipleTimer11 interrupt */ +VECTOR(lc823450_mtimer20, LC823450_IRQ_MTIMER20) /* Vector 16+22: MultipleTimer20 interrupt */ +VECTOR(lc823450_mtimer21, LC823450_IRQ_MTIMER21) /* Vector 16+23: MultipleTimer21 interrupt */ +VECTOR(lc823450_mtimer30, LC823450_IRQ_MTIMER30) /* Vector 16+24: MultipleTimer30 interrupt */ +VECTOR(lc823450_mtimer31, LC823450_IRQ_MTIMER31) /* Vector 16+25: MultipleTimer31 interrupt */ +VECTOR(lc823450_ehci, LC823450_IRQ_EHCI) /* Vector 16+26: USB HOST EHCI interrupt */ +VECTOR(lc823450_ohci, LC823450_IRQ_OHCI) /* Vector 16+27: USB HOST OHCI interrupt */ +VECTOR(lc823450_serflash, LC823450_IRQ_SERFLASH) /* Vector 16+28: USB HOST OHCI interrupt */ +VECTOR(lc823450_dmac, LC823450_IRQ_DMAC) /* Vector 16+29: DMA Controller interrupt */ +VECTOR(lc823450_sdcsync0, LC823450_IRQ_SDCSYNC0) /* Vector 16+30: SDCardSync0 interrupt */ +VECTOR(lc823450_sdcsync1, LC823450_IRQ_SDCSYNC1) /* Vector 16+31: SDCardSync1 interrupt */ +VECTOR(lc823450_sdcsync2, LC823450_IRQ_SDCSYNC2) /* Vector 16+32: SDCardSync2 interrupt */ +VECTOR(lc823450_sdcasync0, LC823450_IRQ_SDCASYNC0) /* Vector 16+33: SDCardAsync0 interrupt */ +VECTOR(lc823450_sdcasync1, LC823450_IRQ_SDCASYNC1) /* Vector 16+34: SDCardAsync1 interrupt */ +VECTOR(lc823450_sdcasync2, LC823450_IRQ_SDCASYNC2) /* Vector 16+35: SDCardAsync2 interrupt */ +VECTOR(lc823450_memstick, LC823450_IRQ_MEMSTICK) /* Vector 16+36: MemoryStick interrupt */ +VECTOR(lc823450_memstickins, LC823450_IRQ_MEMSTICKINS) /* Vector 16+37: MemoryStick ins interrupt */ +VECTOR(lc823450_dspcmd, LC823450_IRQ_DSPCMD) /* Vector 16+38: DSP cmd interface interrupt */ +VECTOR(lc823450_adc, LC823450_IRQ_ADC) /* Vector 16+39: AD Converter interrupt */ +VECTOR(lc823450_sio, LC823450_IRQ_SIO) /* Vector 16+40: SIO interrupt */ +VECTOR(lc823450_i2c0, LC823450_IRQ_I2C0) /* Vector 16+41: I2C0 interrupt */ +VECTOR(lc823450_i2c1, LC823450_IRQ_I2C1) /* Vector 16+42: I2C1 interrupt */ +VECTOR(lc823450_uart0, LC823450_IRQ_UART0) /* Vector 16+43: UART0 interrupt */ +VECTOR(lc823450_uart1, LC823450_IRQ_UART1) /* Vector 16+44: UART1 interrupt */ +VECTOR(lc823450_uart2, LC823450_IRQ_UART2) /* Vector 16+45: UART2 interrupt */ +VECTOR(lc823450_rtc, LC823450_IRQ_RTC) /* Vector 16+46: RTC interrupt */ +VECTOR(lc823450_rtckey, LC823450_IRQ_RTCKEY) /* Vector 16+47: RTCKEY interrupt */ +VECTOR(lc823450_audiobuf0, LC823450_IRQ_AUDIOBUF0) /* Vector 16+48: AudioBuffer0 interrupt */ +VECTOR(lc823450_audiobuf1, LC823450_IRQ_AUDIOBUF1) /* Vector 16+49: AudioBuffer1 interrupt */ +VECTOR(lc823450_audiobuf2, LC823450_IRQ_AUDIOBUF2) /* Vector 16+50: AudioBuffer2 interrupt */ +VECTOR(lc823450_audiobuf3, LC823450_IRQ_AUDIOBUF3) /* Vector 16+51: AudioBuffer3 interrupt */ +VECTOR(lc823450_audiostat0, LC823450_IRQ_AUDIOSTAT0) /* Vector 16+52: AudioStatus0 interrupt */ +VECTOR(lc823450_audiostat1, LC823450_IRQ_AUDIOSTAT1) /* Vector 16+53: AudioStatus1 interrupt */ +VECTOR(lc823450_audiostat2, LC823450_IRQ_AUDIOSTAT2) /* Vector 16+54: AudioStatus2 interrupt */ +VECTOR(lc823450_audiostat3, LC823450_IRQ_AUDIOSTAT3) /* Vector 16+55: AudioStatus3 interrupt */ +VECTOR(lc823450_audiotm0, LC823450_IRQ_AUDIOTM0) /* Vector 16+56: AudioTimer0 interrupt */ +VECTOR(lc823450_audiotm1, LC823450_IRQ_AUDIOTM1) /* Vector 16+57: AudioTimer1 interrupt */ +VECTOR(lc823450_usbdev, LC823450_IRQ_USBDEV) /* Vector 16+58: USB Device interrupt */ +VECTOR(lc823450_extint0, LC823450_IRQ_EXTINT0) /* Vector 16+59: ExternalINT0 interrupt */ +VECTOR(lc823450_extint1, LC823450_IRQ_EXTINT1) /* Vector 16+60: ExternalINT1 interrupt */ +VECTOR(lc823450_extint2, LC823450_IRQ_EXTINT2) /* Vector 16+61: ExternalINT2 interrupt */ +VECTOR(lc823450_extint3, LC823450_IRQ_EXTINT3) /* Vector 16+62: ExternalINT3 interrupt */ +VECTOR(lc823450_extint4, LC823450_IRQ_EXTINT4) /* Vector 16+63: ExternalINT4 interrupt */ +VECTOR(lc823450_extint5, LC823450_IRQ_EXTINT5) /* Vector 16+64: ExternalINT5 interrupt */ + +#endif /* CONFIG_ARMV7M_CMNVECTOR */ diff --git a/configs/Kconfig b/configs/Kconfig index 61ed3b936c7..16dbac6f911 100644 --- a/configs/Kconfig +++ b/configs/Kconfig @@ -244,6 +244,12 @@ config ARCH_BOARD_HYMINI_STM32V A configuration for the HY-Mini STM32v board. This board is based on the STM32F103VCT6 chip. +config ARCH_BOARD_LC823450_XGEVK + bool "ON Semiconductor LC823450-XGEVK development board" + depends on ARCH_CHIP_LC823450 + ---help--- + This port uses the ON Semiconductor LC823450-XGEVK development board. + config ARCH_BOARD_LINCOLN60 bool "Micromint Lincoln 60 board" depends on ARCH_CHIP_LPC1769 @@ -1557,6 +1563,7 @@ config ARCH_BOARD default "hymini-stm32v" if ARCH_BOARD_HYMINI_STM32V default "kwikstik-k40" if ARCH_BOARD_KWIKSTIK_K40 default "launchxl-tms57004" if ARCH_BOARD_LAUNCHXL_TMS57004 + default "lc823450-xgevk" if ARCH_BOARD_LC823450_XGEVK default "lincoln60" if ARCH_BOARD_LINCOLN60 default "lm3s6432-s2e" if ARCH_BOARD_LM3S6432S2E default "lm3s6965-ek" if ARCH_BOARD_LM3S6965EK @@ -1790,6 +1797,9 @@ endif if ARCH_BOARD_LAUNCHXL_TMS57004 source "configs/launchxl-tms57004/Kconfig" endif +if ARCH_BOARD_LC823450_XGEVK +source "configs/lc823450-xgevk/Kconfig" +endif if ARCH_BOARD_LINCOLN60 source "configs/lincoln60/Kconfig" endif diff --git a/configs/lc823450-xgevk/Kconfig b/configs/lc823450-xgevk/Kconfig new file mode 100644 index 00000000000..8e1d81013d2 --- /dev/null +++ b/configs/lc823450-xgevk/Kconfig @@ -0,0 +1,7 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_BOARD_LC823450_XGEVK +endif diff --git a/configs/lc823450-xgevk/README.txt b/configs/lc823450-xgevk/README.txt new file mode 100644 index 00000000000..8994500bf4e --- /dev/null +++ b/configs/lc823450-xgevk/README.txt @@ -0,0 +1,84 @@ +README +^^^^^^ + +README for NuttX port to the LC823450XGEVK board. + +The board information is available at + + http://www.onsemi.com/PowerSolutions/evalBoard.do?id=LC823450XGEVK + +LC823450 related documents are available at + + http://www.onsemi.com/PowerSolutions/supportDoc.do?type=AppNotes&rpn=LC823450 + +This port is intended to test LC823450 features including SMP. +Supported peripherals are UART, TIMER, RTC, GPIO, DMA, I2C, SPI, LCD. + + +Settings +^^^^^^^^ + +1. Currently only SRAM boot via ICE is supported. +2. If SWD connection is lost, please specify lower adaptor clock. +3. Both CPUs are running at 160MHz. +4. Internal SRAMs (seg0 to seg5) are used. +5. Serial console can be used via external USB-UART (115200/8/N/1). +6. Interrupt handlers except for inter-cpu are handled on CPU0. + + +SMP related Status +^^^^^^^^^^^^^^^^^^ + +Currently SMP feature works on the board but might not be stable. +In addition, console output might be corrupted if the both CPUs +output into the console because UART operates in FIFO mode. + +1. "nsh> smp" works but the result will be corrupted. +2. "nsh> ostest" works but might cause a deadlock or assertion. + + +Other Status +^^^^^^^^^^^^ + +1. nsh built-in commands such as ps, free are available. + +NuttShell (NSH) +nsh> ps + PID GROUP CPU PRI POLICY TYPE NPX STATE EVENT SIGMASK STACK COMMAND + 0 0 0 0 FIFO Kthread N-- Assigned 00000000 000000 CPU0 IDLE + 1 0 1 0 FIFO Kthread N-- Running 00000000 002044 CPU1 IDLE + 3 1 0 100 FIFO Task --- Running 00000000 003052 init +nsh> free + total used free largest +Mem: 1027024 13136 1013888 1013888 + +2. date command can be used to get/set RTC date and time. + +nsh> date +Oct 03 00:00:55 2013 +nsh> date -s "Mar 31 12:34:56 2017" +nsh> date +Mar 31 12:34:56 2017 + +3. i2c app can be used to test I2C buses. + +nsh> i2c get -b 1 -a 18 -r 0 +READ Bus: 1 Addr: 18 Subaddr: 00 Value: f9 + +4. nxhello app can be used to test LCD via SPI. + +nsh> nxhello +nxhello_initialize: Initializing LCD +nxhello_initialize: Open NX +nxhello_main: NX handle=20096f0 +nxhello_main: Set background color=0 +nxhello_main: Screen resolution (128,48) +nxhello_hello: Position (31,20) +nxhello_main: Close NX + + +TODO +^^^^ + +The following peripherals will be supported. +eMMC, uSD, USB, ADC, Audio, etc. diff --git a/configs/lc823450-xgevk/include/board.h b/configs/lc823450-xgevk/include/board.h new file mode 100644 index 00000000000..be0bd236c06 --- /dev/null +++ b/configs/lc823450-xgevk/include/board.h @@ -0,0 +1,69 @@ +/**************************************************************************** + * configs/lc823450-xgevk/include/board.h + * + * Copyright (C) 2017 Sony Corporation. All rights reserved. + * Author: Masayuki Ishikawa + * + * 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. + * + ****************************************************************************/ + + +#ifndef __CONFIGS_LC823450_XGEVK_INCLUDE_BOARD_H +#define __CONFIGS_LC823450_XGEVK_INCLUDE_BOARD_H + +#include + +/************************************************************************************ + * Public Data + ************************************************************************************/ +#ifndef __ASSEMBLY__ + +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +extern unsigned int XT1OSC_CLK; + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +void up_init_default_mux(void); + + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __CONFIGS_LC823450_XGEVK_INCLUDE_BOARD_H */ diff --git a/configs/lc823450-xgevk/nsh/defconfig b/configs/lc823450-xgevk/nsh/defconfig new file mode 100644 index 00000000000..a6588691c40 --- /dev/null +++ b/configs/lc823450-xgevk/nsh/defconfig @@ -0,0 +1,119 @@ +CONFIG_AQM_1248A=y +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="lc823450-xgevk" +CONFIG_ARCH_BOARD_LC823450_XGEVK=y +CONFIG_ARCH_CHIP_LC823450=y +CONFIG_ARCH_FLOAT_H=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_STDARG_H=y +CONFIG_BOARD_LOOPSPERMSEC=12061 +CONFIG_BUILTIN=y +CONFIG_C99_BOOL8=y +CONFIG_CODECS_HASH_MD5=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ERROR=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_WARN=y +CONFIG_DEV_ZERO=y +CONFIG_DISABLE_MQUEUE=y +CONFIG_DISABLE_POSIX_TIMERS=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_EXAMPLES_NSH=y +CONFIG_EXAMPLES_NXHELLO_BPP=1 +CONFIG_EXAMPLES_NXHELLO=y +CONFIG_EXAMPLES_OSTEST=y +CONFIG_EXAMPLES_PIPE=y +CONFIG_EXAMPLES_SMP=y +CONFIG_EXPERIMENTAL=y +CONFIG_FS_PROCFS=y +CONFIG_FS_WRITABLE=y +CONFIG_I2C_RESET=y +CONFIG_I2CTOOL_MAXBUS=1 +CONFIG_I2C=y +CONFIG_INTELHEX_BINARY=y +CONFIG_LC823450_I2C0=y +CONFIG_LC823450_I2C1=y +# CONFIG_LC823450_SDIF is not set +CONFIG_LC823450_SPI_DMA=y +CONFIG_LC823450_UART0=y +CONFIG_LCD_ST7565=y +CONFIG_LCD=y +CONFIG_LIB_KBDCODEC=y +CONFIG_LIBM=y +CONFIG_MAX_TASKS=64 +CONFIG_MAX_WDOGPARMS=2 +CONFIG_MEMSET_OPTSPEED=y +CONFIG_NAME_MAX=765 +CONFIG_NETUTILS_CODECS=y +CONFIG_NFILE_DESCRIPTORS=45 +CONFIG_NFILE_STREAMS=8 +CONFIG_NSH_ARCHINIT=y +# CONFIG_NSH_ARGCAT is not set +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_BASENAME=y +CONFIG_NSH_DISABLE_CP=y +CONFIG_NSH_DISABLE_DD=y +CONFIG_NSH_DISABLE_DELROUTE=y +CONFIG_NSH_DISABLE_DIRNAME=y +CONFIG_NSH_DISABLE_EXEC=y +CONFIG_NSH_DISABLE_GET=y +CONFIG_NSH_DISABLE_HEXDUMP=y +CONFIG_NSH_DISABLE_IFCONFIG=y +CONFIG_NSH_DISABLE_LOSETUP=y +CONFIG_NSH_DISABLE_MB=y +CONFIG_NSH_DISABLE_MD5=y +CONFIG_NSH_DISABLE_MH=y +CONFIG_NSH_DISABLE_MKDIR=y +CONFIG_NSH_DISABLE_MKFIFO=y +CONFIG_NSH_DISABLE_MKRD=y +CONFIG_NSH_DISABLE_MV=y +CONFIG_NSH_DISABLE_PUT=y +CONFIG_NSH_DISABLE_RMDIR=y +CONFIG_NSH_DISABLE_RM=y +CONFIG_NSH_DISABLE_SH=y +CONFIG_NSH_DISABLE_WGET=y +CONFIG_NSH_DISABLE_XD=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_MAXARGUMENTS=10 +CONFIG_NSH_READLINE=y +# CONFIG_NX_DISABLE_1BPP is not set +CONFIG_NXFONT_MONO5X8=y +CONFIG_NX=y +CONFIG_PIPES=y +CONFIG_POSIX_SPAWN_PROXY_STACKSIZE=2048 +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PREALLOC_WDOGS=16 +CONFIG_PTHREAD_MUTEX_TYPES=y +CONFIG_PTHREAD_STACK_DEFAULT=3072 +CONFIG_RAM_SIZE=1044480 +CONFIG_RAM_START=0x02001000 +CONFIG_RAW_BINARY=y +CONFIG_RTC_DATETIME=y +CONFIG_RTC=y +CONFIG_SCHED_ATEXIT=y +CONFIG_SCHED_CHILD_STATUS=y +CONFIG_SCHED_HAVE_PARENT=y +CONFIG_SCHED_INSTRUMENTATION_BUFFER=y +CONFIG_SCHED_INSTRUMENTATION=y +CONFIG_SCHED_ONEXIT_MAX=32 +CONFIG_SCHED_ONEXIT=y +CONFIG_SCHED_STARTHOOK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_SERIAL_TERMIOS=y +CONFIG_SMP_NCPUS=2 +CONFIG_SMP=y +# CONFIG_SPI_EXCHANGE is not set +CONFIG_SPI=y +CONFIG_START_DAY=3 +CONFIG_START_MONTH=10 +CONFIG_START_YEAR=2013 +CONFIG_SYSTEM_I2CTOOL=y +CONFIG_TASK_NAME_SIZE=24 +CONFIG_UART0_RXBUFSIZE=512 +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_UART0_TXBUFSIZE=2048 +CONFIG_USER_ENTRYPOINT="nsh_main" +CONFIG_USERMAIN_STACKSIZE=3072 diff --git a/configs/lc823450-xgevk/scripts/Make.defs b/configs/lc823450-xgevk/scripts/Make.defs new file mode 100644 index 00000000000..cedcd64e369 --- /dev/null +++ b/configs/lc823450-xgevk/scripts/Make.defs @@ -0,0 +1,126 @@ +############################################################################ +# configs/lc823450-xgevk/scripts/Make.defs +# +# Copyright (C) 2017 Sony Corporation. All rights reserved. +# Author: Masayuki Ishikawa +# +# 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. +# +############################################################################ + +include ${TOPDIR}/.config +include ${TOPDIR}/tools/Config.mk +include ${TOPDIR}/arch/arm/src/armv7-m/Toolchain.defs + +ifeq ($(WINTOOL),y) + # Windows-native toolchains + DIRLINK = $(TOPDIR)/tools/copydir.sh + DIRUNLINK = $(TOPDIR)/tools/unlink.sh + MKDEP = $(TOPDIR)/tools/mkwindeps.sh + ARCHINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}" + ARCHXXINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}" -isystem "${shell cygpath -w $(TOPDIR)/include/cxx}" + ARCHSCRIPT = -T "${shell cygpath -w $(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/scripts/ld.script}" +else + # Linux/Cygwin-native toolchain + MKDEP = $(TOPDIR)/tools/mkdeps$(HOSTEXEEXT) + ARCHINCLUDES = -I. -isystem $(TOPDIR)/include + ARCHXXINCLUDES = -I. -isystem $(TOPDIR)/include -isystem $(TOPDIR)/include/cxx + ARCHSCRIPT = -T$(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/scripts/ld.script +endif + +CC = $(CROSSDEV)gcc +CXX = $(CROSSDEV)g++ +CPP = $(CROSSDEV)gcc -E +LD = $(CROSSDEV)ld +AR = $(CROSSDEV)ar rcs +NM = $(CROSSDEV)nm +OBJCOPY = $(CROSSDEV)objcopy +OBJDUMP = $(CROSSDEV)objdump + +ARCHCCVERSION = ${shell $(CC) -v 2>&1 | sed -n '/^gcc version/p' | sed -e 's/^gcc version \([0-9\.]\)/\1/g' -e 's/[-\ ].*//g' -e '1q'} +ARCHCCMAJOR = ${shell echo $(ARCHCCVERSION) | cut -d'.' -f1} + +ifeq ($(CONFIG_DEBUG_SYMBOLS),y) + ARCHOPTIMIZATION = -g +endif + +ifneq ($(CONFIG_DEBUG_NOOPT),y) + ARCHOPTIMIZATION += $(MAXOPTIMIZATION) -fno-strict-aliasing -fno-strength-reduce -fomit-frame-pointer +endif + +ARCHCFLAGS = -fno-builtin -ffunction-sections -fdata-sections -nostdinc +ARCHCXXFLAGS = -fno-builtin -fno-exceptions -fcheck-new -fno-rtti -nostdinc++ +ARCHWARNINGS = -Wall -Wstrict-prototypes -Wshadow -Wundef +ARCHWARNINGSXX = -Wall -Wshadow -Wundef +ARCHDEFINES = +ARCHPICFLAGS = -fpic -msingle-pic-base -mpic-register=r10 + +CFLAGS = $(ARCHCFLAGS) $(ARCHWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe +CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) +CXXFLAGS = $(ARCHCXXFLAGS) $(ARCHWARNINGSXX) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe +CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) +CPPFLAGS = $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) +AFLAGS = $(CFLAGS) -D__ASSEMBLY__ + +NXFLATLDFLAGS1 = -r -d -warn-common +NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat-pcrel.ld -no-check-sections +LDNXFLATFLAGS = -e main -s 2048 + +ASMEXT = .S +OBJEXT = .o +LIBEXT = .a +EXEEXT = + +ifneq ($(CROSSDEV),arm-nuttx-elf-) + LDFLAGS += -nostartfiles -nodefaultlibs +endif +ifeq ($(CONFIG_DEBUG_SYMBOLS),y) + LDFLAGS += -g +endif + +LDFLAGS += --gc-sections + +HOSTCC = gcc +HOSTINCLUDES = -I. +HOSTCFLAGS = -Wall -Wstrict-prototypes -Wshadow -Wundef -g -pipe +HOSTLDFLAGS = + +ifeq ($(CONFIG_MTD_LC823450),y) +ARCH_LIBS += -lSdDr_patch_es2 +ARCH_LIBPATHS += -L"$(TOPDIR)/arch/arm/src/lc823450" +ARCH_LIBS += $(ARCH_LIBS_OPT)--just-symbols=$(TOPDIR)/arch/arm/src/lc823450/rom_symbols.txt +LDFLAGS +=--no-wchar-size-warning +endif + + +# NEVER use 'override' variables +# NUTTX_EXTRA_LIBS and NUTTX_EXTRA_LIBPATHS are defined by out-of-repository + +EXTRA_LIBS := $(NUTTX_EXTRA_LIBS) $(ARCH_LIBS) +EXTRA_LIBPATHS := $(NUTTX_EXTRA_LIBPATHS) $(ARCH_LIBPATHS) + diff --git a/configs/lc823450-xgevk/scripts/gnu-elf.ld b/configs/lc823450-xgevk/scripts/gnu-elf.ld new file mode 100644 index 00000000000..04b1d2f9275 --- /dev/null +++ b/configs/lc823450-xgevk/scripts/gnu-elf.ld @@ -0,0 +1,139 @@ +/**************************************************************************** + * configs/lc823450-xgevk/scripts/gnu-elf.ld + * + * Copyright (C) 2017 Sony Corporation. All rights reserved. + * Author: Masayuki Ishikawa + * + * 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. + * + ****************************************************************************/ + +SECTIONS +{ + .text 0x00000000 : + { + _stext = . ; + *(.text) + *(.text.*) + *(.gnu.warning) + *(.stub) + *(.glue_7) + *(.glue_7t) + *(.jcr) + + /* C++ support: The .init and .fini sections contain specific logic + * to manage static constructors and destructors. + */ + + *(.gnu.linkonce.t.*) + *(.init) /* Old ABI */ + *(.fini) /* Old ABI */ + _etext = . ; + } + + .ARM.extab : + { + *(.ARM.extab*) + } + + .ARM.exidx : + { + *(.ARM.exidx*) + } + + .rodata : + { + _srodata = . ; + *(.rodata) + *(.rodata1) + *(.rodata.*) + *(.gnu.linkonce.r*) + _erodata = . ; + } + + .data : + { + _sdata = . ; + *(.data) + *(.data1) + *(.data.*) + *(.gnu.linkonce.d*) + _edata = . ; + } + + /* C++ support. For each global and static local C++ object, + * GCC creates a small subroutine to construct the object. Pointers + * to these routines (not the routines themselves) are stored as + * simple, linear arrays in the .ctors section of the object file. + * Similarly, pointers to global/static destructor routines are + * stored in .dtors. + */ + + .ctors : + { + _sctors = . ; + *(.ctors) /* Old ABI: Unallocated */ + *(.init_array) /* New ABI: Allocated */ + _edtors = . ; + } + + .dtors : + { + _sdtors = . ; + *(.dtors) /* Old ABI: Unallocated */ + *(.fini_array) /* New ABI: Allocated */ + _edtors = . ; + } + + .bss : + { + _sbss = . ; + *(.bss) + *(.bss.*) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.b*) + *(COMMON) + _ebss = . ; + } + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/configs/lc823450-xgevk/scripts/ld.script b/configs/lc823450-xgevk/scripts/ld.script new file mode 100644 index 00000000000..1b638ebb319 --- /dev/null +++ b/configs/lc823450-xgevk/scripts/ld.script @@ -0,0 +1,124 @@ +/**************************************************************************** + * configs/lc823450-xgevk/scripts/ld.script + * + * Copyright (C) 2017 Sony Corporation. All rights reserved. + * Author: Masayuki Ishikawa + * + * 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. + * + ****************************************************************************/ + + +MEMORY +{ + progmem (rx) : ORIGIN = 0x02040000, LENGTH = 480K + flash (rx) : ORIGIN = 0x05008000, LENGTH = 2016K + sram (rwx) : ORIGIN = 0x02001000, LENGTH = 124K +} + +OUTPUT_ARCH(arm) +ENTRY(_stext) +SECTIONS +{ + .text_spif : + { + _sspif = ABSOLUTE(.); + _espif = ABSOLUTE(.); + } > flash + + .text : + { + _stext = ABSOLUTE(.); + KEEP(*(.vectors)) + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > progmem + + .init_section : + { + _sinit = ABSOLUTE(.); + KEEP(*(.init_array .init_array.*)) + _einit = ABSOLUTE(.); + } > progmem + + .ARM.extab : + { + *(.ARM.extab*) + } > progmem + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : + { + *(.ARM.exidx*) + } > progmem + __exidx_end = ABSOLUTE(.); + + _eronly = ABSOLUTE(LOADADDR(.data)); + + .data : + { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + _edata = ABSOLUTE(.); + } > sram AT > progmem + + .bss : + { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + _ebss = ABSOLUTE(.); + } > sram + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/configs/lc823450-xgevk/src/Makefile b/configs/lc823450-xgevk/src/Makefile new file mode 100644 index 00000000000..8c6063ddb91 --- /dev/null +++ b/configs/lc823450-xgevk/src/Makefile @@ -0,0 +1,71 @@ +############################################################################ +# configs/lc823450-xgevk/src/Makefile +# +# Copyright (C) 2017 Sony Corporation. All rights reserved. +# Author: Masayuki Ishikawa +# +# 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. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +ASRCS = +CSRCS = lc823450_boot.c lc823450_mux.c + +ifeq ($(CONFIG_LIB_BOARDCTL),y) +CSRCS += lc823450_appinit.c lc823450_bringup.c +else ifeq ($(CONFIG_BOARD_INITIALIZE),y) +CSRCS += lc823450_bringup.c +endif + +ifeq ($(CONFIG_LC823450_SDIF),y) +CSRCS += lc823450_sdif.c +endif + +ifeq ($(CONFIG_USBMSC),y) +CSRCS += lc823450_usbmsc.c +endif + +ifeq ($(CONFIG_SPI),y) +CSRCS += lc823450_spi.c +endif + +ifeq ($(CONFIG_LCD_ST7565),y) +CSRCS += lc823450_st7565.c +endif + +ifeq ($(CONFIG_BMA250),y) +CSRCS += lc823450_bma250.c +endif + +ifeq ($(CONFIG_NETDEVICES),y) +CSRCS += lc823450_netinit.c +endif + +include $(TOPDIR)/configs/Board.mk diff --git a/configs/lc823450-xgevk/src/lc823450-xgevk.h b/configs/lc823450-xgevk/src/lc823450-xgevk.h new file mode 100644 index 00000000000..b3e6ef698a6 --- /dev/null +++ b/configs/lc823450-xgevk/src/lc823450-xgevk.h @@ -0,0 +1,96 @@ +/**************************************************************************** + * configs/lc823450-xgevk/src/lc823450-xgevk.h + * + * Copyright (C) 2017 Sony Corporation. All rights reserved. + * Author: Masayuki Ishikawa + * + * 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. + * + ****************************************************************************/ + + +#ifndef __CONFIGS_LC823450_XGEVK_SRC_LC823450_XGEVK_H +#define __CONFIGS_LC823450_XGEVK_SRC_LC823450_XGEVK_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Do we need to register I2C drivers on behalf of the I2C tool? */ + +#define HAVE_I2CTOOL 1 +#if !defined(CONFIG_SYSTEM_I2CTOOL) || !defined(CONFIG_I2C_DRIVER) +# undef HAVE_I2CTOOL +#endif + + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lc823450_bringup + * + * Description: + * Bring up board features + * + ****************************************************************************/ + +#if defined(CONFIG_LIB_BOARDCTL) || defined(CONFIG_BOARD_INITIALIZE) +int lc823450_bringup(void); +#endif + + +/************************************************************************************ + * Name: lc823450_bma250initialize + ************************************************************************************/ +#ifdef CONFIG_BMA250 +int lc823450_bma250initialize(FAR const char *devpath); +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __CONFIGS_LC823450_XGEVK_SRC_LC823450_XGEVK_H */ diff --git a/configs/lc823450-xgevk/src/lc823450-xgevk_mux.h b/configs/lc823450-xgevk/src/lc823450-xgevk_mux.h new file mode 100644 index 00000000000..bc64b00a4ce --- /dev/null +++ b/configs/lc823450-xgevk/src/lc823450-xgevk_mux.h @@ -0,0 +1,629 @@ +/**************************************************************************** + * configs/lc823450-xgevk/src/lc823450-xgevk_mux.h + * + * Copyright (C) 2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * + * 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. + * + ****************************************************************************/ + +#ifndef __CONFIGS_LC823450_XGEVK_SRC_LC823450_XGEVK_MUX_H +#define __CONFIGS_LC823450_XGEVK_SRC_LC823450_XGEVK_MUX_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * PORT0 + ****************************************************************************/ + +#define PORT0_MUX \ + 0 << 0 | /* 0: GPIO00, 1:TCLKA0, 2: 3:BCK1 */ \ + 0 << 2 | /* 0: GPIO01, 1:TCLKB0, 2: 3:LRCK1 */ \ + 3 << 4 | /* 0: GPIO02, 1:TIOCB00, 2:DMDIN0, 3:DIN1 */ \ + 3 << 6 | /* 0: GPIO03, 1:TIOCB01, 2:DMCKO0, 3:QSCS */ \ + 1 << 8 | /* 0: GPIO04, 1:TXD1, 2:SDAT20 */ \ + 1 << 10 | /* 0: GPIO05, 1:RXD1, 2:SDAT21 */ \ + 0 << 12 | /* 0: GPIO06, 1:NCS0 */ \ + 1 << 14 | /* 0: GPIO07, 1:SCL0 */ \ + 1 << 16 | /* 0: GPIO08, 1:SDA0 */ \ + 0 << 18 | /* 0: GPIO09, 1:TIOCA00, 2:SDCLK2, 3:PHI0 */ \ + 3 << 20 | /* 0: GPIO0A, 1:TIOCA00, 2:SDCMD2, 3:PHI1 */ \ + 0 << 22 | /* 0: GPIO0B, 1:TXD2, 2:TIOCA10 */ \ + 0 << 24 | /* 0: GPIO0C, 1:RXD2, 2:TIOCA11 */ \ + 1 << 26 | /* 0: GPIO0D, 1:SCK1 */ \ + 1 << 28 | /* 0: GPIO0E, 1:SDI1 */ \ + 1 << 30 /* 0: GPIO0F, 1:SDO1 */ + +#define PORT0_PUPD \ + 0 << 0 | /* GPIO00 0:non, 1:PU, 2:PD */ \ + 0 << 2 | /* GPIO01 0:non, 1:PU, 2:PD */ \ + 0 << 4 | /* GPIO02 0:non, 1:PU, 2:PD */ \ + 1 << 6 | /* GPIO03 0:non, 1:PU, 2:PD */ \ + 0 << 8 | /* GPIO04 0:non, 1:PU, 2:PD */ \ + 0 << 10 | /* GPIO05 0:non, 1:PU, 2:PD */ \ + 0 << 12 | /* GPIO06 0:non, 1:PU */ \ + 0 << 14 | /* GPIO07 0:non, 1:PU, 2:PD */ \ + 0 << 16 | /* GPIO08 0:non, 1:PU, 2:PD */ \ + 0 << 18 | /* GPIO09 0:non, 1:PU, 2:PD */ \ + 0 << 20 | /* GPIO0A 0:non, 1:PU, 2:PD */ \ + 0 << 22 | /* GPIO0B 0:non, 1:PU, 2:PD */ \ + 0 << 24 | /* GPIO0C 0:non, 1:PU, 2:PD */ \ + 0 << 26 | /* GPIO0D 0:non, 1:PU, 2:PD */ \ + 0 << 28 | /* GPIO0E 0:non, 1:PU, 2:PD */ \ + 0 << 30 /* GPIO0F 0:non, 1:PU, 2:PD */ + +#define PORT0_DRV \ + 0 << 0 | /* GPIO00 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 2 | /* GPIO01 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 4 | /* GPIO02 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 6 | /* GPIO03 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 8 | /* GPIO04 0:6mA, 1:---, 2:8mA, 3:10mA */ \ + 0 << 10 | /* GPIO05 0:6mA, 1:---, 2:8mA, 3:10mA */ \ + 0 << 12 | /* GPIO06 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 14 | /* GPIO07 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 16 | /* GPIO08 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 18 | /* GPIO09 0:6mA, 1:---, 2:8mA, 3:10mA */ \ + 0 << 20 | /* GPIO0A 0:6mA, 1:---, 2:8mA, 3:10mA */ \ + 0 << 22 | /* GPIO0B 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 24 | /* GPIO0C 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 26 | /* GPIO0D 0:6mA, 1:---, 2:8mA, 3:10mA */ \ + 0 << 28 | /* GPIO0E 0:6mA, 1:---, 2:8mA, 3:10mA */ \ + 0 << 30 /* GPIO0F 0:6mA, 1:---, 2:8mA, 3:10mA */ + +#define PORT0_DIR \ + 1 << 0 | /* GPIO00 0:in, 1:out */ \ + 1 << 1 | /* GPIO01 0:in, 1:out */ \ + 0 << 2 | /* GPIO02 0:in, 1:out */ \ + 0 << 3 | /* GPIO03 0:in, 1:out */ \ + 0 << 4 | /* GPIO04 0:in, 1:out */ \ + 0 << 5 | /* GPIO05 0:in, 1:out */ \ + 1 << 6 | /* GPIO06 0:in, 1:out */ \ + 0 << 7 | /* GPIO07 0:in, 1:out */ \ + 0 << 8 | /* GPIO08 0:in, 1:out */ \ + 1 << 9 | /* GPIO09 0:in, 1:out */ \ + 0 << 10 | /* GPIO0A 0:in, 1:out */ \ + 1 << 11 | /* GPIO0B 0:in, 1:out */ \ + 1 << 12 | /* GPIO0C 0:in, 1:out */ \ + 0 << 13 | /* GPIO0D 0:in, 1:out */ \ + 0 << 14 | /* GPIO0E 0:in, 1:out */ \ + 0 << 15 /* GPIO0F 0:in, 1:out */ + +#define PORT0_DAT \ + 0 << 0 | /* GPIO00 0:0, 1:1 */ \ + 1 << 1 | /* GPIO01 0:0, 1:1 */ \ + 0 << 2 | /* GPIO02 0:0, 1:1 */ \ + 0 << 3 | /* GPIO03 0:0, 1:1 */ \ + 0 << 4 | /* GPIO04 0:0, 1:1 */ \ + 0 << 5 | /* GPIO05 0:0, 1:1 */ \ + 0 << 6 | /* GPIO06 0:0, 1:1 */ \ + 0 << 7 | /* GPIO07 0:0, 1:1 */ \ + 0 << 8 | /* GPIO08 0:0, 1:1 */ \ + 0 << 9 | /* GPIO09 0:0, 1:1 */ \ + 0 << 10 | /* GPIO0A 0:0, 1:1 */ \ + 0 << 11 | /* GPIO0B 0:0, 1:1 */ \ + 0 << 12 | /* GPIO0C 0:0, 1:1 */ \ + 0 << 13 | /* GPIO0D 0:0, 1:1 */ \ + 0 << 14 | /* GPIO0E 0:0, 1:1 */ \ + 0 << 15 /* GPIO0F 0:0, 1:1 */ \ + + +/**************************************************************************** + * PORT1 + ****************************************************************************/ + +#define PORT1_MUX \ + 3 << 0 | /* 0: GPIO10, 1:NCS1 2: 3:RXD0 */ \ + 1 << 2 | /* 0: GPIO11, 1:SWP1 */ \ + 1 << 4 | /* 0: GPIO12, 1:SHOLD1 */ \ + 1 << 6 | /* 0: GPIO13, 1:BCK1 */ \ + 1 << 8 | /* 0: GPIO14, 1:LRCK1 */ \ + 1 << 10 | /* 0: GPIO15, 1:DOUT1 */ \ + 0 << 12 | /* 0: GPIO16, 1:NLBEXA0 */ \ + 0 << 14 | /* 0: GPIO17, 1:NRD */ \ + 0 << 16 | /* 0: GPIO18, 1:MCLK0, 2:MCLK1 */ \ + 0 << 18 | /* 0: GPIO19, 1:BCK0, 2:DMCKO1 */ \ + 0 << 20 | /* 0: GPIO1A, 1:LRCK0, 2:DMDIN1 */ \ + 2 << 22 | /* 0: GPIO1B, 1:DIN0, 2:DMDIN0 */ \ + 0 << 24 | /* 0: GPIO1C, 1:DOUT0, 2:DMCKO0 */ \ + 1 << 26 | /* 0: GPIO1D, 1:SCK0 */ \ + 0 << 28 | /* 0: GPIO1E, 1:SDI0 */ \ + 1 << 30 /* 0: GPIO1F, 1:SDO0 */ + +#define PORT1_PUPD \ + 0 << 0 | /* GPIO10 0:non, 1:PU */ \ + 0 << 2 | /* GPIO11 0:non, 1:PU, 2:PD */ \ + 0 << 4 | /* GPIO12 0:non, 1:PU, 2:PD */ \ + 0 << 6 | /* GPIO13 0:non, 1:PU, 2:PD */ \ + 0 << 8 | /* GPIO14 0:non, 1:PU, 2:PD */ \ + 0 << 10 | /* GPIO15 0:non, 1:PU, 2:PD */ \ + 0 << 12 | /* GPIO16 0:non, 1: 2:PD */ \ + 0 << 14 | /* GPIO17 0:non, 1: 2:PD */ \ + 0 << 16 | /* GPIO18 0:non, 1:PU, 2:PD */ \ + 0 << 18 | /* GPIO19 0:non, 1:PU, 2:PD */ \ + 0 << 20 | /* GPIO1A 0:non, 1:PU, 2:PD */ \ + 0 << 22 | /* GPIO1B 0:non, 1:PU, 2:PD */ \ + 0 << 24 | /* GPIO1C 0:non, 1:PU, 2:PD */ \ + 0 << 26 | /* GPIO1D 0:non, 1:PU, 2:PD */ \ + 0 << 28 | /* GPIO1E 0:non, 1:PU, 2:PD */ \ + 0 << 30 /* GPIO1F 0:non, 1:PU, 2:PD */ + +#define PORT1_DRV \ + 0 << 0 | /* GPIO10 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 2 | /* GPIO11 0:6mA, 1:---, 2:8mA, 3:10mA */ \ + 0 << 4 | /* GPIO12 0:6mA, 1:---, 2:8mA, 3:10mA */ \ + 0 << 6 | /* GPIO13 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 8 | /* GPIO14 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 10 | /* GPIO15 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 12 | /* GPIO16 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 14 | /* GPIO17 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 16 | /* GPIO18 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 18 | /* GPIO19 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 20 | /* GPIO1A 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 22 | /* GPIO1B 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 24 | /* GPIO1C 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 26 | /* GPIO1D 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 28 | /* GPIO1E 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 30 /* GPIO1F 0:1mA, 1:---, 2:2mA, 3:4mA */ + +#define PORT1_DIR \ + 0 << 0 | /* GPIO10 0:in, 1:out */ \ + 0 << 1 | /* GPIO11 0:in, 1:out */ \ + 0 << 2 | /* GPIO12 0:in, 1:out */ \ + 0 << 3 | /* GPIO13 0:in, 1:out */ \ + 0 << 4 | /* GPIO14 0:in, 1:out */ \ + 0 << 5 | /* GPIO15 0:in, 1:out */ \ + 1 << 6 | /* GPIO16 0:in, 1:out */ \ + 1 << 7 | /* GPIO17 0:in, 1:out */ \ + 0 << 8 | /* GPIO18 0:in, 1:out */ \ + 0 << 9 | /* GPIO19 0:in, 1:out */ \ + 0 << 10 | /* GPIO1A 0:in, 1:out */ \ + 0 << 11 | /* GPIO1B 0:in, 1:out */ \ + 0 << 12 | /* GPIO1C 0:in, 1:out */ \ + 0 << 13 | /* GPIO1D 0:in, 1:out */ \ + 1 << 14 | /* GPIO1E 0:in, 1:out */ \ + 0 << 15 /* GPIO1F 0:in, 1:out */ + +#define PORT1_DAT \ + 0 << 0 | /* GPIO10 0:0, 1:1 */ \ + 0 << 1 | /* GPIO11 0:0, 1:1 */ \ + 0 << 2 | /* GPIO12 0:0, 1:1 */ \ + 0 << 3 | /* GPIO13 0:0, 1:1 */ \ + 0 << 4 | /* GPIO14 0:0, 1:1 */ \ + 0 << 5 | /* GPIO15 0:0, 1:1 */ \ + 0 << 6 | /* GPIO16 0:0, 1:1 */ \ + 0 << 7 | /* GPIO17 0:0, 1:1 */ \ + 0 << 8 | /* GPIO18 0:0, 1:1 */ \ + 0 << 9 | /* GPIO19 0:0, 1:1 */ \ + 0 << 10 | /* GPIO1A 0:0, 1:1 */ \ + 0 << 11 | /* GPIO1B 0:0, 1:1 */ \ + 0 << 12 | /* GPIO1C 0:0, 1:1 */ \ + 0 << 13 | /* GPIO1D 0:0, 1:1 */ \ + 0 << 14 | /* GPIO1E 0:0, 1:1 */ \ + 0 << 15 /* GPIO1F 0:0, 1:1 */ \ + + +/**************************************************************************** + * PORT2 + ****************************************************************************/ + +#define PORT2_MUX \ + 0 << 0 | /* 0: GPIO20, 1:SDCD1, 2:SWO, 3:TDI */ \ + 0 << 2 | /* 0: GPIO21, 1:SDWP1, 2:INS, 3:TDO */ \ + 1 << 4 | /* 0: GPIO22, 1:SDCLK1, 2:SCLK */ \ + 1 << 6 | /* 0: GPIO23, 1:SDCMD1, 2:BS */ \ + 1 << 8 | /* 0: GPIO24, 1:SDAT10, 2:DATA0 */ \ + 1 << 10 | /* 0: GPIO25, 1:SDAT11, 2:DATA1 */ \ + 1 << 12 | /* 0: GPIO26, 1:SDAT12, 2:DATA2 */ \ + 1 << 14 | /* 0: GPIO27, 1:SDAT13, 2:DATA3 */ \ + 0 << 16 | /* 0: GPIO28, 1: 2:SDWP2, 3:TMS */ \ + 0 << 18 | /* 0: GPIO29, 1: 2:SDCD2, 3:TCK */ \ + 0 << 20 | /* 0: GPIO2A, 1: 2:SDRADDR12 */ \ + 1 << 22 | /* 0: GPIO2B, 1:SCL1 */ \ + 1 << 24 | /* 0: GPIO2C, 1:SDA1 */ \ + 1 << 26 | /* 0: GPIO2D, 1:DMCK0, 2:SDRADDR11 */ \ + 0 << 28 | /* 0: GPIO2E */ \ + 0 << 30 /* 0: GPIO2F */ + +#define PORT2_PUPD \ + 0 << 0 | /* GPIO20 0:non, 1:PU, 2:PD */ \ + 0 << 2 | /* GPIO21 0:non, 1:PU, 2:PD */ \ + 0 << 4 | /* GPIO22 0:non, 1:PU, 2:PD */ \ + 1 << 6 | /* GPIO23 0:non, 1:PU, 2:PD */ \ + 1 << 8 | /* GPIO24 0:non, 1:PU, 2:PD */ \ + 1 << 10 | /* GPIO25 0:non, 1:PU, 2:PD */ \ + 1 << 12 | /* GPIO26 0:non, 1:PU, 2:PD */ \ + 1 << 14 | /* GPIO27 0:non, 1:PU, 2:PD */ \ + 0 << 16 | /* GPIO28 0:non, 1:PU, 2:PD */ \ + 0 << 18 | /* GPIO29 0:non, 1:PU, 2:PD */ \ + 0 << 20 | /* GPIO2A 0:non, 1:PU, 2:PD */ \ + 0 << 22 | /* GPIO2B 0:non, 1:PU, 2:PD */ \ + 0 << 24 | /* GPIO2C 0:non, 1:PU, 2:PD */ \ + 0 << 26 | /* GPIO2D 0:non, 1:PU, 2:PD */ \ + 0 << 28 | /* GPIO2E 0:non, 1:PU, 2:PD */ \ + 0 << 30 /* GPIO2F 0:non, 1:PU, 2:PD */ + +#define PORT2_DRV \ + 0 << 0 | /* GPIO20 0:---, 1:---, 2:---, 3:--- */ \ + 0 << 2 | /* GPIO21 0:---, 1:---, 2:---, 3:--- */ \ + 0 << 4 | /* GPIO22 0:6mA, 1:---, 2:8mA, 3:10mA */ \ + 0 << 6 | /* GPIO23 0:6mA, 1:---, 2:8mA, 3:10mA */ \ + 0 << 8 | /* GPIO24 0:6mA, 1:---, 2:8mA, 3:10mA */ \ + 0 << 10 | /* GPIO25 0:6mA, 1:---, 2:8mA, 3:10mA */ \ + 0 << 12 | /* GPIO26 0:6mA, 1:---, 2:8mA, 3:10mA */ \ + 0 << 14 | /* GPIO27 0:6mA, 1:---, 2:8mA, 3:10mA */ \ + 0 << 16 | /* GPIO28 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 18 | /* GPIO29 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 20 | /* GPIO2A 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 22 | /* GPIO2B 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 24 | /* GPIO2C 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 26 | /* GPIO2D 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 28 | /* GPIO2E 0:1mA, 1:---, 2:2mA, 3:4mA */ \ + 0 << 30 /* GPIO2F 0:1mA, 1:---, 2:2mA, 3:4mA */ + +#define PORT2_DIR \ + 0 << 0 | /* GPIO20 0:in, 1:out */ \ + 1 << 1 | /* GPIO21 0:in, 1:out */ \ + 0 << 2 | /* GPIO22 0:in, 1:out */ \ + 0 << 3 | /* GPIO23 0:in, 1:out */ \ + 0 << 4 | /* GPIO24 0:in, 1:out */ \ + 0 << 5 | /* GPIO25 0:in, 1:out */ \ + 0 << 6 | /* GPIO26 0:in, 1:out */ \ + 0 << 7 | /* GPIO27 0:in, 1:out */ \ + 0 << 8 | /* GPIO28 0:in, 1:out */ \ + 0 << 9 | /* GPIO29 0:in, 1:out */ \ + 0 << 10 | /* GPIO2A 0:in, 1:out */ \ + 0 << 11 | /* GPIO2B 0:in, 1:out */ \ + 0 << 12 | /* GPIO2C 0:in, 1:out */ \ + 0 << 13 | /* GPIO2D 0:in, 1:out */ \ + 0 << 14 | /* GPIO2E 0:in, 1:out */ \ + 1 << 15 /* GPIO2F 0:in, 1:out */ + +#define PORT2_DAT \ + 0 << 0 | /* GPIO20 0:0, 1:1 */ \ + 1 << 1 | /* GPIO21 0:0, 1:1 */ \ + 0 << 2 | /* GPIO22 0:0, 1:1 */ \ + 0 << 3 | /* GPIO23 0:0, 1:1 */ \ + 0 << 4 | /* GPIO24 0:0, 1:1 */ \ + 0 << 5 | /* GPIO25 0:0, 1:1 */ \ + 0 << 6 | /* GPIO26 0:0, 1:1 */ \ + 0 << 7 | /* GPIO27 0:0, 1:1 */ \ + 0 << 8 | /* GPIO28 0:0, 1:1 */ \ + 0 << 9 | /* GPIO29 0:0, 1:1 */ \ + 0 << 10 | /* GPIO2A 0:0, 1:1 */ \ + 0 << 11 | /* GPIO2B 0:0, 1:1 */ \ + 0 << 12 | /* GPIO2C 0:0, 1:1 */ \ + 0 << 13 | /* GPIO2D 0:0, 1:1 */ \ + 0 << 14 | /* GPIO2E 0:0, 1:1 */ \ + 0 << 15 /* GPIO2F 0:0, 1:1 */ \ + + +/**************************************************************************** + * PORT3 + ****************************************************************************/ + +#define PORT3_MUX \ + 0 << 0 | /* 0: GPIO30, 1:NWRENWRL */ \ + 3 << 2 | /* 0: GPIO31, 1:NHBNWRH, 2: 3:TXDO */ \ + 0 << 4 | /* 0: GPIO32, 1:EXA1 */ \ + 0 << 6 | /* 0: GPIO33, 1:EXA2 */ \ + 0 << 8 | /* 0: GPIO34, 1:EXA3 */ \ + 0 << 10 | /* 0: GPIO35, 1:EXA4 */ \ + 0 << 12 | /* 0: GPIO36, 1:EXA5 */ \ + 0 << 14 | /* 0: GPIO37, 1:EXA6 */ \ + 0 << 16 | /* 0: GPIO38, 1:EXA7 */ \ + 0 << 18 | /* 0: GPIO39, 1:EXA8 */ \ + 0 << 20 | /* 0: GPIO3A, 1:EXA9 */ \ + 0 << 22 | /* 0: GPIO3B, 1:EXA10 */ \ + 0 << 24 | /* 0: GPIO3C, 1:EXA11 */ \ + 0 << 26 | /* 0: GPIO3D, 1:EXA12 */ \ + 0 << 28 | /* 0: GPIO3E, 1:EXA13 */ \ + 0 << 30 /* 0: GPIO3F, 1:EXA14 */ + +#define PORT3_PUPD \ + 0 << 0 | /* GPIO30 0:non, 1: 2:PD */ \ + 0 << 2 | /* GPIO31 0:non, 1: 2:PD */ \ + 0 << 4 | /* GPIO32 0:non, 1: 2:PD */ \ + 0 << 6 | /* GPIO33 0:non, 1: 2:PD */ \ + 0 << 8 | /* GPIO34 0:non, 1: 2:PD */ \ + 0 << 10 | /* GPIO35 0:non, 1: 2:PD */ \ + 0 << 12 | /* GPIO36 0:non, 1: 2:PD */ \ + 0 << 14 | /* GPIO37 0:non, 1: 2:PD */ \ + 0 << 16 | /* GPIO38 0:non, 1: 2:PD */ \ + 0 << 18 | /* GPIO39 0:non, 1: 2:PD */ \ + 0 << 20 | /* GPIO3A 0:non, 1: 2:PD */ \ + 0 << 22 | /* GPIO3B 0:non, 1: 2:PD */ \ + 0 << 24 | /* GPIO3C 0:non, 1: 2:PD */ \ + 0 << 26 | /* GPIO3D 0:non, 1: 2:PD */ \ + 0 << 28 | /* GPIO3E 0:non, 1: 2:PD */ \ + 0 << 30 /* GPIO3F 0:non, 1: 2:PD */ + +#define PORT3_DRV \ + 0 << 0 | /* GPIO30 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 2 | /* GPIO31 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 4 | /* GPIO32 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 6 | /* GPIO33 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 8 | /* GPIO34 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 10 | /* GPIO35 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 12 | /* GPIO36 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 14 | /* GPIO37 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 16 | /* GPIO38 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 18 | /* GPIO39 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 20 | /* GPIO3A 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 22 | /* GPIO3B 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 24 | /* GPIO3C 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 26 | /* GPIO3D 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 28 | /* GPIO3E 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 30 /* GPIO3F 0:2mA, 1:---, 2:4mA, 3:8mA */ + +#define PORT3_DIR \ + 1 << 0 | /* GPIO30 0:in, 1:out */ \ + 0 << 1 | /* GPIO31 0:in, 1:out */ \ + 0 << 2 | /* GPIO32 0:in, 1:out */ \ + 0 << 3 | /* GPIO33 0:in, 1:out */ \ + 0 << 4 | /* GPIO34 0:in, 1:out */ \ + 0 << 5 | /* GPIO35 0:in, 1:out */ \ + 0 << 6 | /* GPIO36 0:in, 1:out */ \ + 0 << 7 | /* GPIO37 0:in, 1:out */ \ + 0 << 8 | /* GPIO38 0:in, 1:out */ \ + 0 << 9 | /* GPIO39 0:in, 1:out */ \ + 0 << 10 | /* GPIO3A 0:in, 1:out */ \ + 0 << 11 | /* GPIO3B 0:in, 1:out */ \ + 0 << 12 | /* GPIO3C 0:in, 1:out */ \ + 0 << 13 | /* GPIO3D 0:in, 1:out */ \ + 0 << 14 | /* GPIO3E 0:in, 1:out */ \ + 0 << 15 /* GPIO3F 0:in, 1:out */ + +#define PORT3_DAT \ + 0 << 0 | /* GPIO30 0:0, 1:1 */ \ + 0 << 1 | /* GPIO31 0:0, 1:1 */ \ + 0 << 2 | /* GPIO32 0:0, 1:1 */ \ + 0 << 3 | /* GPIO33 0:0, 1:1 */ \ + 0 << 4 | /* GPIO34 0:0, 1:1 */ \ + 0 << 5 | /* GPIO35 0:0, 1:1 */ \ + 0 << 6 | /* GPIO36 0:0, 1:1 */ \ + 0 << 7 | /* GPIO37 0:0, 1:1 */ \ + 0 << 8 | /* GPIO38 0:0, 1:1 */ \ + 0 << 9 | /* GPIO39 0:0, 1:1 */ \ + 0 << 10 | /* GPIO3A 0:0, 1:1 */ \ + 0 << 11 | /* GPIO3B 0:0, 1:1 */ \ + 0 << 12 | /* GPIO3C 0:0, 1:1 */ \ + 0 << 13 | /* GPIO3D 0:0, 1:1 */ \ + 0 << 14 | /* GPIO3E 0:0, 1:1 */ \ + 0 << 15 /* GPIO3F 0:0, 1:1 */ + + +/**************************************************************************** + * PORT4 + ****************************************************************************/ + +#define PORT4_MUX \ + 0 << 0 | /* 0: GPIO40, 1:EXA15 */ \ + 0 << 2 | /* 0: GPIO41, 1:EXA16 */ \ + 0 << 4 | /* 0: GPIO42, 1:EXA17 */ \ + 0 << 6 | /* 0: GPIO43, 1:EXA18 */ \ + 0 << 8 | /* 0: GPIO44, 1:EXA19 */ \ + 0 << 10 | /* 0: GPIO45, 1:EXA20 */ \ + 0 << 12 | /* 0: GPIO46, 1:EXD0 */ \ + 0 << 14 | /* 0: GPIO47, 1:EXD1 */ \ + 0 << 16 | /* 0: GPIO48, 1:EXD2 */ \ + 0 << 18 | /* 0: GPIO49, 1:EXD3 */ \ + 0 << 20 | /* 0: GPIO4A, 1:EXD4 */ \ + 0 << 22 | /* 0: GPIO4B, 1:EXD5 */ \ + 0 << 24 | /* 0: GPIO4C, 1:EXD6 */ \ + 0 << 26 | /* 0: GPIO4D, 1:EXD7 */ \ + 0 << 28 | /* 0: GPIO4E, 1:EXD8 */ \ + 0 << 30 /* 0: GPIO4F, 1:EXD9 */ + +#define PORT4_PUPD \ + 0 << 0 | /* GPIO40 0:non, 1: 2:PD */ \ + 0 << 2 | /* GPIO41 0:non, 1: 2:PD */ \ + 0 << 4 | /* GPIO42 0:non, 1: 2:PD */ \ + 0 << 6 | /* GPIO43 0:non, 1: 2:PD */ \ + 0 << 8 | /* GPIO44 0:non, 1: 2:PD */ \ + 0 << 10 | /* GPIO45 0:non, 1: 2:PD */ \ + 0 << 12 | /* GPIO46 0:non, 1: 2:PD */ \ + 0 << 14 | /* GPIO47 0:non, 1: 2:PD */ \ + 0 << 16 | /* GPIO48 0:non, 1: 2:PD */ \ + 0 << 18 | /* GPIO49 0:non, 1: 2:PD */ \ + 0 << 20 | /* GPIO4A 0:non, 1: 2:PD */ \ + 0 << 22 | /* GPIO4B 0:non, 1: 2:PD */ \ + 0 << 24 | /* GPIO4C 0:non, 1: 2:PD */ \ + 0 << 26 | /* GPIO4D 0:non, 1: 2:PD */ \ + 0 << 28 | /* GPIO4E 0:non, 1: 2:PD */ \ + 0 << 30 /* GPIO4F 0:non, 1: 2:PD */ + +#define PORT4_DRV \ + 0 << 0 | /* GPIO40 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 2 | /* GPIO41 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 4 | /* GPIO42 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 6 | /* GPIO43 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 8 | /* GPIO44 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 10 | /* GPIO45 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 12 | /* GPIO46 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 14 | /* GPIO47 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 16 | /* GPIO48 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 18 | /* GPIO49 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 20 | /* GPIO4A 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 22 | /* GPIO4B 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 24 | /* GPIO4C 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 26 | /* GPIO4D 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 28 | /* GPIO4E 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 30 /* GPIO4F 0:2mA, 1:---, 2:4mA, 3:8mA */ + +#define PORT4_DIR \ + 0 << 0 | /* GPIO40 0:in, 1:out */ \ + 0 << 1 | /* GPIO41 0:in, 1:out */ \ + 0 << 2 | /* GPIO42 0:in, 1:out */ \ + 0 << 3 | /* GPIO43 0:in, 1:out */ \ + 0 << 4 | /* GPIO44 0:in, 1:out */ \ + 0 << 5 | /* GPIO45 0:in, 1:out */ \ + 0 << 6 | /* GPIO46 0:in, 1:out */ \ + 1 << 7 | /* GPIO47 0:in, 1:out */ \ + 1 << 8 | /* GPIO48 0:in, 1:out */ \ + 1 << 9 | /* GPIO49 0:in, 1:out */ \ + 0 << 10 | /* GPIO4A 0:in, 1:out */ \ + 0 << 11 | /* GPIO4B 0:in, 1:out */ \ + 0 << 12 | /* GPIO4C 0:in, 1:out */ \ + 0 << 13 | /* GPIO4D 0:in, 1:out */ \ + 0 << 14 | /* GPIO4E 0:in, 1:out */ \ + 0 << 15 /* GPIO4F 0:in, 1:out */ + +#define PORT4_DAT \ + 0 << 0 | /* GPIO40 0:0, 1:1 */ \ + 0 << 1 | /* GPIO41 0:0, 1:1 */ \ + 0 << 2 | /* GPIO42 0:0, 1:1 */ \ + 0 << 3 | /* GPIO43 0:0, 1:1 */ \ + 0 << 4 | /* GPIO44 0:0, 1:1 */ \ + 0 << 5 | /* GPIO45 0:0, 1:1 */ \ + 0 << 6 | /* GPIO46 0:0, 1:1 */ \ + 0 << 7 | /* GPIO47 0:0, 1:1 */ \ + 0 << 8 | /* GPIO48 0:0, 1:1 */ \ + 0 << 9 | /* GPIO49 0:0, 1:1 */ \ + 0 << 10 | /* GPIO4A 0:0, 1:1 */ \ + 0 << 11 | /* GPIO4B 0:0, 1:1 */ \ + 0 << 12 | /* GPIO4C 0:0, 1:1 */ \ + 0 << 13 | /* GPIO4D 0:0, 1:1 */ \ + 0 << 14 | /* GPIO4E 0:0, 1:1 */ \ + 0 << 15 /* GPIO4F 0:0, 1:1 */ + + +/**************************************************************************** + * PORT5 + ****************************************************************************/ + +#define PORT5_MUX \ + 0 << 0 | /* 0: GPIO50, 1:EXD10 */ \ + 0 << 2 | /* 0: GPIO51, 1:EXD11 */ \ + 0 << 4 | /* 0: GPIO52, 1:EXD12 */ \ + 0 << 6 | /* 0: GPIO53, 1:EXD13 */ \ + 0 << 8 | /* 0: GPIO54, 1:EXD14 */ \ + 0 << 10 | /* 0: GPIO55, 1:EXD25 */ \ + 1 << 12 | /* 0: GPIO56, 1:CTS1, 2:SDAT22 3:RXD0 */ \ + 1 << 14 | /* 0: GPIO57, 1:RTS1, 2:SDAT23 3:TXD0 */ \ + 3 << 16 | /* 0: GPIO58, 1:DMCKO1, 2: 3:SWDCLK */ \ + 3 << 18 /* 0: GPIO59, 1:DMDIN1, 2: 3:SWDIO */ + +#define PORT5_PUPD \ + 0 << 0 | /* GPIO50 0:non, 1: 2:PD */ \ + 0 << 2 | /* GPIO51 0:non, 1: 2:PD */ \ + 0 << 4 | /* GPIO52 0:non, 1: 2:PD */ \ + 0 << 6 | /* GPIO53 0:non, 1: 2:PD */ \ + 0 << 8 | /* GPIO54 0:non, 1: 2:PD */ \ + 0 << 10 | /* GPIO55 0:non, 1: 2:PD */ \ + 2 << 12 | /* GPIO56 0:non, 1:PU, 2:PD */ \ + 2 << 14 | /* GPIO57 0:non, 1:PU, 2:PD */ \ + 0 << 16 | /* GPIO58 0:non, 1:PU, 2:PD */ \ + 0 << 18 /* GPIO59 0:non, 1:PU */ + +#define PORT5_DRV \ + 0 << 0 | /* GPIO50 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 2 | /* GPIO51 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 4 | /* GPIO52 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 6 | /* GPIO53 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 8 | /* GPIO54 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 10 | /* GPIO55 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 12 | /* GPIO56 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 14 | /* GPIO57 0:6mA, 1:---, 2:8mA, 3:10mA */ \ + 0 << 16 | /* GPIO58 0:6mA, 1:---, 2:8mA, 3:10mA */ \ + 0 << 18 /* GPIO59 0:1mA, 1:---, 2:2mA, 3:4mA */ + +#define PORT5_DIR \ + 0 << 0 | /* GPIO50 0:in, 1:out */ \ + 0 << 1 | /* GPIO51 0:in, 1:out */ \ + 0 << 2 | /* GPIO52 0:in, 1:out */ \ + 0 << 3 | /* GPIO53 0:in, 1:out */ \ + 0 << 4 | /* GPIO54 0:in, 1:out */ \ + 0 << 5 | /* GPIO55 0:in, 1:out */ \ + 0 << 6 | /* GPIO56 0:in, 1:out */ \ + 0 << 7 | /* GPIO57 0:in, 1:out */ \ + 0 << 8 | /* GPIO58 0:in, 1:out */ \ + 0 << 9 /* GPIO59 0:in, 1:out */ + +#define PORT5_DAT \ + 0 << 0 | /* GPIO50 0:0, 1:1 */ \ + 0 << 1 | /* GPIO51 0:0, 1:1 */ \ + 0 << 2 | /* GPIO52 0:0, 1:1 */ \ + 0 << 3 | /* GPIO53 0:0, 1:1 */ \ + 0 << 4 | /* GPIO54 0:0, 1:1 */ \ + 0 << 5 | /* GPIO55 0:0, 1:1 */ \ + 0 << 6 | /* GPIO56 0:0, 1:1 */ \ + 0 << 7 | /* GPIO57 0:0, 1:1 */ \ + 0 << 8 | /* GPIO58 0:0, 1:1 */ \ + 0 << 9 /* GPIO59 0:0, 1:1 */ + + +/**************************************************************************** + * PORT6 + ****************************************************************************/ + +#define PORT6_PUPD \ + 1 << 2 | /* SDCMD0 0:non, 1: 2:PD */ \ + 1 << 4 | /* SDAT03-0 0:non, 1: 2:PD */ \ + 0 << 6 | /* SDRDATA15-0 0:non, 1: 2:PD */ \ + 0 << 8 | /* BMODE0 0:non, 1: 2:PD */ \ + 0 << 10 | /* BMODE1 0:non, 1: 2:PD */ \ + 0 << 12 | /* XTALINFO0 0:non, 1:PU, 2:PD */ \ + 0 << 14 /* XTALINFO1 0:non, 1:PU, 2:PD */ + +#define PORT6_DRV \ + 2 << 0 | /* SDCLK0 0:6mA, 1:---, 2:8mA, 3:10mA */ \ + 2 << 2 | /* SDCMD0 0:6mA, 1:---, 2:8mA, 3:10mA */ \ + 2 << 4 | /* SDAT03 0:6mA, 1:---, 2:8mA, 3:10mA */ \ + 0 << 6 | /* SDRDA1 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 8 | /* SDRAD1 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 10 | /* SDRBA1 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 12 | /* SDRCAS 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 14 | /* SDRCKE 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 16 | /* SDRCLK 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 18 | /* SDRCS 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 20 | /* SDRDQM 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 22 | /* XTALI0 0:2mA, 1:---, 2:4mA, 3:8mA */ \ + 0 << 24 /* XTALI1 0:2mA, 1:---, 2:4mA, 3:8mA */ + + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#endif /* __CONFIGS_LC823450_XGEVK_SRC_LC823450_XGEVK_MUX_H */ diff --git a/configs/lc823450-xgevk/src/lc823450_appinit.c b/configs/lc823450-xgevk/src/lc823450_appinit.c new file mode 100644 index 00000000000..9d4a8fb42f4 --- /dev/null +++ b/configs/lc823450-xgevk/src/lc823450_appinit.c @@ -0,0 +1,179 @@ +/**************************************************************************** + * configs/lc823450-xgevk/src/lc823450_appinit.c + * + * Copyright (C) 2017 Sony Corporation. All rights reserved. + * Author: Masayuki Ishikawa + * + * 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 "lc823450_i2c.h" +#include "lc823450-xgevk.h" + +#ifdef CONFIG_LIB_BOARDCTL + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lc823450_i2c_register + * + * Description: + * Register one I2C drivers for the I2C tool. + * + ****************************************************************************/ + +#ifdef HAVE_I2CTOOL +static void lc823450_i2c_register(int bus) +{ + FAR struct i2c_master_s *i2c; + int ret; + + i2c = lc823450_i2cbus_initialize(bus); + if (i2c == NULL) + { + _err("ERROR: Failed to get I2C%d interface\n", bus); + } + else + { + ret = i2c_register(i2c, bus); + if (ret < 0) + { + _err("ERROR: Failed to register I2C%d driver: %d\n", bus, ret); + lc823450_i2cbus_uninitialize(i2c); + } + } +} +#endif + +/**************************************************************************** + * Name: lc823450_i2ctool + * + * Description: + * Register I2C drivers for the I2C tool. + * + ****************************************************************************/ + +#ifdef HAVE_I2CTOOL +static void lc823450_i2ctool(void) +{ +#ifdef CONFIG_LC823450_I2C0 + lc823450_i2c_register(0); +#endif +#ifdef CONFIG_LC823450_I2C1 + lc823450_i2c_register(1); +#endif +} +#else +# define lc823450_i2ctool() +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + + +/**************************************************************************** + * Name: board_app_initialize + * + * Description: + * Perform application specific initialization. This function is never + * called directly from application code, but only indirectly via the + * (non-standard) boardctl() interface using the command BOARDIOC_INIT. + * + * Input Parameters: + * arg - The boardctl() argument is passed to the board_app_initialize() + * implementation without modification. The argument has no + * meaning to NuttX; the meaning of the argument is a contract + * between the board-specific initalization logic and the the + * matching application logic. The value cold be such things as a + * mode enumeration value, a set of DIP switch switch settings, a + * pointer to configuration data read from a file or serial FLASH, + * or whatever you would like to do with it. Every implementation + * should accept zero/NULL as a default configuration. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ + +int board_app_initialize(uintptr_t arg) +{ + /* Register I2C drivers on behalf of the I2C tool */ + + lc823450_i2ctool(); + +#ifdef CONFIG_MTD_LC823450 + /* Initialize eMMC */ + + int ret = lc823450_mtd_initialize(CONFIG_MTD_DEVNO_EMMC); + if (ret != OK) + { + _err("Failed to initialize eMMC: ret=%d\n", ret); + } + +#ifdef CONFIG_LC823450_SDIF_SDC + /* Initialize uSD */ + + ret = lc823450_mtd_initialize(CONFIG_MTD_DEVNO_SDC); + if (ret != OK) + { + _err("Failed to initialize uSD: ret=%d\n", ret); + } +#endif /* CONFIG_LC823450_SDIF_SDC */ + +#endif /* CONFIG_MTD_LC823450 */ + +#ifndef CONFIG_BOARD_INITIALIZE + /* Perform board initialization */ + + return lc823450_bringup(); +#else + return OK; +#endif +} + +#endif /* CONFIG_LIB_BOARDCTL */ diff --git a/configs/lc823450-xgevk/src/lc823450_boot.c b/configs/lc823450-xgevk/src/lc823450_boot.c new file mode 100644 index 00000000000..3c70f673e2b --- /dev/null +++ b/configs/lc823450-xgevk/src/lc823450_boot.c @@ -0,0 +1,79 @@ +/**************************************************************************** + * configs/lc823450-xgevk/src/lc823450_boot.c + * + * Copyright (C) 2017 Sony Corporation. All rights reserved. + * Author: Masayuki Ishikawa + * + * 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 + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_initialize + * + * Description: + * If CONFIG_BOARD_INITIALIZE is selected, then an additional + * initialization call will be performed in the boot-up sequence to a + * function called board_initialize(). board_initialize() will be + * called immediately after up_intitialize() is called and just before the + * initial application is started. This additional initialization phase + * may be used, for example, to initialize board-specific device drivers. + * + ****************************************************************************/ + +#ifdef CONFIG_BOARD_INITIALIZE +void board_initialize(void) +{ + /* Perform board initialization */ + + (void)lc823450_bringup(); +} +#endif /* CONFIG_BOARD_INITIALIZE */ diff --git a/configs/lc823450-xgevk/src/lc823450_bringup.c b/configs/lc823450-xgevk/src/lc823450_bringup.c new file mode 100644 index 00000000000..4f033231ccd --- /dev/null +++ b/configs/lc823450-xgevk/src/lc823450_bringup.c @@ -0,0 +1,95 @@ +/**************************************************************************** + * configs/lc823450-xgevk/src/lc823450_bringup.c + * + * Copyright (C) 2017 Sony Corporation. All rights reserved. + * Author: Masayuki Ishikawa + * + * 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 "lc823450-xgevk.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lc823450_bringup + * + * Description: + * Bring up board features + * + ****************************************************************************/ + +int lc823450_bringup(void) +{ + int ret; + +#ifdef CONFIG_FS_PROCFS + /* Mount the procfs file system */ + + ret = mount(NULL, "/proc", "procfs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount procfs at /proc: %d\n", ret); + } +#endif + +#ifdef CONFIG_BMA250 + lc823450_bma250initialize("/dev/accel"); +#endif + + /* If we got here then perhaps not all initialization was successful, but + * at least enough succeeded to bring-up NSH with perhaps reduced + * capabilities. + */ + + UNUSED(ret); + return OK; +} diff --git a/configs/lc823450-xgevk/src/lc823450_mux.c b/configs/lc823450-xgevk/src/lc823450_mux.c new file mode 100644 index 00000000000..f054d84415e --- /dev/null +++ b/configs/lc823450-xgevk/src/lc823450_mux.c @@ -0,0 +1,133 @@ +/**************************************************************************** + * configs/lc823450-xgevk/src/lc823450_mux.c + * + * Copyright (C) 2017 Sony Corporation. All rights reserved. + * Author: Masatoshi Tateishi + * Author: Masayuki Ishikawa + * + * 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 "chip.h" +#include "up_arch.h" +#include "up_internal.h" +#include "lc823450_syscontrol.h" + +#include "lc823450-xgevk_mux.h" + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_init_default_mux + * + * Description: + * Initial pinmux settings at boot + * + ****************************************************************************/ + +void up_init_default_mux(void) +{ + modifyreg32(MCLKCNTAPB, 0, + MCLKCNTAPB_PORT0_CLKEN | + MCLKCNTAPB_PORT1_CLKEN | + MCLKCNTAPB_PORT2_CLKEN | + MCLKCNTAPB_PORT3_CLKEN | + MCLKCNTAPB_PORT4_CLKEN | + MCLKCNTAPB_PORT5_CLKEN); + + modifyreg32(MRSTCNTAPB, 0, + MRSTCNTAPB_PORT0_RSTB | + MRSTCNTAPB_PORT1_RSTB | + MRSTCNTAPB_PORT2_RSTB | + MRSTCNTAPB_PORT3_RSTB | + MRSTCNTAPB_PORT4_RSTB | + MRSTCNTAPB_PORT5_RSTB); + + putreg32(PORT0_MUX, PMDCNT0); + putreg32(PORT0_PUPD, PUDCNT0); + putreg32(PORT0_DRV, PTDRVCNT0); + putreg32(PORT0_DAT, rP0DT); + putreg32(PORT0_DIR, rP0DRC); + + putreg32(PORT1_MUX, PMDCNT1); + putreg32(PORT1_PUPD, PUDCNT1); + putreg32(PORT1_DRV, PTDRVCNT1); + putreg32(PORT1_DAT, rP1DT); + putreg32(PORT1_DIR, rP1DRC); + + putreg32(PORT2_MUX, PMDCNT2); + putreg32(PORT2_PUPD, PUDCNT2); + putreg32(PORT2_DRV, PTDRVCNT2); + putreg32(PORT2_DAT, rP2DT); + putreg32(PORT2_DIR, rP2DRC); + + putreg32(PORT3_MUX, PMDCNT3); + putreg32(PORT3_PUPD, PUDCNT3); + putreg32(PORT3_DRV, PTDRVCNT3); + putreg32(PORT3_DAT, rP3DT); + putreg32(PORT3_DIR, rP3DRC); + + putreg32(PORT4_MUX, PMDCNT4); + putreg32(PORT4_PUPD, PUDCNT4); + putreg32(PORT4_DRV, PTDRVCNT4); + putreg32(PORT4_DAT, rP4DT); + putreg32(PORT4_DIR, rP4DRC); + + putreg32(PORT5_MUX, PMDCNT5); + putreg32(PORT5_PUPD, PUDCNT5); + putreg32(PORT5_DRV, PTDRVCNT5); + putreg32(PORT5_DAT, rP5DT); + putreg32(PORT5_DIR, rP5DRC); + + putreg32(PORT6_PUPD, PUDCNT6); + putreg32(PORT6_DRV, PTDRVCNT6); + +} diff --git a/configs/lc823450-xgevk/src/lc823450_spi.c b/configs/lc823450-xgevk/src/lc823450_spi.c new file mode 100644 index 00000000000..ea3563662ac --- /dev/null +++ b/configs/lc823450-xgevk/src/lc823450_spi.c @@ -0,0 +1,81 @@ +/**************************************************************************** + * configs/lc823450-xgevk/src/lc823450_spi.c + * + * Copyright (C) 2017 Sony Corporation. All rights reserved. + * Author: Masayuki Ishikawa + * + * 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 "lc823450_gpio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + + +/**************************************************************************** + * Name: lc823450_spiselect + * + ****************************************************************************/ + +void lc823450_spiselect(FAR struct spi_dev_s *dev, uint32_t devid, bool selected) +{ + /* no need */ +} + + +/**************************************************************************** + * Name: lc823450_spiinitialize + * + * Description: + * Called to configure SPI chip select GPIO pins for the lc823450 board. + * + ****************************************************************************/ + +void lc823450_spiinitialize(void) +{ + /* NOTE: already set in _mux.h */ +} diff --git a/configs/lc823450-xgevk/src/lc823450_st7565.c b/configs/lc823450-xgevk/src/lc823450_st7565.c new file mode 100644 index 00000000000..c939cc00420 --- /dev/null +++ b/configs/lc823450-xgevk/src/lc823450_st7565.c @@ -0,0 +1,226 @@ +/**************************************************************************** + * configs/lc823450-xgevk/src/lc823450_st7565.c + * + * Copyright (C) 2017 Sony Corporation. All rights reserved. + * Author: Masayuki Ishikawa + * + * 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 "up_arch.h" +#include "lc823450_gpio.h" +#include "lc823450_spi.h" +#include "lc823450-xgevk.h" + + +#ifdef CONFIG_NX_LCDDRIVER + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define LCD_SPI_PORTNO 0 + +#define GPIO_LCD_CS (GPIO_PORT1 | GPIO_PINE | GPIO_MODE_OUTPUT | GPIO_VALUE_ONE) +#define GPIO_LCD_A0 (GPIO_PORT4 | GPIO_PIN9 | GPIO_MODE_OUTPUT | GPIO_VALUE_ONE) +#define GPIO_LCD_NRES (GPIO_PORT4 | GPIO_PIN8 | GPIO_MODE_OUTPUT | GPIO_VALUE_ONE) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + + +static void lc823450_st7565_reset(FAR struct st7565_lcd_s *lcd, bool on); +static void lc823450_st7565_select(FAR struct st7565_lcd_s *lcd); +static void lc823450_st7565_deselect(FAR struct st7565_lcd_s *lcd); +static void lc823450_st7565_cmddata(FAR struct st7565_lcd_s *lcd, const uint8_t cmd); +static int lc823450_st7565_senddata(FAR struct st7565_lcd_s *lcd, FAR const uint8_t *data, + int size); +static int lc823450_st7565_backlight(FAR struct st7565_lcd_s *lcd, int level); + + +static FAR struct spi_dev_s *g_spidev; +static FAR struct lcd_dev_s *g_lcddev; + +static struct st7565_lcd_s g_st7565_dev = +{ + .reset = lc823450_st7565_reset, + .select = lc823450_st7565_select, + .deselect = lc823450_st7565_deselect, + .cmddata = lc823450_st7565_cmddata, + .senddata = lc823450_st7565_senddata, + .backlight = lc823450_st7565_backlight, +}; + + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lc823450_st7565_reset + ****************************************************************************/ + +static void lc823450_st7565_reset(FAR struct st7565_lcd_s *lcd, bool on) +{ + if (on) + { + lc823450_gpio_write(GPIO_LCD_NRES, false); + } + else + { + lc823450_gpio_write(GPIO_LCD_NRES, true); + } +} + +/**************************************************************************** + * Name: lc823450_st7565_select + ****************************************************************************/ + +static void lc823450_st7565_select(FAR struct st7565_lcd_s *lcd) +{ + lc823450_gpio_write(GPIO_LCD_CS, false); +} + +/**************************************************************************** + * Name: lc823450_st7565_deselect + ****************************************************************************/ + +static void lc823450_st7565_deselect(FAR struct st7565_lcd_s *lcd) +{ + lc823450_gpio_write(GPIO_LCD_CS, true); +} + +/**************************************************************************** + * Name: lc823450_st7565_cmddata + ****************************************************************************/ + +static void lc823450_st7565_cmddata(FAR struct st7565_lcd_s *lcd, const uint8_t cmd) +{ + lc823450_gpio_write(GPIO_LCD_A0, !cmd); +} + +/**************************************************************************** + * Name: lc823450_st7565_senddata + ****************************************************************************/ + +static int lc823450_st7565_senddata(FAR struct st7565_lcd_s *lcd, + FAR const uint8_t *data, + int size) +{ + SPI_SNDBLOCK(g_spidev, data, size); + return 0; +} + +/**************************************************************************** + * Name: lc823450_st7565_backlight + ****************************************************************************/ + +static int lc823450_st7565_backlight(FAR struct st7565_lcd_s *lcd, int level) +{ + return 0; +} + + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_lcd_initialize + ****************************************************************************/ + +int board_lcd_initialize(void) +{ + g_spidev = lc823450_spibus_initialize(LCD_SPI_PORTNO); + ASSERT(NULL != g_spidev); + + g_spidev->ops->setmode(g_spidev, SPIDEV_MODE3); + g_spidev->ops->setbits(g_spidev, 8); + g_spidev->ops->setfrequency(g_spidev, 1000000); + + return 0; +} + + +/**************************************************************************** + * Name: board_lcd_getdev + ****************************************************************************/ + +FAR struct lcd_dev_s *board_lcd_getdev(int lcddev) +{ + g_lcddev = st7565_initialize(&g_st7565_dev, lcddev); + if (!g_lcddev) + { + lcderr("ERROR: Failed to bind SPI port 1 to LCD %d: %d\n", lcddev); + } + else + { + lcdinfo("SPI port 1 bound to LCD %d\n", lcddev); + + (void)g_lcddev->setcontrast(g_lcddev, CONFIG_LCD_MAXCONTRAST); + + /* And turn the LCD on (CONFIG_LCD_MAXPOWER should be 1) */ + + (void)g_lcddev->setpower(g_lcddev, CONFIG_LCD_MAXPOWER); + return g_lcddev; + } + + return NULL; +} + +/**************************************************************************** + * Name: board_lcd_uninitialize + ****************************************************************************/ + +void board_lcd_uninitialize(void) +{ +} + +#endif /* CONFIG_NX_LCDDRIVER */