arch/sparc add initial support for S698PM

This commit is contained in:
zouboan
2022-10-27 15:49:19 +08:00
committed by Masayuki Ishikawa
parent b3ff4ce301
commit 868de3ca4b
27 changed files with 6705 additions and 6 deletions
+1 -1
View File
@@ -43,7 +43,7 @@ config ARCH_CHIP_S698PM
select ARCH_HAVE_TESTSET select ARCH_HAVE_TESTSET
select ARCH_HAVE_SERIAL_TERMIOS select ARCH_HAVE_SERIAL_TERMIOS
---help--- ---help---
Microchip S698PM (ARCH_SPARC_V8) ORBITA Sailing S698PM (ARCH_SPARC_V8)
endchoice endchoice
+206
View File
@@ -0,0 +1,206 @@
/****************************************************************************
* arch/sparc/include/s698pm/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 directed but, rather, only indirectly
* through nuttx/irq.h
*/
#ifndef __ARCH_SPARC_INCLUDE_S698PM_IRQ_H
#define __ARCH_SPARC_INCLUDE_S698PM_IRQ_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/irq.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Interrupt Sources The interrupt source numbers directly map to the trap
* type and to the bits used in the Interrupt Clear, Interrupt Force,
* Interrupt Mask, and the Interrupt Pending Registers.
*/
#if defined(CONFIG_ARCH_CHIP_S698PM)
#define S698PM_IRQREG_BASE 0x80000200
#define S698PM_IRQREG_ILEVEL (S698PM_IRQREG_BASE + 0)
#define S698PM_IRQREG_IPEND (S698PM_IRQREG_BASE + 0x4)
#define S698PM_IRQREG_IFORCE (S698PM_IRQREG_BASE + 0x8)
#define S698PM_IRQREG_ICLEAR (S698PM_IRQREG_BASE + 0xc)
#define S698PM_IRQREG_MPSTATUS (S698PM_IRQREG_BASE + 0x10)
#define S698PM_IRQREG_BROADCAST (S698PM_IRQREG_BASE + 0x14)
#define S698PM_IRQREG_P0_MASK (S698PM_IRQREG_BASE + 0x40)
#define S698PM_IRQREG_P1_MASK (S698PM_IRQREG_BASE + 0x44)
#define S698PM_IRQREG_P2_MASK (S698PM_IRQREG_BASE + 0x48)
#define S698PM_IRQREG_P3_MASK (S698PM_IRQREG_BASE + 0x4c)
#define S698PM_IRQREG_P0_FORCE (S698PM_IRQREG_BASE + 0x80)
#define S698PM_IRQREG_P1_FORCE (S698PM_IRQREG_BASE + 0x84)
#define S698PM_IRQREG_P2_FORCE (S698PM_IRQREG_BASE + 0x88)
#define S698PM_IRQREG_P3_FORCE (S698PM_IRQREG_BASE + 0x8c)
#define S698PM_IRQREG_P0_EXTACK (S698PM_IRQREG_BASE + 0xc0)
#define S698PM_IRQREG_P1_EXTACK (S698PM_IRQREG_BASE + 0xc4)
#define S698PM_IRQREG_P2_EXTACK (S698PM_IRQREG_BASE + 0xc8)
#define S698PM_IRQREG_P3_EXTACK (S698PM_IRQREG_BASE + 0xcc)
#define S698PM_IRQ_FIRST 0x00
#define S698PM_IRQ_RESET 0x00
#define S698PM_IRQ_INST_ACC_EXCEPTION 0x01
#define S698PM_IRQ_ILL_INST 0x02
#define S698PM_IRQ_PRIVELEGE_INST 0x03
#define S698PM_IRQ_FP_DISABLED 0x04
#define S698PM_IRQ_WINDOW_OVERFLOW 0x05
#define S698PM_IRQ_WINDOW_UNDERFLOW 0x06
#define S698PM_IRQ_ADD_NOT_ALIGNED 0x07
#define S698PM_IRQ_ADD_FP_EXCEPTION 0x08
#define S698PM_IRQ_DATA_ACC_EXCEPTION 0x09
#define S698PM_IRQ_TAG_OVERFLOW 0x0A
#define S698PM_IRQ_HW_UNDEFINED_0B 0x0B
#define S698PM_IRQ_HW_UNDEFINED_0C 0x0C
#define S698PM_IRQ_HW_UNDEFINED_0D 0x0D
#define S698PM_IRQ_HW_UNDEFINED_0E 0x0E
#define S698PM_IRQ_HW_UNDEFINED_0F 0x0F
#define S698PM_IRQ_HW_UNDEFINED_10 0x10
#define S698PM_IRQ_FIRST_INT 0x11
#define S698PM_IRQ_AHB_ERROR 0x11
#define S698PM_IRQ_UART_1_RX_TX 0x12
#define S698PM_IRQ_UART_2_RX_TX 0x13
#define S698PM_IRQ_LOCKTIMER12 0x14
#define S698PM_IRQ_ETHERNET 0x15
#define S698PM_IRQ_TIMER1 0x16
#define S698PM_IRQ_TIMER2 0x17
#define S698PM_IRQ_TIMER3 0x18
#define S698PM_IRQ_TIMER4 0x19
#define S698PM_IRQ_1553B 0x1A
#define S698PM_IRQ_EXTENDED 0x1B
#define S698PM_IRQ_EXTERNAL_12 0x1C
#define S698PM_IRQ_EXTERNAL_13 0x1D
#define S698PM_IRQ_EXTERNAL_14 0x1E
#define S698PM_IRQ_EXTERNAL_15 0x1F
#define S698PM_IRQ_LAST_INT 0x1F
#define S698PM_IRQ_HW_UNDEFINED_20 0x20
#define S698PM_IRQ_HW_UNDEFINED_21 0x21
#define S698PM_IRQ_HW_UNDEFINED_22 0x22
#define S698PM_IRQ_HW_UNDEFINED_23 0x23
#define S698PM_IRQ_CP_DISABLED 0x24
#define S698PM_IRQ_HW_UNDEFINED_25 0x25
#define S698PM_IRQ_HW_UNDEFINED_26 0x26
#define S698PM_IRQ_HW_UNDEFINED_27 0x27
#define S698PM_IRQ_CP_EXCEPTION 0x28
#define S698PM_IRQ_HW_UNDEFINED_29 0x29
#define S698PM_IRQ_HW_UNDEFINED_7F 0x7F
#define S698PM_IRQ_SW_SYSCALL_TA0 0x80
#define S698PM_IRQ_SW_UNDEFINED_81 0x81
#define S698PM_IRQ_SW_UNDEFINED_82 0x82
#define S698PM_IRQ_SW_FLUSH_WINDOWS 0x83
#define S698PM_IRQ_SW_UNDEFINED_84 0x84
#define S698PM_IRQ_SW_UNDEFINED_85 0x85
#define S698PM_IRQ_SW_UNDEFINED_86 0x86
#define S698PM_IRQ_SW_UNDEFINED_87 0x87
#define S698PM_IRQ_SW_SYSCALL_TA8 0x88
#define S698PM_IRQ_SW_SYSCALL_IRQDIS 0x89
#define S698PM_IRQ_SW_SYSCALL_IRQEN 0x8A
#define S698PM_IRQ_SW_UNDEFINED_8B 0x8B
#define S698PM_IRQ_SW_UNDEFINED_FF 0xFF
#define S698PM_IRQ_LAST 0xFF
#define S698PM_IRQ_SPW1 0x100
#define S698PM_IRQ_SPW2 0x101
#define S698PM_IRQ_SPW3 0x102
#define S698PM_IRQ_SPW4 0x103
#define S698PM_IRQ_CCSDS 0x104
#define S698PM_IRQ_EXTERNAL 0x105
#define S698PM_IRQ_USBHOST 0x106
#define S698PM_IRQ_UART_3_RX_TX 0x107
#define S698PM_IRQ_CAN1 0x108
#define S698PM_IRQ_CAN2 0x109
#define S698PM_IRQ_CCSDS_CODE 0x10A
#define S698PM_IRQ_CCSDS_DECODE 0x10B
#define S698PM_IRQ_I2C 0x10C
#define S698PM_IRQ_SPI 0x10D
#define S698PM_IRQ_UART_4_RX_TX 0x10E
#define S698PM_IRQ_L2CACHE 0x10F
#define NR_IRQS 272
#define S698PM_EXTENDED_IRQ 11
#define S698PM_IPI_VECTOR 14
#define S698PM_IPI_IRQ S698PM_IRQ_EXTERNAL_14
#define S698PM_EXTENDED_START 16
#define S698PM_CPUINT_MAX 32
#else
#error "Unrecognized chip"
#endif
/****************************************************************************
* Public Types
****************************************************************************/
/****************************************************************************
* 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
#endif /* __ARCH_SPARC_INCLUDE_S698PM_IRQ_H */
-1
View File
@@ -210,7 +210,6 @@ uintptr_t up_intstack_alloc(void);
uintptr_t up_intstack_top(void); uintptr_t up_intstack_top(void);
#endif #endif
/* Chip-specific functions **************************************************/ /* Chip-specific functions **************************************************/
/* Chip specific functions defined in arch/sparc/src/<chip> */ /* Chip specific functions defined in arch/sparc/src/<chip> */
+135
View File
@@ -0,0 +1,135 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
if ARCH_CHIP_S698PM
comment "S698PM Configuration Options"
menu "S698PM Peripheral Support"
config S698PM_WDG
bool "Watchdog timer (WDT)"
default n
select WATCHDOG
config S698PM_TIM1
bool "Timer 1 (T1)"
default n
config S698PM_TIM2
bool "Timer 2 (T2)"
default n
config S698PM_TIM3
bool "Timer 3 (T3)"
default n
config S698PM_TIM4
bool "Timer 4 (T4)"
default n
config S698PM_UART1
bool "UART1"
default n
select UART1_SERIALDRIVER
select ARCH_HAVE_SERIAL_TERMIOS
config S698PM_UART2
bool "UART2"
default n
select UART2_SERIALDRIVER
select ARCH_HAVE_SERIAL_TERMIOS
config S698PM_UART3
bool "UART3"
default n
select UART3_SERIALDRIVER
select ARCH_HAVE_SERIAL_TERMIOS
config S698PM_UART4
bool "UART4"
default n
select UART4_SERIALDRIVER
select ARCH_HAVE_SERIAL_TERMIOS
endmenu # S698PM Peripheral Selections
menuconfig S698PM_GPIOIRQ
bool "GPIO Interrupt Support"
default n
---help---
Build in support for interrupts based on GPIO inputs from IOPorts
if S698PM_GPIOIRQ
config S698PM_GPIOIRQ_PORT4
bool "I/O PORT4 Interrupt Support"
default n
config S698PM_GPIOIRQ_PORT5
bool "I/O PORT5 Interrupt Support"
default n
config S698PM_GPIOIRQ_PORT6
bool "I/O PORT6 Interrupt Support"
default n
config S698PM_GPIOIRQ_PORT7
bool "I/O PORT7 Interrupt Support"
default n
endif # S698PM_GPIOIRQ
menu "Timer Configuration"
if SCHED_TICKLESS
config S698PM_ONESHOT
bool
default y
config S698PM_FREERUN
bool
default y
config S698PM_TICKLESS_ONESHOT
int "Tickless one-shot timer channel"
default 1
range 1 2
depends on S698PM_ONESHOT
---help---
If the Tickless OS feature is enabled, then one clock must be
assigned to provide the one-shot timer needed by the OS.
config S698PM_TICKLESS_FREERUN
int "Tickless free-running timer channel"
default 2
range 1 2
depends on S698PM_FREERUN
---help---
If the Tickless OS feature is enabled, then one clock must be
assigned to provide the free-running timer needed by the OS.
endif # SCHED_TICKLESS
if !SCHED_TICKLESS
config S698PM_ONESHOT
bool "TIM one-shot wrapper"
default n
---help---
Enable a wrapper around the low level timer/counter functions to
support one-shot timer.
config S698PM_FREERUN
bool "TIM free-running wrapper"
default n
---help---
Enable a wrapper around the low level timer/counter functions to
support a free-running timer.
endif # !SCHED_TICKLESS
endmenu # Timer Configuration
endif
+58
View File
@@ -0,0 +1,58 @@
############################################################################
# arch/sparc/src/s698pm/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
# The start-up, "head", file
HEAD_ASRC = s698pm_head.S
# Required S698PM files
CHIP_ASRCS = s698pm_exceptions.S
CHIP_CSRCS = s698pm-lowconsole.c s698pm-lowinit.c s698pm-serial.c s698pm-irq.c s698pm_tim.c
ifeq ($(CONFIG_TIMER),y)
CHIP_CSRCS += s698pm_tim_lowerhalf.c
endif
ifeq ($(CONFIG_S698PM_WDG),y)
CHIP_CSRCS += s698pm_wdg.c
endif
ifneq ($(CONFIG_SCHED_TICKLESS),y)
CHIP_CSRCS += s698pm-timerisr.c
else
CHIP_CSRCS += s698pm_tickless.c
endif
ifeq ($(CONFIG_S698PM_ONESHOT),y)
CHIP_CSRCS += s698pm_oneshot.c s698pm_oneshot_lowerhalf.c
endif
ifeq ($(CONFIG_S698PM_FREERUN),y)
CHIP_CSRCS += s698pm_freerun.c
endif
# Configuration-dependent files
ifeq ($(CONFIG_SMP),y)
CHIP_CSRCS += s698pm_cpuindex.c s698pm_cpustart.c s698pm_cpupause.c s698pm_cpuidlestack.c
endif
+37
View File
@@ -0,0 +1,37 @@
/****************************************************************************
* arch/sparc/src/s698pm/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_SPARC_SRC_S698PM_CHIP_H
#define __ARCH_SPARC_SRC_S698PM_CHIP_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
/* Include only the memory map. Other chip hardware files should then
* include this file for the proper setup
*/
#include "s698pm-memorymap.h"
#endif /* __ARCH_SPARC_SRC_S698PM_CHIP_H */
+100
View File
@@ -0,0 +1,100 @@
/****************************************************************************
* arch/sparc/src/s698pm/s698pm-config.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_SPARC_SRC_S698PM_CONFIG_H
#define __ARCH_SPARC_SRC_S698PM_CONFIG_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <arch/board/board.h>
#include "chip.h"
#include "s698pm-memorymap.h"
#include "s698pm-uart.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* UARTs ********************************************************************/
/* Don't enable UARTs not supported by the chip. */
#if CHIP_NUARTS < 1
# undef CONFIG_S698PM_UART1
# undef CONFIG_S698PM_UART2
# undef CONFIG_S698PM_UART3
# undef CONFIG_S698PM_UART4
#elif CHIP_NUARTS < 2
# undef CONFIG_S698PM_UART2
# undef CONFIG_S698PM_UART3
# undef CONFIG_S698PM_UART4
#elif CHIP_NUARTS < 3
# undef CONFIG_S698PM_UART3
# undef CONFIG_S698PM_UART4
#elif CHIP_NUARTS < 4
# undef CONFIG_S698PM_UART4
#endif
/* Are any UARTs enabled? */
#undef HAVE_UART_DEVICE
#if defined(CONFIG_S698PM_UART1) || defined(CONFIG_S698PM_UART2) || \
defined(CONFIG_S698PM_UART3) || defined(CONFIG_S698PM_UART4)
# define HAVE_UART_DEVICE 1
#endif
/* Is there a serial console? There should be no more than one defined. It
* could be on any UARTn, n=1,.. CHIP_NUARTS
*/
#if defined(CONFIG_UART1_SERIAL_CONSOLE) && defined(CONFIG_S698PM_UART1)
# undef CONFIG_UART2_SERIAL_CONSOLE
# undef CONFIG_UART3_SERIAL_CONSOLE
# undef CONFIG_UART4_SERIAL_CONSOLE
# define HAVE_SERIAL_CONSOLE 1
#elif defined(CONFIG_UART2_SERIAL_CONSOLE) && defined(CONFIG_S698PM_UART2)
# undef CONFIG_UART1_SERIAL_CONSOLE
# undef CONFIG_UART3_SERIAL_CONSOLE
# undef CONFIG_UART4_SERIAL_CONSOLE
# define HAVE_SERIAL_CONSOLE 1
#elif defined(CONFIG_UART3_SERIAL_CONSOLE) && defined(CONFIG_S698PM_UART3)
# undef CONFIG_UART1_SERIAL_CONSOLE
# undef CONFIG_UART2_SERIAL_CONSOLE
# undef CONFIG_UART4_SERIAL_CONSOLE
# define HAVE_SERIAL_CONSOLE 1
#elif defined(CONFIG_UART4_SERIAL_CONSOLE) && defined(CONFIG_S698PM_UART4)
# undef CONFIG_UART1_SERIAL_CONSOLE
# undef CONFIG_UART2_SERIAL_CONSOLE
# undef CONFIG_UART3_SERIAL_CONSOLE
# define HAVE_SERIAL_CONSOLE 1
#else
# undef CONFIG_UART1_SERIAL_CONSOLE
# undef CONFIG_UART2_SERIAL_CONSOLE
# undef CONFIG_UART3_SERIAL_CONSOLE
# undef CONFIG_UART4_SERIAL_CONSOLE
# undef HAVE_SERIAL_CONSOLE
#endif
#endif /* __ARCH_SPARC_SRC_S698PM_CONFIG_H */
File diff suppressed because it is too large Load Diff
+266
View File
@@ -0,0 +1,266 @@
/****************************************************************************
* arch/sparc/src/s698pm/s698pm-lowconsole.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 <nuttx/config.h>
#include <arch/board/board.h>
#include "s698pm-config.h"
#include <assert.h>
#include <debug.h>
#include <arch/irq.h>
#include "up_internal.h"
#include "s698pm-uart.h"
#include "s698pm.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Select UART parameters for the selected console */
#ifdef HAVE_SERIAL_CONSOLE
# if defined(CONFIG_UART1_SERIAL_CONSOLE)
# define S698PM_CONSOLE_BASE S698PM_UART1_BASE
# define S698PM_CONSOLE_BAUD CONFIG_UART1_BAUD
# define S698PM_CONSOLE_BITS CONFIG_UART1_BITS
# define S698PM_CONSOLE_PARITY CONFIG_UART1_PARITY
# define S698PM_CONSOLE_2STOP CONFIG_UART1_2STOP
# elif defined(CONFIG_UART2_SERIAL_CONSOLE)
# define S698PM_CONSOLE_BASE S698PM_UART2_BASE
# define S698PM_CONSOLE_BAUD CONFIG_UART2_BAUD
# define S698PM_CONSOLE_BITS CONFIG_UART2_BITS
# define S698PM_CONSOLE_PARITY CONFIG_UART2_PARITY
# define S698PM_CONSOLE_2STOP CONFIG_UART2_2STOP
# elif defined(CONFIG_UART3_SERIAL_CONSOLE)
# define S698PM_CONSOLE_BASE S698PM_UART3_BASE
# define S698PM_CONSOLE_BAUD CONFIG_UART3_BAUD
# define S698PM_CONSOLE_BITS CONFIG_UART3_BITS
# define S698PM_CONSOLE_PARITY CONFIG_UART3_PARITY
# define S698PM_CONSOLE_2STOP CONFIG_UART3_2STOP
# elif defined(CONFIG_UART4_SERIAL_CONSOLE)
# define S698PM_CONSOLE_BASE S698PM_UART4_BASE
# define S698PM_CONSOLE_BAUD CONFIG_UART4_BAUD
# define S698PM_CONSOLE_BITS CONFIG_UART4_BITS
# define S698PM_CONSOLE_PARITY CONFIG_UART4_PARITY
# define S698PM_CONSOLE_2STOP CONFIG_UART4_2STOP
# else
# error "No CONFIG_UARTn_SERIAL_CONSOLE Setting"
# endif
#endif
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: s698pm_putreg
*
* Description:
* Write a value to a UART register
*
****************************************************************************/
#ifdef HAVE_UART_DEVICE
static inline void s698pm_putreg(uintptr_t uart_base, unsigned int offset,
uint32_t value)
{
putreg32(value, uart_base + offset);
}
#endif
/****************************************************************************
* Name: s698pm_getreg
*
* Description:
* Get a value from a UART register
*
****************************************************************************/
#ifdef HAVE_UART_DEVICE
static inline uint32_t s698pm_getreg(uintptr_t uart_base,
unsigned int offset)
{
return getreg32(uart_base + offset);
}
#endif
/****************************************************************************
* Name: s698pm_uartreset
*
* Description:
* Reset UART.
*
****************************************************************************/
#ifdef HAVE_UART_DEVICE
void s698pm_uartreset(uintptr_t uart_base)
{
uint32_t reg;
/* Clear USART configuration */
reg = s698pm_getreg(uart_base, S698PM_UART_CTRLREG_OFFSET);
uart_disable(reg);
uart_parity_config(reg, NONE);
uart_flow_ctrl_config(reg, OFF);
uart_loopback_config(reg, OFF);
s698pm_putreg(uart_base, S698PM_UART_CTRLREG_OFFSET, reg);
}
#endif
/****************************************************************************
* Name: s698pm_uartconfigure
*
* Description:
* Configure a UART as a console.
*
****************************************************************************/
#ifdef HAVE_UART_DEVICE
void s698pm_uartconfigure(uintptr_t uart_base, uint32_t baudrate,
unsigned int parity, unsigned int nbits,
bool stop2)
{
uint32_t reg;
/* Select baud. */
s698pm_putreg(S698PM_CONSOLE_BASE, S698PM_UART_SCALREG_OFFSET,
uart_set_baudrate(baudrate));
reg = s698pm_getreg(S698PM_CONSOLE_BASE, S698PM_UART_CTRLREG_OFFSET);
/* Select parity */
if (parity == 1)
{
uart_parity_config(reg, ODD); /* Odd parity */
}
else if (parity == 2)
{
uart_parity_config(reg, EVEN); /* Even parity */
}
else
{
uart_parity_config(reg, NONE); /* Even none */
}
uart_flow_ctrl_config(reg, OFF);
uart_loopback_config(reg, OFF);
uart_enable(reg);
s698pm_putreg(S698PM_CONSOLE_BASE, S698PM_UART_CTRLREG_OFFSET, reg);
}
#endif
/****************************************************************************
* Name: s698pm_consoleinit
*
* Description:
* Initialize a console for debug output. This function is called very
* early in the initialization sequence to configure the serial console
* uart
* (only).
*
****************************************************************************/
void s698pm_consoleinit(void)
{
uint32_t gpreg;
#ifdef HAVE_UART_DEVICE
/* Setup up pin selection registers for all configured UARTs. The board.h
* header file must provide these definitions to select the correct pin
* configuration for each enabled UARt.
*/
gpreg = getreg32(S698PM_GPREG_BASE);
#ifdef CONFIG_S698PM_UART3
/* Configure UART3 RX (input) and TX (output) pins */
gpreg |= 0x1;
putreg32(gpreg, S698PM_GPREG_BASE);
#endif /* CONFIG_S698PM_UART3 */
#ifdef CONFIG_S698PM_UART4
/* Configure UART4 RX (input) and TX (output) pins */
gpreg |= 0x2;
putreg32(gpreg, S698PM_GPREG_BASE);
#endif /* CONFIG_S698PM_UART4 */
#ifdef HAVE_SERIAL_CONSOLE
/* Configure the console uart */
s698pm_uartconfigure(S698PM_CONSOLE_BASE, S698PM_CONSOLE_BAUD,
S698PM_CONSOLE_PARITY, S698PM_CONSOLE_BITS,
S698PM_CONSOLE_2STOP);
#endif /* HAVE_SERIAL_CONSOLE */
#endif /* HAVE_UART_DEVICE */
}
/****************************************************************************
* Name: up_lowputc
*
* Description:
* Output one byte on the serial console
*
****************************************************************************/
void up_lowputc(char ch)
{
#ifdef HAVE_SERIAL_CONSOLE
while ((s698pm_getreg(S698PM_CONSOLE_BASE, S698PM_UART_STATREG_OFFSET) &
UART_STA_TE) == 0);
/* Then write the character to the TX data register */
s698pm_putreg(S698PM_CONSOLE_BASE, S698PM_UART_TXREG_OFFSET,
(uint32_t)ch);
#endif
}
+119
View File
@@ -0,0 +1,119 @@
/****************************************************************************
* arch/sparc/src/s698pm/s698pm-lowinit.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 <nuttx/config.h>
#include "s698pm-config.h"
#include "up_internal.h"
#include "s698pm.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: showprogress
*
* Description:
* Print a character on the UART to show boot status.
*
****************************************************************************/
#ifdef CONFIG_DEBUG_FEATURES
# define showprogress(c) up_lowputc(c)
#else
# define showprogress(c)
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_lowinit
*
* Description:
* This performs basic initialization of the USART used for the serial
* console. Its purpose is to get the console output available as soon
* as possible.
*
****************************************************************************/
void up_lowinit(void)
{
uint32_t *dest;
/* Initialize a console (probably a serial console) */
s698pm_consoleinit();
showprogress('A');
/* Clear .bss. We'll do this inline (vs. calling memset) just to be
* certain that there are no issues with the state of global variables.
*/
for (dest = &_bss_start; dest < &_end; )
{
*dest++ = 0;
}
showprogress('B');
/* Perform early serial initialization (so that we will have debug output
* available as soon as possible).
*/
#ifdef USE_EARLYSERIALINIT
up_earlyserialinit();
#endif
/* Perform board-level initialization */
s698pm_boardinitialize();
/* Then start NuttX */
showprogress('\r');
showprogress('\n');
}
+57
View File
@@ -0,0 +1,57 @@
/****************************************************************************
* arch/sparc/src/s698pm/s698pm-memorymap.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_SPARC_SRC_S698PM_S698PM_MEMORYMAP_H
#define __ARCH_SPARC_SRC_S698PM_S698PM_MEMORYMAP_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Register Base Addresses **************************************************/
/* UART 1-4 Register Base Addresses */
# define S698PM_UART1_BASE (0x80000100)
# define S698PM_UART2_BASE (0x80000900)
# define S698PM_UART3_BASE (0x80100100)
# define S698PM_UART4_BASE (0x80100200)
/* GPIO metux Register Base Addresses */
# define S698PM_GPREG_BASE (0x80100500)
#define S698PM_DSU_BASE (0x90000000)
#define S698PM_DSU_CPU0_BASE (0x90000000)
#define S698PM_DSU_CPU1_BASE (0x91000000)
#define S698PM_DSU_CPU2_BASE (0x92000000)
#define S698PM_DSU_CPU3_BASE (0x93000000)
#define S698PM_DSU_PC_OFFSET 0x400010 /* PC register */
#define S698PM_DSU_NPC_OFFSET 0x400014 /* nPC register */
#endif /* __ARCH_SPARC_SRC_S698PM_S698PM_MEMORYMAP_H */
File diff suppressed because it is too large Load Diff
+156
View File
@@ -0,0 +1,156 @@
/****************************************************************************
* arch/sparc/src/s698pm/s698pm-timerisr.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 <nuttx/config.h>
#include <stdint.h>
#include <time.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <arch/board/board.h>
#include "up_internal.h"
#include "s698pm.h"
#include "s698pm_tim.h"
#include "s698pm_irq.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* The CPU frequency is given by BOARD_CPU_CLOCK (defined in board.h). The
* desired interrupt frequency is given by CONFIG_USEC_PER_TICK. An unscaled
* ideal match is given by:
*
* CLOCK = CPU_CLOCK / DIVISOR # CPU clocks/sec
* MATCH = CLOCK / CLOCKS_PER_SEC # CPU clocks/timer tick
* MATCH = CPU_CLOCK / DIVISOR / CLOCKS_PER_SEC # CPU clocks/timer tick
*
* But we only have 16-bits of accuracy so we need to pick the smallest
* divisor using the following brute force calculation:
*/
#define S698PM_TIMER_CLOCK 1000000
#define MATCH1 (( 1000000 / CLOCKS_PER_SEC) - 1)
/* Bit 0: enables the timer when set */
#define TIMCTR_ENABLE_COUNTER (1 << 0)
/* Bit 1: automatically reloaded with the reload value after each underflow */
#define TIMCTR_AUTO_RELOAD (1 << 1)
/* Bit 2: Set 1, will load the timer reload register into the timer counter
* register
*/
#define TIMCTR_LOAD_COUNTER (1 << 2)
/* Bit 3: Set 1, will triger underflow interrupt each underflow */
#define TIMCTR_ENABLE_INT (1 << 3)
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Function: s698pm_timerisr
*
* Description:
* The timer ISR will perform a variety of services for various portions
* of the systems.
*
****************************************************************************/
static int s698pm_timerisr(int irq, uint32_t *regs, void *arg)
{
/* Clear the pending timer interrupt */
up_clrpend_irq(S698PM_IRQ_TIMER1);
/* Process timer interrupt */
nxsched_process_timer();
return 0;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Function: up_timer_initialize
*
* Description:
* This function is called during start-up to initialize the timer
* interrupt. NOTE: This function depends on setup of OSC32 by
* up_clkinitialize().
*
****************************************************************************/
void up_timer_initialize(void)
{
uint32_t regval;
regval = (BOARD_CPU_CLOCK / S698PM_TIMER_CLOCK) - 1;
putreg16(regval, S698PM_TIMPRE_BASE + S698PM_TIM_PSCLOAD_OFFSET);
putreg16(regval, S698PM_TIMPRE_BASE + S698PM_TIM_PSCCONT_OFFSET);
/* Setup timer 1 compare match A to generate a tick interrupt.
*
* First, setup the match value for compare match A.
*/
putreg32(MATCH1, S698PM_TIM1_BASE + S698PM_TIM_CNT_OFFSET);
putreg32(MATCH1, S698PM_TIM1_BASE + S698PM_TIM_ARR_OFFSET);
regval = (TIMCTR_ENABLE_COUNTER | TIMCTR_AUTO_RELOAD |
TIMCTR_LOAD_COUNTER | TIMCTR_ENABLE_INT);
putreg32(regval, S698PM_TIM1_BASE + S698PM_TIM_CR_OFFSET);
/* Configure the timer interrupt */
up_clrpend_irq(S698PM_IRQ_TIMER1);
/* Attach the timer interrupt vector */
irq_attach(S698PM_IRQ_TIMER1, (xcpt_t)s698pm_timerisr, NULL);
/* Set up to timer1 interrupts on the current CPU */
#ifdef CONFIG_ARCH_IRQPRIO
(void)s698pm_setup_irq(0, S698PM_IRQ_TIMER1, CONFIG_S698PM_TIMER1PRIO);
#else
(void)s698pm_setup_irq(0, S698PM_IRQ_TIMER1, 0);
#endif
/* And enable the timer interrupt */
up_enable_irq(S698PM_IRQ_TIMER1);
}
+195
View File
@@ -0,0 +1,195 @@
/****************************************************************************
* arch/sparc/src/s698pm/s698pm-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_SPARC_SRC_S698PM_S698PM_UART_H
#define __ARCH_SPARC_SRC_S698PM_S698PM_UART_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include "chip.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Register Offsets *************************************************^*******/
#define S698PM_UART_TXREG_OFFSET 0x0000 /* UARTx transmit register */
#define S698PM_UART_RXREG_OFFSET 0x0000 /* UARTx receive register */
#define S698PM_UART_STATREG_OFFSET 0x0004 /* UARTx status register */
#define S698PM_UART_CTRLREG_OFFSET 0x0008 /* UARTx control register */
#define S698PM_UART_SCALREG_OFFSET 0x000c /* UARTx scaler register */
/* Register Addresses *******************************************************/
#if CHIP_NUARTS > 0
#define S698PM_UART1_TXREG (S698PM_UART1_BASE+S698PM_UART_TXREG_OFFSET)
#define S698PM_UART1_RXREG (S698PM_UART1_BASE+S698PM_UART_RXREG_OFFSET)
#define S698PM_UART1_STATREG (S698PM_UART1_BASE+S698PM_UART_STATREG_OFFSET)
#define S698PM_UART1_CTRLREG (S698PM_UART1_BASE+S698PM_UART_CTRLREG_OFFSET)
#define S698PM_UART1_SCALREG (S698PM_UART1_BASE+S698PM_UART_SCALREG_OFFSET)
#endif
#if CHIP_NUARTS > 1
#define S698PM_UART2_TXREG (S698PM_UART2_BASE+S698PM_UART_TXREG_OFFSET)
#define S698PM_UART2_RXREG (S698PM_UART2_BASE+S698PM_UART_RXREG_OFFSET)
#define S698PM_UART2_STATREG (S698PM_UART2_BASE+S698PM_UART_STATREG_OFFSET)
#define S698PM_UART2_CTRLREG (S698PM_UART2_BASE+S698PM_UART_CTRLREG_OFFSET)
#define S698PM_UART2_SCALREG (S698PM_UART2_BASE+S698PM_UART_SCALREG_OFFSET)
#endif
#if CHIP_NUARTS > 2
#define S698PM_UART3_TXREG (S698PM_UART3_BASE+S698PM_UART_TXREG_OFFSET)
#define S698PM_UART3_RXREG (S698PM_UART3_BASE+S698PM_UART_RXREG_OFFSET)
#define S698PM_UART3_STATREG (S698PM_UART3_BASE+S698PM_UART_STATREG_OFFSET)
#define S698PM_UART3_CTRLREG (S698PM_UART3_BASE+S698PM_UART_CTRLREG_OFFSET)
#define S698PM_UART3_SCALREG (S698PM_UART3_BASE+S698PM_UART_SCALREG_OFFSET)
#endif
#if CHIP_NUARTS > 3
#define S698PM_UART4_TXREG (S698PM_UART4_BASE+S698PM_UART_TXREG_OFFSET)
#define S698PM_UART4_RXREG (S698PM_UART4_BASE+S698PM_UART_RXREG_OFFSET)
#define S698PM_UART4_STATREG (S698PM_UART4_BASE+S698PM_UART_STATREG_OFFSET)
#define S698PM_UART4_CTRLREG (S698PM_UART4_BASE+S698PM_UART_CTRLREG_OFFSET)
#define S698PM_UART4_SCALREG (S698PM_UART4_BASE+S698PM_UART_SCALREG_OFFSET)
#endif
/* Register Bit-Field Definitions *******************************************/
#define ODD 1
#define EVEN 0
#define ON 1
#define OFF 0
#define NONE 2
#define RX 0
#define TX 1
#define RXTX 3
/** Uart control list - Mask */
#define MSK_UART_ENABLE_RX 0x01
#define MSK_UART_ENABLE_TX 0x02
#define MSK_UART_ENABLE_RXIT 0x04
#define MSK_UART_ENABLE_TXIT 0x08
#define MSK_UART_PAR 0x10
#define MSK_UART_ENABLE_PAR 0x20
#define MSK_UART_ENABLE_FLOW 0x40
#define MSK_UART_LOOPBACK 0x80
#define MSK_UART_CLOCK 0x100
#define MSK_UART_ALLINTS 0x0C
/* UARTx status and control register */
#define UART_STA_DR (1 << 0) /* Bit 0: Receive buffer data available */
#define UART_STA_TS (1 << 1) /* Bit 1: Transmit shift register is empty */
#define UART_STA_TE (1 << 2) /* Bit 2: TX buffer empty */
#define UART_STA_BR (1 << 3) /* Bit 3: Transmit break */
#define UART_STA_OV (1 << 4) /* Bit 4: overflow error status */
#define UART_STA_PE (1 << 5) /* Bit 5: Parity error status */
#define UART_STA_FE (1 << 6) /* Bit 6: Framing error status */
#define UART_STA_TH (1 << 7) /* Bit 7: TX buffer 1/2 full */
#define UART_STA_RH (1 << 8) /* Bit 8: RX buffer 1/2 full */
#define UART_STA_TF (1 << 9) /* Bit 9: Transmit buffer full status */
#define UART_STA_RF (1 << 10) /* Bit 10: Receive buffer full status */
#define REG_STAT_TX_CNT (0x3f << 20)
#define REG_STAT_RX_CNT (0x3f << 26)
/* UARTx transmit register */
#define UART_TXREG_MASK 0xff
/* UARTx receive register */
#define UART_RXREG_MASK 0xff
/* UARTx baud rate register */
#define UART_BRG_MASK 0xfff
#define uart_set_baudrate(baudrate) ((uint32_t)((((BOARD_CPU_CLOCK*10)/(baudrate * 8))-5)/10))
#define uart_parity_config(reg, uart_parity) ((uart_parity == ODD) ? \
(reg = ((reg | MSK_UART_PAR) | MSK_UART_ENABLE_PAR)) : \
((uart_parity == EVEN) ? \
(reg = ((reg & ~MSK_UART_PAR) | MSK_UART_ENABLE_PAR)) : \
(reg &= ~MSK_UART_ENABLE_PAR ) \
) \
)
#define Uart_interrupt_config(reg, uart_its) ((uart_its == RXTX) ? \
(reg |= (MSK_UART_ENABLE_RXIT | MSK_UART_ENABLE_TXIT)) : \
((uart_its == RX ) ? \
(reg |= (MSK_UART_ENABLE_RXIT & ~MSK_UART_ENABLE_TXIT)) : \
((uart_its == TX) ? \
(reg |= (MSK_UART_ENABLE_TXIT & ~MSK_UART_ENABLE_RXIT)) : \
(reg &= ~(MSK_UART_ENABLE_RXIT | MSK_UART_ENABLE_TXIT)) \
) \
) \
)
#define uart_flow_ctrl_config(reg, uart_flow) ((uart_flow == ON) ? \
(reg |= MSK_UART_ENABLE_FLOW) : \
(reg &= ~MSK_UART_ENABLE_FLOW) \
)
#define uart_loopback_config(reg, uart_loopb) ((uart_loopb == ON) ? \
(reg |= MSK_UART_LOOPBACK) : \
(reg &= ~MSK_UART_LOOPBACK) \
)
#define uart_enable(reg) (reg |= (MSK_UART_ENABLE_RX | MSK_UART_ENABLE_TX))
#define uart_disable(reg) (reg &= ~(MSK_UART_ENABLE_RX | MSK_UART_ENABLE_TX))
#define uart_tx_ready() ((S698PM_REG.uart_status1 & UART_STA_TF) != UART_STA_TF)
#define uart_rx_ready() ((S698PM_REG.uart_status1 & UART_STA_DR) == UART_STA_DR)
#define uart_send_byte(ch) (S698PM_REG.uart_data1 = ch)
/****************************************************************************
* Public Types
****************************************************************************/
#ifndef __ASSEMBLY__
/****************************************************************************
* Inline Functions
****************************************************************************/
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_SPARC_SRC_S698PM_S698PM_UART_H */
+442
View File
@@ -0,0 +1,442 @@
/****************************************************************************
* arch/sparc/src/s698pm/s698pm.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_SPARC_SRC_S698PM_S698PM_H
#define __ARCH_SARRC_SRC_S698PM_S698PM_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include "s698pm-config.h"
#include <stdint.h>
#include <stdbool.h>
#include "s698pm_irq.h"
#ifdef CONFIG_S698PM_GPIOIRQ
#include <nuttx/irq.h>
#include "s698pm_exti.h"
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* The following defines the bits in Memory Configuration Register 1. */
#define S698PM_MEMORY_CONFIGURATION_PROM_SIZE_MASK 0x0003C000
/* The following defines the bits in Memory Configuration Register 1. */
#define S698PM_MEMORY_CONFIGURATION_RAM_SIZE_MASK 0x00001E00
/* The following defines the bits in the Timer Control Register. */
/* 1 = enable counting
* 0 = hold scalar and counter
*/
#define S698PM_REG_TIMER_CONTROL_EN 0x00000001
/* 1 = reload at 0
* 0 = stop at 0
*/
#define S698PM_REG_TIMER_CONTROL_RL 0x00000002
/* 1 = load counter
* 0 = no function
*/
#define S698PM_REG_TIMER_CONTROL_LD 0x00000004
/* The following defines the bits in the UART Control Registers. */
#define S698PM_REG_UartCtrlRTD 0x000000FF /* RX/TX data */
/* The following defines the bits in the S698PM UART Status Registers. */
#define S698PM_REG_UART_STATUS_CLR 0x00000000 /* Clear all status bits */
#define S698PM_REG_UART_STATUS_DR 0x00000001 /* Data Ready */
#define S698PM_REG_UART_STATUS_TSE 0x00000002 /* TX Send Register Empty */
#define S698PM_REG_UART_STATUS_THE 0x00000004 /* TX Hold Register Empty */
#define S698PM_REG_UART_STATUS_BR 0x00000008 /* Break Error */
#define S698PM_REG_UART_STATUS_OE 0x00000010 /* RX Overrun Error */
#define S698PM_REG_UART_STATUS_PE 0x00000020 /* RX Parity Error */
#define S698PM_REG_UART_STATUS_FE 0x00000040 /* RX Framing Error */
#define S698PM_REG_UART_STATUS_ERR 0x00000078 /* Error Mask */
/* The following defines the bits in the S698PM UART Status Registers. */
#define S698PM_REG_UART_CTRL_RE 0x00000001 /* Receiver enable */
#define S698PM_REG_UART_CTRL_TE 0x00000002 /* Transmitter enable */
#define S698PM_REG_UART_CTRL_RI 0x00000004 /* Receiver interrupt enable */
#define S698PM_REG_UART_CTRL_TI 0x00000008 /* Transmitter interrupt enable */
#define S698PM_REG_UART_CTRL_PS 0x00000010 /* Parity select */
#define S698PM_REG_UART_CTRL_PE 0x00000020 /* Parity enable */
#define S698PM_REG_UART_CTRL_FL 0x00000040 /* Flow control enable */
#define S698PM_REG_UART_CTRL_LB 0x00000080 /* Loop Back enable */
#ifndef __ASSEMBLY__
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_SMP
/* SPARC requires at least a 8-byte stack alignment */
#define SMP_STACK_ALIGNMENT 8
#define SMP_STACK_MASK 7
#define SMP_STACK_SIZE ((CONFIG_IDLETHREAD_STACKSIZE + 7) & ~7)
#define SMP_STACK_WORDS (SMP_STACK_SIZE >> 2)
/****************************************************************************
* Public Data
****************************************************************************/
extern uint32_t g_cpu0_idlestack[SMP_STACK_WORDS];
#if CONFIG_SMP_NCPUS > 1
extern uint32_t g_cpu1_idlestack[SMP_STACK_WORDS];
#if CONFIG_SMP_NCPUS > 2
extern uint32_t g_cpu2_idlestack[SMP_STACK_WORDS];
#if CONFIG_SMP_NCPUS > 3
extern uint32_t g_cpu3_idlestack[SMP_STACK_WORDS];
#if CONFIG_SMP_NCPUS > 4
# error This logic needs to extended for CONFIG_SMP_NCPUS > 4
#endif /* CONFIG_SMP_NCPUS > 4 */
#endif /* CONFIG_SMP_NCPUS > 3 */
#endif /* CONFIG_SMP_NCPUS > 2 */
#endif /* CONFIG_SMP_NCPUS > 1 */
#endif
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Read CPU ID(LEON3)
****************************************************************************/
#define LEON3_READ_CPUID(reg) \
RD %asr17 , reg; \
SRL reg , 28 , reg;
/****************************************************************************
* Read CPU ID (Now only support LEON3, LEON4!)
****************************************************************************/
#ifdef CONFIG_SMP
#define READ_CPUID(reg) LEON3_READ_CPUID(reg)
#else
#define READ_CPUID(reg) MOV %g0 , reg
#endif
/* Trap Types for on-chip peripherals
*
* Source: Table 8 - Interrupt Trap Type and Default Priority Assignments
*
* NOTE: The priority level for each source corresponds to the least
* significant nibble of the trap type.
*/
#define S698PM_TRAP_TYPE( _source ) SPARC_ASYNCHRONOUS_TRAP((_source) + 0x10)
#define S698PM_TRAP_SOURCE( _trap ) ((_trap) - 0x10)
#define S698PM_INT_TRAP( _trap ) \
( (_trap) >= S698PM_TRAP_TYPE( S698PM_IRQ_CORRECTABLE_MEMORY_ERROR ) && \
(_trap) <= S698PM_TRAP_TYPE( S698PM_IRQ_EMPTY6 ) )
static __inline__ int bsp_irq_fixup(int irq)
{
return irq;
}
/* Macros to manipulate the Interrupt Clear, Interrupt Force, Interrupt Mask
* and the Interrupt Pending Registers.
*
* NOTE: For operations which are not atomic, this code disables interrupts
* to guarantee there are no intervening accesses to the same register
* The operations which read the register, modify the value and then
* store the result back are vulnerable.
*/
#define S698PM_Clear_interrupt( _source ) \
do { \
S698PM_REG.Interrupt_Clear = (1 << (_source)); \
} while (0)
#define S698PM_Force_interrupt( _source ) \
do { \
S698PM_REG.Interrupt_Force = (1 << (_source)); \
} while (0)
#define S698PM_Is_interrupt_pending( _source ) \
(S698PM_REG.Interrupt_Pending & (1 << (_source)))
#define S698PM_Is_interrupt_masked( _source ) \
(!(S698PM_REG.Interrupt_Mask & (1 << (_source))))
#define S698PM_Mask_interrupt( _source ) \
do { \
uint32_t _level; \
\
_level = sparc_disable_interrupts(); \
S698PM_REG.Interrupt_Mask &= ~(1 << (_source)); \
sparc_enable_interrupts( _level ); \
} while (0)
#define S698PM_Unmask_interrupt( _source ) \
do { \
uint32_t _level; \
\
_level = sparc_disable_interrupts(); \
S698PM_REG.Interrupt_Mask |= (1 << (_source)); \
sparc_enable_interrupts( _level ); \
} while (0)
#define S698PM_Disable_interrupt( _source, _previous ) \
do { \
uint32_t _level; \
uint32_t _mask = 1 << (_source); \
\
_level = sparc_disable_interrupts(); \
(_previous) = S698PM_REG.Interrupt_Mask; \
S698PM_REG.Interrupt_Mask = _previous & ~_mask; \
sparc_enable_interrupts( _level ); \
(_previous) &= _mask; \
} while (0)
#define S698PM_Restore_interrupt( _source, _previous ) \
do { \
uint32_t _level; \
uint32_t _mask = 1 << (_source); \
\
_level = sparc_disable_interrupts(); \
S698PM_REG.Interrupt_Mask = \
(S698PM_REG.Interrupt_Mask & ~_mask) | (_previous); \
sparc_enable_interrupts( _level ); \
} while (0)
/* Each timer control register is organized as follows:
*
* D0 - Enable
* 1 = enable counting
* 0 = hold scaler and counter
*
* D1 - Counter Reload
* 1 = reload counter at zero and restart
* 0 = stop counter at zero
*
* D2 - Counter Load
* 1 = load counter with preset value
* 0 = no function
*
*/
#define S698PM_REG_TIMER_COUNTER_RELOAD_AT_ZERO 0x00000002
#define S698PM_REG_TIMER_COUNTER_STOP_AT_ZERO 0x00000000
#define S698PM_REG_TIMER_COUNTER_LOAD_COUNTER 0x00000004
#define S698PM_REG_TIMER_COUNTER_ENABLE_COUNTING 0x00000001
#define S698PM_REG_TIMER_COUNTER_DISABLE_COUNTING 0x00000000
#define S698PM_REG_TIMER_COUNTER_RELOAD_MASK 0x00000002
#define S698PM_REG_TIMER_COUNTER_ENABLE_MASK 0x00000001
#define S698PM_REG_TIMER_COUNTER_DEFINED_MASK 0x00000003
#define S698PM_REG_TIMER_COUNTER_CURRENT_MODE_MASK 0x00000003
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/* Load 32-bit word by forcing a cache-miss */
static inline unsigned int s698pm_r32_no_cache(uintptr_t addr)
{
unsigned int tmp;
__asm__ volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(addr));
return tmp;
}
/****************************************************************************
* Name: up_clkinit
*
* Description:
* Initialiaze clock/PLL settings per the definitions in the board.h file.
*
****************************************************************************/
void up_clkinitialize(void);
/****************************************************************************
* Name: s698pm_consoleinit
*
* Description:
* Performs low level initialization of the console UART. This UART done
* early so that the serial console is available for debugging very early
* in the boot
* sequence.
*
****************************************************************************/
#ifdef HAVE_SERIAL_CONSOLE
void s698pm_consoleinit(void);
#else
# define s698pm_consoleinit()
#endif
/****************************************************************************
* Name: s698pm_uartreset
*
* Description:
* Reset a UART.
*
****************************************************************************/
#ifdef HAVE_UART_DEVICE
void s698pm_uartreset(uintptr_t uart_base);
#endif
/****************************************************************************
* Name: s698pm_uartconfigure
*
* Description:
* Configure a UART as a RS-232 UART.
*
****************************************************************************/
#ifdef HAVE_UART_DEVICE
void s698pm_uartconfigure(uintptr_t uart_base, uint32_t baudrate,
unsigned int parity, unsigned int nbits, bool stop2);
#endif
/****************************************************************************
* Name: s698pm_boardinitialize
*
* Description:
* This function must be provided by the board-specific logic in the
* directory boards/sparc/s698pm/<board-name>/src.
*
****************************************************************************/
void s698pm_boardinitialize(void);
/****************************************************************************
* Name: gpio_irqinitialize
*
* Description:
* Initialize all vectors to the unexpected interrupt handler
*
* Configuration Notes:
* Configuration CONFIG_AVR_GPIOIRQ must be selected to enable the
* overall GPIO IRQ feature.
*
* Assumptions:
* Called during the early boot sequence before global interrupts have
* been enabled.
*
****************************************************************************/
#ifdef CONFIG_SPARC_GPIOIRQ
void weak_function gpio_irqinitialize(void);
#endif
/****************************************************************************
* Name: gpio_irqattach
*
* Description:
* Attach in GPIO interrupt to the provide 'isr'
*
* Configuration Notes:
* Configuration CONFIG_AVR_GPIOIRQ must be selected to enable the
* overall GPIO IRQ feature.
*
****************************************************************************/
#ifdef CONFIG_SPARC_GPIOIRQ
int gpio_irqattach(int irq, xcpt_t newisr, xcpt_t *oldisr);
#endif
/****************************************************************************
* Name: gpio_irqenable
*
* Description:
* Enable the GPIO IRQ specified by 'irq'
*
* Configuration Notes:
* Configuration CONFIG_AVR_GPIOIRQ must be selected to enable the
* overall GPIO IRQ feature.
*
****************************************************************************/
#ifdef CONFIG_SPARC_GPIOIRQ
void gpio_irqenable(int irq);
#endif
/****************************************************************************
* Name: gpio_irqdisable
*
* Description:
* Disable the GPIO IRQ specified by 'irq'
*
* Configuration Notes:
* Configuration CONFIG_AVR_GPIOIRQ must be selected to enable the
* overall GPIO IRQ feature.
*
****************************************************************************/
#ifdef CONFIG_SPARC_GPIOIRQ
void gpio_irqdisable(int irq);
#endif
/****************************************************************************
* Name: s698pm_pause_handler
*
* Description:
* Inter-CPU interrupt handler
*
* Input Parameters:
* Standard interrupt handler inputs
*
* Returned Value:
* Should always return OK
*
****************************************************************************/
#ifdef CONFIG_SMP
int s698pm_pause_handler(int irq, void *c, void *arg);
#endif
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_SPARC_SRC_S698PM_S698PM_H */
+132
View File
@@ -0,0 +1,132 @@
/****************************************************************************
* arch/sparc/src/s698pm/s698pm_cpuidlestack.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 <nuttx/config.h>
#include <sys/types.h>
#include <assert.h>
#include <nuttx/arch.h>
#include <nuttx/sched.h>
#include "up_internal.h"
#include "s698pm.h"
#ifdef CONFIG_SMP
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Stack alignment macros */
#define STACK_ISALIGNED(a) ((uintptr_t)(a) & ~SMP_STACK_MASK)
/****************************************************************************
* Private Data
****************************************************************************/
#if CONFIG_SMP_NCPUS > 1
static const uint32_t *g_cpu_stackalloc[CONFIG_SMP_NCPUS] =
{
g_cpu0_idlestack
, g_cpu1_idlestack
#if CONFIG_SMP_NCPUS > 2
, g_cpu2_idlestack
#if CONFIG_SMP_NCPUS > 3
, g_cpu3_idlestack
#endif /* CONFIG_SMP_NCPUS > 3 */
#endif /* CONFIG_SMP_NCPUS > 2 */
};
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_cpu_idlestack
*
* Description:
* Allocate a stack for the CPU[n] IDLE task (n > 0) if appropriate and
* setup up stack-related information in the IDLE task's TCB. This
* function is always called before up_cpu_start(). This function is
* only called for the CPU's initial IDLE task; up_create_task is used for
* all normal tasks, pthreads, and kernel threads for all CPUs.
*
* The initial IDLE task is a special case because the CPUs can be started
* in different wans in different environments:
*
* 1. The CPU may already have been started and waiting in a low power
* state for up_cpu_start(). In this case, the IDLE thread's stack
* has already been allocated and is already in use. Here
* up_cpu_idlestack() only has to provide information about the
* already allocated stack.
*
* 2. The CPU may be disabled but started when up_cpu_start() is called.
* In this case, a new stack will need to be created for the IDLE
* thread and this function is then equivalent to:
*
* return up_create_stack(tcb, stack_size, TCB_FLAG_TTYPE_KERNEL);
*
* The following TCB fields must be initialized by this function:
*
* - adj_stack_size: Stack size after adjustment for hardware, processor,
* etc. This value is retained only for debug purposes.
* - stack_alloc_ptr: Pointer to allocated stack
* - stack_base_ptr: Adjusted stack base pointer after the TLS Data and
* Arguments has been removed from the stack allocation.
*
* Input Parameters:
* - cpu: CPU index that indicates which CPU the IDLE task is
* being created for.
* - tcb: The TCB of new CPU IDLE task
* - stack_size: The requested stack size for the IDLE task. At least
* this much must be allocated. This should be
* CONFIG_SMP_STACK_SIZE.
*
****************************************************************************/
int up_cpu_idlestack(int cpu, struct tcb_s *tcb, size_t stack_size)
{
#if CONFIG_SMP_NCPUS > 1
uintptr_t stack_alloc;
DEBUGASSERT(cpu > 0 && cpu < CONFIG_SMP_NCPUS && tcb != NULL &&
stack_size <= SMP_STACK_SIZE);
/* Get the top of the stack */
stack_alloc = (uintptr_t)g_cpu_stackalloc[cpu];
DEBUGASSERT(stack_alloc != 0 && STACK_ISALIGNED(stack_alloc));
tcb->adj_stack_size = SMP_STACK_SIZE;
tcb->stack_alloc_ptr = (void *)stack_alloc;
tcb->stack_base_ptr = tcb->stack_alloc_ptr;
#endif
return OK;
}
#endif /* CONFIG_SMP */
+68
View File
@@ -0,0 +1,68 @@
/****************************************************************************
* arch/sparc/src/s698pm/s698pm_cpuindex.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 <nuttx/config.h>
#include <stdint.h>
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include "up_internal.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_cpu_index
*
* Description:
* Return an index in the range of 0 through (CONFIG_SMP_NCPUS-1) that
* corresponds to the currently executing CPU.
*
* Input Parameters:
* None
*
* Returned Value:
* An integer index in the range of 0 through (CONFIG_SMP_NCPUS-1) that
* corresponds to the currently executing CPU.
*
****************************************************************************/
#ifdef CONFIG_SMP
int up_cpu_index(void)
{
int cpu = 0;
__asm__ __volatile__
(
"rd %%asr17, %0\n"
"srl %0, 28, %0\n"
: "=r" (cpu) : "0" (cpu)
);
return cpu;
}
#endif
+324
View File
@@ -0,0 +1,324 @@
/****************************************************************************
* arch/sparc/src/s698pm/s698pm_cpupause.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 <nuttx/config.h>
#include <stdint.h>
#include <assert.h>
#include <debug.h>
#include <string.h>
#include <stdio.h>
#include <nuttx/arch.h>
#include <nuttx/spinlock.h>
#include <nuttx/sched_note.h>
#include "sched/sched.h"
#include "up_internal.h"
#include "chip.h"
/****************************************************************************
* Public Data
****************************************************************************/
/* These spinlocks are used in the SMP configuration in order to implement
* up_cpu_pause(). The protocol for CPUn to pause CPUm is as follows
*
* 1. The up_cpu_pause() implementation on CPUn locks both g_cpu_wait[m]
* and g_cpu_paused[m]. CPUn then waits spinning on g_cpu_paused[m].
* 2. CPUm receives the interrupt it (1) unlocks g_cpu_paused[m] and
* (2) locks g_cpu_wait[m]. The first unblocks CPUn and the second
* blocks CPUm in the interrupt handler.
*
* When CPUm resumes, CPUn unlocks g_cpu_wait[m] and the interrupt handler
* on CPUm continues. CPUm must, of course, also then unlock g_cpu_wait[m]
* so that it will be ready for the next pause operation.
*/
volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
volatile spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS];
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_cpu_pausereq
*
* Description:
* Return true if a pause request is pending for this CPU.
*
* Input Parameters:
* cpu - The index of the CPU to be queried
*
* Returned Value:
* true = a pause request is pending.
* false = no pasue request is pending.
*
****************************************************************************/
bool up_cpu_pausereq(int cpu)
{
return spin_islocked(&g_cpu_paused[cpu]);
}
/****************************************************************************
* Name: up_cpu_paused
*
* Description:
* Handle a pause request from another CPU. Normally, this logic is
* executed from interrupt handling logic within the architecture-specific
* However, it is sometimes necessary necessary to perform the pending
* pause operation in other contexts where the interrupt cannot be taken
* in order to avoid deadlocks.
*
* This function performs the following operations:
*
* 1. It saves the current task state at the head of the current assigned
* task list.
* 2. It waits on a spinlock, then
* 3. Returns from interrupt, restoring the state of the new task at the
* head of the ready to run list.
*
* Input Parameters:
* cpu - The index of the CPU to be paused
*
* Returned Value:
* On success, OK is returned. Otherwise, a negated errno value indicating
* the nature of the failure is returned.
*
****************************************************************************/
int up_cpu_paused(int cpu)
{
struct tcb_s *tcb = this_task();
/* Update scheduler parameters */
nxsched_suspend_scheduler(tcb);
#ifdef CONFIG_SCHED_INSTRUMENTATION
/* Notify that we are paused */
sched_note_cpu_paused(tcb);
#endif
/* Save the current context at CURRENT_REGS into the TCB at the head
* of the assigned task list for this CPU.
*/
up_savestate(tcb->xcp.regs);
/* Wait for the spinlock to be released */
spin_unlock(&g_cpu_paused[cpu]);
spin_lock(&g_cpu_wait[cpu]);
/* Restore the exception context of the tcb at the (new) head of the
* assigned task list.
*/
tcb = this_task();
#ifdef CONFIG_SCHED_INSTRUMENTATION
/* Notify that we have resumed */
sched_note_cpu_resumed(tcb);
#endif
/* Reset scheduler parameters */
nxsched_resume_scheduler(tcb);
/* Then switch contexts. Any necessary address environment changes
* will be made when the interrupt returns.
*/
up_restorestate(tcb->xcp.regs);
spin_unlock(&g_cpu_wait[cpu]);
return OK;
}
/****************************************************************************
* Name: s698pm_pause_handler
*
* Description:
* Inter-CPU interrupt handler
*
* Input Parameters:
* Standard interrupt handler inputs
*
* Returned Value:
* Should always return OK
*
****************************************************************************/
int s698pm_pause_handler(int irq, void *c, void *arg)
{
int cpu = up_cpu_index();
/* Clear IPI (Inter-Processor-Interrupt) */
putreg32(1 << S698PM_IPI_VECTOR, S698PM_IRQREG_ICLEAR);
/* Check for false alarms. Such false could occur as a consequence of
* some deadlock breaking logic that might have already serviced the SG2
* interrupt by calling up_cpu_paused.
*/
if (up_cpu_pausereq(cpu))
{
/* NOTE: The following enter_critical_section() will call
* up_cpu_paused() to process a pause request to break a deadlock
* because the caller held a critical section. Once up_cpu_paused()
* finished, the caller will proceed and release the g_cpu_irqlock.
* Then this CPU will acquire g_cpu_irqlock in the function.
*/
irqstate_t flags = enter_critical_section();
/* NOTE: the pause request should not exist here */
DEBUGVERIFY(!up_cpu_pausereq(cpu));
leave_critical_section(flags);
}
return OK;
}
/****************************************************************************
* Name: up_cpu_pause
*
* Description:
* Save the state of the current task at the head of the
* g_assignedtasks[cpu] task list and then pause task execution on the
* CPU.
*
* This function is called by the OS when the logic executing on one CPU
* needs to modify the state of the g_assignedtasks[cpu] list for another
* CPU.
*
* Input Parameters:
* cpu - The index of the CPU to be stopped/
*
* Returned Value:
* Zero on success; a negated errno value on failure.
*
****************************************************************************/
int up_cpu_pause(int cpu)
{
uintptr_t regaddr;
sinfo("cpu=%d\n", cpu);
#ifdef CONFIG_SCHED_INSTRUMENTATION
/* Notify of the pause event */
sched_note_cpu_pause(this_task(), cpu);
#endif
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
/* Take the both spinlocks. The g_cpu_wait spinlock will prevent the SGI2
* handler from returning until up_cpu_resume() is called; g_cpu_paused
* is a handshake that will prefent this function from returning until
* the CPU is actually paused.
* Note that we might spin before getting g_cpu_wait, this just means that
* the other CPU still hasn't finished responding to the previous resume
* request.
*/
DEBUGASSERT(!spin_islocked(&g_cpu_paused[cpu]));
spin_lock(&g_cpu_wait[cpu]);
spin_lock(&g_cpu_paused[cpu]);
/* Execute Pause IRQ to CPU(cpu) */
regaddr = (uintptr_t)S698PM_IRQREG_P0_FORCE + (4 * cpu);
putreg32(1 << S698PM_IPI_VECTOR, regaddr);
/* Wait for the other CPU to unlock g_cpu_paused meaning that
* it is fully paused and ready for up_cpu_resume();
*/
spin_lock(&g_cpu_paused[cpu]);
spin_unlock(&g_cpu_paused[cpu]);
/* On successful return g_cpu_wait will be locked, the other CPU will be
* spinning on g_cpu_wait and will not continue until g_cpu_resume() is
* called. g_cpu_paused will be unlocked in any case.
*/
return 0;
}
/****************************************************************************
* Name: up_cpu_resume
*
* Description:
* Restart the cpu after it was paused via up_cpu_pause(), restoring the
* state of the task at the head of the g_assignedtasks[cpu] list, and
* resume normal tasking.
*
* This function is called after up_cpu_pause in order resume operation of
* the CPU after modifying its g_assignedtasks[cpu] list.
*
* Input Parameters:
* cpu - The index of the CPU being re-started.
*
* Returned Value:
* Zero on success; a negated errno value on failure.
*
****************************************************************************/
int up_cpu_resume(int cpu)
{
sinfo("cpu=%d\n", cpu);
#ifdef CONFIG_SCHED_INSTRUMENTATION
/* Notify of the resume event */
sched_note_cpu_resume(this_task(), cpu);
#endif
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
/* Release the spinlock. Releasing the spinlock will cause the SGI2
* handler on 'cpu' to continue and return from interrupt to the newly
* established thread.
*/
DEBUGASSERT(spin_islocked(&g_cpu_wait[cpu]) &&
!spin_islocked(&g_cpu_paused[cpu]));
spin_unlock(&g_cpu_wait[cpu]);
return 0;
}
+165
View File
@@ -0,0 +1,165 @@
/****************************************************************************
* arch/sparc/src/s698pm/s698pm_cpustart.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 <nuttx/config.h>
#include <stdint.h>
#include <assert.h>
#include <debug.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <nuttx/arch.h>
#include <nuttx/spinlock.h>
#include <nuttx/sched_note.h>
#include "sched/sched.h"
#include "up_internal.h"
#ifdef CONFIG_BUILD_KERNEL
# include "s698pm_mmu.h"
#endif
#include "s698pm.h"
/****************************************************************************
* Public Data
****************************************************************************/
volatile static spinlock_t g_cpu_boot;
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: s698pm_cpu_boot
*
* Description:
* Boot handler for cpu[x]
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void s698pm_cpu_boot(void)
{
struct tcb_s *tcb = this_task();
_info("CPU%d Started\n", this_cpu());
/* Initialize CPU interrupts */
s698pm_cpuint_initialize();
spin_unlock(&g_cpu_boot);
#ifdef CONFIG_SCHED_INSTRUMENTATION
/* Notify that this CPU has started */
sched_note_cpu_started(tcb);
#endif
/* Reset scheduler parameters */
nxsched_resume_scheduler(tcb);
/* And finally, enable cpu interrupts */
#ifndef CONFIG_SUPPRESS_INTERRUPTS
up_irq_enable();
#endif
/* Then transfer control to the IDLE task */
nx_idle_trampoline();
}
/****************************************************************************
* Name: up_cpu_start
*
* Description:
* In an SMP configuration, only one CPU is initially active (CPU 0).
* System initialization occurs on that single thread. At the completion of
* the initialization of the OS, just before beginning normal multitasking,
* the additional CPUs would be started by calling this function.
*
* Each CPU is provided the entry point to its IDLE task when started. A
* TCB for each CPU's IDLE task has been initialized and placed in the
* CPU's g_assignedtasks[cpu] list. No stack has been allocated or
* initialized.
*
* The OS initialization logic calls this function repeatedly until each
* CPU has been started, 1 through (CONFIG_SMP_NCPUS-1).
*
* Input Parameters:
* cpu - The index of the CPU being started. This will be a numeric
* value in the range of one to (CONFIG_SMP_NCPUS-1).
* (CPU 0 is already active)
*
* Returned Value:
* Zero on success; a negated errno value on failure.
*
****************************************************************************/
int up_cpu_start(int cpu)
{
uintptr_t regaddr;
_info("CPU=%d\n", cpu);
#ifdef CONFIG_SCHED_INSTRUMENTATION
/* Notify of the start event */
sched_note_cpu_start(this_task(), cpu);
#endif
/* Set the start up address */
regaddr = S698PM_DSU_BASE + (0x1000000 * cpu) + S698PM_DSU_PC_OFFSET;
putreg32(CONFIG_RAM_START, regaddr);
putreg32(0x40001000, regaddr);
regaddr = S698PM_DSU_BASE + (0x1000000 * cpu) + S698PM_DSU_NPC_OFFSET;
putreg32(0x40001004, regaddr);
spin_lock(&g_cpu_boot);
/* set 1 to bit n of multiprocessor status register to active cpu n */
putreg32(1 << cpu, S698PM_IRQREG_MPSTATUS);
spin_lock(&g_cpu_boot);
/* prev cpu boot done */
spin_unlock(&g_cpu_boot);
return 0;
}
+482
View File
@@ -0,0 +1,482 @@
/****************************************************************************
* arch/sparc/src/s698pm/up_exceptions.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 <nuttx/config.h>
#include <arch/irq.h>
.file "s698pm_exceptions.S"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
.text
/****************************************************************************
* Public Functions
****************************************************************************/
.global _ISR_Handler
#if defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 7
.global g_cpu_intstack_top
#endif /* CONFIG_SMP && CONFIG_ARCH_INTERRUPTSTACK > 7 */
.global up_doirq /* Dispatch an IRQ */
.align 8
/*
* void _ISR_Handler()
*
* This routine provides the RTEMS interrupt management.
*
* We enter this handler from the 4 instructions in the trap table with
* the following registers assumed to be set as shown:
*
* l0 = PSR
* l1 = PC
* l2 = nPC
* l3 = trap type
*
* NOTE: By an executive defined convention, trap type is between 0 and 255 if
* it is an asynchonous trap and 256 and 511 if it is synchronous.
*/
_ISR_Handler:
/*
* Fix the return address for synchronous traps.
*/
and %l3, 0xF0, %l6
cmp %l6, 0x10 ! Is this a synchronous trap?
be,a win_ovflow ! No, then skip the adjustment
nop ! DELAY
mov %l2, %l1 ! do not return to the instruction
add %l2, 4, %l2 ! indicated
win_ovflow:
/*
* Save the globals this block uses.
*
* These registers are not restored from the locals. Their contents
* are saved directly from the locals into the ISF below.
*/
mov %g4, %l4 ! save the globals this block uses
mov %g5, %l5
/*
* When at a "window overflow" trap, (wim == (1 << cwp)).
* If we get here like that, then process a window overflow.
*/
rd %wim, %g4
srl %g4, %l0, %g5 ! g5 = win >> cwp ; shift count and CWP
! are LS 5 bits ; how convenient :)
cmp %g5, 1 ! Is this an invalid window?
bne dont_do_the_window ! No, then skip all this stuff
nop
! we are using the delay slot
/*
* The following is same as a 1 position right rotate of WIM
*/
srl %g4, 1, %g5 ! g5 = WIM >> 1
sll %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS-1 , %g4
! g4 = WIM << (Number Windows - 1)
or %g4, %g5, %g4 ! g4 = (WIM >> 1) |
! (WIM << (Number Windows - 1))
/*
* At this point:
*
* g4 = the new WIM
* g5 is free
*/
/*
* Since we are tinkering with the register windows, we need to
* make sure that all the required information is in global registers.
*/
save ! Save into the window
wr %g4, 0, %wim ! WIM = new WIM
nop ! delay slots
nop
nop
/*
* Now save the window just as if we overflowed to it.
*/
SAVE_WINDOW:
std %l0, [%sp + CPU_STACK_FRAME_L0_OFFSET]
std %l2, [%sp + CPU_STACK_FRAME_L2_OFFSET]
std %l4, [%sp + CPU_STACK_FRAME_L4_OFFSET]
std %l6, [%sp + CPU_STACK_FRAME_L6_OFFSET]
std %i0, [%sp + CPU_STACK_FRAME_I0_OFFSET]
std %i2, [%sp + CPU_STACK_FRAME_I2_OFFSET]
std %i4, [%sp + CPU_STACK_FRAME_I4_OFFSET]
std %i6, [%sp + CPU_STACK_FRAME_I6_FP_OFFSET]
restore
nop
dont_do_the_window:
/*
* Global registers %g4 and %g5 are saved directly from %l4 and
* %l5 directly into the ISF below.
*/
save_isf:
/*
* Save the state of the interrupted task -- especially the global
* registers -- in the Interrupt Stack Frame. Note that the ISF
* includes a regular minimum stack frame which will be used if
* needed by register window overflow and underflow handlers.
*
* REGISTERS SAME AS AT _ISR_Handler
*/
#if CONFIG_ARCH_INTERRUPTSTACK > 7
#ifdef CONFIG_SMP
rd %asr17 , %g5
srl %g5 , 28 , %g5 ! Bits 0-1=CPU ID
#else
mov %g0, %g5 ! CPU ID = 0
#endif
sll %g5, 2 , %g5 ! %g5 = CPUID * 4
set g_cpu_intstack_top, %g4 ! %g4 = Array of stack pointers
add %g4, %g5, %g4 ! %g4 = g_cpu_intstack_top + CPUID * 4
ld [%g4], %g5 ! restore %sp
sub %g5, CONTEXT_CONTROL_INTERRUPT_FRAME_SIZE, %sp
#else
sub %fp, CONTEXT_CONTROL_INTERRUPT_FRAME_SIZE, %sp
#endif
std %l0, [%sp + ISF_PSR_OFFSET] ! save psr, PC
st %l2, [%sp + ISF_NPC_OFFSET] ! save nPC
st %g1, [%sp + ISF_G1_OFFSET] ! save g1
std %g2, [%sp + ISF_G2_OFFSET] ! save g2, g3
std %l4, [%sp + ISF_G4_OFFSET] ! save g4, g5 -- see above
std %g6, [%sp + ISF_G6_OFFSET] ! save g6, g7
std %i0, [%sp + ISF_I0_OFFSET] ! save i0, i1
std %i2, [%sp + ISF_I2_OFFSET] ! save i2, i3
std %i4, [%sp + ISF_I4_OFFSET] ! save i4, i5
std %i6, [%sp + ISF_I6_FP_OFFSET] ! save i6/fp, i7
rd %y, %g1
st %g1, [%sp + ISF_Y_OFFSET] ! save y
mov %sp, %o1 ! 2nd arg to ISR Handler
st %fsr, [%sp + ISF_FSR_OFFSET]
std %f0, [%sp + ISF_F0_OFFSET]
std %f2, [%sp + ISF_F2_OFFSET]
std %f4, [%sp + ISF_F4_OFFSET]
std %f6, [%sp + ISF_F6_OFFSET]
std %f8, [%sp + ISF_F8_OFFSET]
std %f10, [%sp + ISF_F10_OFFSET]
std %f12, [%sp + ISF_F12_OFFSET]
std %f14, [%sp + ISF_F14_OFFSET]
std %f16, [%sp + ISF_F16_OFFSET]
std %f18, [%sp + ISF_F18_OFFSET]
std %f20, [%sp + ISF_F20_OFFSET]
std %f22, [%sp + ISF_F22_OFFSET]
std %f24, [%sp + ISF_F24_OFFSET]
std %f26, [%sp + ISF_F26_OFFSET]
std %f28, [%sp + ISF_F28_OFFSET]
std %f30, [%sp + ISF_F30_OFFSET] ! total 32 word
fix_pil:
mov %l0, %g5
or %g5, SPARC_PSR_PIL_MASK, %g5 /* 0x00000F00 */
wr %g5, SPARC_PSR_ET_MASK, %psr ! **** ENABLE TRAPS **** /* 0x00000020 */
nop
nop
nop
/*==========================================================================*/
cmp %l3, 11 ! l3 = vector number
bne do_irq
nop
#ifdef CONFIG_SMP
rd %asr17 , %l4
srl %l4 , 28 , %l4
#else
mov %g0 , %l4
#endif
set S698PM_IRQREG_P0_EXTACK, %l5
sll %l4, 2, %l4 ! l4 = CPUID * 4
add %l5, %l4, %l5 ! l5 = S698PM_IRQREG_P(k)_EXTACK
ld [%l5], %l4 ! l4 = EXTENDED_ACK
cmp %l4, %g0
be do_irq
nop
add %l4, 240, %l3 ! l3 = extended vector number
do_irq:
! o1 = 2nd arg = address of the ISF
! WAS LOADED WHEN ISF WAS SAVED!!!
mov %l3, %o0 ! o0 = 1st arg = vector number
call up_doirq /* call ISR dispatcher */
nop
/*==========================================================================*/
mov %l0, %psr ! **** DISABLE TRAPS ****
nop;
nop;
nop;
/* If a context switch occurred while processing the interrupt then
* %o0 may have change value. If we return any value different
* from the input regs %o1, then the lower level will know that a context
* switch occurred during interrupt processing.
*/
mov %o0, %g6 ! g6 = %o0
cmp %g6, %sp ! Is this a context switch occurred?
be,a simple_return ! No, then skip the window save
nop ! DELAY
/*
* Flush all windows with valid contents except the current one.
* In examining the set register windows, one may logically divide
* the windows into sets (some of which may be empty) based on their
* current status:
*
* + current (i.e. in use),
* + used (i.e. a restore would not trap)
* + invalid (i.e. 1 in corresponding bit in WIM)
* + unused
*
* Either the used or unused set of windows may be empty.
*
* NOTE: We assume only one bit is set in the WIM at a time.
*
* Given a CWP of 5 and a WIM of 0x1, the registers are divided
* into sets as follows:
*
* + 0 - invalid
* + 1-4 - unused
* + 5 - current
* + 6-7 - used
*
* In this case, we only would save the used windows -- 6 and 7.
*
* Traps are disabled for the same logical period as in a
* flush all windows trap handler.
*
* Register Usage while saving the windows:
* g1 = current PSR
* g2 = current wim
* g3 = CWP
* g4 = wim scratch
* g5 = scratch
*/
and %l0, SPARC_PSR_CWP_MASK, %g3 ! g3 = CWP
andn %l0, SPARC_PSR_ET_MASK, %g1 ! g1 = psr with traps disabled
! mov %g1, %psr ! **** DISABLE TRAPS ****
mov %wim, %g2 ! g2 = wim
mov 1, %g4
sll %g4, %g3, %g4 ! g4 = WIM mask for CW invalid
save_frame_loop:
sll %g4, 1, %g5 ! rotate the "wim" left 1
srl %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g4
or %g4, %g5, %g4 ! g4 = wim if we do one restore
/*
* If a restore would not underflow, then continue.
*/
andcc %g4, %g2, %g0 ! Any windows to flush?
bnz done_flushing ! No, then continue
nop
restore ! back one window
/*
* Now save the window just as if we overflowed to it.
*/
std %l0, [%sp + CPU_STACK_FRAME_L0_OFFSET]
std %l2, [%sp + CPU_STACK_FRAME_L2_OFFSET]
std %l4, [%sp + CPU_STACK_FRAME_L4_OFFSET]
std %l6, [%sp + CPU_STACK_FRAME_L6_OFFSET]
std %i0, [%sp + CPU_STACK_FRAME_I0_OFFSET]
std %i2, [%sp + CPU_STACK_FRAME_I2_OFFSET]
std %i4, [%sp + CPU_STACK_FRAME_I4_OFFSET]
std %i6, [%sp + CPU_STACK_FRAME_I6_FP_OFFSET]
ba save_frame_loop
nop
done_flushing:
! Wait three instructions after the write to PSR before using
! non-global registers or instructions affecting the CWP
! g1 = psr with traps disabled
! g3 = CWP (interrupt regs window)
mov %g1, %psr ! restore cwp
add %g3, 1, %g2 ! calculate desired WIM
and %g2, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g2
mov 1, %g4
sll %g4, %g2, %g4 ! g4 = new WIM
mov %g4, %wim
mov %g6, %o0 ! %o0 = sp of context switch to
simple_return:
ldd [%o0 + ISF_I6_FP_OFFSET], %i6 ! restore i6/fp, i7
! sub %fp, CONTEXT_CONTROL_INTERRUPT_FRAME_SIZE, %sp
ld [%o0 + ISF_Y_OFFSET], %l5 ! restore y
wr %l5, 0, %y
ldd [%o0 + ISF_PSR_OFFSET], %l0 ! restore psr, PC
ld [%o0 + ISF_NPC_OFFSET], %l2 ! restore nPC
rd %psr, %l3
and %l3, SPARC_PSR_CWP_MASK, %l3 ! want "current" CWP
andn %l0, SPARC_PSR_CWP_MASK, %l0 ! want rest from task
or %l3, %l0, %l0 ! install it later...
andn %l0, SPARC_PSR_ET_MASK, %l0 ! **** DISABLE TRAPS ****
/*
* Restore tasks global and out registers
*/
ld [%o0 + ISF_G1_OFFSET], %g1 ! restore g1 ! g1 is restored later
ldd [%o0 + ISF_G2_OFFSET], %g2 ! restore g2, g3
ldd [%o0 + ISF_G4_OFFSET], %g4 ! restore g4, g5
ldd [%o0 + ISF_G6_OFFSET], %g6 ! restore g6, g7
ldd [%o0 + ISF_I0_OFFSET], %i0 ! restore i0, i1
ldd [%o0 + ISF_I2_OFFSET], %i2 ! restore i2, i3
ldd [%o0 + ISF_I4_OFFSET], %i4 ! restore i4, i5
ldd [%o0 + ISF_F0_OFFSET] ,%f0
ldd [%o0 + ISF_F2_OFFSET] ,%f2
ldd [%o0 + ISF_F4_OFFSET] ,%f4
ldd [%o0 + ISF_F6_OFFSET] ,%f6
ldd [%o0 + ISF_F8_OFFSET] ,%f8
ldd [%o0 + ISF_F10_OFFSET],%f10
ldd [%o0 + ISF_F12_OFFSET],%f12
ldd [%o0 + ISF_F14_OFFSET],%f14
ldd [%o0 + ISF_F16_OFFSET],%f16
ldd [%o0 + ISF_F18_OFFSET],%f18
ldd [%o0 + ISF_F20_OFFSET],%f20
ldd [%o0 + ISF_F22_OFFSET],%f22
ldd [%o0 + ISF_F24_OFFSET],%f24
ldd [%o0 + ISF_F26_OFFSET],%f26
ldd [%o0 + ISF_F28_OFFSET],%f28
ldd [%o0 + ISF_F30_OFFSET],%f30
ld [%o0 + ISF_FSR_OFFSET],%fsr
nop
nop
nop
/*
* Registers:
*
* ALL global registers EXCEPT G1 and the input registers have
* already been restored and thuse off limits.
*
* The following is the contents of the local registers:
*
* %l0 = original psr
* %l1 = return address (i.e. PC)
* %l2 = nPC
* %l3 = %tbr
*/
/*
* if (CWP + 1) is an invalid window then we need to reload it.
*
* WARNING: Traps should now be disabled
*/
mov %l0, %psr ! **** DISABLE TRAPS ****
nop
nop
nop
rd %wim, %l4
add %l0, 1, %l6 ! l6 = cwp + 1
and %l6, SPARC_PSR_CWP_MASK, %l6 ! do the modulo on it
srl %l4, %l6, %l5 ! l5 = win >> cwp + 1 ; shift count
! and CWP are conveniently LS 5 bits
cmp %l5, 1 ! Is tasks window invalid?
bne good_task_window
/*
* The following code is the same as a 1 position left rotate of WIM.
*/
sll %l4, 1, %l5 ! l5 = WIM << 1
srl %l4, SPARC_NUMBER_OF_REGISTER_WINDOWS-1 , %l4
! l4 = WIM >> (Number Windows - 1)
or %l4, %l5, %l4 ! l4 = (WIM << 1) |
! (WIM >> (Number Windows - 1))
/*
* Now restore the window just as if we underflowed to it.
*/
wr %l4, 0, %wim ! WIM = new WIM
nop ! must delay after writing WIM
nop
nop
restore ! now into the tasks window
ldd [%sp + CPU_STACK_FRAME_L0_OFFSET], %l0
ldd [%sp + CPU_STACK_FRAME_L2_OFFSET], %l2
ldd [%sp + CPU_STACK_FRAME_L4_OFFSET], %l4
ldd [%sp + CPU_STACK_FRAME_L6_OFFSET], %l6
ldd [%sp + CPU_STACK_FRAME_I0_OFFSET], %i0
ldd [%sp + CPU_STACK_FRAME_I2_OFFSET], %i2
ldd [%sp + CPU_STACK_FRAME_I4_OFFSET], %i4
ldd [%sp + CPU_STACK_FRAME_I6_FP_OFFSET],%i6
! reload of sp clobbers ISF
save ! Back to ISR dispatch window
good_task_window:
mov %l0, %psr ! **** DISABLE TRAPS ****
nop;
nop;
nop
! and restore condition codes.
jmp %l1 ! transfer control and
rett %l2 ! go back to tasks window
nop
/* isr end */
/* trap handler end*/
.end
File diff suppressed because it is too large Load Diff
+116
View File
@@ -0,0 +1,116 @@
/****************************************************************************
* arch/sparc/src/s698pm/s698pm_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_SPARC_SRC_S698PM_S698PM_IRQ_H
#define __ARCH_SPARC_SRC_S698PM_S698PM_IRQ_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <arch/irq.h>
#ifndef __ASSEMBLY__
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* CPU interrupt types. */
#define S698PM_CPUINT_LEVEL 0
#define S698PM_CPUINT_EDGE 1
/****************************************************************************
* Public Functions Prototypes
****************************************************************************/
/****************************************************************************
* Name: s698pm_cpuint_initialize
*
* Description:
* Initialize CPU interrupts
*
* Input Parameters:
* None
*
* Returned Value:
* Zero (OK) is returned on success; A negated errno value is returned on
* any failure.
*
****************************************************************************/
int s698pm_cpuint_initialize(void);
/****************************************************************************
* Name: s698pm_setup_irq
*
* Description:
* This function sets up the IRQ. It allocates a CPU interrupt of the given
* priority andattaches it to the given irq.
*
* Input Parameters:
* cpu - The CPU to receive the interrupt 0~3
* irq - The irq number from irq.h to be assigned to a EXT interrupt.
* priority - Interrupt's priority (0~1).
*
* Returned Value:
* The allocated CPU interrupt on success, a negated errno value on
* failure.
*
****************************************************************************/
int s698pm_setup_irq(int cpu, int irq, int priority);
/****************************************************************************
* Name: s698pm_teardown_irq
*
* Description:
* This function undoes the operations done by s698pm_setup_irq.
* It detaches a ext interrupt from a CPU irq.
*
* Input Parameters:
* irq - The irq number from irq.h to be assigned to a EXT interrupt.
*
* Returned Value:
* None
*
****************************************************************************/
void s698pm_teardown_irq(int irq);
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_SPARC_SRC_S698PM_S698PM_IRQ_H */
File diff suppressed because it is too large Load Diff
+154
View File
@@ -0,0 +1,154 @@
/****************************************************************************
* arch/sparc/src/s698pm/s698pm_tim.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_SPARC_SRC_S698PM_S698PM_TIM_H
#define __ARCH_SPARC_SRC_S698PM_S698PM_TIM_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include "chip.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define S698PM_TIM1_BASE 0x80000310
#define S698PM_TIM2_BASE 0x80000320
#define S698PM_TIM3_BASE 0x80000330
#define S698PM_TIM4_BASE 0x80000340
#define S698PM_TIMPRE_BASE 0x80000300
#define S698PM_TIM_CR_OFFSET 0x0008 /* Control register 1 (16-bit) */
#define S698PM_TIM_CNT_OFFSET 0x0000 /* Counter (16-bit) */
#define S698PM_TIM_ARR_OFFSET 0x0004 /* Auto-reload register (16-bit) */
#define S698PM_TIM_PSCLOAD_OFFSET 0x0004 /* Prescaler load (16-bit) */
#define S698PM_TIM_PSCCONT_OFFSET 0x0000 /* Prescaler count (16-bit) */
#define TIMER_LOADCOUNT 0x4
#define TIMER_RELOADCOUNT 0x2
#define TIMER_ENABLE 0x1
/* Helpers ******************************************************************/
#define S698PM_TIM_SETMODE(d,mode) ((d)->ops->setmode(d,mode))
#define S698PM_TIM_SETCLOCK(d,freq) ((d)->ops->setclock(d,freq))
#define S698PM_TIM_GETCLOCK(d) ((d)->ops->getclock(d))
#define S698PM_TIM_SETPERIOD(d,period) ((d)->ops->setperiod(d,period))
#define S698PM_TIM_GETPERIOD(d) ((d)->ops->getperiod(d))
#define S698PM_TIM_GETCOUNTER(d) ((d)->ops->getcounter(d))
#define S698PM_TIM_SETISR(d,hnd,arg,s) ((d)->ops->setisr(d,hnd,arg,s))
#define S698PM_TIM_CLRINT(d,s) ((d)->ops->clrint(d,s))
#define S698PM_TIM_CHECKINT(d,s) ((d)->ops->checkint(d,s))
/****************************************************************************
* Public Types
****************************************************************************/
#ifndef __ASSEMBLY__
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/* TIM Device Structure */
struct s698pm_tim_dev_s
{
struct s698pm_tim_ops_s *ops;
};
enum s698pm_tim_mode_e
{
S698PM_TIM_MODE_UNUSED = -1,
/* One of the following */
S698PM_TIM_MODE_MASK = 0x3,
S698PM_TIM_MODE_DISABLED = 0x1,
S698PM_TIM_MODE_DOWN = 0x2,
};
/* TIM Operations */
struct s698pm_tim_ops_s
{
/* Basic Timers */
int (*setmode)(struct s698pm_tim_dev_s *dev,
enum s698pm_tim_mode_e mode);
int (*setclock)(struct s698pm_tim_dev_s *dev, uint32_t freq);
uint32_t (*getclock)(struct s698pm_tim_dev_s *dev);
void (*setperiod)(struct s698pm_tim_dev_s *dev, uint32_t period);
uint32_t (*getperiod)(struct s698pm_tim_dev_s *dev);
uint32_t (*getcounter)(struct s698pm_tim_dev_s *dev);
/* Timer interrupts */
int (*setisr)(struct s698pm_tim_dev_s *dev,
xcpt_t handler, void *arg, int source);
void (*clrint)(struct s698pm_tim_dev_s *dev, int source);
int (*checkint)(struct s698pm_tim_dev_s *dev, int source);
};
/* Power-up timer and get its structure */
struct s698pm_tim_dev_s *s698pm_tim_init(int timer);
/* Power-down timer, mark it as unused */
int s698pm_tim_deinit(struct s698pm_tim_dev_s *dev);
/****************************************************************************
* Name: s698pm_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 number.
*
* Returned Value:
* Zero (OK) is returned on success; A negated errno value is returned
* to indicate the nature of any failure.
*
****************************************************************************/
#ifdef CONFIG_TIMER
int s698pm_timer_initialize(const char *devpath, int timer);
#endif
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_SPARC_SRC_S698PM_S698PM_TIM_H */
@@ -0,0 +1,488 @@
/****************************************************************************
* arch/sparc/src/s698pm/s698pm_tim_lowerhalf.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 <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <nuttx/irq.h>
#include <nuttx/timers/timer.h>
#include <arch/board/board.h>
#include "s698pm_tim.h"
#if defined(CONFIG_TIMER) && \
(defined(CONFIG_S698PM_TIM1) || defined(CONFIG_S698PM_TIM2)) || \
defined(CONFIG_S698PM_TIM3) || defined(CONFIG_S698PM_TIM4))
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define S698PM_TIM1_RES 32
#define S698PM_TIM2_RES 32
#define S698PM_TIM3_RES 32
#define S698PM_TIM4_RES 32
/****************************************************************************
* 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 s698pm_lowerhalf_s
{
const struct timer_ops_s *ops; /* Lower half operations */
struct s698pm_tim_dev_s *tim; /* stm32 timer driver */
tccb_t callback; /* Current upper half interrupt
* callback */
void *arg; /* Argument passed to upper half
* callback */
bool started; /* True: Timer has been started */
const uint8_t resolution; /* Number of bits in the timer
* (16 or 32 bits) */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* Interrupt handling *******************************************************/
static int s698pm_timer_handler(int irq, void *context, void *arg);
/* "Lower half" driver methods **********************************************/
static int s698pm_start(struct timer_lowerhalf_s *lower);
static int s698pm_stop(struct timer_lowerhalf_s *lower);
static int s698pm_getstatus(struct timer_lowerhalf_s *lower,
struct timer_status_s *status);
static int s698pm_settimeout(struct timer_lowerhalf_s *lower,
uint32_t timeout);
static void s698pm_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 = s698pm_start,
.stop = s698pm_stop,
.getstatus = s698pm_getstatus,
.settimeout = s698pm_settimeout,
.setcallback = s698pm_setcallback,
.ioctl = NULL,
};
#ifdef CONFIG_S698PM_TIM1
static struct s698pm_lowerhalf_s g_tim1_lowerhalf =
{
.ops = &g_timer_ops,
.resolution = S698PM_TIM1_RES,
};
#endif
#ifdef CONFIG_S698PM_TIM2
static struct s698pm_lowerhalf_s g_tim2_lowerhalf =
{
.ops = &g_timer_ops,
.resolution = S698PM_TIM2_RES,
};
#endif
#ifdef CONFIG_S698PM_TIM3
static struct s698pm_lowerhalf_s g_tim3_lowerhalf =
{
.ops = &g_timer_ops,
.resolution = S698PM_TIM3_RES,
};
#endif
#ifdef CONFIG_S698PM_TIM4
static struct s698pm_lowerhalf_s g_tim4_lowerhalf =
{
.ops = &g_timer_ops,
.resolution = S698PM_TIM4_RES,
};
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: s698pm_timer_handler
*
* Description:
* timer interrupt handler
*
* Input Parameters:
*
* Returned Value:
*
****************************************************************************/
static int s698pm_timer_handler(int irq, void *context, void *arg)
{
struct s698pm_lowerhalf_s *lower = (struct s698pm_lowerhalf_s *)arg;
uint32_t next_interval_us = 0;
S698PM_TIM_ACKINT(lower->tim, 0);
if (lower->callback(&next_interval_us, lower->arg))
{
if (next_interval_us > 0)
{
S698PM_TIM_SETPERIOD(lower->tim, next_interval_us);
}
}
else
{
s698pm_stop((struct timer_lowerhalf_s *)lower);
}
return OK;
}
/****************************************************************************
* Name: s698pm_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 s698pm_start(struct timer_lowerhalf_s *lower)
{
struct s698pm_lowerhalf_s *priv = (struct s698pm_lowerhalf_s *)lower;
if (!priv->started)
{
S698PM_TIM_SETMODE(priv->tim, S698PM_TIM_MODE_DOWN);
if (priv->callback != NULL)
{
S698PM_TIM_SETISR(priv->tim, s698pm_timer_handler, priv, 0);
}
priv->started = true;
return OK;
}
/* Return EBUSY to indicate that the timer was already running */
return -EBUSY;
}
/****************************************************************************
* Name: s698pm_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 s698pm_stop(struct timer_lowerhalf_s *lower)
{
struct s698pm_lowerhalf_s *priv = (struct s698pm_lowerhalf_s *)lower;
if (priv->started)
{
S698PM_TIM_SETMODE(priv->tim, S698PM_TIM_MODE_DISABLED);
S698PM_TIM_SETISR(priv->tim, NULL, NULL, 0);
priv->started = false;
return OK;
}
/* Return ENODEV to indicate that the timer was not running */
return -ENODEV;
}
/****************************************************************************
* Name: s698pm_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 s698pm_getstatus(struct timer_lowerhalf_s *lower,
struct timer_status_s *status)
{
struct s698pm_lowerhalf_s *priv = (struct s698pm_lowerhalf_s *)lower;
uint64_t maxtimeout;
uint32_t timeout;
uint32_t clock;
uint32_t period;
uint32_t clock_factor;
DEBUGASSERT(priv);
/* Return the status bit */
status->flags = 0;
if (priv->started)
{
status->flags |= TCFLAGS_ACTIVE;
}
if (priv->callback)
{
status->flags |= TCFLAGS_HANDLER;
}
/* Get timeout */
maxtimeout = (1 << priv->resolution) - 1;
clock = S698PM_TIM_GETCLOCK(priv->tim);
period = S698PM_TIM_GETPERIOD(priv->tim);
if (clock == 1000000)
{
timeout = period;
}
else
{
timeout = (maxtimeout * 1000000) / clock;
}
status->timeout = timeout;
/* Get the time remaining until the timer expires (in microseconds) */
clock_factor = (clock == 1000000) ? 1 : (clock / 1000000);
status->timeleft = (timeout - S698PM_TIM_GETCOUNTER(priv->tim)) *
clock_factor;
return OK;
}
/****************************************************************************
* Name: s698pm_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 s698pm_settimeout(struct timer_lowerhalf_s *lower,
uint32_t timeout)
{
struct s698pm_lowerhalf_s *priv = (struct s698pm_lowerhalf_s *)lower;
uint64_t maxtimeout;
if (priv->started)
{
return -EPERM;
}
maxtimeout = (1 << priv->resolution) - 1;
if (timeout > maxtimeout)
{
uint64_t freq = (maxtimeout * 1000000) / timeout;
S698PM_TIM_SETCLOCK(priv->tim, freq);
S698PM_TIM_SETPERIOD(priv->tim, maxtimeout);
}
else
{
S698PM_TIM_SETCLOCK(priv->tim, 1000000);
S698PM_TIM_SETPERIOD(priv->tim, timeout);
}
return OK;
}
/****************************************************************************
* Name: s698pm_sethandler
*
* Description:
* Call this user provided timeout handler.
*
* 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 s698pm_setcallback(struct timer_lowerhalf_s *lower,
tccb_t callback, void *arg)
{
struct s698pm_lowerhalf_s *priv = (struct s698pm_lowerhalf_s *)lower;
irqstate_t flags = enter_critical_section();
/* Save the new callback */
priv->callback = callback;
priv->arg = arg;
if (callback != NULL && priv->started)
{
S698PM_TIM_SETISR(priv->tim, s698pm_timer_handler, priv, 0);
}
else
{
S698PM_TIM_SETISR(priv->tim, NULL, NULL, 0);
}
leave_critical_section(flags);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: s698pm_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 s698pm_timer_initialize(const char *devpath, int timer)
{
struct s698pm_lowerhalf_s *lower;
switch (timer)
{
#ifdef CONFIG_S698PM_TIM1
case 1:
lower = &g_tim1_lowerhalf;
break;
#endif
#ifdef CONFIG_S698PM_TIM2
case 2:
lower = &g_tim2_lowerhalf;
break;
#endif
#ifdef CONFIG_S698PM_TIM3
case 3:
lower = &g_tim3_lowerhalf;
break;
#endif
#ifdef CONFIG_S698PM_TIM4
case 4:
lower = &g_tim4_lowerhalf;
break;
#endif
default:
return -ENODEV;
}
/* Initialize the elements of lower half state structure */
lower->started = false;
lower->callback = NULL;
lower->tim = s698pm_tim_init(timer);
if (lower->tim == NULL)
{
return -EINVAL;
}
/* 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).
*/
return -EEXIST;
}
return OK;
}
#endif /* CONFIG_TIMER */
+1 -1
View File
@@ -71,7 +71,7 @@ void up_initial_state(struct tcb_s *tcb)
if (tcb->pid == IDLE_PROCESS_ID) if (tcb->pid == IDLE_PROCESS_ID)
{ {
tcb->stack_alloc_ptr = (void *)(g_idle_topstack - tcb->stack_alloc_ptr = (void *)(g_idle_topstack -
(CONFIG_SMP_NCPUS * CONFIG_IDLETHREAD_STACKSIZE)); (CONFIG_SMP_NCPUS * CONFIG_IDLETHREAD_STACKSIZE));
tcb->stack_base_ptr = tcb->stack_alloc_ptr; tcb->stack_base_ptr = tcb->stack_alloc_ptr;
tcb->adj_stack_size = CONFIG_IDLETHREAD_STACKSIZE; tcb->adj_stack_size = CONFIG_IDLETHREAD_STACKSIZE;
@@ -251,7 +251,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
* been delivered. * been delivered.
*/ */
tcb->xcp.sigdeliver = (FAR void *)sigdeliver; tcb->xcp.sigdeliver = (void *)sigdeliver;
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
tcb->xcp.saved_npc = tcb->xcp.regs[REG_NPC]; tcb->xcp.saved_npc = tcb->xcp.regs[REG_NPC];
tcb->xcp.saved_status = tcb->xcp.regs[REG_PSR]; tcb->xcp.saved_status = tcb->xcp.regs[REG_PSR];
@@ -274,7 +274,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
* trampoline after the signal(s) have been delivered. * trampoline after the signal(s) have been delivered.
*/ */
tcb->xcp.sigdeliver = (FAR void *)sigdeliver; tcb->xcp.sigdeliver = (void *)sigdeliver;
tcb->xcp.saved_pc = CURRENT_REGS[REG_PC]; tcb->xcp.saved_pc = CURRENT_REGS[REG_PC];
tcb->xcp.saved_npc = CURRENT_REGS[REG_NPC]; tcb->xcp.saved_npc = CURRENT_REGS[REG_NPC];
tcb->xcp.saved_status = CURRENT_REGS[REG_PSR]; tcb->xcp.saved_status = CURRENT_REGS[REG_PSR];
@@ -330,7 +330,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
* trampoline after the signal(s) have been delivered. * trampoline after the signal(s) have been delivered.
*/ */
tcb->xcp.sigdeliver = (FAR void *)sigdeliver; tcb->xcp.sigdeliver = (void *)sigdeliver;
tcb->xcp.saved_pc = CURRENT_REGS[REG_PC]; tcb->xcp.saved_pc = CURRENT_REGS[REG_PC];
tcb->xcp.saved_npc = CURRENT_REGS[REG_NPC]; tcb->xcp.saved_npc = CURRENT_REGS[REG_NPC];
tcb->xcp.saved_status = CURRENT_REGS[REG_PSR]; tcb->xcp.saved_status = CURRENT_REGS[REG_PSR];