diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 653d063920393..81ea402755d28 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -489,6 +489,15 @@ config ARCH_CHIP_PHY62XX ---help--- Phyplus PHY62XX architectures (ARM Cortex-M0). +config ARCH_CHIP_TLSR82 + bool "Telink TLSR82XX" + select ARCH_ARMV6M + select ARCH_HAVE_BACKTRACE + select ARCH_HAVE_RESET + select LIBC_ARCH_ATOMIC + ---help--- + Telink tlsr82xx architectures (Customed armv6m) + config ARCH_CHIP_ARM_CUSTOM bool "Custom ARM chip" select ARCH_CHIP_CUSTOM @@ -845,6 +854,7 @@ config ARCH_CHIP default "xmc4" if ARCH_CHIP_XMC4 default "cxd56xx" if ARCH_CHIP_CXD56XX default "phy62xx" if ARCH_CHIP_PHY62XX + default "tlsr82" if ARCH_CHIP_TLSR82 config ARCH_HAVE_TRUSTZONE bool @@ -905,7 +915,7 @@ config ARM_FPU_ABI_SOFT default n depends on ARCH_HAVE_FPU ---help--- - Pass float value via integer register (-mfloat-abi=softfp) + Pass float value via integer register (-mfloat-abi=softfp) config ARM_DPFPU32 bool "FPU with 32 double-precision register" @@ -1232,5 +1242,7 @@ endif if ARCH_CHIP_CXD56XX source "arch/arm/src/cxd56xx/Kconfig" endif - +if ARCH_CHIP_TLSR82 +source "arch/arm/src/tlsr82/Kconfig" +endif endif # ARCH_ARM diff --git a/arch/arm/include/tlsr82/chip.h b/arch/arm/include/tlsr82/chip.h new file mode 100644 index 0000000000000..f30e7b3431c34 --- /dev/null +++ b/arch/arm/include/tlsr82/chip.h @@ -0,0 +1,24 @@ +/**************************************************************************** + * arch/arm/include/tlsr82/chip.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_INCLUDE_TLSR82_CHIP_H +#define __ARCH_ARM_INCLUDE_TLSR82_CHIP_H + +#endif /* __ARCH_ARM_INCLUDE_TLSR82_CHIP_H */ diff --git a/arch/arm/include/tlsr82/irq.h b/arch/arm/include/tlsr82/irq.h new file mode 100644 index 0000000000000..2ab314c524844 --- /dev/null +++ b/arch/arm/include/tlsr82/irq.h @@ -0,0 +1,259 @@ +/**************************************************************************** + * arch/arm/include/tlsr82/irq.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* This file should never be included directly but, rather, only indirectly + * through nuttx/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_TLSR82_IRQ_H +#define __ARCH_ARM_INCLUDE_TLSR82_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +#endif + +/**************************************************************************** + * Pre-processor Prototypes + ****************************************************************************/ + +/* Define this to prevent the arch irq.h include */ + +#define __ARCH_ARM_INCLUDE_ARMV6_M_IRQ_H + +#define _REG_BASE_ADDR 0x00800000 +#define _REG_ADDR8(a) (*(volatile uint8_t *)(_REG_BASE_ADDR + (a))) +#define _REG_ADDR32(a) (*(volatile uint32_t *)(_REG_BASE_ADDR + (a))) + +#define _IRQ_MASK_REG _REG_ADDR32(0x640) +#define _IRQ_EN_REG _REG_ADDR8(0x643) + +#define NR_TIMER0_IRQ 0 +#define NR_TIMER1_IRQ 1 +#define NR_TIMER2_IRQ 2 +#define NR_USB_PWDN_IRQ 3 +#define NR_DMA_IRQ 4 +#define NR_DMA_FIFO_IRQ 5 +#define NR_UART_IRQ 6 +#define NR_MIX_CMD_IRQ 7 + +#define NR_EP0_SETUP_IRQ 8 +#define NR_EP0_DATA_IRQ 9 +#define NR_EP0_STA_IRQ 10 +#define NR_SET_INTF_IRQ 11 +#define NR_EP_DATA_IRQ 12 +#define NR_RF_IRQ 13 +#define NR_SW_PWM_IRQ 14 +#define NR_PKE_IRQ 15 + +#define NR_USB_250US_IRQ 16 +#define NR_USB_RST_IRQ 17 +#define NR_GPIO_IRQ 18 +#define NR_PM_IRQ 19 +#define NR_SYSTEM_TIMER_IRQ 20 +#define NR_GPIO_RISC0_IRQ 21 +#define NR_GPIO_RISC1_IRQ 22 + +#define NR_IRQS 23 + +/* IRQ Stack Frame Format: + * + * Low Address | + * | regs --> 1 PC (aka R15) + * | 1 SP (aka R13) + * | 5 R12 ~ R8 + * | 1 IRQ_STATE + * | 1 CPSR + * | 8 R7 ~ R0 + * | 1 R14 (aka R14) + * High Address v + * + * This results in the following set of indices that + * can be used to access individual registers in the + * xcp.regs array: + */ + +#define REG_START (0) +#define REG_R15 (0) +#define REG_R13 (1) +#define REG_R12 (2) +#define REG_R11 (3) +#define REG_R10 (4) +#define REG_R9 (5) +#define REG_R8 (6) +#define REG_IRQ_EN (7) +#define REG_CPSR (8) +#define REG_R7 (9) +#define REG_R6 (10) +#define REG_R5 (11) +#define REG_R4 (12) +#define REG_R3 (13) +#define REG_R2 (14) +#define REG_R1 (15) +#define REG_R0 (16) +#define REG_R14 (17) +#define REG_END (18) + +#define XCPTCONTEXT_REGS (18) +#define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS) + +#define REG_FP REG_R7 +#define REG_IP REG_R12 +#define REG_SP REG_R13 +#define REG_LR REG_R14 +#define REG_PC REG_R15 + +/* The PIC register is usually R10. It can be R9 is stack checking is enabled + * or if the user changes it with -mpic-register on the GCC command line. + */ + +#define REG_PIC REG_R10 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This struct defines the way the registers are stored. We + * need to save: + * + * Low Address | + * | regs --> 1 PC (aka R15) + * | 1 SP (aka R13) + * | 5 R12 ~ R8 + * | 1 IRQ_STATE + * | 1 CPSR + * | 8 R7 ~ R0 + * | 1 R14 (aka R14) + * High Address v + * + * For a total of 18 (XCPTCONTEXT_REGS). + * + * Note: all the register are saved by software, hardware not + * push register into the stack automatically when interrupt + * occur. + */ + +#ifndef __ASSEMBLY__ +struct xcptcontext +{ + /* The following function pointer is non-zero if there + * are pending signals to be processed. + */ + + void *sigdeliver; /* Actual type is sig_deliver_t */ + + /* These are saved register array pointer used during + * signal processing. + */ + + uint32_t *saved_regs; + + /* Register save area */ + + uint32_t *regs; +}; +#endif + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* Name: up_irq_save, up_irq_restore, and friends. + * + * NOTE: This function should never be called from application code and, + * as a general rule unless you really know what you are doing, this + * function should not be called directly from operation system code either: + * Typically, the wrapper functions, enter_critical_section() and + * leave_critical section(), are probably what you really want. + */ + +/* Save the current interrupt enable state & disable IRQs. */ + +static inline irqstate_t up_irq_save(void) +{ + irqstate_t r = _IRQ_EN_REG; + _IRQ_EN_REG = 0; + return r; +} + +/* Restore saved IRQ & FIQ state */ + +static inline void up_irq_restore(irqstate_t flags) +{ + _IRQ_EN_REG = flags; +} + +/* Enable IRQs and return the previous IRQ state */ + +static inline irqstate_t up_irq_enable(void) +{ + irqstate_t r = _IRQ_EN_REG; + _IRQ_EN_REG = 1; + return r; +} + +static inline void up_irq_disable(void) +{ + up_irq_save(); +} + +static inline void up_disable_irq(int irq) +{ + _IRQ_MASK_REG &= ~(1 << irq); +} + +static inline void up_enable_irq(int irq) +{ + _IRQ_MASK_REG |= (1 << irq); +} + +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_ARM_INCLUDE_TLSR82_IRQ_H */ diff --git a/arch/arm/src/tlsr82/Kconfig b/arch/arm/src/tlsr82/Kconfig new file mode 100644 index 0000000000000..eb9c0e2f7c153 --- /dev/null +++ b/arch/arm/src/tlsr82/Kconfig @@ -0,0 +1,344 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_CHIP_TLSR82 + +comment "TLSR82XX Configuration Options" + +choice + prompt "TLSR82XX Chip Selection" + default ARCH_CHIP_TLSR8278 + depends on ARCH_CHIP_TLSR82 + +config ARCH_CHIP_TLSR8278 + bool "TELINK_TLSR8278" + select TLSR82_FLASH_512K + select TLSR82_SRAM_64K + ---help--- + Multi-mode, Bluetooth LE5.1, AoA/AoD QFN 7x7, 48 pins, + 512KB FLASH, 64KB SRAM + +endchoice # TLSR82XX Chip Selection + +config TLSR82_FLASH_1M + bool + default n + +config TLSR82_FLASH_512K + bool + default n + +config TLSR82_SRAM_64K + bool + default n + +config TLSR82_SRAM_32K + bool + default n + +config TLSR82_FLASH_SIZE_KB + int + default 1024 if TLSR82_FLASH_1M + default 512 if TLSR82_FLASH_512K + +config TLSR82_SRAM_SIZE_KB + int + default 64 if TLSR82_SRAM_64K + default 32 if TLSR82_SRAM_32K + +config TLSR82_CPU_CLK_MHZ + int "TLSR82_CPU_CLK (Mhz)" + default 48 + +config TLSR82_BOOTLOADER + bool "TLSR82_BOOTLOADER" + default n + ---help--- + Configure and position code for use with the telink bootloader. + Do not select this option if you will load code using JTAG/SWM. + +config TLSR82_SOFT_FPU + bool "TLSR82 Software Fpu Enable" + default n + ---help--- + Enable software fpu support for tlsr82. + +config TLSR82_SOFT_FPU_LIB_NAME + string "TLSR82 Software Fpu Library Name" + default "soft-fp" + depends on TLSR82_SOFT_FPU + ---help--- + This is the software fpu library name. + +config TLSR82_SOFT_FPU_LIB_PATH + string "TLSR82 Software Fpu Library Path" + default "arch/arm/src/tlsr82/common" + depends on TLSR82_SOFT_FPU + ---help--- + This is the software fpu library path. + +config TLSR8278_BLE_SDK + bool "TLSR8278 Bluetooth SDK Enable" + default n + depends on ARCH_CHIP_TLSR8278 + ---help--- + Enable the Bluetooth SDK Code of tlsr8278. + +config TLSR8278_BLE_SDK_LIB_NAME + string "TLSR8278 Bluetooth SDK Library Name" + default "lt_8278" + depends on TLSR8278_BLE_SDK + ---help--- + This is the library name needed by bluetooth sdk. + +config TLSR8278_BLE_SDK_LIB_PATH + string "TLSR8278 Bluetooth SDK Library Path" + default "../apps/vendor/telink/proj_lib" + depends on TLSR8278_BLE_SDK + ---help--- + This is the library path needed by bluetooth sdk. + +menu "TLSR82 Peripheral Support" + +# These are the peripheral selections proper + +# "Timer Configuration" +menuconfig TLSR82_TIMER + bool "Timer Configuration" + default n + +if TLSR82_TIMER + +config TLSR82_TIMER1 + bool "Tlsr82 Timer1" + default n + +config TLSR82_TIMER2 + bool "Tlsr82 Timer2" + default n + depends on !TLSR82_WATCHDOG + +config TLSR82_WATCHDOG + bool "Tlsr82 WatchDoag" + default n + +config TLSR82_WDOG_DEFTIMOUT + int "Tlsr82 Watchdog deafult timeout time (ms)" + default 5000 + depends on TLSR82_WATCHDOG + ---help--- + This value is the default watchdog timeout time. + +endif + +# "Uart Configuration" +menuconfig TLSR82_UART + bool "Uart Configuration" + default n + +if TLSR82_UART + +config TLSR82_UART0 + bool "Tlsr82 Uart0" + default n + +config TLSR82_UART0_TX_BUF_SIZE + int "Tlsr82 Uart0 Tx Buffer Size" + default 240 + depends on TLSR82_UART0 + ---help--- + The Uart0 transmit buffer size. + +config TLSR82_UART0_RX_BUF_SIZE + int "Tlsr82 Uart0 Rx Buffer Size" + default 240 + depends on TLSR82_UART0 + ---help--- + The Uart0 receive buffer size. + +config TLSR82_UART0_RXDMA + bool "Tlsr82 Uart0 RxDma Enable" + default n + depends on TLSR82_UART0 + select SERIAL_RXDMA + +config TLSR82_UART0_RXDMA_BUF_SIZE + int "Tlsr82 Uart0 RxDma Buffer Size" + default 240 + range 16 240 + depends on TLSR82_UART0_RXDMA + ---help--- + This value is the uart0 rx dma buffer size, this size must be less + than 240 and be multiple of 16. + +config TLSR82_UART0_TXDMA + bool "Tlsr82 Uart0 TxDma Enable" + default n + depends on TLSR82_UART0 + select SERIAL_TXDMA + +config TLSR82_UART0_TXDMA_BUF_SIZE + int "Tlsr82 Uart0 TxDma Buffer Size" + default 240 + range 16 240 + depends on TLSR82_UART0_TXDMA + ---help--- + This value is the uart0 tx dma buffer size, this size must be less + than 240 and be multiple of 16. + +endif + +menuconfig TLSR82_GPIO + bool "GPIO Configuration" + default n + +if TLSR82_GPIO + +config TLSR82_GPIO_IRQ + bool "Tlsr82 gpio interrupt enable" + default n + +config TLSR82_GPIO_VALIDATION + bool "Tlsr82 gpio validation enable" + default n + ---help--- + If enable this config, when config the gpio as multiplex function, + function tlsr82_gpio_cfg_check() can be used to check whether the + gpio can be configured be this multiplex function. But this function + need more flash space. + +endif + +menuconfig TLSR82_I2C + bool "I2C Configuration" + default n + +# "SPI Configuration" +menuconfig TLSR82_SPI + bool "SPI Configuration" + default n + +if TLSR82_SPI + +config TLSR82_SPI_CONSOLE + bool "TLSR82 SPI as console output" + default n + ---help--- + This configuration will enable the spi as the console output + (printf), input function is not implemented in current code. + This is a useful debug option, beacause some tc32 archtecture chips + only have one uart, another debug log output channel is needed + when the only uart is used for doing other things. + +config TLSR82_SPI_SYSLOG + bool "TLSR82 SPI as syslog output" + default n + ---help--- + This configuration will enable the spi as the syslog output + channel (syslog). This is a useful debug option, beacause some tc32 + archtecture chips only have one uart, another debug log output + channel is needed when the only uart is used for doing other things. + +endif + +menuconfig TLSR82_USB + bool "USB Configuration" + default n + +menuconfig TLSR82_PWM + bool "PWM Configuration" + default n + +menuconfig TLSR82_AUDIO + bool "AUDIO Configuration" + default n + +menuconfig TLSR82_QEDC + bool "QEDE Configuration" + default n + +menuconfig TLSR82_MEDC + bool "MEDC Configuration" + default n + +menuconfig TLSR82_ADC + bool "ADC Configuration" + default n + +menuconfig TLSR82_LPCOMP + bool "LPCOMP Configuration" + default n + +menuconfig TLSR82_PKE + bool "PKE Configuration" + default n + +menuconfig TLSR82_AES + bool "AES Configuration" + default n + +menuconfig TLSR82_RNG + bool "RNG Configuration" + default n + +menuconfig TLSR82_PTA + bool "PTA Configuration" + default n + +menuconfig TLSR82_FLASH + bool "FLASH Configuration" + default n + depends on MTD + select MTD_BYTE_WRITE + +if TLSR82_FLASH + + config TLSR82_FLASH_FS_OFFSET + hex "Start address of flash used by the file system" + default 0x00060000 + ---help--- + This value is the start address of flash used by the file system, + therefore, this value must be larger than the end of code address. + + config TLSR82_FLASH_FS_SIZE + hex "Size of flash used by the file system" + default 0x20000 + ---help--- + This value is the size of flash used by the file system, therefore, + TLSR82_FLASH_FS_SIZE + TLSR82_FLASH_FS_OFFSET must less than the + boundary address of flash. + + config TLSR82_FLASH_WRITE_BUFFER + bool "Enable the flash byte write buffer" + default n + depends on MTD_BYTE_WRITE + ---help--- + When enable this config, the flash byte write opreation will write the + data to a middle buffer and then write the flash using this buffer to + avoid the data buffer passed by apps is at flash. The flash not support + read during writing. + + config TLSR82_FLASH_WRITE_BUFFER_SIZE + int "Flash byte write buffer size" + default 40 + range 16 256 + depends on TLSR82_FLASH_WRITE_BUFFER + ---help--- + Flash byte write buffer size, the larger this size, the higher byte write + efficiency. + + config TLSR82_FLASH_TEST + bool "Enable the falsh test when initializing" + default n + ---help--- + When enable this config, the flash test function will execute when + the flash initializing. This config is useful to debug the flash + problem. + +endif + +endmenu # "TLSR82 Peripheral Support" + +endif # ARCH_CHIP_TLSR82 diff --git a/arch/arm/src/tlsr82/Make.defs b/arch/arm/src/tlsr82/Make.defs new file mode 100644 index 0000000000000..57cca35b8cd49 --- /dev/null +++ b/arch/arm/src/tlsr82/Make.defs @@ -0,0 +1,62 @@ +############################################################################ +# arch/tc32/src/tlsr82/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include tlsr82/tc32/Make.defs + +# Chip devices related files in arch/arm/src/tlsr82 + +CHIP_CSRCS += tlsr82_start.c tlsr82_irq.c tlsr82_gpio.c tlsr82_timer_isr.c +CHIP_CSRCS += tlsr82_serial.c tlsr82_gpio_cfg.c tlsr82_analog.c +CHIP_CSRCS += tlsr82_clock.c tlsr82_cpu.c tlsr82_flash.c tlsr82_flash_mtd.c + +ifeq ($(CONFIG_TLSR82_SPI),y) + CHIP_CSRCS += tlsr82_spi_console.c +endif + +ifeq ($(CONFIG_TLSR82_TIMER),y) + CHIP_CSRCS += tlsr82_timer.c tlsr82_timer_lowerhalf.c + ifeq ($(CONFIG_TLSR82_WATCHDOG), y) + CHIP_CSRCS += tlsr82_watchdog.c + endif +endif + +ifeq ($(CONFIG_TLSR82_PWM),y) + CHIP_CSRCS += tlsr82_pwm.c +endif + +ifeq ($(CONFIG_TLSR82_ADC),y) + CHIP_CSRCS += tlsr82_adc.c +endif + +VPATH += chip/tc32 +VPATH += chip/chip/b87/boot + +CFLAGS += -I$(TOPDIR)/arch/arm/src/arm +CFLAGS += -I$(TOPDIR)/arch/arm/src/tlsr82/tc32 + +ifeq ($(CONFIG_TLSR8278_BLE_SDK),y) + EXTRA_LIBPATHS += -L$(TOPDIR)/$(CONFIG_TLSR8278_BLE_SDK_LIB_PATH) + EXTRA_LIBS += -l$(CONFIG_TLSR8278_BLE_SDK_LIB_NAME) +endif + +ifeq ($(CONFIG_TLSR82_SOFT_FPU),y) + EXTRA_LIBPATHS += -L$(TOPDIR)/$(CONFIG_TLSR82_SOFT_FPU_LIB_PATH) + EXTRA_LIBS += -l$(CONFIG_TLSR82_SOFT_FPU_LIB_NAME) +endif diff --git a/arch/arm/src/tlsr82/Toolchain.defs b/arch/arm/src/tlsr82/Toolchain.defs new file mode 100644 index 0000000000000..b0172f908fdc5 --- /dev/null +++ b/arch/arm/src/tlsr82/Toolchain.defs @@ -0,0 +1,191 @@ +############################################################################ +# arch/arm/src/tlsr82/Toolchain.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +# Setup for the selected toolchain + +# +# Handle old-style chip-specific toolchain names in the absence of +# a new-style toolchain specification, force the selection of a single +# toolchain and allow the selected toolchain to be overridden by a +# command-line selection. +# + +ifeq ($(filter y, $(CONFIG_ARMV6M_TOOLCHAIN_BUILDROOT)),y) + CONFIG_ARMV6M_TOOLCHAIN ?= BUILDROOT +endif + +ifeq ($(filter y, $(CONFIG_ARMV6M_TOOLCHAIN_GNU_EABI)),y) + CONFIG_ARMV6M_TOOLCHAIN ?= GNU_EABI +endif + +ifeq ($(filter y, $(CONFIG_ARMV6M_TOOLCHAIN_CLANG)),y) + CONFIG_ARMV6M_TOOLCHAIN ?= CLANG +endif + +# +# Supported toolchains +# +# Each toolchain definition should set: +# +# CROSSDEV The GNU toolchain triple (command prefix) +# ARCHCPUFLAGS CPU-specific flags selecting the instruction set +# options, etc. +# ARCHOPTIMIZATION The maximum optimization level that results in +# reliable code generation. +# + +ifeq ($(CONFIG_DEBUG_CUSTOMOPT),y) + ARCHOPTIMIZATION := $(CONFIG_DEBUG_OPTLEVEL) +else ifeq ($(CONFIG_DEBUG_FULLOPT),y) + ifeq ($(CONFIG_ARMV6M_TOOLCHAIN),CLANG) + ARCHOPTIMIZATION ?= -Oz + else + ARCHOPTIMIZATION ?= -Os + endif +endif + +ifneq ($(CONFIG_DEBUG_NOOPT),y) + ARCHOPTIMIZATION += -fno-strict-aliasing +endif + +ifeq ($(CONFIG_FRAME_POINTER),y) + ARCHOPTIMIZATION += -fno-omit-frame-pointer -fno-optimize-sibling-calls +else + ARCHOPTIMIZATION += -fomit-frame-pointer +endif + +# Clang Configuration files + +ifeq ($(CONFIG_ARMV6M_TOOLCHAIN),CLANG) + TOOLCHAIN_MARCH := --config armv6m_soft_nofp_nosys +endif + +# Link Time Optimization + +ifeq ($(CONFIG_LTO_THIN),y) + ARCHOPTIMIZATION += -flto=thin +else ifeq ($(CONFIG_LTO_FULL),y) + ARCHOPTIMIZATION += -flto +endif + +# NuttX buildroot under Linux or Cygwin + +ifeq ($(CONFIG_ARMV6M_TOOLCHAIN),BUILDROOT) + CROSSDEV ?= arm-nuttx-eabi- + ARCHCPUFLAGS = $(TOOLCHAIN_MARCH) $(TOOLCHAIN_MTUNE) $(TOOLCHAIN_MFLOAT) +endif + +# Generic GNU EABI toolchain + +ifeq ($(CONFIG_ARMV6M_TOOLCHAIN),GNU_EABI) + CROSSDEV ?= tc32-elf- + ARCHCPUFLAGS = $(TOOLCHAIN_MARCH) $(TOOLCHAIN_MTUNE) $(TOOLCHAIN_MFLOAT) +endif + +# Clang toolchain + +ifeq ($(CONFIG_ARMV6M_TOOLCHAIN),CLANG) + ARCHCPUFLAGS = $(TOOLCHAIN_MARCH) $(TOOLCHAIN_MTUNE) $(TOOLCHAIN_MFLOAT) + + CC = clang + CXX = clang++ + CPP = clang -E -P -x c + LD = ld.lld -m armelf + STRIP = llvm-strip --strip-unneeded + AR = llvm-ar rcs + NM = llvm-nm + OBJCOPY = llvm-objcopy + OBJDUMP = llvm-objdump + + # Since the no_builtin attribute is not fully supported on Clang + # disable the built-in functions, refer: + # https://github.com/apache/incubator-nuttx/pull/5971 + + MAXOPTIMIZATION += -fno-builtin + +# Default toolchain + +else + CC = $(CROSSDEV)gcc + CXX = $(CROSSDEV)g++ + CPP = $(CROSSDEV)gcc -E -P -x c + LD = $(CROSSDEV)ld + STRIP = $(CROSSDEV)strip --strip-unneeded + AR = $(CROSSDEV)ar rcs + NM = $(CROSSDEV)nm + OBJCOPY = $(CROSSDEV)objcopy + OBJDUMP = $(CROSSDEV)objdump +endif + +# Architecture flags + +ifeq ($(CONFIG_MM_KASAN),y) + ARCHCPUFLAGS += -fsanitize=kernel-address +endif + +ARCHCFLAGS += -fno-common +ARCHCXXFLAGS += -fno-common + +ifneq ($(CONFIG_CXX_EXCEPTION),y) + ARCHCXXFLAGS += -fno-exceptions -fcheck-new +endif + +ifneq ($(CONFIG_CXX_RTTI),y) + ARCHCXXFLAGS += -fno-rtti +endif + +# Optimization of unused sections + +ifeq ($(CONFIG_DEBUG_OPT_UNUSED_SECTIONS),y) + LDFLAGS += --gc-sections + ARCHOPTIMIZATION += -ffunction-sections -fdata-sections +endif + +# Debug link map + +ifeq ($(CONFIG_DEBUG_LINK_MAP),y) + LDFLAGS += --cref -Map=$(call CONVERT_PATH,$(TOPDIR)$(DELIM)nuttx.map) +endif + +# Debuf link symbols + +ifeq ($(CONFIG_DEBUG_SYMBOLS),y) + LDFLAGS += -g + ARCHOPTIMIZATION += -g +endif + +# Add the builtin library + +COMPILER_RT_LIB = $(shell $(CC) $(ARCHCPUFLAGS) --print-libgcc-file-name) +ifeq ($(wildcard $(COMPILER_RT_LIB)),) + # if "--print-libgcc-file-name" unable to find the correct libgcc PATH + # then go ahead and try "--print-file-name" + COMPILER_RT_LIB := $(wildcard $(shell $(CC) $(ARCHCPUFLAGS) --print-file-name $(notdir $(COMPILER_RT_LIB)))) +endif + +EXTRA_LIBS += $(COMPILER_RT_LIB) + +ifneq ($(CONFIG_LIBM),y) + EXTRA_LIBS += $(wildcard $(shell $(CC) $(ARCHCPUFLAGS) --print-file-name=libm.a)) +endif + +ifeq ($(CONFIG_LIBSUPCXX),y) + EXTRA_LIBS += $(wildcard $(shell $(CC) $(ARCHCPUFLAGS) --print-file-name=libsupc++.a)) +endif diff --git a/arch/arm/src/tlsr82/chip.h b/arch/arm/src/tlsr82/chip.h new file mode 100644 index 0000000000000..dfc81861bde5b --- /dev/null +++ b/arch/arm/src/tlsr82/chip.h @@ -0,0 +1,41 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/chip.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_CHIP_H +#define __ARCH_ARM_SRC_TLSR82_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/* Include the chip capabilities file */ + +#define ARMV6M_PERIPHERAL_INTERRUPTS NR_IRQS + +/* Include the memory map file. + * Other chip hardware files should then include this file for the proper + * setup. + */ + +#endif /* __ARCH_ARM_SRC_TLSR82_CHIP_H */ diff --git a/arch/arm/src/tlsr82/chip/b87/boot/cstartup_flash.S b/arch/arm/src/tlsr82/chip/b87/boot/cstartup_flash.S new file mode 100644 index 0000000000000..8482b78245006 --- /dev/null +++ b/arch/arm/src/tlsr82/chip/b87/boot/cstartup_flash.S @@ -0,0 +1,567 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/chip/b87/boot/cstartup_flash.S + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#include +#include + +#define SRAM_SIZE_32K_EN 0/*defaut sram size=64k*/ + +#define FLL_STK_EN 1 +#define ZERO_IC_TAG_EN 1 +#define IC_TAG_CACEH_ADDR_EQU_EN 0 +#define FLASH_WAKEUP_EN 1 +#define COPY_DATA_EN 1 +#define MULTI_ADDRESS_START 1 +#define MOVE_BIN_CODE_EN 0 + +#ifndef __LOAD_RAM_SIZE__ +#define __LOAD_RAM_SIZE__ 0xc +#endif + +#ifndef __IRQ_STK_SIZE__ +#define __IRQ_STK_SIZE__ CONFIG_ARCH_INTERRUPTSTACK +#if CONFIG_ARCH_INTERRUPTSTACK <= 128 +# error "Interrupt Stack must be larger than 128" +#endif +#endif + .code 16 +@******************************************************************************************************** +@ MACROS AND DEFINIITIONS +@******************************************************************************************************** + + @ Mode, correspords to bits 0-5 in CPSR + .equ MODE_BITS, 0x1F @ Bit mask for mode bits in CPSR + .equ IRQ_MODE, 0x12 @ Interrupt Request mode + .equ SVC_MODE, 0x13 @ Supervisor mode + .equ IRQ_STK_SIZE, __IRQ_STK_SIZE__ + .equ __LOAD_FLASH, 1 + .equ __LOAD_DUT, 0 + .equ __LOAD_RAM, 0 +@******************************************************************************************************** +@ TC32 EXCEPTION VECTORS +@******************************************************************************************************** + + .section .vectors,"ax" + .global __reset + .global __irq + .global __start + .global __LOAD_RAM + .global __LOAD_DUT + .global __LOAD_FLASH + + .extern g_current_regs + +__start: @ MUST, referenced by boot.link + + .extern irq_handler + + .extern firmwareVersion + + .extern _ramcode_size_div_16_ + .extern _ramcode_size_div_256_ + .extern _ramcode_size_div_16_align_256_ + .extern _ramcode_size_align_256_ + .extern _ictag_start_ + .extern _ictag_end_ + .extern tl_multi_addr_L + .extern tl_multi_addr_H + .org 0x0 + tj __reset +@ .word (firmwareVersion) + .org 0x8 + .word (0x544c4e4b) +#if MOVE_BIN_CODE_EN + .word (0x00880000 + _bin_size_div_16) +#else + .word (0x00880000 + _ramcode_size_div_16_align_256_) +#endif + + .org 0x10 + tj __irq + .org 0x18 + .word (_bin_size_) + .extern __tc32_start + + .org 0x20 + +__reset: + +#if 0 + @ add debug, PB4 output 1 + tloadr r1, DEBUG_GPIO @0x80058a PB oen + tmov r0, #139 @0b 11101111 + tstorerb r0, [r1, #0] + + tmov r0, #16 @0b 00010000 + tstorerb r0, [r1, #1] @0x800583 PB output +#endif + +#if FLASH_WAKEUP_EN + +FLASH_WAKEUP_BEGIN: + tloadr r0,DATA_I+44 + tmov r1,#0 + tstorerb r1,[r0,#1] + tmov r1,#171 @Flash deep cmd: 0xAB + tstorerb r1,[r0,#0] + tmov r2,#0 + tmov r3,#6 +TNOP: + tadd r2,#1 + tcmp r2,r3 + tjle TNOP + tmov r1,#1 + tstorerb r1,[r0,#1] +FLASH_WAKEUP_END: + +#endif + +@ efuse load need delay about 18us + tmov r2,#0 + tmov r3,#110 +EFUSE_DELAY: + tadd r2,#1 + tcmp r2,r3 + tjle EFUSE_DELAY +EFUSE_DELAY_END: + +@******************************************************************************************************** +@ FILL .DATA AND .BSS WITH 0xFF +@******************************************************************************************************** +#if FLL_STK_EN + + @ tloadr r0, FLL_D @r0 = 0xffffffff + tmov r0, #0 @r0 = 0xffffffff + tloadr r1, FLL_D+4 @r1 = _start_data_ + tloadr r2, FLL_D+8 @r2 = 0x850000 + +FLL_STK: + tcmp r1, r2 @ + tjge FLL_STK_END @r1>=r2 jump to FLL_STK_END + tstorer r0, [r1, #0] @*(unsigned int*)(_start_data_)=0xffffffff + tadd r1, #4 @r1 = r1+4 + tj FLL_STK @jump to FLL_STK +FLL_STK_END: + +#endif +@******************************************************************************************************** +@ UPDATE SP UNDER IRQ/SVC MODE +@******************************************************************************************************** + tloadr r0, DAT0 @r0 = 0x12 IRQ + tmcsr r0 @CPSR=r0 + tloadr r0, DAT0 + 8 @r0 = g_intstacktop + tmov r13, r0 @r13/SP= r0 update SP under IRQ mode + + tloadr r0, DAT0 + 4 @r0 = 0x13 SVC + tmcsr r0 @CPSR=r0 + tloadr r0, IDLE_STACK @r0 = _ebss + CONFIG_IDLETHREAD_STACKSIZE + tmov r13, r0 @r13= r0 update SP under SVC mode +@******************************************************************************************************** +@ .BSS INITIALIZATION FOR 0 +@******************************************************************************************************** + tmov r0, #0 @r0 = 0 + tloadr r1, DAT0 + 16 @r1 = _sbss + tloadr r2, DAT0 + 20 @r2 = _ebss + +ZERO_BSS_BEGIN: + tcmp r1, r2 + tjge ZERO_BSS_END @r1>=r2 jump to ZERO_BSS_END + tstorer r0, [r1, #0] @*(unsigned int*)(_sbss)=r0=0 + tadd r1, #4 @r1 = r1 + 4 + tj ZERO_BSS_BEGIN @jump to ZERO_BSS_BEGIN +ZERO_BSS_END: +@******************************************************************************************************** +@ IC TAG INITIALIZATION +@******************************************************************************************************** +#if ZERO_IC_TAG_EN +ZERO_TAG: + tmov r0, #0 + tloadr r1, DAT0 + 28 @r1 = _ictag_start_ + tloadr r2, DAT0 + 32 @r2 = _ictag_end_ +ZERO_TAG_BEGIN: + tcmp r1, r2 + tjge ZERO_TAG_END @r1>=r2 jump to ZERO_TAG_END + tstorer r0, [r1, #0] @*(unsigned int*)(_ictag_start_)=r0=0 + tadd r1, #4 @r1 = r1 + 4 + tj ZERO_TAG_BEGIN @jump to ZERO_TAG_BEGIN +ZERO_TAG_END: +#endif +@******************************************************************************************************** +@ IC CACHE INITIALIZATION +@******************************************************************************************************** + +SET_IC: + tloadr r1, DAT0 + 24 @ r1 = 0x80060c + tloadr r0, DAT0 + 36 @ r0 = _ramcode_size_align_256_ + tshftr r0,r0,#8 @ r0 = _ramcode_size_align_256_/256 + tstorerb r0, [r1, #0] @ *(unsigned int*)(0x80060c) = r0 +#if IC_TAG_CACHE_ADDR_EQU_EN + +#else + tadd r0, #1 @ r0 = r0 + 1 +#endif + tstorerb r0, [r1, #1] @ *(unsigned int*)(0x80060d) = r0 +SET_IC_END: +@******************************************************************************************************** +@ DCDC INITIALIZATION FOR FLASH +@******************************************************************************************************** + /*system on*/ + tloadr r0,DATA_I+32 @0x00800060 + tloadr r1,DATA_I+36 @0xff000000 + tstorer r1,[r0,#0] @*(unsigned int*)0x800060=0xff000000 + tshftr r1,r1,#24 @0x000000ff + tstorerb r1,[r0,#4] @dig_0x64=0xff + tloadr r1,DATA_I+40 @dig_0x65=0xf7 + tstorerb r1,[r0,#5] + + + /*check ana_reg_0x7e*/ + tloadr r0,DATA_I+24 @0x7e + +RANA_REG_BEGIN: + tloadr r1,DATA_I+28 @0x008000b8 + tmov r2,r0 @ana_reg_adr:0x7e + tstorerb r2,[r1,#0] @*(unsigned int*)0x8000b8=0x7e; + tmov r2,#64 @ana_reg_dat:0x40=64 + tstorerb r2,[r1,#2] @*(unsigned int*)0x8000ba=0x40; + +RWAIT_REG_FINISH: + tloadrb r2,[r1,#2] + tshftl r2,r2,#31 + tshftr r2,r2,#31 + tcmp r2,#1 + tjeq RWAIT_REG_FINISH + tloadrb r2,[r1,#1] +RANA_REG_END: + + tshftl r2,r2,#31 + tshftr r2,r2,#31 + tcmp r2,#0 + /*if ana_reg_0x7e==0x00 retention data initiate after waking up from deep*/ +#if MULTI_ADDRESS_START + tjeq MULTI_ADDRESS_END +MULTI_ADDRESS_BEGIN: + tloadr r0, MULTI_ADDRESS_DATA + tloadr r1, MULTI_ADDRESS_DATA+4 + tloadr r3, MULTI_ADDRESS_DATA+8 + tloadrb r2, [r1,#0] + tstorerb r2, [r0,#0] + tloadrb r2, [r3,#0] + tstorerb r2, [r0,#1] +#if COPY_DATA_EN + tj COPY_DATA @deep wakeup with retention +#else + tj COPY_DATA_END +#endif +MULTI_ADDRESS_END: +#endif + + +@******************************************************************************************************** +@ RETENTION DATA INITIALIZATION +@******************************************************************************************************** +COPY_RET_DATA: + tloadr r1, DATA_I @ r1 = _rstored_ + tloadr r2, DATA_I+4 @ r2 = _retention_data_start_ + tloadr r3, DATA_I+8 @ r3 = _retention_data_end_ +COPY_RET_DATA_BEGIN: + tcmp r2, r3 @ + tjge COPY_RET_DATA_END @ r2>=r3 jump to COPY_RET_DATA_END + tloadr r0, [r1, #0] @ r0 = *(unsigned int*)(_rstored_) + tstorer r0, [r2, #0] @ *(unsigned int*)(_retention_data_start_) = r0 + tadd r1, #4 @ r1 = r1 + 4 + tadd r2, #4 @ r2 = r2 + 4 + tj COPY_RET_DATA_BEGIN @ jump to COPY_RET_DATA_BEGIN +COPY_RET_DATA_END: + + +@******************************************************************************************************** +@ DATA INITIALIZATION +@******************************************************************************************************** +COPY_DATA: + tloadr r1, DATA_I+12 @ r1 = _dstored_ + tloadr r2, DATA_I+16 @ r2 = _start_data_ + tloadr r3, DATA_I+20 @ r3 = _end_data_ +COPY_DATA_BEGIN: + tcmp r2, r3 @ + tjge COPY_DATA_END @ r2>=r3 jump to COPY_DATA_END + tloadr r0, [r1, #0] @ r0 = *(unsigned int*)(_dstored_) + tstorer r0, [r2, #0] @ *(unsigned int*)(_start_data_) = r0 + tadd r1, #4 @ r1 = r1 + 4 + tadd r2, #4 @ r2 = r2 + 4 + tj COPY_DATA_BEGIN @ jump to COPY_DATA_BEGIN +COPY_DATA_END: + + + +#if 0 +SETSPISPEED: + tloadr r1, DAT0 + 36 + tmov r0, #0xbb @0x0b for fast read; 0xbb for dual dat/adr + tstorerb r0, [r1, #0] + tmov r0, #3 @3 for dual dat/adr + tstorerb r0, [r1, #1] +#endif + +ENTER_MAIN: + tjl __tc32_start +END: tj END + + .balign 4 +DAT0: + .word 0x12 @0 IRQ + .word 0x13 @4 SVC + .word g_intstacktop @8 interrupt stack top +#if SRAM_SIZE_32K_EN + .word (0x848000) @12 stack end +#else + .word (0x850000) @12 stack end +#endif + .word (_sbss) @16 + .word (_ebss) @20 + .word (0x80060c) @24 + .word _ictag_start_ @28 IC tag start + .word _ictag_end_ @32 IC tag end +#if IC_TAG_CACHE_ADDR_EQU_EN + .word (0x00f000) @36 +#endif + .word _ramcode_size_align_256_ @40 + +DATA_I: + .word (_rstored_) @0 + .word (_retention_data_start_) @4 + .word (_retention_data_end_) @8 + .word _dstored_ @12 + .word _start_data_ @16 + .word _end_data_ @20 + .word (0x0000007e) @24 + .word (0x008000b8) @28 + .word (0x00800060) @32 + .word (0xff080000) @36 + .word (0x000000f7) @40 + .word (0x0080000c) @44 + +DEBUG_GPIO: + .word (0x80058a) @ PBx oen + +FLL_D: + .word 0xffffffff @0 + .word (_start_data_) @4 +#if SRAM_SIZE_32K_EN + .word (0x848000) @8 +#else + .word (0x850000) @8 +#endif + .word _ramcode_size_div_256_ @12 + +MULTI_ADDRESS_DATA: + .word (0x0080063e) @0 + .word tl_multi_addr_L @4 + .word tl_multi_addr_H @8 + +IDLE_STACK: + .word (_ebss + CONFIG_IDLETHREAD_STACKSIZE) + + .align 4 +@ src code for the irq proc part . + +__irq: + /* Save R0 ~ R3, these registers will be used */ + + tpush {r0} + tpush {r1} + tpush {r2} + tpush {r3} + + /* Switch to SVC mode to get the SVC mode SP, then save context + * into the interrupted task stack. + */ + + /* Disable interrupt, because cpu will switch into SVC mode, interrupt + * nested should be prevented, this is not supported by tc32 + * architecture. + */ + + tloadr r0, _REG_IRQ_EN @ disable irq + tloadrb r1, [r0] @ get irq state in R1 + tmov r2, #0 @ disable irq + tstorerb r2, [r0] @ disable irq + + /* Switch to SVC mode and get the LR and SP in SVC mode */ + + tloadr r0, _REG_IRQ_EN + 4 @ switch to SVC mode + tnop + tmcsr r0 @ switch to SVC mode + tnop + tmov r2, r14 @ get SVC mode LR in R2 + tmov r3, r13 @ get SVC mode SP in R3 + tloadr r0, _REG_IRQ_EN + 8 @ return to IRQ mode + tnop + tmcsr r0 @ return to IRQ mode + tnop + + /* R0 = the interrupted task SP after context save */ + + tmov r0, #XCPTCONTEXT_SIZE + tsub r0, r3, r0 + + /* Save IRQ_STATE, SVC mode SP and SVC mode LR as PC */ + + tstorer r1, [r0, #(4 * REG_IRQ_EN)] + tstorer r3, [r0, #(4 * REG_SP)] + tstorer r2, [r0, #(4 * REG_PC)] + + /* Get SPSR and save as CPSR */ + + tmrss r1 + tstorer r1, [r0, #(4 * REG_CPSR)] + + /* Save IRQ mode LR as LR */ + + tmov r1, r14 + tstorer r1, [r0, #(4 * REG_LR)] + + /* Pop the saved R1 ~ R3 (pushed in beginning of irq), + * then save R1 ~ R7. + */ + + tpop {r3} + tpop {r2} + tpop {r1} + tstorer r1, [r0, #(4 * REG_R1)] + tstorer r2, [r0, #(4 * REG_R2)] + tstorer r3, [r0, #(4 * REG_R3)] + tstorer r4, [r0, #(4 * REG_R4)] + tstorer r5, [r0, #(4 * REG_R5)] + tstorer r6, [r0, #(4 * REG_R6)] + tstorer r7, [r0, #(4 * REG_R7)] + + /* Pop R0 and save it */ + + tpop {r1} + tstorer r1, [r0, #(4 * REG_R0)] + + /* Save R8 ~ R12 */ + + tmov r1, r8 + tstorer r1, [r0, #(4 * REG_R8)] + tmov r1, r9 + tstorer r1, [r0, #(4 * REG_R9)] + tmov r1, r10 + tstorer r1, [r0, #(4 * REG_R10)] + tmov r1, r11 + tstorer r1, [r0, #(4 * REG_R11)] + tmov r1, r12 + tstorer r1, [r0, #(4 * REG_R12)] + + /* R0 = interrupted task SP after the context save */ + + tjl irq_handler + + /* R0 = interrupted task SP after the context save (no context switch) + * = next task tcb->regs (with context switch) + * Restore all the register according to R0 + */ + + /* Dsiable interrupt to protect the SVC mode */ + + tloadr r2, _REG_IRQ_EN @ disable irq + tmov r3, #0 @ disable irq + tstorerb r3, [r2] @ disable irq + + /* Restore SVC mode SP (R13), SVC mode LR (R14, based saved PC) + * PC is not need to retore */ + + tloadr r2, [r0, #(4 * REG_SP)] + tloadr r3, [r0, #(4 * REG_PC)] + + tloadr r1, _REG_IRQ_EN + 4 @ switch to SVC mode + tnop + tmcsr r1 @ switch to SVC mode + tnop + tmov r14, r3 @ restore SVC mode LR + tmov r13, r2 @ restore SVC mode SP + tloadr r1, _REG_IRQ_EN + 8 @ return to IRQ mode + tnop + tmcsr r1 @ return to IRQ mode + tnop + + /* Restore CPSR to SPSR, IRQ_STATE */ + + tloadr r2, [r0, #(4 * REG_CPSR)] + tloadr r3, [r0, #(4 * REG_IRQ_EN)] + + tmssr r2 @ restore CPSR to SPSR + + tloadr r1, _REG_IRQ_EN @ restore IRQ enable flag + tstorerb r3, [r1] @ restore IRQ enable flag + + /* Restore R8 ~ R12, IRQ mode LR */ + + tloadr r2, [r0, #(4 * REG_R8)] + tloadr r3, [r0, #(4 * REG_R9)] + tloadr r4, [r0, #(4 * REG_R10)] + tloadr r5, [r0, #(4 * REG_R11)] + tloadr r6, [r0, #(4 * REG_R12)] + tloadr r7, [r0, #(4 * REG_LR)] + + tmov r8, r2 + tmov r9, r3 + tmov r10, r4 + tmov r11, r5 + tmov r12, r6 + tmov r14, r7 + + /* Restore R1 ~ R7 */ + + tloadr r1, [r0, #(4 * REG_R1)] + tloadr r2, [r0, #(4 * REG_R2)] + tloadr r3, [r0, #(4 * REG_R3)] + tloadr r4, [r0, #(4 * REG_R4)] + tloadr r5, [r0, #(4 * REG_R5)] + tloadr r6, [r0, #(4 * REG_R6)] + tloadr r7, [r0, #(4 * REG_R7)] + + /* Restore R0 */ + + tloadr r0, [r0, #(4 * REG_R0)] + + /* Return to interrupted task or next task */ + + tpush {r14} + treti {r15} + + .align 4 +_REG_IRQ_EN: + .word 0x00800643 + .word 0x00000093 + .word 0x00000092 + +ASMEND: + .section .bss + .global g_intstackalloc + .global g_intstacktop + .align 4 +g_intstackalloc: + @ .lcomm irq_stk, IRQ_STK_SIZE + .skip (CONFIG_ARCH_INTERRUPTSTACK & ~3) +g_intstacktop: + .size g_intstackalloc, .-g_intstackalloc + .end diff --git a/arch/arm/src/tlsr82/hardware/tlsr82_adc.h b/arch/arm/src/tlsr82/hardware/tlsr82_adc.h new file mode 100644 index 0000000000000..c384916fda36b --- /dev/null +++ b/arch/arm/src/tlsr82/hardware/tlsr82_adc.h @@ -0,0 +1,154 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/hardware/tlsr82_adc.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_ADC_H +#define __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_ADC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "hardware/tlsr82_register.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ADC_VREF_REG (0xea) +#define ADC_CHAN_REG (0xeb) +#define ADC_MODE_REG (0xec) +#define ADC_SAMP0_REG (0xee) +#define ADC_SAMP1_REG (0xef) +#define ADC_SAMP2_REG (0xf0) +#define ADC_SAMP3_REG (0xf1) +#define ADC_CTRL0_REG (0xf2) +#define ADC_CTRL1_REG (0xf3) +#define ADC_CLKDIV_REG (0xf4) +#define ADC_STATUS_REG (0xf6) +#define ADC_DATAL_REG (0xf7) +#define ADC_DATAH_REG (0xf8) +#define ADC_DIVIDER_REG (0xf9) +#define ADC_SCALE_REG (0xfa) +#define ADC_PAG_CTRL_REG (0xfc) + +#define ADC_CLK_REG (0x82) + +/* ADC Reference Voltage definition */ + +#define ADC_VREF_SHIFT 0 +#define ADC_VREF_MASK (0x3 << ADC_VREF_SHIFT) +#define ADC_VREF_RSVD1 (0x0 << ADC_VREF_SHIFT) +#define ADC_VREF_0P9V (0x1 << ADC_VREF_SHIFT) +#define ADC_VREF_1P2V (0x2 << ADC_VREF_SHIFT) +#define ADC_VREF_RSVD2 (0x3 << ADC_VREF_SHIFT) + +/* ADC Mode, Resolution definition */ + +#define ADC_MODE_RES_SHIFT 0 +#define ADC_MODE_RES_MASK (0x3 << ADC_MODE_RES_SHIFT) +#define ADC_MODE_RES_8BIT (0x0 << ADC_MODE_RES_SHIFT) +#define ADC_MODE_RES_10BIT (0x1 << ADC_MODE_RES_SHIFT) +#define ADC_MODE_RES_12BIT (0x2 << ADC_MODE_RES_SHIFT) +#define ADC_MODE_RES_14BIT (0x3 << ADC_MODE_RES_SHIFT) + +#define ADC_MODE_INPUT_SHIFT 6 +#define ADC_MODE_INPUT_MASK (0x1 << ADC_MODE_INPUT_SHIFT) +#define ADC_MODE_INPUT_RSVD (0x0 << ADC_MODE_INPUT_SHIFT) +#define ADC_MODE_INPUT_DIFF (0x1 << ADC_MODE_INPUT_SHIFT) + +/* ADC Sample 0 defnition + * - Sample cycle + */ + +/* ADC Sample cycle definition */ + +#define ADC_SAMP0_CYCLE_SHIFT 0 +#define ADC_SAMP0_CYCLE_MASK (0xf << ADC_SAMP0_CYCLE_SHIFT) +#define ADC_SAMP0_CYCLE_3 (0x0 << ADC_SAMP0_CYCLE_SHIFT) +#define ADC_SAMP0_CYCLE_6 (0x1 << ADC_SAMP0_CYCLE_SHIFT) +#define ADC_SAMP0_CYCLE_9 (0x2 << ADC_SAMP0_CYCLE_SHIFT) +#define ADC_SAMP0_CYCLE_48 (0xf << ADC_SAMP0_CYCLE_SHIFT) + +/* ADC Control 0 definition + * - Channal enable + * - Sample length + */ + +/* ADC Channel enabel definition */ + +#define ADC_CTRL0_CHANEN_SHIFT 2 +#define ADC_CTRL0_CHANEN_MASK (0x1 << ADC_CTRL0_CHANEN_SHIFT) +#define ADC_CTRL0_CHANEN_ENABLE (0x1 << ADC_CTRL0_CHANEN_SHIFT) +#define ADC_CTRL0_CHANEN_DISABLE (0x0 << ADC_CTRL0_CHANEN_SHIFT) + +/* ADC Sample length definition */ + +#define ADC_CTRL0_SAMPLEN_SHIFT 4 +#define ADC_CTRL0_SAMPLEN_MASK (0x3 << ADC_CTRL0_SAMPLEN_SHIFT) + +/* ADC Control 1 definition + * - Adc Sample Control + */ + +#define ADC_CTRL1_SAMP_SHIFT 0 +#define ADC_CTRL1_SAMP_MASK (0x1 << ADC_CTRL1_SAMP_SHIFT) +#define ADC_CTRL1_SAMP_ON (0x0 << ADC_CTRL1_SAMP_SHIFT) +#define ADC_CTRL1_SAMP_OFF (0x1 << ADC_CTRL1_SAMP_SHIFT) + +/* ADC clock divide definition */ + +#define ADC_CLKDIV_SHIFT 0 +#define ADC_CLKDIV_MASK (0x3 << ADC_CLKDIV_SHIFT) +#define ADC_CLKDIV_0 (0x0 << ADC_CLKDIV_SHIFT) +#define ADC_CLKDIV_1 (0x1 << ADC_CLKDIV_SHIFT) +#define ADC_CLKDIV_2 (0x2 << ADC_CLKDIV_SHIFT) +#define ADC_CLKDIV_3 (0x3 << ADC_CLKDIV_SHIFT) + +/* The adc vbat divider specification can not found in datasheet, below + * definition follows the sdk code. + */ + +#define ADC_DIVIDER_SEL_SHIFT 2 +#define ADC_DIVIDER_SEL_MASK (0x3 << ADC_DIVIDER_SEL_SHIFT) +#define ADC_DIVIDER_SEL_OFF (0x0 << ADC_DIVIDER_SEL_SHIFT) +#define ADC_DIVIDER_SEL_1F3 (0x2 << ADC_DIVIDER_SEL_SHIFT) + +/* ADC input pre-scaline select */ + +#define ADC_SCALE_SHIFT 6 +#define ADC_SCALE_MASK (0x3 << ADC_SCALE_SHIFT) +#define ADC_SCALE_1 (0x0 << ADC_SCALE_SHIFT) +#define ADC_SCALE_RSVD1 (0x1 << ADC_SCALE_SHIFT) +#define ADC_SCALE_RSVD2 (0x2 << ADC_SCALE_SHIFT) +#define ADC_SCALE_1F8 (0x3 << ADC_SCALE_SHIFT) + +#define ADC_POWER_SHIFT 5 +#define ADC_POWER_MASK (0x1 << ADC_POWER_SHIFT) +#define ADC_POWER_UP (0x1 << ADC_POWER_SHIFT) +#define ADC_POWER_DOWN (0x0 << ADC_POWER_SHIFT) + +#define ADC_CLK_24M_EN_SHIFT 6 +#define ADC_CLK_24M_EN_MASK (0x1 << ADC_CLK_24M_EN_SHIFT) +#define ADC_CLK_24M_EN (0x1 << ADC_CLK_24M_EN_SHIFT) + +#endif /* __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_ADC_H */ diff --git a/arch/arm/src/tlsr82/hardware/tlsr82_analog.h b/arch/arm/src/tlsr82/hardware/tlsr82_analog.h new file mode 100644 index 0000000000000..c9faaa2182425 --- /dev/null +++ b/arch/arm/src/tlsr82/hardware/tlsr82_analog.h @@ -0,0 +1,41 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/hardware/tlsr82_analog.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_ANALOG_H +#define __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_ANALOG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "hardware/tlsr82_register.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ANALOG_ADDR_REG REG_ADDR8(0xb8) +#define ANALOG_DATA_REG REG_ADDR8(0xb9) +#define ANALOG_CTRL_REG REG_ADDR8(0xba) + +#endif /* __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_ANALOG_H */ diff --git a/arch/arm/src/tlsr82/hardware/tlsr82_clock.h b/arch/arm/src/tlsr82/hardware/tlsr82_clock.h new file mode 100644 index 0000000000000..ebd23dab40c1d --- /dev/null +++ b/arch/arm/src/tlsr82/hardware/tlsr82_clock.h @@ -0,0 +1,78 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/hardware/tlsr82_clock.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_CLOCK_H +#define __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_CLOCK_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "hardware/tlsr82_register.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define CPU_CLK (CONFIG_TLSR82_CPU_CLK_MHZ * 1000000) + +#define CLK_EN1_REG REG_ADDR8(0x63) +#define CLK_EN2_REG REG_ADDR8(0x64) +#define CLK_EN3_REG REG_ADDR8(0x65) +#define CLK_SYS_SEL REG_ADDR8(0x66) + +#define CLK_EN1_SPI BIT(0) +#define CLK_EN1_I2C BIT(1) +#define CLK_EN1_UART BIT(2) +#define CLK_EN1_USB BIT(3) +#define CLK_EN1_PWM BIT(4) +#define CLK_EN1_QDEC BIT(5) +#define CLK_EN1_IR BIT(6) +#define CLK_EN1_SWIRE BIT(7) + +#define CLK_EN2_ZB BIT(0) +#define CLK_EN2_SYSTIM BIT(1) +#define CLK_EN2_DMA BIT(2) +#define CLK_EN2_ALGM BIT(3) +#define CLK_EN2_AES BIT(4) +#define CLK_EN2_RSVD1 BIT(5) +#define CLK_EN2_RSVD2 BIT(6) +#define CLK_EN2_PKE BIT(7) + +#define CLK_EN3_AIF BIT(0) +#define CLK_EN3_AUDIO BIT(1) +#define CLK_EN3_DFIFO BIT(2) +#define CLK_EN3_TRNG BIT(3) +#define CLK_EN3_MC BIT(4) +#define CLK_EN3_MCIC BIT(5) +#define CLK_EN3_RSVD1 BIT(6) +#define CLK_EN3_RSVD2 BIT(7) + +#define CLK_SYS_12M_CRYSTAL 0x44 +#define CLK_SYS_16M_CRYSTAL 0x43 +#define CLK_SYS_24M_CRYSTAL 0x42 +#define CLK_SYS_32M_CRYSTAL 0x60 +#define CLK_SYS_48M_CRYSTAL 0x20 +#define CLK_SYS_RC_THRES 0x10 + +#endif /* __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_CLOCK_H */ diff --git a/arch/arm/src/tlsr82/hardware/tlsr82_dma.h b/arch/arm/src/tlsr82/hardware/tlsr82_dma.h new file mode 100644 index 0000000000000..1c4055b73c9ff --- /dev/null +++ b/arch/arm/src/tlsr82/hardware/tlsr82_dma.h @@ -0,0 +1,127 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/hardware/tlsr82_dma.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_DMA_H +#define __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_DMA_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "hardware/tlsr82_register.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* DMA address, size, mode resigster definitions + * By default, DMA0 is for Uart RX + * By default, DMA1 is for Uart TX + * By default, DMA2 is for RF RX + * By default, DMA3,4,5 is for RF TX + * By default, DMA7 is for PWM + */ + +#define DMA0_ADDR_REG REG_ADDR16(0xc00) +#define DMA0_ADDRHI_REG REG_ADDR8(0xc40) +#define DMA0_SIZE_REG REG_ADDR8(0xc02) +#define DMA0_MODE_REG REG_ADDR8(0xc03) +#define DMA_UART_RX_ADDR_REG DMA0_ADDR_REG +#define DMA_UART_RX_ADDRHI_REG DMA0_ADDRHI_REG +#define DMA_UART_RX_SIZE_REG DMA0_SIZE_REG +#define DMA_UART_RX_MODE_REG DMA0_MODE_REG + +#define DMA1_ADDR_REG REG_ADDR16(0xc04) +#define DMA1_ADDRHI_REG REG_ADDR8(0xc41) +#define DMA1_SIZE_REG REG_ADDR8(0xc06) +#define DMA1_MODE_REG REG_ADDR8(0xc07) +#define DMA_UART_TX_ADDR_REG DMA1_ADDR_REG +#define DMA_UART_TX_ADDRHI_REG DMA1_ADDRHI_REG +#define DMA_UART_TX_SIZE_REG DMA1_SIZE_REG +#define DMA_UART_TX_MODE_REG DMA1_MODE_REG + +#define DMA2_ADDR_REG REG_ADDR16(0xc08) +#define DMA2_SIZE_REG REG_ADDR8(0xc0a) +#define DMA2_MODE_REG REG_ADDR8(0xc0b) + +#define DMA3_ADDR_REG REG_ADDR16(0xc0c) +#define DMA3_SIZE_REG REG_ADDR8(0xc0e) +#define DMA3_MODE_REG REG_ADDR8(0xc0f) + +#define DMA4_ADDR_REG REG_ADDR16(0xc10) +#define DMA4_SIZE_REG REG_ADDR8(0xc16) +#define DMA4_MODE_REG REG_ADDR8(0xc17) + +#define DMA5_ADDR_REG REG_ADDR16(0xc14) +#define DMA5_SIZE_REG REG_ADDR8(0xc16) +#define DMA5_MODE_REG REG_ADDR8(0xc17) + +#define DMA7_ADDR_REG REG_ADDR16(0xc18) +#define DMA7_SIZE_REG REG_ADDR8(0xc1a) +#define DMA7_MODE_REG REG_ADDR8(0xc1b) + +/* DMA realdy register definitions */ + +#define DMA_TX_RDY0_REG REG_ADDR8(0xc24) +#define DMA_TX_RDY1_REG REG_ADDR8(0xc25) +#define DMA_RX_RDY0_REG REG_ADDR8(0xc26) +#define DMA_RX_RDY1_REG REG_ADDR8(0xc27) + +/* DMA irq register definitions + * DMA_IRQ_MASK_REG: enable or disable the dma interrupt + * DMA_IRQ_EN_REG : enable or disable the dma channel + * DMA_IRQ_STA_REG : get the dma interupt status and write 1 to clear + */ + +#define DMA_IRQ_MASK_REG REG_ADDR8(0xc21) +#define DMA_IRQ_EN_REG REG_ADDR8(0xc20) +#define DMA_IRQ_STA_REG REG_ADDR8(0xc26) + +/* DMA Channel */ + +#define DMA_CHAN0 BIT(0) +#define DMA_CHAN1 BIT(1) +#define DMA_CHAN2 BIT(2) +#define DMA_CHAN3 BIT(3) +#define DMA_CHAN4 BIT(4) +#define DMA_CHAN5 BIT(5) +#define DMA_CHAN7 BIT(7) + +#define DMA_CHAN_UART_RX DMA_CHAN0 +#define DMA_CHAN_UART_TX DMA_CHAN1 +#define DMA_CHAN_RF_RX DMA_CHAN2 +#define DMA_CHAN_RF_TX DMA_CHAN3 +#define DMA_CHAN_AES_OUT DMA_CHAN4 +#define DMA_CHAN_AES_IN DMA_CHAN5 +#define DMA_CHAN_PWM DMA_CHAN7 + +/* DMA Mode */ + +#define DMA_MODE_WR_MEM BIT(0) +#define DMA_MODE_PINGPONG_EN BIT(1) +#define DMA_MODE_FIFO_EN BIT(2) +#define DMA_MODE_AUTO_MODE BIT(3) +#define DMA_MODE_READ_MODE BIT(4) +#define DMA_MODE_BYTE_MODE BIT(5) + +#endif /* __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_DMA_H */ diff --git a/arch/arm/src/tlsr82/hardware/tlsr82_gpio.h b/arch/arm/src/tlsr82/hardware/tlsr82_gpio.h new file mode 100644 index 0000000000000..d8ca83bca2508 --- /dev/null +++ b/arch/arm/src/tlsr82/hardware/tlsr82_gpio.h @@ -0,0 +1,111 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/hardware/tlsr82_gpio.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_GPIO_H +#define __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_GPIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "hardware/tlsr82_register.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* GPIO register definitions */ + +#define GPIO_SET_PA_ACT_REG REG_ADDR8(0x586) +#define GPIO_SET_PA_IN_REG REG_ADDR8(0x580) +#define GPIO_SET_PA_IE_REG REG_ADDR8(0x581) +#define GPIO_SET_PA_OEN_REG REG_ADDR8(0x582) +#define GPIO_SET_PA_OUT_REG REG_ADDR8(0x583) +#define GPIO_SET_PA_POL_REG REG_ADDR8(0x584) +#define GPIO_SET_PA_DS_REG REG_ADDR8(0x585) + +#define GPIO_SET_PB_ACT_REG REG_ADDR8(0x586 + 8) +#define GPIO_SET_PB_IN_REG REG_ADDR8(0x580 + 8) +#define GPIO_SET_PB_IE_REG REG_ADDR8(0x581 + 8) +#define GPIO_SET_PB_OEN_REG REG_ADDR8(0x582 + 8) +#define GPIO_SET_PB_OUT_REG REG_ADDR8(0x583 + 8) +#define GPIO_SET_PB_POL_REG REG_ADDR8(0x584 + 8) +#define GPIO_SET_PB_DS_REG REG_ADDR8(0x585 + 8) + +#define GPIO_SET_PC_ACT_REG REG_ADDR8(0x586 + 16) +#define GPIO_SET_PC_IN_REG REG_ADDR8(0x580 + 16) +#define ANALOG_PC_IE_ADDR 0xc0 +#define GPIO_SET_PC_OEN_REG REG_ADDR8(0x582 + 16) +#define GPIO_SET_PC_OUT_REG REG_ADDR8(0x583 + 16) +#define GPIO_SET_PC_POL_REG REG_ADDR8(0x584 + 16) +#define ANALOG_PC_DS_ADDR 0xc2 + +#define GPIO_SET_PD_ACT_REG REG_ADDR8(0x586 + 24) +#define GPIO_SET_PD_IN_REG REG_ADDR8(0x580 + 24) +#define GPIO_SET_PD_IE_REG REG_ADDR8(0x581 + 24) +#define GPIO_SET_PD_OEN_REG REG_ADDR8(0x582 + 24) +#define GPIO_SET_PD_OUT_REG REG_ADDR8(0x583 + 24) +#define GPIO_SET_PD_POL_REG REG_ADDR8(0x584 + 24) +#define GPIO_SET_PD_DS_REG REG_ADDR8(0x585 + 24) + +#define GPIO_SET_PE_ACT_REG REG_ADDR8(0x5A6) +#define GPIO_SET_PE_IN_REG REG_ADDR8(0x5A0) +#define GPIO_SET_PE_IE_REG REG_ADDR8(0x5A1) +#define GPIO_SET_PE_OEN_REG REG_ADDR8(0x5A2) +#define GPIO_SET_PE_OUT_REG REG_ADDR8(0x5A3) +#define GPIO_SET_PE_POL_REG REG_ADDR8(0x5A4) +#define GPIO_SET_PE_DS_REG REG_ADDR8(0x5A5) + +#define GPIO_SETTING_ACT_REG(group) REG_ADDR8(0x586 + ((group) << 3)) +#define GPIO_SETTING_IN_REG(group) REG_ADDR8(0x580 + ((group) << 3)) +#define GPIO_SETTING_IE_REG(group) REG_ADDR8(0x581 + ((group) << 3)) +#define GPIO_SETTING_OEN_REG(group) REG_ADDR8(0x582 + ((group) << 3)) +#define GPIO_SETTING_OUT_REG(group) REG_ADDR8(0x583 + ((group) << 3)) +#define GPIO_SETTING_POL_REG(group) REG_ADDR8(0x584 + ((group) << 3)) +#define GPIO_SETTING_DS_REG(group) REG_ADDR8(0x585 + ((group) << 3)) + +#define GPIO_MUX_REG(group, pin) REG_ADDR8(0x5a8 + ((group) << 1) \ + + (((pin) >= 4) ? 1 : 0)) + +#define GPIO_IRQ_NORMAL_ALL_REG REG_ADDR8(0x5b5) +#define GPIO_IRQ_RISC_EN_REG REG_ADDR8(0x642) + +#define GPIO_IRQ_NORMAL_REG(group) REG_ADDR8(0x587 + (group)) +#define GPIO_IRQ_M0_REG(group) REG_ADDR8(0x5b8 + (group)) +#define GPIO_IRQ_M1_REG(group) REG_ADDR8(0x5c0 + (group)) +#define GPIO_IRQ_M2_REG(group) REG_ADDR8(0x5c8 + (group)) + +#define GPIO_IRQ_NORMAL_ALL_WAKEUP (1 << 2) +#define GPIO_IRQ_NORMAL_ALL_EN (1 << 3) +#define GPIO_IRQ_RISC0_EN (1 << 5) +#define GPIO_IRQ_RISC1_EN (1 << 6) + +#define GPIO_SET_AS_GPIO(group, pin) BM_SET(GPIO_SETTING_ACT_REG(group), BIT(pin)) +#define GPIO_SET_AS_MUX(group, pin) BM_CLR(GPIO_SETTING_ACT_REG(group), BIT(pin)) + +#define GPIO_SET_OUT_HIGH(group, pin) +#define GPIO_SET_OUT_LOW(group, pin) + +#define GPIO_SET_IN_VAL(group, pin) + +#endif /* __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_GPIO_H */ diff --git a/arch/arm/src/tlsr82/hardware/tlsr82_irq.h b/arch/arm/src/tlsr82/hardware/tlsr82_irq.h new file mode 100644 index 0000000000000..6ba548f4e223a --- /dev/null +++ b/arch/arm/src/tlsr82/hardware/tlsr82_irq.h @@ -0,0 +1,43 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/hardware/tlsr82_irq.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_IRQ_H +#define __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "hardware/tlsr82_register.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define IRQ_MASK_REG REG_ADDR32(0x640) +#define IRQ_PRIO_REG REG_ADDR32(0x644) +#define IRQ_SRC_REG REG_ADDR32(0x648) +#define IRQ_SRC3_REG REG_ADDR8(0x64a) +#define IRQ_EN_REG REG_ADDR8(0x643) + +#endif /* __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_IRQ_H */ diff --git a/arch/arm/src/tlsr82/hardware/tlsr82_mspi.h b/arch/arm/src/tlsr82/hardware/tlsr82_mspi.h new file mode 100644 index 0000000000000..c22abd2f0f46a --- /dev/null +++ b/arch/arm/src/tlsr82/hardware/tlsr82_mspi.h @@ -0,0 +1,76 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/hardware/tlsr82_mspi.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_MSPI_H +#define __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_MSPI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "hardware/tlsr82_register.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MSPI_DATA_REG REG_ADDR8(0x0c) +#define MSPI_CTRL_REG REG_ADDR8(0x0d) +#define MSPI_MODE_REG REG_ADDR8(0x0f) + +#define MSPI_CTRL_CS_SHIFT 0 +#define MSPI_CTRL_CS_MASK (0x1 << MSPI_CTRL_CS_SHIFT) +#define MSPI_CTRL_CS_HIGH (0x1 << MSPI_CTRL_CS_SHIFT) +#define MSPI_CTRL_CS_LOW (0x0 << MSPI_CTRL_CS_SHIFT) + +#define MSPI_CTRL_SDO_SHIFT 1 +#define MSPI_CTRL_SDO_MASK (0x1 << MSPI_CTRL_SDO_SHIFT) + +#define MSPI_CTRL_CONT_SHIFT 2 +#define MSPI_CTRL_CONT_MASK (0x1 << MSPI_CTRL_CONT_SHIFT) + +#define MSPI_CTRL_RD_SHIFT 3 +#define MSPI_CTRL_RD_MASK (0x1 << MSPI_CTRL_RD_SHIFT) + +#define MSPI_CTRL_BUSY_SHIFT 4 +#define MSPI_CTRL_BUSY_MASK (0x1 << MSPI_CTRL_BUSY_SHIFT) + +#define MSPI_MODE_DUAL_DATA_SHIFT 0 +#define MSPI_MODE_DUAL_DATA_MASK (0x1 << MSPI_MODE_DUAL_DATA_SHIFT) + +#define MSPI_MODE_DUAL_ADDR_SHIFT 1 +#define MSPI_MODE_DUAL_ADDR_MASK (0x1 << MSPI_MODE_DUAL_ADDR_SHIFT) + +#define MSPI_MODE_CLKDIV_SHIFT 2 +#define MSPI_MODE_CLKDIV_MASK (0x3f << MSPI_MODE_CLKDIV_SHIFT) + +/* MSPI Operation Macros, follow the telink SDK */ + +#define MSPI_CS_HIGH() (MSPI_CTRL_REG = MSPI_CTRL_CS_MASK) +#define MSPI_CS_LOW() (MSPI_CTRL_REG = 0) +#define MSPI_WRITE(data) (MSPI_DATA_REG = (data)) +#define MSPI_READ() (MSPI_DATA_REG) +#define MSPI_WAIT() while (MSPI_CTRL_REG & MSPI_CTRL_BUSY_MASK) +#define MSPI_AUTO_MODE() (MSPI_CTRL_REG = 0x0a) + +#endif /* __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_MSPI_H */ diff --git a/arch/arm/src/tlsr82/hardware/tlsr82_pwm.h b/arch/arm/src/tlsr82/hardware/tlsr82_pwm.h new file mode 100644 index 0000000000000..1fc1a6575e00e --- /dev/null +++ b/arch/arm/src/tlsr82/hardware/tlsr82_pwm.h @@ -0,0 +1,69 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/hardware/tlsr82_pwm.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_PWM_H +#define __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_PWM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "hardware/tlsr82_register.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define PWM_CLKDIV_REG REG_ADDR8(0x782) + +#define PWM_ENABLE0_REG REG_ADDR8(0x781) +#define PWM_MODE0_REG REG_ADDR8(0x783) + +#define PWM_ENABLE_REG REG_ADDR8(0x780) +#define PWM_INVERT_REG REG_ADDR8(0x784) +#define PWM_N_INVERT_REG REG_ADDR8(0x785) +#define PWM_POL_REG REG_ADDR8(0x786) + +#define PWM_CYCLE_REG(n) REG_ADDR32(0x794 + ((n) << 2)) +#define PWM_CMP_REG(n) REG_ADDR16(0x794 + ((n) << 2)) +#define PWM_MAX_REG(n) REG_ADDR16(0x796 + ((n) << 2)) + +#define PWM_PLUSE_NUM_REG REG_ADDR16(0x7ac) + +#define PWM_IRQ_CTRL_REG REG_ADDR8(0x7b0) +#define PWM_IRQ_STA_REG REG_ADDR8(0x7b1) + +#define PWM_PLUSE_CNT_REG REG_ADDR8(0x7c0) + +/* PWM IRQ status */ + +#define PWM_IRQ_STA_PNUM0 BIT(0) +#define PWM_IRQ_STA_IRFIFO0 BIT(1) +#define PWM_IRQ_STA_CYCLE0 BIT(2) +#define PWM_IRQ_STA_CYCLE1 BIT(3) +#define PWM_IRQ_STA_CYCLE2 BIT(4) +#define PWM_IRQ_STA_CYCLE3 BIT(5) +#define PWM_IRQ_STA_CYCLE4 BIT(6) +#define PWM_IRQ_STA_CYCLE5 BIT(7) + +#endif /* __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_PWM_H */ diff --git a/arch/arm/src/tlsr82/hardware/tlsr82_register.h b/arch/arm/src/tlsr82/hardware/tlsr82_register.h new file mode 100644 index 0000000000000..82c311ec3c7c0 --- /dev/null +++ b/arch/arm/src/tlsr82/hardware/tlsr82_register.h @@ -0,0 +1,99 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/hardware/tlsr82_register.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_REGISTER_H +#define __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_REGISTER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "arm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Regisger base address */ + +#define REG_BASE_ADDR 0x00800000 + +#define REG_ADDR8(a) getreg8(REG_BASE_ADDR + (a)) +#define REG_ADDR16(a) getreg16(REG_BASE_ADDR + (a)) +#define REG_ADDR32(a) getreg32(REG_BASE_ADDR + (a)) + +#define write_reg8(addr,v) putreg8(v, REG_BASE_ADDR + (addr)) +#define write_reg16(addr,v) putreg16(v, REG_BASE_ADDR + (addr)) +#define write_reg32(addr,v) putreg32(v, REG_BASE_ADDR + (addr)) + +/* Common macros definition */ + +#define BIT(n) (1 << (n)) +#define BIT_MASK_LEN(len) (BIT(len)-1) +#define BIT_RNG(s, e) (BIT_MASK_LEN((e) - (s) + 1) << (s)) +#define BM_SET(x, m) ((x) |= (m)) +#define BM_CLR(x, m) ((x) &= ~(m)) +#define BM_IS_SET(x, m) ((x) & (m)) +#define BM_IS_CLR(x, m) ((~(x)) & (m)) +#define BM_FLIP(x, m) ((x) ^= (mask)) + +/* Reset register definition */ + +#define RESET_RST0_REG REG_ADDR8(0x60) +#define RESET_RST1_REG REG_ADDR8(0x61) +#define RESET_RST2_REG REG_ADDR8(0x62) +#define RESET_PWDNEN_REG REG_ADDR8(0x6f) + +/* Reset reson definition */ + +#define RESET_RST0_SPI BIT(0) +#define RESET_RST0_I2C BIT(1) +#define RESET_RST0_UART BIT(2) +#define RESET_RST0_USB BIT(3) +#define RESET_RST0_PWM BIT(4) +#define RESET_RST0_QDEC BIT(5) +#define RESET_RST0_IR BIT(6) +#define RESET_RST0_SWIRE BIT(7) + +#define RESET_RST1_ZB BIT(0) +#define RESET_RST1_SYSTIM BIT(1) +#define RESET_RST1_DMA BIT(2) +#define RESET_RST1_ALGM BIT(3) +#define RESET_RST1_AES BIT(4) +#define RESET_RST1_ADC BIT(5) +#define RESET_RST1_ALG BIT(6) +#define RESET_RST1_PKE BIT(7) + +#define RESET_RST2_AIF BIT(0) +#define RESET_RST2_AUDIO BIT(1) +#define RESET_RST2_DFIFO BIT(2) +#define RESET_RST2_TRNG BIT(3) +#define RESET_RST2_RISC BIT(4) +#define RESET_RST2_MCIC BIT(5) +#define RESET_RST2_RSIC1R BIT(6) +#define RESET_RST2_MCIC1R BIT(7) + +#define RESET_PWDNEN_SUSP_EN BIT(0) +#define RESET_PWDNEN_RESET_ALL BIT(5) +#define RESET_PWDNEN_SUSP BIT(7) + +#endif /* __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_REGISTER_H */ diff --git a/arch/arm/src/tlsr82/hardware/tlsr82_spi.h b/arch/arm/src/tlsr82/hardware/tlsr82_spi.h new file mode 100644 index 0000000000000..d7ac17cd87c69 --- /dev/null +++ b/arch/arm/src/tlsr82/hardware/tlsr82_spi.h @@ -0,0 +1,91 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/hardware/tlsr82_spi.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_SPI_H +#define __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_SPI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "hardware/tlsr82_register.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* SPI and I2C Group select register */ + +#define SPI_I2C_GROUP_REG REG_ADDR8(0x5b6) + +#define SPI_I2C_GROUPA_EN BIT_RNG(4,5) +#define SPI_I2C_GROUPB_EN BIT(6) +#define SPI_I2C_GROUPD_EN BIT(7) + +/* SPI and I2C Pin select register */ + +#define SPI_I2C_PIN_REG REG_ADDR8(0x5b7) + +#define SPI_PA3_SPI_EN BIT(0) +#define SPI_PA4_SPI_EN BIT(1) +#define SPI_PB6_SPI_EN BIT(2) +#define SPI_PD7_SPI_EN BIT(3) +#define I2C_PA3_I2C_EN BIT(4) +#define I2C_PA4_I2C_EN BIT(5) +#define I2C_PB6_I2C_EN BIT(6) +#define I2C_PD7_I2C_EN BIT(7) + +/* SPI Data register */ + +#define SPI_DATA_REG REG_ADDR8(0x08) + +/* SPI Control register */ + +#define SPI_CTRL_REG REG_ADDR8(0x09) + +#define SPI_CTRL_CS BIT(0) +#define SPI_CTRL_MASTER_EN BIT(1) +#define SPI_CTRL_OUT_OFF BIT(2) +#define SPI_CTRL_RW_STA BIT(3) +#define SPI_CTRL_ADDR_ADD BIT(4) +#define SPI_CTRL_SHARE_MODE BIT(5) +#define SPI_CTRL_BUSY BIT(6) + +#define SPI_CS_HIGH BM_SET(SPI_CTRL_REG, SPI_CTRL_CS) +#define SPI_CS_LOW BM_CLR(SPI_CTRL_REG, SPI_CTRL_CS) + +/* SPI Clock register */ + +#define SPI_CLK_REG REG_ADDR8(0x0a) + +#define SPI_CLK_DIV BIT_RNG(0,6) +#define SPI_CLK_EN BIT(7) + +/* SPI Mode select register, CPOL, CPHA */ + +#define SPI_MODE_REG REG_ADDR8(0x0b) + +#define SPI_MODE_CPOL BIT(0) +#define SPI_MODE_CPHA BIT(1) + +#endif /* __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_SPI_H */ diff --git a/arch/arm/src/tlsr82/hardware/tlsr82_timer.h b/arch/arm/src/tlsr82/hardware/tlsr82_timer.h new file mode 100644 index 0000000000000..be8da2846f206 --- /dev/null +++ b/arch/arm/src/tlsr82/hardware/tlsr82_timer.h @@ -0,0 +1,109 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/hardware/tlsr82_timer.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_TIMER_H +#define __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_TIMER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "hardware/tlsr82_register.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Watchdog Register definitions */ + +#define WDOG_STATUS_REG REG_ADDR8(0x72) + +#define WDOG_CTRL_REG REG_ADDR32(0x620) + +/* Bit definitions */ + +#define WDOG_STATUS_RESET_SHIFT 0 +#define WDOG_STATUS_RESET_MASK (0x1 << WDOG_STATUS_RESET_SHIFT) +#define WDOG_STATUS_RESET_YES (0x1 << WDOG_STATUS_RESET_SHIFT) +#define WDOG_STATUS_RESET_NO (0x0 << WDOG_STATUS_RESET_SHIFT) + +#define WDOG_CTRL_CAPT_SHIFT 9 +#define WDOG_CTRL_CAPT_MASK (0x3fff << WDOG_CTRL_CAPT_SHIFT) + +#define WDOG_CTRL_ENABLE_SHIFT 23 +#define WDOG_CTRL_ENABLE_MASK (0x1 << WDOG_CTRL_ENABLE_SHIFT) +#define WDOG_CTRL_ENABLE_ON (0x1 << WDOG_CTRL_ENABLE_SHIFT) +#define WDOG_CTRL_ENABLE_OFF (0x0 << WDOG_CTRL_ENABLE_SHIFT) + +/* Timer Regisger definitions */ + +#define TIMER_CTRL_REG REG_ADDR32(0x620) + +#define TIMER_STATUS_REG REG_ADDR8(0x623) + +#define TIMER_CAPT_REG(n) REG_ADDR32(0x624 + ((n) << 2)) +#define TIMER_CAPT0_REG REG_ADDR32(0x624) +#define TIMER_CAPT1_REG REG_ADDR32(0x628) +#define TIMER_CAPT2_REG REG_ADDR32(0x62c) + +#define TIMER_TICK_REG(n) REG_ADDR32(0x630 + ((n) << 2)) +#define TIMER_TICK0_REG REG_ADDR32(0x630) +#define TIMER_TICK1_REG REG_ADDR32(0x634) +#define TIMER_TICK2_REG REG_ADDR32(0x638) + +#define SYSTIMER_TICK_REG REG_ADDR32(0x740) +#define SYSTIMER_CAPT_REG REG_ADDR32(0x744) +#define SYSTIMER_CALI_REG REG_ADDR8(0x749) +#define SYSTIMER_CTRL_REG REG_ADDR8(0x74a) +#define SYSTIMER_STATUS_REG REG_ADDR8(0x74b) +#define SYSTIMER_IRQ_MASK_REG REG_ADDR8(0x748) + +/* Bit definition */ + +#define TIMER_CTRL_T0_ENABLE_SHIFT 0 +#define TIMER_CTRL_T0_MODE_SHIFT 1 +#define TIMER_CTRL_T1_ENABLE_SHIFT 3 +#define TIMER_CTRL_T1_MODE_SHIFT 4 +#define TIMER_CTRL_T2_ENABLE_SHIFT 6 +#define TIMER_CTRL_T2_MODE_SHIFT 7 +#define TIMER_CTRL_WDOG_CAPT_SHIFT 9 + +#define TIMER_CTRL_T0_ENABLE BIT(0) +#define TIMER_CTRL_T0_MODE BIT_RNG(1, 2) +#define TIMER_CTRL_T1_ENABLE BIT(3) +#define TIMER_CTRL_T1_MODE BIT_RNG(4, 5) +#define TIMER_CTRL_T2_ENABLE BIT(6) +#define TIMER_CTRL_T2_MODE BIT_RNG(7, 8) +#define TIMER_CTRL_WDOG_CAPT BIT(9, 22) + +#define TIMER_STATUS_T0_CLR BIT(0) +#define TIMER_STATUS_T1_CLR BIT(1) +#define TIMER_STATUS_T2_CLR BIT(2) +#define TIMER_STATUS_WDOG_CLR BIT(3) + +#define SYSTIMER_CTRL_TIMER_EN BIT(1) +#define SYSTIMER_CTRL_CALI_EN BIT(3) + +#define SYSTIMER_IRQ_MASK_EN BIT(2) + +#endif /* __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_TIMER_H */ diff --git a/arch/arm/src/tlsr82/hardware/tlsr82_uart.h b/arch/arm/src/tlsr82/hardware/tlsr82_uart.h new file mode 100644 index 0000000000000..050cd8a20214d --- /dev/null +++ b/arch/arm/src/tlsr82/hardware/tlsr82_uart.h @@ -0,0 +1,157 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/hardware/tlsr82_uart.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_UART_H +#define __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_UART_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "hardware/tlsr82_register.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Uart buffer register definitions */ + +#define UART_BUF_REG REG_ADDR32(0x90) +#define UART_BUF0_REG REG_ADDR8(0x90) +#define UART_BUF1_REG REG_ADDR8(0x91) +#define UART_BUF2_REG REG_ADDR8(0x92) +#define UART_BUF3_REG REG_ADDR8(0x93) + +#define UART_BUF(n) REG_ADDR8(0x90 + (n)) + +/* Uart clock register definitions */ + +#define UART_CLK_REG REG_ADDR16(0x94) + +#define UART_CLK_DIV 0x7fff +#define UART_CLK_EN_SHIFT 15 +#define UART_CLK_EN (0x1 << UART_CLK_EN_SHIFT) + +/* Uart control register definitions */ + +#define UART_CTRL_REG REG_ADDR32(0x96) +#define UART_CTRL0_REG REG_ADDR8(0x96) +#define UART_CTRL1_REG REG_ADDR8(0x97) +#define UART_CTRL2_REG REG_ADDR8(0x98) +#define UART_CTRL3_REG REG_ADDR8(0x99) + +#define UART_CTRL0_BWPC_SHIFT 0 +#define UART_CTRL0_BWPC (0xf << UART_CTRL0_BWPC_SHIFT) +#define UART_CTRL0_RX_DMA_EN_SHIFT 4 +#define UART_CTRL0_RX_DMA_EN (0x1 << UART_CTRL0_RX_DMA_EN_SHIFT) +#define UART_CTRL0_TX_DMA_EN_SHIFT 5 +#define UART_CTRL0_TX_DMA_EN (0x1 << UART_CTRL0_TX_DMA_EN_SHIFT) +#define UART_CTRL0_RX_IRQ_EN_SHIFT 6 +#define UART_CTRL0_RX_IRQ_EN (0x1 << UART_CTRL0_RX_IRQ_EN_SHIFT) +#define UART_CTRL0_TX_IRQ_EN_SHIFT 7 +#define UART_CTRL0_TX_IRQ_EN (0x1 << UART_CTRL0_TX_IRQ_EN_SHIFT) + +#define UART_CTRL1_CTS_SEL_SHIFT 0 +#define UART_CTRL1_CTS_SEL (0x1 << UART_CTRL1_CTS_SEL_SHIFT) +#define UART_CTRL1_CTS_EN_SHIFT 1 +#define UART_CTRL1_CTS_EN (0x1 << UART_CTRL1_CTS_EN_SHIFT) +#define UART_CTRL1_PARITY_EN_SHIFT 2 +#define UART_CTRL1_PARITY_EN (0x1 << UART_CTRL1_PARITY_EN_SHIFT) +#define UART_CTRL1_PARITY_SEL_SHIFT 3 +#define UART_CTRL1_PARITY_SEL (0x1 << UART_CTRL1_PARITY_SEL_SHIFT) +#define UART_CTRL1_STOPBIT_SHIFT 4 +#define UART_CTRL1_STOPBIT (0x3 << UART_CTRL1_STOPBIT_SHIFT) +#define UART_CTRL1_TTL_SHIFT 6 +#define UART_CTRL1_TTL (0x1 << UART_CTRL1_TTL_SHIFT) +#define UART_CTRL1_LOOPBACK_SHIFT 7 +#define UART_CTRL1_LOOPBACK (0x1 << UART_CTRL1_LOOPBACK_SHIFT) + +#define UART_CTRL2_RTS_TRI_LEVEL_SHIFT 0 +#define UART_CTRL2_RTS_TRI_LEVEL (0xf << UART_CTRL2_RTS_TRI_LEVEL_SHIFT) +#define UART_CTRL2_RTS_PARITY_SHIFT 4 +#define UART_CTRL2_RTS_PARITY (0x1 << UART_CTRL2_RTS_PARITY_SHIFT) +#define UART_CTRL2_RTS_MUL_VAL_SHIFT 5 +#define UART_CTRL2_RTS_MUL_VAL (0x1 << UART_CTRL2_RTS_MUL_VAL_SHIFT) +#define UART_CTRL2_RTS_MUL_EN_SHIFT 6 +#define UART_CTRL2_RTS_MUL_EN (0x1 << UART_CTRL2_RTS_MUL_EN_SHIFT) +#define UART_CTRL2_RTS_EN_SHIFT 7 +#define UART_CTRL2_RTS_EN (0x1 << UART_CTRL2_RTS_EN_SHIFT) + +#define UART_CTRL3_RX_TRI_LEVEL_SHIFT 0 +#define UART_CTRL3_RX_TRI_LEVEL (0xf << UART_CTRL3_RX_TRI_LEVEL_SHIFT) +#define UART_CTRL3_TX_TRI_LEVEL_SHIFT 4 +#define UART_CTRL3_TX_TRI_LEVEL (0xf << UART_CTRL3_TX_TRI_LEVEL_SHIFT) + +/* Uart rx timeout register definitions */ + +#define UART_RXTIMEOUT0_REG REG_ADDR8(0x9a) +#define UART_RXTIMEOUT1_REG REG_ADDR8(0x9b) + +#define UART_RXTIMEOUT1_SEL_SHIFT 0 +#define UART_RXTIMEOUT1_SEL (0x3 << UART_RXTIMEOUT1_SEL_SHIFT) +#define UART_RXTIMEOUT1_P7816_EN_SHIFT 5 +#define UART_RXTIMEOUT1_P7816_EN (0x1 << UART_RXTIMEOUT1_P7816_EN_SHIFT) +#define UART_RXTIMEOUT1_MASK_TXDONE_SHIFT 6 +#define UART_RXTIMEOUT1_MASK_TXDONE (0x1 << UART_RXTIMEOUT1_MASK_TXDONE_SHIFT) +#define UART_RXTIMEOUT1_MASK_ERR_SHIFT 7 +#define UART_RXTIMEOUT1_MASK_ERR (0x1 << UART_RXTIMEOUT1_MASK_ERR_SHIFT) + +/* Uart buffer count register definitions */ + +#define UART_BUF_CNT0_REG REG_ADDR8(0x9c) +#define UART_BUF_CNT1_REG REG_ADDR8(0x9d) + +#define UART_BUF_CNT0_RX_CNT_SHIFT 0 +#define UART_BUF_CNT0_RX_CNT (0xf << UART_BUF_CNT0_RX_CNT_SHIFT) +#define UART_BUF_CNT0_TX_CNT_SHIFT 4 +#define UART_BUF_CNT0_TX_CNT (0xf << UART_BUF_CNT0_TX_CNT_SHIFT) + +#define UART_BUF_CNT1_RB_CNT 0x07 +#define UART_BUF_CNT1_IRQ BIT(3) +#define UART_BUF_CNT1_WB_CNT 0x70 +#define UART_BUF_CNT1_RX_CLR BIT(6) +#define UART_BUF_CNT1_TX_CLR BIT(7) +#define UART_BUF_CNT1_RX_ERR BIT(7) + +#define UART_GET_RX_BUF_CNT() ((UART_BUF_CNT0_REG & UART_BUF_CNT0_RX_CNT) >>\ + UART_BUF_CNT0_RX_CNT_SHIFT) +#define UART_GET_TX_BUF_CNT() ((UART_BUF_CNT0_REG & UART_BUF_CNT0_TX_CNT) >>\ + UART_BUF_CNT0_TX_CNT_SHIFT) + +/* Uart interupt register definitions */ + +#define UART_IRQ_REG REG_ADDR8(0x9e) + +#define UART_IRQ_TXDONE (0x1 << 0) +#define UART_IRQ_TXBUF (0x1 << 1) +#define UART_IRQ_RXDONE (0x1 << 2) +#define UART_IRQ_RXBUF (0x1 << 3) +#define UART_IRQ_CLR_RX (0x1 << 6) +#define UART_IRQ_CLR_TX (0x1 << 7) + +#define UART_STATE_REG REG_ADDR8(0x9f) + +#define UART_STATE_TX 0x07 +#define UART_STATE_RX 0xf0 + +#endif /* __ARCH_ARM_SRC_TLSR82_HARDWARE_TLSR82_UART_H */ diff --git a/arch/arm/src/tlsr82/tc32/Make.defs b/arch/arm/src/tlsr82/tc32/Make.defs new file mode 100644 index 0000000000000..61fa0f10cc295 --- /dev/null +++ b/arch/arm/src/tlsr82/tc32/Make.defs @@ -0,0 +1,56 @@ +############################################################################ +# arch/arm/src/tlsr82/tc32/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include common/Make.defs + +# Specify our HEAD assembly file. This will be linked as +# the first object file, so it will appear at address 0 + +HEAD_ASRC = cstartup_flash.S + +# Arch Flags + +AFLAGS += -DMCU_STARTUP_FLASH + +# Filter-out unnecessary .S files + +CMN_ASRCS := + +# Filter-out unnecessary .c files + +TC32_CSRCS_FILTER := arm_backtrace_fp.c arm_backtrace_thumb.c +TC32_CSRCS_FILTER += arm_switchcontext.c arm_fullcontextrestore.c +TC32_CSRCS_FILTER += arm_saveusercontext.c +CMN_CSRCS := $(filter-out $(TC32_CSRCS_FILTER), $(CMN_CSRCS)) + +# Common files in arch/arm/src/armv6-m + +CMN_CSRCS += arm_sigdeliver.c + +# Common files in arch/arm/src/tlsr82/tc32 + +CMN_ASRCS += tc32_fullcontextrestore.S tc32_switchcontext.S tc32_saveusercontext.S + +CMN_CSRCS += tc32_doirq.c tc32_initialstate.c tc32_schedulesigaction.c +CMN_CSRCS += tc32_syscall.c tc32_udelay.c + +ifeq ($(CONFIG_SCHED_BACKTRACE),y) + CMN_CSRCS += tc32_backtrace.c +endif diff --git a/arch/arm/src/tlsr82/tc32/div_mod.S b/arch/arm/src/tlsr82/tc32/div_mod.S new file mode 100644 index 0000000000000..3e5ea90ba567d --- /dev/null +++ b/arch/arm/src/tlsr82/tc32/div_mod.S @@ -0,0 +1,320 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tc32/div_mod.S + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#define UDIV #0 +#define SDIV #1 +#define UMOD #2 +#define SMOD #3 + +#define MUL2_STEP 8 + + .code 16 + .text + + .align 2 + .global __modsi3 + .code 16 + .thumb_func + .type __modsi3, %function +__modsi3: + tmov r2, SMOD + tj div + .size __modsi3, .-__modsi3 + + .align 2 + .global __divsi3 + .code 16 + .thumb_func + .type __divsi3, %function +__divsi3: + tmov r2, SDIV + tj div + .size __divsi3, .-__divsi3 + + .align 2 + .global __umodsi3 + .code 16 + .thumb_func + .type __umodsi3, %function +__umodsi3: + tmov r2, UMOD + tj div + .size __umodsi3, .-__umodsi3 + + .align 2 + .global __udivsi3 + .code 16 + .thumb_func + .type __udivsi3, %function +__udivsi3: + tmov r2, UDIV + tj div + .size __udivsi3, .-__udivsi3 + + .align 2 + .global div + .code 16 + .thumb_func + .type div, %function +div: + tmrcs r3 + tpush {r3, r4} + tmov r4, #0x80 + tor r3, r4 + tmcsr r3 + + tloadr r3, .L11 + tstorer r0, [r3] + tadd r3, r3, #4 + tstorer r1, [r3] + tsub r3, r3, #8 + tstorerb r2, [r3] + +.L2: + tloadrb r0, [r3] + tcmp r0, #0 + tjne .L2 + tcmp r2, #1 + tjls .L4 + tadd r3, r3, #8 + tloadr r0, [r3] + tj .L6 +.L4: + tadd r3, r3, #4 + tloadr r0, [r3] + +.L6: + tpop {r3, r4} + tmcsr r3 + tjex lr + + .align 4 +.L11: + .word(0x800664) + .word(0x800660) + .word(0x800668) + .size div, .-div + +#if 1 + .align 4 + .global mul32x32_64 + .thumb_func + .type mul32x32_64, %function +mul32x32_64: + tmul r0, r1 + tloadr r1, [pc, #4] + tloadr r1, [r1, #0] + tjex lr + .word(0x008006fc) +#endif + +#if 1 + .align 4 + .global mz_mul1 + .thumb_func + .type mz_mul1, %function +mz_mul1: + tpush {r4, r5, r6, r7} + tmov r4, r8 + tpush {r4} + tmov r4, #1 + tmov r8, r4 //r8 = 1 + tloadr r6, [pc, #4] //r6 REG_ADDR32(0x6fc) + tmovs r5, #0 //clear carry + tj MZ_MUL1_END + .word(0x008006fc) +MZ_MUL1_START: + tmul r4, r3 // l0 = a0 * b + tloadr r7, [r0, #0] // y0 + tadd r4, r5 // l0 + c => c0 + tsubc r5, r5 // c0 - 1 + tadd r4, r7 // l0 + c + y0 => c1 + tloadr r7, [r6, #0] // r7 = h0 + tadd r5, r8 // c0 - 1 + 1 = c0 (nc) + tstorem r0!, {r4} // store y0 + taddc r5, r7 // cn = c0 + h1 + c1 +MZ_MUL1_END: + tloadm r1!, {r4} // load *a + tsub r2, #1 // r2-- + tcmp r2, #0 + tjge MZ_MUL1_START // carry set + tstorem r0!, {r5} + + tpop {r4} + tmov r8, r4 + tpop {r4, r5, r6, r7} + tjex lr +#endif + + .align 4 + .global mz_mul2 + .thumb_func + .type mz_mul2, %function +mz_mul2: + tpush {r4, r5, r6, r7} + tmov r4, r8 + tmov r5, r9 + tmov r6, r10 + + tmov r7, r11 + tpush {r4, r5, r6, r7} + tmov r8, r2 //r8 = n, loop number + tmov r2, #1 + + tmov r10, r2 // r10 = 1 + tsub r2, #(MUL2_STEP + 1) + tmov r9, r2 //r9 = -MUL2_STEP + tmov r2, #0 + + tmov r2, #0 + tloadr r6, [pc, #4] //r6 REG_ADDR32(0x6fc) + tmov r11,r2 //r11 = 0 + tj MZ_MUL2_LOOP + //tj MZ_MUL2_LOOP2 + .word(0x008006fc) + +MZ_MUL2_START: + //a0 + tmul r4, r3 // l0 = a0 * b + tloadr r7, [r0, #0] // y0 + tadd r4, r2 // l0 + c => c0 + tsubc r2, r2 // c0 - 1 + tadd r4, r7 // l0 + c + y0 => c1 + tloadr r7, [r6, #0] // r7 = h0 + tadd r2, r10 // c0 - 1 + 1 = c0 (nc) + tstorem r0!, {r4} // store y0 y1 + taddc r2, r7 // cn = c0 + h1 + c1 + + tmul r5, r3 // l1 = a1 * b + tloadr r7, [r0, #0] // y1 + tadd r5, r2 // l1 + cn => c2 + tsubc r2, r2 // c2 - 1 + tadd r5, r7 // l1 + c + y1 => c3 + tloadr r7, [r6, #0] // r7 = h0 + tadd r2, r10 // c0 - 1 + 1 = c0 (nc) + tstorem r0!, {r5} // store y0 y1 + tloadm r1!, {r4, r5} // load *a + taddc r2, r7 // cn2 = c2 + h1 + c3 + + //a0 + tmul r4, r3 // l0 = a0 * b + tloadr r7, [r0, #0] // y0 + tadd r4, r2 // l0 + c => c0 + tsubc r2, r2 // c0 - 1 + tadd r4, r7 // l0 + c + y0 => c1 + tloadr r7, [r6, #0] // r7 = h0 + tadd r2, r10 // c0 - 1 + 1 = c0 (nc) + tstorem r0!, {r4} // store y0 y1 + taddc r2, r7 // cn = c0 + h1 + c1 + + tmul r5, r3 // l1 = a1 * b + tloadr r7, [r0, #0] // y1 + tadd r5, r2 // l1 + cn => c2 + tsubc r2, r2 // c2 - 1 + tadd r5, r7 // l1 + c + y1 => c3 + tloadr r7, [r6, #0] // r7 = h0 + tadd r2, r10 // c0 - 1 + 1 = c0 (nc) + tstorem r0!, {r5} // store y0 y1 + tloadm r1!, {r4, r5} // load *a + taddc r2, r7 // cn2 = c2 + h1 + c3 + + //a0 + tmul r4, r3 // l0 = a0 * b + tloadr r7, [r0, #0] // y0 + tadd r4, r2 // l0 + c => c0 + tsubc r2, r2 // c0 - 1 + tadd r4, r7 // l0 + c + y0 => c1 + tloadr r7, [r6, #0] // r7 = h0 + tadd r2, r10 // c0 - 1 + 1 = c0 (nc) + tstorem r0!, {r4} // store y0 y1 + taddc r2, r7 // cn = c0 + h1 + c1 + + tmul r5, r3 // l1 = a1 * b + tloadr r7, [r0, #0] // y1 + tadd r5, r2 // l1 + cn => c2 + tsubc r2, r2 // c2 - 1 + tadd r5, r7 // l1 + c + y1 => c3 + tloadr r7, [r6, #0] // r7 = h0 + tadd r2, r10 // c0 - 1 + 1 = c0 (nc) + tstorem r0!, {r5} // store y0 y1 + tloadm r1!, {r4, r5} // load *a + taddc r2, r7 // cn2 = c2 + h1 + c3 + +///// next 2 + tmul r4, r3 // l0 = a0 * b + tloadr r7, [r0, #0] // y0 + tadd r4, r2 // l0 + c => c0 + tsubc r2, r2 // c0 - 1 + tadd r4, r7 // l0 + c + y0 => c1 + tloadr r7, [r6, #0] // r7 = h0 + tadd r2, r10 // c0 - 1 + 1 = c0 (nc) + tstorem r0!, {r4} // store y0 y1 + taddc r2, r7 // cn = c0 + h1 + c1 + + tmul r5, r3 // l1 = a1 * b + tloadr r7, [r0, #0] // y1 + tadd r5, r2 // l1 + cn => c2 + tsubc r2, r2 // c2 - 1 + tadd r5, r7 // l1 + c + y1 => c3 + tloadr r7, [r6, #0] // r7 = h0 + tadd r2, r10 // c0 - 1 + 1 = c0 (nc) + tstorem r0!, {r5} // store y0 y1 + taddc r2, r7 // cn2 = c2 + h1 + c3 + +MZ_MUL2_LOOP: + tloadm r1!, {r4, r5} // load *a + tadd r8, r9 // r8 -= MUL2_STEP + tcmp r8, r11 // const 0 + tjge MZ_MUL2_START // carry set + + tmov r5, r8 + tadd r5, #MUL2_STEP + tsub r1, #8 + tj MZ_MUL2_LOOP2 + +MZ_MUL2_START2: + tmul r4, r3 // l0 = a0 * b + tloadr r7, [r0, #0] // y0 + tadd r4, r2 // l0 + c => c0 + tsubc r2, r2 // c0 - 1 + tadd r4, r7 // l0 + c + y0 => c1 + tloadr r7, [r6, #0] // r7 = h0 + tadd r2, r10 // c0 - 1 + 1 = c0 (nc) + tstorem r0!, {r4} // store y0 + taddc r2, r7 // cn = c0 + h1 + c1 + +MZ_MUL2_LOOP2: + tloadm r1!, {r4} // load *a + tsub r5, #1 // r7-- + tcmp r5, #0 + tjge MZ_MUL2_START2 // carry set + +MZ_MUL2_END: + //tmov r2, #13 + tstorem r0!, {r2} + + tpop {r4, r5, r6, r7} + tmov r8, r4 + tmov r9, r5 + tmov r10, r6 + tmov r11, r7 + tpop {r4, r5, r6, r7} + tjex lr + tnop diff --git a/arch/arm/src/tlsr82/tc32/tc32.h b/arch/arm/src/tlsr82/tc32/tc32.h new file mode 100644 index 0000000000000..18952c9017558 --- /dev/null +++ b/arch/arm/src/tlsr82/tc32/tc32.h @@ -0,0 +1,80 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tc32/tc32.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_TC32_TC32_H +#define __ARCH_ARM_SRC_TLSR82_TC32_TC32_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* TC32 */ + +/* PSR bits */ + +#define PSR_MODE_MASK 0x0000001f /* Bits 0-4: Mode bits */ +#define PSR_MODE_IRQ 0x00000012 /* 32-bit IRQ mode */ +#define PSR_MODE_SVC 0x00000013 /* 32-bit Supervisor mode */ +#define PSR_I_BIT 0x00000080 /* Bit 7: IRQ disable */ + /* Bits 8-23: Reserved */ +#define PSR_J_BIT 0x01000000 /* Bit 24: Jazelle state bit */ + /* Bits 25-26: Reserved */ +#define PSR_Q_BIT 0x08000000 /* Bit 27: Sticky overflow */ +#define PSR_V_BIT 0x10000000 /* Bit 28: Overflow */ +#define PSR_C_BIT 0x20000000 /* Bit 29: Carry/Borrow/Extend */ +#define PSR_Z_BIT 0x40000000 /* Bit 30: Zero */ +#define PSR_N_BIT 0x80000000 /* Bit 31: Negative/Less than */ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif /* __ASSEMBLY__ */ + +#endif /* __ARCH_ARM_SRC_TLSR82_TC32_TC32_H */ diff --git a/arch/arm/src/tlsr82/tc32/tc32_backtrace.c b/arch/arm/src/tlsr82/tc32/tc32_backtrace.c new file mode 100644 index 0000000000000..d5b1e46c37edb --- /dev/null +++ b/arch/arm/src/tlsr82/tc32/tc32_backtrace.c @@ -0,0 +1,556 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tc32/tc32_backtrace.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "sched/sched.h" + +#include "arm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Macro and definitions for simple decoding of instuctions. + * To check an instruction, it is ANDed with the IMASK_ and + * the result is compared with the IOP_. The macro INSTR_IS + * does this and returns !0 to indicate a match. + */ + +#define INSTR_IS(i, o) (((i) & (IMASK_##o)) == (IOP_##o)) + +#define IMASK_T_PUSH_LO 0xff00 /* push {reglist} (not LR) */ +#define IOP_T_PUSH_LO 0x6400 + +#define IMASK_T_PUSH 0xff00 /* push {reglist} (inc LR) */ +#define IOP_T_PUSH 0x6500 + +#define IMASK_T_SUB_SP_16 0xff80 /* sub sp, # */ +#define IOP_T_SUB_SP_16 0x6080 + +#define IMASK_T_BL 0xf000 /* bl */ +#define IOP_T_BL 0x9000 + +#define INSTR_LIMIT 0x2000 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static void **g_backtrace_code_regions; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: getlroffset + * + * Description: + * getlroffset() returns the currect link address offset. + * + * Input Parameters: + * lr - Link register address + * + * Returned Value: + * Link address offset, 0 is returned if the lr is invalid. + * + ****************************************************************************/ + +#ifdef CONFIG_MM_KASAN +__attribute__((no_sanitize_address)) +#endif +static int getlroffset(uint8_t *lr) +{ + lr = (uint8_t *)((uintptr_t)lr & 0xfffffffe); + + if (((uintptr_t)lr & 0xffffffe0) == 0xffffffe0) + { + return 0; + } + + /* Always return 4, only tjl (32bit instruction) jump with lr in tc32 + * return (*(uint16_t *)(lr - 4) & 0xf000) == 0xf000 ? 5 : 3; + */ + + return 4; +} + +/**************************************************************************** + * Name: in_code_region + * + * Description: + * in_code_region() check if the program counter is in the program + * section, program counter should always be within the view of executable + * sections. + * + * Input Parameters: + * pc - Program counter address + * + * Returned Value: + * A boolean value: true the counter is vaild + * + ****************************************************************************/ + +#ifdef CONFIG_MM_KASAN +__attribute__((no_sanitize_address)) +#endif +static bool in_code_region(void *pc) +{ + int i = 0; + + if ((uintptr_t)pc >= (uintptr_t)_START_TEXT && + (uintptr_t)pc < (uintptr_t)_END_TEXT) + { + return true; + } + + if (g_backtrace_code_regions) + { + while (g_backtrace_code_regions[i] && + (g_backtrace_code_regions[i] != + g_backtrace_code_regions[i + 1])) + { + if (g_backtrace_code_regions[i] <= pc && + g_backtrace_code_regions[i + 1] > pc) + { + return true; + } + + i += 2; + } + } + + return false; +} + +/**************************************************************************** + * Name: backtrace_push_internal + * + * Description: + * backtrace_push_internal() returns the currect link address from + * program counter and stack pointer + * + * Input Parameters: + * psp - Double poninter to the SP, this parameter will be changed if + * the corresponding LR address is successfully found. + * ppc - Double poninter to the PC, this parameter will be changed if + * the corresponding LR address is successfully found. + * + * Returned Value: + * Link address should be returned if successful + * Otherwise, NULL is returned + * + ****************************************************************************/ + +#ifdef CONFIG_MM_KASAN +__attribute__((no_sanitize_address)) +#endif +static void *backtrace_push_internal(void **psp, void **ppc) +{ + uint8_t *sp = *psp; + uint8_t *pc = *ppc; + uint8_t *base; + uint8_t *lr; + uint16_t ins16; + int offset = 1; + bool found; + int frame; + int i; +#ifdef CONFIG_ALLSYMS + const struct symtab_s *symbol; + size_t symbolsize; + + symbol = allsyms_findbyvalue(pc, &symbolsize); + if (!symbol || !in_code_region(symbol->sym_value)) + { + return NULL; + } +#endif + + found = false; + + for (i = 0; i < INSTR_LIMIT; i += 2) + { + base = pc - i; + ins16 = *(uint16_t *)(base); + if (INSTR_IS(ins16, T_PUSH)) + { + /* Bit 1 number in low byte indicates the number of pushed + * low register, +1 for LR is alao pushed into the stack. + */ + + frame = __builtin_popcount(ins16 & 0xff) + 1; + ins16 = *(uint16_t *)(base - 2); + if (INSTR_IS(ins16, T_PUSH_LO)) + { + offset += __builtin_popcount(ins16 & 0xff); + frame += offset - 1; + } + + found = true; + } + + if (found) + { +#ifdef CONFIG_ALLSYMS + if (base >= (uint8_t *)symbol->sym_value && + base - (uint8_t *)symbol->sym_value < 8) + { + break; + } + else + { + found = false; + } +#else + break; +#endif + } + } + + if (!found) + { + return NULL; + } + + i = 0; + + while (base + i < pc) + { + ins16 = *(uint16_t *)(base + i); + if (INSTR_IS(ins16, T_SUB_SP_16)) + { + /* Low 7 bit indicates the number sub to sp */ + + frame += (ins16 & 0x7f); + break; + } + + if (INSTR_IS(ins16, T_PUSH_LO)) + { + /* Bit 1 number in low 8bit indicated the number of pushed + * low register. + */ + + frame += __builtin_popcount(ins16 & 0xff); + } + + /* 16bit instruction */ + + i += 2; + } + + lr = (uint8_t *)*((uint32_t *)sp + frame - offset); + if (!in_code_region(lr)) + { + return NULL; + } + + offset = getlroffset(lr); + if (offset == 0) + { + return NULL; + } + + *psp = (uint32_t *)sp + frame; + + return lr - offset; +} + +/**************************************************************************** + * Name: backtrace_push + * + * Description: + * backtrace_push() parsing the return address through instruction + * + ****************************************************************************/ + +#ifdef CONFIG_MM_KASAN +__attribute__((no_sanitize_address)) +#endif +static int backtrace_push(void *limit, void **sp, void *pc, + void **buffer, int size, int *skip) +{ + int i = 0; + + if (!in_code_region(pc)) + { + return 0; + } + + pc = (void *)((uintptr_t)pc & 0xfffffffe); + + if ((*skip)-- <= 0) + { + buffer[i++] = pc; + } + + while (i < size) + { + if (*sp >= limit) + { + break; + } + + pc = backtrace_push_internal(sp, &pc); + if (!pc) + { + break; + } + + if ((*skip)-- <= 0) + { + buffer[i++] = pc; + } + } + + return i; +} + +/**************************************************************************** + * Name: backtrace_branch + * + * Description: + * backtrace() parsing the return address through branch instruction + * + ****************************************************************************/ + +#ifdef CONFIG_MM_KASAN +__attribute__((no_sanitize_address)) +#endif +static int backtrace_branch(void *limit, void *sp, + void **buffer, int size, int *skip) +{ +#if 1 + uint16_t ins16; + uint32_t addr; + int i; + + for (i = 0; i < size && sp < limit; sp += sizeof(uint32_t)) + { + addr = *(uint32_t *)sp; + if (!in_code_region((void *)addr)) + { + continue; + } + + addr = (addr & ~1) - 2; + ins16 = *(uint16_t *)addr; + + /* TJL Instruction + * OFFSET: 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 + * VALUE : 1 0 0 1 - - - - - - - - - - - - + * OFFSET: 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 + * VALUE : 1 0 0 1 1 - - - - - - - - - - - + */ + + if ((ins16 & 0x9800) == 0x9800) + { + addr -= 2; + ins16 = *(uint16_t *)addr; + if (INSTR_IS(ins16, T_BL)) + { + if ((*skip)-- <= 0) + { + buffer[i++] = (void *)addr; + } + } + } + } + + return i; +#else + /* Not implement backtrace branch method temporarily + * Wait for the instruction tjl encode document from telink. + */ + + return 0; +#endif +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_backtrace_init_code_regions + * + * Description: + * The up call up_backtrace_init_code_regions() will set the start + * and end addresses of the customized program sections, this method + * will help the different boards to configure the current text + * sections for some complicate platfroms + * + * Input Parameters: + * regions The start and end address of the text segment + * This interface supports the input of multiple + * groups of sections, Each set of the sections + * must be a pair, the end of the area must specify + * two NULL porint, e.g : + * + * static void *g_code_regions[] = + * { + * _START_TEXT, _END_TEXT, + * _START2_TEXT, _END2_TEXT, + * _START3_TEXT, _END3_TEXT, + * NULL, NULL, + * }; + * + * up_backtrace_init_code_regions(g_code_regions); + * + ****************************************************************************/ + +#ifdef CONFIG_MM_KASAN +__attribute__((no_sanitize_address)) +#endif +void up_backtrace_init_code_regions(void **regions) +{ + g_backtrace_code_regions = regions; +} + +/**************************************************************************** + * Name: up_backtrace + * + * Description: + * up_backtrace() returns a backtrace for the TCB, in the array + * pointed to by buffer. A backtrace is the series of currently active + * function calls for the program. Each item in the array pointed to by + * buffer is of type void *, and is the return address from the + * corresponding stack frame. The size argument specifies the maximum + * number of addresses that can be stored in buffer. If the backtrace is + * larger than size, then the addresses corresponding to the size most + * recent function calls are returned; to obtain the complete backtrace, + * make sure that buffer and size are large enough. + * + * Input Parameters: + * tcb - Address of the task's TCB + * buffer - Return address from the corresponding stack frame + * size - Maximum number of addresses that can be stored in buffer + * + * Returned Value: + * up_backtrace() returns the number of addresses returned in buffer + * + ****************************************************************************/ + +#ifdef CONFIG_MM_KASAN +__attribute__((no_sanitize_address)) +#endif +int up_backtrace(struct tcb_s *tcb, void **buffer, int size, int skip) +{ + struct tcb_s *rtcb = running_task(); + irqstate_t flags; + void *sp; + int ret; + + if (size <= 0 || !buffer) + { + return 0; + } + + if (tcb == NULL) + { + tcb = rtcb; + } + + if (tcb == rtcb) + { + sp = (void *)up_getsp(); + + if (up_interrupt_context()) + { +#if CONFIG_ARCH_INTERRUPTSTACK > 7 + ret = backtrace_push( +# ifdef CONFIG_SMP + arm_intstack_top(), +# else + &g_intstacktop, +# endif /* CONFIG_SMP */ + &sp, (void *)up_backtrace + 10, + buffer, size, &skip); +#else + ret = backtrace_push(rtcb->stack_base_ptr + + rtcb->adj_stack_size, + &sp, (void *)up_backtrace + 10, + buffer, size, &skip); +#endif + if (ret < size) + { + sp = (void *)CURRENT_REGS[REG_SP]; + ret += backtrace_push(rtcb->stack_base_ptr + + rtcb->adj_stack_size, &sp, + (void *)CURRENT_REGS[REG_PC], + &buffer[ret], size - ret, &skip); + } + } + else + { + ret = backtrace_push(rtcb->stack_base_ptr + + rtcb->adj_stack_size, &sp, + (void *)up_backtrace + 10, + buffer, size, &skip); + } + + if (ret < size) + { + ret += backtrace_branch(rtcb->stack_base_ptr + + rtcb->adj_stack_size, sp, + &buffer[ret], size - ret, &skip); + } + } + else + { + ret = 0; + + flags = enter_critical_section(); + + if (skip-- <= 0) + { + buffer[ret++] = (void *)tcb->xcp.regs[REG_PC]; + } + + if (ret < size) + { + sp = (void *)tcb->xcp.regs[REG_SP]; + ret += backtrace_push(tcb->stack_base_ptr + + tcb->adj_stack_size, &sp, + (void *)tcb->xcp.regs[REG_LR], + &buffer[ret], size - ret, &skip); + + if (ret < size) + { + ret += backtrace_branch(tcb->stack_base_ptr + + tcb->adj_stack_size, sp, + &buffer[ret], size - ret, &skip); + } + } + + leave_critical_section(flags); + } + + return ret; +} diff --git a/arch/arm/src/tlsr82/tc32/tc32_doirq.c b/arch/arm/src/tlsr82/tc32/tc32_doirq.c new file mode 100644 index 0000000000000..bbe178da8c052 --- /dev/null +++ b/arch/arm/src/tlsr82/tc32/tc32_doirq.c @@ -0,0 +1,270 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tc32/tc32_doirq.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "arm_internal.h" + +#include "group/group.h" + +#include "hardware/tlsr82_irq.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const uint8_t tc32_lowbit_bitmap[] = +{ + 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 00 */ + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 10 */ + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 20 */ + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 30 */ + 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 40 */ + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 50 */ + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 60 */ + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 70 */ + 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 80 */ + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 90 */ + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* A0 */ + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* B0 */ + 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* C0 */ + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* D0 */ + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* E0 */ + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* F0 */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tc32_ffs + * + * Description: + * This function finds the first bit set (beginning with the least + * significant bit) in value and return the index of that bit. + * TC32 archtecture does not support clz instruction. + * + * Parameters: + * uint32_t - value + * + * Return Value: + * [1, 32] - On Success. + * 0 - No set bit in value (value = 0). + * + ****************************************************************************/ + +static inline int locate_code(".ram_code") tc32_ffs(uint32_t value) +{ + int ret; + + if (value == 0) + { + ret = 0; + } + else if (value & 0xff) + { + ret = (int)tc32_lowbit_bitmap[value & 0xff] + 1; + } + else if (value & 0xff00) + { + ret = (int)tc32_lowbit_bitmap[(value & 0xff00) >> 8] + 9; + } + else if (value & 0xff0000) + { + ret = (int)tc32_lowbit_bitmap[(value & 0xff0000) >> 16] + 17; + } + else + { + ret = (int)tc32_lowbit_bitmap[(value & 0xff000000) >> 24] + 25; + } + + return ret; +} + +/**************************************************************************** + * Name: tc32_getirq + * + * Description: + * This function is used to get the interrupt number based on the + * interrupt source flag register. + * + * Parameters: + * void + * + * Return Value: + * [0, NR_IRQS-1] - On success, found interrupt number, success. + * NR_IRQS - Error, invalid interrupt number. + * + ****************************************************************************/ + +static int locate_code(".ram_code") tc32_getirq(void) +{ + int irq; + + /* Only detect the enable interrupt */ + + irq = tc32_ffs(IRQ_SRC_REG & IRQ_MASK_REG); + + if (irq > 0 && irq <= NR_IRQS) + { + /* Minus one to obatin the correct irq number */ + + irq = irq - 1; + } + else + { + /* Invalid irq number */ + + irq = NR_IRQS; + } + + return irq; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/** + * @brief This function serves to handle the interrupt of MCU + * @param[in] none + * @return none + */ + +uint32_t *arm_doirq(int irq, uint32_t *regs) +{ + board_autoled_on(LED_INIRQ); +#ifdef CONFIG_SUPPRESS_INTERRUPTS + PANIC(); +#else + /* Current regs non-zero indicates that we are processing an interrupt; + * g_current_regs is also used to manage interrupt level context switches. + * + * Nested interrupts are not supported + */ + + DEBUGASSERT(CURRENT_REGS == NULL); + CURRENT_REGS = regs; + + /* Disable further occurrences of this interrupt (until the interrupt + * sources have been clear by the driver). + */ + + /* Deliver the IRQ */ + + irq_dispatch(irq, regs); + +#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV) + /* Check for a context switch. If a context switch occurred, then + * g_current_regs will have a different value than it did on entry. If an + * interrupt level context switch has occurred, then restore the floating + * point state and the establish the correct address environment before + * returning from the interrupt. + */ + + if (regs != CURRENT_REGS) + { +#ifdef CONFIG_ARCH_FPU + /* Restore floating point registers */ + + riscv_restorefpu(CURRENT_REGS); +#endif + +#ifdef CONFIG_ARCH_ADDRENV + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ + + group_addrenv(NULL); +#endif + } +#endif + + /* If a context switch occurred while processing the interrupt then + * g_current_regs may have change value. If we return any value different + * from the input regs, then the lower level will know that a context + * switch occurred during interrupt processing. + */ + + regs = (uint32_t *)CURRENT_REGS; + + /* Set g_current_regs to NULL to indicate that we are no longer in an + * interrupt handler. + */ + + CURRENT_REGS = NULL; + + /* Unmask the last interrupt (global interrupts are still disabled) */ + +#endif + board_autoled_off(LED_INIRQ); + return regs; +} + +/**************************************************************************** + * Name: irq_handler + * + * Description: + * This function is the common interrupt handler for all interrupts. + * + * Parameters: + * uint32_t *regs - the saved context array pointer of interrpted task, + * size = XCPTCONTEXT_REGS. + * + * Return Value: + * uint32_t *regs - if occur context switch, regs = the saved context + * array pointer of next task, if not, regs = input regs, + * size = XCPTCONTEXT_REGS. + * + ****************************************************************************/ + +uint32_t * locate_code(".ram_code") irq_handler(uint32_t *regs) +{ + int irq = tc32_getirq(); + + return arm_doirq(irq, regs); +} + diff --git a/arch/arm/src/tlsr82/tc32/tc32_exception.S b/arch/arm/src/tlsr82/tc32/tc32_exception.S new file mode 100644 index 0000000000000..74324e845d552 --- /dev/null +++ b/arch/arm/src/tlsr82/tc32/tc32_exception.S @@ -0,0 +1,234 @@ +/**************************************************************************** + * arch/arm/src/tlsr82xx/tc32/tc32_exception.S + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + @ .global exception_common + @ .extern irq_handler + @ .file "tc32_exception.S" + +/**************************************************************************** + * Macro Definitions + ****************************************************************************/ + +/**************************************************************************** + * Name: setintstack + * + * Description: + * Set the current stack pointer to the "top" the interrupt stack. Single CPU + * case. Must be provided by MCU-specific logic in the SMP case. + * + ****************************************************************************/ + +@ #if !defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 3 +@ .macro setintstack, tmp1, tmp2 +@ ldr \tmp1, =g_intstacktop +@ mov sp, \tmp1 +@ .endm +@ #endif + +/**************************************************************************** + * .text + ****************************************************************************/ + +@ .align 2 +@ .code 16 +@ .thumb_func +@ .type exception_common, function +@ exception_common: + +@ tpush {r14} +@ tpush {r0} // It is NOT equivalent to tpush {r0-r7} !!! +@ tpush {r1} +@ tpush {r2} +@ tpush {r3} +@ tpush {r4} +@ tpush {r5} +@ tpush {r6} +@ tpush {r7} +@ tmrss r0 +@ tpush {r0} + +@ tloadr r0, _REG_IRQ_EN @ disable irq +@ tloadrb r1, [r0] +@ tpush {r1} @ save REG_IRQ_EN +@ tmov r1, #0 @ disable irq +@ tstorerb r1, [r0] @ disable irq + +@ tmov r1, r8 +@ tmov r2, r9 +@ tmov r3, r10 +@ tmov r4, r11 +@ tmov r5, r12 + +@ tloadr r0, _REG_IRQ_EN + 4 @ switch to normal mode +@ tnop +@ tmcsr r0 @ switch to normal mode +@ tnop +@ tmov r6, r13 @ get normal SP +@ tloadr r0, _REG_IRQ_EN + 8 @ switch to IRQ mode +@ tnop +@ tmcsr r0 @ switch to IRQ mode +@ tnop + +@ tmov r7, r14 @ save r14 as PC (r15). not accurate though +@ tpush {r1} @ It is NOT equivalent to tpush {r1-r7} !!! +@ tpush {r2} +@ tpush {r3} +@ tpush {r4} +@ tpush {r5} +@ tpush {r6} +@ tpush {r7} + +@ tmov r0, r13 +@ tjl irq_handler +@ tmov r1, r13 + +@ tloadr r2, _REG_IRQ_EN @ disable irq +@ tmov r3, #0 @ disable irq +@ tstorerb r3, [r2] @ disable irq + +@ /* Judge weather a context switch occur */ + +@ tcmp r0, r1 +@ tjeq 1f + +@ /* Return with a pending context switch, copy the next task register to main stack +@ * r0 = pointer to next task register array +@ */ + +@ tloadr r2, [r0, #0] +@ tloadr r3, [r0, #4] +@ tloadr r4, [r0, #8] +@ tloadr r5, [r0, #12] +@ tloadr r6, [r0, #16] +@ tloadr r7, [r0, #20] +@ tstorer r2, [r1, #0] +@ tstorer r3, [r1, #4] +@ tstorer r4, [r1, #8] +@ tstorer r5, [r1, #12] +@ tstorer r6, [r1, #16] +@ tstorer r7, [r1, #20] + +@ tloadr r2, [r0, #24] +@ tloadr r3, [r0, #28] +@ tloadr r4, [r0, #32] +@ tloadr r5, [r0, #36] +@ tloadr r6, [r0, #40] +@ tloadr r7, [r0, #44] +@ tstorer r2, [r1, #24] +@ tstorer r3, [r1, #28] +@ tstorer r4, [r1, #32] +@ tstorer r5, [r1, #36] +@ tstorer r6, [r1, #40] +@ tstorer r7, [r1, #44] + +@ tloadr r2, [r0, #48] +@ tloadr r3, [r0, #52] +@ tloadr r4, [r0, #56] +@ tloadr r5, [r0, #60] +@ tloadr r6, [r0, #64] +@ tloadr r7, [r0, #68] +@ tstorer r2, [r1, #48] +@ tstorer r3, [r1, #52] +@ tstorer r4, [r1, #56] +@ tstorer r5, [r1, #60] +@ tstorer r6, [r1, #64] +@ tstorer r7, [r1, #68] + +@ 1: +@ /* No context switch, pop the register and return to the task interrupted */ + +@ tpop {r7} @ It is NOT equivalent to tpop {r1-r7} !!! +@ tpop {r6} +@ tpop {r5} +@ tpop {r4} +@ tpop {r3} +@ tpop {r2} +@ tpop {r1} + +@ tmov r8, r1 +@ tmov r9, r2 +@ tmov r10,r3 +@ tmov r11,r4 +@ tmov r12,r5 + +@ tloadr r0, _REG_IRQ_EN + 4 @ switch to normal mode +@ tnop +@ tmcsr r0 @ switch to normal mode +@ tnop +@ tmov r13, r6 @ set normal SP +@ tloadr r0, _REG_IRQ_EN + 8 @ switch to IRQ mode +@ tnop +@ tmcsr r0 @ switch to IRQ mode +@ tnop + +@ tpop {r1} @ got IRQ enable flag +@ tloadr r0, _REG_IRQ_EN @ restore irq enable flag +@ tstorerb r1, [r0] @ restore irq enable flag + +@ tpop {r0} +@ tmssr r0 + +@ tpop {r7} @ It is NOT equivalent to tpop {r0-r7} !!! +@ tpop {r6} +@ tpop {r5} +@ tpop {r4} +@ tpop {r3} +@ tpop {r2} +@ tpop {r1} +@ tpop {r0} + +@ treti {r15} +@ .align 4 +@ _REG_IRQ_EN: +@ .word 0x800643 +@ .word 0x000093 +@ .word 0x000092 + +@ .size exception_common, .-exception_common + +/**************************************************************************** + * Name: g_intstackalloc/g_intstacktop + * + * Description: + * Shouldn't happen + * + ****************************************************************************/ + +@ #if CONFIG_ARCH_INTERRUPTSTACK > 3 +@ .bss +@ .global g_intstackalloc +@ .global g_intstacktop +@ .balign 4 +@ g_intstackalloc: +@ .skip (CONFIG_ARCH_INTERRUPTSTACK & ~3) +@ g_intstacktop: +@ .size g_intstackalloc, .-g_intstackalloc +@ #endif + +@ .end diff --git a/arch/arm/src/tlsr82/tc32/tc32_fullcontextrestore.S b/arch/arm/src/tlsr82/tc32/tc32_fullcontextrestore.S new file mode 100644 index 0000000000000..7c35b7a784d6e --- /dev/null +++ b/arch/arm/src/tlsr82/tc32/tc32_fullcontextrestore.S @@ -0,0 +1,156 @@ +/**************************************************************************** + * arch/arm/src/tlsr82xx/tc32/tc32_fullcontextrestore.S + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + .file "tc32_fullcontextrestore.S" + +/**************************************************************************** + * Macros + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm_fullcontextrestore + * + * Description: + * Restore the current thread context. Full prototype is: + * + * void arm_fullcontextrestore(uint32_t *restoreregs) noreturn_function; + * + * Returned Value: + * None + * + ****************************************************************************/ + + .align 2 + .code 16 + .thumb_func + .section .ram_code,"ax" + .global arm_fullcontextrestore + .type arm_fullcontextrestore, function +arm_fullcontextrestore: + + /* Move saved register to register R1 ~ R7 + * R8 --> R1 + * R9 --> R2 + * R10 --> R3 + * R11 --> R4 + * R12 --> R5 + * R13 (SP) --> R6 + * R15 (PC) --> R7 + */ + + tloadr r1, [r0, #(4 * REG_R8)] + tloadr r2, [r0, #(4 * REG_R9)] + tloadr r3, [r0, #(4 * REG_R10)] + tloadr r4, [r0, #(4 * REG_R11)] + tloadr r5, [r0, #(4 * REG_R12)] + tloadr r6, [r0, #(4 * REG_R13)] + tloadr r7, [r0, #(4 * REG_R15)] + + /* Restore register R8 ~ R12 */ + + tmov r8, r1 + tmov r9, r2 + tmov r10, r3 + tmov r11, r4 + tmov r12, r5 + + /* Restore register SP (SVC mode)*/ + + tmov r13, r6 + + /* Restore LR (R14, SVC mode) as PC (R15), not accurate though */ + + tmov r14, r7 + + /* Set CPSR be 0x00000092 to switch to IRQ mode */ + + tloadr r1, _REG_IRQ_EN2 + 4 + tnop + tmcsr r1 + tnop + + /* Get the saved IRQ_STATE and restore to [0x00800643] */ + + tloadr r1, _REG_IRQ_EN2 + tloadr r2, [r0, #(4 * REG_IRQ_EN)] + tstorerb r2, [r1] + + /* Get the saved CPSR and restore to SPSR, when return + * to SVC mode, the value of CPSR will be automatically + * updated to the value of SPSR. + */ + + tloadr r1, [r0, #(4 * REG_CPSR)] + tmssr r1 + + /* Get the saved R14 (LR, IRQ mode), clear the bit0 in LR to make + * return address be even, then restore it to LR + */ + + tloadr r1, [r0, #(4 * REG_R14)] + tloadr r2, _REG_IRQ_EN2 + 8 + tand r1, r2 + tmov r14, r1 + + /* Restore saved registers R1 ~ R7 */ + + tloadr r1, [r0, #(4 * REG_R1)] + tloadr r2, [r0, #(4 * REG_R2)] + tloadr r3, [r0, #(4 * REG_R3)] + tloadr r4, [r0, #(4 * REG_R4)] + tloadr r5, [r0, #(4 * REG_R5)] + tloadr r6, [r0, #(4 * REG_R6)] + tloadr r7, [r0, #(4 * REG_R7)] + + /* Restore saved register R0 */ + + tloadr r0, [r0, #(4 * REG_R0)] + + /* Push the R14 and pop to pc, return from IRQ mode */ + + tpush {r14} + treti {r15} + + .align 2 +_REG_IRQ_EN2: + .word 0x00800643 + .word 0x00000092 + .word 0xfffffffe + .size arm_fullcontextrestore, .-arm_fullcontextrestore + .end diff --git a/arch/arm/src/tlsr82/tc32/tc32_initialstate.c b/arch/arm/src/tlsr82/tc32/tc32_initialstate.c new file mode 100644 index 0000000000000..404b2b9221696 --- /dev/null +++ b/arch/arm/src/tlsr82/tc32/tc32_initialstate.c @@ -0,0 +1,152 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tc32/tc32_initialstate.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "tc32.h" +#include "arm_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_initial_state + * + * Description: + * A new thread is being started and a new TCB + * has been created. This function is called to initialize + * the processor specific portions of the new TCB. + * + * This function must setup the initial architecture registers + * and/or stack so that execution will begin at tcb->start + * on the next context switch. + * + ****************************************************************************/ + +void up_initial_state(struct tcb_s *tcb) +{ + struct xcptcontext *xcp = &tcb->xcp; + uint32_t cpsr; + + /* Initialize the initial exception register context structure */ + + memset(xcp, 0, sizeof(struct xcptcontext)); + + /* Initialize the idle thread stack */ + + if (tcb->pid == IDLE_PROCESS_ID) + { + tcb->stack_alloc_ptr = (void *)(g_idle_topstack - + CONFIG_IDLETHREAD_STACKSIZE); + tcb->stack_base_ptr = tcb->stack_alloc_ptr; + tcb->adj_stack_size = CONFIG_IDLETHREAD_STACKSIZE; + +#ifdef CONFIG_STACK_COLORATION + /* If stack debug is enabled, then fill the stack with a + * recognizable value that we can use later to test for high + * water marks. + */ + + arm_stack_color(tcb->stack_alloc_ptr, 0); +#endif /* CONFIG_STACK_COLORATION */ + + return; + } + + /* Initialize the context registers to stack top */ + + xcp->regs = (void *)((uint32_t)tcb->stack_base_ptr + + tcb->adj_stack_size - + XCPTCONTEXT_SIZE); + + /* Initialize the xcp registers */ + + memset(xcp->regs, 0, XCPTCONTEXT_SIZE); + + /* Save the initial stack pointer */ + + xcp->regs[REG_SP] = (uint32_t)tcb->stack_base_ptr + + tcb->adj_stack_size; + + /* Save the task entry point */ + + xcp->regs[REG_LR] = (uint32_t)tcb->start & ~1; + xcp->regs[REG_IRQ_EN] = 1; + + /* If this task is running PIC, then set the PIC base register to the + * address of the allocated D-Space region. + */ + +#ifdef CONFIG_PIC + if (tcb->dspace != NULL) + { + /* Set the PIC base register (probably R10) to the address of the + * alloacated D-Space region. + */ + + xcp->regs[REG_PIC] = (uint32_t)tcb->dspace->region; + } +#endif + + /* Set supervisor- or user-mode, depending on how NuttX is configured and + * what kind of thread is being started. Disable FIQs in any event + */ + +#ifdef CONFIG_BUILD_KERNEL + if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL) + { + /* It is a kernel thread.. set supervisor mode */ + + cpsr = PSR_MODE_SVC | PSR_F_BIT; + } + else + { + /* It is a normal task or a pthread. Set user mode */ + + cpsr = PSR_MODE_USR | PSR_F_BIT; + } +#else + /* If the kernel build is not selected, then all threads run in + * supervisor-mode. + */ + + cpsr = PSR_MODE_SVC; +#endif + + /* Enable or disable interrupts, based on user configuration */ + +# ifdef CONFIG_SUPPRESS_INTERRUPTS + cpsr |= PSR_I_BIT; +# endif + + xcp->regs[REG_CPSR] = cpsr; +} diff --git a/arch/arm/src/tlsr82/tc32/tc32_saveusercontext.S b/arch/arm/src/tlsr82/tc32/tc32_saveusercontext.S new file mode 100644 index 0000000000000..3f6c986a0458c --- /dev/null +++ b/arch/arm/src/tlsr82/tc32/tc32_saveusercontext.S @@ -0,0 +1,123 @@ +/**************************************************************************** + * arch/arm/src/tlsr82xx/tc32/tc32_saveusercontext.S + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + .file "tc32_saveusercontext.S" + +/**************************************************************************** + * Macros + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm_saveusercontext + * + * Description: + * Restore the current thread context. Full prototype is: + * + * int arm_saveusercontext(uint32_t *saveregs); + * + * R0 = saveregs = pinter saved array + * + * Returned Value: + * None + * + ****************************************************************************/ + + .align 2 + .code 16 + .thumb_func + .section .ram_code,"ax" + .global up_saveusercontext + .type up_saveusercontext, function +up_saveusercontext: + + /* + * r0 = pointer to the saveregs array + * Save r0 ~ r7 into the saved register array + */ + + tstorer r0, [r0, #64] + tstorer r1, [r0, #60] + tstorer r2, [r0, #56] + tstorer r3, [r0, #52] + tstorer r4, [r0, #48] + tstorer r5, [r0, #44] + tstorer r6, [r0, #40] + tstorer r7, [r0, #36] + + /* Save r14 (lr) into the saved register array */ + + tmov r1, r14 + tstorer r1, [r0, #68] + + /* Get CPSR and save it into the saved register array */ + + tmrcs r1 + tstorer r1, [r0, #32] + + /* Save IRQ_STATE into the saved register array */ + + tloadr r1, _REG_IRQ_EN1 + tloadrb r2, [r1] + tstorer r2, [r0, #28] + + /* Save r8 ~ r14 into the saved register array, r13(sp) r14 (lr/pc) */ + + tmov r1, r8 + tstorer r1, [r0, #24] + tmov r1, r9 + tstorer r1, [r0, #20] + tmov r1, r10 + tstorer r1, [r0, #16] + tmov r1, r11 + tstorer r1, [r0, #12] + tmov r1, r12 + tstorer r1, [r0, #8] + tmov r1, r13 + tstorer r1, [r0, #4] + tmov r1, r14 + tstorer r1, [r0, #0] + + /* Return 0 */ + + tmov r0, #0 + tjex lr + + .align 2 +_REG_IRQ_EN1: + .word 0x00800643 + .size up_saveusercontext, .-up_saveusercontext + .end + diff --git a/arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c b/arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c new file mode 100644 index 0000000000000..fb0ddcd97a819 --- /dev/null +++ b/arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c @@ -0,0 +1,195 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "tc32.h" +#include "sched/sched.h" +#include "arm_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_schedule_sigaction + * + * Description: + * This function is called by the OS when one or more + * signal handling actions have been queued for execution. + * The architecture specific code must configure things so + * that the 'sigdeliver' callback is executed on the thread + * specified by 'tcb' as soon as possible. + * + * This function may be called from interrupt handling logic. + * + * This operation should not cause the task to be unblocked + * nor should it cause any immediate execution of sigdeliver. + * Typically, a few cases need to be considered: + * + * (1) This function may be called from an interrupt handler + * During interrupt processing, all xcptcontext structures + * should be valid for all tasks. That structure should + * be modified to invoke sigdeliver() either on return + * from (this) interrupt or on some subsequent context + * switch to the recipient task. + * (2) If not in an interrupt handler and the tcb is NOT + * the currently executing task, then again just modify + * the saved xcptcontext structure for the recipient + * task so it will invoke sigdeliver when that task is + * later resumed. + * (3) If not in an interrupt handler and the tcb IS the + * currently executing task -- just call the signal + * handler now. + * + * Assumptions: + * Called from critical section + * + ****************************************************************************/ + +void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +{ + sinfo("tcb=0x%p sigdeliver=0x%p\n", tcb, sigdeliver); + + /* Refuse to handle nested signal actions */ + + if (!tcb->xcp.sigdeliver) + { + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ + + sinfo("rtcb=0x%p CURRENT_REGS=0x%p\n", this_task(), CURRENT_REGS); + + if (tcb == this_task()) + { + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. + */ + + if (!CURRENT_REGS) + { + /* In this case just deliver the signal now. */ + + sigdeliver(tcb); + } + + /* CASE 2: We are in an interrupt handler AND the + * interrupted task is the same as the one that + * must receive the signal, then we will have to modify + * the return state as well as the state in the TCB. + * + * Hmmm... there looks like a latent bug here: The following + * logic would fail in the strange case where we are in an + * interrupt handler, the thread is signalling itself, but + * a context switch to another task has occurred so that + * CURRENT_REGS does not refer to the thread of this_task()! + */ + + else + { + /* Save the return lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.sigdeliver = sigdeliver; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + arm_savestate(tcb->xcp.saved_regs); + + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ + + CURRENT_REGS = (void *)((uint32_t)CURRENT_REGS - + (uint32_t)XCPTCONTEXT_SIZE); + memcpy((uint32_t *)CURRENT_REGS, tcb->xcp.saved_regs, + XCPTCONTEXT_SIZE); + + CURRENT_REGS[REG_SP] = (uint32_t)CURRENT_REGS + + (uint32_t)XCPTCONTEXT_SIZE; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + CURRENT_REGS[REG_LR] = (uint32_t)arm_sigdeliver; + CURRENT_REGS[REG_CPSR] = PSR_MODE_SVC | PSR_I_BIT; + CURRENT_REGS[REG_IRQ_EN] = 0; + } + } + + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ + + else + { + /* Save the return lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.sigdeliver = sigdeliver; + + /* Save the current register context location */ + + tcb->xcp.saved_regs = tcb->xcp.regs; + + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ + + tcb->xcp.regs = (void *)((uint32_t)tcb->xcp.regs - + (uint32_t)XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); + + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + (uint32_t)XCPTCONTEXT_SIZE; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_LR] = (uint32_t)arm_sigdeliver; + tcb->xcp.regs[REG_CPSR] = PSR_MODE_SVC | PSR_I_BIT; + tcb->xcp.regs[REG_IRQ_EN] = 0; + } + } +} diff --git a/arch/arm/src/tlsr82/tc32/tc32_switchcontext.S b/arch/arm/src/tlsr82/tc32/tc32_switchcontext.S new file mode 100644 index 0000000000000..6b591a413d05d --- /dev/null +++ b/arch/arm/src/tlsr82/tc32/tc32_switchcontext.S @@ -0,0 +1,138 @@ +/**************************************************************************** + * arch/arm/src/tlsr82xx/tc32/tc32_switchcontext.S + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + .file "tc32_switchcontext.S" + +/**************************************************************************** + * Macros + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm_switchcontext + * + * Description: + * Restore the current thread context. Full prototype is: + * + * void arm_switchcontext(uint32_t **saveregs, uint32_t *restoreregs); + * + * R0 = saveregs , pointer to the current task tcb->regs, the sp after + current task context save should be saved in it. + * R1 = restoreregs , next task sp, using it to restore next task context. + * + * Returned Value: + * None + * + ****************************************************************************/ + + .align 2 + .code 16 + .thumb_func + .section .ram_code,"ax" + .extern arm_fullcontextrestore + .global arm_switchcontext + .type arm_switchcontext, function +arm_switchcontext: + + /* Save LR, R0 ~ R7 into current task stack */ + + tpush {lr} + tpush {r0} + tpush {r1} + tpush {r2} + tpush {r3} + tpush {r4} + tpush {r5} + tpush {r6} + tpush {r7} + + /* Get current CPSR and save it into current task stack */ + + tmrcs r3 + tpush {r3} + + /* Save IRQ_STATE into current task stack */ + + tloadr r3, _REG_IRQ_EN3 + tloadrb r2, [r3] + tpush {r2} + + /* Save r8 ~ r12 into current task stack */ + + tmov r3, r8 + tpush {r3} + tmov r3, r9 + tpush {r3} + tmov r3, r10 + tpush {r3} + tmov r3, r11 + tpush {r3} + tmov r3, r12 + tpush {r3} + + /* Get the SP (before context save) value and + * save it into current task stack + */ + + tmov r2, #(XCPTCONTEXT_SIZE - 8) + tmov r3, r13 + tadd r3, r3, r2 + tpush {r3} + + /* Save PC into current task stack */ + + tmov r3, r14 + tpush {r3} + + /* Save back current sp to the tcb->regs */ + + tmov r3, r13 + tstorer r3, [r0] + + /* r0 = r1 = next task tcb->regs (actualy sp) */ + + tmov r0, r1 + + /* Call arm_fullcontextrestore to restore the context */ + + tjl arm_fullcontextrestore + + .align 2 +_REG_IRQ_EN3: + .word 0x00800643 + .size arm_switchcontext, .-arm_switchcontext + .end diff --git a/arch/arm/src/tlsr82/tc32/tc32_syscall.c b/arch/arm/src/tlsr82/tc32/tc32_syscall.c new file mode 100644 index 0000000000000..2fb11cf5f49d5 --- /dev/null +++ b/arch/arm/src/tlsr82/tc32/tc32_syscall.c @@ -0,0 +1,57 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tc32/tc32_syscall.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "arm_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm_syscall + * + * Description: + * SWI interrupts will vector here with insn=the SWI instruction and + * xcp=the interrupt context + * + * The handler may get the SWI number be de-referencing + * the return address saved in the xcp and decoding + * the SWI instruction + * + ****************************************************************************/ + +void arm_syscall(uint32_t *regs) +{ + _alert("Syscall from 0x%" PRIx32 "\n", regs[REG_PC]); + CURRENT_REGS = regs; + PANIC(); +} diff --git a/arch/arm/src/tlsr82/tc32/tc32_udelay.c b/arch/arm/src/tlsr82/tc32/tc32_udelay.c new file mode 100644 index 0000000000000..c109314847424 --- /dev/null +++ b/arch/arm/src/tlsr82/tc32/tc32_udelay.c @@ -0,0 +1,57 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tc32/tc32_udelay.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include "tlsr82_timer.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_udelay + * + * Description: + * Delay inline for the requested number of microseconds. NOTE: Because + * of all of the setup, several microseconds will be lost before the actual + * timing loop begins. Thus, the delay will always be a few microseconds + * longer than requested. + * + * *** NOT multi-tasking friendly *** + * + ****************************************************************************/ + +void locate_code(".ram_code") up_udelay(useconds_t microseconds) +{ + uint32_t current = SYSTIMER_TICK_REG; + while ((SYSTIMER_TICK_REG - current) <= (microseconds * 16)); +} diff --git a/arch/arm/src/tlsr82/tlsr82_adc.c b/arch/arm/src/tlsr82/tlsr82_adc.c new file mode 100644 index 0000000000000..b2687845d89f9 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_adc.c @@ -0,0 +1,940 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_adc.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "tlsr82_adc.h" +#include "tlsr82_gpio.h" +#include "tlsr82_analog.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* ADC calibration max count */ + +#ifndef MIN +# define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef MAX +# define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* ADC Private Data */ + +struct adc_chan_s +{ + uint32_t ref; /* Reference count */ + const uint8_t channel; /* Channel number */ + const uint32_t pinset; /* GPIO pin number */ + const struct adc_callback_s *cb; /* Upper driver callback */ +}; + +/* ADC Config data */ + +struct adc_config_s +{ + uint32_t vref; /* The reference voltage (mV) */ + bool calied; /* Calibration finished or not */ + const bool cali; /* Calibration enable/disable, default enable */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void tlsr82_adc_reset(void); +static void tlsr82_adc_power_ctrl(bool enable); +static void tlsr82_adc_clk_ctrl(bool enable); +static void tlsr82_adc_set_sampleclk(uint32_t clk); +static void tlsr82_adc_config(uint32_t cfg); +static void tlsr82_adc_pin_config(uint32_t pinset); +static void tlsr82_adc_chan_config(uint32_t pinset); + +static void adc_dump(const char *msg); +static int adc_bind(struct adc_dev_s *dev, + const struct adc_callback_s *callback); +static void adc_reset(struct adc_dev_s *dev); +static int adc_setup(struct adc_dev_s *dev); +static void adc_shutdown(struct adc_dev_s *dev); +static void adc_rxint(struct adc_dev_s *dev, bool enable); +static int adc_ioctl(struct adc_dev_s *dev, int cmd, unsigned long arg); +static void adc_read_work(struct adc_dev_s *dev); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* ADC interface operations */ + +static const struct adc_ops_s g_adcops = +{ + .ao_bind = adc_bind, + .ao_reset = adc_reset, + .ao_setup = adc_setup, + .ao_shutdown = adc_shutdown, + .ao_rxint = adc_rxint, + .ao_ioctl = adc_ioctl, +}; + +static struct adc_chan_s g_adc_chan0 = +{ + .channel = 0, + .pinset = GPIO_PIN_PB2, +}; + +static struct adc_dev_s g_adc_chan0_dev = +{ + .ad_ops = &g_adcops, + .ad_priv = &g_adc_chan0, +}; + +static sem_t g_sem_excl = SEM_INITIALIZER(1); + +/* ADC config */ + +static struct adc_config_s g_adc_config = +{ + .vref = 1175, /* Default reference voltage is 1175mV (1.2V) */ + .cali = true, /* Default calibration switch is enable */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_adc_reset + * + * Description: + * Reset the adc, reconfig the adc. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void tlsr82_adc_reset(void) +{ + BM_SET(RESET_RST1_REG, RESET_RST1_ADC); + BM_CLR(RESET_RST1_REG, RESET_RST1_ADC); +} + +/**************************************************************************** + * Name: tlsr82_adc_power_ctrl + * + * Description: + * Enable/Disable the ADC power, the power should be power up before + * config the adc. + * + * Input Parameters: + * enable - true : power up + * false: power down + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void tlsr82_adc_power_ctrl(bool enable) +{ + tlsr82_analog_write(ADC_PAG_CTRL_REG, + (tlsr82_analog_read(ADC_PAG_CTRL_REG) & + (~ADC_POWER_MASK)) | + (!enable) << ADC_POWER_SHIFT); +} + +/**************************************************************************** + * Name: tlsr82_adc_clk_ctrl + * + * Description: + * Enable/Disable the ADC clock. + * + * Input Parameters: + * enable - true : enable adc clock + * false: disable adc clock + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void tlsr82_adc_clk_ctrl(bool enable) +{ + if (enable) + { + tlsr82_analog_write(ADC_CLK_REG, + tlsr82_analog_read(ADC_CLK_REG) | + ADC_CLK_24M_EN); + } + else + { + tlsr82_analog_write(ADC_CLK_REG, + tlsr82_analog_read(ADC_CLK_REG) & + (~ADC_CLK_24M_EN)); + } +} + +/**************************************************************************** + * Name: tlsr82_adc_config + * + * Description: + * Config the adc, after this, the adc can start sample. + * + * Input Parameters: + * cfg - adc pinset + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void tlsr82_adc_config(uint32_t cfg) +{ + /* Follow the datasheet and sdk adc_vbat_init() to config the adc */ + + /* Enable misc chanel and set totaol length for sampling state be 2 */ + + tlsr82_analog_write(ADC_CTRL0_REG, ADC_CTRL0_CHANEN_ENABLE | + (2 << ADC_CTRL0_SAMPLEN_SHIFT)); + + /* Set the max capture time and max set time, time = count / 24Mhz + * r_max_s (Set) : ADC_SAMP3_REG_0xf1<3:0> + * r_max_mc(Capture) : ADC_SAMP3_REG_0xf1<7:6>, ADC_SAMP1_REG_0xef<7:0> + * Here, set r_max_s = 10 (0.417us), r_max_mc = 240 (10us) + * So, total duration = 10.417us, sample frequency = 24Mhz / 250 = 96Khz + */ + + tlsr82_analog_write(ADC_SAMP1_REG, 240 & 0xff); + tlsr82_analog_write(ADC_SAMP3_REG, ((240 >> 8) << 6) | (10 & 0xff)); + + /* Divider select OFF */ + + tlsr82_analog_modify(ADC_DIVIDER_REG, ADC_DIVIDER_SEL_MASK, + ADC_DIVIDER_SEL_OFF); + + /* Set the adc differential channel */ + + tlsr82_adc_chan_config(cfg); + + /* Enable the Different input mode */ + + tlsr82_analog_modify(ADC_MODE_REG, ADC_MODE_INPUT_MASK, + ADC_MODE_INPUT_DIFF); + + /* Reference voltage select, 1.2V */ + + tlsr82_analog_modify(ADC_VREF_REG, ADC_VREF_MASK, ADC_VREF_1P2V); + + /* Adc resolution select, 14bit */ + + tlsr82_analog_modify(ADC_MODE_REG, ADC_MODE_RES_MASK, + ADC_MODE_RES_14BIT); + + /* Adc sample cycle number, 6 */ + + tlsr82_analog_modify(ADC_SAMP0_REG, ADC_SAMP0_CYCLE_MASK, + ADC_SAMP0_CYCLE_6); + + /* Adc pre-scale select, 1/8 + * When pre-scaling is 1 , the ADC_DIVIDER_REG_0xf9 <4:5> must be 0 + * When pre-scaling is 1/8, the ADC_DIVIDER_REG_0xf9 <4> must be 1 + */ + + tlsr82_analog_modify(ADC_SCALE_REG, ADC_SCALE_MASK, ADC_SCALE_1F8); + tlsr82_analog_modify(ADC_DIVIDER_REG, 0, (0x1 << 4)); +} + +/**************************************************************************** + * Name: tlsr82_adc_pin_config + * + * Description: + * Configure the the input pin as adc function, this function should be + * called before used this pin as adc. + * + * Input Parameters: + * pinset - adc pinset + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void tlsr82_adc_pin_config(uint32_t pinset) +{ + uint32_t cfg = GPIO_CFG2PIN(pinset); + + GPIO_SET_AS_GPIO(GPIO_GET(GROUP, cfg), GPIO_GET(PIN, cfg)); + + /* Vbat mode pin config, disable input, enable output, output set high */ + + tlsr82_gpio_input_ctrl(cfg, false); + + tlsr82_gpio_output_ctrl(cfg, true); + + tlsr82_gpiowrite(cfg, true); + + /* Base mode pin config, diable input, disable output, output set low */ + + /* nothing */ +} + +/**************************************************************************** + * Name: tlsr82_adc_chan_config + * + * Description: + * Configure the the input pin as the adc channel input, tlsr82 only have + * one adc conversion channel. + * + * Input Parameters: + * pinset - adc pinset + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void tlsr82_adc_chan_config(uint32_t pinset) +{ + uint16_t pinnum = GPIO_PIN2NUM(pinset); + uint16_t pinadc; + + /* Convert the gpio pin index to adc register defined pin index */ + + if (pinnum >= 8 && pinnum <= 15) + { + /* PB0 ~ PB7 */ + + pinadc = pinnum - 7; + } + else if (pinnum >= 20 && pinnum <= 21) + { + /* PC4 ~ PC5 */ + + pinadc = pinnum - 11; + } + else + { + aerr("Adc pin number error, pinnum=%u\n", pinnum); + return; + } + + /* Config the positive and negative input, here, the negative input + * is always configured to GND (0x0f). + */ + + tlsr82_analog_write(ADC_CHAN_REG, (pinadc << 4) | 0x0f); +} + +/**************************************************************************** + * Name: read_efuse + * + * Description: + * Read Efuse data. + * + * Input Parameters: + * addr - register address + * b_off - bit offset + * b_size - bit size + * + * Returned Value: + * Efuse data. + * + ****************************************************************************/ + +static uint32_t read_efuse(uint32_t addr, uint32_t b_off, uint32_t b_size) +{ + uint32_t data; + uint32_t regval; + uint32_t shift = 32 - b_size; + uint32_t mask = UINT32_MAX >> shift; + uint32_t res = b_off % 32; + uint32_t regaddr = addr + (b_off / 32 * 4); + + regval = getreg32(regaddr); + data = regval >> res; + if (res <= shift) + { + data &= mask; + } + else + { + shift = 32 - res; + + regval = getreg32(regaddr + 4); + data |= (regval & (mask >> shift)) << shift; + } + + return data; +} + +/**************************************************************************** + * Name: adc_dump + * + * Description: + * Dump all the adc register value. + * + * Input Parameters: + * msg - Message need to print. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void adc_dump(const char *msg) +{ + if (msg) + { + ainfo("%s, dump all adc regs:\n", msg); + } + else + { + ainfo("Dump all adc regs:\n"); + } + + ainfo("ADC_VREF_REG : addr=0x%x, val=0x%x\n", + ADC_VREF_REG, tlsr82_analog_read(ADC_VREF_REG)); + ainfo("ADC_CHAN_REG : addr=0x%x, val=0x%x\n", + ADC_CHAN_REG, tlsr82_analog_read(ADC_CHAN_REG)); + ainfo("ADC_MODE_REG : addr=0x%x, val=0x%x\n", + ADC_MODE_REG, tlsr82_analog_read(ADC_MODE_REG)); + ainfo("ADC_SAMP0_REG : addr=0x%x, val=0x%x\n", + ADC_SAMP0_REG, tlsr82_analog_read(ADC_SAMP0_REG)); + ainfo("ADC_SAMP1_REG : addr=0x%x, val=0x%x\n", + ADC_SAMP1_REG, tlsr82_analog_read(ADC_SAMP1_REG)); + ainfo("ADC_SAMP2_REG : addr=0x%x, val=0x%x\n", + ADC_SAMP2_REG, tlsr82_analog_read(ADC_SAMP2_REG)); + ainfo("ADC_SAMP3_REG : addr=0x%x, val=0x%x\n", + ADC_SAMP3_REG, tlsr82_analog_read(ADC_SAMP3_REG)); + ainfo("ADC_CTRL0_REG : addr=0x%x, val=0x%x\n", + ADC_CTRL0_REG, tlsr82_analog_read(ADC_CTRL0_REG)); + ainfo("ADC_CTRL1_REG : addr=0x%x, val=0x%x\n", + ADC_CTRL1_REG, tlsr82_analog_read(ADC_CTRL1_REG)); + ainfo("ADC_CLKDIV_REG : addr=0x%x, val=0x%x\n", + ADC_CLKDIV_REG, tlsr82_analog_read(ADC_CLKDIV_REG)); + ainfo("ADC_STATUS_REG : addr=0x%x, val=0x%x\n", + ADC_STATUS_REG, tlsr82_analog_read(ADC_STATUS_REG)); + ainfo("ADC_DATAL_REG : addr=0x%x, val=0x%x\n", + ADC_DATAL_REG, tlsr82_analog_read(ADC_DATAL_REG)); + ainfo("ADC_DATAH_REG : addr=0x%x, val=0x%x\n", + ADC_DATAH_REG, tlsr82_analog_read(ADC_DATAH_REG)); + ainfo("ADC_DIVIDER_REG : addr=0x%x, val=0x%x\n", + ADC_DIVIDER_REG, tlsr82_analog_read(ADC_DIVIDER_REG)); + ainfo("ADC_SCALE_REG : addr=0x%x, val=0x%x\n", + ADC_SCALE_REG, tlsr82_analog_read(ADC_SCALE_REG)); + ainfo("ADC_PAG_CTRL_REG : addr=0x%x, val=0x%x\n", + ADC_PAG_CTRL_REG, tlsr82_analog_read(ADC_PAG_CTRL_REG)); + ainfo("ADC_CLK_REG : addr=0x%x, val=0x%x\n", + ADC_CLK_REG, tlsr82_analog_read(ADC_CLK_REG)); +} + +/**************************************************************************** + * Name: adc_read + * + * Description: + * Start ADC sampling and read ADC value. + * + * Input Parameters: + * None + * + * Returned Value: + * Read ADC value. + * + ****************************************************************************/ + +static uint16_t adc_read(void) +{ + volatile uint8_t adc_misc_data_l; + volatile uint8_t adc_misc_data_h; + volatile uint16_t adc_misc_data; + + /* Stop the adc sample */ + + tlsr82_analog_modify(ADC_CTRL1_REG, ADC_CTRL1_SAMP_MASK, + ADC_CTRL1_SAMP_OFF); + + /* Get adc sample value */ + + adc_misc_data_l = tlsr82_analog_read(ADC_DATAL_REG); + adc_misc_data_h = tlsr82_analog_read(ADC_DATAH_REG); + + /* Restart the adc sample */ + + tlsr82_analog_modify(ADC_CTRL1_REG, ADC_CTRL1_SAMP_MASK, + ADC_CTRL1_SAMP_ON); + + /* Combine the adc sample value and process */ + + adc_misc_data = (adc_misc_data_h << 8 | adc_misc_data_l); + + if (adc_misc_data & BIT(13)) + { + /* Bit13 is the sign bit, bit13 = 1 indicates the data + * is negative. + */ + + adc_misc_data = 0; + } + else + { + /* Only get the low 13bit data */ + + adc_misc_data &= 0x1fff; + } + + return adc_misc_data; +} + +/**************************************************************************** + * Name: adc_calibrate + * + * Description: + * ADC calibration. + * + * Input Parameters: + * None + * + * Returned Value: + * None. + * + ****************************************************************************/ + +#if 0 + +static void adc_calibrate(void) +{ + uint16_t cali_val; + uint16_t adc; + uint16_t adc_max = 0; + uint16_t adc_min = UINT16_MAX; + uint32_t adc_sum = 0; + uint32_t regval; + + regval = read_efuse(ADC_CAL_BASE_REG, ADC_CAL_VER_OFF, ADC_CAL_VER_LEN); + if (regval == 1) + { + ainfo("Calibrate based on efuse data\n"); + + regval = read_efuse(ADC_CAL_BASE_REG, ADC_CAL_DATA_OFF, + ADC_CAL_DATA_LEN); + cali_val = regval + ADC_CAL_DATA_COMP; + } + else + { + ainfo("Calibrate based on GND voltage\n"); + + /* Enable Vdef */ + + rom_i2c_writereg_mask(I2C_ADC, I2C_ADC_HOSTID, + I2C_ADC1_DEF, I2C_ADC1_DEF_MSB, + I2C_ADC1_DEF_LSB, 1); + + /* Start sampling */ + + adc_samplecfg(ADC_CAL_CHANNEL); + + /* Enable internal connect GND (for calibration). */ + + rom_i2c_writereg_mask(I2C_ADC, I2C_ADC_HOSTID, + I2C_ADC1_ENCAL_GND, I2C_ADC1_ENCAL_GND_MSB, + I2C_ADC1_ENCAL_GND_LSB, 1); + + for (int i = 1; i < ADC_CAL_CNT_MAX ; i++) + { + adc_set_calibration(0); + adc = adc_read(); + + adc_sum += adc; + adc_max = MAX(adc, adc_max); + adc_min = MIN(adc, adc_min); + } + + cali_val = (adc_sum - adc_max - adc_min) / (ADC_CAL_CNT_MAX - 2); + + /* Disable internal connect GND (for calibration). */ + + rom_i2c_writereg_mask(I2C_ADC, I2C_ADC_HOSTID, + I2C_ADC1_ENCAL_GND, + I2C_ADC1_ENCAL_GND_MSB, + I2C_ADC1_ENCAL_GND_LSB, 0); + } + + ainfo("calibration value: %" PRIu16 "\n", cali_val); + + /* Set final calibration parameters */ + + adc_set_calibration(cali_val); + + /* Set calibration digital parameters */ + + regval = read_efuse(ADC_CAL_BASE_REG, ADC_CAL_VOL_OFF, ADC_CAL_VOL_LEN); + if (regval & BIT(ADC_CAL_VOL_LEN - 1)) + { + g_cal_digit = 2000 - (regval & ~(BIT(ADC_CAL_VOL_LEN - 1))); + } + else + { + g_cal_digit = 2000 + regval; + } +} + +#endif + +/**************************************************************************** + * Name: adc_read_work + * + * Description: + * Read ADC value and pass it to up. + * + * Input Parameters: + * dev - ADC device pointer + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void adc_read_work(struct adc_dev_s *dev) +{ + int ret; + uint32_t value; + int32_t adc; + struct adc_chan_s *priv = (struct adc_chan_s *)dev->ad_priv; + + ret = sem_wait(&g_sem_excl); + if (ret < 0) + { + aerr("Failed to wait sem ret=%d\n", ret); + return; + } + + tlsr82_adc_chan_config(priv->pinset); + + /* Dump adc register for debug */ + + adc_dump("adc_read_work"); + + value = adc_read(); + + /* Transfer the adc count into voltage (mV) + * ADC resolution is 14bit, bit13 is a signed bit and we set the + * negative input be gnd, so the actual adc resolution is 13bit. + */ + + adc = (value * g_adc_config.vref * 8) >> 13; + + /* Calibration */ + + priv->cb->au_receive(dev, priv->channel, adc); + + ainfo("channel: %" PRIu8 ", voltage: %" PRIu32 " mV\n", priv->channel, + adc); + + sem_post(&g_sem_excl); +} + +/**************************************************************************** + * Name: adc_bind + * + * Description: + * Bind the upper-half driver callbacks to the lower-half implementation. + * This must be called early in order to receive ADC event notifications. + * + ****************************************************************************/ + +static int adc_bind(struct adc_dev_s *dev, + const struct adc_callback_s *callback) +{ + struct adc_chan_s *priv = (struct adc_chan_s *)dev->ad_priv; + + DEBUGASSERT(priv != NULL); + + ainfo("channel: %" PRIu8 "\n", priv->channel); + + priv->cb = callback; + + return OK; +} + +/**************************************************************************** + * Name: adc_reset + * + * Description: + * Reset the ADC device. Called early to initialize the hardware. + * This is called, before adc_setup() and on error conditions. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static void adc_reset(struct adc_dev_s *dev) +{ + irqstate_t flags; + struct adc_chan_s *priv = (struct adc_chan_s *)dev->ad_priv; + + ainfo("channel: %" PRIu8 "\n", priv->channel); + + flags = enter_critical_section(); + + /* Do nothing if ADC instance is currently in use */ + + if (priv->ref > 0) + { + goto out; + } + + /* Reset ADC hardware */ + + tlsr82_adc_power_ctrl(true); + + tlsr82_adc_reset(); + + tlsr82_adc_clk_ctrl(false); + +out: + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: adc_setup + * + * Description: + * Configure the ADC. This method is called the first time that the ADC + * device is opened. This will occur when the port is first opened. + * This setup includes configuring. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static int adc_setup(struct adc_dev_s *dev) +{ + int ret; + uint32_t regval; + struct adc_chan_s *priv = (struct adc_chan_s *)dev->ad_priv; + + ainfo("channel: %" PRIu8 "\n", priv->channel); + + /* Do nothing when the ADC device is already set up */ + + if (priv->ref > 0) + { + priv->ref++; + return OK; + } + + /* Enable ADC clock */ + + tlsr82_adc_clk_ctrl(true); + + /* Config ADC hardware (Calibration and gpio) */ + + ainfo("pin: 0x%" PRIx32 "\n", priv->pinset); + + tlsr82_adc_config(priv->pinset); + + /* The ADC device is ready */ + + priv->ref++; + + return OK; +} + +/**************************************************************************** + * Name: adc_rxint + * + * Description: + * Call to enable or disable RX interrupts. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static void adc_rxint(struct adc_dev_s *dev, bool enable) +{ + UNUSED(dev); + UNUSED(enable); + + return -ENOTTY; +} + +/**************************************************************************** + * Name: adc_ioctl + * + * Description: + * All ioctl calls will be routed through this method. + * + * Input Parameters: + * dev - pointer to device structure used by the driver + * cmd - command + * arg - arguments passed with command + * + * Returned Value: + * + ****************************************************************************/ + +static int adc_ioctl(struct adc_dev_s *dev, int cmd, unsigned long arg) +{ + int ret; + struct adc_chan_s *priv = (struct adc_chan_s *)dev->ad_priv; + + ainfo("channel: %" PRIu8 " cmd=%d\n", priv->channel, cmd); + + switch (cmd) + { + case ANIOC_TRIGGER: + { + /* Start sampling and read ADC value here */ + + adc_read_work(dev); + ret = OK; + } + break; + + case ANIOC_GET_NCHANNELS: + { + /* Return the number of configured channels */ + + ret = 1; + } + break; + + default: + { + aerr("ERROR: Unknown cmd: %d\n", cmd); + ret = -ENOTTY; + } + break; + } + + return ret; +} + +/**************************************************************************** + * Name: adc_shutdown + * + * Description: + * Disable the ADC. This method is called when the ADC device is closed. + * This method reverses the operation the setup method. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static void adc_shutdown(struct adc_dev_s *dev) +{ + struct adc_chan_s *priv = (struct adc_chan_s *)dev->ad_priv; + + ainfo("channel: %" PRIu8 "\n", priv->channel); + + /* Decrement count only when ADC device is in use */ + + if (priv->ref > 0) + { + priv->ref--; + + /* Shutdown the ADC device only when not in use */ + + if (priv->ref == 0) + { + /* Disable ADC clock */ + + tlsr82_adc_clk_ctrl(false); + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_adc_init + * + * Description: + * Initialize the ADC. + * + * Input Parameters: + * channel - ADC channel number + * + * Returned Value: + * ADC device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +int tlsr82_adc_init(const char *devpath, int miror) +{ + int ret = OK; + struct adc_dev_s *dev; + + ainfo("ADC channel: %" PRIu8 "\n", miror); + + switch (miror) + { + case 0: + dev = &g_adc_chan0_dev; + break; + + default: + { + aerr("ERROR: No ADC interface defined\n"); + return -ENOTTY; + } + } + + ret = adc_register(devpath, dev); + if (ret < 0) + { + aerr("Adc register fail, devpath=%s, ret=%d\n", devpath, ret); + } + + return ret; +} diff --git a/arch/arm/src/tlsr82/tlsr82_adc.h b/arch/arm/src/tlsr82/tlsr82_adc.h new file mode 100644 index 0000000000000..ea42fe60adeaa --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_adc.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_adc.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_TLSR82_ADC_H +#define __ARCH_ARM_SRC_TLSR82_TLSR82_ADC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "hardware/tlsr82_adc.h" + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_adc_init + ****************************************************************************/ + +int tlsr82_adc_init(const char *devpath, int miror); + +#endif /* __ARCH_ARM_SRC_TLSR82_TLSR82_ADC_H */ diff --git a/arch/arm/src/tlsr82/tlsr82_analog.c b/arch/arm/src/tlsr82/tlsr82_analog.c new file mode 100644 index 0000000000000..f8b69e5ce55d9 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_analog.c @@ -0,0 +1,181 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_analog.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include + +#include "hardware/tlsr82_register.h" +#include "hardware/tlsr82_analog.h" +#include "tlsr82_analog.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ANALOG_BUSY BIT(0) +#define ANALOG_RSV BIT(4) +#define ANALOG_RW BIT(5) +#define ANALOG_START BIT(6) +#define ANALOG_CYC BIT(7) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_analog_wait + * + * Description: + * Wait until the analog quit from busy state + * + * Input Parameters: + * void + * + * Returned Value: + * void + * + ****************************************************************************/ + +static inline void tlsr82_analog_wait(void) +{ + while (ANALOG_CTRL_REG & ANALOG_BUSY); +} + +/**************************************************************************** + * Name: tlsr82_analog_read + * + * Description: + * Read the analog register value at address + * + * Input Parameters: + * addr - the address of analog register that read + * + * Returned Value: + * read value + * + ****************************************************************************/ + +uint8_t locate_code(".ram_code") tlsr82_analog_read(uint8_t addr) +{ + irqstate_t flags; + uint8_t data; + + flags = enter_critical_section(); + + /* Read analog address addr */ + + ANALOG_ADDR_REG = addr; + ANALOG_CTRL_REG = ANALOG_START; + + /* Wait until the read finish */ + + tlsr82_analog_wait(); + + /* Get the data and clear the analog contrl register */ + + data = ANALOG_DATA_REG; + ANALOG_CTRL_REG = 0; + + leave_critical_section(flags); + return data; +} + +/**************************************************************************** + * Name: tlsr82_analog_read + * + * Description: + * Write the analog register value at address + * + * Input Parameters: + * addr - the address of analog register that write + * val - the write value + * + * Returned Value: + * void + * + ****************************************************************************/ + +void locate_code(".ram_code") tlsr82_analog_write(uint8_t addr, uint8_t val) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + /* Set the write address and value */ + + ANALOG_ADDR_REG = addr; + ANALOG_DATA_REG = val; + ANALOG_CTRL_REG = (ANALOG_START | ANALOG_RW); + + /* Wait until the write finish */ + + tlsr82_analog_wait(); + + /* Clear the analog contrl register */ + + ANALOG_CTRL_REG = 0; + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: tlsr82_analog_modify + * + * Description: + * Modity the value at + * + * Input Parameters: + * addr - the address of analog register that write + * val - the write value + * mask - mask of the modified value + * shift - modified value shift + * + * Returned Value: + * void + * + ****************************************************************************/ + +void locate_code(".ram_code") tlsr82_analog_modify(uint8_t addr, + uint8_t mask, + uint8_t val) +{ + tlsr82_analog_write(addr, (tlsr82_analog_read(addr) & (~mask)) | val); +} diff --git a/arch/arm/src/tlsr82/tlsr82_analog.h b/arch/arm/src/tlsr82/tlsr82_analog.h new file mode 100644 index 0000000000000..6a0397c376a1b --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_analog.h @@ -0,0 +1,54 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_analog.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_TLSR82_ANALOG_H +#define __ARCH_ARM_SRC_TLSR82_TLSR82_ANALOG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_analog_read + ****************************************************************************/ + +uint8_t locate_code(".ram_code") tlsr82_analog_read(uint8_t addr); + +/**************************************************************************** + * Name: tlsr82_analog_write + ****************************************************************************/ + +void locate_code(".ram_code") tlsr82_analog_write(uint8_t addr, uint8_t val); + +/**************************************************************************** + * Name: tlsr82_analog_modify + ****************************************************************************/ + +void locate_code(".ram_code") tlsr82_analog_modify(uint8_t addr, + uint8_t mask, + uint8_t val); + +#endif /* __ARCH_ARM_SRC_TLSR82_TLSR82_ANALOG_H */ diff --git a/arch/arm/src/tlsr82/tlsr82_clock.c b/arch/arm/src/tlsr82/tlsr82_clock.c new file mode 100644 index 0000000000000..cb923bd33ad41 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_clock.c @@ -0,0 +1,113 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_clock.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include + +#include "tlsr82_clock.h" +#include "tlsr82_analog.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MCU_CORE_B87 1 +#define SYSCLK_RC_CLOCK_EN 0 + +#define CLOCK_SYS_CLOCK_HZ CPU_CLK + +#if (CLOCK_SYS_CLOCK_HZ == 12000000) +# define SYS_CLK CLK_SYS_12M_CRYSTAL +#elif (CLOCK_SYS_CLOCK_HZ == 16000000) +# define SYS_CLK CLK_SYS_16M_CRYSTAL +#elif (CLOCK_SYS_CLOCK_HZ == 24000000) +# define SYS_CLK CLK_SYS_24M_CRYSTAL +#elif ((CLOCK_SYS_CLOCK_HZ == 32000000) && (MCU_CORE_B85 || MCU_CORE_B87)) +# define SYS_CLK CLK_SYS_32M_CRYSTAL +#elif ((CLOCK_SYS_CLOCK_HZ == 48000000) && (MCU_CORE_B85 || MCU_CORE_B87)) +# define SYS_CLK CLK_SYS_48M_CRYSTAL +#else +# error "sys clock error or undefined" +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +void clock_rc24m_init(void) +{ + uint8_t cap; + + tlsr82_analog_write(0xc8, 0x80); + + tlsr82_analog_write(0x30, tlsr82_analog_read(0x30) | BIT(7)); + + tlsr82_analog_write(0xc7, 0x0e); + tlsr82_analog_write(0xc7, 0x0f); + while ((tlsr82_analog_read(0xcf) & 0x80) == 0); + + /* Write 24m cap into manual register */ + + cap = tlsr82_analog_read(0xcb); + tlsr82_analog_write(0x33, cap); + + tlsr82_analog_write(0x30, tlsr82_analog_read(0x30) & (~BIT(7))); + + tlsr82_analog_write(0xc7, 0x0e); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void tlsr82_clock_init(void) +{ + CLK_SYS_SEL = (uint8_t)SYS_CLK; + +#if (SYSCLK_RC_CLOCK_EN) + if (SYS_CLK < SYS_CLK_RC_THRES) + { + clock_rc_set(SYS_CLK); + } +#endif + + clock_rc24m_init(); +} diff --git a/arch/arm/src/tlsr82/tlsr82_clock.h b/arch/arm/src/tlsr82/tlsr82_clock.h new file mode 100644 index 0000000000000..7da9f7003cfb6 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_clock.h @@ -0,0 +1,69 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_clock.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_TLSR82_CLOCK_H +#define __ARCH_ARM_SRC_TLSR82_TLSR82_CLOCK_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" + +#include "hardware/tlsr82_clock.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void tlsr82_clock_init(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_TLSR82_TLSR82_SPI_CONSOLE_H */ diff --git a/arch/arm/src/tlsr82/tlsr82_cpu.c b/arch/arm/src/tlsr82/tlsr82_cpu.c new file mode 100644 index 0000000000000..f064aa92e231d --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_cpu.c @@ -0,0 +1,306 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_cpu.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include + +#include "tlsr82_cpu.h" +#include "tlsr82_analog.h" +#include "tlsr82_clock.h" +#include "tlsr82_gpio.h" +#include "tlsr82_timer.h" +#include "hardware/tlsr82_dma.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#define XTAL_READY_CHECK_TIMING_OPTIMIZE 1 +#define BLC_PM_DEEP_RETENTION_MODE_EN 0 + +void locate_code (".ram_code") tlsr82_pm_wait_bbpll_done(void) +{ + volatile uint8_t i; + uint8_t j; + uint8_t ana_81 = tlsr82_analog_read(0x81); + + tlsr82_analog_write(0x81, ana_81 | BIT (6)); + for (j = 0; j < 3; j++) + { + /* Delay about 20us */ + + for (i = 0; i < 30; i++) + { + asm("tnop"); + } + + if (BIT (5) == (tlsr82_analog_read(0x88) & BIT (5))) + { + tlsr82_analog_write(0x81, ana_81 & 0xbf); + break; + } + else + { + if (j == 0) + { + tlsr82_analog_write(0x01, 0x4e); + } + else if (j == 1) + { + tlsr82_analog_write(0x01, 0x4b); + } + else + { + tlsr82_analog_write(0x81, ana_81 & 0xbf); + } + } + } +} + +void tlsr82_cpu_wakeup_init(power_mode_t power_mode, xtal_t xtal) +{ + /* This code strictly follow the telink code, just modity the comment */ + + /* poweron_default : 0x7c -> 0x00 + * poweron_default : 0xff -> 0x00 + * poweron_default : 0xcf -> 0xc8 + * <7> : mcic1,R default:1 + * <6> : risc1,R default:1 + * <3> : trng default:1 + */ + + write_reg8(0x60, 0x00); + write_reg8(0x61, 0x00); + write_reg8(0x62, 0x08); + + /* poweron_default : 0x83 -> 0xff + * poweron_default : 0x00 -> 0x9f + * <5/6> : undefined, default:0 + */ + + write_reg8(0x63, 0xff); + write_reg8(0x64, 0xff); + + /* poweron_default : 0x30 -> 0x37 + * <0> : aif -> disable 32k for qdec + * <5/6> : undefined, default:0 + */ + + write_reg8(0x65, 0xf7); + + /* when load code twice without power down dut, dut will + * use crystal clock in here, xo_quick_settle manual mode + * need to use in RC colck. + * poweron_default : set RC clock as system clock. + */ + + write_reg8(0x66, 0x06); + + /* poweron_default : 0xcf -> 0xce + * <0> : power on bbpll LDO + * <4> : power on otp LDO + */ + + tlsr82_analog_write(0x06, 0xce); + + /* xo_quict_settle with auto will cause the pragram crash + * in high temperature, must be set to manual mode. + * (add by Yi Bao, confirmed by wenfeng 20190911) + */ + + unsigned char ana_2c = tlsr82_analog_read(0x2c); + unsigned char ana_05 = tlsr82_analog_read(0x05); + + /* 0x2c<5>: xo_quick_rst + * <5> 1b'1: xtal 24M quick settle count + * 0x05<3>: 24M_xtl_pd + * <3> 1b'0 : Power up 24MHz XTL oscillator + * <3> 1b'1 : Power down 24MHz XTL oscillator + */ + + tlsr82_analog_write(0x2c, ana_2c | 0x20); + tlsr82_analog_write(0x2c, ana_2c & 0xdf); + tlsr82_analog_write(0x05, ana_05 | 0x08); + tlsr82_analog_write(0x05, ana_05 & 0xf7); + + /* poweron_default: 0x05 -> 0x25 + * <3:0>: bbpll setting + * <5>: enable 48M clock to digital core + * <6>: enable signal of 24M clock to sar + */ + + tlsr82_analog_write(0x82, 0x65); + + /* poweron_default: 0x07 -> 0x80 + * <0>: power on baseband + * <1>: power on usb + * <2>: power on audio + * <7>: enable change power sequence clk + */ + + tlsr82_analog_write(0x34, 0x80); + + /* When using the BDT tool to download a program through USB, + * if the dp pull-up is turned off, the device will be disconnected, + * so the dp pull-up is set to be keep, modify by kaixin(2019.12.27). + */ + + /* default: 0x7b + * <7>: enable_b signal of 1.5K pullup resistor for DP PAD--keep + * <6>: enable signal of 1M pullup resistor for mscn PAD, avoid current + * leakage 1->0 + * <5:4>: reference scale select 11->11 + * <1:0>: power on native 1.8v/1.4v 11->00 + */ + + tlsr82_analog_write(0x0b, (tlsr82_analog_read(0x0b) & 0x80) | 0x38); + + /* poweron_default: 0x00 + * <1> set 1: reg_xo_en_clk_ana_ana, to enable external 24M crystal + */ + + tlsr82_analog_write(0x8c, 0x02); + + /* poweron_default: 0x18 + * <7> MSB of ret_ldo_trim, 0: 0.8-1.15V; 1: 0.6-0.95V + */ + + tlsr82_analog_write(0x00, tlsr82_analog_read(0x00) & 0x7f); + + /* poweron_default: 0xa4, + * <2:0> ret_ldo_trim, set 0x04: 1.00V + */ + + tlsr82_analog_write(0x02, 0xa4); + + /* pragram can crash in high temperature, + * ana_01 and pm_wait_bbpll_done() is order to solve this problem. + */ + + tlsr82_analog_write(0x01, 0x4d); + + if (xtal == EXTERNAL_XTAL_48M) + { + /* use external 48M crystal instead of external 24M crystal + * poweron_default: 0x15 + * <6>: 0 - 24M XTAL + * 1 - 48M XTAL + */ + + tlsr82_analog_write(0x2d, tlsr82_analog_read(0x2d) | BIT (6)); + } + + /* poweron_default: 0x40 + * <1:0>: 00 - LDO + * 01 - LDO_DC + * 11 - DCDC + * when use the LDO_1P4_DCDC_1P8, should use synchronize mode + * (0x0a <2>: 1-synchronize mode, 0-asynchronize mode) to avoid + * the current abnormal in A0. + */ + + tlsr82_analog_write(0x0a, power_mode); + + if (LDO_MODE != power_mode) + { + /* poweron_default: 0xc4, 1.4v voltage turn dowm 100mv */ + + tlsr82_analog_write(0x0c, 0xa4); + } + + /* poweron_default: 0x00, PA gpio wakeup disable */ + + tlsr82_analog_write(0x27, 0x00); + + /* poweron_default: 0x00 PB gpio wakeup disable */ + + tlsr82_analog_write(0x28, 0x00); + + /* poweron_default: 0x00 PC gpio wakeup disable */ + + tlsr82_analog_write(0x29, 0x00); + + /* poweron_default: 0x00 PD gpio wakeup disable */ + + tlsr82_analog_write(0x2a, 0x00); + + /* poweron_default: 0x00000000 -> 0x04040404 */ + + write_reg32(0xc40, 0x04040404); + + /* poweron_default: 0x00000000 -> 0x04040404 */ + + write_reg32(0xc44, 0x04040404); + + /* poweron_default: 0x00 -> 0x04 */ + + write_reg8(0xc48, 0x04); + + /* core_c20/c21 power on default all enable, so we disable them first, + * then if use, enable them by manual + * note that: PWM/RF Tx/RF Rx/AES code/AES dcode dma may be affected + * by this, you must handle them when initialization. + */ + + DMA_IRQ_EN_REG = 0; + DMA_IRQ_MASK_REG = 0; + GPIO_IRQ_NORMAL_ALL_REG = GPIO_IRQ_NORMAL_ALL_WAKEUP | + GPIO_IRQ_NORMAL_ALL_WAKEUP; + + /* xo_ready check should be done after Xtal manual on_off, we put it here + * to save code running time, code running time between Xtal manual on_off + * and xo_ready check can be used as Xtal be stable timimg + * 0x88<7>: xo_ready_ana + */ + + while (BIT (7) != (tlsr82_analog_read(0x88) & (BIT (7)))); + + tlsr82_pm_wait_bbpll_done(); + + /* System timer config, enable system timer and interrupt */ + + SYSTIMER_CTRL_REG |= SYSTIMER_CTRL_TIMER_EN | SYSTIMER_CTRL_CALI_EN; + SYSTIMER_IRQ_MASK_REG |= SYSTIMER_IRQ_MASK_EN; +} diff --git a/arch/arm/src/tlsr82/tlsr82_cpu.h b/arch/arm/src/tlsr82/tlsr82_cpu.h new file mode 100644 index 0000000000000..a76eef7e28bce --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_cpu.h @@ -0,0 +1,53 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_cpu.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_TLSR82_CPU_H +#define __ARCH_ARM_SRC_TLSR82_TLSR82_CPU_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +typedef enum +{ + LDO_MODE = 0x40, /* LDO mode */ + DCDC_LDO_MODE = 0x41, /* DCDC_LDO mode */ + DCDC_MODE = 0x43, /* DCDC mode (16pin chip not suported) */ +} power_mode_t; + +typedef enum +{ + EXTERNAL_XTAL_24M = 0, + EXTERNAL_XTAL_48M = 1, +} xtal_t; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void tlsr82_cpu_wakeup_init(power_mode_t power_mode, xtal_t xtal); + +#endif /* __ARCH_ARM_SRC_TLSR82_TLSR82_CPU_H */ diff --git a/arch/arm/src/tlsr82/tlsr82_flash.c b/arch/arm/src/tlsr82/tlsr82_flash.c new file mode 100644 index 0000000000000..ffba2d95dc7d3 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_flash.c @@ -0,0 +1,478 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_flash.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include +#include + +#include "hardware/tlsr82_mspi.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Manufacturer id definitions */ + +#if defined(CONFIG_ARCH_CHIP_TLSR8278) +# define FLASH_MID_GD25LD10C 0x1160c8 +# define FLASH_MID_GD25LD40C 0x1360c8 +# define FLASH_MID_GD25LD80C 0x1460c8 +# define FLASH_MID_ZB25WD10A 0x11325e +# define FLASH_MID_ZB25WD40B 0x13325e +# define FLASH_MID_ZB25WD80B 0x14325e +# define FLASH_MID_ZB25WD20A 0x12325e +#elif defined(CONFIG_ARCH_CHIP_TLSR8258) +# define FLASH_MID_ZB25WD40B 0x13325e +# define FLASH_MID_ZB25WD80B 0x14325e +# define FLASH_MID_GD25LD05C 0x1060c8 +# define FLASH_MID_GD25LD40C 0x1360c8 +# define FLASH_MID_GD25LD80C 0x1460c8 +# define FLASH_MID_GD25LE80C 0x1460c8 +# define FLASH_MID_GD25LQ80C 0x1460c8 +# define FLASH_MID_MD25D40D 0x134051 +# define FLASH_MID_P25Q40L 0x136085 +# define FLASH_MID_TH25D40LA 0x1360eb +# define FLASH_MID_TH25D40UA 0x1360eb +#endif + +/* Flash command definitions */ + +#define FLASH_INVALID_ADDR 0xffffffff + +#define FLASH_CMD_WRITE 0x02 +#define FLASH_CMD_WRITE_ENABLE 0x06 +#define FLASH_CMD_WRITE_DISABLE 0x04 +#define FLASH_CMD_WRITE_SECURITY_REG 0x42 +#define FLASH_CMD_WRITE_STATUS_LBYTE 0x01 +#define FLASH_CMD_WRITE_STATUS_HBYTE 0x31 + +#define FLASH_CMD_READ 0x03 +#define FLASH_CMD_READ_SECURITY_REG 0x48 +#define FLASH_CMD_READ_JEDEC_ID 0x9f +#define FLASH_CMD_READ_STATUS_LBYTE 0x05 +#define FLASH_CMD_READ_STATUS_HBYTE 0x35 + +#define FLASH_CMD_ERASE_SECTOR 0x20 +#define FLASH_CMD_ERASE_SECURITY_REG 0x44 + +/* Read the flash uniqe id command + * FLASH_CMD_READ_UID1: GD_PUYA_ZB_TH + * FLASH_CMD_READ_UID2: XTX + */ + +#define FLASH_CMD_READ_UID1 0x4b +#define FLASH_CMD_READ_UID2 0x5a + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const uint8_t g_invalid_uid[16] = +{ + 0x51, 0x01, 0x51, 0x01, + 0x51, 0x01, 0x51, 0x01, + 0x51, 0x01, 0x51, 0x01, + 0x51, 0x01, 0x51, 0x01, +}; + +#if defined(CONFIG_ARCH_CHIP_TLSR8278) +static const uint32_t g_support_mid[] = +{ + 0x1160c8, /* FLASH_MID_GD25LD10C */ + 0x1360c8, /* FLASH_MID_GD25LD40C */ + 0x1460c8, /* FLASH_MID_GD25LD80C */ + 0x11325e, /* FLASH_MID_ZB25WD10A */ + 0x12325e, /* FLASH_MID_ZB25WD20A */ + 0x13325e, /* FLASH_MID_ZB25WD40B */ + 0x14325e, /* FLASH_MID_ZB25WD80B */ +}; +#elif defined(CONFIG_ARCH_CHIP_TLSR8258) +static const uint32_t g_support_mid[] = +{ + 0x0013325e, /* FLASH_MID_ZB25WD40B */ + 0x0014325e, /* FLASH_MID_ZB25WD80B */ + 0x001060c8, /* FLASH_MID_GD25LD05C */ + 0x001360c8, /* FLASH_MID_GD25LD40C */ + 0x001460c8, /* FLASH_MID_GD25LD80C, FLASH_MID_GD25LE80C */ + 0x011460c8, /* FLASH_MID_GD25LQ80C */ + 0x00134051, /* FLASH_MID_MD25D40D */ + 0x00136085, /* FLASH_MID_P25Q40L */ + 0x001360eb, /* FLASH_MID_TH25D40LA, FLASH_MID_TH25D40UA */ +}; +#endif + +static const uint32_t g_support_mid_num = + sizeof(g_support_mid) / sizeof(uint32_t); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: flash_send_cmd + * + * Description: + * Configurate the gpio drive strength be high/low. + * + * Input Parameters: + * cmd - GPIO config information + * + * Returned Value: + * void + * + ****************************************************************************/ + +static void locate_code(".ram_code") flash_send_cmd(uint8_t cmd) +{ + MSPI_CS_HIGH(); + up_udelay(1); + MSPI_CS_LOW(); + MSPI_WRITE(cmd); + MSPI_WAIT(); +} + +static void locate_code(".ram_code") flash_send_addr(uint32_t addr) +{ + MSPI_WRITE((uint8_t)(addr >> 16)); + MSPI_WAIT(); + + MSPI_WRITE((uint8_t)(addr >> 8)); + MSPI_WAIT(); + + MSPI_WRITE((uint8_t)(addr)); + MSPI_WAIT(); +} + +static void locate_code(".ram_code") flash_wait_done(void) +{ + int i; + + up_udelay(100); + flash_send_cmd(FLASH_CMD_READ_STATUS_LBYTE); + + for (i = 0; i < 10000000; i++) + { + MSPI_WRITE(0); + MSPI_WAIT(); + if ((MSPI_READ() & 0x01) == 0) + { + break; + } + } + + MSPI_CS_HIGH(); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_flash_read + * + * Description: + * Write data to addr + * + * Input Parameters: + * cmd - flash write command + * addr - flash write address + * buf - flash write buffer + * len - flash write buffer length + * + * Returned Value: + * void + * + ****************************************************************************/ + +void locate_code(".ram_code") tlsr82_flash_read(uint8_t cmd, uint32_t addr, + uint8_t dummy_cnt, + uint8_t *buf, uint32_t len) +{ + int i; + irqstate_t flags; + + flags = enter_critical_section(); + + flash_send_cmd(cmd); + + /* If send read address first, send the address */ + + if (addr != FLASH_INVALID_ADDR) + { + flash_send_addr(addr); + } + + /* Write dummy data, why ? */ + + for (i = 0; i < dummy_cnt; i++) + { + MSPI_WRITE(0); + MSPI_WAIT(); + } + + /* Issue clock, why ? */ + + MSPI_WRITE(0); + MSPI_WAIT(); + + /* Switch to auto mode */ + + MSPI_AUTO_MODE(); + MSPI_WAIT(); + + /* Read data */ + + for (i = 0; i < len; i++) + { + buf[i] = MSPI_READ(); + MSPI_WAIT(); + } + + /* Write finish, pull-up the cs */ + + MSPI_CS_HIGH(); + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: tlsr82_flash_write + * + * Description: + * Write data to addr + * + * Input Parameters: + * cmd - flash write command + * addr - flash write address + * buf - flash write buffer + * len - flash write buffer length + * + * Returned Value: + * void + * + ****************************************************************************/ + +void locate_code(".ram_code") tlsr82_flash_write(uint8_t cmd, uint32_t addr, + const uint8_t *buf, + uint32_t len) +{ + int i; + irqstate_t flags; + + flags = enter_critical_section(); + + flash_send_cmd(FLASH_CMD_WRITE_ENABLE); + flash_send_cmd(cmd); + + /* If send write address first, send the address */ + + if (addr != FLASH_INVALID_ADDR) + { + flash_send_addr(addr); + } + + /* Write data */ + + for (i = 0; i < len; i++) + { + MSPI_WRITE(buf[i]); + MSPI_WAIT(); + } + + /* Write finish, pull-up the cs */ + + MSPI_CS_HIGH(); + + /* Wait the flash write finish */ + + flash_wait_done(); + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: tlsr82_flash_erase_sector + * + * Description: + * Erase the section addr at + * + * Input Parameters: + * addr - flash erase address + * + * Returned Value: + * void + * + ****************************************************************************/ + +void tlsr82_flash_erase_sector(uint32_t addr) +{ + DEBUGASSERT(addr != FLASH_INVALID_ADDR); + + tlsr82_flash_write(FLASH_CMD_ERASE_SECTOR, addr, NULL, 0); +} + +/**************************************************************************** + * Name: tlsr82_flash_read_data + * + * Description: + * Read the data at address addr + * + * Input Parameters: + * addr - flash read start address + * buf - flash read buffer + * len - flash read buffer length + * + * Returned Value: + * void + * + ****************************************************************************/ + +void tlsr82_flash_read_data(uint32_t addr, uint8_t *buf, uint32_t len) +{ + tlsr82_flash_read(FLASH_CMD_READ, addr, 0, buf, len); +} + +/**************************************************************************** + * Name: tlsr82_flash_write_data + * + * Description: + * Write the data at address addr + * + * Input Parameters: + * addr - flash write start address + * buf - flash write buffer + * len - flash write buffer length + * + * Returned Value: + * void + * + ****************************************************************************/ + +void tlsr82_flash_write_data(uint32_t addr, const uint8_t *buf, uint32_t len) +{ + tlsr82_flash_write(FLASH_CMD_WRITE, addr, buf, len); +} + +/**************************************************************************** + * Name: tlsr82_flash_read_uid + * + * Description: + * Read the flash unique id + * + * Input Parameters: + * cmd - read uid command + * buf - uid read buffer + * + * Returned Value: + * void + * + ****************************************************************************/ + +void tlsr82_flash_read_uid(uint8_t cmd, uint8_t *buf) +{ + if (cmd == FLASH_CMD_READ_UID1) + { + tlsr82_flash_read(FLASH_CMD_READ_UID1, 0, 1, buf, 16); + } +} + +/**************************************************************************** + * Name: tlsr82_flash_read_mid + * + * Description: + * Read the flash chip manufacaturer ID + * + * Input Parameters: + * pmid - manufacaturer ID pointer, size 4 bytes + * puid - unique ID pointer, size 16 bytes + * + * Returned Value: + * Positive on success, negative on fail + * + ****************************************************************************/ + +int tlsr82_flash_miduid_check(uint32_t *pmid, uint8_t *puid) +{ + int i; +#ifdef CONFIG_ARCH_CHIP_TLSR8258 + uint8_t buf[4]; +#endif + + DEBUGASSERT(pmid != NULL && puid != NULL); + + /* Read the flash manufacaturer ID */ + + tlsr82_flash_read(FLASH_CMD_READ_JEDEC_ID, FLASH_INVALID_ADDR, + 0, (uint8_t *)pmid, 3); +#ifdef CONFIG_ARCH_CHIP_TLSR8258 + if (mid == FLASH_MID_GD25LE80C) + { + tlsr82_flash_read(FLASH_CMD_READ_UID2, 0, 1, buf, 4); + if ((buf[0] == 0x53) && (buf[1] == 0x46) && + (buf[2] == 0x44) && (buf[3] == 0x50)) + { + mid = 0x011460c8; + } + } +#endif + + /* Check the validation of the manufacaturer ID */ + + for (i = 0; i < g_support_mid_num; i++) + { + if (g_support_mid[i] == *pmid) + { + tlsr82_flash_read_uid(FLASH_CMD_READ_UID1, (uint8_t *)puid); + break; + } + } + + if (i == g_support_mid_num) + { + ferr("Current flash device is not supported, mid=0x%lu\n", *pmid); + return -ENOTSUP; + } + + /* Check the validation of the unique ID */ + + if (memcmp(g_invalid_uid, puid, 16) == 0) + { + ferr("Current flash no unique id\n"); + return -ENOTSUP; + } + + return OK; +} diff --git a/arch/arm/src/tlsr82/tlsr82_flash.h b/arch/arm/src/tlsr82/tlsr82_flash.h new file mode 100644 index 0000000000000..3ae53207b558f --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_flash.h @@ -0,0 +1,75 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_flash.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_TLSR82_FLASH_H +#define __ARCH_ARM_SRC_TLSR82_TLSR82_FLASH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "chip.h" + +#include "hardware/tlsr82_mspi.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void tlsr82_flash_erase_sector(uint32_t addr); +void tlsr82_flash_read_data(uint32_t addr, uint8_t *buf, uint32_t len); +void tlsr82_flash_write_data(uint32_t addr, const uint8_t *buf, + uint32_t len); +int tlsr82_flash_miduid_check(uint32_t *pmid, uint8_t *puid); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_TLSR82_TLSR82_FLASH_H */ diff --git a/arch/arm/src/tlsr82/tlsr82_flash_mtd.c b/arch/arm/src/tlsr82/tlsr82_flash_mtd.c new file mode 100644 index 0000000000000..b09f501e72842 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_flash_mtd.c @@ -0,0 +1,837 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_flash_mtd.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "hardware/tlsr82_gpio.h" +#include "tlsr82_flash.h" +#include "tlsr82_flash_mtd.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MIN(a, b) (((a) > (b)) ? (b) : (a)) + +/* Flash size deifnitions */ + +#define TLSR82_SECTOR_SHIFT 12 +#define TLSR82_SECTOR_SIZE (1 << TLSR82_SECTOR_SHIFT) +#define TLSR82_PAGE_SHIFT 8 +#define TLSR82_PAGE_SIZE (1 << TLSR82_PAGE_SHIFT) +#define TLSR82_SECTOR_NUMBER 4 + +/* Flash layout definitions */ + +#define TLSR82_START_ADDR (0) +#define TLSR82_TOTAL_SIZE (512 * 1024) + +#define TLSR82_BANKA_ADDR TLSR82_START_ADDR +#define TLSR82_BANKA_SIZE (240 * 1024) + +#define TLSR82_USR_ADDR (TLSR82_BANKA_ADDR + TLSR82_BANKA_SIZE) +#define TLSR82_USR_SIZE (12 * 1024) + +#define TLSR82_KEY_ADDR (TLSR82_USR_ADDR + TLSR82_USR_SIZE) +#define TLSR82_KEY_SIZE (4 * 1024) + +#define TLSR82_BANKB_ADDR (TLSR82_KEY_ADDR + TLSR82_KEY_SIZE) +#define TLSR82_BANKB_SIZE (240 * 1024) + +#define TLSR82_SYS_ADDR (TLSR82_BANKB_ADDR + TLSR82_BANKB_SIZE) +#define TLSR82_SYS_SIZE (16 * 1024) + +/* Flash write buffer size definitions */ + +#ifdef CONFIG_TLSR82_FLASH_WRITE_BUFFER +# define FLASH_WRITE_BUF_SIZE CONFIG_TLSR82_FLASH_WRITE_BUFFER_SIZE +#endif + +/* Flash test definitions */ + +#ifdef CONFIG_TLSR82_FLASH_TEST + +/* Flash sector erase trace macro definition */ + +#define FLASH_ERASE_TRACE_START() +#define FLASH_ERASE_TRACE_END() + +/* Flash page read/write trace macro definition */ + +#define FLASH_READ_TRACE_START() +#define FLASH_READ_TRACE_END() + +#define FLASH_WRITE_TRACE_START() +#define FLASH_WRITE_TRACE_END() + +#define FLASH_BUF_LIST16(n) \ + n , n + 1, n + 2, n + 3, n + 4, n + 5, n + 6, n + 7, \ + n + 8, n + 9, n + 10, n + 11, n + 12, n + 13, n + 14, n + 15, + +#define FLASH_BUF_LIST128(n) \ + FLASH_BUF_LIST16(n) \ + FLASH_BUF_LIST16(n + 0x10) \ + FLASH_BUF_LIST16(n + 0x20) \ + FLASH_BUF_LIST16(n + 0x30) \ + FLASH_BUF_LIST16(n + 0x40) \ + FLASH_BUF_LIST16(n + 0x50) \ + FLASH_BUF_LIST16(n + 0x60) \ + FLASH_BUF_LIST16(n + 0x70) \ + +#endif +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This type represents the state of the MTD device. + * The struct mtd_dev_s must appear at the beginning of the definition + * so that you can freely cast between pointers to struct mtd_dev_s and + * struct tlsr82_flash_dev_s. + */ + +struct tlsr82_flash_dev_s +{ + struct mtd_dev_s mtd; /* MTD interface */ + uint32_t baseaddr; /* mtd flash start address */ + uint32_t size; /* avaliable size for MTD */ + uint16_t nsectors; /* Number of erase sectors */ + uint16_t sectorsize; /* Size of one sector */ + uint16_t pagesize; /* Size of one page */ +}; + +struct tlsr82_partition_s +{ + char *path; + off_t firstblock; + off_t nblocks; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Flash mtd partition table */ + +#ifdef CONFIG_MTD_PARTITION +static const struct tlsr82_partition_s tlsr82_part_table[] = +{ + { + .path = "dev/banka", + .firstblock = TLSR82_BANKA_ADDR / TLSR82_PAGE_SIZE, + .nblocks = TLSR82_BANKA_SIZE / TLSR82_PAGE_SIZE, + }, + { + .path = "dev/usr", + .firstblock = TLSR82_USR_ADDR / TLSR82_PAGE_SIZE, + .nblocks = TLSR82_USR_SIZE / TLSR82_PAGE_SIZE, + }, + { + .path = "dev/key", + .firstblock = TLSR82_KEY_ADDR / TLSR82_PAGE_SIZE, + .nblocks = TLSR82_KEY_SIZE / TLSR82_PAGE_SIZE, + }, + { + .path = "dev/bankb", + .firstblock = TLSR82_BANKB_ADDR / TLSR82_PAGE_SIZE, + .nblocks = TLSR82_BANKB_SIZE / TLSR82_PAGE_SIZE, + }, + { + .path = "dev/sys", + .firstblock = TLSR82_SYS_ADDR / TLSR82_PAGE_SIZE, + .nblocks = TLSR82_SYS_SIZE / TLSR82_PAGE_SIZE, + } +}; +#endif + +/* Flash manufacture ID and unique ID */ + +static uint32_t g_flash_mid; +static uint8_t g_flash_uid[16]; + +/* Flash byte write buffer when enable the flash byte write buffer */ + +#ifdef CONFIG_TLSR82_FLASH_WRITE_BUFFER +static uint8_t flash_write_buffer[FLASH_WRITE_BUF_SIZE]; +#endif + +/* Flash test buffer when enable the flash test */ + +#ifdef CONFIG_TLSR82_FLASH_TEST + +static uint8_t flash_buffer[TLSR82_PAGE_SIZE] = +{ + FLASH_BUF_LIST128(0) + FLASH_BUF_LIST128(1) +}; + +static uint8_t flash_read_buffer[TLSR82_PAGE_SIZE]; +static char print_buf[128]; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Flash driver methods */ + +static int tlsr82_flash_chip_erase(struct tlsr82_flash_dev_s *priv); + +#ifdef CONFIG_TLSR82_FLASH_TEST +static void tlsr82_flash_print(const char *msg, const uint8_t *buf, + size_t len); + +static int tlsr82_flash_test(struct tlsr82_flash_dev_s *priv); +#endif + +/* MTD driver methods */ + +static int tlsr82_flash_erase (struct mtd_dev_s *dev, off_t startblock, + size_t nblocks); + +static ssize_t tlsr82_flash_bread (struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, uint8_t *buf); + +static ssize_t tlsr82_flash_bwrite(struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, const uint8_t *buf); + +static ssize_t tlsr82_flash_read (struct mtd_dev_s *dev, off_t offset, + size_t nbytes, uint8_t *buffer); + +#ifdef CONFIG_MTD_BYTE_WRITE +static ssize_t tlsr82_flash_write (struct mtd_dev_s *dev, off_t offset, + size_t nbytes, const uint8_t *buffer); +#endif + +static int tlsr82_flash_ioctl (struct mtd_dev_s *dev, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_flash_readid + ****************************************************************************/ + +static int tlsr82_flash_chip_erase(struct tlsr82_flash_dev_s *priv) +{ + int i; + uint32_t addr; + + addr = priv->baseaddr; + for (i = 0; i < priv->nsectors; i++) + { + finfo("Erase sector: %d, address: 0x%08lx\n", i, addr); + tlsr82_flash_erase_sector(addr); + addr += priv->sectorsize; + } + + return OK; +} + +/**************************************************************************** + * Name: tlsr82_flash_print + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_FLASH_TEST +static void tlsr82_flash_print(const char *msg, const uint8_t *buf, + size_t len) +{ + int i = 0; + int off = 0; + + ferr("%s\n", msg); + while (len--) + { + if (i % 16 == 0) + { + off += sprintf(&print_buf[off], "0x%08x:", i); + } + + off += sprintf(&print_buf[off], "0x%02x ", buf[i]); + i++; + + if (i % 16 == 0) + { + ferr("%s\n", print_buf); + off = 0; + } + } + + if (i % 16 != 0) + { + ferr("%s\n", print_buf); + } +} +#endif + +/**************************************************************************** + * Name: tlsr82_flash_test + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_FLASH_TEST +static int tlsr82_flash_test(struct tlsr82_flash_dev_s *priv) +{ + int ret = OK; + int npages = 0; + int i = 0; + int j = 0; + + npages = priv->nsectors * (TLSR82_SECTOR_SIZE / TLSR82_PAGE_SIZE); + + ferr("======== Flash test start ========\n"); + + /* 1. print the manufacture id and unique id */ + + ret = 0; + ferr("Flash information print:\n"); + ferr(" Flash MID: 0x%08lx\n", g_flash_mid); + ret += sprintf(&print_buf[ret], " Flash UID: "); + for (i = 1; i < 16; i++) + { + ret += sprintf(&print_buf[ret], "0x%x ", g_flash_uid[i]); + } + + ferr("%s\n", print_buf); + + ferr(" Flash Start Address: 0x%08lx\n", priv->baseaddr); + ferr(" Flash Size : 0x%08lx\n", priv->size); + ferr(" Flash Sector: %d\n", priv->nsectors); + ferr(" Flash Page : %d\n", npages); + + /* 2. erase chip and check all the erased sector, all the bit in erased + * sector should be 1. + */ + + ferr("Flash chip erase test start:\n"); + + FLASH_ERASE_TRACE_START(); + tlsr82_flash_chip_erase(priv); + FLASH_ERASE_TRACE_END(); + + for (i = 0; i < npages; i++) + { + FLASH_READ_TRACE_START(); + ret = tlsr82_flash_bread(&priv->mtd, i, 1, flash_read_buffer); + FLASH_READ_TRACE_END(); + if (ret != 1) + { + ferr(" Flash block read failed, ret=%d\n", ret); + goto errout; + } + + for (j = 0; j < TLSR82_PAGE_SIZE; j++) + { + if (flash_read_buffer[j] != 0xff) + { + ferr(" Flash erased data is not 0xff, page_i=%d, byte_j=%d," + "data=0x%x\n", i, j, flash_read_buffer[j]); + goto errout; + } + } + } + + ferr("Flach chip erase test Success.\n"); + + /* 3. Write all the flash and check result */ + + ferr("Flash page write/read test start:\n"); + tlsr82_flash_print("Write buffer data:", flash_buffer, + TLSR82_PAGE_SIZE); + for (i = 0; i < npages; i++) + { + FLASH_WRITE_TRACE_START(); + ret = tlsr82_flash_bwrite(&priv->mtd, i, 1, flash_buffer); + FLASH_WRITE_TRACE_END(); + if (ret != 1) + { + ferr(" Flash block write failed, ret=%d\n", ret); + goto errout; + } + } + + for (i = 0; i < npages; i++) + { + memset(flash_read_buffer, 0, TLSR82_PAGE_SIZE); + ret = tlsr82_flash_bread(&priv->mtd, i, 1, flash_read_buffer); + if (ret != 1) + { + ferr(" Flash block read failed, ret=%d\n", ret); + goto errout; + } + + if (memcmp(flash_read_buffer, flash_buffer, TLSR82_PAGE_SIZE) != 0) + { + ferr(" Flash write compre is not equal, page_i=%d\n", i); + tlsr82_flash_print("Write buffer data:", flash_buffer, + TLSR82_PAGE_SIZE); + tlsr82_flash_print("Read buffer data:", flash_read_buffer, + TLSR82_PAGE_SIZE); + goto errout; + } + } + + ferr("Flash page write/read test Success.\n"); + +#ifdef CONFIG_MTD_BYTE_WRITE + + /* 4. Erase chip again for byte write/read test */ + + uint32_t offset = 0; + int k; + + ferr("Erase chip for byte write test\n"); + tlsr82_flash_chip_erase(priv); + ferr("Erase chip finished\n"); + + ferr("Flash byte read/write test start\n"); + do + { + /* i = the write number, j = the flash_buffer index */ + + i = 40; + if (i + offset > priv->size) + { + i = priv->size - offset; + } + + j = offset & 128; + + FLASH_WRITE_TRACE_START(); + ret = tlsr82_flash_write(&priv->mtd, offset, i, &flash_buffer[j]); + FLASH_WRITE_TRACE_END(); + + if (ret != i) + { + ferr(" Flash byte write failed, offset: 0x%08lx, ret=%d\n", + offset, ret); + goto errout; + } + + memset(flash_read_buffer, 0, i); + + FLASH_READ_TRACE_START(); + ret = tlsr82_flash_read(&priv->mtd, offset, i, flash_read_buffer); + FLASH_READ_TRACE_END(); + + if (ret != i) + { + ferr(" Flash byte read failed, offset: 0x%08lx, ret=%d\n", + offset, ret); + goto errout; + } + + for (k = 0; k < i; k++) + { + if (flash_buffer[j + k] != flash_read_buffer[k]) + { + ferr(" Flash byte write/read compare failed\n"); + ferr(" Flash address: 0x%08lx\n", priv->baseaddr + offset); + tlsr82_flash_print("Write Data:", &flash_buffer[j], i); + tlsr82_flash_print("Read Data:", flash_read_buffer, i); + goto errout; + } + } + + offset += i; + } + while (offset < priv->size); + + ferr("Flash byte read/write test Success\n"); + +#endif + + ferr("======== Flash test Success ========\n"); + + return OK; + +errout: + ferr("Flash test Failed.\n"); + return ret; +} +#endif + +/**************************************************************************** + * Name: tlsr82_flash_erase + ****************************************************************************/ + +static int tlsr82_flash_erase(struct mtd_dev_s *dev, off_t startblock, + size_t nblocks) +{ + struct tlsr82_flash_dev_s *priv = (struct tlsr82_flash_dev_s *)dev; + size_t i; + uint32_t addr; + + finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks); + + addr = priv->baseaddr + startblock * priv->sectorsize; + for (i = 0; i < nblocks; i++) + { + tlsr82_flash_erase_sector(addr); + addr += priv->sectorsize; + } + + return (int)nblocks; +} + +/**************************************************************************** + * Name: tlsr82_flash_bread + ****************************************************************************/ + +static ssize_t tlsr82_flash_bread(struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, uint8_t *buffer) +{ + struct tlsr82_flash_dev_s *priv = (struct tlsr82_flash_dev_s *)dev; + uint32_t addr; + size_t i; + + finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks); + + addr = priv->baseaddr + startblock * priv->pagesize; + + for (i = 0; i < nblocks; i++) + { + tlsr82_flash_read_data(addr, buffer, priv->pagesize); + addr += priv->pagesize; + buffer += priv->pagesize; + } + + return nblocks; +} + +/**************************************************************************** + * Name: tlsr82_flash_bwrite + ****************************************************************************/ + +static ssize_t tlsr82_flash_bwrite(struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, const uint8_t *buffer) +{ + struct tlsr82_flash_dev_s *priv = (struct tlsr82_flash_dev_s *)dev; + uint32_t addr; + size_t i; + + finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks); + + addr = priv->baseaddr + startblock * priv->pagesize; + + for (i = 0; i < nblocks; i++) + { + tlsr82_flash_write_data(addr, buffer, priv->pagesize); + addr += priv->pagesize; + buffer += priv->pagesize; + } + + return nblocks; +} + +/**************************************************************************** + * Name: tlsr82_flash_read + ****************************************************************************/ + +static ssize_t tlsr82_flash_read(struct mtd_dev_s *dev, off_t offset, + size_t nbytes, uint8_t *buffer) +{ + struct tlsr82_flash_dev_s *priv = (struct tlsr82_flash_dev_s *)dev; + uint32_t addr; + + finfo("offset: %08lx nbytes: %d\n", (long)offset, (int)nbytes); + + addr = priv->baseaddr + offset; + + tlsr82_flash_read_data(addr, buffer, nbytes); + + finfo("return nbytes: %d\n", (int)nbytes); + return (ssize_t)nbytes; +} + +/**************************************************************************** + * Name: tlsr82_flash_write + ****************************************************************************/ + +#ifdef CONFIG_MTD_BYTE_WRITE +static ssize_t tlsr82_flash_write (struct mtd_dev_s *dev, off_t offset, + size_t nbytes, const uint8_t *buffer) +{ + struct tlsr82_flash_dev_s *priv = (struct tlsr82_flash_dev_s *)dev; + uint32_t addr; + size_t allow_len = 0; + size_t write_len = 0; + size_t len = nbytes; + + finfo("offset: %08lx nbytes: %d\n", (long)offset, (int)nbytes); + + addr = priv->baseaddr + offset; + + do + { + /* The allow length is the max allow write lentgh that not cross page */ + + allow_len = TLSR82_PAGE_SIZE - (addr & (TLSR82_PAGE_SIZE - 1)); + write_len = MIN(nbytes, allow_len); + +#ifdef CONFIG_TLSR82_FLASH_WRITE_BUFFER + + /* The write length can not be larger than FLASH_WRITE_BUF_SIZE */ + + write_len = MIN(FLASH_WRITE_BUF_SIZE, write_len); + + /* Copy the data to the buffer and write, the temporary buffer is used + * to make sure the argument buffer is not in flash. Telink flash is + * not allowed read during flash writing. + */ + + memcpy(flash_write_buffer, buffer, write_len); + tlsr82_flash_write_data(addr, flash_write_buffer, write_len); +#else + tlsr82_flash_write_data(addr, buffer, write_len); +#endif + + addr += write_len; + buffer += write_len; + nbytes -= write_len; + } + while (nbytes > 0); + + return (ssize_t)len; +} +#endif + +/**************************************************************************** + * Name: tlsr82_flash_ioctl + ****************************************************************************/ + +static int tlsr82_flash_ioctl(struct mtd_dev_s *dev, int cmd, + unsigned long arg) +{ + struct tlsr82_flash_dev_s *priv = (struct tlsr82_flash_dev_s *)dev; + int ret = -EINVAL; /* Assume good command with bad parameters */ + + finfo("cmd: %d\n", cmd); + + switch (cmd) + { + case MTDIOC_GEOMETRY: + { + struct mtd_geometry_s *geo = + (struct mtd_geometry_s *)((uintptr_t)arg); + + if (geo) + { + /* Populate the geometry structure with information need to + * know the capacity and how to access the device. + * + * NOTE: + * that the device is treated as though it where just an array + * of fixed size blocks. That is most likely not true, but + * the client will expect the device logic to do whatever is + * necessary to make it appear so. + */ + + geo->blocksize = TLSR82_PAGE_SIZE; + geo->erasesize = TLSR82_SECTOR_SIZE; + geo->neraseblocks = priv->nsectors; + ret = OK; + + finfo("blocksize: %" PRId32 " erasesize: %" PRId32 + " neraseblocks: %" PRId32 "\n", + geo->blocksize, geo->erasesize, geo->neraseblocks); + } + } + break; + + case MTDIOC_BULKERASE: + { + tlsr82_flash_chip_erase(priv); + } + break; + + default: + ret = -ENOTTY; /* Bad/unsupported command */ + break; + } + + finfo("return %d\n", ret); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_flash_initialize + * + * Description: + * Create an initialize MTD device instance for the internal FLASH. + * + * MTD devices are not registered in the file system, but are created as + * instances that can be bound to other functions (such as a block or + * character driver front end). + * + * Parameter: + * offset - offset from 0 of internal flash + * size - avaiable size for NVM + * + ****************************************************************************/ + +struct mtd_dev_s *tlsr82_flash_initialize(uint32_t offset, uint32_t size) +{ + int ret; + struct tlsr82_flash_dev_s *priv; + + /* If the mtd device address exceeded the flash address space, return + * NULL. + */ + + if ((offset + size) > (CONFIG_TLSR82_FLASH_SIZE_KB * 1024)) + { + goto errout; + } + + /* Allocate a state structure (we allocate the structure instead of using + * a fixed, static allocation so that we can handle multiple FLASH devices. + * The current implementation would handle only one FLASH part per QuadSPI + * device (only because of the QSPIDEV_FLASH(0) definition) and so would + * have to be extended to handle multiple FLASH parts on the same QuadSPI + * bus. + */ + + priv = (struct tlsr82_flash_dev_s *) + kmm_zalloc(sizeof(struct tlsr82_flash_dev_s)); + if (priv) + { + /* Initialize the allocated structure (unsupported methods were + * nullified by kmm_zalloc). + */ + + priv->mtd.erase = tlsr82_flash_erase; + priv->mtd.bread = tlsr82_flash_bread; + priv->mtd.bwrite = tlsr82_flash_bwrite; + priv->mtd.read = tlsr82_flash_read; +#ifdef CONFIG_MTD_BYTE_WRITE + priv->mtd.write = tlsr82_flash_write; +#endif + priv->mtd.ioctl = tlsr82_flash_ioctl; + priv->mtd.name = "tlsr82_flash_mtd"; + + priv->baseaddr = offset; + priv->size = size; + priv->sectorsize = TLSR82_SECTOR_SIZE; + priv->pagesize = TLSR82_PAGE_SIZE; + priv->nsectors = size >> TLSR82_SECTOR_SHIFT; + + /* Identify the FLASH chip */ + + ret = tlsr82_flash_miduid_check(&g_flash_mid, &g_flash_uid[0]); + if (ret < 0) + { + ferr("Flash mid or uid error\n"); + goto errout_with_priv; + } + } + else + { + ferr("Flash device malloc failed, size=%lu\n", + sizeof(struct tlsr82_flash_dev_s)); + goto errout; + } + +#ifdef CONFIG_TLSR82_FLASH_TEST + ret = tlsr82_flash_test(priv); + if (ret < 0) + { + ferr("Flash test failed, ret=%d\n", ret); + goto errout_with_priv; + } +#endif + + /* Return the implementation-specific state structure as the MTD device */ + + finfo("Return %p\n", priv); + return (struct mtd_dev_s *)priv; + +errout_with_priv: + kmm_free(priv); + return NULL; + +errout: + return NULL; +} + +/**************************************************************************** + * Name: tlsr82_partition_init + * + * Description: + * Register partition MTD device on the parent MTD device. + * + * Parameter: + * path - the parent mtd device path. + * + ****************************************************************************/ + +#ifdef CONFIG_MTD_PARTITION +int tlsr82_partition_init(const char *path) +{ + int ret = OK; + int num; + int i; + + num = sizeof(tlsr82_part_table) / sizeof(struct tlsr82_partition_s); + + for (i = 0; i < num; i++) + { + ret = register_mtdpartition(tlsr82_part_table[i].path, 0, path, + tlsr82_part_table[i].firstblock, + tlsr82_part_table[i].nblocks); + if (ret < 0) + { + ferr("Register mtd partition failed, path=%s, ret=%d\n", + tlsr82_part_table[i].path, ret); + break; + } + } + + return ret; +} +#endif diff --git a/arch/arm/src/tlsr82/tlsr82_flash_mtd.h b/arch/arm/src/tlsr82/tlsr82_flash_mtd.h new file mode 100644 index 0000000000000..9de0f7ece76e9 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_flash_mtd.h @@ -0,0 +1,44 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_flash_mtd.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_TLSR82_FLASH_MTD_H +#define __ARCH_ARM_SRC_TLSR82_TLSR82_FLASH_MTD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +struct mtd_dev_s *tlsr82_flash_initialize(uint32_t offset, uint32_t size); + +#ifdef CONFIG_MTD_PARTITION +int tlsr82_partition_init(const char *path); +#endif + +#endif /* __ARCH_ARM_SRC_TLSR82_TLSR82_FLASH_MTD_H */ diff --git a/arch/arm/src/tlsr82/tlsr82_gpio.c b/arch/arm/src/tlsr82/tlsr82_gpio.c new file mode 100644 index 0000000000000..5bd0a5c158e46 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_gpio.c @@ -0,0 +1,921 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_gpio.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "tlsr82_gpio.h" +#include "tlsr82_analog.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define GPIO_ENABLE 1 +#define GPIO_DISABLE 0 +#define CONFIG_GPIO_IRQ_MAX_NUM 5 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_GPIO_IRQ +struct tlsr82_gpio_irq_cb +{ + xcpt_t callback; + void *arg; + gpio_cfg_t cfg; +}; +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_GPIO_IRQ +struct tlsr82_gpio_irq_cb gpio_irq_cbs[CONFIG_GPIO_IRQ_MAX_NUM]; +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void tlsr82_gpio_ds_ctrl(gpio_cfg_t cfg, uint8_t ds); +static void tlsr82_gpio_pol_ctrl(gpio_cfg_t cfg, uint8_t pol); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_gpio_ds_ctrl + * + * Description: + * Configurate the gpio drive strength be high/low. + * + * Input Parameters: + * gpio_cfg_t - GPIO config information + * ds - 1 : high drive strength + * 0 : low drive strength + * + * Returned Value: + * void + * + ****************************************************************************/ + +static void tlsr82_gpio_ds_ctrl(gpio_cfg_t cfg, uint8_t ds) +{ + uint32_t group; + uint32_t pin; + uint32_t bit; + + DEBUGASSERT(GPIO_VALID(cfg)); + + group = (uint32_t)GPIO_GET(GROUP, cfg); + pin = (uint32_t)GPIO_GET(PIN, cfg); + bit = 1 << pin; + + if (group == GPIO_VAL(GROUP, C)) + { + if (ds) + { + tlsr82_analog_write(ANALOG_PC_DS_ADDR, + tlsr82_analog_read(ANALOG_PC_DS_ADDR) | + bit); + } + else + { + tlsr82_analog_write(ANALOG_PC_DS_ADDR, + tlsr82_analog_read(ANALOG_PC_DS_ADDR) & + (~bit)); + } + } + else + { + if (ds) + { + BM_SET(GPIO_SETTING_DS_REG(group), bit); + } + else + { + BM_CLR(GPIO_SETTING_DS_REG(group), bit); + } + } +} + +/**************************************************************************** + * Name: tlsr82_gpio_pol_ctrl + * + * Description: + * Configurate the gpio interrupt polarity (interruot trigger edge). + * + * Input Parameters: + * gpio_cfg_t - GPIO config information + * pol - 0 : rising edge trigger + * 1 : falling edge trigger + * + * Returned Value: + * void + * + ****************************************************************************/ + +static void tlsr82_gpio_pol_ctrl(gpio_cfg_t cfg, uint8_t pol) +{ + uint32_t group; + uint32_t pin; + + DEBUGASSERT(GPIO_VALID(cfg)); + + group = (uint32_t)GPIO_GET(GROUP, cfg); + pin = (uint32_t)GPIO_GET(PIN, cfg); + + if (pol) + { + BM_SET(GPIO_SETTING_POL_REG(group), 1 << pin); + } + else + { + BM_CLR(GPIO_SETTING_POL_REG(group), 1 << pin); + } +} + +/**************************************************************************** + * Name: tlsr82_gpio_irq + * + * Description: + * GPIO interrupt handler. + * + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_GPIO_IRQ +static int tlsr82_gpio_irq(int irq, void *context, void *arg) +{ + int i; + void *arg_cb; + xcpt_t callback; + int ret = OK; + + /* Clear the GPIO interrupt status */ + + BM_SET(IRQ_SRC_REG, 1 << NR_GPIO_IRQ); + + /* Dispatch pending interrupts in the lower GPIO status register */ + + for (i = 0; i < CONFIG_GPIO_IRQ_MAX_NUM; ++i) + { + if (gpio_irq_cbs[i].callback != NULL && + GPIO_IS(IRQ, NORMAL, gpio_irq_cbs[i].cfg)) + { + arg_cb = gpio_irq_cbs[i].arg; + callback = gpio_irq_cbs[i].callback; + ret = callback(irq, context, arg_cb); + } + } + + return ret; +} + +/**************************************************************************** + * Name: tlsr82_gpio_risc1_irq + * + * Description: + * GPIO interrupt handler. + * + ****************************************************************************/ + +static int tlsr82_gpio_risc0_irq(int irq, void *context, void *arg) +{ + int i; + void *arg_cb; + xcpt_t callback; + int ret = OK; + + /* Clear the GPIO interrupt status */ + + BM_SET(IRQ_SRC_REG, 1 << NR_GPIO_RISC0_IRQ); + + /* Dispatch pending interrupts in the lower GPIO status register */ + + for (i = 0; i < CONFIG_GPIO_IRQ_MAX_NUM; ++i) + { + if (gpio_irq_cbs[i].callback != NULL && + GPIO_IS(IRQ, RISC0, gpio_irq_cbs[i].cfg)) + { + arg_cb = gpio_irq_cbs[i].arg; + callback = gpio_irq_cbs[i].callback; + ret = callback(irq, context, arg_cb); + } + } + + return ret; +} + +/**************************************************************************** + * Name: tlsr82_gpio_risc1_irq + * + * Description: + * GPIO interrupt handler. + * + ****************************************************************************/ + +static int tlsr82_gpio_risc1_irq(int irq, void *context, void *arg) +{ + int i; + void *arg_cb; + xcpt_t callback; + int ret = OK; + + /* Clear the GPIO interrupt status */ + + BM_SET(IRQ_SRC_REG, 1 << NR_GPIO_RISC1_IRQ); + + /* Dispatch pending interrupts in the lower GPIO status register */ + + for (i = 0; i < CONFIG_GPIO_IRQ_MAX_NUM; ++i) + { + if (gpio_irq_cbs[i].callback != NULL && + GPIO_IS(IRQ, RISC1, gpio_irq_cbs[i].cfg)) + { + arg_cb = gpio_irq_cbs[i].arg; + callback = gpio_irq_cbs[i].callback; + ret = callback(irq, context, arg_cb); + } + } + + return ret; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_gpio_as_gpio + * + * Description: + * Config the gpio as a gpio or mux function + * + * Input Parameters: + * gpio_cfg_t - GPIO config information + * enable - true : enable gpio as gpio + * false: enable gpio as mux function + * + * Returned Value: + * void + * + ****************************************************************************/ + +void tlsr82_gpio_as_gpio(gpio_cfg_t cfg, bool enable) +{ + uint32_t group; + uint32_t pin; + + group = (uint32_t)GPIO_GET(GROUP, cfg); + pin = (uint32_t)GPIO_GET(PIN, cfg); + + if (enable) + { + BM_SET(GPIO_SETTING_ACT_REG(group), BIT(pin)); + } + else + { + BM_CLR(GPIO_SETTING_ACT_REG(group), BIT(pin)); + } +} + +/**************************************************************************** + * Name: tlsr82_gpio_input_ctrl + * + * Description: + * Enable/Disable the gpio input function. + * + * Input Parameters: + * gpio_cfg_t - GPIO config information + * enable - true : enable gpio input function + * false: disable gpio input function + * + * Returned Value: + * void + * + ****************************************************************************/ + +void tlsr82_gpio_input_ctrl(gpio_cfg_t cfg, bool enable) +{ + uint32_t group; + uint32_t pin; + uint32_t bit; + + DEBUGASSERT(GPIO_VALID(cfg)); + + group = (uint32_t)GPIO_GET(GROUP, cfg); + pin = (uint32_t)GPIO_GET(PIN, cfg); + bit = 1 << pin; + + if (group == GPIO_VAL(GROUP, C)) + { + if (enable) + { + tlsr82_analog_write(ANALOG_PC_IE_ADDR, + tlsr82_analog_read(ANALOG_PC_IE_ADDR) | + bit); + } + else + { + tlsr82_analog_write(ANALOG_PC_IE_ADDR, + tlsr82_analog_read(ANALOG_PC_IE_ADDR) & + (~bit)); + } + } + else + { + if (enable) + { + BM_SET(GPIO_SETTING_IE_REG(group), bit); + } + else + { + BM_CLR(GPIO_SETTING_IE_REG(group), bit); + } + } +} + +/**************************************************************************** + * Name: tlsr82_gpio_output_ctrl + * + * Description: + * Enable/Disable the gpio output function. + * + * Input Parameters: + * gpio_cfg_t - GPIO config information + * enable - true : enable gpio output function + * false: disable gpio output function + * + * Returned Value: + * void + * + ****************************************************************************/ + +void tlsr82_gpio_output_ctrl(gpio_cfg_t cfg, bool enable) +{ + uint32_t group; + uint32_t pin; + uint32_t bit; + + DEBUGASSERT(GPIO_VALID(cfg)); + + group = (uint32_t)GPIO_GET(GROUP, cfg); + pin = (uint32_t)GPIO_GET(PIN, cfg); + bit = 1 << pin; + + if (!enable) + { + BM_SET(GPIO_SETTING_OEN_REG(group), bit); + } + else + { + BM_CLR(GPIO_SETTING_OEN_REG(group), bit); + } +} + +/**************************************************************************** + * Name: tlsr82_gpio_pupd_ctrl + * + * Description: + * Configurate the gpio pull-up/pull-down. + * + * Input Parameters: + * gpio_cfg_t - GPIO config information + * pupd - 0 : none/float + * 1 : pull-up x100 - 1M + * 2 : pull-down x10 - 100K + * 3 : pull-dup x1 - 10K + * + * Returned Value: + * void + * + ****************************************************************************/ + +void tlsr82_gpio_pupd_ctrl(gpio_cfg_t cfg, uint8_t pupd) +{ + uint32_t group; + uint32_t pin; + uint32_t basereg; + uint32_t mask; + uint32_t shift; + + DEBUGASSERT(GPIO_VALID(cfg)); + + group = (uint32_t)GPIO_GET(GROUP, cfg); + pin = (uint32_t)GPIO_GET(PIN, cfg); + + basereg = 0x0e + (group << 1) + ((pin >= 4) ? 1 : 0); + + shift = (pin >= 4) ? (2 * pin - 8) : (2 * pin); + mask = ~(0x03 << shift); + + /* Usb dp pull-up/down config */ + + if (GPIO_PIN_PA6 == GPIO_CFG2PIN(cfg)) + { + /* usb_dp_pullup_en(0); */ + } + + tlsr82_analog_write(basereg, + (tlsr82_analog_read(basereg) & mask) | + (pupd << shift)); +} + +/**************************************************************************** + * Name: tlsr82_configgpio + * + * Description: + * Configure a GPIO pin based on encoded pin attributes. + * + ****************************************************************************/ + +int tlsr82_gpioconfig(gpio_cfg_t cfg) +{ + uint32_t group; + uint32_t pin; + uint8_t mux; + uint8_t shift; + + /* Get the gpio group and pin */ + + group = (uint32_t)GPIO_GET(GROUP, cfg); + pin = (uint32_t)GPIO_GET(PIN, cfg); + + /* Pull-up and Pull-down config */ + + if (GPIO_GET(PUPD, cfg) <= GPIO_VAL(PUPD, PU10K)) + { + tlsr82_gpio_pupd_ctrl(cfg, GPIO_GET(PUPD, cfg)); + } + + /* Input, Output, and Mux function config */ + + if (GPIO_IS(AF, INPUT, cfg)) + { + /* GPIO setting act as GPIO */ + + BM_SET(GPIO_SETTING_ACT_REG(group), BIT(pin)); + + /* IE and OEN should be set to 1 for Input usage */ + + tlsr82_gpio_input_ctrl(cfg, true); + tlsr82_gpio_output_ctrl(cfg, false); + } + else if (GPIO_IS(AF, OUTPUT, cfg)) + { + /* GPIO setting act as GPIO */ + + BM_SET(GPIO_SETTING_ACT_REG(group), BIT(pin)); + + /* IE and OEN should be set to 0 for Output usage */ + + tlsr82_gpio_input_ctrl(cfg, false); + tlsr82_gpio_output_ctrl(cfg, true); + + /* Drive Strength config */ + + tlsr82_gpio_ds_ctrl(cfg, (bool)GPIO_GET(DS, cfg)); + } + else if (GPIO_GET(AF, cfg) >= GPIO_VAL(AF, MUX0) && + GPIO_GET(AF, cfg) <= GPIO_VAL(AF, MUX3)) + { + /* Clear mux first and then set mux value */ + + shift = (pin >= 4) ? (2 * pin - 8) : (2 * pin); + mux = GPIO_GET(AF, cfg) - GPIO_VAL(AF, MUX0); + + BM_CLR(GPIO_MUX_REG(group, pin), 0x03 << shift); + + BM_SET(GPIO_MUX_REG(group, pin), mux << shift); + + /* GPIO setting act as MUX */ + + BM_CLR(GPIO_SETTING_ACT_REG(group), BIT(pin)); + } + + return OK; +} + +/**************************************************************************** + * Name: tlsr82_unconfiggpio + * + * Description: + * Un-configure a GPIO pin based on encoded pin attributes. + * + ****************************************************************************/ + +int tlsr82_gpiounconfig(gpio_cfg_t cfg) +{ + gpio_cfg_t pinset; + + /* Get the pin infomation in cfg */ + + pinset = GPIO_CFG2PIN(cfg); + + /* Config gpio as input and float state */ + + pinset |= GPIO_AF_INPUT | GPIO_PUPD_NONE; + + return tlsr82_gpioconfig(pinset); +} + +/**************************************************************************** + * Name: tlsr82_gpiowrite + * + * Description: + * Write one or zero to the selected GPIO pin + * + ****************************************************************************/ + +void tlsr82_gpiowrite(gpio_cfg_t cfg, bool value) +{ + uint32_t group; + uint32_t pin; + + group = (uint16_t)GPIO_GET(GROUP, cfg); + pin = (uint16_t)GPIO_GET(PIN, cfg); + + if (value) + { + BM_SET(GPIO_SETTING_OUT_REG(group), BIT(pin)); + } + else + { + BM_CLR(GPIO_SETTING_OUT_REG(group), BIT(pin)); + } +} + +/**************************************************************************** + * Name: tlsr82_gpioread + * + * Description: + * Read one or zero from the selected GPIO pin + * + ****************************************************************************/ + +bool tlsr82_gpioread(gpio_cfg_t cfg) +{ + uint32_t group; + uint32_t pin; + + group = (uint32_t)GPIO_GET(GROUP, cfg); + pin = (uint32_t)GPIO_GET(PIN, cfg); + + if (GPIO_IS(AF, OUTPUT, cfg)) + { + return BM_IS_SET(GPIO_SETTING_OUT_REG(group), BIT(pin)) != 0; + } + else + { + return BM_IS_SET(GPIO_SETTING_IN_REG(group), BIT(pin)) != 0; + } +} + +/**************************************************************************** + * Name: tlsr82_gpioirqinitialize + * + * Description: + * Initialize logic to support a second level of interrupt decoding for + * GPIO pins. + * + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_GPIO_IRQ +void tlsr82_gpioirqinitialize(void) +{ + int ret; + int i; + int irqs[3] = + { + NR_GPIO_IRQ, + NR_GPIO_RISC0_IRQ, + NR_GPIO_RISC1_IRQ + }; + + xcpt_t isrs[3] = + { + tlsr82_gpio_irq, + tlsr82_gpio_risc0_irq, + tlsr82_gpio_risc1_irq + }; + + for (i = 0; i < 3; i++) + { + /* Disable interrupt */ + + up_disable_irq(irqs[i]); + + /* Attach the gpio interrupt */ + + ret = irq_attach(irqs[i], isrs[i], NULL); + if (ret == OK) + { + up_enable_irq(irqs[i]); + } + else + { + gpioerr("ERROR: GPIO interrupt:%d not attached!\n", irqs[i]); + } + } + + for (i = 0; i < CONFIG_GPIO_IRQ_MAX_NUM; i++) + { + gpio_irq_cbs[i].callback = NULL; + gpio_irq_cbs[i].arg = NULL; + gpio_irq_cbs[i].cfg = GPIO_INVLD_CFG; + } +} +#endif + +/**************************************************************************** + * Name: tlsr82_gpioirqconfig + * + * Description: + * Config the gpio irq according to the cfg, and attach or + * detach the interrupt callback function according to value of func. + * + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_GPIO_IRQ +int tlsr82_gpioirqconfig(gpio_cfg_t cfg, xcpt_t func, void *arg) +{ + int i; + gpio_cfg_t pinset; + + /* Get pin information from cfg */ + + pinset = GPIO_CFG2PIN(cfg); + + /* func == NULL indicates disable this interrupt */ + + if (func == NULL) + { + /* Disable interrupt when modify the callback */ + + tlsr82_gpioirqdisable_all(); + + for (i = 0; i < CONFIG_GPIO_IRQ_MAX_NUM; ++i) + { + if (GPIO_CFG2PIN(gpio_irq_cbs[i].cfg) == pinset) + { + gpio_irq_cbs[i].callback = NULL; + gpio_irq_cbs[i].arg = NULL; + gpio_irq_cbs[i].cfg = GPIO_INVLD_CFG; + break; + } + } + + /* Disable corresponding pin interrupt */ + + tlsr82_gpioirqdisable(cfg); + } + else + { + /* Find an approprite callback object */ + + for (i = 0; i < CONFIG_GPIO_IRQ_MAX_NUM; ++i) + { + if (GPIO_CFG2PIN(gpio_irq_cbs[i].cfg) == pinset || + gpio_irq_cbs[i].callback == NULL) + { + /* 1. Re-config the same pin before unconfig it, just direct + * use pervious callback object. + * 2. New pinset, use a new callback object. + */ + + break; + } + } + + if (i == CONFIG_GPIO_IRQ_MAX_NUM) + { + /* Callback objects have been ran out */ + + gpioerr("Config Fail, gpio_irq_cbs[] have been ran out.\n"); + return -ENOSPC; + } + + /* Disable interrupt when modify the callback */ + + tlsr82_gpioirqdisable_all(); + + /* Find callback object success */ + + gpio_irq_cbs[i].callback = func; + gpio_irq_cbs[i].arg = arg; + gpio_irq_cbs[i].cfg = cfg; + + /* Enable corresponding pin interrupt */ + + tlsr82_gpioirqenable(cfg); + } + + /* GPIO must be in input mode for gpio interrupt */ + + tlsr82_gpioconfig(pinset | GPIO_AF_INPUT | GPIO_PUPD_NONE); + + /* Config gpio interrupt polarity */ + + tlsr82_gpio_pol_ctrl(GPIO_CFG2SDKPIN(cfg), GPIO_GET(POL, cfg)); + + /* Enable corresponding gpio interrupt */ + + tlsr82_gpioirqenable_all(); + + return OK; +} +#endif + +/**************************************************************************** + * Name: tlsr82_gpioirqenable + * + * Description: + * Enable the interrupt for specified GPIO IRQ + * + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_GPIO_IRQ +void tlsr82_gpioirqenable(gpio_cfg_t cfg) +{ + uint32_t group; + uint32_t pin; + uint32_t irqmode; + + group = (uint32_t)GPIO_GET(GROUP, cfg); + pin = (uint32_t)GPIO_GET(PIN, cfg); + irqmode = (uint32_t)GPIO_GET(IRQ, cfg); + + /* Enable corresponding gpio interrupt */ + + if (irqmode == GPIO_IRQ_NORMAL_VAL) + { + /* Enable corresponding pin interrupt, irq */ + + BM_SET(GPIO_IRQ_NORMAL_REG(group), BIT(pin)); + + /* Enable the total gpio interrupt */ + + BM_SET(GPIO_IRQ_NORMAL_ALL_REG, GPIO_IRQ_NORMAL_ALL_EN); + } + else if (irqmode == GPIO_IRQ_M0_VAL) + { + /* Set M0, the timer interrupt is controled by timer */ + + BM_SET(GPIO_IRQ_M0_REG(group), BIT(pin)); + } + else if (irqmode == GPIO_IRQ_M1_VAL) + { + /* Set M1, the timer interrupt is controled by timer */ + + BM_SET(GPIO_IRQ_M1_REG(group), BIT(pin)); + } + else if (irqmode == GPIO_IRQ_M2_VAL) + { + /* Set M2, the timer interrupt is controled by timer */ + + BM_SET(GPIO_IRQ_M2_REG(group), BIT(pin)); + } + else if (irqmode == GPIO_IRQ_RISC0_VAL) + { + /* Set M0, enable risc0 bit, enable gpio risc0 interrupt */ + + BM_SET(GPIO_IRQ_M0_REG(group), BIT(pin)); + BM_SET(GPIO_IRQ_RISC_EN_REG, GPIO_IRQ_RISC0_EN); + } + else if (irqmode == GPIO_IRQ_RISC1_VAL) + { + /* Set M1, enable risc1 bit, enable gpio risc1 interrupt */ + + BM_SET(GPIO_IRQ_M1_REG(group), BIT(pin)); + BM_SET(GPIO_IRQ_RISC_EN_REG, GPIO_IRQ_RISC1_EN); + } + else + { + gpioerr("GPIO irq type is not correct, cfg=0x%lx\n", cfg); + } +} + +#endif + +/**************************************************************************** + * Name: tlsr82_gpioirqdisable + * + * Description: + * Disable the interrupt for specified GPIO IRQ + * + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_GPIO_IRQ +void tlsr82_gpioirqdisable(gpio_cfg_t cfg) +{ + uint32_t group; + uint32_t pin; + uint32_t irqmode; + + group = (uint32_t)GPIO_GET(GROUP, cfg); + pin = (uint32_t)GPIO_GET(PIN, cfg); + irqmode = (uint32_t)GPIO_GET(IRQ, cfg); + + if (irqmode == GPIO_IRQ_NORMAL_VAL) + { + BM_CLR(GPIO_IRQ_NORMAL_REG(group), BIT(pin)); + } + else if (irqmode == GPIO_IRQ_M0_VAL) + { + BM_CLR(GPIO_IRQ_M0_REG(group), BIT(pin)); + } + else if (irqmode == GPIO_IRQ_M1_VAL) + { + BM_CLR(GPIO_IRQ_M1_REG(group), BIT(pin)); + } + else if (irqmode == GPIO_IRQ_M2_VAL) + { + BM_CLR(GPIO_IRQ_M2_REG(group), BIT(pin)); + } + else if (irqmode == GPIO_IRQ_RISC0_VAL) + { + BM_CLR(GPIO_IRQ_M0_REG(group), BIT(pin)); + BM_CLR(GPIO_IRQ_RISC_EN_REG, GPIO_IRQ_RISC0_EN); + } + else if (irqmode == GPIO_IRQ_RISC1_VAL) + { + BM_CLR(GPIO_IRQ_M1_REG(group), BIT(pin)); + BM_CLR(GPIO_IRQ_RISC_EN_REG, GPIO_IRQ_RISC1_EN); + } + else + { + gpioerr("GPIO irq type is not correct, cfg=0x%lx\n", cfg); + } +} + +#endif + +/**************************************************************************** + * Name: tlsr82_gpioirqdisable_all + * + * Description: + * Disable all the gpio interrupt (not clear gpio pin corresponding + * interrupt bit.) + * + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_GPIO_IRQ +void tlsr82_gpioirqdisable_all(void) +{ + up_disable_irq(NR_GPIO_IRQ); + up_disable_irq(NR_GPIO_RISC0_IRQ); + up_disable_irq(NR_GPIO_RISC1_IRQ); +} +#endif + +/**************************************************************************** + * Name: tlsr82_gpioirqenable_all + * + * Description: + * Enable all the gpio interrupt (not set gpio pin corresponding + * interrupt bit.) + * + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_GPIO_IRQ +void tlsr82_gpioirqenable_all(void) +{ + up_enable_irq(NR_GPIO_IRQ); + up_enable_irq(NR_GPIO_RISC0_IRQ); + up_enable_irq(NR_GPIO_RISC1_IRQ); +} +#endif diff --git a/arch/arm/src/tlsr82/tlsr82_gpio.h b/arch/arm/src/tlsr82/tlsr82_gpio.h new file mode 100644 index 0000000000000..29859a23bf917 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_gpio.h @@ -0,0 +1,344 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_gpio.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_TLSR82_GPIO_H +#define __ARCH_ARM_SRC_TLSR82_TLSR82_GPIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "hardware/tlsr82_irq.h" +#include "hardware/tlsr82_gpio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* GPIO definitions t = type, n = name, c = config, p = pinset */ + +#define GPIO_VAL(t, n) (GPIO_##t##_##n >> GPIO_##t##_SHIFT) +#define GPIO_GET(t, c) (((c) & GPIO_##t##_MASK) >> GPIO_##t##_SHIFT) +#define GPIO_IS(t, n, c) (((c) & GPIO_##t##_MASK) == GPIO_##t##_##n) + +#define GPIO_CFG2SDKPIN(p) (((p) & GPIO_GROUP_MASK) | (1 << GPIO_GET(PIN, p))) +#define GPIO_CFG2PIN(p) ((p) & (GPIO_GROUP_MASK | GPIO_PIN_MASK)) +#define GPIO_PIN2NUM(p) (GPIO_GET(PIN, p) + (GPIO_GET(GROUP, p) << 3)) + +#define GPIO_ALL_MASK (GPIO_PIN_MASK | GPIO_GROUP_MASK | GPIO_AF_MASK |\ + GPIO_PUPD_MASK | GPIO_DS_MASK | GPIO_IRQ_MASK |\ + GPIO_POL_MASK) + +#define GPIO_INVLD_CFG (~GPIO_ALL_MASK) + +#define GPIO_VALID(c) (((c) & (~GPIO_ALL_MASK)) == 0) + +/* Gpio pin option, each gpio group has 8 pin + * Mask in pinset 0x0000 00FF + */ + +#define GPIO_PIN_SHIFT 0 +#define GPIO_PIN_MASK (0xFF << GPIO_PIN_SHIFT) +#define GPIO_PIN(n) ((n) << 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) + +/* Gpio group option + * Mask in pinset 0x0000 0300 + */ + +#define GPIO_GROUP_SHIFT 8 +#define GPIO_GROUP_MASK (0x3 << GPIO_GROUP_SHIFT) +#define GPIO_GROUP_A (0 << GPIO_GROUP_SHIFT) +#define GPIO_GROUP_B (1 << GPIO_GROUP_SHIFT) +#define GPIO_GROUP_C (2 << GPIO_GROUP_SHIFT) +#define GPIO_GROUP_D (3 << GPIO_GROUP_SHIFT) + +/* Gpio alternative function option + * Mask in config 0x0000 7000 + */ + +#define GPIO_AF_SHIFT 12 +#define GPIO_AF_MASK (0x7 << GPIO_AF_SHIFT) +#define GPIO_AF_SHUTDOWN (0 << GPIO_AF_SHIFT) +#define GPIO_AF_INPUT (1 << GPIO_AF_SHIFT) +#define GPIO_AF_OUTPUT (2 << GPIO_AF_SHIFT) +#define GPIO_AF_MUX0 (3 << GPIO_AF_SHIFT) +#define GPIO_AF_MUX1 (4 << GPIO_AF_SHIFT) +#define GPIO_AF_MUX2 (5 << GPIO_AF_SHIFT) +#define GPIO_AF_MUX3 (6 << GPIO_AF_SHIFT) + +/* Pull-up and Pull-down option + * Mask in config 0x0003 0000 + */ + +#define GPIO_PUPD_SHIFT 16 +#define GPIO_PUPD_MASK (0x3 << GPIO_PUPD_SHIFT) +#define GPIO_PUPD_NONE (0 << GPIO_PUPD_SHIFT) +#define GPIO_PUPD_PU1M (1 << GPIO_PUPD_SHIFT) +#define GPIO_PUPD_PD100K (2 << GPIO_PUPD_SHIFT) +#define GPIO_PUPD_PU10K (3 << GPIO_PUPD_SHIFT) + +/* Driver Strength option + * Mask in config 0x0004 0000 + */ + +#define GPIO_DS_SHIFT 18 +#define GPIO_DS_MASK (0x1 << GPIO_DS_SHIFT) +#define GPIO_DS_LOW (0 << GPIO_DS_SHIFT) +#define GPIO_DS_HIGH (1 << GPIO_DS_SHIFT) + +/* Gpio interrupt type option + * Mask in config 0x0070 0000 + */ + +#define GPIO_IRQ_SHIFT 20 +#define GPIO_IRQ_MASK (0x7 << GPIO_IRQ_SHIFT) +#define GPIO_IRQ_DISABLE (0 << GPIO_IRQ_SHIFT) +#define GPIO_IRQ_NORMAL (1 << GPIO_IRQ_SHIFT) +#define GPIO_IRQ_M0 (2 << GPIO_IRQ_SHIFT) +#define GPIO_IRQ_M1 (3 << GPIO_IRQ_SHIFT) +#define GPIO_IRQ_M2 (4 << GPIO_IRQ_SHIFT) +#define GPIO_IRQ_RISC0 (5 << GPIO_IRQ_SHIFT) +#define GPIO_IRQ_RISC1 (6 << GPIO_IRQ_SHIFT) +#define GPIO_IRQ_NORMAL_VAL 1 +#define GPIO_IRQ_M0_VAL 2 +#define GPIO_IRQ_M1_VAL 3 +#define GPIO_IRQ_M2_VAL 4 +#define GPIO_IRQ_RISC0_VAL 5 +#define GPIO_IRQ_RISC1_VAL 6 + +/* Gpio interrupt polarity option + * Mask in config 0x0080 0000 + */ + +#define GPIO_POL_SHIFT 23 +#define GPIO_POL_MASK (0x1 << GPIO_POL_SHIFT) +#define GPIO_POL_RISE (0 << GPIO_POL_SHIFT) +#define GPIO_POL_FAIL (1 << GPIO_POL_SHIFT) + +/* GPIO specific pin definitions */ + +#define GPIO_PIN_PA0 (GPIO_GROUP_A | GPIO_PIN0) +#define GPIO_PIN_PA1 (GPIO_GROUP_A | GPIO_PIN1) +#define GPIO_PIN_PA2 (GPIO_GROUP_A | GPIO_PIN2) +#define GPIO_PIN_PA3 (GPIO_GROUP_A | GPIO_PIN3) +#define GPIO_PIN_PA4 (GPIO_GROUP_A | GPIO_PIN4) +#define GPIO_PIN_PA5 (GPIO_GROUP_A | GPIO_PIN5) +#define GPIO_PIN_PA6 (GPIO_GROUP_A | GPIO_PIN6) +#define GPIO_PIN_PA7 (GPIO_GROUP_A | GPIO_PIN7) + +#define GPIO_PIN_PB0 (GPIO_GROUP_B | GPIO_PIN0) +#define GPIO_PIN_PB1 (GPIO_GROUP_B | GPIO_PIN1) +#define GPIO_PIN_PB2 (GPIO_GROUP_B | GPIO_PIN2) +#define GPIO_PIN_PB3 (GPIO_GROUP_B | GPIO_PIN3) +#define GPIO_PIN_PB4 (GPIO_GROUP_B | GPIO_PIN4) +#define GPIO_PIN_PB5 (GPIO_GROUP_B | GPIO_PIN5) +#define GPIO_PIN_PB6 (GPIO_GROUP_B | GPIO_PIN6) +#define GPIO_PIN_PB7 (GPIO_GROUP_B | GPIO_PIN7) + +#define GPIO_PIN_PC0 (GPIO_GROUP_C | GPIO_PIN0) +#define GPIO_PIN_PC1 (GPIO_GROUP_C | GPIO_PIN1) +#define GPIO_PIN_PC2 (GPIO_GROUP_C | GPIO_PIN2) +#define GPIO_PIN_PC3 (GPIO_GROUP_C | GPIO_PIN3) +#define GPIO_PIN_PC4 (GPIO_GROUP_C | GPIO_PIN4) +#define GPIO_PIN_PC5 (GPIO_GROUP_C | GPIO_PIN5) +#define GPIO_PIN_PC6 (GPIO_GROUP_C | GPIO_PIN6) +#define GPIO_PIN_PC7 (GPIO_GROUP_C | GPIO_PIN7) + +#define GPIO_PIN_PD0 (GPIO_GROUP_D | GPIO_PIN0) +#define GPIO_PIN_PD1 (GPIO_GROUP_D | GPIO_PIN1) +#define GPIO_PIN_PD2 (GPIO_GROUP_D | GPIO_PIN2) +#define GPIO_PIN_PD3 (GPIO_GROUP_D | GPIO_PIN3) +#define GPIO_PIN_PD4 (GPIO_GROUP_D | GPIO_PIN4) +#define GPIO_PIN_PD5 (GPIO_GROUP_D | GPIO_PIN5) +#define GPIO_PIN_PD6 (GPIO_GROUP_D | GPIO_PIN6) +#define GPIO_PIN_PD7 (GPIO_GROUP_D | GPIO_PIN7) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* Must be big enough to hold the above encodings */ + +typedef uint32_t gpio_cfg_t; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void tlsr82_gpio_as_gpio(gpio_cfg_t cfg, bool enable); +void tlsr82_gpio_input_ctrl(gpio_cfg_t cfg, bool enable); +void tlsr82_gpio_output_ctrl(gpio_cfg_t cfg, bool enable); +void tlsr82_gpio_pupd_ctrl(gpio_cfg_t cfg, uint8_t pupd); + +/**************************************************************************** + * Name: tlsr82_gpioconfig + * + * Description: + * Configure a GPIO pin based on encoded pin config. + * + ****************************************************************************/ + +int tlsr82_gpioconfig(gpio_cfg_t cfg); + +/**************************************************************************** + * Name: tlsr82_unconfiggpio + * + * Description: + * Un-configure a GPIO pin based on encoded pin config. + * + ****************************************************************************/ + +int tlsr82_gpiounconfig(gpio_cfg_t cfg); + +/**************************************************************************** + * Name: tlsr82_gpiowrite + * + * Description: + * Write one or zero to the selected GPIO pin + * + ****************************************************************************/ + +void tlsr82_gpiowrite(gpio_cfg_t cfg, bool value); + +/**************************************************************************** + * Name: tlsr82_gpioread + * + * Description: + * Read one or zero from the selected GPIO pin + * + ****************************************************************************/ + +bool tlsr82_gpioread(gpio_cfg_t cfg); + +/**************************************************************************** + * Name: tlsr82_gpioirqinitialize + * + * Description: + * Initialize logic to support a second level of interrupt decoding for + * GPIO pins. + * + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_GPIO_IRQ +void tlsr82_gpioirqinitialize(void); +#else +# define tlsr82_gpioirqinitialize() +#endif + +#ifdef CONFIG_TLSR82_GPIO_IRQ +int tlsr82_gpioirqconfig(gpio_cfg_t cfg, xcpt_t func, void *arg); +#else +# define tlsr82_gpioirqconfig(cfg, func, arg) +#endif + +/**************************************************************************** + * Name: tlsr82_gpioirqenable + * + * Description: + * Enable the interrupt for specified GPIO IRQ + * + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_GPIO_IRQ +void tlsr82_gpioirqenable(gpio_cfg_t cfg); +#else +# define tlsr82_gpioirqenable(cfg) +#endif + +/**************************************************************************** + * Name: tlsr82_gpioirqdisable + * + * Description: + * Disable the interrupt for specified GPIO IRQ + * + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_GPIO_IRQ +void tlsr82_gpioirqdisable(gpio_cfg_t cfg); +#else +# define tlsr82_gpioirqdisable(cfg) +#endif + +/**************************************************************************** + * Name: tlsr82_gpioirqdisable_all + * + * Description: + * Disable all the gpio interrupt (not clear gpio pin corresponding + * interrupt bit.) + * + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_GPIO_IRQ +void tlsr82_gpioirqdisable_all(void); +#else +# define tlsr82_gpioirqdisable_all() +#endif + +/**************************************************************************** + * Name: tlsr82_gpioirqenable_all + * + * Description: + * Enable all the gpio interrupt (not set gpio pin corresponding + * interrupt bit.) + * + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_GPIO_IRQ +void tlsr82_gpioirqenable_all(void); +#else +# define tlsr82_gpioirqenable_all() +#endif + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_RISCV_SRC_TLSR82_TLSR82_GPIO_H */ diff --git a/arch/arm/src/tlsr82/tlsr82_gpio_cfg.c b/arch/arm/src/tlsr82/tlsr82_gpio_cfg.c new file mode 100644 index 0000000000000..9567f71fdbb4b --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_gpio_cfg.c @@ -0,0 +1,228 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_gpio_cfg.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "tlsr82_analog.h" +#include "tlsr82_gpio.h" +#include "tlsr82_gpio_cfg.h" +#include "tlsr82_gpio_default.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MUX_NONE TLSR82_MUX_NONE +#define MUX_UART TLSR82_MUX_UART +#define MUX_PWM TLSR82_MUX_PWM +#define MUX_DMIC TLSR82_MUX_DMIC +#define MUX_I2C TLSR82_MUX_I2C +#define MUX_SPI TLSR82_MUX_SPI +#define MUX_U7816 TLSR82_MUX_U7816 +#define MUX_SDM TLSR82_MUX_SDM +#define MUX_I2S TLSR82_MUX_I2S +#define MUX_ATSEL TLSR82_MUX_ATSEL +#define MUX_SWS TLSR82_MUX_SWS +#define MUX_AMP TLSR82_MUX_AMP +#define MUX_USB TLSR82_MUX_USB +#define MUX_ADC TLSR82_MUX_ADC +#define MUX_LPC TLSR82_MUX_LPC +#define MUX_INPUT TLSR82_MUX_INPUT +#define MUX_OUTPUT TLSR82_MUX_OUTPUT + +#define I2C_SPI (MUX_I2C | MUX_SPI) +#define UART7816 (MUX_UART | MUX_U7816) +#define ADC_LPC (MUX_ADC | MUX_LPC) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_GPIO_VALIDATION +const static struct tlsr82_gpio_mux_s gpio_mux_tbl[GPIO_NUM] = +{ + {MUX_DMIC, MUX_PWM , MUX_UART , MUX_NONE}, /* -- PA0 */ + {MUX_DMIC, MUX_U7816, MUX_I2S , MUX_NONE}, /* PA1 */ + {MUX_SPI , MUX_UART , MUX_PWM , MUX_NONE}, /* PA2 */ + {I2C_SPI , MUX_UART , MUX_PWM , MUX_NONE}, /* PA3 */ + {I2C_SPI , MUX_UART , MUX_PWM , MUX_NONE}, /* PA4 */ + {MUX_SWS , MUX_NONE , MUX_NONE , MUX_NONE}, /* PA5 */ + {MUX_SWS , MUX_NONE , MUX_NONE , MUX_NONE}, /* PA6 */ + {MUX_SWS , MUX_UART , MUX_NONE , MUX_NONE}, /* PA7 */ + {MUX_PWM , MUX_UART , MUX_ATSEL, ADC_LPC }, /* -- PB0 */ + {MUX_PWM , MUX_UART , MUX_ATSEL, ADC_LPC }, /* PB1 */ + {MUX_PWM , MUX_UART , MUX_AMP , ADC_LPC }, /* PB2 */ + {MUX_PWM , MUX_UART , MUX_AMP , ADC_LPC }, /* PB3 */ + {MUX_SDM , MUX_PWM , MUX_NONE , ADC_LPC }, /* PB4 */ + {MUX_SDM , MUX_UART , MUX_NONE , ADC_LPC }, /* PB5 */ + {MUX_SDM , I2C_SPI , MUX_UART , ADC_LPC }, /* PB6 */ + {MUX_SDM , MUX_SPI , MUX_UART , ADC_LPC }, /* PB7 */ + {MUX_I2C , MUX_PWM , MUX_UART , MUX_NONE}, /* -- PC0 */ + {MUX_I2C , MUX_PWM , MUX_PWM , MUX_NONE}, /* PC1 */ + {MUX_PWM , UART7816 , MUX_I2C , MUX_NONE}, /* PC2 */ + {MUX_PWM , MUX_UART , MUX_I2C , MUX_NONE}, /* PC3 */ + {MUX_PWM , MUX_UART , MUX_PWM , MUX_ADC }, /* PC4 */ + {MUX_PWM , MUX_UART , MUX_ATSEL, MUX_ADC }, /* PC5 */ + {MUX_AMP , MUX_ATSEL, MUX_PWM , MUX_NONE}, /* PC6 */ + {MUX_AMP , MUX_ATSEL, MUX_PWM , MUX_NONE}, /* PC7 */ + {MUX_AMP , MUX_NONE , UART7816 , MUX_NONE}, /* -- PD0 */ + {MUX_AMP , MUX_NONE , MUX_UART , MUX_NONE}, /* PD1 */ + {MUX_SPI , MUX_I2S , MUX_PWM , MUX_NONE}, /* PD2 */ + {MUX_PWM , MUX_I2S , UART7816 , MUX_NONE}, /* PD3 */ + {MUX_SWS , MUX_I2S , MUX_PWM , MUX_NONE}, /* PD4 */ + {MUX_PWM , MUX_NONE , MUX_PWM , MUX_NONE}, /* PD5 */ + {MUX_SPI , MUX_UART , MUX_ATSEL, MUX_NONE}, /* PD6 */ + {I2C_SPI , MUX_I2S , UART7816 , MUX_NONE}, /* PD7 */ +}; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_gpio_cfg_check + * + * Description: + * Check weather the mux function is supported or not by the input pin. + * + * Input Parameters: + * cfg - the pin config information, include the group and pin num + * information. + * mux - mux function. + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +int tlsr82_gpio_cfg_check(uint32_t cfg, uint32_t mux) +{ +#ifdef CONFIG_TLSR82_GPIO_VALIDATION + int muxid; + uint32_t mux3; + uint32_t cfg_af; + uint16_t pinnum; + + DEBUGASSERT(GPIO_VALID(cfg)); + + pinnum = GPIO_PIN2NUM(cfg); + cfg_af = GPIO_GET(AF, cfg); + + /* ADC and LPC is not configed by gpio mux register */ + + if ((mux == MUX_ADC) || (mux == MUX_LPC)) + { + mux3 = gpio_mux_tbl[pinnum].muxs[3]; + return (mux3 & mux) ? 0 : -1; + } + + /* If af is not mux0 ~ mux3, return -2 */ + + if (cfg_af < GPIO_VAL(AF, MUX0)) + { + return -2; + } + + /* Get the muxid [0, 3], if mux is not supported by + * this gpio pin, return -1, otherwise return 0. + */ + + muxid = cfg_af - GPIO_VAL(AF, MUX0); + if ((gpio_mux_tbl[pinnum].muxs[muxid] & mux) == 0) + { + return -1; + } +#endif + + return 0; +} + +/**************************************************************************** + * Name: tlsr82_gpio_init + * + * Description: + * GPIO config initialization. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void tlsr82_gpio_init(void) +{ + /* Group A */ + + GPIO_SET_PA_IE_REG = GPIO_DEFAULT_IE_GET(A); + GPIO_SET_PA_OEN_REG = GPIO_DEFAULT_OEN_GET(A); + GPIO_SET_PA_OUT_REG = GPIO_DEFAULT_OUT_GET(A); + GPIO_SET_PA_DS_REG = GPIO_DEFAULT_DS_GET(A); + GPIO_SET_PA_ACT_REG = GPIO_DEFAULT_ACT_GET(A); + + /* Group B */ + + GPIO_SET_PB_IE_REG = GPIO_DEFAULT_IE_GET(B); + GPIO_SET_PB_OEN_REG = GPIO_DEFAULT_OEN_GET(B); + GPIO_SET_PB_OUT_REG = GPIO_DEFAULT_OUT_GET(B); + GPIO_SET_PB_DS_REG = GPIO_DEFAULT_DS_GET(B); + GPIO_SET_PB_ACT_REG = GPIO_DEFAULT_ACT_GET(B); + + /* Group C */ + + tlsr82_analog_write(ANALOG_PC_IE_ADDR, GPIO_DEFAULT_IE_GET(C)); + GPIO_SET_PC_OEN_REG = GPIO_DEFAULT_OEN_GET(C); + GPIO_SET_PC_OUT_REG = GPIO_DEFAULT_OUT_GET(C); + tlsr82_analog_write(ANALOG_PC_DS_ADDR, GPIO_DEFAULT_DS_GET(C)); + GPIO_SET_PC_ACT_REG = GPIO_DEFAULT_ACT_GET(C); + + /* Group D */ + + GPIO_SET_PD_IE_REG = GPIO_DEFAULT_IE_GET(D); + GPIO_SET_PD_OEN_REG = GPIO_DEFAULT_OEN_GET(D); + GPIO_SET_PD_OUT_REG = GPIO_DEFAULT_OUT_GET(D); + GPIO_SET_PD_DS_REG = GPIO_DEFAULT_DS_GET(D); + GPIO_SET_PD_ACT_REG = GPIO_DEFAULT_ACT_GET(D); + + /* Group E */ + + GPIO_SET_PE_IE_REG = GPIO_DEFAULT_IE_GET_E; + GPIO_SET_PE_OEN_REG = GPIO_DEFAULT_OEN_GET_E; + GPIO_SET_PE_OUT_REG = GPIO_DEFAULT_OUT_GET_E; + GPIO_SET_PE_DS_REG = GPIO_DEFAULT_DS_GET_E; + GPIO_SET_PE_ACT_REG = GPIO_DEFAULT_ACT_GET_E; +} diff --git a/arch/arm/src/tlsr82/tlsr82_gpio_cfg.h b/arch/arm/src/tlsr82/tlsr82_gpio_cfg.h new file mode 100644 index 0000000000000..9013b02046598 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_gpio_cfg.h @@ -0,0 +1,117 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_gpio_cfg.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_TLSR82_GPIO_CFG_H +#define __ARCH_ARM_SRC_TLSR82_TLSR82_GPIO_CFG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include "hardware/tlsr82_gpio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define GPIO_NUM (4 * 8) + +#define TLSR82_MUX_NONE (0) +#define TLSR82_MUX_INPUT (1 << 0) +#define TLSR82_MUX_OUTPUT (1 << 1) +#define TLSR82_MUX_UART (1 << 2) +#define TLSR82_MUX_PWM (1 << 3) +#define TLSR82_MUX_DMIC (1 << 4) +#define TLSR82_MUX_I2C (1 << 5) +#define TLSR82_MUX_SPI (1 << 6) +#define TLSR82_MUX_U7816 (1 << 7) +#define TLSR82_MUX_SDM (1 << 8) +#define TLSR82_MUX_I2S (1 << 9) +#define TLSR82_MUX_ATSEL (1 << 10) +#define TLSR82_MUX_SWS (1 << 11) +#define TLSR82_MUX_AMP (1 << 12) +#define TLSR82_MUX_USB (1 << 13) +#define TLSR82_MUX_ADC (1 << 14) +#define TLSR82_MUX_LPC (1 << 15) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct tlsr82_gpio_mux_s +{ + uint32_t muxs[4]; +}; + +struct tlsr82_gpio_cfg_s +{ + uint32_t mux; + uint32_t cfg; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_gpio_cfg_check + * + * Description: + * Check weather the mux function is supported or not by the input pin. + * + * Input Parameters: + * cfg - the pin config information, include the group and pin num + * information. + * mux - mux function. + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +int tlsr82_gpio_cfg_check(uint32_t cfg, uint32_t mux); + +/**************************************************************************** + * Name: tlsr82_gpio_init + * + * Description: + * GPIO config initialization. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void tlsr82_gpio_init(void); + +#endif /* __ARCH_ARM_SRC_TLSR82_TLSR82_GPIO_CFG_H */ diff --git a/arch/arm/src/tlsr82/tlsr82_gpio_default.h b/arch/arm/src/tlsr82/tlsr82_gpio_default.h new file mode 100644 index 0000000000000..ad9c6a979c185 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_gpio_default.h @@ -0,0 +1,784 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_gpio_default.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_TLSR82_GPIO_DEFAULT_H +#define __ARCH_ARM_SRC_TLSR82_TLSR82_GPIO_DEFAULT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Group A ~ D, IE, OEN, OUT, DS, ACT GET */ + +#define GPIO_DEFAULT_IE_GET(G) \ + ((P##G##0_INPUT_ENABLE << 0) | (P##G##1_INPUT_ENABLE << 1) | \ + (P##G##2_INPUT_ENABLE << 2) | (P##G##3_INPUT_ENABLE << 3) | \ + (P##G##4_INPUT_ENABLE << 4) | (P##G##5_INPUT_ENABLE << 5) | \ + (P##G##6_INPUT_ENABLE << 6) | (P##G##7_INPUT_ENABLE << 7)) + +#define GPIO_DEFAULT_OEN_GET(G) \ + (((P##G##0_OUTPUT_ENABLE ? 0 : 1) << 0) | \ + ((P##G##1_OUTPUT_ENABLE ? 0 : 1) << 1) | \ + ((P##G##2_OUTPUT_ENABLE ? 0 : 1) << 2) | \ + ((P##G##3_OUTPUT_ENABLE ? 0 : 1) << 3) | \ + ((P##G##4_OUTPUT_ENABLE ? 0 : 1) << 4) | \ + ((P##G##5_OUTPUT_ENABLE ? 0 : 1) << 5) | \ + ((P##G##6_OUTPUT_ENABLE ? 0 : 1) << 6) | \ + ((P##G##7_OUTPUT_ENABLE ? 0 : 1) << 7)) + +#define GPIO_DEFAULT_OUT_GET(G) \ + ((P##G##0_DATA_OUT << 0) | (P##G##1_DATA_OUT << 1) | \ + (P##G##2_DATA_OUT << 2) | (P##G##3_DATA_OUT << 3) | \ + (P##G##4_DATA_OUT << 4) | (P##G##5_DATA_OUT << 5) | \ + (P##G##6_DATA_OUT << 6) | (P##G##7_DATA_OUT << 7)) + +#define GPIO_DEFAULT_DS_GET(G) \ + ((P##G##0_DATA_STRENGTH << 0) | (P##G##1_DATA_STRENGTH << 1) | \ + (P##G##2_DATA_STRENGTH << 2) | (P##G##3_DATA_STRENGTH << 3) | \ + (P##G##4_DATA_STRENGTH << 4) | (P##G##5_DATA_STRENGTH << 5) | \ + (P##G##6_DATA_STRENGTH << 6) | (P##G##7_DATA_STRENGTH << 7)) + +#define GPIO_DEFAULT_ACT_GET(G) \ + ((P##G##0_FUNC == AS_GPIO ? BIT (0) : 0) | \ + (P##G##1_FUNC == AS_GPIO ? BIT (1) : 0) | \ + (P##G##2_FUNC == AS_GPIO ? BIT (2) : 0) | \ + (P##G##3_FUNC == AS_GPIO ? BIT (3) : 0) | \ + (P##G##4_FUNC == AS_GPIO ? BIT (4) : 0) | \ + (P##G##5_FUNC == AS_GPIO ? BIT (5) : 0) | \ + (P##G##6_FUNC == AS_GPIO ? BIT (6) : 0) | \ + (P##G##7_FUNC == AS_GPIO ? BIT (7) : 0)) + +/* Group E, IE, OEN, OUT, DS, ACT GET */ + +#define GPIO_DEFAULT_IE_GET_E \ + ((PE0_INPUT_ENABLE << 0) | (PE1_INPUT_ENABLE << 1) | \ + (PE2_INPUT_ENABLE << 2) | (PE3_INPUT_ENABLE << 3)) + +#define GPIO_DEFAULT_OEN_GET_E \ + (((PE0_OUTPUT_ENABLE ? 0 : 1) << 0) | \ + ((PE1_OUTPUT_ENABLE ? 0 : 1) << 1) | \ + ((PE2_OUTPUT_ENABLE ? 0 : 1) << 2) | \ + ((PE3_OUTPUT_ENABLE ? 0 : 1) << 3)) + +#define GPIO_DEFAULT_OUT_GET_E \ + ((PE0_DATA_OUT << 0) | (PE1_DATA_OUT << 1) | \ + (PE2_DATA_OUT << 2) | (PE3_DATA_OUT << 3)) + +#define GPIO_DEFAULT_DS_GET_E \ + ((PE0_DATA_STRENGTH << 0) | (PE1_DATA_STRENGTH << 1) | \ + (PE2_DATA_STRENGTH << 2) | (PE3_DATA_STRENGTH << 3)) + +#define GPIO_DEFAULT_ACT_GET_E \ + ((PE0_FUNC == AS_GPIO ? BIT (0) : 0) | \ + (PE1_FUNC == AS_GPIO ? BIT (1) : 0) | \ + (PE2_FUNC == AS_GPIO ? BIT (2) : 0) | \ + (PE3_FUNC == AS_GPIO ? BIT (3) : 0)) + +/* GPIO GROUP A Default Definition */ + +#ifndef PA0_INPUT_ENABLE +#define PA0_INPUT_ENABLE 0 +#endif +#ifndef PA1_INPUT_ENABLE +#define PA1_INPUT_ENABLE 0 +#endif +#ifndef PA2_INPUT_ENABLE +#define PA2_INPUT_ENABLE 0 +#endif +#ifndef PA3_INPUT_ENABLE +#define PA3_INPUT_ENABLE 0 +#endif +#ifndef PA4_INPUT_ENABLE +#define PA4_INPUT_ENABLE 0 +#endif +#ifndef PA5_INPUT_ENABLE +#define PA5_INPUT_ENABLE 0 /* USB */ +#endif +#ifndef PA6_INPUT_ENABLE +#define PA6_INPUT_ENABLE 0 /* USB */ +#endif +#ifndef PA7_INPUT_ENABLE +#define PA7_INPUT_ENABLE 1 /* SWS */ +#endif +#ifndef PA0_OUTPUT_ENABLE +#define PA0_OUTPUT_ENABLE 0 +#endif +#ifndef PA1_OUTPUT_ENABLE +#define PA1_OUTPUT_ENABLE 0 +#endif +#ifndef PA2_OUTPUT_ENABLE +#define PA2_OUTPUT_ENABLE 0 +#endif +#ifndef PA3_OUTPUT_ENABLE +#define PA3_OUTPUT_ENABLE 0 +#endif +#ifndef PA4_OUTPUT_ENABLE +#define PA4_OUTPUT_ENABLE 0 +#endif +#ifndef PA5_OUTPUT_ENABLE +#define PA5_OUTPUT_ENABLE 0 +#endif +#ifndef PA6_OUTPUT_ENABLE +#define PA6_OUTPUT_ENABLE 0 +#endif +#ifndef PA7_OUTPUT_ENABLE +#define PA7_OUTPUT_ENABLE 0 +#endif +#ifndef PA0_DATA_STRENGTH +#define PA0_DATA_STRENGTH 1 +#endif +#ifndef PA1_DATA_STRENGTH +#define PA1_DATA_STRENGTH 1 +#endif +#ifndef PA2_DATA_STRENGTH +#define PA2_DATA_STRENGTH 1 +#endif +#ifndef PA3_DATA_STRENGTH +#define PA3_DATA_STRENGTH 1 +#endif +#ifndef PA4_DATA_STRENGTH +#define PA4_DATA_STRENGTH 1 +#endif +#ifndef PA5_DATA_STRENGTH +#define PA5_DATA_STRENGTH 1 +#endif +#ifndef PA6_DATA_STRENGTH +#define PA6_DATA_STRENGTH 1 +#endif +#ifndef PA7_DATA_STRENGTH +#define PA7_DATA_STRENGTH 1 +#endif +#ifndef PA0_DATA_OUT +#define PA0_DATA_OUT 0 +#endif +#ifndef PA1_DATA_OUT +#define PA1_DATA_OUT 0 +#endif +#ifndef PA2_DATA_OUT +#define PA2_DATA_OUT 0 +#endif +#ifndef PA3_DATA_OUT +#define PA3_DATA_OUT 0 +#endif +#ifndef PA4_DATA_OUT +#define PA4_DATA_OUT 0 +#endif +#ifndef PA5_DATA_OUT +#define PA5_DATA_OUT 0 +#endif +#ifndef PA6_DATA_OUT +#define PA6_DATA_OUT 0 +#endif +#ifndef PA7_DATA_OUT +#define PA7_DATA_OUT 0 +#endif +#ifndef PA0_FUNC +#define PA0_FUNC AS_GPIO +#endif +#ifndef PA1_FUNC +#define PA1_FUNC AS_GPIO +#endif +#ifndef PA2_FUNC +#define PA2_FUNC AS_GPIO +#endif +#ifndef PA3_FUNC +#define PA3_FUNC AS_GPIO +#endif +#ifndef PA4_FUNC +#define PA4_FUNC AS_GPIO +#endif +#ifndef PA5_FUNC +#define PA5_FUNC AS_GPIO +#endif +#ifndef PA6_FUNC +#define PA6_FUNC AS_GPIO +#endif +#ifndef PA7_FUNC +#define PA7_FUNC AS_SWIRE +#endif +#ifndef PULL_WAKEUP_SRC_PA0 +#define PULL_WAKEUP_SRC_PA0 0 +#endif +#ifndef PULL_WAKEUP_SRC_PA1 +#define PULL_WAKEUP_SRC_PA1 0 +#endif +#ifndef PULL_WAKEUP_SRC_PA2 +#define PULL_WAKEUP_SRC_PA2 0 +#endif +#ifndef PULL_WAKEUP_SRC_PA3 +#define PULL_WAKEUP_SRC_PA3 0 +#endif +#ifndef PULL_WAKEUP_SRC_PA4 +#define PULL_WAKEUP_SRC_PA4 0 +#endif +#ifndef PULL_WAKEUP_SRC_PA5 +#define PULL_WAKEUP_SRC_PA5 0 +#endif +#ifndef PULL_WAKEUP_SRC_PA6 +#define PULL_WAKEUP_SRC_PA6 0 +#endif +#ifndef PULL_WAKEUP_SRC_PA7 +#define PULL_WAKEUP_SRC_PA7 PM_PIN_PULLUP_1M /* sws pullup */ +#endif + +/* GPIO GROUP B Default Definition */ + +#ifndef PB0_INPUT_ENABLE +#define PB0_INPUT_ENABLE 0 +#endif +#ifndef PB1_INPUT_ENABLE +#define PB1_INPUT_ENABLE 0 +#endif +#ifndef PB2_INPUT_ENABLE +#define PB2_INPUT_ENABLE 0 +#endif +#ifndef PB3_INPUT_ENABLE +#define PB3_INPUT_ENABLE 0 +#endif +#ifndef PB4_INPUT_ENABLE +#define PB4_INPUT_ENABLE 0 +#endif +#ifndef PB5_INPUT_ENABLE +#define PB5_INPUT_ENABLE 0 +#endif +#ifndef PB6_INPUT_ENABLE +#define PB6_INPUT_ENABLE 0 +#endif +#ifndef PB7_INPUT_ENABLE +#define PB7_INPUT_ENABLE 0 +#endif +#ifndef PB0_OUTPUT_ENABLE +#define PB0_OUTPUT_ENABLE 0 +#endif +#ifndef PB1_OUTPUT_ENABLE +#define PB1_OUTPUT_ENABLE 0 +#endif +#ifndef PB2_OUTPUT_ENABLE +#define PB2_OUTPUT_ENABLE 0 +#endif +#ifndef PB3_OUTPUT_ENABLE +#define PB3_OUTPUT_ENABLE 0 +#endif +#ifndef PB4_OUTPUT_ENABLE +#define PB4_OUTPUT_ENABLE 0 +#endif +#ifndef PB5_OUTPUT_ENABLE +#define PB5_OUTPUT_ENABLE 0 +#endif +#ifndef PB6_OUTPUT_ENABLE +#define PB6_OUTPUT_ENABLE 0 +#endif +#ifndef PB7_OUTPUT_ENABLE +#define PB7_OUTPUT_ENABLE 0 +#endif +#ifndef PB0_DATA_STRENGTH +#define PB0_DATA_STRENGTH 1 +#endif +#ifndef PB1_DATA_STRENGTH +#define PB1_DATA_STRENGTH 1 +#endif +#ifndef PB2_DATA_STRENGTH +#define PB2_DATA_STRENGTH 1 +#endif +#ifndef PB3_DATA_STRENGTH +#define PB3_DATA_STRENGTH 1 +#endif +#ifndef PB4_DATA_STRENGTH +#define PB4_DATA_STRENGTH 1 +#endif +#ifndef PB5_DATA_STRENGTH +#define PB5_DATA_STRENGTH 1 +#endif +#ifndef PB6_DATA_STRENGTH +#define PB6_DATA_STRENGTH 1 +#endif +#ifndef PB7_DATA_STRENGTH +#define PB7_DATA_STRENGTH 1 +#endif +#ifndef PB0_DATA_OUT +#define PB0_DATA_OUT 0 +#endif +#ifndef PB1_DATA_OUT +#define PB1_DATA_OUT 0 +#endif +#ifndef PB2_DATA_OUT +#define PB2_DATA_OUT 0 +#endif +#ifndef PB3_DATA_OUT +#define PB3_DATA_OUT 0 +#endif +#ifndef PB4_DATA_OUT +#define PB4_DATA_OUT 0 +#endif +#ifndef PB5_DATA_OUT +#define PB5_DATA_OUT 0 +#endif +#ifndef PB6_DATA_OUT +#define PB6_DATA_OUT 0 +#endif +#ifndef PB7_DATA_OUT +#define PB7_DATA_OUT 0 +#endif +#ifndef PB0_FUNC +#define PB0_FUNC AS_GPIO +#endif +#ifndef PB1_FUNC +#define PB1_FUNC AS_GPIO +#endif +#ifndef PB2_FUNC +#define PB2_FUNC AS_GPIO +#endif +#ifndef PB3_FUNC +#define PB3_FUNC AS_GPIO +#endif +#ifndef PB4_FUNC +#define PB4_FUNC AS_GPIO +#endif +#ifndef PB5_FUNC +#define PB5_FUNC AS_GPIO +#endif +#ifndef PB6_FUNC +#define PB6_FUNC AS_GPIO +#endif +#ifndef PB7_FUNC +#define PB7_FUNC AS_GPIO +#endif +#ifndef PULL_WAKEUP_SRC_PB0 +#define PULL_WAKEUP_SRC_PB0 0 +#endif +#ifndef PULL_WAKEUP_SRC_PB1 +#define PULL_WAKEUP_SRC_PB1 0 +#endif +#ifndef PULL_WAKEUP_SRC_PB2 +#define PULL_WAKEUP_SRC_PB2 0 +#endif +#ifndef PULL_WAKEUP_SRC_PB3 +#define PULL_WAKEUP_SRC_PB3 0 +#endif +#ifndef PULL_WAKEUP_SRC_PB4 +#define PULL_WAKEUP_SRC_PB4 0 +#endif +#ifndef PULL_WAKEUP_SRC_PB5 +#define PULL_WAKEUP_SRC_PB5 0 +#endif +#ifndef PULL_WAKEUP_SRC_PB6 +#define PULL_WAKEUP_SRC_PB6 0 +#endif +#ifndef PULL_WAKEUP_SRC_PB7 +#define PULL_WAKEUP_SRC_PB7 0 +#endif + +/* GPIO GROUP C Default Definition */ + +#ifndef PC0_INPUT_ENABLE +#define PC0_INPUT_ENABLE 0 +#endif +#ifndef PC1_INPUT_ENABLE +#define PC1_INPUT_ENABLE 0 +#endif +#ifndef PC2_INPUT_ENABLE +#define PC2_INPUT_ENABLE 0 +#endif +#ifndef PC3_INPUT_ENABLE +#define PC3_INPUT_ENABLE 0 +#endif +#ifndef PC4_INPUT_ENABLE +#define PC4_INPUT_ENABLE 0 +#endif +#ifndef PC5_INPUT_ENABLE +#define PC5_INPUT_ENABLE 0 +#endif +#ifndef PC6_INPUT_ENABLE +#define PC6_INPUT_ENABLE 0 +#endif +#ifndef PC7_INPUT_ENABLE +#define PC7_INPUT_ENABLE 0 +#endif +#ifndef PC0_OUTPUT_ENABLE +#define PC0_OUTPUT_ENABLE 0 +#endif +#ifndef PC1_OUTPUT_ENABLE +#define PC1_OUTPUT_ENABLE 0 +#endif +#ifndef PC2_OUTPUT_ENABLE +#define PC2_OUTPUT_ENABLE 0 +#endif +#ifndef PC3_OUTPUT_ENABLE +#define PC3_OUTPUT_ENABLE 0 +#endif +#ifndef PC4_OUTPUT_ENABLE +#define PC4_OUTPUT_ENABLE 0 +#endif +#ifndef PC5_OUTPUT_ENABLE +#define PC5_OUTPUT_ENABLE 0 +#endif +#ifndef PC6_OUTPUT_ENABLE +#define PC6_OUTPUT_ENABLE 0 +#endif +#ifndef PC7_OUTPUT_ENABLE +#define PC7_OUTPUT_ENABLE 0 +#endif +#ifndef PC0_DATA_STRENGTH +#define PC0_DATA_STRENGTH 1 +#endif +#ifndef PC1_DATA_STRENGTH +#define PC1_DATA_STRENGTH 1 +#endif +#ifndef PC2_DATA_STRENGTH +#define PC2_DATA_STRENGTH 1 +#endif +#ifndef PC3_DATA_STRENGTH +#define PC3_DATA_STRENGTH 1 +#endif +#ifndef PC4_DATA_STRENGTH +#define PC4_DATA_STRENGTH 1 +#endif +#ifndef PC5_DATA_STRENGTH +#define PC5_DATA_STRENGTH 1 +#endif +#ifndef PC6_DATA_STRENGTH +#define PC6_DATA_STRENGTH 1 +#endif +#ifndef PC7_DATA_STRENGTH +#define PC7_DATA_STRENGTH 1 +#endif +#ifndef PC0_DATA_OUT +#define PC0_DATA_OUT 0 +#endif +#ifndef PC1_DATA_OUT +#define PC1_DATA_OUT 0 +#endif +#ifndef PC2_DATA_OUT +#define PC2_DATA_OUT 0 +#endif +#ifndef PC3_DATA_OUT +#define PC3_DATA_OUT 0 +#endif +#ifndef PC4_DATA_OUT +#define PC4_DATA_OUT 0 +#endif +#ifndef PC5_DATA_OUT +#define PC5_DATA_OUT 0 +#endif +#ifndef PC6_DATA_OUT +#define PC6_DATA_OUT 0 +#endif +#ifndef PC7_DATA_OUT +#define PC7_DATA_OUT 0 +#endif +#ifndef PC0_FUNC +#define PC0_FUNC AS_GPIO +#endif +#ifndef PC1_FUNC +#define PC1_FUNC AS_GPIO +#endif +#ifndef PC2_FUNC +#define PC2_FUNC AS_GPIO +#endif +#ifndef PC3_FUNC +#define PC3_FUNC AS_GPIO +#endif +#ifndef PC4_FUNC +#define PC4_FUNC AS_GPIO +#endif +#ifndef PC5_FUNC +#define PC5_FUNC AS_GPIO +#endif +#ifndef PC6_FUNC +#define PC6_FUNC AS_GPIO +#endif +#ifndef PC7_FUNC +#define PC7_FUNC AS_GPIO +#endif +#ifndef PULL_WAKEUP_SRC_PC0 +#define PULL_WAKEUP_SRC_PC0 0 +#endif +#ifndef PULL_WAKEUP_SRC_PC1 +#define PULL_WAKEUP_SRC_PC1 0 +#endif +#ifndef PULL_WAKEUP_SRC_PC2 +#define PULL_WAKEUP_SRC_PC2 0 +#endif +#ifndef PULL_WAKEUP_SRC_PC3 +#define PULL_WAKEUP_SRC_PC3 0 +#endif +#ifndef PULL_WAKEUP_SRC_PC4 +#define PULL_WAKEUP_SRC_PC4 0 +#endif +#ifndef PULL_WAKEUP_SRC_PC5 +#define PULL_WAKEUP_SRC_PC5 0 +#endif +#ifndef PULL_WAKEUP_SRC_PC6 +#define PULL_WAKEUP_SRC_PC6 0 +#endif +#ifndef PULL_WAKEUP_SRC_PC7 +#define PULL_WAKEUP_SRC_PC7 0 +#endif + +/* GPIO GROUP D Default Definition */ + +#ifndef PD0_INPUT_ENABLE +#define PD0_INPUT_ENABLE 0 +#endif +#ifndef PD1_INPUT_ENABLE +#define PD1_INPUT_ENABLE 0 +#endif +#ifndef PD2_INPUT_ENABLE +#define PD2_INPUT_ENABLE 0 +#endif +#ifndef PD3_INPUT_ENABLE +#define PD3_INPUT_ENABLE 0 +#endif +#ifndef PD4_INPUT_ENABLE +#define PD4_INPUT_ENABLE 0 +#endif +#ifndef PD5_INPUT_ENABLE +#define PD5_INPUT_ENABLE 0 +#endif +#ifndef PD6_INPUT_ENABLE +#define PD6_INPUT_ENABLE 0 +#endif +#ifndef PD7_INPUT_ENABLE +#define PD7_INPUT_ENABLE 0 +#endif +#ifndef PD0_OUTPUT_ENABLE +#define PD0_OUTPUT_ENABLE 0 +#endif +#ifndef PD1_OUTPUT_ENABLE +#define PD1_OUTPUT_ENABLE 0 +#endif +#ifndef PD2_OUTPUT_ENABLE +#define PD2_OUTPUT_ENABLE 0 +#endif +#ifndef PD3_OUTPUT_ENABLE +#define PD3_OUTPUT_ENABLE 0 +#endif +#ifndef PD4_OUTPUT_ENABLE +#define PD4_OUTPUT_ENABLE 0 +#endif +#ifndef PD5_OUTPUT_ENABLE +#define PD5_OUTPUT_ENABLE 0 +#endif +#ifndef PD6_OUTPUT_ENABLE +#define PD6_OUTPUT_ENABLE 0 +#endif +#ifndef PD7_OUTPUT_ENABLE +#define PD7_OUTPUT_ENABLE 0 +#endif +#ifndef PD0_DATA_STRENGTH +#define PD0_DATA_STRENGTH 1 +#endif +#ifndef PD1_DATA_STRENGTH +#define PD1_DATA_STRENGTH 1 +#endif +#ifndef PD2_DATA_STRENGTH +#define PD2_DATA_STRENGTH 1 +#endif +#ifndef PD3_DATA_STRENGTH +#define PD3_DATA_STRENGTH 1 +#endif +#ifndef PD4_DATA_STRENGTH +#define PD4_DATA_STRENGTH 1 +#endif +#ifndef PD5_DATA_STRENGTH +#define PD5_DATA_STRENGTH 1 +#endif +#ifndef PD6_DATA_STRENGTH +#define PD6_DATA_STRENGTH 1 +#endif +#ifndef PD7_DATA_STRENGTH +#define PD7_DATA_STRENGTH 1 +#endif +#ifndef PD0_DATA_OUT +#define PD0_DATA_OUT 0 +#endif +#ifndef PD1_DATA_OUT +#define PD1_DATA_OUT 0 +#endif +#ifndef PD2_DATA_OUT +#define PD2_DATA_OUT 0 +#endif +#ifndef PD3_DATA_OUT +#define PD3_DATA_OUT 0 +#endif +#ifndef PD4_DATA_OUT +#define PD4_DATA_OUT 0 +#endif +#ifndef PD5_DATA_OUT +#define PD5_DATA_OUT 0 +#endif +#ifndef PD6_DATA_OUT +#define PD6_DATA_OUT 0 +#endif +#ifndef PD7_DATA_OUT +#define PD7_DATA_OUT 0 +#endif +#ifndef PD0_FUNC +#define PD0_FUNC AS_GPIO +#endif +#ifndef PD1_FUNC +#define PD1_FUNC AS_GPIO +#endif +#ifndef PD2_FUNC +#define PD2_FUNC AS_GPIO +#endif +#ifndef PD3_FUNC +#define PD3_FUNC AS_GPIO +#endif +#ifndef PD4_FUNC +#define PD4_FUNC AS_GPIO +#endif +#ifndef PD5_FUNC +#define PD5_FUNC AS_GPIO +#endif +#ifndef PD6_FUNC +#define PD6_FUNC AS_GPIO +#endif +#ifndef PD7_FUNC +#define PD7_FUNC AS_GPIO +#endif +#ifndef PULL_WAKEUP_SRC_PD0 +#define PULL_WAKEUP_SRC_PD0 0 +#endif +#ifndef PULL_WAKEUP_SRC_PD1 +#define PULL_WAKEUP_SRC_PD1 0 +#endif +#ifndef PULL_WAKEUP_SRC_PD2 +#define PULL_WAKEUP_SRC_PD2 0 +#endif +#ifndef PULL_WAKEUP_SRC_PD3 +#define PULL_WAKEUP_SRC_PD3 0 +#endif +#ifndef PULL_WAKEUP_SRC_PD4 +#define PULL_WAKEUP_SRC_PD4 0 +#endif +#ifndef PULL_WAKEUP_SRC_PD5 +#define PULL_WAKEUP_SRC_PD5 0 +#endif +#ifndef PULL_WAKEUP_SRC_PD6 +#define PULL_WAKEUP_SRC_PD6 0 +#endif +#ifndef PULL_WAKEUP_SRC_PD7 +#define PULL_WAKEUP_SRC_PD7 0 +#endif + +/* GPIO GROUP E Default Definition */ + +#ifndef PE0_INPUT_ENABLE +#define PE0_INPUT_ENABLE 1 /* MSPI */ +#endif +#ifndef PE1_INPUT_ENABLE +#define PE1_INPUT_ENABLE 1 /* MSPI */ +#endif +#ifndef PE2_INPUT_ENABLE +#define PE2_INPUT_ENABLE 1 /* MSPI */ +#endif +#ifndef PE3_INPUT_ENABLE +#define PE3_INPUT_ENABLE 1 /* MSPI */ +#endif +#ifndef PE0_OUTPUT_ENABLE +#define PE0_OUTPUT_ENABLE 0 +#endif +#ifndef PE1_OUTPUT_ENABLE +#define PE1_OUTPUT_ENABLE 0 +#endif +#ifndef PE2_OUTPUT_ENABLE +#define PE2_OUTPUT_ENABLE 0 +#endif +#ifndef PE3_OUTPUT_ENABLE +#define PE3_OUTPUT_ENABLE 0 +#endif + +#ifndef PE0_DATA_STRENGTH +#define PE0_DATA_STRENGTH 1 +#endif +#ifndef PE1_DATA_STRENGTH +#define PE1_DATA_STRENGTH 1 +#endif +#ifndef PE2_DATA_STRENGTH +#define PE2_DATA_STRENGTH 1 +#endif +#ifndef PE3_DATA_STRENGTH +#define PE3_DATA_STRENGTH 1 +#endif + +#ifndef PE0_DATA_OUT +#define PE0_DATA_OUT 0 +#endif +#ifndef PE1_DATA_OUT +#define PE1_DATA_OUT 0 +#endif +#ifndef PE2_DATA_OUT +#define PE2_DATA_OUT 0 +#endif +#ifndef PE3_DATA_OUT +#define PE3_DATA_OUT 0 +#endif + +#ifndef PE0_FUNC +#define PE0_FUNC AS_MSPI +#endif +#ifndef PE1_FUNC +#define PE1_FUNC AS_MSPI +#endif +#ifndef PE2_FUNC +#define PE2_FUNC AS_MSPI +#endif +#ifndef PE3_FUNC +#define PE3_FUNC AS_MSPI +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This enum is from telink sdk */ + +enum gpio_func_e +{ + AS_GPIO = 0, + AS_MSPI = 1, + AS_SWIRE = 2, + AS_UART = 3, + AS_I2C = 4, + AS_SPI = 5, + AS_I2S = 6, + AS_AMIC = 7, + AS_DMIC = 8, + AS_SDM = 9, + AS_USB = 10, + AS_ADC = 11, + AS_CMP = 12, + AS_ATS = 13, + AS_PWM0 = 20, + AS_PWM1 = 21, + AS_PWM2 = 22, + AS_PWM3 = 23, + AS_PWM4 = 24, + AS_PWM5 = 25, + AS_PWM0_N = 26, + AS_PWM1_N = 27, + AS_PWM2_N = 28, + AS_PWM3_N = 29, + AS_PWM4_N = 30, + AS_PWM5_N = 31, +}; + +#endif /* __ARCH_ARM_SRC_TLSR82_TLSR82_GPIO_DEFAULT_H */ diff --git a/arch/arm/src/tlsr82/tlsr82_irq.c b/arch/arm/src/tlsr82/tlsr82_irq.c new file mode 100644 index 0000000000000..5e6bc823ba38b --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_irq.c @@ -0,0 +1,76 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_irq.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "arm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* g_current_regs[] holds a references to the current interrupt level + * register storage structure. If is non-NULL only during interrupt + * processing. Access to g_current_regs[] must be through the macro + * CURRENT_REGS for portability. + */ + +volatile uint32_t *g_current_regs[CONFIG_SMP_NCPUS]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_irqinitialize + ****************************************************************************/ + +void up_irqinitialize(void) +{ + int i; + + /* Disable all the interrupts */ + + up_irq_disable(); + + for (i = 0; i < NR_IRQS; i++) + { + up_disable_irq(i); + } + + /* currents_regs is non-NULL only while processing an interrupt */ + + CURRENT_REGS = NULL; + + /* And finally, enable interrupts */ + + up_irq_enable(); +} + diff --git a/arch/arm/src/tlsr82/tlsr82_mspi.c b/arch/arm/src/tlsr82/tlsr82_mspi.c new file mode 100644 index 0000000000000..a182396336ad9 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_mspi.c @@ -0,0 +1,41 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_mspi.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "tlsr82_mspi.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ diff --git a/arch/arm/src/tlsr82/tlsr82_mspi.h b/arch/arm/src/tlsr82/tlsr82_mspi.h new file mode 100644 index 0000000000000..5efbd3a72e15f --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_mspi.h @@ -0,0 +1,67 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_mspi.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_TLSR82_MSPI_H +#define __ARCH_ARM_SRC_TLSR82_TLSR82_MSPI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" + +#include "hardware/tlsr82_mspi.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_TLSR82_TLSR82_MSPI_H */ diff --git a/arch/arm/src/tlsr82/tlsr82_pwm.c b/arch/arm/src/tlsr82/tlsr82_pwm.c new file mode 100644 index 0000000000000..c76045423966b --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_pwm.c @@ -0,0 +1,897 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_pwm.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "arm_internal.h" + +#include "chip.h" +#include "tlsr82_pwm.h" +#include "tlsr82_gpio.h" +#include "tlsr82_gpio_cfg.h" + +#include "hardware/tlsr82_pwm.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The pwm clock source is system clock */ + +#define PWM_SRC_CLK_HZ (CONFIG_TLSR82_CPU_CLK_MHZ * 1000000) + +/* The default clkdiv = 9, default pwm clk = PWM_SRC_CLK_HZ / 10 */ + +#define PWM_INIT_CLKDIV 9 + +/* Make sure the max frequency has at least 1% duty accruay */ + +#define PWM_MAX_FREQ (g_pwmclk / 100) +#define PWM_MIN_FREQ (g_pwmclk / UINT16_MAX + 1) + +/* PWM simple operation definition */ + +#define PWM_INT_PEND(id) BM_IS_SET(PWM_IRQ_STA_REG, 1 << ((id) + 2)) +#define PWM_INT_CLEAR(id) BM_CLR(PWM_IRQ_STA_REG, 1 << ((id) + 2)) +#define PWM_INT_ENABLE(id) BM_SET(PWM_IRQ_CTRL_REG, 1 << ((id) + 2)) +#define PWM_INT_DISABLE(id) BM_CLR(PWM_IRQ_CTRL_REG, 1 << ((id) + 2)) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure represents the state of one PWM timer */ + +struct tlsr82_pwmtimer_s +{ + const struct pwm_ops_s *ops; /* PWM operations */ + uint32_t pincfg; /* PWM pin config */ + uint8_t id; /* PWM hardware id */ + bool invert; /* PWM output is inverted or not */ + bool started; /* PWM output has started or not */ +#ifdef CONFIG_PWM_PULSECOUNT + uint8_t irq; /* Timer update IRQ */ + uint8_t prev; /* The previous value of the RCR (pre-loaded) */ + uint8_t curr; /* The current value of the RCR (pre-loaded) */ + uint32_t count; /* Remaining pulse count */ +#else + uint32_t frequency; /* Current frequency setting */ +#endif + uint16_t max; + uint16_t cmp; +#ifdef CONFIG_PWM_PULSECOUNT + void *handle; /* Handle used for upper-half callback */ +#endif +}; + +/**************************************************************************** + * Static Function Prototypes + ****************************************************************************/ + +/* Register access */ + +#ifdef CONFIG_DEBUG_PWM_INFO +static void pwm_dumpregs(const char *msg); +#else +# define pwm_dumpregs(msg) +#endif + +/* Timer management */ + +static void pwm_enable(struct tlsr82_pwmtimer_s *priv, bool en); +static int pwm_cfg_check(struct tlsr82_pwmtimer_s *priv); +static int pwm_config(struct tlsr82_pwmtimer_s *priv, + const struct pwm_info_s *info); + +#if defined(CONFIG_PWM_PULSECOUNT) +static int pwm_interrupt(struct tlsr82_pwmtimer_s *priv); +static uint8_t pwm_pulsecount(uint32_t count); +#endif + +/* PWM driver methods */ + +static int pwm_setup(struct pwm_lowerhalf_s *dev); +static int pwm_shutdown(struct pwm_lowerhalf_s *dev); + +#ifdef CONFIG_PWM_PULSECOUNT +static int pwm_start(struct pwm_lowerhalf_s *dev, + const struct pwm_info_s *info, + void *handle); +#else +static int pwm_start(struct pwm_lowerhalf_s *dev, + const struct pwm_info_s *info); +#endif + +static int pwm_stop(struct pwm_lowerhalf_s *dev); +static int pwm_ioctl(struct pwm_lowerhalf_s *dev, + int cmd, unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static uint32_t g_pwmclk; + +/* This is the list of lower half PWM driver methods used by the upper half + * driver + */ + +static const struct pwm_ops_s g_pwmops = +{ + .setup = pwm_setup, + .shutdown = pwm_shutdown, + .start = pwm_start, + .stop = pwm_stop, + .ioctl = pwm_ioctl, +}; + +static struct tlsr82_pwmtimer_s g_pwm1dev = +{ + .ops = &g_pwmops, + .pincfg = GPIO_PIN_PD3 | GPIO_AF_MUX0, + .id = 1, + .invert = true, + .started = false, +#ifdef CONFIG_PWM_PULSECOUNT + .irq = NR_SW_PWM_IRQ, +#endif +}; + +static struct tlsr82_pwmtimer_s g_pwm2dev = +{ + .ops = &g_pwmops, + .pincfg = GPIO_PIN_PD4 | GPIO_AF_MUX2, + .id = 2, + .invert = true, + .started = false, +#ifdef CONFIG_PWM_PULSECOUNT + .irq = NR_SW_PWM_IRQ, +#endif +}; + +static struct tlsr82_pwmtimer_s g_pwm3dev = +{ + .ops = &g_pwmops, + .pincfg = GPIO_PIN_PB4 | GPIO_AF_MUX1, + .id = 3, + .invert = false, + .started = false, +#ifdef CONFIG_PWM_PULSECOUNT + .irq = NR_SW_PWM_IRQ, +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pwm_dumpregs + * + * Description: + * Dump all pwm registers. + * + * Input Parameters: + * msg - message. + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_PWM_INFO +static void pwm_dumpregs(const char *msg) +{ + int i; + pwminfo("%s:\n", msg); + pwminfo("PWM_CLKDIV_REG : 0x%x\n", PWM_CLKDIV_REG); + pwminfo("PWM_ENABLE0_REG : 0x%x\n", PWM_ENABLE0_REG); + pwminfo("PWM_MODE0_REG : 0x%x\n", PWM_MODE0_REG); + pwminfo("PWM_ENABLE_REG : 0x%x\n", PWM_ENABLE_REG); + pwminfo("PWM_INVERT_REG : 0x%x\n", PWM_INVERT_REG); + pwminfo("PWM_N_INVERT_REG : 0x%x\n", PWM_N_INVERT_REG); + pwminfo("PWM_POL_REG : 0x%x\n", PWM_POL_REG); + + for (i = 0; i < 5; i++) + { + pwminfo("PWM_CYCLE_REG(%d): 0x%lx\n", i, PWM_CYCLE_REG(i)); + pwminfo("PWM_CMP_REG(%d) : 0x%x\n", i, PWM_CMP_REG(i)); + pwminfo("PWM_MAX_REG(%d) : 0x%x\n", i, PWM_MAX_REG(i)); + } + + pwminfo("PWM_PLUSE_NUM_RE : 0x%x\n", PWM_PLUSE_NUM_REG); + pwminfo("PWM_IRQ_CTRL_REG : 0x%x\n", PWM_IRQ_CTRL_REG); + pwminfo("PWM_IRQ_STA_REG : 0x%x\n", PWM_IRQ_STA_REG); +} +#endif + +/**************************************************************************** + * Name: pwm_config + * + * Description: + * (Re-)initialize the timer resources and start the pulsed output + * + * Input Parameters: + * priv - A reference to the lower half PWM driver state structure + * info - A reference to the characteristics of the pulsed output + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_config(struct tlsr82_pwmtimer_s *priv, + const struct pwm_info_s *info) +{ + /* Calculated values */ + + uint16_t max; + uint16_t cmp; + + if (priv == NULL || info == NULL) + { + pwmerr("priv or info is null, priv=0x%p info=0x%p\n", priv, info); + return -EINVAL; + } + + pwminfo("PWM%d invert: %d frequency: %lu duty: %08lx\n", + (int)priv->id, (int)priv->invert, info->frequency, + info->duty); + + if (info->frequency == 0 || info->duty >= uitoub16(100)) + { + pwrerr("pwm info is invalid, fre: %lu duty: %08lx\n", + info->frequency, info->duty); + return -EINVAL; + } + + if (info->frequency > PWM_MAX_FREQ || info->frequency < PWM_MIN_FREQ) + { + pwmerr("pwm freq out of range, freq: %ld, max: %ld, min: %ld\n", + info->frequency, PWM_MAX_FREQ, PWM_MIN_FREQ); + return -EINVAL; + } + + /* Calculate the MAX and CMP register value + * period = max_reg / g_pwmclk + * freq = g_pwmclk / max_reg + */ + + max = (uint16_t)((g_pwmclk / info->frequency)); + + cmp = (uint16_t)((((uint64_t)max * (uint64_t)info->duty) >> 16) / + (uint64_t)100); + + pwminfo("PWM%d PCLK: %lu freq: %lu duty: %lu max: %u cmp: %u\n", + priv->id, g_pwmclk, info->frequency, info->duty, max, cmp); + + priv->max = max; + priv->cmp = cmp; + + if (!priv->started) + { + PWM_MAX_REG(priv->id) = priv->max; + PWM_CMP_REG(priv->id) = priv->cmp; + pwm_enable(priv, true); + } + + return OK; +} + +#ifndef CONFIG_PWM_PULSECOUNT +/**************************************************************************** + * Name: pwm_update_duty + * + * Description: + * Try to change only channel duty. + * + * Input Parameters: + * priv - A reference to the lower half PWM driver state structure + * duty - New duty. + * Maximum: 65535/65536 (0x0000ffff) ==> 0.99998474 + * Minimum: 1/65536 (0x00000001) ==> 0.00001526 + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_update_duty(struct tlsr82_pwmtimer_s *priv, ub16_t duty) +{ + uint8_t id = priv->id; + uint32_t max; + uint16_t cmp = 0; + + if (duty >= uitoub16(100)) + { + pwmerr("Duty is too large, duty=%ld\n", duty); + return -EINVAL; + } + + max = (uint32_t)PWM_MAX_REG(id); + + cmp = (uint16_t)(ub16toi(max * duty) / 100); + + PWM_CMP_REG(id) = cmp; + + pwm_enable(priv, true); + + return OK; +} +#endif + +/**************************************************************************** + * Name: pwm_interrupt + * + * Description: + * Handle timer interrupts. + * + * Input Parameters: + * priv - A reference to the lower half PWM driver state structure + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +#if defined(CONFIG_PWM_PULSECOUNT) +static int pwm_interrupt(struct tlsr82_pwmtimer_s *priv) +{ + uint16_t regval; + + /* Verify that this is an update interrupt. Nothing else is expected. */ + + regval = pwm_getreg(priv, STM32_ATIM_SR_OFFSET); + DEBUGASSERT((regval & ATIM_SR_UIF) != 0); + + /* Clear the UIF interrupt bit */ + + pwm_putreg(priv, STM32_ATIM_SR_OFFSET, regval & ~ATIM_SR_UIF); + + /* Calculate the new count by subtracting the number of pulses + * since the last interrupt. + */ + + if (priv->count <= priv->prev) + { + /* We are finished. Turn off the mast output to stop the output as + * quickly as possible. + */ + + regval = pwm_getreg(priv, STM32_ATIM_BDTR_OFFSET); + regval &= ~ATIM_BDTR_MOE; + pwm_putreg(priv, STM32_ATIM_BDTR_OFFSET, regval); + + /* Disable first interrupts, stop and reset the timer */ + + pwm_stop((struct pwm_lowerhalf_s *)priv); + + /* Then perform the callback into the upper half driver */ + + pwm_expired(priv->handle); + + priv->handle = NULL; + priv->count = 0; + priv->prev = 0; + priv->curr = 0; + } + else + { + /* Decrement the count of pulses remaining using the number of + * pulses generated since the last interrupt. + */ + + priv->count -= priv->prev; + + /* Set up the next RCR. Set 'prev' to the value of the RCR that + * was loaded when the update occurred (just before this interrupt) + * and set 'curr' to the current value of the RCR register (which + * will bet loaded on the next update event). + */ + + priv->prev = priv->curr; + priv->curr = pwm_pulsecount(priv->count - priv->prev); + pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, (uint16_t)priv->curr - 1); + } + + /* Now all of the time critical stuff is done so we can do some debug + * output + */ + + pwminfo("Update interrupt SR: %04x prev: %u curr: %u count: %u\n", + regval, priv->prev, priv->curr, priv->count); + + return OK; +} +#endif + +/**************************************************************************** + * Name: pwm_pulsecount + * + * Description: + * Pick an optimal pulse count to program the RCR. + * + * Input Parameters: + * count - The total count remaining + * + * Returned Value: + * The recommended pulse count + * + ****************************************************************************/ + +#if defined(CONFIG_PWM_PULSECOUNT) +static uint8_t pwm_pulsecount(uint32_t count) +{ + /* The the remaining pulse count is less than or equal to the maximum, the + * just return the count. + */ + + if (count <= ATIM_RCR_REP_MAX) + { + return count; + } + + /* Otherwise, we have to be careful. We do not want a small number of + * counts at the end because we might have trouble responding fast enough. + * If the remaining count is less than 150% of the maximum, then return + * half of the maximum. In this case the final sequence will be between 64 + * and 128. + */ + + else if (count < (3 * ATIM_RCR_REP_MAX / 2)) + { + return (ATIM_RCR_REP_MAX + 1) >> 1; + } + + /* Otherwise, return the maximum. The final count will be 64 or more */ + + else + { + return ATIM_RCR_REP_MAX; + } +} +#endif + +/**************************************************************************** + * Name: pwm_enable + * + * Description: + * Enable or disable APB clock for the timer peripheral + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * on - Enable clock if 'on' is 'true' and disable if 'false' + * + ****************************************************************************/ + +static void pwm_enable(struct tlsr82_pwmtimer_s *priv, bool en) +{ + int id = (int)priv->id; + + if (en) + { + if (priv->started) + { + return; + } + + if (id == 0) + { + BM_SET(PWM_ENABLE0_REG, 1); + } + else + { + BM_SET(PWM_ENABLE_REG, 1 << id); + } + + priv->started = true; + } + else + { + if (!priv->started) + { + return; + } + + if (id == 0) + { + BM_CLR(PWM_ENABLE0_REG, 1); + } + else + { + BM_CLR(PWM_ENABLE_REG, 1 << id); + } + + priv->started = false; + } +} + +/**************************************************************************** + * Name: pwm_cfg_check + * + * Description: + * This method is called when the driver intialize. This function will + * check the pincfg, if pincfg is not valid, this function will call + * PANIC() to assert here. + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + * + ****************************************************************************/ + +static int pwm_cfg_check(struct tlsr82_pwmtimer_s *priv) +{ + uint32_t pincfg = priv->pincfg; + + if (pincfg == GPIO_INVLD_CFG) + { + pwmerr("pwm pincfg is not valid, pincfg=0x%lx\n", pincfg); + PANIC(); + return -EINVAL; + } + + if (tlsr82_gpio_cfg_check(pincfg, TLSR82_MUX_PWM) != 0) + { + pwmerr("pincfg=0x%lx not support pwm mux\n", pincfg); + PANIC(); + return -EINVAL; + } + + return OK; +} + +/**************************************************************************** + * Name: pwm_setup + * + * Description: + * This method is called when the driver is opened. The lower half driver + * should configure and initialize the device so that it is ready for use. + * It should not, however, output pulses until the start method is called. + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + * Assumptions: + * APB1 or 2 clocking for the GPIOs has already been configured by the RCC + * logic at power up. + * + ****************************************************************************/ + +static int pwm_setup(struct pwm_lowerhalf_s *dev) +{ + struct tlsr82_pwmtimer_s *priv = (struct tlsr82_pwmtimer_s *)dev; + uint32_t pincfg; + + pwm_dumpregs("Initially"); + + /* Configure the PWM output pins, but do not start the timer yet */ + + pincfg = priv->pincfg; + + pwminfo("pincfg: %08lx\n", pincfg); + + /* Set the pwm_id_n be inverted to unify the pwm duty config, this + * configuration must precede the gpio configuration, otherwise, the + * gpio output is high between the invert and gpio config, and become + * low after the invert configuration. + */ + + if (priv->invert) + { + BM_SET(PWM_N_INVERT_REG, 1 << priv->id); + } + + tlsr82_gpioconfig(pincfg); + + return OK; +} + +/**************************************************************************** + * Name: pwm_shutdown + * + * Description: + * This method is called when the driver is closed. The lower half driver + * stop pulsed output, free any resources, disable the timer hardware, and + * put the system into the lowest possible power usage state + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_shutdown(struct pwm_lowerhalf_s *dev) +{ + struct tlsr82_pwmtimer_s *priv = (struct tlsr82_pwmtimer_s *)dev; + + /* Make sure that the output has been stopped */ + + pwm_stop(dev); + + /* Then put the GPIO pins back to the default state */ + + tlsr82_gpiounconfig(priv->pincfg); + + return OK; +} + +/**************************************************************************** + * Name: pwm_start + * + * Description: + * (Re-)initialize the timer resources and start the pulsed output + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * info - A reference to the characteristics of the pulsed output + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +#ifdef CONFIG_PWM_PULSECOUNT +static int pwm_start(struct pwm_lowerhalf_s *dev, + const struct pwm_info_s *info, + void *handle) +{ + struct tlsr82_pwmtimer_s *priv = (struct tlsr82_pwmtimer_s *)dev; + + /* Check if a pulsecount has been selected */ + + if (info->count > 0) + { + /* Only the advanced timers (TIM1,8 can support the pulse counting) */ + + if (priv->timtype != TIMTYPE_ADVANCED) + { + pwmerr("ERROR: TIM%u cannot support pulse count: %u\n", + priv->timid, info->count); + return -EPERM; + } + } + + /* Save the handle */ + + priv->handle = handle; + + /* Start the time */ + + return pwm_config(priv, info); +} +#else +static int pwm_start(struct pwm_lowerhalf_s *dev, + const struct pwm_info_s *info) +{ + int ret = OK; + struct tlsr82_pwmtimer_s *priv = (struct tlsr82_pwmtimer_s *)dev; + + /* if frequency has not changed we just update duty */ + + if (info->frequency == priv->frequency) + { + ret = pwm_update_duty(priv, info->duty); + } + else + { + ret = pwm_config(priv, info); + + /* Save current frequency */ + + if (ret == OK) + { + priv->frequency = info->frequency; + } + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: pwm_stop + * + * Description: + * Stop the pulsed output and reset the timer resources + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + * Assumptions: + * This function is called to stop the pulsed output at anytime. This + * method is also called from the timer interrupt handler when a repetition + * count expires... automatically stopping the timer. + * + ****************************************************************************/ + +static int pwm_stop(struct pwm_lowerhalf_s *dev) +{ + struct tlsr82_pwmtimer_s *priv = (struct tlsr82_pwmtimer_s *)dev; + irqstate_t flags; + + pwminfo("PWM%u\n", priv->id); + + /* Disable interrupts momentary to stop any ongoing pwm processing and + * to prevent any concurrent access to the reset register. + */ + + flags = enter_critical_section(); + + /* Disable PWMn output */ + + pwm_enable(priv, false); + + /* Disable PWMn interrupt and clear interrupt flag */ + + PWM_INT_DISABLE(priv->id); + PWM_INT_CLEAR(priv->id); + + leave_critical_section(flags); + + pwm_dumpregs("After stop"); + + return OK; +} + +/**************************************************************************** + * Name: pwm_ioctl + * + * Description: + * Lower-half logic may support platform-specific ioctl commands + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * cmd - The ioctl command + * arg - The argument accompanying the ioctl command + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_ioctl(struct pwm_lowerhalf_s *dev, int cmd, + unsigned long arg) +{ +#ifdef CONFIG_DEBUG_PWM_INFO + struct tlsr82_pwmtimer_s *priv = (struct tlsr82_pwmtimer_s *)dev; + + /* There are no platform-specific ioctl commands */ + + pwminfo("PWM%d\n", priv->id); +#endif + return -ENOTTY; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_pwminitialize + * + * Description: + * Initialize one timer for use with the upper_level PWM driver. + * + * Input Parameters: + * timer - A number identifying the timer use. The number of valid timer + * IDs varies with the STM32 MCU and MCU family but is somewhere in + * the range of {1,..,17}. + * + * Returned Value: + * On success, a pointer to the STM32 lower half PWM driver is returned. + * NULL is returned on any failure. + * + ****************************************************************************/ + +int tlsr82_pwminitialize(const char *devpath, int miror) +{ + struct tlsr82_pwmtimer_s *lower; + int ret = OK; + + static bool pwm_initialized = false; + + if (!pwm_initialized) + { + pwm_initialized = true; + + /* Disable all the output */ + + BM_CLR(PWM_ENABLE0_REG, 0xff); + BM_CLR(PWM_ENABLE_REG, 0xff); + + /* Config the pwm clock */ + + g_pwmclk = PWM_SRC_CLK_HZ / (PWM_INIT_CLKDIV + 1); + PWM_CLKDIV_REG = PWM_INIT_CLKDIV; + + /* Disable all the pwm interrupt and clear all the interrupt flags */ + + BM_CLR(PWM_IRQ_CTRL_REG, 0xff); + BM_SET(PWM_IRQ_STA_REG, 0xff); + + /* Enable the pwm total interrupt */ + + up_enable_irq(NR_SW_PWM_IRQ); + } + + pwminfo("PWM%u\n", miror); + + switch (miror) + { + case 1: + lower = &g_pwm1dev; + break; + + case 2: + lower = &g_pwm2dev; + break; + + case 3: + lower = &g_pwm3dev; + break; + + default: + pwmerr("ERROR: No such pwm configured\n"); + return -EINVAL; + } + + ret = pwm_cfg_check(lower); + if (ret < 0) + { + return ret; + } + + ret = pwm_register(devpath, (struct pwm_lowerhalf_s *)lower); + if (ret < 0) + { + pwmerr("%s has existed\n", devpath); + return ret; + } + + pwm_dumpregs("tlsr82_pwminitialize"); + + return OK; +} diff --git a/arch/arm/src/tlsr82/tlsr82_pwm.h b/arch/arm/src/tlsr82/tlsr82_pwm.h new file mode 100644 index 0000000000000..8fc13f0b7bdb1 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_pwm.h @@ -0,0 +1,84 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_pwm.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_TLSR82_PWM_H +#define __ARCH_ARM_SRC_TLSR82_TLSR82_PWM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" + +#include "hardware/tlsr82_pwm.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define PWM_ENABLE 0x1 +#define PWM_DISABLE 0x0 + +#define PWM_MODE_NORMAL 0x0 +#define PWM_MODE_CNT 0x1 +#define PWM_MODE_IR 0x3 +#define PWM_MODE_IR_FIFO 0x7 +#define PWM_MODE_IR_DMA_FIFO 0xF + +#define PWM_INV_ENABLE 0x1 +#define PWM_INV_DISABLE 0x0 + +#define PWM_POL_HIGH 0x0 +#define PWM_POL_LOW 0x1 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +int tlsr82_pwminitialize(const char *devpath, int miror); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_TLSR82_TLSR82_PWM_H */ diff --git a/arch/arm/src/tlsr82/tlsr82_serial.c b/arch/arm/src/tlsr82/tlsr82_serial.c new file mode 100644 index 0000000000000..92a4ce282fa5a --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_serial.c @@ -0,0 +1,1612 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_serial.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "arm_internal.h" + +#include "hardware/tlsr82_gpio.h" +#include "hardware/tlsr82_register.h" +#include "tlsr82_spi_console.h" +#include "tlsr82_gpio.h" + +#include "hardware/tlsr82_uart.h" +#include "hardware/tlsr82_dma.h" +#include "hardware/tlsr82_clock.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define UART_RAMCODE locate_code(".ram_code") + +#define CONSOLE_PORT 0 +#define CONSOLE_PRIV g_uart0priv +#define CONSOLE_DEV g_uart0_dev + +#define UART0_PIN_TX_MUX GPIO_AF_MUX1 +#define UART0_PIN_RX_MUX GPIO_AF_MUX1 + +#define UART0_PIN_TX GPIO_PIN_PB1 +#define UART0_PIN_RX GPIO_PIN_PB0 + +#define UART0_TX_BUF_SIZE CONFIG_TLSR82_UART0_TX_BUF_SIZE +#define UART0_RX_BUF_SIZE CONFIG_TLSR82_UART0_RX_BUF_SIZE + +#define UART0_TXDMA_BUF_SIZE CONFIG_TLSR82_UART0_TXDMA_BUF_SIZE +#define UART0_RXDMA_BUF_SIZE CONFIG_TLSR82_UART0_RXDMA_BUF_SIZE + +#define DMA_HEAD_LEN 4 + +#ifdef CONFIG_SERIAL_TXDMA +# if UART0_TXDMA_BUF_SIZE > UINT8_MAX +# error "UART0 Tx dma buffer size must less than 255" +# endif + +# if (UART0_TXDMA_BUF_SIZE % 16) != 0 +# error "UART0 Tx dma buffer size must be multiple of 16" +# endif + +# if UART0_TXDMA_BUF_SIZE < UART0_TX_BUF_SIZE +# warning "UART0 Tx dma buffer size better larger than tx buffer size" +# endif +#endif + +#ifdef CONFIG_SERIAL_RXDMA +# if UART0_RXDMA_BUF_SIZE > UINT8_MAX +# error "UART0 Rx dma buffer size must less than 255" +# endif + +# if (UART0_RXDMA_BUF_SIZE % 16) != 0 +# error "UART0 Rx dma buffer size must be multiple of 16" +# endif + +# if UART0_RXDMA_BUF_SIZE < UART0_RX_BUF_SIZE +# warning "UART0 Rx dma buffer size better larger than rx buffer size" +# endif +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +typedef struct +{ + uint32_t baud; + uint32_t port; + uint32_t irq; + uint32_t txpin; + uint32_t rxpin; + uint32_t parity; + uint32_t stopbits; + bool txdma; + bool rxdma; +#ifdef CONFIG_SERIAL_TXDMA + sem_t *txdmasem; + char *txdmabuf; + uint32_t txdmasize; +#endif +#ifdef CONFIG_SERIAL_RXDMA + char *rxdmabuf; + uint32_t rxdmasize; + uint32_t rxdmaindex; + uint32_t rxdmalen; +#endif +} uart_priv_t; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Uart interrupt handler */ + +static int UART_RAMCODE tlsr82_interrupt(int irq, void *context, void *arg); + +#if defined(CONFIG_SERIAL_RXDMA) || defined(CONFIG_SERIAL_TXDMA) +static int UART_RAMCODE tlsr82_dma_interrupt(int irq, void *context, + void *arg); +#endif + +/* Uart operation function */ + +static int tlsr82_uart_setup(struct uart_dev_s *dev); +static void tlsr82_uart_shutdown(struct uart_dev_s *dev); +static int tlsr82_uart_attach(struct uart_dev_s *dev); +static void tlsr82_uart_detach(struct uart_dev_s *dev); +static int tlsr82_uart_ioctl(struct file *filep, int cmd, + unsigned long arg); +static void tlsr82_uart_rxint(struct uart_dev_s *dev, bool enable); +static void tlsr82_uart_txint(uart_dev_t *dev, bool enable); +static int UART_RAMCODE tlsr82_uart_receive(struct uart_dev_s *dev, + unsigned int * status); +static bool UART_RAMCODE tlsr82_uart_rxavailable(struct uart_dev_s *dev); +static void UART_RAMCODE tlsr82_uart_send(struct uart_dev_s *dev, int ch); +static bool UART_RAMCODE tlsr82_uart_txready(struct uart_dev_s *dev); +static bool UART_RAMCODE tlsr82_uart_txempty(struct uart_dev_s *dev); + +#ifdef CONFIG_SERIAL_RXDMA +static void tlsr82_uart_dma_rxint(struct uart_dev_s *dev, bool enable); +static int UART_RAMCODE tlsr82_uart_dma_receive(struct uart_dev_s *dev, + unsigned int * status); +static bool UART_RAMCODE tlsr82_uart_dma_rxavail(struct uart_dev_s *dev); +#endif + +#ifdef CONFIG_SERIAL_TXDMA +static void tlsr82_uart_dma_send(struct uart_dev_s *dev); +static void tlsr82_uart_dma_txavail(struct uart_dev_s *dev); +static void tlsr82_uart_dma_txint(struct uart_dev_s *dev, bool enable); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static uint8_t uart_rxindex; +static uint8_t uart_txindex; + +/* UART operations */ + +#if !defined(CONFIG_TLSR82_UART0_RXDMA) && \ + !defined(CONFIG_TLSR82_UART0_TXDMA) +static const struct uart_ops_s g_uart_ops = +{ + .setup = tlsr82_uart_setup, + .shutdown = tlsr82_uart_shutdown, + .attach = tlsr82_uart_attach, + .detach = tlsr82_uart_detach, + .ioctl = tlsr82_uart_ioctl, + .receive = tlsr82_uart_receive, + .rxint = tlsr82_uart_rxint, + .rxavailable = tlsr82_uart_rxavailable, + .send = tlsr82_uart_send, + .txint = tlsr82_uart_txint, + .txready = tlsr82_uart_txready, + .txempty = tlsr82_uart_txempty, +}; +#elif defined(CONFIG_TLSR82_UART0_RXDMA) && \ + !defined(CONFIG_TLSR82_UART0_TXDMA) +static const struct uart_ops_s g_uart_rxdma_ops = +{ + .setup = tlsr82_uart_setup, + .shutdown = tlsr82_uart_shutdown, + .attach = tlsr82_uart_attach, + .detach = tlsr82_uart_detach, + .ioctl = tlsr82_uart_ioctl, + .receive = tlsr82_uart_dma_receive, + .rxint = tlsr82_uart_dma_rxint, + .rxavailable = tlsr82_uart_dma_rxavail, + .send = tlsr82_uart_send, + .txint = tlsr82_uart_txint, + .txready = tlsr82_uart_txready, + .txempty = tlsr82_uart_txempty, +}; +#elif !defined(CONFIG_TLSR82_UART0_RXDMA) && \ + defined(CONFIG_TLSR82_UART0_TXDMA) +static const struct uart_ops_s g_uart_txdma_ops = +{ + .setup = tlsr82_uart_setup, + .shutdown = tlsr82_uart_shutdown, + .attach = tlsr82_uart_attach, + .detach = tlsr82_uart_detach, + .ioctl = tlsr82_uart_ioctl, + .receive = tlsr82_uart_receive, + .rxint = tlsr82_uart_rxint, + .rxavailable = tlsr82_uart_rxavailable, + .send = tlsr82_uart_send, + .txint = tlsr82_uart_dma_txint, + .txready = tlsr82_uart_txready, + .txempty = tlsr82_uart_txempty, + .dmatxavail = tlsr82_uart_dma_txavail, + .dmasend = tlsr82_uart_dma_send, +}; +#else +static const struct uart_ops_s g_uart_rxtxdma_ops = +{ + .setup = tlsr82_uart_setup, + .shutdown = tlsr82_uart_shutdown, + .attach = tlsr82_uart_attach, + .detach = tlsr82_uart_detach, + .ioctl = tlsr82_uart_ioctl, + .receive = tlsr82_uart_dma_receive, + .rxint = tlsr82_uart_dma_rxint, + .rxavailable = tlsr82_uart_dma_rxavail, + .send = tlsr82_uart_send, + .txint = tlsr82_uart_dma_txint, + .txready = tlsr82_uart_txready, + .txempty = tlsr82_uart_txempty, + .dmatxavail = tlsr82_uart_dma_txavail, + .dmasend = tlsr82_uart_dma_send, +}; +#endif + +static char g_uart0rxbuffer[UART0_RX_BUF_SIZE]; +static char g_uart0txbuffer[UART0_TX_BUF_SIZE]; + +#ifdef CONFIG_TLSR82_UART0_TXDMA +static char g_uart0txdmabuf[UART0_TXDMA_BUF_SIZE + DMA_HEAD_LEN] \ +aligned_data(4); +static sem_t g_uart0txdmasem = SEM_INITIALIZER(1); +#endif + +#ifdef CONFIG_TLSR82_UART0_RXDMA +static char g_uart0rxdmabuf[UART0_RXDMA_BUF_SIZE + DMA_HEAD_LEN] \ +aligned_data(4); +#endif + +/* Private UART config and state */ + +static uart_priv_t g_uart0priv = +{ + .baud = 115200, + .port = 0, + .irq = NR_UART_IRQ, + .parity = 0, + .stopbits = 0, + .txpin = UART0_PIN_TX, + .rxpin = UART0_PIN_RX, +#ifdef CONFIG_TLSR82_UART0_TXDMA + .txdma = true, + .txdmasem = &g_uart0txdmasem, + .txdmabuf = g_uart0txdmabuf, + .txdmasize = UART0_TXDMA_BUF_SIZE, +#else + .txdma = false, +#endif +#ifdef CONFIG_TLSR82_UART0_RXDMA + .rxdma = true, + .rxdmabuf = g_uart0rxdmabuf, + .rxdmasize = UART0_RXDMA_BUF_SIZE, + .rxdmalen = 0, + .rxdmaindex = 0, +#else + .rxdma = false, +#endif +}; + +/* UART device structure */ + +static uart_dev_t g_uart0_dev = +{ + .recv = + { + .size = sizeof(g_uart0rxbuffer), + .buffer = g_uart0rxbuffer, + }, + .xmit = + { + .size = sizeof(g_uart0txbuffer), + .buffer = g_uart0txbuffer, + }, +#if defined(CONFIG_TLSR82_UART0_TXDMA) && defined(CONFIG_TLSR82_UART0_RXDMA) + .ops = &g_uart_rxtxdma_ops, +#elif defined(CONFIG_TLSR82_UART0_TXDMA) && !defined(CONFIG_TLSR82_UART0_RXDMA) + .ops = &g_uart_txdma_ops, +#elif !defined(CONFIG_TLSR82_UART0_TXDMA) && defined(CONFIG_TLSR82_UART0_RXDMA) + .ops = &g_uart_rxdma_ops, +#else + .ops = &g_uart_ops, +#endif + .priv = &g_uart0priv, +}; + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uart_reset + * + * Description: + * Reset the uart hardware, the software pointer must be set to zero + * (function uart_clr_rx_index() must be called). + * + * Parameters: + * void + * + * Returned Values: + * void + * + ****************************************************************************/ + +static inline void uart_reset(void) +{ + RESET_RST0_REG |= RESET_RST0_UART; + RESET_RST0_REG &= ~RESET_RST0_UART; +} + +/**************************************************************************** + * Name: uart_reset + * + * Description: + * Clear the uart receive software pointer, this function must be called + * after wakeup from power-saving mode or reset uart. + * + * Parameters: + * uart_num - the uart hardware index + * + * Returned Values: + * void + * + ****************************************************************************/ + +static inline void uart_clr_rx_index(int uart_num) +{ + uart_rxindex = 0; +} + +/**************************************************************************** + * Name: uart_get_rxfifo_num + * + * Description: + * Get the recieved data numbers in the rx fifo. + * + * Parameters: + * uart_num - the uart hardware index + * + * Returned Values: + * number + * + ****************************************************************************/ + +static inline uint8_t uart_get_rxfifo_num(int uart_num) +{ + return UART_GET_RX_BUF_CNT(); +} + +/**************************************************************************** + * Name: uart_get_txfifo_num + * + * Description: + * Get the transimit data numbers in the tx fifo. + * + * Parameters: + * uart_num - the uart hardware index + * + * Returned Values: + * number + * + ****************************************************************************/ + +static inline uint8_t uart_get_txfifo_num(int uart_num) +{ + return UART_GET_TX_BUF_CNT(); +} + +/**************************************************************************** + * Name: uart_get_irq_status + * + * Description: + * Get the uart interrupt status + * + * Parameters: + * uart_num - the uart hardware index + * flags - interrupt bit mask: UART_IRQ_TXDONE + * UART_IRQ_TXBUF + * UART_IRQ_RXDONE + * UART_IRQ_RXBUF + * + * Returned Values: + * interrupt status: 0, interrupt not occured + * 1, interrupt occured + * + ****************************************************************************/ + +static inline uint8_t uart_get_irq_status(int uart_num, uint8_t flags) +{ + return (UART_IRQ_REG & flags); +} + +/**************************************************************************** + * Name: uart_irq_clr + * + * Description: + * Clear the uart interrupt status + * + * Parameters: + * uart_num - the uart hardware index + * flag - interrupt bit mask: UART_IRQ_CLR_RX + * UART_IRQ_CLR_TX + * + * Returned Values: + * void + * + ****************************************************************************/ + +static inline void uart_irq_clr(int uart_num, uint8_t flag) +{ + BM_SET(UART_IRQ_REG, flag); +} + +/**************************************************************************** + * Name: uart_irq_rx_enable + * + * Description: + * Enable/Disable the uart rx interrupt + * + * Parameters: + * enable - true : enable the rx interrupt + * false: disable the rx interrupt + * + * Returned Values: + * void + * + ****************************************************************************/ + +static inline void uart_irq_rx_enable(bool enable) +{ + if (enable) + { + UART_CTRL0_REG |= UART_CTRL0_RX_IRQ_EN; + } + else + { + UART_CTRL0_REG &= ~UART_CTRL0_RX_IRQ_EN; + } +} + +/**************************************************************************** + * Name: uart_irq_tx_enable + * + * Description: + * Enable/Disable the uart tx interrupt + * + * Parameters: + * enable - true : enable the tx interrupt + * false: disable the tx interrupt + * + * Returned Values: + * void + * + ****************************************************************************/ + +static inline void uart_irq_tx_enable(bool enable) +{ + if (enable) + { + UART_CTRL0_REG |= UART_CTRL0_TX_IRQ_EN; + } + else + { + UART_CTRL0_REG &= ~UART_CTRL0_TX_IRQ_EN; + } +} + +/**************************************************************************** + * Name: uart_txbufirq_isenable + * + * Description: + * Check weather the uart tx buffer interrupt is enable or not + * + * Parameters: + * uart_num - the uart hardware index + * + * Returned Values: + * interrupt is enable or not: 1, enable + * 0, disable + * + ****************************************************************************/ + +static inline int uart_txbufirq_isenable(int uart_num) +{ + return (UART_CTRL0_REG & UART_CTRL0_TX_IRQ_EN); +} + +/**************************************************************************** + * Name: uart_rxbufirq_isenable + * + * Description: + * Check weather the uart rx buffer interrupt is enable or not + * + * Parameters: + * uart_num - the uart hardware index + * + * Returned Values: + * interrupt is enable or not: 1, enable + * 0, disable + * + ****************************************************************************/ + +static inline int uart_rxbufirq_isenable(int uart_num) +{ + return (UART_CTRL0_REG & UART_CTRL0_RX_IRQ_EN); +} + +/**************************************************************************** + * Name: uart_rxbufirq_isenable + * + * Description: + * Check weather the uart tx done interrupt is enable or not, + * uart rx done interrupt is used for uart tx dma mode. + * + * Parameters: + * port - the uart hardware index + * + * Returned Values: + * interrupt is enable or not: 1, enable + * 0, disable + * + ****************************************************************************/ + +static inline bool uart_txdoneirq_isenable(int port) +{ + return (UART_RXTIMEOUT1_REG & UART_RXTIMEOUT1_MASK_TXDONE); +} + +/**************************************************************************** + * Name: uart_read_byte + * + * Description: + * Read a byte data from uart received buffer + * + * Parameters: + * uart_num - the uart hardware index + * + * Returned Values: + * received char + * + ****************************************************************************/ + +static inline uint8_t uart_read_byte(int uart_num) +{ + uint8_t data = UART_BUF(uart_rxindex); + + uart_rxindex++; + + /* Cycle the four register 0x90 0x91 0x92 0x93 */ + + uart_rxindex &= 0x03; + return data; +} + +/**************************************************************************** + * Name: uart_send_byte + * + * Description: + * Send a char by uart transimit buffer + * + * Parameters: + * uart_num - the uart hardware index + * byte - the char want to send + * + * Returned Values: + * void + * + ****************************************************************************/ + +static inline void uart_send_byte(uint8_t byte) +{ + while (UART_GET_TX_BUF_CNT() > 7); + + UART_BUF(uart_txindex) = byte; + + /* Cycle the four register 0x90 0x91 0x92 0x93 */ + + uart_txindex++; + uart_txindex &= 0x03; +} + +/**************************************************************************** + * Name: uart_dma_send + * + * Description: + * Send a buffer by dma, this function only allowed to be called when the + * uart dma is in idle state. + * + * Parameters: + * priv - the uart driver private struct + * buf - the data buffer pointer + * len - the data length + * + * Returned Values: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_SERIAL_TXDMA +static void uart_dma_send(uart_priv_t *priv, char *buf, size_t len) +{ + /* Get the real data pointer */ + + char *data = &priv->txdmabuf[DMA_HEAD_LEN]; + + /* Buffer is too large, assert here */ + + if (len + DMA_HEAD_LEN > priv->txdmasize) + { + DEBUGASSERT(false); + return; + } + + /* Copy the driver buffer to dma buffer, this is necessary because + * the first 4 bytes of the buffer must be the transfered size, which + * is telin dma peripheral required. + * NOTE: the memcpy better be ramcode. + */ + + memcpy(data, buf, len); + + /* Set the dma transfer length */ + + priv->txdmabuf[0] = len; + priv->txdmabuf[1] = 0; + priv->txdmabuf[2] = 0; + priv->txdmabuf[3] = 0; + + /* Set the dma buffer address, the high 8 byte is not need because + * telink chip not use. + */ + + DMA_UART_TX_ADDR_REG = + (uint16_t)((uint32_t)priv->txdmabuf & 0x0000ffff); + DMA_UART_TX_ADDRHI_REG = + (uint8_t)(((uint32_t)priv->txdmabuf >> 16) & 0x000000ff); + + /* Set uart tx channel be ready for transfer */ + + DMA_TX_RDY0_REG |= DMA_CHAN_UART_TX; +} +#endif + +/**************************************************************************** + * Name: uart_irq_trilevel + * + * Description: + * Set the receive and transimit interrupt trigger threshold + * + * Parameters: + * rxlevel - receive interrupt triiger threshold + * txlevel - transimit interrupt triiger threshold + * + * Returned Values: + * void + * + ****************************************************************************/ + +static inline void uart_irq_trilevel(uint8_t rxlevel, uint8_t txlevel) +{ + UART_CTRL3_REG = rxlevel | (txlevel << 4); +} + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uart_gpio_config + * + * Description: + * Config tx_pin and rx_pin as uart usage. + * + * Parameters: + * tx_pin - uart transimit pin config + * rx_pin - uart receive pin config + * + * Returned Values: + * void + * + ****************************************************************************/ + +static void uart_gpio_config(uint32_t tx_pin, uint32_t rx_pin) +{ + /* When the pad is configured with mux input and a pull-up resistor is + * required, tlsr82_gpio_input_ctrl() needs to be placed before + * tlsr82_gpioconfig, otherwise, the mux pad will may misread the short + * low-level timing. + */ + + tlsr82_gpio_input_ctrl(tx_pin, true); + tlsr82_gpio_input_ctrl(rx_pin, true); + + /* The pullup setting must before uart gpio config, cause it will lead + * to ERR data to uart RX buffer (PM_PIN_PULLUP_1M or PM_PIN_PULLUP_10K), + * then set Tx pin and RX pin mux function + */ + + tlsr82_gpioconfig(tx_pin | UART0_PIN_TX_MUX | GPIO_PUPD_PU10K); + tlsr82_gpioconfig(rx_pin | UART0_PIN_RX_MUX | GPIO_PUPD_PU10K); +} + +/**************************************************************************** + * Name: uart_baudrate_config + * + * Description: + * Config the uart baudrate + * + * Parameters: + * baudrate - excepted baudrate + * + * Returned Values: + * void + * + ****************************************************************************/ + +static void uart_baudrate_config(uint32_t baudrate) +{ + int i; + int j; + int bwpc = 0; + int clkdiv; + int clkdivp1_arr[2]; + int tmp; + int min; + + /* Caculate the uart clkdiv and bit width + * baudrate = CPU_CLK / ((clkdiv + 1) * (bwpc + 1)), 3 <= bwpc <= 15 + */ + + min = INT32_MAX; + for (i = 3; i <= 15; i++) + { + /* Consider the round up and round down clkdiv value */ + + clkdivp1_arr[0] = CPU_CLK / (baudrate * (i + 1)); + clkdivp1_arr[1] = clkdivp1_arr[0] + 1; + for (j = 0; j < 2; j++) + { + if (clkdivp1_arr[j] == 0) + { + continue; + } + + tmp = CPU_CLK / clkdivp1_arr[j]; + tmp = abs(tmp / (i + 1) - baudrate); + + /* Get the clkdiv and bwpc that make the smallest difference + * between expected baudrate and real baudrate, mealwhile the + * clkdiv should be smaller as soon as possible to get a larger + * uart clock, whick leads more precise baudrate. + */ + + if ((tmp == min && i > bwpc) || (tmp < min)) + { + min = tmp; + bwpc = i; + clkdiv = clkdivp1_arr[j] - 1; + } + } + } + + /* Set the bwpc (first clear) */ + + BM_CLR(UART_CTRL0_REG, UART_CTRL0_BWPC); + BM_SET(UART_CTRL0_REG, bwpc << UART_CTRL0_BWPC_SHIFT); + + /* Set the Clock Divider and Enable clock */ + + UART_CLK_REG = (clkdiv & UART_CLK_DIV) | UART_CLK_EN; + + /* Set Rx timeout numbers, one byte includes 12 bits at most */ + + UART_RXTIMEOUT0_REG = (bwpc + 1) * 12; + BM_CLR(UART_RXTIMEOUT1_REG, UART_RXTIMEOUT1_SEL); + BM_SET(UART_RXTIMEOUT1_REG, 2 << UART_RXTIMEOUT1_SEL_SHIFT); +} + +/**************************************************************************** + * Name: uart_parity_config + * + * Description: + * Config the uart parity + * + * Parameters: + * parity - 0 , no parity + * odd number , odd parity + * even number (not 0), even parity + * + * Returned Values: + * void + * + ****************************************************************************/ + +static void uart_parity_config(int parity) +{ + if (parity) + { + BM_SET(UART_CTRL1_REG, UART_CTRL1_PARITY_EN); + if (parity % 2 == 1) + { + /* Odd parity */ + + BM_CLR(UART_CTRL1_REG, UART_CTRL1_PARITY_SEL); + } + else + { + /* Even parity */ + + BM_SET(UART_CTRL1_REG, UART_CTRL1_PARITY_SEL); + } + } + else + { + BM_CLR(UART_CTRL1_REG, UART_CTRL1_PARITY_EN); + } +} + +/**************************************************************************** + * Name: uart_stopbits_config + * + * Description: + * Config the uart stop bits + * + * Parameters: + * stopbits - 0, one stop bit + * - 1, one and a halp stop bit + * - 2, two stop bits + * + * Returned Values: + * void + * + ****************************************************************************/ + +static void uart_stopbits_config(int stopbits) +{ + BM_CLR(UART_CTRL1_REG, UART_CTRL1_STOPBIT); + BM_SET(UART_CTRL1_REG, stopbits << UART_CTRL1_STOPBIT_SHIFT); +} + +/**************************************************************************** + * Name: uart_dma_config + * + * Description: + * Disable the dma function for uart + * + * Parameters: + * void + * + * Returned Values: + * void + * + ****************************************************************************/ + +static void uart_dma_config(uart_priv_t *priv) +{ + /* Disable dma interrupt */ + + up_disable_irq(NR_DMA_IRQ); + +#ifdef CONFIG_SERIAL_TXDMA + if (priv->txdma) + { + /* Enable the dma function in uart */ + + BM_SET(UART_CTRL0_REG, UART_CTRL0_TX_DMA_EN); + + /* Enable the uart tx dma channel in dma */ + + BM_SET(DMA_IRQ_EN_REG, DMA_CHAN_UART_TX); + } + else +#endif + { + BM_CLR(UART_CTRL0_REG, UART_CTRL0_TX_DMA_EN); + BM_CLR(DMA_IRQ_EN_REG, DMA_CHAN_UART_TX); + } + +#ifdef CONFIG_SERIAL_RXDMA + if (priv->rxdma) + { + /* Enable the dma function in uart */ + + BM_SET(UART_CTRL0_REG, UART_CTRL0_RX_DMA_EN); + + /* Enable the uart rx dma channel in dma */ + + BM_SET(DMA_IRQ_EN_REG, DMA_CHAN_UART_RX); + + /* Set the rx dma buffer, this configuration must be earlier than + * uart configuration, such as BaudRate, Parity etc. + */ + + DMA_UART_RX_ADDR_REG = + (uint16_t)((uint32_t)priv->rxdmabuf & 0x0000ffff); + DMA_UART_RX_ADDRHI_REG = + (uint8_t)(((uint32_t)priv->rxdmabuf >> 16) & 0x000000ff); + DMA_UART_RX_SIZE_REG = priv->rxdmasize / 16; + + /* Set dma mode to 0x01 for receive */ + + DMA_UART_RX_MODE_REG |= DMA_MODE_WR_MEM; + } + else +#endif + { + BM_CLR(UART_CTRL0_REG, UART_CTRL0_RX_DMA_EN); + BM_CLR(DMA_IRQ_EN_REG, DMA_CHAN_UART_RX); + } + + /* Disable uart dma interrupt, interrupt will be enabled when attach + * the interrupt. + */ + + BM_CLR(DMA_IRQ_MASK_REG, DMA_CHAN_UART_RX | DMA_CHAN_UART_TX); +} + +/**************************************************************************** + * Name: tlsr82_uart_setup + * + * Description: + * Configure the UART baud, bits, parity, etc. This method is called the + * first time that the serial port is opened. + * + ****************************************************************************/ + +static int tlsr82_uart_setup(struct uart_dev_s *dev) +{ + uart_priv_t *priv = (uart_priv_t *)dev->priv; + + /* Uart Dma config, follow the telink sdk, the dma receive buffer + * configuration must be earlier than uart configuration, so put + * dma_config earlier than uart config. + */ + + uart_dma_config(priv); + + /* Uart Gpio config */ + + uart_gpio_config(priv->txpin, priv->rxpin); + + /* Reset the uart */ + + uart_reset(); + + /* Uart communication parameters config + * TODO: unity below functions to uart_format_config() + */ + + uart_baudrate_config(priv->baud); + uart_parity_config(priv->parity); + uart_stopbits_config(priv->stopbits); + + /* Diable uart rx_buff and tx_buff irq */ + + uart_irq_rx_enable(false); + uart_irq_tx_enable(false); + + /* Rx trigger level = 1 indicates one byte will cause interrupt + * Tx trigger level = 0 indicates tx buff empty will cause interrupt + */ + + uart_irq_trilevel(1, 0); + + /* open uart_error_mask, when stop bit error or parity error, + * it will enter error_interrupt + */ + + /* uart_mask_error_irq_enable(); */ + + return 0; +} + +/**************************************************************************** + * Name: tlsr82_uart_shutdown + * + * Description: + * Disable the UART. This method is called when the serial + * port is closed + * + ****************************************************************************/ + +static void tlsr82_uart_shutdown(struct uart_dev_s *dev) +{ + UNUSED(dev); +} + +/**************************************************************************** + * Name: tlsr82_uart_interrupt + * + * Description: + * This is the UART status 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 + * appropriate uart_dev_s structure in order to call these functions. + * + ****************************************************************************/ + +static int UART_RAMCODE tlsr82_interrupt(int irq, void *context, void *arg) +{ + UNUSED(irq); + UNUSED(context); + + struct uart_dev_s *dev = (struct uart_dev_s *)arg; + uart_priv_t * priv = (uart_priv_t *)dev->priv; + + if ((UART_BUF_CNT1_REG & UART_BUF_CNT1_RX_ERR)) + { + /* It will clear rx_fifo and rx_err_irq, rx_buff_irq, so it won't enter + * rx_buff interrupt. + */ + + uart_irq_clr(priv->port, UART_IRQ_CLR_RX); + + /* uart_reset() clear hardware pointer, and clear software pointer */ + + uart_reset(); + uart_clr_rx_index(priv->port); + } + +#ifdef CONFIG_SERIAL_TXDMA + if (priv->txdma && uart_get_irq_status(priv->port, UART_IRQ_TXDONE) && + uart_txdoneirq_isenable(priv->port)) + { + /* Clear txdone interrupt */ + + UART_STATE_REG = BIT(7); + + /* Adjust the send bytes */ + + dev->dmatx.nbytes += dev->dmatx.length; + if (dev->dmatx.nlength) + { + /* Dma send */ + + uart_dma_send(priv, dev->dmatx.nbuffer, dev->dmatx.nlength); + + /* Set length for next next completion */ + + dev->dmatx.length = dev->dmatx.nlength; + dev->dmatx.nlength = 0; + } + else + { + /* No data to send, call uart_xmitchars_done() */ + + uart_xmitchars_done(dev); + + /* Post the tx dma sem, the next dma transfer can start */ + + nxsem_post(priv->txdmasem); + } + } +#else + if (uart_get_irq_status(priv->port, UART_IRQ_TXBUF) && + uart_txbufirq_isenable(priv->port)) + { + uart_xmitchars(dev); + } +#endif + + if (uart_get_irq_status(priv->port, UART_IRQ_RXBUF) && + uart_rxbufirq_isenable(priv->port)) + { + uart_recvchars(dev); + } + + return OK; +} + +/**************************************************************************** + * Name: tlsr82_dma_interrupt + * + * Description: + * This is the UART dma interrupt handler. When the dma transfer finish, + * this interrupt will occur. In this interrupt, we should call + * uart_recvchars() to receive the char from the dma buffer. + * + ****************************************************************************/ + +#if defined(CONFIG_SERIAL_RXDMA) +static int UART_RAMCODE tlsr82_dma_interrupt(int irq, void *context, + void *arg) +{ + struct uart_dev_s *dev = (struct uart_dev_s *)arg; + uart_priv_t * priv = (uart_priv_t *)dev->priv; + + /* Check the uart dma rx interrupt status */ + + if ((DMA_IRQ_STA_REG & DMA_CHAN_UART_RX) && + (DMA_IRQ_MASK_REG & DMA_CHAN_UART_RX)) + { + /* Write 1 to clear the interrupt status */ + + DMA_IRQ_STA_REG |= DMA_CHAN_UART_RX; + + /* The first 4 bytes in dma rx buffer indicates the received + * data number, the real data start at DMA_HEAD_LEN + * set rxdmalen be the total valid length (Include DMA HEADER) + * set rxdmaindex be DMA_HEAD_LEN for skipping the DMA HEADER + */ + + priv->rxdmalen = priv->rxdmabuf[0] + DMA_HEAD_LEN; + priv->rxdmaindex = DMA_HEAD_LEN; + + /* Call uart_recvchars */ + + uart_recvchars(dev); + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: tlsr82_uart_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 tlsr82_uart_attach(struct uart_dev_s *dev) +{ + int ret; + uart_priv_t *priv = (uart_priv_t *)dev->priv; + +#ifdef CONFIG_SERIAL_RXDMA + /* If the serial rx dma is enable, the dma interrupt must be used for + * received. + */ + + ret = irq_attach(NR_DMA_IRQ, tlsr82_dma_interrupt, dev); + if (ret == OK) + { + /* Enable the rx dma interrupt, and Write 1 to clear the dma + * interrupt status + */ + + DMA_IRQ_MASK_REG |= DMA_CHAN_UART_RX; + DMA_IRQ_STA_REG |= DMA_CHAN_UART_RX; + + up_enable_irq(NR_DMA_IRQ); + } +#endif + + ret = irq_attach(priv->irq, tlsr82_interrupt, dev); + if (ret == OK) + { + uart_irq_clr(priv->port, UART_IRQ_CLR_RX); + uart_clr_rx_index(priv->port); + +#ifndef CONFIG_SERIAL_RXDMA + /* Enable the rx fifo not empty irq, but when serial rx dma + * is enable, rx fito not empty interrupt is not used, so + * disable it. + */ + + uart_irq_rx_enable(true); +#endif + +#ifdef CONFIG_SERIAL_TXDMA + /* Enable the tx dma irq and clear the txdone status */ + + UART_RXTIMEOUT1_REG |= UART_RXTIMEOUT1_MASK_TXDONE; + UART_STATE_REG = BIT(7); +#endif + + up_enable_irq(NR_UART_IRQ); + } + + return ret; +} + +/**************************************************************************** + * Name: tlsr82_uart_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 tlsr82_uart_detach(struct uart_dev_s *dev) +{ + uart_priv_t *priv = (uart_priv_t *)dev->priv; + + /* Disable interrupts */ + + up_disable_irq(priv->irq); + + /* Detach from the interrupt(s) */ + + irq_detach(priv->irq); +} + +/**************************************************************************** + * Name: tlsr82_uart_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + ****************************************************************************/ + +static int tlsr82_uart_ioctl(struct file *filep, int cmd, unsigned long arg) +{ + UNUSED(filep); + UNUSED(cmd); + UNUSED(arg); + + return -ENOTTY; +} + +/**************************************************************************** + * Name: tlsr82_uart_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 UART_RAMCODE tlsr82_uart_receive(struct uart_dev_s *dev, + unsigned int *status) +{ + uart_priv_t *priv = (uart_priv_t *)dev->priv; + + /* Return receiver control information */ + + if (status) + { + *status = 0x00; + } + + /* Then return the actual received data. */ + + return uart_read_byte(priv->port); +} + +/**************************************************************************** + * Name: tlsr82_uart_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +static void tlsr82_uart_rxint(struct uart_dev_s *dev, bool enable) +{ + uart_irq_rx_enable(enable); +} + +/**************************************************************************** + * Name: tlsr82_uart_rxavailable + * + * Description: + * Return true if the receive register is not empty + * + ****************************************************************************/ + +static bool UART_RAMCODE tlsr82_uart_rxavailable(struct uart_dev_s *dev) +{ + uart_priv_t *priv = (uart_priv_t *)dev->priv; + + /* Return true if the receive buffer/fifo is not "empty." */ + + return 0 != uart_get_rxfifo_num(priv->port); +} + +/**************************************************************************** + * Name: tlsr82_txint + * + * Description: + * Call to enable or disable TX interrupts + * + ****************************************************************************/ + +static void tlsr82_uart_txint(uart_dev_t *dev, bool enable) +{ + uart_irq_tx_enable(enable); +} + +/**************************************************************************** + * Name: tlsr82_uart_dma_rxint + * + * Description: + * Control the uart rx interrupt in UART RX DMA mode, but here nothing + * to be done. + * + ****************************************************************************/ + +#ifdef CONFIG_SERIAL_RXDMA +static void tlsr82_uart_dma_rxint(struct uart_dev_s *dev, bool enable) +{ + /* Nothing */ +} +#endif + +/**************************************************************************** + * Name: tlsr82_uart_dma_receive + * + * Description: + * Receive the data from uart rx dma buffer, and increase the rx dma index + * + * Parameters: + * dev - uart driver device pointer + * status - driver not used + * + * Returned Values: + * received char + * + ****************************************************************************/ + +#ifdef CONFIG_SERIAL_RXDMA +static int UART_RAMCODE tlsr82_uart_dma_receive(struct uart_dev_s *dev, + unsigned int * status) +{ + uart_priv_t *priv = (uart_priv_t *)dev->priv; + int ch; + + ch = (int)priv->rxdmabuf[priv->rxdmaindex]; + priv->rxdmaindex++; + + return ch; +} +#endif + +/**************************************************************************** + * Name: tlsr82_uart_dma_rxavail + * + * Description: + * Receive the data from uart rx dma buffer, and increase the rx dma index + * + * Parameters: + * dev - uart driver device pointer + * + * Returned Values: + * true : uart rx available + * false: uart rx not available + * + ****************************************************************************/ + +#ifdef CONFIG_SERIAL_RXDMA +static bool UART_RAMCODE tlsr82_uart_dma_rxavail(struct uart_dev_s *dev) +{ + uart_priv_t *priv = (uart_priv_t *)dev->priv; + + return priv->rxdmaindex < priv->rxdmalen; +} +#endif + +/**************************************************************************** + * Name: tlsr82_uart_send + * + * Description: + * This method will send one byte on the UART. + * + ****************************************************************************/ + +static void UART_RAMCODE tlsr82_uart_send(struct uart_dev_s *dev, int ch) +{ + uart_send_byte((uint8_t)ch); +} + +/**************************************************************************** + * Name: tlsr82_txready + * + * Description: + * Return true if the tranmsit data register is empty + * + ****************************************************************************/ + +static bool UART_RAMCODE tlsr82_uart_txready(struct uart_dev_s *dev) +{ + uart_priv_t *priv = (uart_priv_t *)dev->priv; + + /* Return true if the transmit FIFO is "not full." */ + + return uart_get_txfifo_num(priv->port) < 8; +} + +/**************************************************************************** + * Name: tlsr82_txempty + * + * Description: + * Return true if the transmit data register is empty + * + ****************************************************************************/ + +static bool UART_RAMCODE tlsr82_uart_txempty(struct uart_dev_s *dev) +{ + uart_priv_t *priv = (uart_priv_t *)dev->priv; + + /* Return true if the transmit FIFO is "empty." */ + + return 0 == uart_get_txfifo_num(priv->port); +} + +/**************************************************************************** + * Name: tlsr82_uart_dma_txint + * + * Description: + * Call to enable or disable TX interrupts from the UART. + * + ****************************************************************************/ + +#ifdef CONFIG_SERIAL_TXDMA +static void tlsr82_uart_dma_txint(struct uart_dev_s *dev, bool enable) +{ + /* Nothing to do. */ + + /* In case of DMA transfer we do not want to make use of UART interrupts. + * Instead, we use DMA interrupts that are activated once during boot + * sequence. Furthermore we can use up_dma_txcallback() to handle staff at + * half DMA transfer or after transfer completion (depending configuration, + * see stm32_dmastart(...) ). + */ +} +#endif + +/**************************************************************************** + * Name: tlsr82_uart_dma_send + * + * Description: + * Return true if the transmit data register is empty + * + ****************************************************************************/ + +#ifdef CONFIG_SERIAL_TXDMA +static void tlsr82_uart_dma_send(struct uart_dev_s *dev) +{ + uart_priv_t *priv = (uart_priv_t *)dev->priv; + + uart_dma_send(priv, dev->dmatx.buffer, dev->dmatx.length); +} +#endif + +/**************************************************************************** + * Name: tlsr82_uart_dma_txavail + * + * Description: + * Informs DMA that Tx data is available and is ready for transfer. + * + ****************************************************************************/ + +#ifdef CONFIG_SERIAL_TXDMA +static void tlsr82_uart_dma_txavail(struct uart_dev_s *dev) +{ + uart_priv_t *priv = (uart_priv_t *)dev->priv; + + if (dev->xmit.head == dev->xmit.tail) + { + /* No data to transfer. */ + + return; + } + + /* Wait for the previous dma transfer finish */ + + nxsem_wait(priv->txdmasem); + + uart_xmitchars_dma(dev); +} +#endif + +/**************************************************************************** + * Name: tlsr82_uart_lowputc + * + * Description: + * Direct put the char into the uart tx fifo + * + * Parameters: + * ch - output char + * + * Return Value: + * Output char. + * + ****************************************************************************/ + +static inline int tlsr82_uart_lowputc(int ch) +{ + /* Wait until the tx fifo is not full */ + + while (uart_get_txfifo_num(CONSOLE_PORT) > 7); + + tlsr82_uart_send(&CONSOLE_DEV, ch); + + return ch; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug + * writes + * + ****************************************************************************/ + +#ifndef CONFIG_TLSR82_SPI_SYSLOG +int up_putc(int ch) +{ + if (ch == '\n') + { + /* Add CR */ + + tlsr82_uart_lowputc('\r'); + } + + tlsr82_uart_lowputc(ch); + + return 0; +} +#endif + +/**************************************************************************** + * Name: arm_serialinit + * + * Description: + * Register serial console and serial ports. This assumes that + * arm_earlyserialinit was called previously. + * + ****************************************************************************/ + +void arm_serialinit(void) +{ + /* Register the serial console */ + +#ifndef CONFIG_TLSR82_SPI_CONSOLE + CONSOLE_DEV.isconsole = true; + uart_register("/dev/console", &CONSOLE_DEV); +#else + spi_console_init(); +#endif /* CONFIG_TLSR82_SPI_CONSOLE */ + + /* Register the serial driver */ + + uart_register("/dev/ttyS0", &g_uart0_dev); +} + +/**************************************************************************** + * Name: tlsr82_earlyserialinit + * + * 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 arm_serialinit. + * + ****************************************************************************/ + +void tlsr82_earlyserialinit(void) +{ + tlsr82_uart_setup(&CONSOLE_DEV); +} diff --git a/arch/arm/src/tlsr82/tlsr82_serial.h b/arch/arm/src/tlsr82/tlsr82_serial.h new file mode 100644 index 0000000000000..ee754cbe01f50 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_serial.h @@ -0,0 +1,69 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_serial.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_TLSR82_SERIAL_H +#define __ARCH_ARM_SRC_TLSR82_TLSR82_SERIAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" + +#include "hardware/tlsr82_uart.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void tlsr82_earlyserialinit(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_TLSR82_TLSR82_SERIAL_H */ diff --git a/arch/arm/src/tlsr82/tlsr82_spi_console.c b/arch/arm/src/tlsr82/tlsr82_spi_console.c new file mode 100644 index 0000000000000..73a37e352dd71 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_spi_console.c @@ -0,0 +1,344 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_spi_console.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "arm_internal.h" + +#include "tlsr82_gpio.h" +#include "hardware/tlsr82_spi.h" +#include "hardware/tlsr82_clock.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define CONFIG_TLSR82_SPI_CS_ON 1 + +#define SPI_WAIT_BUSY(t, _timeout_) \ + do \ + { \ + t = 0; \ + while ((SPI_CTRL_REG & SPI_CTRL_BUSY) && (t < (_timeout_))) \ + { \ + t++; \ + } \ + } \ + while (0) + +#ifdef CONFIG_TLSR82_SPI_CS_ON +# define TLSR82_SPI_CS_HIGH SPI_CS_HIGH +# define TLSR82_SPI_CS_LOW SPI_CS_LOW +#else +# define TLSR82_SPI_CS_HIGH 0 +# define TLSR82_SPI_CS_LOW 0 +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct spi_console_dev_s +{ + uint32_t clkdiv; + uint32_t pin_mosi; + uint32_t pin_miso; + uint32_t pin_sck; + uint32_t pin_cs; + uint32_t cpol; + uint32_t cpha; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_SPI_SYSLOG +static inline void spi_putc(char ch); +#endif + +static ssize_t spi_console_read(struct file *filep, char *buffer, + size_t buflen); +static ssize_t spi_console_write(struct file *filep, + const char *buffer, size_t buflen); +static int spi_console_ioctl(struct file *filep, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct spi_console_dev_s g_console_dev = +{ + .clkdiv = 2, + .pin_mosi = GPIO_PIN_PA2 | GPIO_AF_MUX0, + .pin_miso = GPIO_PIN_PA3 | GPIO_AF_MUX0, + .pin_sck = GPIO_PIN_PD7 | GPIO_AF_MUX0, + .pin_cs = GPIO_PIN_PD2 | GPIO_AF_MUX0, + .cpol = 0, + .cpha = 0, +}; + +static const struct file_operations g_consoleops = +{ + NULL, /* open */ + NULL, /* close */ + spi_console_read, /* read */ + spi_console_write, /* write */ + NULL, /* seek */ + spi_console_ioctl, /* ioctl */ + NULL /* poll */ +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + , NULL /* unlink */ +#endif +}; + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gpio_console_ioctl + ****************************************************************************/ + +static int spi_console_ioctl(struct file *filep, int cmd, + unsigned long arg) +{ + return -ENOTTY; +} + +/**************************************************************************** + * Name: gpio_console_read + ****************************************************************************/ + +static ssize_t spi_console_read(struct file *filep, char *buffer, + size_t buflen) +{ + return 0; +} + +/**************************************************************************** + * Name: gpio_console_write + ****************************************************************************/ + +static ssize_t spi_console_write(struct file *filep, + const char *buffer, size_t buflen) +{ + int i; + + /* Pull low the CS pin */ + + TLSR82_SPI_CS_LOW; + + /* Enable SPI output and set status to write */ + + BM_CLR(SPI_CTRL_REG, SPI_CTRL_OUT_OFF); + BM_CLR(SPI_CTRL_REG, SPI_CTRL_RW_STA); + + for (i = 0; i < buflen; i++) + { + SPI_DATA_REG = buffer[i]; + + while (SPI_CTRL_REG & SPI_CTRL_BUSY); + } + + /* Pull high the CS pin */ + + TLSR82_SPI_CS_HIGH; + + return buflen; +} + +/**************************************************************************** + * Name: spi_putc + * + * Description: + * Directly output a char by spi per + * + * Parameters: + * dev - Pointer to the driver state structure. + * handler - Callback to be invoked on timer interrupt. + * arg - Argument to be passed to the handler callback. + * + * Returned Values: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_SPI_SYSLOG +static inline void spi_putc(char ch) +{ + int t; + + TLSR82_SPI_CS_LOW; + + BM_CLR(SPI_CTRL_REG, SPI_CTRL_OUT_OFF); + BM_CLR(SPI_CTRL_REG, SPI_CTRL_RW_STA); + + SPI_DATA_REG = ch; + + SPI_WAIT_BUSY(t, 100); + + TLSR82_SPI_CS_HIGH; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: spi_console_init + ****************************************************************************/ + +/**************************************************************************** + * Name: spi_console_early_init + * + * Description: + * SPI early init, after this, the spi can be used for syslog before the + * console register, used for debug. + * + * Parameters: + * void + * + * Returned Values: + * void + * + ****************************************************************************/ + +void spi_console_early_init(void) +{ + /* SPI I2C multiplex config: + * 1. Enable the SPI and I2C for GroupA and GroupD; + * 2. Enable the PD7 SPI function; + * 3. Disable the PD7 I2C function; + */ + + BM_SET(SPI_I2C_GROUP_REG, SPI_I2C_GROUPA_EN); + BM_SET(SPI_I2C_GROUP_REG, SPI_I2C_GROUPD_EN); + BM_SET(SPI_I2C_PIN_REG, SPI_PD7_SPI_EN); + BM_CLR(SPI_I2C_PIN_REG, I2C_PD7_I2C_EN); + + /* GPIO config, the miso pin config can be removed */ + + tlsr82_gpioconfig(g_console_dev.pin_miso); + tlsr82_gpioconfig(g_console_dev.pin_mosi); + tlsr82_gpioconfig(g_console_dev.pin_sck); + tlsr82_gpioconfig(g_console_dev.pin_cs); + + /* Pull-up the cs pin */ + + SPI_CS_HIGH; + + /* Enable SPI clock source; */ + + BM_SET(CLK_EN1_REG, CLK_EN1_SPI); + + /* Config the SPI clkdiv = 2, + * SpiClosk = SystemClock / ((clkdiv + 1) * 2) + * = 4MHz + */ + + SPI_CLK_REG = 0; + BM_SET(SPI_CLK_REG, 2); + + /* Enable SPI clock and config SPI as master; */ + + BM_SET(SPI_CLK_REG, SPI_CLK_EN); + BM_SET(SPI_CTRL_REG, SPI_CTRL_MASTER_EN); + + /* CPOL = 0, CPHA = 0 */ + + SPI_MODE_REG = SPI_MODE_REG & (~0x3); +} + +/**************************************************************************** + * Name: spi_console_init + * + * Description: + * SPI as the console, only support write, the printf() will output by + * spi, used for debug. + * + * Parameters: + * void + * + * Returned Values: + * void + * + ****************************************************************************/ + +void spi_console_init(void) +{ + int ret; + + /* Driver register */ + + ret = register_driver("/dev/console", &g_consoleops, 0666, NULL); + if (ret < 0) + { + syslog(LOG_DEBUG, "register spi_console failed\n"); + } +} + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug + * writes. When the SPI is used for syslog ouput, the up_putc() should be + * implemented by spi. + * + ****************************************************************************/ + +#ifdef CONFIG_TLSR82_SPI_SYSLOG +int up_putc(int ch) +{ + if (ch == '\n') + { + /* Add CR */ + + spi_putc('\r'); + } + + spi_putc((uint8_t)ch); + + return 0; +} +#endif diff --git a/arch/arm/src/tlsr82/tlsr82_spi_console.h b/arch/arm/src/tlsr82/tlsr82_spi_console.h new file mode 100644 index 0000000000000..540c29e614f69 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_spi_console.h @@ -0,0 +1,71 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_spi_console.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_TLSR82_SPI_CONSOLE_H +#define __ARCH_ARM_SRC_TLSR82_TLSR82_SPI_CONSOLE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" + +#include "hardware/tlsr82_gpio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void spi_console_init(void); + +void spi_console_early_init(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_TLSR82_TLSR82_SPI_CONSOLE_H */ diff --git a/arch/arm/src/tlsr82/tlsr82_start.c b/arch/arm/src/tlsr82/tlsr82_start.c new file mode 100644 index 0000000000000..1aa1df01cc440 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_start.c @@ -0,0 +1,103 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_start.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +#include "arm_internal.h" + +#include "hardware/tlsr82_gpio.h" +#include "tlsr82_gpio.h" +#include "tlsr82_gpio_cfg.h" +#include "tlsr82_serial.h" +#include "tlsr82_spi_console.h" +#include "tlsr82_clock.h" +#include "tlsr82_cpu.h" +#include "tlsr82_flash.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* g_idle_topstack: _sbss is the start of the BSS region as defined by the + * linker script. _ebss lies at the end of the BSS region. 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. + * g_idle_topstack is a read-only variable the provides this computed + * address. + */ + +const uintptr_t g_idle_topstack = (uintptr_t)(&_ebss) + + CONFIG_IDLETHREAD_STACKSIZE; + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void __tc32_start(void) +{ + tlsr82_cpu_wakeup_init(LDO_MODE, EXTERNAL_XTAL_24M); + + tlsr82_gpio_init(); + + tlsr82_clock_init(); + +#ifdef CONFIG_SCHED_BACKTRACE + extern uint32_t _sramcode; + extern uint32_t _eramcode; + static void *g_code_regions[] = + { + &_stext , &_etext, + &_sramcode, &_eramcode, + NULL , NULL, + }; + + extern void up_backtrace_init_code_regions(void **regions); + up_backtrace_init_code_regions(g_code_regions); +#endif + +#ifdef CONFIG_TLSR82_SPI + spi_console_early_init(); +#endif + + tlsr82_earlyserialinit(); + + nx_start(); + + /* Never reach here */ + + for (; ; ); +} diff --git a/arch/arm/src/tlsr82/tlsr82_timer.c b/arch/arm/src/tlsr82/tlsr82_timer.c new file mode 100644 index 0000000000000..bb892e0c3fb81 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_timer.c @@ -0,0 +1,737 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_timer.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include + +#include +#include +#include + +#include "tlsr82_timer.h" + +#include "hardware/tlsr82_irq.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct tlsr82_timer_priv_s +{ + struct tlsr82_timer_ops_s *ops; + enum tlsr82_timer_inst_e inst; /* Timer instance */ + uint8_t periph; /* Peripheral ID */ + int irq; /* Interrupt ID */ + bool inuse; /* Flag indicating if the timer is in use */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* TIM operations ***********************************************************/ + +static void tlsr82_timer_start(struct tlsr82_timer_dev_s *dev); +static void tlsr82_timer_stop(struct tlsr82_timer_dev_s *dev); +static void tlsr82_timer_clear(struct tlsr82_timer_dev_s *dev); +static void tlsr82_timer_setmode(struct tlsr82_timer_dev_s *dev, + enum tlsr82_timer_mode_e mode); +static void tlsr82_timer_getcounter(struct tlsr82_timer_dev_s *dev, + uint32_t *value); +static void tlsr82_timer_setcounter(struct tlsr82_timer_dev_s *dev, + uint32_t value); +static void tlsr82_timer_getcapture(struct tlsr82_timer_dev_s *dev, + uint32_t *value); +static void tlsr82_timer_setcapture(struct tlsr82_timer_dev_s *dev, + uint32_t value); +static void tlsr82_timer_getclock(struct tlsr82_timer_dev_s *dev, + uint32_t *value); +static int tlsr82_timer_setisr(struct tlsr82_timer_dev_s *dev, + xcpt_t handler, void * arg); +static void tlsr82_timer_enableint(struct tlsr82_timer_dev_s *dev); +static void tlsr82_timer_disableint(struct tlsr82_timer_dev_s *dev); +static void tlsr82_timer_ackint(struct tlsr82_timer_dev_s *dev); +static int tlsr82_timer_checkint(struct tlsr82_timer_dev_s *dev); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* TLSR82 TIMER ops */ + +struct tlsr82_timer_ops_s tlsr82_timer_ops = +{ + .start = tlsr82_timer_start, + .stop = tlsr82_timer_stop, + .clear = tlsr82_timer_clear, + .setmode = tlsr82_timer_setmode, + .getcounter = tlsr82_timer_getcounter, + .setcounter = tlsr82_timer_setcounter, + .getcapture = tlsr82_timer_getcapture, + .setcapture = tlsr82_timer_setcapture, + .getclock = tlsr82_timer_getclock, + .setisr = tlsr82_timer_setisr, + .enableint = tlsr82_timer_enableint, + .disableint = tlsr82_timer_disableint, + .ackint = tlsr82_timer_ackint, + .checkint = tlsr82_timer_checkint +}; + +struct tlsr82_timer_priv_s g_tlsr82_timers_priv[] = +{ +#ifdef CONFIG_TLSR82_TIMER1 + { + .ops = &tlsr82_timer_ops, + .inst = TLSR82_INST_TIMER1, + .irq = NR_TIMER1_IRQ, /* Interrupt ID */ + .inuse = false, + }, +#endif +#ifdef CONFIG_TLSR82_TIMER2 + { + .ops = &tlsr82_timer_ops, + .inst = TLSR82_INST_TIMER2, + .irq = NR_TIMER2_IRQ, /* Interrupt ID */ + .inuse = false, + }, +#endif +}; + +/* TIMER0 is used for os tick */ + +#ifdef CONFIG_TLSR82_TIMER1 +/* TIMER1 */ + +struct tlsr82_timer_priv_s g_tlsr82_timer1_priv = +{ + .ops = &tlsr82_timer_ops, + .inst = TLSR82_INST_TIMER1, + .irq = NR_TIMER1_IRQ, /* Interrupt ID */ + .inuse = false, +}; +#endif + +#ifdef CONFIG_TLSR82_TIMER2 +/* TIMER2 */ + +struct tlsr82_timer_priv_s g_tlsr82_timer2_priv = +{ + .ops = &tlsr82_timer_ops, + .inst = TLSR82_INST_TIMER2, + .irq = NR_TIMER2_IRQ, /* Interrupt ID */ + .inuse = false, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_timer_start + * + * Description: + * Release the counter. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void tlsr82_timer_start(struct tlsr82_timer_dev_s *dev) +{ + struct tlsr82_timer_priv_s *priv; + DEBUGASSERT(dev); + priv = (struct tlsr82_timer_priv_s *)dev; + if (priv->inst == TLSR82_INST_TIMER1) + { + BM_SET(TIMER_CTRL_REG, TIMER_CTRL_T1_ENABLE); + } + else if (priv->inst == TLSR82_INST_TIMER2) + { + BM_SET(TIMER_CTRL_REG, TIMER_CTRL_T2_ENABLE); + } + else + { + tmrerr("Timer instance %d is not existed.\n", (int)priv->inst); + } +} + +/**************************************************************************** + * Name: tlsr82_timer_stop + * + * Description: + * Halt the counter. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void tlsr82_timer_stop(struct tlsr82_timer_dev_s *dev) +{ + struct tlsr82_timer_priv_s *priv; + DEBUGASSERT(dev); + priv = (struct tlsr82_timer_priv_s *)dev; + if (priv->inst == TLSR82_INST_TIMER1) + { + BM_CLR(TIMER_CTRL_REG, TIMER_CTRL_T1_ENABLE); + } + else if (priv->inst == TLSR82_INST_TIMER2) + { + BM_CLR(TIMER_CTRL_REG, TIMER_CTRL_T2_ENABLE); + } + else + { + tmrerr("Timer instance %d is not existed.\n", (int)priv->inst); + } +} + +/**************************************************************************** + * Name: tlsr82_timer_clear + * + * Description: + * Set the counter to zero instantly. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void tlsr82_timer_clear(struct tlsr82_timer_dev_s *dev) +{ + DEBUGASSERT(dev); + tlsr82_timer_setcounter(dev, 0); +} + +/**************************************************************************** + * Name: tlsr82_timer_setmode + * + * Description: + * Set counter mode. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * mode - Variable indicating the counting direction (up/down). + * + ****************************************************************************/ + +static void tlsr82_timer_setmode(struct tlsr82_timer_dev_s *dev, + enum tlsr82_timer_mode_e mode) +{ + struct tlsr82_timer_priv_s *priv; + DEBUGASSERT(dev); + priv = (struct tlsr82_timer_priv_s *)dev; + + if (mode >= TLSR82_TIMER_MODE_NUM) + { + tmrerr("Timer mode error, mode: %d\n", (int)mode); + return; + } + + if (priv->inst == TLSR82_INST_TIMER1) + { + BM_CLR(TIMER_CTRL_REG, TIMER_CTRL_T1_MODE); + BM_SET(TIMER_CTRL_REG, ((uint32_t)mode << TIMER_CTRL_T1_MODE_SHIFT)); + } + else if (priv->inst == TLSR82_INST_TIMER2) + { + BM_CLR(TIMER_CTRL_REG, TIMER_CTRL_T2_MODE); + BM_SET(TIMER_CTRL_REG, ((uint32_t)mode << TIMER_CTRL_T2_MODE_SHIFT)); + } + else + { + tmrerr("Timer instance %d is not existed.\n", (int)priv->inst); + } +} + +/**************************************************************************** + * Name: tlsr82_timer_getcounter + * + * Description: + * Get the current counter value. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * value - A pointer to a variable to store the current read + * value from counter. + * + ****************************************************************************/ + +static void tlsr82_timer_getcounter(struct tlsr82_timer_dev_s *dev, + uint32_t *value) +{ + struct tlsr82_timer_priv_s *priv; + DEBUGASSERT(dev); + DEBUGASSERT(value); + priv = (struct tlsr82_timer_priv_s *)dev; + if (priv->inst == TLSR82_INST_TIMER1) + { + *value = TIMER_TICK1_REG; + } + else if (priv->inst == TLSR82_INST_TIMER2) + { + *value = TIMER_TICK2_REG; + } + else + { + *value = 0; + tmrerr("Timer instance %d is not existed.\n", (int)priv->inst); + } +} + +/**************************************************************************** + * Name: tlsr82_timer_setcounter + * + * Description: + * Set the value to be loaded to the counter. + * If you want the counter to be loaded at an alarm, enable the alarm and + * the auto-reload before. + * If you want the counter to be loaded instantly, call + * tlsr82_timer_reload_now() after this function. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * value - The value to be loaded the counter. + * + ****************************************************************************/ + +static void tlsr82_timer_setcounter(struct tlsr82_timer_dev_s *dev, + uint32_t value) +{ + struct tlsr82_timer_priv_s *priv; + DEBUGASSERT(dev); + priv = (struct tlsr82_timer_priv_s *)dev; + + if (priv->inst == TLSR82_INST_TIMER1) + { + TIMER_TICK1_REG = value; + } + else if (priv->inst == TLSR82_INST_TIMER2) + { + TIMER_TICK2_REG = value; + } + else + { + tmrerr("Timer instance %d is not existed.\n", (int)priv->inst); + } +} + +/**************************************************************************** + * Name: tlsr82_timer_getcapture + * + * Description: + * Get the alarm value. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * value - Pointer to retrieve the current configured alarm value. + * + ****************************************************************************/ + +static void tlsr82_timer_getcapture(struct tlsr82_timer_dev_s *dev, + uint32_t *value) +{ + struct tlsr82_timer_priv_s *priv; + DEBUGASSERT(dev); + DEBUGASSERT(value); + priv = (struct tlsr82_timer_priv_s *)dev; + if (priv->inst == TLSR82_INST_TIMER1) + { + *value = TIMER_CAPT1_REG; + } + else if (priv->inst == TLSR82_INST_TIMER2) + { + *value = TIMER_CAPT2_REG; + } + else + { + tmrerr("Timer instance %d is not existed.\n", (int)priv->inst); + } +} + +/**************************************************************************** + * Name: tlsr82_timer_setcapture + * + * Description: + * Set the value that will trigger an alarm when the + * counter value matches this value. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * value - The alarm value. + * + ****************************************************************************/ + +static void tlsr82_timer_setcapture(struct tlsr82_timer_dev_s *dev, + uint32_t value) +{ + struct tlsr82_timer_priv_s *priv; + DEBUGASSERT(dev); + priv = (struct tlsr82_timer_priv_s *)dev; + if (priv->inst == TLSR82_INST_TIMER1) + { + TIMER_CAPT1_REG = value; + } + else if (priv->inst == TLSR82_INST_TIMER2) + { + TIMER_CAPT2_REG = value; + } + else + { + tmrerr("Timer instance %d is not existed.\n", (int)priv->inst); + } +} + +/**************************************************************************** + * Name: tlsr82_timer_getclock + * + * Description: + * Get the timer clock. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * value - Pointer to clock value (MHz). + * + ****************************************************************************/ + +static void tlsr82_timer_getclock(struct tlsr82_timer_dev_s *dev, + uint32_t *value) +{ + DEBUGASSERT(dev); + DEBUGASSERT(value); + + /* Timer clock always using the system clock */ + + *value = CONFIG_TLSR82_CPU_CLK_MHZ; +} + +/**************************************************************************** + * Name: tlsr82_timer_setisr + * + * Description: + * Allocate a CPU Interrupt, connect the peripheral source to this + * Interrupt, register the callback and enable CPU the Interruption. + * In case a NULL handler is provided, deallocate the interrupt and + * unregister the previously provided handler. + * + * Parameters: + * dev - Pointer to the driver state structure. + * handler - Callback to be invoked on timer interrupt. + * arg - Argument to be passed to the handler callback. + * + * Returned Values: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +static int tlsr82_timer_setisr(struct tlsr82_timer_dev_s *dev, + xcpt_t handler, void *arg) +{ + struct tlsr82_timer_priv_s *priv = NULL; + int ret = OK; + + DEBUGASSERT(dev); + + priv = (struct tlsr82_timer_priv_s *)dev; + + /* Disable interrupt when callback is removed. */ + + if (handler == NULL) + { + if (priv->irq < NR_IRQS) + { + /* Disable cpu interrupt */ + + up_disable_irq(priv->irq); + + /* Dissociate the IRQ from the ISR */ + + irq_detach(priv->irq); + } + } + + /* Otherwise set callback and enable interrupt */ + + else + { + if (priv->irq < NR_IRQS) + { + /* Disable the provided CPU interrupt to configure it. */ + + up_disable_irq(priv->irq); + + /* Associate an IRQ Number (from the timer) to an ISR */ + + ret = irq_attach(priv->irq, handler, arg); + if (ret != OK) + { + tmrerr("ERROR: Failed to associate an IRQ Number to and ISR"); + goto errout; + } + + /* Enable the CPU Interrupt that is linked to the timer */ + + up_enable_irq(priv->irq); + } + else + { + tmrerr("Timer isr can't attach, irq number=%d is invalid\n", + priv->irq); + } + } + +errout: + return ret; +} + +/**************************************************************************** + * Name: tlsr82_timer_enableint + * + * Description: + * Enable a level Interrupt at the alarm if it is set. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void tlsr82_timer_enableint(struct tlsr82_timer_dev_s *dev) +{ + struct tlsr82_timer_priv_s *priv; + DEBUGASSERT(dev); + priv = (struct tlsr82_timer_priv_s *)dev; + if (priv->inst == TLSR82_INST_TIMER1) + { + up_enable_irq(NR_TIMER1_IRQ); + } + else if (priv->inst == TLSR82_INST_TIMER2) + { + up_enable_irq(NR_TIMER2_IRQ); + } + else + { + tmrerr("Timer instance %d is not existed.\n", (int)priv->inst); + } +} + +/**************************************************************************** + * Name: tlsr82_timer_disableint + * + * Description: + * Disable a level Interrupt at the alarm if it is set. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void tlsr82_timer_disableint(struct tlsr82_timer_dev_s *dev) +{ + struct tlsr82_timer_priv_s *priv; + DEBUGASSERT(dev); + priv = (struct tlsr82_timer_priv_s *)dev; + if (priv->inst == TLSR82_INST_TIMER1) + { + up_disable_irq(NR_TIMER1_IRQ); + } + else if (priv->inst == TLSR82_INST_TIMER2) + { + up_disable_irq(NR_TIMER2_IRQ); + } + else + { + tmrerr("Timer instance %d is not existed.\n", (int)priv->inst); + } +} + +/**************************************************************************** + * Name: tlsr82_timer_ackint + * + * Description: + * Acknowledge an interrupt, that means, clear the interrupt. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +static void tlsr82_timer_ackint(struct tlsr82_timer_dev_s *dev) +{ + struct tlsr82_timer_priv_s *priv; + DEBUGASSERT(dev); + priv = (struct tlsr82_timer_priv_s *)dev; + if (priv->inst == TLSR82_INST_TIMER1) + { + BM_SET(TIMER_STATUS_REG, TIMER_STATUS_T1_CLR); + } + else if (priv->inst == TLSR82_INST_TIMER2) + { + BM_SET(TIMER_STATUS_REG, TIMER_STATUS_T2_CLR); + } + else + { + tmrerr("Timer instance %d is not existed.\n", (int)priv->inst); + } +} + +/**************************************************************************** + * Name: tlsr82_timer_checkint + * + * Description: + * Check the interrupt status bit. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + * Returned Values: + * Return 1 in case of an interrupt is triggered, otherwise 0. + * + ****************************************************************************/ + +static int tlsr82_timer_checkint(struct tlsr82_timer_dev_s *dev) +{ + struct tlsr82_timer_priv_s *priv = (struct tlsr82_timer_priv_s *)dev; + int ret = 0; + + DEBUGASSERT(dev != NULL); + + if (priv->inst == TLSR82_INST_TIMER1) + { + if (BM_IS_SET(IRQ_SRC_REG, 1 << NR_TIMER1_IRQ)) + { + ret = 1; + } + } + else if (priv->inst == TLSR82_INST_TIMER2) + { + if (BM_IS_SET(IRQ_SRC_REG, 1 << NR_TIMER2_IRQ)) + { + ret = 1; + } + } + else + { + tmrerr("Timer instance %d is not existed.\n", (int)priv->inst); + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_timer_init + * + * Description: + * Initialize TIMER device. + * + * Parameters: + * timer - Timer instance to be initialized. + * Valid values: 1 or 2. + * + * Returned Values: + * If the initialization is successful, return a pointer to the timer + * driver struct associated to that timer instance. + * In case it fails, return NULL. + * + ****************************************************************************/ + +struct tlsr82_timer_dev_s *tlsr82_timer_init(int timer) +{ + struct tlsr82_timer_priv_s *tim = NULL; + + /* First, take the data structure associated with the timer instance */ + + switch (timer) + { +#ifdef CONFIG_TLSR82_TIMER1 + case 1: + { + tim = &g_tlsr82_timer1_priv; + break; + } +#endif + +#ifdef CONFIG_TLSR82_TIMER2 + case 2: + { + tim = &g_tlsr82_timer2_priv; + break; + } +#endif + + default: + { + tmrerr("ERROR: unsupported TIMER %d\n", timer); + goto errout; + } + } + + /* Verify if it is in use */ + + if (tim->inuse == false) + { + tim->inuse = true; /* If it was not, now it is */ + } + else + { + tmrerr("ERROR: TIMER %d is already in use\n", timer); + tim = NULL; + } + +errout: + return (struct tlsr82_timer_dev_s *)tim; +} + +/**************************************************************************** + * Name: tlsr82_timer_deinit + * + * Description: + * Deinit TIMER device. + * + * Parameters: + * dev - Pointer to the timer driver struct. + * + ****************************************************************************/ + +void tlsr82_timer_deinit(struct tlsr82_timer_dev_s *dev) +{ + struct tlsr82_timer_priv_s *tim = NULL; + + DEBUGASSERT(dev); + + tim = (struct tlsr82_timer_priv_s *)dev; + tim->inuse = false; +} diff --git a/arch/arm/src/tlsr82/tlsr82_timer.h b/arch/arm/src/tlsr82/tlsr82_timer.h new file mode 100644 index 0000000000000..6bd50649e3aca --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_timer.h @@ -0,0 +1,130 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_timer.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_TLSR82_TIMER_H +#define __ARCH_ARM_SRC_TLSR82_TLSR82_TIMER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +#include "hardware/tlsr82_timer.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Helpers ******************************************************************/ + +#define TLSR82_TIMER_START(d) ((d)->ops->start(d)) +#define TLSR82_TIMER_STOP(d) ((d)->ops->stop(d)) +#define TLSR82_TIMER_CLEAR(d) ((d)->ops->clear(d)) +#define TLSR82_TIMER_SETMODE(d, m) ((d)->ops->setmode(d, m)) +#define TLSR82_TIMER_GETCTR(d, v) ((d)->ops->getcounter(d, v)) +#define TLSR82_TIMER_SETCTR(d, v) ((d)->ops->setcounter(d, v)) +#define TLSR82_TIMER_GETCAPTURE(d, v) ((d)->ops->getcapture(d, v)) +#define TLSR82_TIMER_SETCAPTURE(d, v) ((d)->ops->setcapture(d, v)) +#define TLSR82_TIMER_GETCLK(d, v) ((d)->ops->getclock(d, v)) +#define TLSR82_TIMER_SETISR(d, hnd, arg) ((d)->ops->setisr(d, hnd, arg)) +#define TLSR82_TIMER_ENABLEINT(d) ((d)->ops->enableint(d)) +#define TLSR82_TIMER_DISABLEINT(d) ((d)->ops->disableint(d)) +#define TLSR82_TIMER_ACKINT(d) ((d)->ops->ackint(d)) +#define TLSR82_TIMER_CHECKINT(d) ((d)->ops->checkint(d)) + +#define TLSR82_TIMER0 0 +#define TLSR82_TIMER1 1 +#define TLSR82_TIMER2 2 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Instances of Timer */ + +enum tlsr82_timer_inst_e +{ + TLSR82_INST_TIMER1 = 0, /* Timer 1 */ + TLSR82_INST_TIMER2, /* Timer 2 */ + TLSR82_INST_NUM, /* Timer number */ +}; + +/* Timer mode */ + +enum tlsr82_timer_mode_e +{ + TLSR82_TIMER_MODE_SYS_CLK, + TLSR82_TIMER_MODE_GPIO_TRIG, + TLSR82_TIMER_MODE_GPIO_PWM, + TLSR82_TIMER_MODE_TICK, + TLSR82_TIMER_MODE_NUM, +}; + +/* TIMER device */ + +struct tlsr82_timer_dev_s +{ + struct tlsr82_timer_ops_s *ops; +}; + +/* TIMER ops */ + +/* This is a struct containing the pointers to the timer operations */ + +struct tlsr82_timer_ops_s +{ + /* Timer tasks */ + + void (*start)(struct tlsr82_timer_dev_s *dev); + void (*stop)(struct tlsr82_timer_dev_s *dev); + void (*clear)(struct tlsr82_timer_dev_s *dev); + + /* Timer operations */ + + void (*setmode)(struct tlsr82_timer_dev_s *dev, + enum tlsr82_timer_mode_e mode); + void (*getcounter)(struct tlsr82_timer_dev_s *dev, uint32_t *value); + void (*setcounter)(struct tlsr82_timer_dev_s *dev, uint32_t value); + void (*getcapture)(struct tlsr82_timer_dev_s *dev, uint32_t *value); + void (*setcapture)(struct tlsr82_timer_dev_s *dev, uint32_t value); + void (*getclock)(struct tlsr82_timer_dev_s *dev, uint32_t *value); + + /* Timer interrupts */ + + int (*setisr)(struct tlsr82_timer_dev_s *dev, xcpt_t handler, + void * arg); + void (*enableint)(struct tlsr82_timer_dev_s *dev); + void (*disableint)(struct tlsr82_timer_dev_s *dev); + void (*ackint)(struct tlsr82_timer_dev_s *dev); + int (*checkint)(struct tlsr82_timer_dev_s *dev); +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +struct tlsr82_timer_dev_s *tlsr82_timer_init(int timer); +void tlsr82_timer_deinit(struct tlsr82_timer_dev_s *dev); + +#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_TIM_H */ diff --git a/arch/arm/src/tlsr82/tlsr82_timer_isr.c b/arch/arm/src/tlsr82/tlsr82_timer_isr.c new file mode 100644 index 0000000000000..df5d8ccbc5863 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_timer_isr.c @@ -0,0 +1,111 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_timer_isr.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "arm_internal.h" + +#include "tlsr82_timer.h" + +#include "hardware/tlsr82_clock.h" +#include "hardware/tlsr82_gpio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define TIMER_ISR_CAPT (CONFIG_TLSR82_CPU_CLK_MHZ * CONFIG_USEC_PER_TICK) + +#if TIMER_ISR_CAPT > UINT32_MAX +# error "The tick period is too large." +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* timer is 10ms tick part */ + +static void tlsr82_timer_setup(void) +{ + /* Disable timer0 */ + + TIMER_CTRL_REG &= ~TIMER_CTRL_T0_ENABLE; + + /* Config timer0 */ + + TIMER_TICK0_REG = 0; + TIMER_CAPT0_REG = TIMER_ISR_CAPT; + + /* Enable timer0 */ + + TIMER_CTRL_REG |= TIMER_CTRL_T0_ENABLE; +} + +static int tlsr82_os_timer_isr(int irq, void *context, void *arg) +{ + UNUSED(irq); + UNUSED(context); + UNUSED(arg); + + /* Ack interrupt */ + + TIMER_STATUS_REG |= TIMER_STATUS_T0_CLR; + + nxsched_process_timer(); + + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void up_timer_initialize(void) +{ + int ret; + up_disable_irq(NR_TIMER0_IRQ); + + ret = irq_attach(NR_TIMER0_IRQ, tlsr82_os_timer_isr, NULL); + if (ret == OK) + { + tlsr82_timer_setup(); + up_enable_irq(NR_TIMER0_IRQ); + } + else + { + _err("timer irq attach fail, ret=%d\n", ret); + PANIC(); + } +} + diff --git a/arch/arm/src/tlsr82/tlsr82_timer_lowerhalf.c b/arch/arm/src/tlsr82/tlsr82_timer_lowerhalf.c new file mode 100644 index 0000000000000..f5221e3bedc69 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_timer_lowerhalf.c @@ -0,0 +1,568 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_timer_lowerhalf.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this args for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "tlsr82_timer.h" +#include "tlsr82_timer_lowerhalf.h" + +#if defined(CONFIG_TIMER) && \ + (defined(CONFIG_TLSR82_TIMER1) || defined(CONFIG_TLSR82_TIMER2)) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure provides the private representation of the "lower-half" + * driver state structure. This structure must be cast-compatible with the + * timer_lowerhalf_s structure. + */ + +struct tlsr82_lowerhalf_s +{ + const struct timer_ops_s *ops; /* Lower half operations */ + struct tlsr82_timer_dev_s *tim; /* tlsr82 timer driver */ + tccb_t callback; /* Current user interrupt callback */ + void *arg; /* Argument passed to upper half callback */ + bool started; /* True: Timer has been started */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int tlsr82_timer_handler(int irq, void * context, void * arg); + +/* "Lower half" driver methods **********************************************/ + +static int tlsr82_timer_start(struct timer_lowerhalf_s *lower); +static int tlsr82_timer_stop(struct timer_lowerhalf_s *lower); +static int tlsr82_timer_getstatus(struct timer_lowerhalf_s *lower, + struct timer_status_s *status); +static int tlsr82_timer_settimeout(struct timer_lowerhalf_s *lower, + uint32_t timeout); +static int tlsr82_timer_maxtimeout(struct timer_lowerhalf_s *lower, + uint32_t *timeout); +static void tlsr82_timer_setcallback(struct timer_lowerhalf_s *lower, + tccb_t callback, void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* "Lower half" driver methods */ + +static const struct timer_ops_s g_timer_ops = +{ + .start = tlsr82_timer_start, + .stop = tlsr82_timer_stop, + .getstatus = tlsr82_timer_getstatus, + .settimeout = tlsr82_timer_settimeout, + .setcallback = tlsr82_timer_setcallback, + .maxtimeout = tlsr82_timer_maxtimeout, + .ioctl = NULL, +}; + +#ifdef CONFIG_TLSR82_TIMER1 +static struct tlsr82_lowerhalf_s g_timer1_lowerhalf = +{ + .ops = &g_timer_ops, + .tim = NULL, + .started = false, +}; +#endif + +#ifdef CONFIG_TLSR82_TIMER2 +static struct tlsr82_lowerhalf_s g_timer2_lowerhalf = +{ + .ops = &g_timer_ops, + .tim = NULL, + .started = false, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_timer_handler + * + * Description: + * timer interrupt handler + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static int tlsr82_timer_handler(int irq, void * context, void * arg) +{ + struct tlsr82_lowerhalf_s *lower = (struct tlsr82_lowerhalf_s *)arg; + struct tlsr82_timer_dev_s *timer = lower->tim; + uint32_t next_interval_us = 0; + uint32_t clock_mhz = 0; + + TLSR82_TIMER_ACKINT(timer); + + if (lower->callback(&next_interval_us, lower->arg)) + { + if (next_interval_us > 0) + { + /* Get timer clock in MHz */ + + TLSR82_TIMER_GETCLK(timer, &clock_mhz); + TLSR82_TIMER_SETCAPTURE(timer, next_interval_us * clock_mhz); + } + } + else + { + TLSR82_TIMER_STOP(timer); + } + + return OK; +} + +/**************************************************************************** + * Name: tlsr82_timer_start + * + * Description: + * Start the timer, resetting the time to the current timeout, + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the + * "lower-half" driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int tlsr82_timer_start(struct timer_lowerhalf_s *lower) +{ + struct tlsr82_lowerhalf_s *priv = (struct tlsr82_lowerhalf_s *)lower; + struct tlsr82_timer_dev_s *timer = priv->tim; + + if (!priv->started) + { + TLSR82_TIMER_SETMODE(timer, TLSR82_TIMER_MODE_SYS_CLK); + + if (priv->callback != NULL) + { + TLSR82_TIMER_SETISR(timer, tlsr82_timer_handler, priv); + TLSR82_TIMER_ENABLEINT(timer); + } + + priv->started = true; + return OK; + } + + /* Return EBUSY to indicate that the timer was already running */ + + return -EBUSY; +} + +/**************************************************************************** + * Name: tlsr82_timer_stop + * + * Description: + * Stop the timer + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the + * "lower-half" driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int tlsr82_timer_stop(struct timer_lowerhalf_s *lower) +{ + struct tlsr82_lowerhalf_s *priv = (struct tlsr82_lowerhalf_s *)lower; + struct tlsr82_timer_dev_s *timer = priv->tim; + + if (priv->started) + { + TLSR82_TIMER_DISABLEINT(timer); + TLSR82_TIMER_STOP(timer); + TLSR82_TIMER_SETCTR(timer, 0); + TLSR82_TIMER_SETCAPTURE(timer, 0); + TLSR82_TIMER_SETISR(timer, NULL, NULL); + priv->started = false; + return OK; + } + + /* Return ENODEV to indicate that the timer was not running */ + + return -ENODEV; +} + +/**************************************************************************** + * Name: tlsr82_timer_getstatus + * + * Description: + * Get timer status. + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower- + * half" driver state structure. + * status - The location to return the status information. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int tlsr82_timer_getstatus(struct timer_lowerhalf_s *lower, + struct timer_status_s *status) +{ + struct tlsr82_lowerhalf_s *priv = (struct tlsr82_lowerhalf_s *)lower; + int ret = OK; + uint32_t current_counter_value; + uint32_t capture_value; + uint32_t clock_mhz; + + DEBUGASSERT(priv); + DEBUGASSERT(status); + + /* Return the status bit */ + + status->flags = 0; + + if (priv->started == true) + { + /* Timer is running */ + + status->flags |= TCFLAGS_ACTIVE; + } + + if (priv->callback != NULL) + { + /* Timer has a user callback function to be called when + * expiration happens + */ + + status->flags |= TCFLAGS_HANDLER; + } + + /* Get the timer clock in MHz */ + + TLSR82_TIMER_GETCLK(priv->tim, &clock_mhz); + + /* Get the current counter value */ + + TLSR82_TIMER_GETCTR(priv->tim, ¤t_counter_value); + + /* Get the current configured timeout */ + + TLSR82_TIMER_GETCAPTURE(priv->tim, &capture_value); + + if (clock_mhz > 0) + { + /* Time in microseconds */ + + status->timeout = capture_value / clock_mhz; + status->timeleft = (capture_value - current_counter_value) / + clock_mhz; + } + + return ret; +} + +/**************************************************************************** + * Name: tlsr82_timer_settimeout + * + * Description: + * Set a new timeout value (and reset the timer) + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower- + * half" driver state structure. + * timeout - The new timeout value in microseconds. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int tlsr82_timer_settimeout(struct timer_lowerhalf_s *lower, + uint32_t timeout) +{ + struct tlsr82_lowerhalf_s *priv = (struct tlsr82_lowerhalf_s *)lower; + struct tlsr82_timer_dev_s *timer = priv->tim; + int ret = OK; + uint32_t maxtimeout = 0; + uint32_t clock_mhz = 0; + + /* Exception handling */ + + if (priv->started) + { + tmrerr("Operation Failed, timer has started.\n"); + ret = -EPERM; + goto errout; + } + + ret = tlsr82_timer_maxtimeout(lower, &maxtimeout); + if (ret < 0) + { + tmrerr("Operation Failed, maxtimeout get failed.\n"); + ret = -EPERM; + goto errout; + } + + if (timeout > maxtimeout) + { + tmrerr("Operation Failed, timeout value is too large," + "maxtimeout=%ldus\n", maxtimeout); + ret = -EPERM; + goto errout; + } + else if (timeout == 0) + { + tmrerr("Operation Failed, timeout is 0.\n"); + ret = -EPERM; + goto errout; + } + + /* Disable irq and stop timer */ + + TLSR82_TIMER_DISABLEINT(timer); + TLSR82_TIMER_STOP(timer); + + /* Get timer clock in MHZ */ + + TLSR82_TIMER_GETCLK(timer, &clock_mhz); + + /* Clear timer tick register */ + + TLSR82_TIMER_SETCTR(timer, 0); + + /* Set timer capture register based on timeout and frequency */ + + TLSR82_TIMER_SETCAPTURE(timer, clock_mhz * timeout); + + /* Enable irq and start timer */ + + TLSR82_TIMER_ENABLEINT(timer); + TLSR82_TIMER_START(timer); + +errout: + return ret; +} + +/**************************************************************************** + * Name: tlsr82_timer_maxtimeout + * + * Description: + * Get the maximum timeout value + * + * Input Parameters: + * lower - A pointer the publicly visible representation of + * the "lower-half" driver state structure. + * maxtimeout - A pointer to the variable that will store the max timeout + * (microseconds). + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int tlsr82_timer_maxtimeout(struct timer_lowerhalf_s *lower, + uint32_t *maxtimeout) +{ + struct tlsr82_lowerhalf_s *priv = (struct tlsr82_lowerhalf_s *)lower; + uint32_t clock_mhz = 0; + + if (maxtimeout == NULL) + { + tmrerr("Pointer to maxtimeout is NULL.\n"); + return -EINVAL; + } + + /* Get timer clock in MHZ */ + + TLSR82_TIMER_GETCLK(priv->tim, &clock_mhz); + + if (clock_mhz > 0) + { + /* *maxtimeout = UINT32_MAX * 1000000 / (clock_mhz * 1000000); + * Simplify the denominator to obtain simpler code. + */ + + *maxtimeout = UINT32_MAX / clock_mhz; + } + else + { + *maxtimeout = 0; + tmrerr("Timer clock is 0.\n"); + return -EINVAL; + } + + return OK; +} + +/**************************************************************************** + * Name: tlsr82_timer_setcallback + * + * Description: + * Call this user provided timeout callback. + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the + * "lower-half" driver state structure. + * callback - The new timer expiration function pointer. If this + * function pointer is NULL, then the reset-on-expiration + * behavior is restored, + * arg - Argument that will be provided in the callback. + * + * Returned Value: + * The previous timer expiration function pointer or NULL is there was + * no previous function pointer. + * + ****************************************************************************/ + +static void tlsr82_timer_setcallback(struct timer_lowerhalf_s *lower, + tccb_t callback, void *arg) +{ + struct tlsr82_lowerhalf_s *priv = (struct tlsr82_lowerhalf_s *)lower; + + irqstate_t flags = enter_critical_section(); + + /* Save the new callback */ + + priv->callback = callback; + priv->arg = arg; + + if (callback != NULL && priv->started) + { + TLSR82_TIMER_SETISR(priv->tim, tlsr82_timer_handler, priv); + } + else + { + TLSR82_TIMER_SETISR(priv->tim, NULL, NULL); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_timer_initialize + * + * Description: + * Bind the configuration timer to a timer lower half instance and + * register the timer drivers at 'devpath' + * + * Input Parameters: + * devpath - The full path to the timer device. This should be of the + * form /dev/timer0 + * timer - the timer's number. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int tlsr82_timer_initialize(const char *devpath, int timer) +{ + struct tlsr82_lowerhalf_s *lower; + int ret = OK; + + switch (timer) + { +#ifdef CONFIG_TLSR82_TIMER1 + case 1: + lower = &g_timer1_lowerhalf; + break; +#endif +#ifdef CONFIG_TLSR82_TIMER2 + case 2: + lower = &g_timer2_lowerhalf; + break; +#endif + default: + ret = -ECHRNG; + goto errout; + } + + /* Initialize the elements of lower half state structure */ + + lower->started = false; + lower->callback = NULL; + lower->tim = tlsr82_timer_init(timer); + + if (lower->tim == NULL) + { + ret = -EBUSY; + goto errout; + } + + /* Register the timer driver as /dev/timerX. The returned value from + * timer_register is a handle that could be used with timer_unregister(). + * REVISIT: The returned handle is discard here. + */ + + void *drvr = timer_register(devpath, + (struct timer_lowerhalf_s *)lower); + if (drvr == NULL) + { + /* The actual cause of the failure may have been a failure to allocate + * perhaps a failure to register the timer driver (such as if the + * 'depath' were not unique). We know here but we return EEXIST to + * indicate the failure (implying the non-unique devpath). + */ + + ret = -EEXIST; + goto errout; + } + +errout: + return ret; +} + +#endif /* CONFIG_TIMER */ diff --git a/arch/arm/src/tlsr82/tlsr82_timer_lowerhalf.h b/arch/arm/src/tlsr82/tlsr82_timer_lowerhalf.h new file mode 100644 index 0000000000000..50c63b2fe7836 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_timer_lowerhalf.h @@ -0,0 +1,40 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_timer_lowerhalf.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_TLSR82_TIMER_LOWERHALF_H +#define __ARCH_ARM_SRC_TLSR82_TLSR82_TIMER_LOWERHALF_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_timer_initialize + ****************************************************************************/ + +int tlsr82_timer_initialize(const char *devpath, int timer); + +#endif /* __ARCH_ARM_SRC_TLSR82_TLSR82_TIMER_LOWERHALF_H */ diff --git a/arch/arm/src/tlsr82/tlsr82_watchdog.c b/arch/arm/src/tlsr82/tlsr82_watchdog.c new file mode 100644 index 0000000000000..6e592dd812b0c --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_watchdog.c @@ -0,0 +1,550 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_watchdog.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "hardware/tlsr82_clock.h" +#include "hardware/tlsr82_timer.h" + +#if defined(CONFIG_WATCHDOG) && defined(CONFIG_TLSR82_WATCHDOG) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The timer2 clock in watchdog mode is always system clock, and the watchdog + * capture bits number is only 14 (high 14 bit valid, mask = 0xfffc0000) + * so the max timeout value = 0xfffc0000 / WDOG_CLK_MHZ / 1000 (ms) + * the resolution value = 0x0003ffff / WDOG_CLK_MHZ / 1000 (ms) + */ + +#define WDOG_CLK_MHZ CONFIG_TLSR82_CPU_CLK_MHZ +#define WDOG_VALID_SHIFT 18 +#define WDOG_VALID_MASK (0x00003fff << WDOG_VALID_SHIFT) +#define WDOG_RES_MASK (~WDOG_VALID_MASK) +#define WDOG_MINTIMEOUT 1 +#define WDOG_MAXTIMEOUT (WDOG_VALID_MASK / WDOG_CLK_MHZ / 1000) +#define WDOG_RESOLUTION (WDOG_RES_MASK / WDOG_CLK_MHZ / 1000) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure provides the private representation of the "lower-half" + * driver state structure. This structure must be cast-compatible with the + * well-known watchdog_lowerhalf_s structure. + */ + +struct tlsr82_lowerhalf_s +{ + const struct watchdog_ops_s *ops; /* Lower half operations */ + xcpt_t handler; /* Current EWI interrupt handler */ + uint32_t timeout; /* The actual timeout value */ + uint32_t capture; /* Watchdog capture register value */ + bool started; /* The timer has been started */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Register operations ******************************************************/ + +#ifdef CONFIG_DEBUG_WATCHDOG_INFO +static void tlsr82_dumpregs(const char *msg); +#else +# define tlsr82_dumpregs(msg) +#endif + +/* "Lower half" driver methods **********************************************/ + +static int tlsr82_start(struct watchdog_lowerhalf_s *lower); +static int tlsr82_stop(struct watchdog_lowerhalf_s *lower); +static int tlsr82_keepalive(struct watchdog_lowerhalf_s *lower); +static int tlsr82_getstatus(struct watchdog_lowerhalf_s *lower, + struct watchdog_status_s *status); +static int tlsr82_settimeout(struct watchdog_lowerhalf_s *lower, + uint32_t timeout); +static xcpt_t tlsr82_capture(struct watchdog_lowerhalf_s *lower, + xcpt_t handler); +static int tlsr82_ioctl(struct watchdog_lowerhalf_s *lower, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* "Lower half" driver methods */ + +static const struct watchdog_ops_s g_wdgops = +{ + .start = tlsr82_start, + .stop = tlsr82_stop, + .keepalive = tlsr82_keepalive, + .getstatus = tlsr82_getstatus, + .settimeout = tlsr82_settimeout, + .capture = tlsr82_capture, + .ioctl = tlsr82_ioctl, +}; + +/* "Lower half" driver state */ + +static struct tlsr82_lowerhalf_s g_wdgdev; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_dumpregs + * + * Description: + * Start the watchdog timer, resetting the time to the current timeout, + * + * Input Parameters: + * msg - the message that caller want to print + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_WATCHDOG_INFO +static void tlsr82_dumpregs(const char *msg) +{ + uint8_t status = WDOG_STATUS_REG; + uint32_t ctrl = WDOG_CTRL_REG; + uint32_t tick2 = TIMER_TICK2_REG; + + wdinfo("%s\n", msg); + + /* Watchdog status register */ + + wdinfo(" WDOG_STATUS_REG : 0x%02x\n", status); + + /* Watchdog control register, extract the key information */ + + wdinfo(" WDOG_CTRL_REG, CAPTURE : 0x%08lx\n", + (ctrl & WDOG_CTRL_CAPT_MASK) >> WDOG_CTRL_CAPT_SHIFT); + wdinfo(" WDOG_CTRL_REG, WDOG EN : 0x%08lx\n", + (ctrl & WDOG_CTRL_ENABLE_MASK) >> WDOG_CTRL_ENABLE_SHIFT); + wdinfo(" WDOG_CTRL_REG, TIM2 EN : 0x%08lx\n", + (ctrl & TIMER_CTRL_T2_ENABLE) >> TIMER_CTRL_T2_ENABLE_SHIFT); + + /* Timer2 tick register */ + + wdinfo(" TIMER_TICK2_REG : 0x%08lx\n", tick2); +} +#endif + +/**************************************************************************** + * Name: tlsr82_start + * + * Description: + * Start the watchdog timer, resetting the time to the current timeout, + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower- + * half" driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int tlsr82_start(struct watchdog_lowerhalf_s *lower) +{ + struct tlsr82_lowerhalf_s *priv = (struct tlsr82_lowerhalf_s *)lower; + + wdinfo("Entry\n"); + DEBUGASSERT(priv); + + /* Write 1 to TIMER_STATUS_REG to clear the watch dog */ + + BM_SET(TIMER_STATUS_REG, TIMER_STATUS_WDOG_CLR); + + /* Enable watchdog capture and timer2 */ + + BM_SET(WDOG_CTRL_REG, WDOG_CTRL_ENABLE_MASK); + BM_SET(TIMER_CTRL_REG, TIMER_CTRL_T2_ENABLE); + + tlsr82_dumpregs("Watchdog start"); + + priv->started = true; + return OK; +} + +/**************************************************************************** + * Name: tlsr82_stop + * + * Description: + * Stop the watchdog timer + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower- + * half" driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int tlsr82_stop(struct watchdog_lowerhalf_s *lower) +{ + struct tlsr82_lowerhalf_s *priv = (struct tlsr82_lowerhalf_s *)lower; + + wdinfo("Entry\n"); + + /* Disable watchdog capture and timer2 */ + + BM_CLR(WDOG_CTRL_REG, WDOG_CTRL_ENABLE_MASK); + BM_CLR(TIMER_CTRL_REG, TIMER_CTRL_T2_ENABLE); + + /* Write 1 to TIMER_STATUS_REG to clear the watch dog */ + + BM_SET(TIMER_STATUS_REG, TIMER_STATUS_WDOG_CLR); + + tlsr82_dumpregs("Watchdog stop"); + + priv->started = false; + + return OK; +} + +/**************************************************************************** + * Name: tlsr82_keepalive + * + * Description: + * Reset the watchdog timer to the current timeout value, prevent any + * imminent watchdog timeouts. This is sometimes referred as "pinging" + * the watchdog timer or "petting the dog". + * + * The application program must write in the WWDG_CR register at regular + * intervals during normal operation to prevent an MCU reset. This + * operation must occur only when the counter value is lower than the + * window register value. The value to be stored in the WWDG_CR register + * must be between 0xff and 0xC0: + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower- + * half" driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int tlsr82_keepalive(struct watchdog_lowerhalf_s *lower) +{ + struct tlsr82_lowerhalf_s *priv = (struct tlsr82_lowerhalf_s *)lower; + + wdinfo("Entry\n"); + DEBUGASSERT(priv); + + /* Write 1 to TIMER_STATUS_REG to clear the watch dog */ + + BM_SET(TIMER_STATUS_REG, TIMER_STATUS_WDOG_CLR); + + tlsr82_dumpregs("Watchdog keepalive"); + + return OK; +} + +/**************************************************************************** + * Name: tlsr82_getstatus + * + * Description: + * Get the current watchdog timer status + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower- + * half" driver state structure. + * status - The location to return the watchdog status information. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int tlsr82_getstatus(struct watchdog_lowerhalf_s *lower, + struct watchdog_status_s *status) +{ + struct tlsr82_lowerhalf_s *priv = (struct tlsr82_lowerhalf_s *)lower; + uint32_t lefttick; + + wdinfo("Entry\n"); + DEBUGASSERT(priv); + + /* Return the status bit */ + + status->flags = WDFLAGS_RESET; + if (priv->started) + { + status->flags |= WDFLAGS_ACTIVE; + } + + /* Return the actual timeout is milliseconds */ + + status->timeout = priv->timeout; + + /* Get the time remaining until the watchdog expires (in milliseconds) */ + + lefttick = priv->capture - TIMER_TICK2_REG; + status->timeleft = lefttick / (WDOG_CLK_MHZ * 1000); + + tlsr82_dumpregs("Watchdog getstatus"); + + wdinfo("Status :\n"); + wdinfo(" flags : %08lx\n", status->flags); + wdinfo(" timeout : %lu\n", status->timeout); + wdinfo(" timeleft : %lu\n", status->timeleft); + return OK; +} + +/**************************************************************************** + * Name: tlsr82_settimeout + * + * Description: + * Set a new timeout value (and reset the watchdog timer) + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the + * "lower-half" driver state structure. + * timeout - The new timeout value in milliseconds. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int tlsr82_settimeout(struct watchdog_lowerhalf_s *lower, + uint32_t timeout) +{ + struct tlsr82_lowerhalf_s *priv = (struct tlsr82_lowerhalf_s *)lower; + uint32_t capture; + uint32_t tick; + + DEBUGASSERT(priv); + wdinfo("Entry: timeout=%lu\n", timeout); + + /* Can this timeout be represented? */ + + if (timeout < WDOG_MINTIMEOUT || timeout > WDOG_MAXTIMEOUT) + { + wderr("ERROR: Cannot represent timeout=%u > %u\n", + (unsigned)timeout, WDOG_MAXTIMEOUT); + return -ERANGE; + } + + /* Calculate the watchdog capture value */ + + /* Get the ideal tick value */ + + tick = timeout * 1000 * WDOG_CLK_MHZ; + + /* Transfer tick to the watchdog capture value, make sure the real + * timeout value is larger than the set timeout value + * Note: loss some accuracy + */ + + capture = (tick + WDOG_RESOLUTION - 1) & WDOG_VALID_MASK; + + /* Calculate and save the actual timeout value in milliseconds: + * + * timeout = 1000 * (reload + 1) / Fwwdg + */ + + priv->timeout = capture / (1000 * WDOG_CLK_MHZ); + priv->capture = capture; + + wdinfo("tick=%lu capture=%lu, actual timeout=%lu\n", + tick, capture, priv->timeout); + + /* Set capture value to watchdog capture register */ + + WDOG_CTRL_REG = (WDOG_CTRL_REG & (~WDOG_CTRL_CAPT_MASK)) | + ((capture >> WDOG_VALID_SHIFT) << WDOG_CTRL_CAPT_SHIFT); + + /* Write 1 to TIMER_STATUS_REG to clear the watch dog */ + + BM_SET(TIMER_STATUS_REG, TIMER_STATUS_WDOG_CLR); + + tlsr82_dumpregs("Watchdog settimeout"); + + return OK; +} + +/**************************************************************************** + * Name: tlsr82_capture + * + * Description: + * Don't reset on watchdog timer timeout; instead, call this user provider + * timeout handler. NOTE: Providing handler==NULL will restore the reset + * behavior. + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the + * "lower-half" driver state structure. + * newhandler - The new watchdog expiration function pointer. If this + * function pointer is NULL, then the reset-on-expiration + * behavior is restored, + * + * Returned Value: + * The previous watchdog expiration function pointer or NULL is there was + * no previous function pointer, i.e., if the previous behavior was + * reset-on-expiration (NULL is also returned if an error occurs). + * + ****************************************************************************/ + +static xcpt_t tlsr82_capture(struct watchdog_lowerhalf_s *lower, + xcpt_t handler) +{ + /* Not support early watchdog expiration interrupt */ + + return NULL; +} + +/**************************************************************************** + * Name: tlsr82_ioctl + * + * Description: + * Any ioctl commands that are not recognized by the "upper-half" driver + * are forwarded to the lower half driver through this method. + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower- + * half" driver state structure. + * cmd - The ioctl command value + * arg - The optional argument that accompanies the 'cmd'. The + * interpretation of this argument depends on the particular + * command. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int tlsr82_ioctl(struct watchdog_lowerhalf_s *lower, int cmd, + unsigned long arg) +{ + struct tlsr82_lowerhalf_s *priv = (struct tlsr82_lowerhalf_s *)lower; + int ret = -ENOTTY; + + DEBUGASSERT(priv); + wdinfo("Entry: cmd=%d arg=%ld\n", cmd, arg); + + /* WDIOC_MINTIME: Set the minimum ping time. If two keepalive ioctls + * are received within this time, a reset event will be generated. + * Argument: A 32-bit time value in milliseconds. + */ + + /* if (cmd == WDIOC_MINTIME) */ + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_wdginitialize + * + * Description: + * Initialize the WWDG watchdog timer. The watchdog timer is initialized + * and registers as 'devpath'. The initial state of the watchdog timer is + * disabled. + * + * Input Parameters: + * devpath - The full path to the watchdog. This should be of the form + * /dev/watchdog0 + * + * Returned Value: + * 0 on Success and Negative number on fail + * + ****************************************************************************/ + +int tlsr82_wdginitialize(const char *devpath) +{ + struct tlsr82_lowerhalf_s *priv = &g_wdgdev; + void *driv; + + wdinfo("Entry: devpath=%s\n", devpath); + + if (WDOG_STATUS_REG & WDOG_STATUS_RESET_MASK) + { + syslog(LOG_DEBUG, "Reset by Watchdog\n"); + + /* Write 1 to clear the watchdog reset bit */ + + BM_SET(WDOG_STATUS_REG, WDOG_STATUS_RESET_MASK); + } + else + { + syslog(LOG_DEBUG, "Reset by Power\n"); + } + + /* Initialize the driver state structure. Here we assume: (1) the state + * structure lies in .bss and was zeroed at reset time. (2) This function + * is only called once so it is never necessary to re-zero the structure. + */ + + priv->ops = &g_wdgops; + priv->started = false; + + /* Select an arbitrary initial timeout value. But don't start the watchdog + * yet. NOTE: If the "Hardware watchdog" feature is enabled through the + * device option bits, the watchdog is automatically enabled at power-on. + */ + + tlsr82_settimeout((struct watchdog_lowerhalf_s *)priv, + CONFIG_TLSR82_WDOG_DEFTIMOUT); + + /* Register the watchdog driver as /dev/watchdog0 */ + + driv = watchdog_register(devpath, (struct watchdog_lowerhalf_s *)priv); + if (driv == NULL) + { + wderr("Watchdog driver register failed, devpath=%s\n", devpath); + return -ENOMEM; + } + + /* When the microcontroller enters debug mode, the watchdog should be + * halted, but there is no corresponding configuration in telink chip. + */ + + return OK; +} + +#endif /* CONFIG_WATCHDOG && CONFIG_TLSR82_WATCHDOG */ diff --git a/arch/arm/src/tlsr82/tlsr82_watchdog.h b/arch/arm/src/tlsr82/tlsr82_watchdog.h new file mode 100644 index 0000000000000..68340efc1ff93 --- /dev/null +++ b/arch/arm/src/tlsr82/tlsr82_watchdog.h @@ -0,0 +1,40 @@ +/**************************************************************************** + * arch/arm/src/tlsr82/tlsr82_watchdog.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TLSR82_TLSR82_WATCHDOG_H +#define __ARCH_ARM_SRC_TLSR82_TLSR82_WATCHDOG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: tlsr82_wwdginitialize + ****************************************************************************/ + +int tlsr82_wdginitialize(const char *devpath); + +#endif /* __ARCH_ARM_SRC_TLSR82_TLSR82_WATCHDOG_H */ diff --git a/boards/Kconfig b/boards/Kconfig index ce5ef17ecf402..9acbde251b8f9 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -225,6 +225,12 @@ config ARCH_BOARD_ESP32_DEVKITC of two CPUs is symmetric, meaning they use the same addresses to access the same memory. +config ARCH_BOARD_TLSR8278ADK80D + bool "Telink tlsr8278adk80d board" + depends on ARCH_CHIP_TLSR82 + ---help--- + Enable support for Telink tlsr8278adk80d board. + config ARCH_BOARD_ESP32_ETHERNETKIT bool "Espressif ESP32 Ethernet Kit" depends on ARCH_CHIP_ESP32WROVER @@ -2424,6 +2430,7 @@ config ARCH_BOARD default "esp32s2-saola-1" if ARCH_BOARD_ESP32S2_SAOLA_1 default "esp32s3-devkit" if ARCH_BOARD_ESP32S3_DEVKIT default "et-stm32-stamp" if ARCH_BOARD_ET_STM32_STAMP + default "tlsr8278adk80d" if ARCH_BOARD_TLSR8278ADK80D default "ez80f910200kitg" if ARCH_BOARD_EZ80F910200KITG default "ez80f910200zco" if ARCH_BOARD_EZ80F910200ZCO default "fire-stm32v2" if ARCH_BOARD_FIRE_STM32 @@ -3379,6 +3386,9 @@ endif if ARCH_BOARD_XX3823 source "boards/sparc/bm3823/xx3823/Kconfig" endif +if ARCH_BOARD_TLSR8278ADK80D +source "boards/arm/tlsr82/tlsr8278adk80d/Kconfig" +endif comment "Board-Common Options" diff --git a/boards/arm/tlsr82/tlsr8278adk80d/Kconfig b/boards/arm/tlsr82/tlsr8278adk80d/Kconfig new file mode 100644 index 0000000000000..8d44d61034ade --- /dev/null +++ b/boards/arm/tlsr82/tlsr8278adk80d/Kconfig @@ -0,0 +1,31 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +if ARCH_BOARD_TLSR8278ADK80D + +menu "Telink TLSR8278ADK80D board" + +choice + prompt "Default pin interrupt type" + default PIN_INTERRUPT_DEFAULT_RISING + depends on DEV_GPIO + +config PIN_INTERRUPT_DEFAULT_RISING + bool "Rising" + +config PIN_INTERRUPT_DEFAULT_FALLING + bool "Falling" + +config PIN_INTERRUPT_DEFAULT_HIGH + bool "High level" + +config PIN_INTERRUPT_DEFAULT_LOW + bool "Low level" + +endchoice + +endmenu + +endif diff --git a/boards/arm/tlsr82/tlsr8278adk80d/configs/nsh/defconfig b/boards/arm/tlsr82/tlsr8278adk80d/configs/nsh/defconfig new file mode 100644 index 0000000000000..d179dcc210297 --- /dev/null +++ b/boards/arm/tlsr82/tlsr8278adk80d/configs/nsh/defconfig @@ -0,0 +1,85 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_DEV_NULL is not set +# CONFIG_DISABLE_ENVIRON is not set +# CONFIG_DISABLE_MQUEUE is not set +# CONFIG_DISABLE_POSIX_TIMERS is not set +# CONFIG_DISABLE_PSEUDOFS_OPERATIONS is not set +# CONFIG_DISABLE_PTHREAD is not set +# CONFIG_NSH_DISABLEBG is not set +# CONFIG_NSH_DISABLESCRIPT is not set +# CONFIG_NSH_DISABLE_CD is not set +# CONFIG_NSH_DISABLE_DF is not set +# CONFIG_NSH_DISABLE_ECHO is not set +# CONFIG_NSH_DISABLE_EXIT is not set +# CONFIG_NSH_DISABLE_FREE is not set +# CONFIG_NSH_DISABLE_HELP is not set +# CONFIG_NSH_DISABLE_ITEF is not set +# CONFIG_NSH_DISABLE_KILL is not set +# CONFIG_NSH_DISABLE_LOOPS is not set +# CONFIG_NSH_DISABLE_PS is not set +# CONFIG_NSH_DISABLE_PSSTACKUSAGE is not set +# CONFIG_NSH_DISABLE_PWD is not set +# CONFIG_NSH_DISABLE_SEMICOLON is not set +# CONFIG_NSH_DISABLE_UNAME is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="tlsr8278adk80d" +CONFIG_ARCH_BOARD_TLSR8278ADK80D=y +CONFIG_ARCH_CHIP="tlsr82" +CONFIG_ARCH_CHIP_TLSR8278=y +CONFIG_ARCH_CHIP_TLSR82=y +CONFIG_ARCH_INTERRUPTSTACK=384 +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL=y +CONFIG_BOARD_LATE_INITIALIZE=y +CONFIG_BOARD_LOOPSPERMSEC=2000 +CONFIG_BUILTIN=y +CONFIG_DEBUG_CUSTOMOPT=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEFAULT_SMALL=y +CONFIG_DEV_GPIO=y +CONFIG_DRVR_MKRD=y +CONFIG_FS_PROCFS=y +CONFIG_FS_PROCFS_EXCLUDE_BLOCKS=y +CONFIG_FS_PROCFS_EXCLUDE_MEMDUMP=y +CONFIG_FS_PROCFS_EXCLUDE_MOUNT=y +CONFIG_FS_PROCFS_EXCLUDE_MOUNTS=y +CONFIG_FS_PROCFS_EXCLUDE_USAGE=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_LIBC_LONG_LONG=y +CONFIG_MTD=y +CONFIG_MTD_PARTITION=y +CONFIG_NSH_ARGCAT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_CMDPARMS=y +CONFIG_NSH_LINELEN=80 +CONFIG_NSH_QUOTE=y +CONFIG_PREALLOC_MQ_IRQ_MSGS=8 +CONFIG_PREALLOC_MQ_MSGS=8 +CONFIG_PREALLOC_TIMERS=8 +CONFIG_PTHREAD_MUTEX_ROBUST=y +CONFIG_RAM_SIZE=65536 +CONFIG_RAM_START=0x00840000 +CONFIG_RAW_BINARY=y +CONFIG_SCHED_BACKTRACE=y +CONFIG_SIG_PREALLOC_IRQ_ACTIONS=8 +CONFIG_STACK_COLORATION=y +CONFIG_SYSLOG_TIMESTAMP=y +CONFIG_SYSTEM_NSH=y +CONFIG_TIMER=y +CONFIG_TLSR82_FLASH=y +CONFIG_TLSR82_FLASH_FS_OFFSET=0x00000000 +CONFIG_TLSR82_FLASH_FS_SIZE=0x80000 +CONFIG_TLSR82_GPIO=y +CONFIG_TLSR82_GPIO_IRQ=y +CONFIG_TLSR82_TIMER1=y +CONFIG_TLSR82_TIMER=y +CONFIG_TLSR82_UART0=y +CONFIG_TLSR82_UART=y +CONFIG_USEC_PER_TICK=1000 diff --git a/boards/arm/tlsr82/tlsr8278adk80d/include/board.h b/boards/arm/tlsr82/tlsr8278adk80d/include/board.h new file mode 100644 index 0000000000000..bc47067ecba28 --- /dev/null +++ b/boards/arm/tlsr82/tlsr8278adk80d/include/board.h @@ -0,0 +1,28 @@ +/**************************************************************************** + * boards/arm/tlsr82/tlsr8278adk80d/include/board.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_TLSR82_TLSR8278ADK80D_INCLUDE_BOARD_H +#define __BOARDS_ARM_TLSR82_TLSR8278ADK80D_INCLUDE_BOARD_H + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __BOARDS_ARM_TLSR82_TLSR8278ADK80D_INCLUDE_BOARD_H */ diff --git a/boards/arm/tlsr82/tlsr8278adk80d/scripts/Make.defs b/boards/arm/tlsr82/tlsr8278adk80d/scripts/Make.defs new file mode 100644 index 0000000000000..73a0f36d3c762 --- /dev/null +++ b/boards/arm/tlsr82/tlsr8278adk80d/scripts/Make.defs @@ -0,0 +1,42 @@ +############################################################################ +# boards/arm/tlsr82/tlsr8278adk80d/scripts/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +########################################################################### + +include $(TOPDIR)/.config +include $(TOPDIR)/tools/Config.mk +include $(TOPDIR)/arch/arm/src/tlsr82/Toolchain.defs + +ARCHSCRIPT = $(BOARD_DIR)$(DELIM)scripts$(DELIM)flash_boot.ld + +ARCHCFLAGS = -DMCU_CORE_B87=1 -Wall -fms-extensions -std=gnu99 +ARCHCFLAGS += -Wno-unused-value +ARCHWARNINGS = -Wall -Wstrict-prototypes #-Wshadow -Wundef +ARCHWARNINGSXX = -Wall -Wshadow -Wundef +ARCHPICFLAGS = -fpic + +CFLAGS := $(ARCHCFLAGS) $(ARCHWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe +CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) +CXXFLAGS := $(ARCHCXXFLAGS) $(ARCHWARNINGSXX) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe +CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) +CPPFLAGS := $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) +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 diff --git a/boards/arm/tlsr82/tlsr8278adk80d/scripts/flash_boot.ld b/boards/arm/tlsr82/tlsr8278adk80d/scripts/flash_boot.ld new file mode 100644 index 0000000000000..49907e8cc108d --- /dev/null +++ b/boards/arm/tlsr82/tlsr8278adk80d/scripts/flash_boot.ld @@ -0,0 +1,138 @@ +/**************************************************************************** + * board/arm/src/tlsr82/tlsr8278adk80d/scripts/flash_boot.ld + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* to tell the linker the program begin from __start label in cstartup.s, + * thus do not treat it as a unused symbol + */ + +ENTRY(__start) + +SECTIONS +{ + . = 0x0; + .vectors : + { + *(.vectors) + + /* MUST as follows, when compile with -ffunction-sections + * -fdata-sections, session name may changed + */ + + *(.vectors.*) + } + + .ram_code : + { + PROVIDE(_sramcode = ABSOLUTE(.)); + *(.ram_code) + *(.ram_code.*) + PROVIDE(_eramcode = ABSOLUTE(.)); + } + + PROVIDE(_ramcode_size_ = . ); + PROVIDE(_ramcode_size_div_16_ = (. + 15 ) / 16); + PROVIDE(_ramcode_size_div_256_ = (. + 255) / 256); + PROVIDE(_ramcode_size_div_16_align_256_ = ( (. + 255) / 256) * 16); + PROVIDE(_ramcode_size_align_256_ = ( (. + 255) / 256) * 256); + + . = _ramcode_size_align_256_ ; /* >= (_ictag_start_ - 0x840000)*/ + + .text : + { + PROVIDE(_stext = ABSOLUTE(.)); + *(.text) + *(.text.*) + PROVIDE(_etext = ABSOLUTE(.)); + } + + .rodata : + { + *(.rodata) + *(.rodata.*) + } + + . = ALIGN(4); + PROVIDE(_rstored_ = . ); + PROVIDE(_code_size_ = .); + + /* __LOAD_FLASH for MCU RUN IN Flash 0x100 alighned, must greater + * than or equal to : 0x808000 + ram_code_size + irq_vector(0x100) + + * IC_tag(0x100) + IC_cache(0x800) == 0x808a00 + ram_code_size + * + * __LOAD_DUT for MCU RUN IN SRAM, this setting is used for DUT + * Test and bin size is limited to 8k + * + * __LOAD_RAM for MCU RUN IN SRAM + */ + + . = (0x840000 + ((0x900 + _ramcode_size_align_256_) * __LOAD_FLASH) + (0x400 * __LOAD_DUT) + (_rstored_ * __LOAD_RAM)); + + .retention_data : AT ( _rstored_ ) + { + . = ALIGN(4); + PROVIDE(_retention_data_start_ = . ); + *(.retention_data) + *(.retention_data.*) + . = ALIGN(4); + PROVIDE(_retention_data_end_ = . ); + } + PROVIDE(_dstored_ = _rstored_ + _retention_data_end_ - _retention_data_start_); + + .my_code(NOLOAD) : + { + *(.spi_slave_buff) + } + + .data : AT ( _dstored_ ) + { + . = ALIGN(4); + PROVIDE(_start_data_ = . ); + *(.data); + *(.data.*); + . = ALIGN(4); + PROVIDE(_end_data_ = . ); + } + + .bss : + { + . = ALIGN(4); + PROVIDE(_sbss = .); + *(.sbss) + *(.sbss.*) + *(.bss) + *(.bss.*) + } + + /* data in ram but no need to clean in .s*/ + + .noinit (NOLOAD) : + { + . = ALIGN(4); + *(.noinit) + *(.noinit.*) + } + . = ALIGN(4); + + PROVIDE(_ebss = .); + PROVIDE(_bin_size_ = _code_size_ + _end_data_ - _start_data_ + _retention_data_end_ - _retention_data_start_ ); + PROVIDE(_bin_size_div_16 = ( _bin_size_ + 15 ) / 16 ); + PROVIDE(_ictag_start_ = 0x840000 + _ramcode_size_align_256_ ); + PROVIDE(_ictag_end_ = 0x840000 + _ramcode_size_align_256_ + 0x100); +} diff --git a/boards/arm/tlsr82/tlsr8278adk80d/src/Makefile b/boards/arm/tlsr82/tlsr8278adk80d/src/Makefile new file mode 100644 index 0000000000000..f5b26ce02608b --- /dev/null +++ b/boards/arm/tlsr82/tlsr8278adk80d/src/Makefile @@ -0,0 +1,37 @@ +############################################################################# +# boards/arm/tlsr82/tlsr8278adk80d/src/Makefile +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################# + +include $(TOPDIR)/Make.defs + +CSRCS = tlsr8278_appinit.c +CSRCS += tlsr8278_bringup.c tlsr8278_boot.c +CSRCS += tlsr8278_gpio.c + +ifeq ($(CONFIG_BOARDCTL_RESET),y) +CSRCS += tlsr8278_reset.c +endif + +.PHONY = context distclean + +context:: + +distclean:: + +include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_appinit.c b/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_appinit.c new file mode 100644 index 0000000000000..d1654eed62862 --- /dev/null +++ b/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_appinit.c @@ -0,0 +1,92 @@ +/**************************************************************************** + * boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_appinit.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "tlsr8278adk80d.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define TELINK_LIB_VAR_PASTE(v) tl_multi_addr_##v + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +uint16_t TELINK_LIB_VAR_PASTE(L); +uint16_t TELINK_LIB_VAR_PASTE(H); + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_app_initialize + * + * Description: + * Perform architecture specific initialization + * + * 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 initialization logic and the + * matching application logic. The value could 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) +{ + UNUSED(arg); + + /* Perform board-specific initialization */ + + return 0; +} + +#ifdef CONFIG_BOARDCTL_IOCTL +int board_ioctl(unsigned int cmd, uintptr_t arg) +{ + switch (cmd) + { + default: + return -EINVAL; + } + + return OK; +} +#endif diff --git a/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_boot.c b/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_boot.c new file mode 100644 index 0000000000000..e9c93da1d216e --- /dev/null +++ b/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_boot.c @@ -0,0 +1,40 @@ +/**************************************************************************** + * boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_boot.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "tlsr8278adk80d.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifdef CONFIG_BOARD_LATE_INITIALIZE +void board_late_initialize(void) +{ + /* Perform board-specific initialization */ + + tlsr8278_bringup(); +} +#endif diff --git a/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_bringup.c b/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_bringup.c new file mode 100644 index 0000000000000..f97ad6d0f82b3 --- /dev/null +++ b/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_bringup.c @@ -0,0 +1,177 @@ +/**************************************************************************** + * boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_bringup.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "tlsr8278adk80d.h" + +#include "tlsr82_timer.h" +#include "tlsr82_timer_lowerhalf.h" +#include "tlsr82_watchdog.h" +#include "tlsr82_pwm.h" +#include "tlsr82_adc.h" +#include "tlsr82_gpio.h" +#include "tlsr82_flash_mtd.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int tlsr8278_bringup(void) +{ + int ret = 0; + +#ifdef CONFIG_FS_PROCFS + /* Mount the procfs file system */ + + ret = nx_mount(NULL, "/proc", "procfs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount procfs at /proc: %d\n", ret); + return ret; + } + +#endif /* CONFIG_FS_PROCFS */ + +#ifdef CONFIG_TLSR82_TIMER +#ifdef CONFIG_TLSR82_TIMER1 + ret = tlsr82_timer_initialize("/dev/timer1", TLSR82_TIMER1); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to initialize timer1 driver: %d\n", + ret); + return ret; + } +#endif /* CONFIG_TLSR82_TIMER1 */ + +#ifdef CONFIG_TLSR82_TIMER2 + ret = tlsr82_timer_initialize("/dev/timer2", TLSR82_TIMER2); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to initialize timer2 driver: %d\n", + ret); + return ret; + } +#endif /* CONFIG_TLSR82_TIMER2 */ + +#ifdef CONFIG_TLSR82_WATCHDOG + ret = tlsr82_wdginitialize("dev/watchdog0"); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to initialize watchdog driver: %d\n", + ret); + return ret; + } +#endif /* CONFIG_TLSR82_WATCHDOG */ + +#endif /* CONFIG_TIMER */ + +#if defined(CONFIG_DEV_GPIO) && !defined(CONFIG_GPIO_LOWER_HALF) + ret = tlsr82_gpio_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to initialize gpio driver: %d\n", + ret); + return ret; + } + +#endif /* defined(CONFIG_DEV_GPIO) && !defined(CONFIG_GPIO_LOWER_HALF) */ + +#ifdef CONFIG_TLSR82_PWM + ret = tlsr82_pwminitialize("/dev/pwm1", 1); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to initialize pwm1 driver: %d\n", + ret); + return ret; + } +#endif /* CONFIG_TLSR82_PWM */ + +#ifdef CONFIG_TLSR82_ADC + ret = tlsr82_adc_init("/dev/adc0", 0); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to initialize adc0 driver: %d\n", + ret); + return ret; + } +#endif /* CONFIG_TLSR82_ADC */ + +#ifdef CONFIG_TLSR82_FLASH + struct mtd_dev_s *mtd = tlsr82_flash_initialize( + CONFIG_TLSR82_FLASH_FS_OFFSET, + CONFIG_TLSR82_FLASH_FS_SIZE); + if (mtd == NULL) + { + syslog(LOG_ERR, + "ERROR: Failed to initialize mtd driver: %d\n", + ret); + return ret; + } + + ret = register_mtddriver("/dev/mtd", mtd, 0755, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register MTD driver: %d\n", ret); + return ret; + } + +#ifdef CONFIG_MTD_PARTITION + ret = tlsr82_partition_init("/dev/mtd"); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to init MTD partition: %d\n", ret); + return ret; + } +#endif + +#ifdef CONFIG_FS_LITTLEFS + /* Mount the LittleFS file system */ + + ret = nx_mount("/dev/mtd", "/data", "littlefs", 0, "autoformat"); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to mount LittleFS at /data: %d\n", ret); + return ret; + } +#endif /* CONFIG_FS_LITTLEFS */ + +#endif /* CONFIG_TLSR82_FLASH */ + + return ret; +} diff --git a/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_gpio.c b/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_gpio.c new file mode 100644 index 0000000000000..90c2db629c043 --- /dev/null +++ b/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_gpio.c @@ -0,0 +1,296 @@ +/**************************************************************************** + * boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_gpio.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "chip.h" +#include "tlsr82_gpio.h" +#include "tlsr8278adk80d.h" + +#if defined(CONFIG_DEV_GPIO) && !defined(CONFIG_GPIO_LOWER_HALF) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct tlsr82gpio_dev_s +{ + struct gpio_dev_s gpio; + pin_interrupt_t callback; + uint8_t id; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int tlsr82_go_read(FAR struct gpio_dev_s *dev, FAR bool *value); +static int tlsr82_go_write(FAR struct gpio_dev_s *dev, bool value); +static int tlsr82_go_attach(FAR struct gpio_dev_s *dev, + pin_interrupt_t callback); +static int tlsr82_go_enable(FAR struct gpio_dev_s *dev, bool enable); +static int tlsr82_go_setpintype(FAR struct gpio_dev_s *dev, + enum gpio_pintype_e pintype); +static int tlsr82_go_interrupt(int irq, void *context, void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct gpio_operations_s gpio_ops = +{ + .go_read = tlsr82_go_read, + .go_write = tlsr82_go_write, + .go_attach = tlsr82_go_attach, + .go_enable = tlsr82_go_enable, + .go_setpintype = tlsr82_go_setpintype, +}; + +static gpio_cfg_t g_gpios[BOARD_NGPIO] = +{ + GPIO_PIN_PD6 | GPIO_AF_INPUT | GPIO_PUPD_NONE, + GPIO_PIN_PD0 | GPIO_AF_OUTPUT | GPIO_PUPD_NONE, + GPIO_PIN_PD1 | GPIO_AF_OUTPUT | GPIO_PUPD_NONE, + GPIO_PIN_PB3 | GPIO_IRQ_NORMAL | GPIO_POL_RISE, +}; + +static const enum gpio_pintype_e g_init_pintype[BOARD_NGPIO] = +{ + GPIO_INPUT_PIN, + GPIO_OUTPUT_PIN, + GPIO_OUTPUT_PIN, + GPIO_INTERRUPT_RISING_PIN, +}; + +static struct tlsr82gpio_dev_s g_gpdevs[BOARD_NGPIO]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int tlsr82_go_interrupt(int irq, void *context, void *arg) +{ + FAR struct tlsr82gpio_dev_s *tlsr82gpio = + (FAR struct tlsr82gpio_dev_s *)arg; + + DEBUGASSERT(tlsr82gpio != NULL && tlsr82gpio->callback != NULL); + gpioinfo("Interrupt! callback=%p\n", tlsr82gpio->callback); + + tlsr82gpio->callback(&tlsr82gpio->gpio, tlsr82gpio->id); + return OK; +} + +static int tlsr82_go_read(FAR struct gpio_dev_s *dev, FAR bool *value) +{ + FAR struct tlsr82gpio_dev_s *tlsr82gpio = + (FAR struct tlsr82gpio_dev_s *)dev; + + DEBUGASSERT(tlsr82gpio != NULL && value != NULL); + DEBUGASSERT(tlsr82gpio->id < BOARD_NGPIO); + gpioinfo("Reading...\n"); + + *value = tlsr82_gpioread(g_gpios[tlsr82gpio->id]); + return OK; +} + +static int tlsr82_go_write(FAR struct gpio_dev_s *dev, bool value) +{ + FAR struct tlsr82gpio_dev_s *tlsr82gpio = + (FAR struct tlsr82gpio_dev_s *)dev; + + DEBUGASSERT(tlsr82gpio != NULL); + DEBUGASSERT(tlsr82gpio->id < BOARD_NGPIO); + gpioinfo("Writing %d\n", (int)value); + + tlsr82_gpiowrite(g_gpios[tlsr82gpio->id], value); + return OK; +} + +static int tlsr82_go_attach(FAR struct gpio_dev_s *dev, + pin_interrupt_t callback) +{ + FAR struct tlsr82gpio_dev_s *tlsr82gpio = + (FAR struct tlsr82gpio_dev_s *)dev; + + gpioinfo("Attaching the callback\n"); + + /* Make sure the interrupt is disabled */ + + tlsr82_gpioirqconfig(g_gpios[tlsr82gpio->id], NULL, NULL); + + gpioinfo("Attach %p\n", callback); + tlsr82gpio->callback = callback; + return OK; +} + +static int tlsr82_go_enable(FAR struct gpio_dev_s *dev, bool enable) +{ + FAR struct tlsr82gpio_dev_s *tlsr82gpio = + (FAR struct tlsr82gpio_dev_s *)dev; + + uint8_t gpioid = tlsr82gpio->id; + + if (enable) + { + if (tlsr82gpio->callback != NULL) + { + gpioinfo("Enabling the interrupt\n"); + + /* Configure the interrupt for rising edge */ + + tlsr82_gpioirqconfig(g_gpios[gpioid], tlsr82_go_interrupt, + &g_gpdevs[gpioid]); + } + else + { + gpiowarn("GPIO interrupt callback is NULL\n"); + } + } + else + { + gpioinfo("Disable the interrupt\n"); + tlsr82_gpioirqconfig(g_gpios[gpioid], NULL, NULL); + } + + return OK; +} + +static int tlsr82_go_setpintype(FAR struct gpio_dev_s *dev, + enum gpio_pintype_e pintype) +{ + int ret = OK; + gpio_cfg_t cfg; + FAR struct tlsr82gpio_dev_s *tlsr82gpio = + (FAR struct tlsr82gpio_dev_s *)dev; + + cfg = GPIO_CFG2PIN(g_gpios[tlsr82gpio->id]); + + switch (pintype) + { + case GPIO_INPUT_PIN: + { + cfg |= GPIO_AF_INPUT | GPIO_PUPD_NONE; + tlsr82_gpioconfig(cfg); + } + break; + + case GPIO_INPUT_PIN_PULLUP: + { + cfg |= GPIO_AF_INPUT | GPIO_PUPD_PU10K; + tlsr82_gpioconfig(cfg); + } + break; + + case GPIO_INPUT_PIN_PULLDOWN: + { + cfg |= GPIO_AF_INPUT | GPIO_PUPD_PD100K; + tlsr82_gpioconfig(cfg); + } + break; + + case GPIO_OUTPUT_PIN: + { + cfg = GPIO_AF_OUTPUT | GPIO_DS_HIGH; + tlsr82_gpioconfig(cfg); + } + break; + + case GPIO_INTERRUPT_PIN: + case GPIO_INTERRUPT_RISING_PIN: + { + cfg |= GPIO_AF_INPUT | GPIO_PUPD_NONE | GPIO_IRQ_NORMAL | + GPIO_POL_RISE; + tlsr82_gpioirqconfig(cfg, NULL, NULL); + } + break; + + case GPIO_INTERRUPT_FALLING_PIN: + { + cfg |= GPIO_AF_INPUT | GPIO_PUPD_NONE | GPIO_IRQ_NORMAL | + GPIO_POL_FAIL; + tlsr82_gpioirqconfig(cfg, NULL, NULL); + } + break; + + case GPIO_OUTPUT_PIN_OPENDRAIN: + case GPIO_INTERRUPT_HIGH_PIN: + case GPIO_INTERRUPT_LOW_PIN: + case GPIO_INTERRUPT_BOTH_PIN: + default: + { + gpioerr("Not support pin type, pintype=%d\n", (int)pintype); + ret = -ENOTSUP; + goto errout; + } + } + + /* Assign back the config information */ + + g_gpios[tlsr82gpio->id] = cfg; + +errout: + return ret; +} + +/**************************************************************************** + * Name: tlsr82_gpio_initialize + * + * Description: + * Initialize GPIO drivers for use with /apps/examples/gpio + * + ****************************************************************************/ + +int tlsr82_gpio_initialize(void) +{ + int i; + + tlsr82_gpioirqconfig(g_gpios[3], NULL, NULL); + + for (i = 0; i < BOARD_NGPIO; i++) + { + g_gpdevs[i].gpio.gp_pintype = g_init_pintype[i]; + g_gpdevs[i].gpio.gp_ops = &gpio_ops; + g_gpdevs[i].id = i; + gpio_pin_register(&g_gpdevs[i].gpio, i); + + /* Configure the pin that will be used as input */ + + tlsr82_gpioconfig(g_gpios[i]); + } + + return 0; +} + +#endif /* CONFIG_DEV_GPIO && !CONFIG_GPIO_LOWER_HALF */ diff --git a/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_reset.c b/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_reset.c new file mode 100644 index 0000000000000..c7da183ac87c6 --- /dev/null +++ b/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_reset.c @@ -0,0 +1,71 @@ +/**************************************************************************** + * boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_reset.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "hardware/tlsr82_register.h" + +#ifdef CONFIG_BOARDCTL_RESET + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_reset + * + * Description: + * Reset board. Support for this function is required by board-level + * logic if CONFIG_BOARDCTL_RESET is selected. + * + * Input Parameters: + * status - Status information provided with the reset event. This + * meaning of this status information is board-specific. If not + * used by a board, the value zero may be provided in calls to + * board_reset(). + * + * Returned Value: + * If this function returns, then it was not possible to power-off the + * board due to some constraints. The return value int this case is a + * board-specific reason for the failure to shutdown. + * + ****************************************************************************/ + +int board_reset(int status) +{ + /* Disable all the interrupt and reset */ + + (void)enter_critical_section(); + + RESET_PWDNEN_REG = RESET_PWDNEN_RESET_ALL; + + while (1); + + return 0; +} + +#endif /* CONFIG_BOARDCTL_RESET */ diff --git a/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278adk80d.h b/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278adk80d.h new file mode 100644 index 0000000000000..45e51d7434ede --- /dev/null +++ b/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278adk80d.h @@ -0,0 +1,48 @@ +/**************************************************************************** + * boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278adk80d.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_TLSR82_TLSR8278ADK80D_SRC_TLSR8278ADK80D_H +#define __BOARDS_ARM_TLSR82_TLSR8278ADK80D_SRC_TLSR8278ADK80D_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define BOARD_NGPIO 4 + +#define GPIO_IN_CFG (GPIO_AF_INPUT | GPIO_PUPD_NONE) +#define GPIO_OUT_CFG (GPIO_AF_OUTPUT | GPIO_PUPD_NONE) +#define GPIO_INT_CFG (GPIO_AF_INPUT | GPIO_IRQ_NORMAL | GPIO_POL_RISE) + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +int tlsr8278_bringup(void); + +int tlsr82_gpio_initialize(void); + +#endif /* __BOARDS_ARM_TLSR82_TLSR8278ADK80D_SRC_TLSR8278ADK80D_H */