Merged in alinjerpelea/nuttx (pull request #902)
arch: arm: cxd56xx: PM and PWM * configs: spresense: add SPI configuration add SPI configuration for spresense board Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com> * arch: arm: cxd56xx: add support for PWM add support for PWM for cxd56xx Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com> * configs: spresense: enable PWM support enable PWM support on spresense board Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com> * arch: arm: cxd56xx: add Power Management PROCFS support the powermanager procfs support will export /proc/pm: clock power Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com> * configs: spresense: enable powermanager procfs support The powermanager procfs is disabled by default and need to be enabled by the CONFIG_CXD56_PM_PROCFS option Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com> * arch: arm: cxd56xx: add timer driver Add timer driver for cxd56xx. NOTE The timer allows a divider of 1, 16 and 256 options Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com> * arch: arm: cxd56xx: add Watch Dog Timer Add Watch Dog Timer on cxd56xx Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com> * configs: spresense: enable timer the platform support has been added and now we can use the timers on spresense board. Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com> * configs: spresense: enable WatchDog timer The platform support has been added and now we can use the WatchDog Timer on spresense board. Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com> Approved-by: Gregory Nutt <gnutt@nuttx.org>
This commit is contained in:
parent
ae2506619f
commit
92892a8dd7
69
arch/arm/include/cxd56xx/timer.h
Normal file
69
arch/arm/include/cxd56xx/timer.h
Normal file
@ -0,0 +1,69 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/include/cxd56xx/timer.h
|
||||
*
|
||||
* Copyright 2018 Sony Semiconductor Solutions Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of Sony Semiconductor Solutions Corporation nor
|
||||
* the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
/**
|
||||
* @file timer.h
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ARM_INCLUDE_CXD56XX_TIMER_H
|
||||
#define __ARCH_ARM_INCLUDE_CXD56XX_TIMER_H
|
||||
|
||||
#include <nuttx/timers/timer.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* Set callback handler
|
||||
*
|
||||
* @param A pointer to struct timer_sethandler_s
|
||||
* @return ioctl return value provides success/failure indication
|
||||
*/
|
||||
|
||||
#define TCIOC_SETHANDLER _TCIOC(0x0020)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This is the type of the argument passed to the TCIOC_SETHANDLER ioctl */
|
||||
|
||||
struct timer_sethandler_s
|
||||
{
|
||||
FAR void *arg; /* An argument */
|
||||
CODE tccb_t handler; /* The timer interrupt handler */
|
||||
};
|
||||
|
||||
#endif /* __ARCH_ARM_INCLUDE_CXD56XX_TIMER_H */
|
@ -61,7 +61,6 @@ config CXD56_FARAPI_VERSION_CHECK
|
||||
|
||||
if CXD56_FARAPI_VERSION_CHECK
|
||||
|
||||
|
||||
config CXD56_FARAPI_VERSION_FAILED_PANIC
|
||||
bool "Far API Version Check Failed to PANIC"
|
||||
default n
|
||||
@ -76,6 +75,8 @@ endmenu # Far API Configuration
|
||||
|
||||
comment "Timer Options"
|
||||
|
||||
menu "Timer Options"
|
||||
|
||||
menuconfig CXD56_RTC
|
||||
bool "Real Time Clock (RTC)"
|
||||
default y
|
||||
@ -94,6 +95,74 @@ config CXD56_RTC_LATEINIT
|
||||
|
||||
endif # CXD56_RTC
|
||||
|
||||
menuconfig CXD56_TIMER
|
||||
bool "Timer"
|
||||
default y
|
||||
select TIMER
|
||||
|
||||
if CXD56_TIMER
|
||||
|
||||
choice
|
||||
prompt "Timer divider selection"
|
||||
default CXD56_TIMER_DIVIDER_1
|
||||
---help---
|
||||
Timer divider selects 1, 16 or 256. The smaller the divider, the higher
|
||||
time resolution, but the shorter the maximum time until wrap-around.
|
||||
|
||||
config CXD56_TIMER_DIVIDER_1
|
||||
bool "Divider 1"
|
||||
|
||||
config CXD56_TIMER_DIVIDER_16
|
||||
bool "Divider 16"
|
||||
|
||||
config CXD56_TIMER_DIVIDER_256
|
||||
bool "Divider 256"
|
||||
|
||||
endchoice
|
||||
endif # CXD56_TIMER
|
||||
|
||||
menuconfig CXD56_WDT
|
||||
bool "Watchdog Timer (WDT)"
|
||||
default y
|
||||
select WATCHDOG
|
||||
|
||||
if CXD56_WDT
|
||||
|
||||
config CXD56_WDT_INTERRUPT
|
||||
bool "Interrupt on timeout"
|
||||
default y
|
||||
---help---
|
||||
This watchdog timer run 2 laps as long as the counter is not reloaded.
|
||||
In the first lap, the watchdog interrupt occurs. Without interrupt
|
||||
clear, The reset signal is asserted in the second timeout. This setting
|
||||
enables the first interrupt.
|
||||
|
||||
config CXD56_WDT_REGDEBUG
|
||||
bool "Register level debug"
|
||||
default n
|
||||
---help---
|
||||
Enable low-level register debug output
|
||||
|
||||
endif # CXD56_WDT
|
||||
|
||||
endmenu
|
||||
|
||||
comment "Power Management Options"
|
||||
|
||||
menuconfig CXD56_PM
|
||||
bool "Power Management"
|
||||
default y
|
||||
|
||||
if CXD56_PM
|
||||
|
||||
config CXD56_PM_PROCFS
|
||||
bool "Power Management PROCFS support"
|
||||
default n
|
||||
---help---
|
||||
Enable the power domain status or the clock frequency monitor.
|
||||
|
||||
endif # CXD56_PM
|
||||
|
||||
comment "Peripheral Support"
|
||||
|
||||
menu "Peripheral Support"
|
||||
@ -297,6 +366,37 @@ config CXD56_USBDEV
|
||||
default n
|
||||
---help---
|
||||
Enables USB
|
||||
|
||||
config CXD56_PWM
|
||||
bool "PWM"
|
||||
|
||||
if CXD56_PWM
|
||||
|
||||
config CXD56_PWM0
|
||||
bool "PWM0"
|
||||
default n
|
||||
---help---
|
||||
Enable PWM channel 0
|
||||
|
||||
config CXD56_PWM1
|
||||
bool "PWM1"
|
||||
default n
|
||||
---help---
|
||||
Enable PWM channel 1
|
||||
|
||||
config CXD56_PWM2
|
||||
bool "PWM2"
|
||||
default n
|
||||
---help---
|
||||
Enable PWM channel 2
|
||||
|
||||
config CXD56_PWM3
|
||||
bool "PWM3"
|
||||
default n
|
||||
---help---
|
||||
Enable PWM channel 3
|
||||
|
||||
endif # CXD56_PWM
|
||||
endmenu
|
||||
|
||||
comment "Storage Options"
|
||||
|
@ -99,6 +99,10 @@ CHIP_CSRCS += cxd56_powermgr.c
|
||||
CHIP_CSRCS += cxd56_farapi.c
|
||||
CHIP_CSRCS += cxd56_sysctl.c
|
||||
|
||||
ifeq ($(CONFIG_CXD56_PM_PROCFS),y)
|
||||
CHIP_CSRCS += cxd56_powermgr_procfs.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CXD56_RTC),y)
|
||||
CHIP_CSRCS += cxd56_rtc.c
|
||||
ifeq ($(CONFIG_RTC_DRIVER),y)
|
||||
@ -129,3 +133,15 @@ endif
|
||||
ifeq ($(CONFIG_CXD56_DMAC),y)
|
||||
CHIP_CSRCS += cxd56_dmac.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CXD56_PWM),y)
|
||||
CHIP_CSRCS += cxd56_pwm.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CXD56_TIMER),y)
|
||||
CHIP_CSRCS += cxd56_timer.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CXD56_WDT),y)
|
||||
CHIP_CSRCS += cxd56_wdt.c
|
||||
endif
|
||||
|
794
arch/arm/src/cxd56xx/cxd56_powermgr_procfs.c
Normal file
794
arch/arm/src/cxd56xx/cxd56_powermgr_procfs.c
Normal file
@ -0,0 +1,794 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/cxd56xx/cxd56_powermgr_procfs.c
|
||||
*
|
||||
* Copyright 2018 Sony Semiconductor Solutions Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of Sony Semiconductor Solutions Corporation nor
|
||||
* the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/fs/procfs.h>
|
||||
#include <nuttx/fs/dirent.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "cxd56_clock.h"
|
||||
#include "cxd56_powermgr.h"
|
||||
#include "up_arch.h"
|
||||
#include "hardware/cxd56_crg.h"
|
||||
#include "hardware/cxd5602_topreg.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_CXD56_PM_DEBUG
|
||||
# define pmerr(format, ...) _err(format, ##__VA_ARGS__)
|
||||
# define pmwarn(format, ...) _warn(format, ##__VA_ARGS__)
|
||||
# define pminfo(format, ...) _info(format, ##__VA_ARGS__)
|
||||
#else
|
||||
# define pmerr(x...)
|
||||
# define pmwarn(x...)
|
||||
# define pminfo(x...)
|
||||
#endif
|
||||
|
||||
#define PWD_STAT(val, shift) ((val >> shift) & 0x1)
|
||||
#define DSP_NUM (6)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct cxd56_powermgr_procfs_file_s
|
||||
{
|
||||
struct procfs_file_s base; /* Base open file structure */
|
||||
int fileno;
|
||||
int readcnt;
|
||||
};
|
||||
|
||||
struct cxd56_powermgr_procfs_dir_s
|
||||
{
|
||||
struct procfs_dir_priv_s base; /* Base directory private data */
|
||||
int index;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_powermgr_procfs_open(FAR struct file *filep,
|
||||
FAR const char *relpath, int oflags, mode_t mode);
|
||||
static int cxd56_powermgr_procfs_close(FAR struct file *filep);
|
||||
static ssize_t cxd56_powermgr_procfs_read(FAR struct file *filep,
|
||||
FAR char *buffer, size_t buflen);
|
||||
static int cxd56_powermgr_procfs_dup(FAR const struct file *oldp,
|
||||
FAR struct file *newp);
|
||||
static int cxd56_powermgr_procfs_opendir(FAR const char *relpath,
|
||||
FAR struct fs_dirent_s *dir);
|
||||
static int cxd56_powermgr_procfs_closedir(FAR struct fs_dirent_s *dir);
|
||||
static int cxd56_powermgr_procfs_readdir(struct fs_dirent_s *dir);
|
||||
static int cxd56_powermgr_procfs_rewinddir(struct fs_dirent_s *dir);
|
||||
static int cxd56_powermgr_procfs_stat(FAR const char *relpath,
|
||||
FAR struct stat *buf);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
const struct procfs_operations cxd56_powermgr_procfs_operations =
|
||||
{
|
||||
cxd56_powermgr_procfs_open, /* open */
|
||||
cxd56_powermgr_procfs_close, /* close */
|
||||
cxd56_powermgr_procfs_read, /* read */
|
||||
NULL, /* write */
|
||||
cxd56_powermgr_procfs_dup, /* dup */
|
||||
cxd56_powermgr_procfs_opendir, /* opendir */
|
||||
cxd56_powermgr_procfs_closedir, /* closedir */
|
||||
cxd56_powermgr_procfs_readdir, /* readdir */
|
||||
cxd56_powermgr_procfs_rewinddir, /* rewinddir */
|
||||
cxd56_powermgr_procfs_stat /* stat */
|
||||
};
|
||||
|
||||
static const struct procfs_entry_s g_powermgr_procfs1 =
|
||||
{"pm**", &cxd56_powermgr_procfs_operations};
|
||||
static const struct procfs_entry_s g_powermgr_procfs2 =
|
||||
{"pm/" , &cxd56_powermgr_procfs_operations};
|
||||
static FAR char *g_powermg_procfs_buffer;
|
||||
static size_t g_powermg_procfs_size;
|
||||
static size_t g_powermg_procfs_len;
|
||||
|
||||
static const char* g_powermg_procfs_clock_source_name[]
|
||||
= {"RCOSC", "SYSPLL", "XOSC", "RTC"};
|
||||
static const char* g_powermg_procfs_power_state[]
|
||||
= {"-", "o"};
|
||||
static const char* g_powermg_procfs_dir[]
|
||||
= {"clock", "power"};
|
||||
/****************************************************************************
|
||||
* Private Function
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_powermgr_procfs_step_buffer
|
||||
*
|
||||
* Description:
|
||||
* step buffer position
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void cxd56_powermgr_procfs_step_buffer(size_t len)
|
||||
{
|
||||
DEBUGASSERT(g_powermg_procfs_size > (g_powermg_procfs_len + len));
|
||||
g_powermg_procfs_len = g_powermg_procfs_len + len;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_powermgr_procfs_clock_base
|
||||
*
|
||||
* Description:
|
||||
* collect clock base value
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void cxd56_powermgr_procfs_clock_base(void)
|
||||
{
|
||||
uint32_t sys_clk_sel;
|
||||
uint32_t app_clk_sel;
|
||||
size_t len;
|
||||
|
||||
/* Collect clock base value */
|
||||
|
||||
sys_clk_sel = getreg32(CXD56_TOPREG_CKSEL_ROOT) >> 22 & 0x3;
|
||||
app_clk_sel = getreg32(CXD56_TOPREG_APP_CKSEL) >> 8 & 0x3;
|
||||
|
||||
/* Store data in buffer */
|
||||
|
||||
len = snprintf(g_powermg_procfs_buffer + g_powermg_procfs_len,
|
||||
g_powermg_procfs_size - g_powermg_procfs_len,
|
||||
"Clock Source\n"
|
||||
" SYS:%s\n"
|
||||
" APP:%s\n\n",
|
||||
g_powermg_procfs_clock_source_name[sys_clk_sel],
|
||||
g_powermg_procfs_clock_source_name[app_clk_sel]);
|
||||
|
||||
/* Step buffer position */
|
||||
|
||||
cxd56_powermgr_procfs_step_buffer(len);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_powermgr_procfs_clock
|
||||
*
|
||||
* Description:
|
||||
* collect clock value
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void cxd56_powermgr_procfs_clock(void)
|
||||
{
|
||||
size_t len;
|
||||
uint32_t scu;
|
||||
uint32_t hpadc;
|
||||
uint32_t lpadc;
|
||||
uint32_t gps;
|
||||
uint32_t gpsahb;
|
||||
uint32_t val;
|
||||
uint32_t emmc;
|
||||
int dsp;
|
||||
uint32_t dsptabl[DSP_NUM];
|
||||
|
||||
/* collect clock value
|
||||
* and store data in buffer
|
||||
*/
|
||||
|
||||
/* Check SCU clock status */
|
||||
|
||||
scu = cxd56_get_scu_baseclock();
|
||||
hpadc = cxd56_get_hpadc_baseclock();
|
||||
lpadc = cxd56_get_lpadc_baseclock();
|
||||
val = getreg32(CXD56_TOPREG_SYSIOP_CKEN);
|
||||
if ((val & CKEN_BRG_SCU) != CKEN_BRG_SCU)
|
||||
{
|
||||
scu = 0;
|
||||
hpadc = 0;
|
||||
lpadc = 0;
|
||||
}
|
||||
|
||||
/* Check GPS clock status */
|
||||
|
||||
gps = cxd56_get_gps_cpu_baseclock();
|
||||
gpsahb = cxd56_get_gps_ahb_baseclock();
|
||||
val = getreg32(CXD56_TOPREG_GNSDSP_CKEN);
|
||||
if (((val & GNSDSP_CKEN_P1) != GNSDSP_CKEN_P1)
|
||||
&& ((val & GNSDSP_CKEN_COP) != GNSDSP_CKEN_COP))
|
||||
{
|
||||
gps = 0;
|
||||
gpsahb = 0;
|
||||
}
|
||||
|
||||
/* Check DSP clock status */
|
||||
|
||||
val = getreg32(CXD56_CRG_CK_GATE_AHB);
|
||||
val = (val >> 16) & 0x3f;
|
||||
for (dsp = 0; dsp < DSP_NUM; dsp++)
|
||||
{
|
||||
if ((val & (1 << dsp)) == (1 << dsp))
|
||||
{
|
||||
dsptabl[dsp] = cxd56_get_cpu_baseclk();
|
||||
}
|
||||
else
|
||||
{
|
||||
dsptabl[dsp] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
val = getreg32(CXD56_CRG_CKEN_EMMC);
|
||||
val = val & 0x7;
|
||||
if (val == 0x7)
|
||||
{
|
||||
emmc = cxd56_get_cpu_baseclk();
|
||||
}
|
||||
else
|
||||
{
|
||||
emmc = 0;
|
||||
}
|
||||
|
||||
len = snprintf(g_powermg_procfs_buffer + g_powermg_procfs_len,
|
||||
g_powermg_procfs_size - g_powermg_procfs_len,
|
||||
"Clock Status [Hz]\n"
|
||||
" |-RTC : %9d"" |-APP : %9d\n"
|
||||
" |-RCOSC : %9d"" ||-DSP0 : %9d\n"
|
||||
" |-XOSC : %9d"" ||-DSP1 : %9d\n"
|
||||
" |-SYSPLL : %9d"" ||-DSP2 : %9d\n"
|
||||
" |-M0P : %9d"" ||-DSP3 : %9d\n"
|
||||
" ||-AHB : %9d"" ||-DSP4 : %9d\n"
|
||||
" | |-APB : %9d"" ||-DSP5 : %9d\n"
|
||||
" |-UART1 : %9d"" ||-UART2 : %9d\n"
|
||||
" |-SFC : %9d"" ||-SPI4 : %9d\n"
|
||||
" |-SCU : %9d"" ||-SPI5 : %9d\n"
|
||||
" ||-LPADC : %9d"" ||-USB : %9d\n"
|
||||
" ||-HPADC : %9d"" ||-EMMC : %9d\n"
|
||||
" |-I2C4 : %9d"" ||-SDIO : %9d\n"
|
||||
" |-GPS : %9d"" ||-VSYNC : %9d\n"
|
||||
" ||-AHB : %9d\n",
|
||||
cxd56_get_rtc_clock(), cxd56_get_appsmp_baseclock(),
|
||||
cxd56_get_rcosc_clock(), dsptabl[0],
|
||||
cxd56_get_xosc_clock(), dsptabl[1],
|
||||
cxd56_get_syspll_clock(), dsptabl[2],
|
||||
cxd56_get_sys_baseclock(), dsptabl[3],
|
||||
cxd56_get_sys_ahb_baseclock(), dsptabl[4],
|
||||
cxd56_get_sys_apb_baseclock(), dsptabl[5],
|
||||
cxd56_get_com_baseclock(), cxd56_get_img_uart_baseclock(),
|
||||
cxd56_get_sys_sfc_baseclock(), cxd56_get_img_spi_baseclock(),
|
||||
scu, cxd56_get_img_wspi_baseclock(),
|
||||
lpadc, cxd56_get_usb_baseclock(),
|
||||
hpadc, emmc,
|
||||
cxd56_get_pmui2c_baseclock(), cxd56_get_sdio_baseclock(),
|
||||
gps, cxd56_get_img_vsync_baseclock(),
|
||||
gpsahb);
|
||||
|
||||
/* Step buffer position */
|
||||
|
||||
cxd56_powermgr_procfs_step_buffer(len);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_powermgr_procfs_power_state
|
||||
*
|
||||
* Description:
|
||||
* collect clock power state
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void cxd56_powermgr_procfs_power_state(void)
|
||||
{
|
||||
uint32_t reg_pwd_stat;
|
||||
uint32_t reg_ana_pw_stat;
|
||||
uint32_t rf;
|
||||
size_t len;
|
||||
|
||||
/* Collect power status */
|
||||
|
||||
reg_pwd_stat = getreg32(CXD56_TOPREG_PWD_STAT);
|
||||
reg_ana_pw_stat = getreg32(CXD56_TOPREG_ANA_PW_STAT);
|
||||
|
||||
/* Check RF_xxx power status */
|
||||
|
||||
rf = reg_ana_pw_stat & 0x3f0;
|
||||
if (rf != 0)
|
||||
{
|
||||
rf = 1;
|
||||
}
|
||||
|
||||
/* Store data in buffer */
|
||||
|
||||
len = snprintf(g_powermg_procfs_buffer + g_powermg_procfs_len,
|
||||
g_powermg_procfs_size - g_powermg_procfs_len,
|
||||
"Power Status\n"
|
||||
"|-RCOSC : %s\n"
|
||||
"|-XOSC : %s\n"
|
||||
"|-SYSPLL : %s\n"
|
||||
"|-SCU : %s\n"
|
||||
"||-LPADC : %s\n"
|
||||
"||-HPADC : %s\n"
|
||||
"|-CORE : %s\n"
|
||||
"||-GNSS_ITP : %s\n"
|
||||
"||-SYSIOP : %s\n"
|
||||
"| |-SYSIOP_SUB : %s\n"
|
||||
"| |-GNSS : %s\n"
|
||||
"| ||-RF : %s\n"
|
||||
"| |-APP : %s\n"
|
||||
"| ||-APP_DSP : %s\n"
|
||||
"| ||-APP_SUB : %s\n"
|
||||
"| ||-APP_AUD : %s\n",
|
||||
g_powermg_procfs_power_state[PWD_STAT(reg_ana_pw_stat, 0)],
|
||||
g_powermg_procfs_power_state[PWD_STAT(reg_ana_pw_stat, 1)],
|
||||
g_powermg_procfs_power_state[PWD_STAT(reg_ana_pw_stat, 2)],
|
||||
g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 0)],
|
||||
g_powermg_procfs_power_state[PWD_STAT(reg_ana_pw_stat, 13)],
|
||||
g_powermg_procfs_power_state[PWD_STAT(reg_ana_pw_stat, 12)],
|
||||
g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 4)],
|
||||
g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 12)],
|
||||
g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 5)],
|
||||
g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 6)],
|
||||
g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 13)],
|
||||
g_powermg_procfs_power_state[rf],
|
||||
g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 8)],
|
||||
g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 9)],
|
||||
g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 10)],
|
||||
g_powermg_procfs_power_state[PWD_STAT(reg_pwd_stat, 14)]);
|
||||
|
||||
/* step buffer position */
|
||||
|
||||
cxd56_powermgr_procfs_step_buffer(len);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_powermgr_procfs_check_path
|
||||
*
|
||||
* Description:
|
||||
* Check path power manager procfs
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_powermgr_procfs_check_dir(char *relpath,
|
||||
mode_t *mode, int *level, int *fileno)
|
||||
{
|
||||
char *temp;
|
||||
int ret = OK;
|
||||
|
||||
*level = 0;
|
||||
*mode = S_IFDIR;
|
||||
*fileno = 0;
|
||||
temp = strtok(relpath, "/");
|
||||
if (strncmp (temp, "pm", 3) == 0)
|
||||
{
|
||||
while ((temp = strtok (NULL, "/")) != NULL)
|
||||
{
|
||||
*level = *level + 1;
|
||||
if (*level == 1)
|
||||
{
|
||||
if (strncmp(temp, g_powermg_procfs_dir[0],
|
||||
strlen(g_powermg_procfs_dir[0])+1) == 0)
|
||||
{
|
||||
*mode = S_IFREG;
|
||||
*fileno = 1;
|
||||
}
|
||||
else if (strncmp(temp, g_powermg_procfs_dir[1],
|
||||
strlen(g_powermg_procfs_dir[1])+1) == 0)
|
||||
{
|
||||
*mode = S_IFREG;
|
||||
*fileno = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -ENOENT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -ENOENT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -ENOENT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_powermgr_procfs_open
|
||||
*
|
||||
* Description:
|
||||
* Request Open power manager procfs
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_powermgr_procfs_open(FAR struct file *filep,
|
||||
FAR const char *relpath, int oflags, mode_t mode)
|
||||
{
|
||||
FAR struct cxd56_powermgr_procfs_file_s *priv;
|
||||
int ret;
|
||||
mode_t getmode;
|
||||
int level;
|
||||
int fileno;
|
||||
char temp[16];
|
||||
|
||||
pminfo("Open '%s'\n", relpath);
|
||||
|
||||
/* PROCFS is read-only. Any attempt to open with any kind of write
|
||||
* access is not permitted.
|
||||
*
|
||||
* REVISIT: Write-able proc files could be quite useful.
|
||||
*/
|
||||
|
||||
if (((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0))
|
||||
{
|
||||
pmerr("ERROR: Only O_RDONLY supported\n");
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
memset(temp, 0, sizeof(temp));
|
||||
snprintf(temp, sizeof(temp)-1, "%s", relpath);
|
||||
ret = cxd56_powermgr_procfs_check_dir(temp, &getmode, &level, &fileno);
|
||||
|
||||
if (ret != OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Allocate the open file structure */
|
||||
|
||||
priv = (FAR struct cxd56_powermgr_procfs_file_s *)
|
||||
kmm_zalloc(sizeof(struct cxd56_powermgr_procfs_file_s));
|
||||
if (!priv)
|
||||
{
|
||||
pmerr("ERROR: Failed to allocate file attributes\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->fileno = fileno;
|
||||
priv->readcnt = 0;
|
||||
filep->f_priv = (void *)priv;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_powermgr_procfs_close
|
||||
*
|
||||
* Description:
|
||||
* Request Close power manager procfs
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_powermgr_procfs_close(FAR struct file *filep)
|
||||
{
|
||||
pminfo("Close\n");
|
||||
|
||||
DEBUGASSERT(filep->f_priv);
|
||||
kmm_free(filep->f_priv);
|
||||
filep->f_priv = NULL;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_powermgr_procfs_read
|
||||
*
|
||||
* Description:
|
||||
* Request Read power manager procfs
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t cxd56_powermgr_procfs_read(FAR struct file *filep,
|
||||
FAR char *buffer, size_t buflen)
|
||||
{
|
||||
size_t len;
|
||||
FAR struct cxd56_powermgr_procfs_file_s *priv;
|
||||
|
||||
pminfo("READ buffer=%p buflen=%lu len=%lu\n", buffer,
|
||||
(unsigned long)buflen, g_powermg_procfs_len);
|
||||
|
||||
DEBUGASSERT(filep && filep->f_priv);
|
||||
|
||||
priv = (FAR struct cxd56_powermgr_procfs_file_s *)filep->f_priv;
|
||||
|
||||
if (priv->fileno == 0)
|
||||
{
|
||||
/* pm directory */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (priv->readcnt == 0)
|
||||
{
|
||||
/* Collect data and store data in buffer */
|
||||
|
||||
g_powermg_procfs_buffer = buffer;
|
||||
g_powermg_procfs_size = buflen;
|
||||
g_powermg_procfs_len = 0;
|
||||
|
||||
if (priv->fileno == 1)
|
||||
{
|
||||
cxd56_powermgr_procfs_clock_base();
|
||||
cxd56_powermgr_procfs_clock();
|
||||
}
|
||||
else
|
||||
{
|
||||
cxd56_powermgr_procfs_power_state();
|
||||
}
|
||||
|
||||
len = g_powermg_procfs_len;
|
||||
priv->readcnt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Indicate already provided all data */
|
||||
|
||||
len = 0;
|
||||
priv->readcnt = 0;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_powermgr_procfs_dup
|
||||
*
|
||||
* Description:
|
||||
* Request Dup power manager procfs
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_powermgr_procfs_dup(FAR const struct file *oldp,
|
||||
FAR struct file *newp)
|
||||
{
|
||||
void *oldpriv;
|
||||
void *newpriv;
|
||||
|
||||
pminfo("Dup %p->%p\n", oldp, newp);
|
||||
|
||||
/* Recover our private data from the old struct file instance */
|
||||
|
||||
oldpriv = oldp->f_priv;
|
||||
DEBUGASSERT(oldpriv);
|
||||
|
||||
/* Allocate a new container to hold the task and attribute selection */
|
||||
|
||||
newpriv = kmm_malloc(sizeof(struct cxd56_powermgr_procfs_file_s));
|
||||
if (!newpriv)
|
||||
{
|
||||
pmerr("ERROR: Failed to allocate file attributes\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* The copy the file attributes from the old attributes to the new */
|
||||
|
||||
memcpy(newpriv, oldpriv, sizeof(struct cxd56_powermgr_procfs_file_s));
|
||||
|
||||
/* Save the new attributes in the new file structure */
|
||||
|
||||
newp->f_priv = newpriv;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_powermgr_procfs_stat
|
||||
*
|
||||
* Description:
|
||||
* Request Stat power manager procfs
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_powermgr_procfs_stat(FAR const char *relpath,
|
||||
FAR struct stat *buf)
|
||||
{
|
||||
int ret;
|
||||
mode_t mode;
|
||||
int level;
|
||||
int fileno;
|
||||
char temp[16];
|
||||
|
||||
memset(temp, 0, sizeof(temp));
|
||||
snprintf(temp, sizeof(temp)-1, "%s", relpath);
|
||||
ret = cxd56_powermgr_procfs_check_dir(temp, &mode, &level, &fileno);
|
||||
|
||||
pminfo("Stat %s %d %d %d\n", relpath, mode, level, ret);
|
||||
|
||||
buf->st_mode = mode | S_IROTH | S_IRGRP | S_IRUSR;
|
||||
buf->st_size = 0;
|
||||
buf->st_blksize = 0;
|
||||
buf->st_blocks = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_powermgr_procfs_opendir
|
||||
*
|
||||
* Description:
|
||||
* Request Opendir power manager procfs
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_powermgr_procfs_opendir(FAR const char *relpath,
|
||||
FAR struct fs_dirent_s *dir)
|
||||
{
|
||||
FAR struct cxd56_powermgr_procfs_dir_s *procfs;
|
||||
int ret;
|
||||
mode_t mode;
|
||||
int level;
|
||||
int fileno;
|
||||
char temp[16];
|
||||
|
||||
memset(temp, 0, sizeof(temp));
|
||||
snprintf(temp, sizeof(temp)-1, "%s", relpath);
|
||||
ret = cxd56_powermgr_procfs_check_dir(temp, &mode, &level, &fileno);
|
||||
|
||||
pminfo("Opendir '%s' %d %d\n", relpath, ret, level);
|
||||
|
||||
if (ret != OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
if (level > 0)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
procfs = (FAR struct cxd56_powermgr_procfs_dir_s *)
|
||||
kmm_malloc(sizeof(struct cxd56_powermgr_procfs_dir_s));
|
||||
if (!procfs)
|
||||
{
|
||||
pmerr("ERROR: Failed to allocate dir attributes\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
procfs->index = 0;
|
||||
dir->u.procfs = (FAR void *)procfs;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_powermgr_procfs_closedir
|
||||
*
|
||||
* Description:
|
||||
* Request Closedir power manager procfs
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_powermgr_procfs_closedir(FAR struct fs_dirent_s *dir)
|
||||
{
|
||||
FAR struct smartfs_level1_s *priv;
|
||||
|
||||
pminfo("Closedir\n");
|
||||
|
||||
DEBUGASSERT(dir && dir->u.procfs);
|
||||
priv = dir->u.procfs;
|
||||
|
||||
if (priv)
|
||||
{
|
||||
kmm_free(priv);
|
||||
}
|
||||
|
||||
dir->u.procfs = NULL;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_powermgr_procfs_readdir
|
||||
*
|
||||
* Description:
|
||||
* Request Readdir power manager procfs
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_powermgr_procfs_readdir(struct fs_dirent_s *dir)
|
||||
{
|
||||
FAR struct cxd56_powermgr_procfs_dir_s *procfs;
|
||||
|
||||
DEBUGASSERT(dir && dir->u.procfs);
|
||||
|
||||
procfs = (FAR struct cxd56_powermgr_procfs_dir_s *)dir->u.procfs;
|
||||
|
||||
pminfo("Readdir %d\n", procfs->index);
|
||||
|
||||
if (procfs->index > ((sizeof(g_powermg_procfs_dir)
|
||||
/ sizeof(g_powermg_procfs_dir[0])) - 1))
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
dir->fd_dir.d_type = DTYPE_FILE;
|
||||
strncpy(dir->fd_dir.d_name, g_powermg_procfs_dir[procfs->index],
|
||||
strlen(g_powermg_procfs_dir[procfs->index])+1);
|
||||
procfs->index++;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_powermgr_procfs_rewinddir
|
||||
*
|
||||
* Description:
|
||||
* Request Rewind power manager procfs
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_powermgr_procfs_rewinddir(struct fs_dirent_s *dir)
|
||||
{
|
||||
FAR struct cxd56_powermgr_procfs_dir_s *procfs;
|
||||
|
||||
DEBUGASSERT(dir && dir->u.procfs);
|
||||
|
||||
procfs = (FAR struct cxd56_powermgr_procfs_dir_s *)dir->u.procfs;
|
||||
pminfo("Rewind %d\n", procfs->index);
|
||||
procfs->index = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_pm_initialize_procfs
|
||||
*
|
||||
* Description:
|
||||
* Initialize power manager procfs
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int cxd56_pm_initialize_procfs(void)
|
||||
{
|
||||
int ret;
|
||||
ret = procfs_register(&g_powermgr_procfs1);
|
||||
if (ret < 0)
|
||||
return -EPERM;
|
||||
ret = procfs_register(&g_powermgr_procfs2);
|
||||
if (ret < 0)
|
||||
return -EPERM;
|
||||
return ret;
|
||||
}
|
88
arch/arm/src/cxd56xx/cxd56_powermgr_procfs.h
Normal file
88
arch/arm/src/cxd56xx/cxd56_powermgr_procfs.h
Normal file
@ -0,0 +1,88 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/cxd56xx/cxd56_timerisr.h
|
||||
*
|
||||
* Copyright 2018 Sony Semiconductor Solutions Corporation
|
||||
*
|
||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_POWERMGR_PROCFS_H
|
||||
#define __ARCH_ARM_SRC_CXD56XX_CXD56_POWERMGR_PROCFS_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_pm_initialize_procfs
|
||||
*
|
||||
* Description:
|
||||
* Initialize power manager procfs
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int cxd56_pm_initialize_procfs(void);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_POWERMGR_PROCFS_H */
|
495
arch/arm/src/cxd56xx/cxd56_pwm.c
Normal file
495
arch/arm/src/cxd56xx/cxd56_pwm.c
Normal file
@ -0,0 +1,495 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/cxd56xx/cxd56_pwm.c
|
||||
*
|
||||
* Copyright 2018 Sony Semiconductor Solutions Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of Sony Semiconductor Solutions Corporation nor
|
||||
* the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/drivers/pwm.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "chip.h"
|
||||
#include "up_arch.h"
|
||||
|
||||
#include "cxd56_pinconfig.h"
|
||||
#include "cxd56_clock.h"
|
||||
#include "cxd56_pwm.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define PWM_REG_BASE (0x04195600)
|
||||
#define PWM_PHASE_REG_BASE (0x04195630)
|
||||
|
||||
#define PWM_REG(ch) \
|
||||
( \
|
||||
(PWM_REG_t*)(PWM_REG_BASE + (sizeof(PWM_REG_t) * (ch))) \
|
||||
)
|
||||
|
||||
#define PWM_PHASE_REG(ch) \
|
||||
( \
|
||||
(PWM_PHASE_REG_t*) \
|
||||
(PWM_PHASE_REG_BASE + (sizeof(PWM_PHASE_REG_t) * (ch))) \
|
||||
)
|
||||
|
||||
#define PWM_PARAM_OFFPERIOD_SHIFT (16)
|
||||
|
||||
#ifndef itemsof
|
||||
# define itemsof(array) (sizeof(array)/sizeof(array[0]))
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This structure represents the state of one PWM channel */
|
||||
|
||||
struct cxd56_pwm_chan_s
|
||||
{
|
||||
const struct pwm_ops_s *ops; /* PWM operations */
|
||||
uint8_t ch; /* PWM channel: {0..3} */
|
||||
uint8_t prescale; /* prescale (reserved) */
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t PARAM;
|
||||
volatile uint32_t EN;
|
||||
volatile uint32_t UPDATE;
|
||||
} PWM_REG_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t PHASE;
|
||||
} PWM_PHASE_REG_t;
|
||||
|
||||
/****************************************************************************
|
||||
* Static Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* PWM driver methods */
|
||||
|
||||
static int pwm_setup(FAR struct pwm_lowerhalf_s *dev);
|
||||
static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev);
|
||||
static int pwm_start(FAR struct pwm_lowerhalf_s *dev,
|
||||
FAR const struct pwm_info_s *info);
|
||||
static int pwm_stop(FAR struct pwm_lowerhalf_s *dev);
|
||||
static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev,
|
||||
int cmd, unsigned long arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* This is the list of lower half PWM driver methods used by the upper half
|
||||
* driver
|
||||
*/
|
||||
|
||||
static const struct pwm_ops_s g_pwmops =
|
||||
{
|
||||
.setup = pwm_setup,
|
||||
.shutdown = pwm_shutdown,
|
||||
.start = pwm_start,
|
||||
.stop = pwm_stop,
|
||||
.ioctl = pwm_ioctl,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_CXD56_PWM0
|
||||
static struct cxd56_pwm_chan_s g_pwm_ch0 =
|
||||
{
|
||||
.ops = &g_pwmops,
|
||||
.ch = CXD56_PWM_CH0,
|
||||
.prescale = 0,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CXD56_PWM1
|
||||
static struct cxd56_pwm_chan_s g_pwm_ch1 =
|
||||
{
|
||||
.ops = &g_pwmops,
|
||||
.ch = CXD56_PWM_CH1,
|
||||
.prescale = 0,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CXD56_PWM2
|
||||
static struct cxd56_pwm_chan_s g_pwm_ch2 =
|
||||
{
|
||||
.ops = &g_pwmops,
|
||||
.ch = CXD56_PWM_CH2,
|
||||
.prescale = 0,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CXD56_PWM3
|
||||
static struct cxd56_pwm_chan_s g_pwm_ch3 =
|
||||
{
|
||||
.ops = &g_pwmops,
|
||||
.ch = CXD56_PWM_CH3,
|
||||
.prescale = 0,
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pwm_pin_config
|
||||
*
|
||||
* Description:
|
||||
* Configure PWM pin
|
||||
*
|
||||
* Input Parameters:
|
||||
* channel - pwm channel number.
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; A negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int pwm_pin_config(uint32_t channel)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t pingroupa[] = PINCONFS_PWMA;
|
||||
uint32_t pingroupb[] = PINCONFS_PWMB;
|
||||
|
||||
if ((channel == CXD56_PWM_CH0) || (channel == CXD56_PWM_CH1))
|
||||
{
|
||||
ret = cxd56_pin_configs(pingroupa, itemsof(pingroupa));
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cxd56_pin_configs(pingroupb, itemsof(pingroupb));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: convert_freq2period
|
||||
*
|
||||
* Description:
|
||||
* Convert frequency and duty to period and offperiod of param register.
|
||||
*
|
||||
* Input Parameters:
|
||||
* freq - pwm frequency [Hz]
|
||||
* duty - duty
|
||||
*
|
||||
* Output Parameters:
|
||||
* param - set value of PWM_PARAM register
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; A negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int convert_freq2period(uint32_t freq, ub16_t duty, uint32_t *param)
|
||||
{
|
||||
DEBUGASSERT(param);
|
||||
|
||||
uint32_t pwmfreq = 0;
|
||||
uint32_t period = 0;
|
||||
uint32_t offperiod = 0;
|
||||
|
||||
/* Get frequency of pwm base clock */
|
||||
|
||||
pwmfreq = cxd56_get_pwm_baseclock();
|
||||
if (pwmfreq == 0)
|
||||
{
|
||||
pwmerr("Unknown pwm frequency\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* check frequency range */
|
||||
|
||||
if ((freq > ((pwmfreq + 1) >> 1)) || (freq < (pwmfreq >> 16)))
|
||||
{
|
||||
pwmerr("Frequency out of range. %d [Effective range:%d - %d]\n",
|
||||
freq, pwmfreq >> 16, (pwmfreq + 1) >> 1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* check duty range */
|
||||
|
||||
if ((duty < 0x00000001) || (duty > 0x0000ffff))
|
||||
{
|
||||
pwmerr("Duty out of range. %d\n", duty);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* calcurate period and offperiod */
|
||||
|
||||
period = (pwmfreq * 10 / freq - 5) / 10;
|
||||
if (period > 0xffff)
|
||||
{
|
||||
period = 0xffff;
|
||||
}
|
||||
offperiod = ((0x10000 - duty) * (period + 1) + 0x8000) >> 16;
|
||||
if (offperiod == 0)
|
||||
{
|
||||
offperiod = 0;
|
||||
}
|
||||
else if (period < offperiod)
|
||||
{
|
||||
offperiod = period;
|
||||
}
|
||||
*param = (period & 0xffff) |
|
||||
((offperiod & 0xffff) << PWM_PARAM_OFFPERIOD_SHIFT);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pwm_setup
|
||||
*
|
||||
* Description:
|
||||
* This method is called when the driver is opened. The lower half driver
|
||||
* should configure and initialize the device so that it is ready for use.
|
||||
* It should not, however, output pulses until the start method is called.
|
||||
*
|
||||
* Input parameters:
|
||||
* dev - A reference to the lower half PWM driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; A negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int pwm_setup(FAR struct pwm_lowerhalf_s *dev)
|
||||
{
|
||||
FAR struct cxd56_pwm_chan_s *priv = (FAR struct cxd56_pwm_chan_s *)dev;
|
||||
int ret;
|
||||
|
||||
ret = pwm_pin_config(priv->ch);
|
||||
if (ret < 0)
|
||||
{
|
||||
pwmerr("Failed to pinconf():%d\n", channel);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pwm_shutdown
|
||||
*
|
||||
* Description:
|
||||
* This method is called when the driver is closed. The lower half driver
|
||||
* stop pulsed output, free any resources, disable the timer hardware, and
|
||||
* put the system into the lowest possible power usage state
|
||||
*
|
||||
* Input parameters:
|
||||
* dev - A reference to the lower half PWM driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; A negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pwm_start
|
||||
*
|
||||
* Description:
|
||||
* (Re-)initialize the timer resources and start the pulsed output
|
||||
*
|
||||
* Input parameters:
|
||||
* dev - A reference to the lower half PWM driver state structure
|
||||
* info - A reference to the characteristics of the pulsed output
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; A negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int pwm_start(FAR struct pwm_lowerhalf_s *dev,
|
||||
FAR const struct pwm_info_s *info)
|
||||
{
|
||||
FAR struct cxd56_pwm_chan_s *priv = (FAR struct cxd56_pwm_chan_s *)dev;
|
||||
uint32_t param;
|
||||
int ret;
|
||||
|
||||
if (info->duty <= 0)
|
||||
{
|
||||
/* Output low level if duty cycle is almost 0% */
|
||||
|
||||
PWM_REG(priv->ch)->EN = 0x0;
|
||||
}
|
||||
else if (info->duty >= 65536)
|
||||
{
|
||||
/* Output high level if duty cycle is almost 100% */
|
||||
|
||||
PWM_REG(priv->ch)->PARAM = 1;
|
||||
PWM_REG(priv->ch)->EN = 0x1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = convert_freq2period(info->frequency, info->duty, ¶m);
|
||||
if (ret < 0)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (PWM_REG(priv->ch)->EN & 1)
|
||||
{
|
||||
/* Change duty cycle dynamically if already running */
|
||||
|
||||
PWM_REG(priv->ch)->PARAM = param;
|
||||
return OK;
|
||||
}
|
||||
|
||||
PWM_REG(priv->ch)->EN = 0x0;
|
||||
PWM_REG(priv->ch)->PARAM = param;
|
||||
|
||||
/* Since prescale is not supported, always set to a fixed value '0' */
|
||||
|
||||
PWM_PHASE_REG(priv->ch)->PHASE = 0x0;
|
||||
|
||||
PWM_REG(priv->ch)->EN = 0x1;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pwm_stop
|
||||
*
|
||||
* Description:
|
||||
* Stop the pulsed output and reset the timer resources
|
||||
*
|
||||
* Input parameters:
|
||||
* dev - A reference to the lower half PWM driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; A negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int pwm_stop(FAR struct pwm_lowerhalf_s *dev)
|
||||
{
|
||||
FAR struct cxd56_pwm_chan_s *priv = (FAR struct cxd56_pwm_chan_s *)dev;
|
||||
|
||||
PWM_REG(priv->ch)->EN = 0x0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pwm_ioctl
|
||||
*
|
||||
* Description:
|
||||
* Lower-half logic may support platform-specific ioctl commands
|
||||
*
|
||||
* Input parameters:
|
||||
* dev - A reference to the lower half PWM driver state structure
|
||||
* cmd - The ioctl command
|
||||
* arg - The argument accompanying the ioctl command
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; A negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_pwminitialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize PWM channel for use with the upper_level PWM driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* channel - pwm channel number.
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, a pointer to the CXD56 lower half PWM driver is returned.
|
||||
* NULL is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct pwm_lowerhalf_s *cxd56_pwminitialize(uint32_t channel)
|
||||
{
|
||||
FAR struct cxd56_pwm_chan_s *pwmch;
|
||||
|
||||
switch (channel)
|
||||
{
|
||||
#ifdef CONFIG_CXD56_PWM0
|
||||
case CXD56_PWM_CH0:
|
||||
pwmch = &g_pwm_ch0;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_CXD56_PWM1
|
||||
case CXD56_PWM_CH1:
|
||||
pwmch = &g_pwm_ch1;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_CXD56_PWM2
|
||||
case CXD56_PWM_CH2:
|
||||
pwmch = &g_pwm_ch2;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_CXD56_PWM3
|
||||
case CXD56_PWM_CH3:
|
||||
pwmch = &g_pwm_ch3;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
pwmerr("Illeagal channel number:%d\n", channel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (FAR struct pwm_lowerhalf_s *)pwmch;
|
||||
}
|
103
arch/arm/src/cxd56xx/cxd56_pwm.h
Normal file
103
arch/arm/src/cxd56xx/cxd56_pwm.h
Normal file
@ -0,0 +1,103 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/cxd56xx/cxd56_pwm.h
|
||||
*
|
||||
* Copyright 2018 Sony Semiconductor Solutions Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of Sony Semiconductor Solutions Corporation nor
|
||||
* the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_PWM_H
|
||||
#define __ARCH_ARM_SRC_CXD56XX_CXD56_PWM_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* PWM channel definitions **************************************************/
|
||||
|
||||
#define CXD56_PWM_CH0 0
|
||||
#define CXD56_PWM_CH1 1
|
||||
#define CXD56_PWM_CH2 2
|
||||
#define CXD56_PWM_CH3 3
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_pwminitialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize PWM channel for use with the upper_level PWM driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* channel - pwm channel number.
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, a pointer to the CXD56 lower half PWM driver is returned.
|
||||
* NULL is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct pwm_lowerhalf_s *cxd56_pwminitialize(uint32_t channel);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_PWM_H */
|
583
arch/arm/src/cxd56xx/cxd56_timer.c
Normal file
583
arch/arm/src/cxd56xx/cxd56_timer.c
Normal file
@ -0,0 +1,583 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/cxd56xx/cxd56_timer.c
|
||||
*
|
||||
* Copyright 2018 Sony Semiconductor Solutions Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of Sony Semiconductor Solutions Corporation nor
|
||||
* the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/timers/timer.h>
|
||||
#include <arch/board/board.h>
|
||||
#include <arch/chip/timer.h>
|
||||
|
||||
#include "up_arch.h"
|
||||
#include "cxd56_timer.h"
|
||||
#include "hardware/cxd56_timer.h"
|
||||
#include "cxd56_clock.h"
|
||||
|
||||
#ifdef CONFIG_TIMER
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Timer divider definitions */
|
||||
|
||||
#if defined(CONFIG_CXD56_TIMER_DIVIDER_1)
|
||||
#define TIMER_DIVIDER (1)
|
||||
#define TIMERCTRL_DIV (TIMERCTRL_DIV_1)
|
||||
#elif defined(CONFIG_CXD56_TIMER_DIVIDER_16)
|
||||
#define TIMER_DIVIDER (16)
|
||||
#define TIMERCTRL_DIV (TIMERCTRL_DIV_16)
|
||||
#elif defined(CONFIG_CXD56_TIMER_DIVIDER_256)
|
||||
#define TIMER_DIVIDER (256)
|
||||
#define TIMERCTRL_DIV (TIMERCTRL_DIV_256)
|
||||
#else
|
||||
#define TIMER_DIVIDER (16)
|
||||
#define TIMERCTRL_DIV (TIMERCTRL_DIV_16)
|
||||
#endif
|
||||
|
||||
/* e.g.) When the timer divider is 16, timer's max clock is about 10MHz
|
||||
* (Divide max 160MHz resolution by 16) and the timer has 32bit counter.
|
||||
* Therefore, the max counter is the following value to avoid counter
|
||||
* wrap around. Timer's base clock is dynamically changed with cpu clock.
|
||||
*/
|
||||
|
||||
#define TIMER_MAXTIMEOUT (ULONG_MAX / 160 / TIMER_DIVIDER)
|
||||
|
||||
/****************************************************************************
|
||||
* 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 cxd56_lowerhalf_s
|
||||
{
|
||||
FAR const struct timer_ops_s *ops; /* Lower half operations */
|
||||
|
||||
/* Private data */
|
||||
|
||||
uint32_t base; /* Base address of the timer */
|
||||
tccb_t callback; /* Current user interrupt callback */
|
||||
FAR void *arg; /* Argument passed to upper half callback */
|
||||
uint32_t timeout; /* The current timeout value (us) */
|
||||
uint32_t clkticks; /* actual clock ticks for current interval */
|
||||
bool started; /* The timer has been started */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* Interrupt handling *******************************************************/
|
||||
|
||||
static int cxd56_timer_interrupt(int irq, FAR void *context,
|
||||
FAR void *arg);
|
||||
|
||||
/* "Lower half" driver methods **********************************************/
|
||||
|
||||
static int cxd56_start(FAR struct timer_lowerhalf_s *lower);
|
||||
static int cxd56_stop(FAR struct timer_lowerhalf_s *lower);
|
||||
static int cxd56_getstatus(FAR struct timer_lowerhalf_s *lower,
|
||||
FAR struct timer_status_s *status);
|
||||
static int cxd56_settimeout(FAR struct timer_lowerhalf_s *lower,
|
||||
uint32_t timeout);
|
||||
static void cxd56_setcallback(struct timer_lowerhalf_s *lower,
|
||||
tccb_t callback, FAR void *arg);
|
||||
static int cxd56_ioctl(FAR struct timer_lowerhalf_s *lower, int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* "Lower half" driver methods */
|
||||
|
||||
static const struct timer_ops_s g_tmrops =
|
||||
{
|
||||
.start = cxd56_start,
|
||||
.stop = cxd56_stop,
|
||||
.getstatus = cxd56_getstatus,
|
||||
.settimeout = cxd56_settimeout,
|
||||
.setcallback = cxd56_setcallback,
|
||||
.ioctl = cxd56_ioctl,
|
||||
};
|
||||
|
||||
/* "Lower half" driver state */
|
||||
|
||||
static struct cxd56_lowerhalf_s g_tmrdevs[2];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_timer_interrupt
|
||||
*
|
||||
* Description:
|
||||
* TC interrupt
|
||||
*
|
||||
* Input Parameters:
|
||||
* Usual interrupt callback arguments.
|
||||
*
|
||||
* Returned Values:
|
||||
* Always returns OK.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_timer_interrupt(int irq, FAR void *context, FAR void *arg)
|
||||
{
|
||||
FAR struct cxd56_lowerhalf_s *priv = (FAR struct cxd56_lowerhalf_s *)arg;
|
||||
uint32_t timeout;
|
||||
uint32_t load;
|
||||
|
||||
tmrinfo("Entry\n");
|
||||
DEBUGASSERT((irq >= CXD56_IRQ_TIMER0) && (irq <= CXD56_IRQ_TIMER1));
|
||||
|
||||
/* Is there a registered callback? If the callback has been
|
||||
* nullified, the timer will be stopped.
|
||||
*/
|
||||
|
||||
timeout = priv->timeout;
|
||||
if (priv->callback && priv->callback(&timeout, priv->arg))
|
||||
{
|
||||
if (timeout != priv->timeout)
|
||||
{
|
||||
/* Change period dynamically */
|
||||
|
||||
priv->timeout = timeout;
|
||||
load =
|
||||
(((uint64_t)timeout * priv->clkticks) / TIMER_DIVIDER / 1000000);
|
||||
putreg32(load, priv->base + CXD56_TIMER_LOAD);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No callback or the callback returned false.. stop the timer */
|
||||
|
||||
cxd56_stop((FAR struct timer_lowerhalf_s *)priv);
|
||||
tmrinfo("Stopped\n");
|
||||
}
|
||||
|
||||
/* Clear the interrupts */
|
||||
|
||||
putreg32(TIMER_INTERRUPT, priv->base + CXD56_TIMER_INTCLR);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_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 Values:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_start(FAR struct timer_lowerhalf_s *lower)
|
||||
{
|
||||
FAR struct cxd56_lowerhalf_s *priv = (FAR struct cxd56_lowerhalf_s *)lower;
|
||||
|
||||
tmrinfo("Entry: started %d\n", priv->started);
|
||||
|
||||
/* Has the timer already been started? */
|
||||
|
||||
if (!priv->started)
|
||||
{
|
||||
uint32_t ctrl = (TIMERCTRL_ENABLE | TIMERCTRL_DIV |
|
||||
TIMERCTRL_SIZE_32BIT | TIMERCTRL_MODE_WRAP);
|
||||
|
||||
if (priv->timeout)
|
||||
{
|
||||
ctrl |= (TIMERCTRL_PERIODIC | TIMERCTRL_INTENABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctrl |= (TIMERCTRL_FREERUN | TIMERCTRL_INTDISABLE);
|
||||
}
|
||||
|
||||
/* Start the timer */
|
||||
|
||||
putreg32(ctrl, priv->base + CXD56_TIMER_CONTROL);
|
||||
|
||||
priv->started = true;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Return EBUSY to indicate that the timer was already running */
|
||||
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_stop
|
||||
*
|
||||
* Description:
|
||||
* Stop the timer
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of the "lower-half"
|
||||
* driver state structure.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_stop(FAR struct timer_lowerhalf_s *lower)
|
||||
{
|
||||
FAR struct cxd56_lowerhalf_s *priv = (FAR struct cxd56_lowerhalf_s *)lower;
|
||||
|
||||
tmrinfo("Entry: started %d\n", priv->started);
|
||||
|
||||
/* Has the timer already been started? */
|
||||
|
||||
if (priv->started)
|
||||
{
|
||||
/* Stop the timer */
|
||||
|
||||
putreg32(0, priv->base + CXD56_TIMER_CONTROL);
|
||||
|
||||
/* Clear interrupt just in case */
|
||||
|
||||
putreg32(TIMER_INTERRUPT, priv->base + CXD56_TIMER_INTCLR);
|
||||
|
||||
priv->started = false;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Return ENODEV to indicate that the timer was not running */
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_getstatus
|
||||
*
|
||||
* Description:
|
||||
* Get the current 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 Values:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_getstatus(FAR struct timer_lowerhalf_s *lower,
|
||||
FAR struct timer_status_s *status)
|
||||
{
|
||||
FAR struct cxd56_lowerhalf_s *priv = (FAR struct cxd56_lowerhalf_s *)lower;
|
||||
uint64_t remaining;
|
||||
|
||||
tmrinfo("Entry\n");
|
||||
DEBUGASSERT(priv);
|
||||
|
||||
/* Return the status bit */
|
||||
|
||||
status->flags = 0;
|
||||
if (priv->started)
|
||||
{
|
||||
status->flags |= TCFLAGS_ACTIVE;
|
||||
}
|
||||
|
||||
if (priv->callback)
|
||||
{
|
||||
status->flags |= TCFLAGS_HANDLER;
|
||||
}
|
||||
|
||||
/* Return the actual timeout in microseconds */
|
||||
|
||||
status->timeout = priv->timeout;
|
||||
|
||||
/* Get the time remaining until the timer expires (in microseconds). */
|
||||
|
||||
remaining = (uint64_t)getreg32(priv->base + CXD56_TIMER_VALUE);
|
||||
status->timeleft =
|
||||
(uint32_t)(remaining * 1000000ULL * TIMER_DIVIDER / priv->clkticks);
|
||||
|
||||
tmrinfo(" flags : %08x\n", status->flags);
|
||||
tmrinfo(" timeout : %d\n", status->timeout);
|
||||
tmrinfo(" timeleft : %d\n", status->timeleft);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_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 milliseconds.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_settimeout(FAR struct timer_lowerhalf_s *lower,
|
||||
uint32_t timeout)
|
||||
{
|
||||
FAR struct cxd56_lowerhalf_s *priv = (FAR struct cxd56_lowerhalf_s *)lower;
|
||||
uint32_t load;
|
||||
|
||||
DEBUGASSERT(priv);
|
||||
|
||||
if (priv->started)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
tmrinfo("Entry: timeout=%d\n", timeout);
|
||||
|
||||
/* Can this timeout be represented? */
|
||||
|
||||
if (timeout < 1 || timeout > TIMER_MAXTIMEOUT)
|
||||
{
|
||||
tmrerr("ERROR: Cannot represent timeout=%lu > %lu\n", timeout,
|
||||
TIMER_MAXTIMEOUT);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
/* Intended timeout */
|
||||
|
||||
priv->timeout = timeout;
|
||||
|
||||
/* Actual clock ticks */
|
||||
|
||||
priv->clkticks = cxd56_get_cpu_baseclk();
|
||||
|
||||
load = (((uint64_t)timeout * priv->clkticks) / TIMER_DIVIDER / 1000000);
|
||||
putreg32(load, priv->base + CXD56_TIMER_LOAD);
|
||||
modifyreg32(priv->base + CXD56_TIMER_CONTROL, 0,
|
||||
TIMERCTRL_PERIODIC | TIMERCTRL_INTENABLE);
|
||||
|
||||
tmrinfo("clkticks=%d timeout=%d load=%d\n", priv->clkticks, priv->timeout,
|
||||
load);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_setcallback
|
||||
*
|
||||
* Description:
|
||||
* Call this user provided timeout callback.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of the
|
||||
* "lower-half" driver state structure.
|
||||
* newhandler - The new timer expiration function pointer. If this
|
||||
* function pointer is NULL, then the reset-on-expiration
|
||||
* behavior is restored,
|
||||
*
|
||||
* Returned Values:
|
||||
* The previous timer expiration function pointer or NULL is there was
|
||||
* no previous function pointer.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void cxd56_setcallback(struct timer_lowerhalf_s *lower,
|
||||
tccb_t callback, FAR void *arg)
|
||||
{
|
||||
FAR struct cxd56_lowerhalf_s *priv = (struct cxd56_lowerhalf_s *)lower;
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
DEBUGASSERT(priv);
|
||||
tmrinfo("Entry: callback=%p\n", callback);
|
||||
|
||||
/* Save the new callback and argument */
|
||||
|
||||
priv->callback = callback;
|
||||
priv->arg = arg;
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_ioctl
|
||||
*
|
||||
* Description:
|
||||
* Any ioctl commands that are not recognized by the "upper-half" driver
|
||||
* are forwarded to the lower half driver through this method.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of the "lower-half"
|
||||
* driver state structure.
|
||||
* cmd - The ioctl command value
|
||||
* arg - The optional argument that accompanies the 'cmd'. The
|
||||
* interpretation of this argument depends on the particular
|
||||
* command.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_ioctl(FAR struct timer_lowerhalf_s *lower, int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
int ret = -ENOTTY;
|
||||
|
||||
tmrinfo("Entry: cmd=%d arg=%ld\n", cmd, arg);
|
||||
|
||||
/* Handle ioctl commands */
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
/* cmd: TCIOC_SETHANDLER
|
||||
* Description: Set interrupt callback function
|
||||
* Argument: A pointer to struct timer_sethandler_s
|
||||
*/
|
||||
|
||||
case TCIOC_SETHANDLER:
|
||||
{
|
||||
FAR struct timer_sethandler_s *param;
|
||||
|
||||
/* Set user provided timeout callback function */
|
||||
|
||||
param = (FAR struct timer_sethandler_s *)((uintptr_t)arg);
|
||||
|
||||
if (param != NULL)
|
||||
{
|
||||
cxd56_setcallback(lower, param->handler, param->arg);
|
||||
ret = OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -EINVAL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_timer_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the timer. The timer is initialized and
|
||||
* registers as 'devpath'.
|
||||
*
|
||||
* Input Parameters:
|
||||
* devpath - The full path to the timer. This should be of the form
|
||||
* /dev/timer0
|
||||
* timer - the timer's number.
|
||||
*
|
||||
* Returned Values:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void cxd56_timer_initialize(FAR const char *devpath, int timer)
|
||||
{
|
||||
FAR struct cxd56_lowerhalf_s *priv = &g_tmrdevs[timer];
|
||||
int irq;
|
||||
|
||||
tmrinfo("Entry: devpath=%s\n", devpath);
|
||||
DEBUGASSERT((timer >= CXD56_TIMER0) && (timer <= CXD56_TIMER1));
|
||||
|
||||
/* Initialize the driver state structure. Here we assume: (1) the state
|
||||
* structure lies in .bss and was zeroed at reset time. (2) This function
|
||||
* is only called once so it is never necessary to re-zero the structure.
|
||||
*/
|
||||
|
||||
switch (timer)
|
||||
{
|
||||
case CXD56_TIMER0:
|
||||
priv->base = CXD56_TIMER0_BASE;
|
||||
irq = CXD56_IRQ_TIMER0;
|
||||
tmrinfo("Using: Timer 0");
|
||||
break;
|
||||
|
||||
case CXD56_TIMER1:
|
||||
priv->base = CXD56_TIMER1_BASE;
|
||||
irq = CXD56_IRQ_TIMER1;
|
||||
tmrinfo("Using: Timer 1");
|
||||
break;
|
||||
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
priv->ops = &g_tmrops;
|
||||
|
||||
(void)irq_attach(irq, cxd56_timer_interrupt, priv);
|
||||
|
||||
/* Enable NVIC interrupt. */
|
||||
|
||||
up_enable_irq(irq);
|
||||
|
||||
/* Register the timer driver as /dev/timerX */
|
||||
|
||||
(void)timer_register(devpath, (FAR struct timer_lowerhalf_s *)priv);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_TIMER */
|
99
arch/arm/src/cxd56xx/cxd56_timer.h
Normal file
99
arch/arm/src/cxd56xx/cxd56_timer.h
Normal file
@ -0,0 +1,99 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/cxd56xx/cxd56_timer.h
|
||||
*
|
||||
* Copyright 2018 Sony Semiconductor Solutions Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of Sony Semiconductor Solutions Corporation nor
|
||||
* the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_TIMER_H
|
||||
#define __ARCH_ARM_SRC_CXD56XX_CXD56_TIMER_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#ifdef CONFIG_TIMER
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Channel ******************************************************************/
|
||||
|
||||
#define CXD56_TIMER0 (0)
|
||||
#define CXD56_TIMER1 (1)
|
||||
#define CXD56_TIMER_NUM (2)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_timer_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the timer. The timer is initialized and
|
||||
* registers as 'devpath. The initial state of the timer is
|
||||
* disabled.
|
||||
*
|
||||
* Input Parameters:
|
||||
* devpath - The full path to the timer. This should be of the form
|
||||
* /dev/timer0
|
||||
* timer - the timer's number.
|
||||
*
|
||||
* Returned Values:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void cxd56_timer_initialize(FAR const char *devpath, int timer);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* CONFIG_TIMER */
|
||||
#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_TIMER_H */
|
690
arch/arm/src/cxd56xx/cxd56_wdt.c
Normal file
690
arch/arm/src/cxd56xx/cxd56_wdt.c
Normal file
@ -0,0 +1,690 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/cxd56xx/cxd56_wdt.c
|
||||
*
|
||||
* Copyright 2018 Sony Semiconductor Solutions Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of Sony Semiconductor Solutions Corporation nor
|
||||
* the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
#include <nuttx/debug.h>
|
||||
#endif
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/timers/watchdog.h>
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "up_arch.h"
|
||||
#include "cxd56_clock.h"
|
||||
#include "cxd56_wdt.h"
|
||||
#include "cxd56_powermgr.h"
|
||||
|
||||
#ifdef CONFIG_CXD56_WDT
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Select the path to the registered watchdog timer device */
|
||||
|
||||
#ifdef CONFIG_WATCHDOG_DEVPATH
|
||||
#define DEVPATH CONFIG_WATCHDOG_DEVPATH
|
||||
#else
|
||||
#define DEVPATH "/dev/watchdog0"
|
||||
#endif
|
||||
|
||||
/* watchdog timeout maximum value */
|
||||
|
||||
#define WDT_MAX_TIMEOUT (40000) /* 40 sec */
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
/* This structure provides the private representation of the "lower-half"
|
||||
* driver state structure. This structure must be cast-compatible with the
|
||||
* well-known watchdog_lowerhalf_s structure.
|
||||
*/
|
||||
|
||||
struct cxd56_lowerhalf_s
|
||||
{
|
||||
FAR const struct watchdog_ops_s *ops; /* Lower half operations */
|
||||
#ifdef CONFIG_CXD56_WDT_INTERRUPT
|
||||
xcpt_t handler; /* Current WDT interrupt handler */
|
||||
#endif
|
||||
uint32_t timeout; /* The actual timeout value (milliseconds) */
|
||||
uint32_t reload; /* The 32-bit watchdog reload value */
|
||||
bool started; /* The timer has been started */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* Register operations */
|
||||
|
||||
#if defined(CONFIG_CXD56_WDT_REGDEBUG) && defined(CONFIG_DEBUG_FEATURES)
|
||||
static uint32_t cxd56_getreg(uintptr_t regaddr);
|
||||
static void cxd56_putreg(uint32_t regval, uintptr_t regaddr);
|
||||
#else
|
||||
# define cxd56_getreg(regaddr) getreg32(regaddr)
|
||||
# define cxd56_putreg(regval, regaddr) putreg32(regval, regaddr)
|
||||
#endif
|
||||
|
||||
/* Interrupt hanlding *******************************************************/
|
||||
|
||||
#ifdef CONFIG_CXD56_WDT_INTERRUPT
|
||||
static int cxd56_wdtinterrupt(int irq, FAR void *context, FAR void *arg);
|
||||
#endif
|
||||
|
||||
/* "Lower half" driver methods **********************************************/
|
||||
|
||||
static int cxd56_start(FAR struct watchdog_lowerhalf_s *lower);
|
||||
static int cxd56_stop(FAR struct watchdog_lowerhalf_s *lower);
|
||||
static int cxd56_keepalive(FAR struct watchdog_lowerhalf_s *lower);
|
||||
static int cxd56_getstatus(FAR struct watchdog_lowerhalf_s *lower,
|
||||
FAR struct watchdog_status_s *status);
|
||||
static int cxd56_settimeout(FAR struct watchdog_lowerhalf_s *lower,
|
||||
uint32_t timeout);
|
||||
static xcpt_t cxd56_capture(FAR struct watchdog_lowerhalf_s *lower,
|
||||
xcpt_t handler);
|
||||
static int cxd56_ioctl(FAR struct watchdog_lowerhalf_s *lower, int cmd,
|
||||
unsigned long arg);
|
||||
static int cxd56_pm_event(uint8_t id);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* "Lower half" driver methods */
|
||||
|
||||
static const struct watchdog_ops_s g_wdgops =
|
||||
{
|
||||
.start = cxd56_start,
|
||||
.stop = cxd56_stop,
|
||||
.keepalive = cxd56_keepalive,
|
||||
.getstatus = cxd56_getstatus,
|
||||
.settimeout = cxd56_settimeout,
|
||||
.capture = cxd56_capture,
|
||||
.ioctl = cxd56_ioctl,
|
||||
};
|
||||
|
||||
/* "Lower half" driver state */
|
||||
|
||||
static struct cxd56_lowerhalf_s g_wdtdev;
|
||||
|
||||
/* pm handle */
|
||||
|
||||
static void *pmhandle = NULL;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_getreg
|
||||
*
|
||||
* Description:
|
||||
* Get the contents of an CXD56 register
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
# if defined(CONFIG_CXD56_WDT_REGDEBUG) && defined(CONFIG_DEBUG_FEATURES)
|
||||
static uint32_t cxd56_getreg(uintptr_t regaddr)
|
||||
{
|
||||
static uint32_t prevaddr = 0;
|
||||
static uint32_t count = 0;
|
||||
static uint32_t preval = 0;
|
||||
|
||||
/* Read the value from the register */
|
||||
|
||||
uint32_t regval = getreg32(regaddr);
|
||||
|
||||
/* Is this the same value that we read from the same registe last time? Are
|
||||
* we polling the register? If so, suppress some of the output.
|
||||
*/
|
||||
|
||||
if (regaddr == prevaddr && regval == preval)
|
||||
{
|
||||
if (count == 0xffffffff || ++count > 3)
|
||||
{
|
||||
if (count == 4)
|
||||
{
|
||||
logdebug("...\n");
|
||||
}
|
||||
|
||||
return regval;
|
||||
}
|
||||
}
|
||||
|
||||
/* No this is a new address or value */
|
||||
|
||||
else
|
||||
{
|
||||
/* Did we print "..." for the previous value? */
|
||||
|
||||
if (count > 3)
|
||||
{
|
||||
/* Yes.. then show how many times the value repeated */
|
||||
|
||||
logdebug("[repeats %d more times]\n", count - 3);
|
||||
}
|
||||
|
||||
/* Save the new address, value, and count */
|
||||
|
||||
prevaddr = regaddr;
|
||||
preval = regval;
|
||||
count = 1;
|
||||
}
|
||||
|
||||
/* Show the register value read */
|
||||
|
||||
logdebug("%08x->%08\n", regaddr, regval);
|
||||
return regval;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_putreg
|
||||
*
|
||||
* Description:
|
||||
* Set the contents of an CXD56 register to a value
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_CXD56_WDT_REGDEBUG) && defined(CONFIG_DEBUG_FEATURES)
|
||||
static void cxd56_putreg(uint32_t regval, uintptr_t regaddr)
|
||||
{
|
||||
/* Show the register value being written */
|
||||
|
||||
logdebug("%08x<-%08x\n", regaddr, regval);
|
||||
|
||||
/* Write the value */
|
||||
|
||||
putreg32(regval, regaddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_wdtinterrupt
|
||||
*
|
||||
* Description:
|
||||
* WDT early warning interrupt
|
||||
*
|
||||
* Input Parameters:
|
||||
* Usual interrupt handler arguments.
|
||||
*
|
||||
* Returned Values:
|
||||
* Always returns OK.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_CXD56_WDT_INTERRUPT
|
||||
static int cxd56_wdtinterrupt(int irq, FAR void *context, FAR void *arg)
|
||||
{
|
||||
FAR struct cxd56_lowerhalf_s *priv = arg;
|
||||
|
||||
/* Is there a registered handler? */
|
||||
|
||||
if (priv->handler)
|
||||
{
|
||||
/* Yes... NOTE: This interrupt service routine (ISR) must reload
|
||||
* the WDT counter to prevent the reset. Otherwise, we will reset
|
||||
* upon return.
|
||||
*/
|
||||
|
||||
priv->handler(irq, context, NULL);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_start
|
||||
*
|
||||
* Description:
|
||||
* Start the watchdog timer, resetting the time to the current timeout,
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of the "lower-half"
|
||||
* driver state structure.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_start(FAR struct watchdog_lowerhalf_s *lower)
|
||||
{
|
||||
FAR struct cxd56_lowerhalf_s *priv = (FAR struct cxd56_lowerhalf_s *)lower;
|
||||
|
||||
wdinfo("Entry\n");
|
||||
|
||||
cxd56_putreg(WDOGLOCK_UNLOCK_KEY, CXD56_WDT_WDOGLOCK);
|
||||
cxd56_putreg(WDOGCONTROL_RESEN | WDOGCONTROL_INTEN, CXD56_WDT_WDOGCONTROL);
|
||||
cxd56_putreg(0, CXD56_WDT_WDOGLOCK);
|
||||
|
||||
priv->started = true;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_stop
|
||||
*
|
||||
* Description:
|
||||
* Stop the watchdog timer
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of the "lower-half"
|
||||
* driver state structure.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_stop(FAR struct watchdog_lowerhalf_s *lower)
|
||||
{
|
||||
FAR struct cxd56_lowerhalf_s *priv = (FAR struct cxd56_lowerhalf_s *)lower;
|
||||
|
||||
wdinfo("Entry\n");
|
||||
cxd56_putreg(WDOGLOCK_UNLOCK_KEY, CXD56_WDT_WDOGLOCK);
|
||||
cxd56_putreg(WDOGCONTROL_STOP, CXD56_WDT_WDOGCONTROL);
|
||||
priv->started = false;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_keepalive
|
||||
*
|
||||
* Description:
|
||||
* Reset the watchdog timer to the current timeout value, prevent any
|
||||
* imminent watchdog timeouts. This is sometimes referred as "pinging"
|
||||
* the atchdog timer or "petting the dog".
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of the "lower-half"
|
||||
* driver state structure.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_keepalive(FAR struct watchdog_lowerhalf_s *lower)
|
||||
{
|
||||
wdinfo("Entry\n");
|
||||
cxd56_putreg(WDOGLOCK_UNLOCK_KEY, CXD56_WDT_WDOGLOCK);
|
||||
cxd56_putreg(0, CXD56_WDT_WDOGINTCLR); /* reload by write any value */
|
||||
cxd56_putreg(0, CXD56_WDT_WDOGLOCK);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_getstatus
|
||||
*
|
||||
* Description:
|
||||
* Get the current watchdog timer status
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of the
|
||||
* "lower-half" driver state structure.
|
||||
* stawtus - The location to return the watchdog status information.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_getstatus(FAR struct watchdog_lowerhalf_s *lower,
|
||||
FAR struct watchdog_status_s *status)
|
||||
{
|
||||
FAR struct cxd56_lowerhalf_s *priv = (FAR struct cxd56_lowerhalf_s *)lower;
|
||||
uint64_t remain;
|
||||
|
||||
wdinfo("Entry\n");
|
||||
DEBUGASSERT(priv);
|
||||
|
||||
/* Return the status bit */
|
||||
|
||||
status->flags = WDFLAGS_RESET;
|
||||
if (priv->started)
|
||||
{
|
||||
status->flags |= WDFLAGS_ACTIVE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CXD56_WDT_INTERRUPT
|
||||
if (priv->handler)
|
||||
{
|
||||
status->flags |= WDFLAGS_CAPTURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return the actual timeout is milliseconds */
|
||||
|
||||
status->timeout = priv->timeout;
|
||||
|
||||
/* Get the time remaining until the watchdog expires (in miliseconds) */
|
||||
|
||||
remain = (uint64_t)cxd56_getreg(CXD56_WDT_WDOGVALUE);
|
||||
status->timeleft = (uint32_t)(remain * 1000 / cxd56_get_cpu_baseclk());
|
||||
if (cxd56_getreg(CXD56_WDT_WDOGRIS) != WDOGRIS_RAWINT)
|
||||
{
|
||||
status->timeleft += status->timeout / 2;
|
||||
}
|
||||
|
||||
wdinfo("Status :\n");
|
||||
wdinfo(" flags : %08x\n", status->flags);
|
||||
wdinfo(" timeout : %d\n", status->timeout);
|
||||
wdinfo(" timeleft : %d\n", status->timeleft);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_settimeout
|
||||
*
|
||||
* Description:
|
||||
* Set a new timeout value (and reset the watchdog timer)
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of the
|
||||
* "lower-half" driver state structure.
|
||||
* timeout - The new timeout value in millisecnds.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_settimeout(FAR struct watchdog_lowerhalf_s *lower,
|
||||
uint32_t timeout)
|
||||
{
|
||||
FAR struct cxd56_lowerhalf_s *priv = (FAR struct cxd56_lowerhalf_s *)lower;
|
||||
uint32_t reload;
|
||||
uint32_t freq;
|
||||
uint64_t llreload;
|
||||
|
||||
DEBUGASSERT(priv);
|
||||
wdinfo("Entry: timeout=%d\n", timeout);
|
||||
|
||||
if ((timeout == 0) || (timeout > WDT_MAX_TIMEOUT))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Calculate the reload value to achiee this (appoximate) timeout. */
|
||||
|
||||
freq = cxd56_get_cpu_baseclk();
|
||||
|
||||
if (!freq)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
llreload = ((uint64_t)freq * (uint64_t)timeout + 500) / 1000;
|
||||
|
||||
/* Actual register value is half of timeout value because watchdog makes
|
||||
* two laps until reset signal is asserted. At 1st lap, interrupt signal
|
||||
* is asserted. At 2nd lap, reset signal is asserted.
|
||||
*/
|
||||
|
||||
llreload /= 2;
|
||||
|
||||
if (llreload >> 32)
|
||||
{
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
reload = (uint32_t)llreload;
|
||||
|
||||
/* Calculate and save the actual timeout value in milliseconds */
|
||||
|
||||
priv->timeout = (uint32_t)((llreload * 1000 + freq / 2) / freq) * 2;
|
||||
|
||||
/* Remember the selected values */
|
||||
|
||||
priv->reload = reload;
|
||||
|
||||
wdinfo("reload=%u timout: %d->%d\n", reload, timeout, priv->timeout);
|
||||
|
||||
/* Set the WDT register according to calculated value */
|
||||
|
||||
cxd56_putreg(WDOGLOCK_UNLOCK_KEY, CXD56_WDT_WDOGLOCK);
|
||||
cxd56_putreg(reload, CXD56_WDT_WDOGLOAD);
|
||||
cxd56_putreg(WDOGCONTROL_RESEN | WDOGCONTROL_INTEN, CXD56_WDT_WDOGCONTROL);
|
||||
cxd56_putreg(0, CXD56_WDT_WDOGLOCK);
|
||||
|
||||
priv->started = true;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_capture
|
||||
*
|
||||
* Description:
|
||||
* Don't reset on watchdog timer timeout; instead, call this user provider
|
||||
* timeout handler. NOTE: Providing handler==NULL will restore the reset
|
||||
* behavior.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of the
|
||||
* "lower-half" driver state structure.
|
||||
* newhandler - The new watchdog expiration function pointer. If this
|
||||
* function pointer is NULL, then the reset-on-expiration
|
||||
* behavior is restored,
|
||||
*
|
||||
* Returned Values:
|
||||
* The previous watchdog expiration function pointer or NULL is there was
|
||||
* no previous function pointer, i.e., if the previous behavior was
|
||||
* reset-on-expiration (NULL is also returned if an error occurs).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static xcpt_t cxd56_capture(FAR struct watchdog_lowerhalf_s *lower,
|
||||
xcpt_t handler)
|
||||
{
|
||||
#ifndef CONFIG_CXD56_WDT_INTERRUPT
|
||||
wderr("ERROR: Not configured for this mode\n");
|
||||
return NULL;
|
||||
#else
|
||||
FAR struct cxd56_lowerhalf_s *priv = (FAR struct cxd56_lowerhalf_s *)lower;
|
||||
irqstate_t flags;
|
||||
xcpt_t oldhandler;
|
||||
|
||||
DEBUGASSERT(priv);
|
||||
wdinfo("Entry: handler=%p\n", handler);
|
||||
|
||||
/* Get the old handler return value */
|
||||
|
||||
flags = enter_critical_section();
|
||||
oldhandler = priv->handler;
|
||||
|
||||
/* Save the new handler */
|
||||
|
||||
priv->handler = handler;
|
||||
|
||||
/* Are we attaching or detaching the handler? */
|
||||
|
||||
if (handler)
|
||||
{
|
||||
/* Attaching... Enable the WDT interrupt */
|
||||
|
||||
up_enable_irq(CXD56_IRQ_WDT_INT);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Detaching... Disable the WDT interrupt */
|
||||
|
||||
up_disable_irq(CXD56_IRQ_WDT_INT);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
return oldhandler;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_ioctl
|
||||
*
|
||||
* Description:
|
||||
* Any ioctl commands that are not recognized by the "upper-half" driver
|
||||
* are forwarded to the lower half driver through this method.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of the "lower-half"
|
||||
* driver state structure.
|
||||
* cmd - The ioctol command value
|
||||
* arg - The optional argument that accompanies the 'cmd'. The
|
||||
* interpretation of this argument depends on the particular
|
||||
* command.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_ioctl(FAR struct watchdog_lowerhalf_s *lower, int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
wdinfo("cmd=%d arg=%ld\n", cmd, arg);
|
||||
|
||||
/* No ioctls are supported */
|
||||
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_pm_event
|
||||
*
|
||||
* Description:
|
||||
* A callback function to receive events from power manager
|
||||
*
|
||||
* Input Parameters:
|
||||
* id - A event identifier from power manager
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cxd56_pm_event(uint8_t id)
|
||||
{
|
||||
FAR struct cxd56_lowerhalf_s *priv = &g_wdtdev;
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case CXD56_PM_CALLBACK_ID_CLK_CHG_START:
|
||||
case CXD56_PM_CALLBACK_ID_HOT_SLEEP:
|
||||
|
||||
/* do nothing, but watchdog is automatically stopped in hot sleep */
|
||||
|
||||
break;
|
||||
|
||||
case CXD56_PM_CALLBACK_ID_CLK_CHG_END:
|
||||
case CXD56_PM_CALLBACK_ID_HOT_BOOT:
|
||||
/* If watchdog has been already running before the clock is changed or
|
||||
* entering in hot sleep , re-start the watchdog timer with a timeout
|
||||
* value based on the new watchdog timer clock.
|
||||
*/
|
||||
|
||||
if (priv->started)
|
||||
{
|
||||
cxd56_settimeout((struct watchdog_lowerhalf_s *)priv,
|
||||
priv->timeout);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_wdt_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the WDT watchdog time. The watchdog timer is initialized and
|
||||
* registered as 'devpath. The initial state of the watchdog time is
|
||||
* disabled.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Values:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int cxd56_wdt_initialize(void)
|
||||
{
|
||||
FAR struct cxd56_lowerhalf_s *priv = &g_wdtdev;
|
||||
|
||||
/* set load value to max and lock */
|
||||
|
||||
cxd56_putreg(0xffffffffu, CXD56_WDT_WDOGLOAD);
|
||||
cxd56_putreg(0, CXD56_WDT_WDOGLOCK);
|
||||
|
||||
wdinfo("Entry: devpath=%s\n", DEVPATH);
|
||||
|
||||
priv->ops = &g_wdgops;
|
||||
|
||||
#ifdef CONFIG_CXD56_WDT_INTERRUPT
|
||||
/* Attach our WDT interrupt handler (But don't enable it yet) */
|
||||
|
||||
(void)irq_attach(CXD56_IRQ_WDT_INT, cxd56_wdtinterrupt, priv);
|
||||
#endif
|
||||
|
||||
/* Register the watchdog driver as /dev/watchdog0 */
|
||||
|
||||
(void)watchdog_register(DEVPATH, (FAR struct watchdog_lowerhalf_s *)priv);
|
||||
|
||||
/* Register pm event callback */
|
||||
|
||||
pmhandle = cxd56_pm_register_callback(PM_CLOCK_APP_CPU, cxd56_pm_event);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CXD56_WDT */
|
94
arch/arm/src/cxd56xx/cxd56_wdt.h
Normal file
94
arch/arm/src/cxd56xx/cxd56_wdt.h
Normal file
@ -0,0 +1,94 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/cxd56xx/cxd56_wdt.h
|
||||
*
|
||||
* Copyright 2018 Sony Semiconductor Solutions Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of Sony Semiconductor Solutions Corporation nor
|
||||
* the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_WDT_H
|
||||
#define __ARCH_ARM_SRC_CXD56XX_CXD56_WDT_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include "chip.h"
|
||||
#include "hardware/cxd56_wdt.h"
|
||||
|
||||
#ifdef CONFIG_CXD56_WDT
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_wdt_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the WDT watchdog time. The watchdog timer is initialized and
|
||||
* registered as 'devpath. The initial state of the watchdog time is
|
||||
* disabled.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Values:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int cxd56_wdt_initialize(void);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* CONFIG_CXD56_WDT */
|
||||
#endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_WDT_H */
|
117
arch/arm/src/cxd56xx/hardware/cxd56_timer.h
Normal file
117
arch/arm/src/cxd56xx/hardware/cxd56_timer.h
Normal file
@ -0,0 +1,117 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/cxd56xx/hardware/cxd56_timer.h
|
||||
*
|
||||
* Copyright 2018 Sony Semiconductor Solutions Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of Sony Semiconductor Solutions Corporation nor
|
||||
* the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_CXD56XX_CHIP_CXD56_TIMER_H
|
||||
#define __ARCH_ARM_SRC_CXD56XX_CHIP_CXD56_TIMER_H
|
||||
|
||||
/****************************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <arch/cxd56xx/chip.h>
|
||||
|
||||
#include "hardware/cxd5602_memorymap.h"
|
||||
|
||||
/****************************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************************/
|
||||
|
||||
/* Register addresses *******************************************************************/
|
||||
|
||||
#define CXD56_TIMER0_BASE (CXD56_TIMER_BASE)
|
||||
#define CXD56_TIMER1_BASE (CXD56_TIMER_BASE + 0x0020)
|
||||
#define CXD56_TIMER_LOAD (0x0000) /* Load register */
|
||||
#define CXD56_TIMER_VALUE (0x0004) /* Value register [RO] */
|
||||
#define CXD56_TIMER_CONTROL (0x0008) /* Control register */
|
||||
#define CXD56_TIMER_INTCLR (0x000C) /* Clear Interrupt register [WO] */
|
||||
#define CXD56_TIMER_RIS (0x0010) /* Raw Interrupt Status register [RO] */
|
||||
#define CXD56_TIMER_MIS (0x0014) /* Interrupt Status register [RO] */
|
||||
#define CXD56_TIMER_BGLOAD (0x0018) /* Backround Load register [RO] */
|
||||
#define CXD56_TIMER_ITCR (0x0F00) /* Integration Test Control register */
|
||||
#define CXD56_TIMER_ITOP (0x0F04) /* Integration Test Output register [WO] */
|
||||
#define CXD56_TIMER_PERIPHID0 (0x0FE0) /* Peripheral ID0 register [RO] */
|
||||
#define CXD56_TIMER_PERIPHID1 (0x0FE4) /* Peripheral ID1 register [RO] */
|
||||
#define CXD56_TIMER_PERIPHID2 (0x0FE8) /* Peripheral ID2 register [RO] */
|
||||
#define CXD56_TIMER_PERIPHID3 (0x0FFC) /* Peripheral ID3 register [RO] */
|
||||
#define CXD56_TIMER_PCELLID0 (0x0FF0) /* PrimeCell ID0 register [RO] */
|
||||
#define CXD56_TIMER_PCELLID1 (0x0FF4) /* PrimeCell ID1 register [RO] */
|
||||
#define CXD56_TIMER_PCELLID2 (0x0FF8) /* PrimeCell ID2 register [RO] */
|
||||
#define CXD56_TIMER_PCELLID3 (0x0FFC) /* PrimeCell ID3 register [RO] */
|
||||
|
||||
/* Register bit definitions *************************************************************/
|
||||
|
||||
/* Control Register */
|
||||
|
||||
#define TIMERCTRL_ENABLE (0x1u << 7)
|
||||
#define TIMERCTRL_DISABLE (0x0u << 7)
|
||||
#define TIMERCTRL_PERIODIC (0x1u << 6)
|
||||
#define TIMERCTRL_FREERUN (0x0u << 6)
|
||||
#define TIMERCTRL_INTENABLE (0x1u << 5)
|
||||
#define TIMERCTRL_INTDISABLE (0x0u << 5)
|
||||
#define TIMERCTRL_DIV_256 (0x2u << 2)
|
||||
#define TIMERCTRL_DIV_16 (0x1u << 2)
|
||||
#define TIMERCTRL_DIV_1 (0x0u << 2)
|
||||
#define TIMERCTRL_SIZE_32BIT (0x1u << 1)
|
||||
#define TIMERCTRL_SIZE_16BIT (0x0u << 1)
|
||||
#define TIMERCTRL_MODE_ONESHOT (0x1u << 0)
|
||||
#define TIMERCTRL_MODE_WRAP (0x0u << 0)
|
||||
|
||||
/* Interrupt Register */
|
||||
|
||||
#define TIMER_INTERRUPT (0x1u << 0)
|
||||
|
||||
/* Integration Test Control register */
|
||||
|
||||
#define TIMERITCR_ENABLE (0x1u << 0)
|
||||
|
||||
/* Integration Test Output register */
|
||||
|
||||
#define TIMERITOP_TIMINT1 (0x1u << 0)
|
||||
#define TIMERITOP_TIMINT2 (0x1u << 1)
|
||||
|
||||
/****************************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************************/
|
||||
|
||||
/****************************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************************/
|
||||
|
||||
/****************************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************************/
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_CXD56XX_CHIP_CXD56_TIMER_H */
|
108
arch/arm/src/cxd56xx/hardware/cxd56_wdt.h
Normal file
108
arch/arm/src/cxd56xx/hardware/cxd56_wdt.h
Normal file
@ -0,0 +1,108 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/cxd56xx/hardware/cxd56_wdt.h
|
||||
*
|
||||
* Copyright 2018 Sony Semiconductor Solutions Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of Sony Semiconductor Solutions Corporation nor
|
||||
* the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_CXD56XX_CHIP_CXD56_WDT_H
|
||||
#define __ARCH_ARM_SRC_CXD56XX_CHIP_CXD56_WDT_H
|
||||
|
||||
/****************************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************************/
|
||||
|
||||
#include <arch/cxd56xx/chip.h>
|
||||
|
||||
#include "hardware/cxd5602_memorymap.h"
|
||||
|
||||
/****************************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************************/
|
||||
|
||||
/* WDT register addresses ***************************************************************/
|
||||
|
||||
#define CXD56_WDT_WDOGLOAD (CXD56_WDOG_BASE + 0x0000) /* Load register */
|
||||
#define CXD56_WDT_WDOGVALUE (CXD56_WDOG_BASE + 0x0004) /* Value register [RO] */
|
||||
#define CXD56_WDT_WDOGCONTROL (CXD56_WDOG_BASE + 0x0008) /* Control register */
|
||||
#define CXD56_WDT_WDOGINTCLR (CXD56_WDOG_BASE + 0x000C) /* Clear Interrupt register [WO] */
|
||||
#define CXD56_WDT_WDOGRIS (CXD56_WDOG_BASE + 0x0010) /* Raw Interrupt Status register [RO] */
|
||||
#define CXD56_WDT_WDOGMIS (CXD56_WDOG_BASE + 0x0014) /* Interrupt Status register [RO] */
|
||||
#define CXD56_WDT_WDOGLOCK (CXD56_WDOG_BASE + 0x0C00) /* Lock register */
|
||||
#define CXD56_WDT_WDOGITCR (CXD56_WDOG_BASE + 0x0F00) /* Integration Test Control register */
|
||||
#define CXD56_WDT_WDOGITOP (CXD56_WDOG_BASE + 0x0F04) /* Integration Test Output register [WO] */
|
||||
#define CXD56_WDT_WDOGPERIPHID0 (CXD56_WDOG_BASE + 0x0FE0) /* Peripheral ID0 register [RO] */
|
||||
#define CXD56_WDT_WDOGPERIPHID1 (CXD56_WDOG_BASE + 0x0FE4) /* Peripheral ID1 register [RO] */
|
||||
#define CXD56_WDT_WDOGPERIPHID2 (CXD56_WDOG_BASE + 0x0FE8) /* Peripheral ID2 register [RO] */
|
||||
#define CXD56_WDT_WDOGPERIPHID3 (CXD56_WDOG_BASE + 0x0FFC) /* Peripheral ID3 register [RO] */
|
||||
#define CXD56_WDT_WDOGPCELLID0 (CXD56_WDOG_BASE + 0x0FF0) /* PrimeCell ID0 register [RO] */
|
||||
#define CXD56_WDT_WDOGPCELLID1 (CXD56_WDOG_BASE + 0x0FF4) /* PrimeCell ID1 register [RO] */
|
||||
#define CXD56_WDT_WDOGPCELLID2 (CXD56_WDOG_BASE + 0x0FF8) /* PrimeCell ID2 register [RO] */
|
||||
#define CXD56_WDT_WDOGPCELLID3 (CXD56_WDOG_BASE + 0x0FFC) /* PrimeCell ID3 register [RO] */
|
||||
|
||||
/* WDT register bit definitions *********************************************************/
|
||||
|
||||
/* Control Register */
|
||||
|
||||
#define WDOGCONTROL_RESEN (0x1 << 1) /* enable reset output */
|
||||
#define WDOGCONTROL_INTEN (0x1 << 0) /* enable interrupt output */
|
||||
#define WDOGCONTROL_STOP (0x0) /* stop */
|
||||
|
||||
/* Interrupt Register */
|
||||
|
||||
#define WDOGRIS_RAWINT (0x1 << 0) /* raw interrupt status */
|
||||
#define WDOGRIS_INT (0x1 << 0) /* interrupt status */
|
||||
|
||||
/* Lock Register */
|
||||
|
||||
#define WDOGLOCK_UNLOCK_KEY (0x1ACCE551) /* unlock key */
|
||||
#define WDOGLOCK_ACCESS_ENABLE (0x0 << 0) /* enable write access */
|
||||
#define WDOGLOCK_ACCESS_DISABLE (0x1 << 0) /* disable write access */
|
||||
|
||||
/* Test Register */
|
||||
|
||||
#define WDOGITCR_ENABLE (0x1 << 0) /* enable test mode */
|
||||
#define WDOGITOP_WDOGINT (0x1 << 1) /* output interrupt */
|
||||
#define WDOGITOP_WDOGRES (0x1 << 0) /* output reset */
|
||||
|
||||
/****************************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************************/
|
||||
|
||||
/****************************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************************/
|
||||
|
||||
/****************************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************************/
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_CXD56XX_CHIP_CXD56_WDT_H */
|
@ -49,6 +49,7 @@
|
||||
#include "cxd56_power.h"
|
||||
#include "cxd56_flash.h"
|
||||
#include "cxd56_sdcard.h"
|
||||
#include "cxd56_wdt.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
84
configs/spresense/include/cxd56_pwm.h
Normal file
84
configs/spresense/include/cxd56_pwm.h
Normal file
@ -0,0 +1,84 @@
|
||||
/****************************************************************************
|
||||
* configs/spresense/include/cxd56_pwm.h
|
||||
*
|
||||
* Copyright 2018 Sony Semiconductor Solutions Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of Sony Semiconductor Solutions Corporation nor
|
||||
* the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __BOARD_COMMON_INCLUDE_CXD56_PWM_H
|
||||
#define __BOARD_COMMON_INCLUDE_CXD56_PWM_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_pwm_setup
|
||||
*
|
||||
* Description:
|
||||
* Initialize PWM on the board.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int board_pwm_setup(void);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __BOARD_COMMON_INCLUDE_CXD56_PWM_H */
|
84
configs/spresense/include/cxd56_wdt.h
Normal file
84
configs/spresense/include/cxd56_wdt.h
Normal file
@ -0,0 +1,84 @@
|
||||
/****************************************************************************
|
||||
* configs/spresense/include/cxd56_wdt.h
|
||||
*
|
||||
* Copyright 2018 Sony Semiconductor Solutions Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of Sony Semiconductor Solutions Corporation nor
|
||||
* the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __BOARD_COMMON_INCLUDE_CXD56_WDT_H
|
||||
#define __BOARD_COMMON_INCLUDE_CXD56_WDT_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_wdt_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize WDT on the board.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int cxd56_wdt_initialize(void);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __BOARD_COMMON_INCLUDE_CXD56_WDT_H */
|
@ -60,10 +60,18 @@ ifeq ($(CONFIG_ARCH_LEDS),y)
|
||||
CSRCS += cxd56_leds.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CXD56_PWM),y)
|
||||
CSRCS += cxd56_pwm.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CXD56_SFC),y)
|
||||
CSRCS += cxd56_flash.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SPI),y)
|
||||
CSRCS += cxd56_spi.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CXD56_SDIO),y)
|
||||
CSRCS += cxd56_sdcard.c
|
||||
endif
|
||||
|
@ -39,6 +39,7 @@
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
@ -62,6 +63,18 @@
|
||||
#include "cxd56_gpio.h"
|
||||
#include "cxd56_pinconfig.h"
|
||||
|
||||
#ifdef CONFIG_CXD56_PM_PROCFS
|
||||
#include "cxd56_powermgr_procfs.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TIMER
|
||||
#include "cxd56_timer.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_WDT
|
||||
#include "cxd56_wdt.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CXD56_RTC
|
||||
#include <nuttx/timers/rtc.h>
|
||||
#include "cxd56_rtc.h"
|
||||
@ -83,6 +96,10 @@
|
||||
#include "cxd56_usbdev.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PWM
|
||||
#include "cxd56_pwm.h"
|
||||
#endif
|
||||
|
||||
#include "spresense.h"
|
||||
|
||||
/****************************************************************************
|
||||
@ -127,6 +144,21 @@ static int nsh_cpucom_initialize(void)
|
||||
# define nsh_cpucom_initialize() (OK)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TIMER
|
||||
static void timer_initialize(void)
|
||||
{
|
||||
int i;
|
||||
char devname[16];
|
||||
|
||||
for (i = 0; i < CXD56_TIMER_NUM; i++)
|
||||
{
|
||||
snprintf(devname, sizeof(devname), "/dev/timer%d", i);
|
||||
cxd56_timer_initialize(devname, i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -162,6 +194,14 @@ int cxd56_bringup(void)
|
||||
_err("ERROR: Failed to initialize powermgr.\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CXD56_PM_PROCFS
|
||||
ret = cxd56_pm_initialize_procfs();
|
||||
if (ret < 0)
|
||||
{
|
||||
_err("ERROR: Failed to initialize powermgr.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
wlock.info = PM_CPUWAKELOCK_TAG('C', 'A', 0);
|
||||
wlock.count = 0;
|
||||
up_pm_acquire_wakelock(&wlock);
|
||||
@ -170,6 +210,18 @@ int cxd56_bringup(void)
|
||||
rtc_initialize(0, cxd56_rtc_lowerhalf());
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TIMER
|
||||
timer_initialize();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CXD56_WDT
|
||||
ret = cxd56_wdt_initialize();
|
||||
if (ret < 0)
|
||||
{
|
||||
_err("ERROR: Failed to initialize WDT.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
cxd56_uart_initialize();
|
||||
cxd56_timerisr_initialize();
|
||||
|
||||
@ -208,6 +260,14 @@ int cxd56_bringup(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PWM
|
||||
ret = board_pwm_setup();
|
||||
if (ret < 0)
|
||||
{
|
||||
_err("ERROR: Failed to initialze pwm. \n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CXD56_SFC
|
||||
ret = board_flash_initialize();
|
||||
if (ret < 0)
|
||||
|
141
configs/spresense/src/cxd56_pwm.c
Normal file
141
configs/spresense/src/cxd56_pwm.c
Normal file
@ -0,0 +1,141 @@
|
||||
/****************************************************************************
|
||||
* configs/spresense/src/cxd56_pwm.c
|
||||
*
|
||||
* Copyright 2018 Sony Semiconductor Solutions Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of Sony Semiconductor Solutions Corporation nor
|
||||
* the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/board.h>
|
||||
#include <nuttx/drivers/pwm.h>
|
||||
|
||||
#include "cxd56_pwm.h"
|
||||
|
||||
#ifdef CONFIG_PWM
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_CXD56_PWM0) || defined(CONFIG_CXD56_PWM1) || \
|
||||
defined(CONFIG_CXD56_PWM2) || defined(CONFIG_CXD56_PWM3)
|
||||
static int pwm_initialize(uint32_t channel)
|
||||
{
|
||||
char devname[16];
|
||||
struct pwm_lowerhalf_s *pwm = NULL;
|
||||
int ret;
|
||||
|
||||
/* Call cxd56_pwminitialize() to get an instance of the PWM interface */
|
||||
|
||||
pwm = cxd56_pwminitialize(channel);
|
||||
if (!pwm)
|
||||
{
|
||||
pwmerr("Failed to get the CXD56 PWM%d lower half\n", channel);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Register the PWM driver at "/dev/pwmX" */
|
||||
|
||||
snprintf(devname, sizeof(devname), "/dev/pwm%d", channel);
|
||||
ret = pwm_register(devname, pwm);
|
||||
if (ret < 0)
|
||||
{
|
||||
pwmerr("pwm_register(%s) failed: %d\n", devname, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_pwm_setup
|
||||
*
|
||||
* Description:
|
||||
* All CXD56 architectures must provide the following interface to work
|
||||
* with examples/pwm.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int board_pwm_setup(void)
|
||||
{
|
||||
static bool initialized = false;
|
||||
|
||||
/* Have we already initialized? */
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
#ifdef CONFIG_CXD56_PWM0
|
||||
pwm_initialize(CXD56_PWM_CH0);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CXD56_PWM1
|
||||
pwm_initialize(CXD56_PWM_CH1);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CXD56_PWM2
|
||||
pwm_initialize(CXD56_PWM_CH2);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CXD56_PWM3
|
||||
pwm_initialize(CXD56_PWM_CH3);
|
||||
#endif
|
||||
|
||||
/* Now we are initialized */
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PWM */
|
174
configs/spresense/src/cxd56_spi.c
Normal file
174
configs/spresense/src/cxd56_spi.c
Normal file
@ -0,0 +1,174 @@
|
||||
/****************************************************************************
|
||||
* configs/spresense/src/cxd56_spi.c
|
||||
*
|
||||
* Copyright 2018 Sony Semiconductor Solutions Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of Sony Semiconductor Solutions Corporation nor
|
||||
* the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/spi/spi.h>
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "up_arch.h"
|
||||
#include "chip.h"
|
||||
#include "hardware/cxd56_spi.h"
|
||||
#include "cxd56_clock.h"
|
||||
#include "cxd56_gpio.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define MMCSD_DETECT PIN_AP_CLK
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cxd56_spi0/3/4/5select and cxd56_spi0/3/4/5status
|
||||
*
|
||||
* Description:
|
||||
* The external functions, cxd56_spi1/2/3select and cxd56_spi1/2/3status must be
|
||||
* provided by board-specific logic. They are implementations of the select
|
||||
* and status methods of the SPI interface defined by struct spi_ops_s (see
|
||||
* include/nuttx/spi/spi.h). All other methods (including cxd56_spibus_initialize())
|
||||
* are provided by common CXD56 logic. To use this common SPI logic on your
|
||||
* board:
|
||||
*
|
||||
* 1. Provide logic in cxd56_boardinitialize() to configure SPI chip select
|
||||
* pins.
|
||||
* 2. Provide cxd56_spi0/3/4/5select() and cxd56_spi0/3/4/5status() functions in your
|
||||
* board-specific logic. These functions will perform chip selection and
|
||||
* status operations using GPIOs in the way your board is configured.
|
||||
* 3. Add a calls to cxd56_spibus_initialize() in your low level application
|
||||
* initialization logic
|
||||
* 4. The handle returned by cxd56_spibus_initialize() may then be used to bind the
|
||||
* SPI driver to higher level logic (e.g., calling
|
||||
* mmcsd_spislotinitialize(), for example, will bind the SPI driver to
|
||||
* the SPI MMC/SD driver).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_CXD56_SPI0
|
||||
void cxd56_spi0select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected)
|
||||
{
|
||||
spiinfo("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert");
|
||||
}
|
||||
|
||||
uint8_t cxd56_spi0status(FAR struct spi_dev_s *dev, uint32_t devid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CXD56_SPI3
|
||||
void cxd56_spi3select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected)
|
||||
{
|
||||
spiinfo("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert");
|
||||
|
||||
/* Disable clock gating (clock enable) */
|
||||
|
||||
cxd56_spi_clock_gate_disable(3);
|
||||
|
||||
if (selected)
|
||||
{
|
||||
putreg32(0, CXD56_SPI3_CS);
|
||||
}
|
||||
else
|
||||
{
|
||||
putreg32(1, CXD56_SPI3_CS);
|
||||
}
|
||||
|
||||
/* Enable clock gating (clock disable) */
|
||||
|
||||
cxd56_spi_clock_gate_enable(3);
|
||||
}
|
||||
|
||||
uint8_t cxd56_spi3status(FAR struct spi_dev_s *dev, uint32_t devid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CXD56_SPI4
|
||||
void cxd56_spi4select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected)
|
||||
{
|
||||
spiinfo("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert");
|
||||
}
|
||||
|
||||
uint8_t cxd56_spi4status(FAR struct spi_dev_s *dev, uint32_t devid)
|
||||
{
|
||||
# ifdef CONFIG_CXD56_SPISD
|
||||
if (devid == SPIDEV_MMCSD(0))
|
||||
{
|
||||
static bool initialized = false;
|
||||
if (initialized == false)
|
||||
{
|
||||
/* Input enable */
|
||||
|
||||
cxd56_gpio_config(MMCSD_DETECT, true);
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
/* MMCSD_DETECT is mapping to SD Card detect pin
|
||||
* MMCSD_DETECT = 0: Inserted
|
||||
* MMCSD_DETECT = 1: Removed
|
||||
*/
|
||||
return cxd56_gpio_read(MMCSD_DETECT) ? 0 : SPI_STATUS_PRESENT;
|
||||
}
|
||||
# endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CXD56_SPI5
|
||||
void cxd56_spi5select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected)
|
||||
{
|
||||
spiinfo("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert");
|
||||
}
|
||||
|
||||
uint8_t cxd56_spi5status(FAR struct spi_dev_s *dev, uint32_t devid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user