Merged in masayuki2009/nuttx.nuttx/lc823450_dvfs_auto (pull request #604)

lc823450 dvfs auto

* arch/arm/src/lc823450: Fix up_enable_irq() timing for I2S.

    In previous commit, I2S IRQ might be sometimes assigned to CPU1
    when CONFIG_SMP=y. This change fixes this issue.

    Signed-off-by: Masayuki Ishikawa <Masayuki.Ishikawa@jp.sony.com>

* arch/arm/src/lc823450: Refactor timer driver.

    Introduce lc823450_timer.h and move lc823450_timerisr.c to
    lc823450_timer.c Add MTM timer APIs for DVFS.  Introduce
    up_rtc_gettime() for CONFIG_RTC_HIRES.

    Signed-off-by: Masayuki Ishikawa <Masayuki.Ishikawa@jp.sony.com>

* arch/arm/src/lc823450: Introduce idle time calculation in DVFS

    Also, DVFS autonomous mode based on CPU idle time is supported.
    NOTE: voltage control is still disabled.

    Signed-off-by: Masayuki Ishikawa <Masayuki.Ishikawa@jp.sony.com>

* configs/lc823450-xgevk: Update defconfigs

    Enable RTC_HIRES instead of RTC_DATETIME (audio/rndis)
    Disable TCP_WRITE_BUFFERS and change SCHED_LPWORKPRIORITY (rndis)

    Signed-off-by: Masayuki Ishikawa <Masayuki.Ishikawa@jp.sony.com>

* configs/lc823450-xgevk: Update README.txt

    Update SMP and DVFS related part

    Signed-off-by: Masayuki Ishikawa <Masayuki.Ishikawa@jp.sony.com>

Approved-by: Gregory Nutt <gnutt@nuttx.org>
This commit is contained in:
Masayuki Ishikawa 2018-02-23 13:26:40 +00:00 committed by Gregory Nutt
parent 9812f6f932
commit 82e94a9948
13 changed files with 529 additions and 120 deletions

View File

@ -84,7 +84,7 @@ endif
CHIP_ASRCS =
CHIP_CSRCS = lc823450_start.c lc823450_irq.c lc823450_idle.c
CHIP_CSRCS += lc823450_timerisr.c lc823450_lowputc.c
CHIP_CSRCS += lc823450_timer.c lc823450_lowputc.c
CHIP_CSRCS += lc823450_serial.c lc823450_clockconfig.c lc823450_syscontrol.c
CHIP_CSRCS += lc823450_gpio.c

View File

@ -51,6 +51,8 @@
#include "lc823450_syscontrol.h"
#include "lc823450_intc.h"
#include "lc823450_sdc.h"
#include "lc823450_gpio.h"
#include "lc823450_timer.h"
#include "lc823450_dvfs2.h"
/****************************************************************************
@ -61,6 +63,25 @@
#define FREQ_080 1
#define FREQ_040 2
#define FREQ_KP 2
#define FREQ_UP 1
#define FREQ_DN 0
#define UP_THRESHOLD 20
#define DN_THRESHOLD 60
#ifndef CONFIG_SMP_NCPUS
# define CONFIG_SMP_NCPUS 1
#endif
#ifdef CONFIG_DVFS_CHANGE_VOLTAGE
# define CORE12V_PIN (GPIO_PORT2 | GPIO_PIN1)
#endif
#ifndef CONFIG_RTC_HIRES
# error "Should be enabled to get high-accuracy for CPU idle time"
#endif
/****************************************************************************
* Private Data
****************************************************************************/
@ -90,28 +111,49 @@ static struct freq_entry _dvfs_idl_tbl[3] =
static uint16_t _dvfs_cur_idx = 0; /* current speed index */
static uint16_t _dvfs_cur_hdiv = 3;
static uint16_t _dvfs_cur_mdiv = OSCCNT_MAINDIV_1;
static uint16_t _dvfs_core12v = 0;
#if 0
static uint16_t _dvfs_init_timeout = (5 * 100); /* in ticks */
#endif
#if defined(CONFIG_SMP) && (CONFIG_SMP_NCPUS == 2)
static uint8_t _dvfs_cpu_is_active[CONFIG_SMP_NCPUS];
#endif
static void lc823450_dvfs_set_div(int idx, int tbl);
static uint64_t g_idle_starttime[CONFIG_SMP_NCPUS];
static uint64_t g_idle_totaltime[CONFIG_SMP_NCPUS];
static uint64_t g_idle_totaltime0[CONFIG_SMP_NCPUS];
/****************************************************************************
* Public Data
****************************************************************************/
int8_t g_dvfs_enabled = 0;
int8_t g_dvfs_auto = 0;
uint16_t g_dvfs_cur_freq = 160;
uint32_t g_dvfs_freq_stat[3] =
{
0, 0, 0
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: up_get_current_time()
****************************************************************************/
static uint64_t _get_current_time64(void)
{
struct timespec ts;
#ifdef CONFIG_CLOCK_MONOTONIC
clock_gettime(CLOCK_MONOTONIC, &ts);
#else
clock_gettime(CLOCK_REALTIME, &ts);
#endif
return (uint64_t)ts.tv_sec * NSEC_PER_SEC + (uint64_t)ts.tv_nsec;
}
/****************************************************************************
* Name: lc823450_dvfs_update_lpm
****************************************************************************/
@ -121,7 +163,7 @@ static void lc823450_dvfs_update_lpm(int freq)
/* TODO */
}
#if defined(CONFIG_SMP) && (CONFIG_SMP_NCPUS == 2)
#if CONFIG_SMP_NCPUS == 2
static int _dvfs_another_cpu_state(int me)
{
if (0 == me)
@ -135,6 +177,50 @@ static int _dvfs_another_cpu_state(int me)
}
#endif
/****************************************************************************
* Name: lc823450_dvfs_oneshot
* Callback for 1 shot timer
****************************************************************************/
int lc823450_dvfs_oneshot(int irq, uint32_t *regs, FAR void *arg)
{
/* voltage has reached at 1.2V */
_dvfs_core12v = 1;
lc823450_mtm_stop_oneshot();
/* go to max freq */
lc823450_dvfs_set_div(FREQ_160, 0);
return 0;
}
/****************************************************************************
* Name: lc832450_set_core_voltage
* high=true (1.2V), high=false (1.0V)
****************************************************************************/
#ifdef CONFIG_DVFS_CHANGE_VOLTAGE
static void lc832450_set_core_voltage(bool high)
{
if (false == high)
{
_dvfs_core12v = 0;
}
lc823450_gpio_write(CORE12V_PIN, (int)high);
if (high)
{
/* start 3ms timer to change internal dividers */
lc823450_mtm_start_oneshot(3);
}
}
#endif
/****************************************************************************
* Name: lc823450_dvfs_set_div
* Set dividers in the OSC block
@ -160,6 +246,16 @@ static void lc823450_dvfs_set_div(int idx, int tbl)
t_mdiv = _dvfs_idl_tbl[idx].mdiv;
}
#ifdef CONFIG_DVFS_CHANGE_VOLTAGE
if (100 < target && !_dvfs_core12v)
{
/* Set high voltage (i.e. 1.2v) */
lc832450_set_core_voltage(true);
return;
}
#endif
if (100 < target)
{
/* Set ROM wait cycle (CPU=1wait) */
@ -242,6 +338,18 @@ static void lc823450_dvfs_set_div(int idx, int tbl)
_dvfs_cur_mdiv = t_mdiv;
g_dvfs_cur_freq = target;
#ifdef CONFIG_DVFS_CHANGE_VOLTAGE
/* NOTE: check the index instead of the target freq */
if (_dvfs_core12v && _dvfs_cur_idx != FREQ_160)
{
/* set to lower voltage (i.e. 1.0v) */
lc832450_set_core_voltage(false);
}
#endif
if (100 > target)
{
/* Clear ROM wait cycle (CPU=0wait) */
@ -251,10 +359,123 @@ static void lc823450_dvfs_set_div(int idx, int tbl)
}
/****************************************************************************
* Name: lc823450_dvfs_change_idx
* up: 1=clock up, 0=clock down
* called in autonomous mode from interrupt context
****************************************************************************/
static void lc823450_dvfs_change_idx(int up)
{
uint16_t idx = _dvfs_cur_idx;
/* NOTE: clock index is in reverse order to the speed */
/* clock up */
if (up && (FREQ_160 < idx))
{
idx--;
}
/* clock down */
if (!up && (FREQ_040 > idx))
{
idx++;
}
#ifdef CONFIG_DVFS_EXCLUDE_40M
if (idx == FREQ_040)
{
return;
}
#endif
if (idx != _dvfs_cur_idx)
{
lc823450_dvfs_set_div(idx, 0);
}
}
/****************************************************************************
* Name: lc823450_dvfs_do_auto
****************************************************************************/
static void lc823450_dvfs_do_auto(uint32_t idle[])
{
uint32_t state[CONFIG_SMP_NCPUS];
int i;
for (i = 0; i < CONFIG_SMP_NCPUS; i++)
{
if (UP_THRESHOLD >= idle[i])
{
state[i] = FREQ_UP;
}
else if (DN_THRESHOLD <= idle[i])
{
state[i] = FREQ_DN;
}
else
{
state[i] = FREQ_KP;
}
}
#if CONFIG_SMP_NCPUS == 1
if (FREQ_UP == state[0])
#elif CONFIG_SMP_NCPUS == 2
if (FREQ_UP == state[0] || FREQ_UP == state[1])
#endif
{
lc823450_dvfs_change_idx(FREQ_UP);
}
#if CONFIG_SMP_NCPUS == 1
if (FREQ_DN == state[0])
#elif CONFIG_SMP_NCPUS == 2
if (FREQ_DN == state[0] && FREQ_DN == state[1])
#endif
{
lc823450_dvfs_change_idx(FREQ_DN);
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: lc823450_dvfs_get_idletime
****************************************************************************/
void lc823450_dvfs_get_idletime(uint64_t idletime[])
{
irqstate_t flags = spin_lock_irqsave();
/* First, copy g_idle_totaltime to the caller */
memcpy(idletime, g_idle_totaltime, sizeof(g_idle_totaltime));
#if CONFIG_SMP_NCPUS == 2
int me = up_cpu_index();
if (0 == _dvfs_another_cpu_state(me))
{
/* Another CPU is in idle, so consider this situation */
int cpu = (me == 0) ? 1 : 0;
idletime[cpu] += (_get_current_time64() - g_idle_starttime[cpu]);
/* NOTE: g_idletotaltime[cpu] must not be updated */
}
#endif
spin_unlock_irqrestore(flags);
}
/****************************************************************************
* Name: lc823450_get_apb
* Assumption: CPU=APB
@ -267,22 +488,39 @@ uint32_t lc823450_get_apb(void)
/****************************************************************************
* Name: lc823450_dvfs_tick_callback
* This callback is called in the timer interupt
* This callback is called in the timer interupt on CPU0
****************************************************************************/
void lc823450_dvfs_tick_callback(void)
{
#if 0
if (_dvfs_init_timeout)
{
_dvfs_init_timeout--;
uint64_t tmp_idle_total[CONFIG_SMP_NCPUS];
uint32_t idle[CONFIG_SMP_NCPUS];
int i;
if (0 == _dvfs_init_timeout)
if (g_dvfs_enabled && g_dvfs_auto)
{
g_dvfs_enabled = 1;
lc823450_dvfs_get_idletime(tmp_idle_total);
/* Calculate idle ratio for each CPU */
for (i = 0; i < CONFIG_SMP_NCPUS; i++)
{
idle[i] = 100 * (tmp_idle_total[i] - g_idle_totaltime0[i])
/ NSEC_PER_TICK;
}
/* Update g_idle_totaltime0 */
memcpy(g_idle_totaltime0, tmp_idle_total, sizeof(tmp_idle_total));
/* Do autonomous mode */
lc823450_dvfs_do_auto(idle);
}
#endif
/* Update freqency statistics */
g_dvfs_freq_stat[_dvfs_cur_idx]++;
}
/****************************************************************************
@ -293,18 +531,22 @@ void lc823450_dvfs_enter_idle(void)
{
irqstate_t flags = spin_lock_irqsave();
if (0 == g_dvfs_enabled)
{
goto exit_with_error;
}
#if defined(CONFIG_SMP) && (CONFIG_SMP_NCPUS == 2)
int me = up_cpu_index();
/* Update my state first : 0 (idle) */
_dvfs_cpu_is_active[me] = 0;
/* Update my idle start time */
g_idle_starttime[me] = _get_current_time64();
if (0 == g_dvfs_enabled)
{
goto exit_with_error;
}
#if CONFIG_SMP_NCPUS == 2
/* check if another core is still active */
if (_dvfs_another_cpu_state(me))
@ -313,7 +555,6 @@ void lc823450_dvfs_enter_idle(void)
goto exit_with_error;
}
#endif
#ifdef CONFIG_DVFS_CHECK_SDC
@ -340,18 +581,16 @@ void lc823450_dvfs_exit_idle(int irq)
{
irqstate_t flags = spin_lock_irqsave();
int me = up_cpu_index();
uint64_t d;
uint64_t now;
if (0 == g_dvfs_enabled)
{
goto exit_with_error;
}
#if defined(CONFIG_SMP) && (CONFIG_SMP_NCPUS == 2)
int me = up_cpu_index();
/* Update my state first: 1 (active) */
_dvfs_cpu_is_active[me] = 1;
#if CONFIG_SMP_NCPUS == 2
/* Check if another core is already active */
if (_dvfs_another_cpu_state(me))
@ -367,6 +606,21 @@ void lc823450_dvfs_exit_idle(int irq)
lc823450_dvfs_set_div(_dvfs_cur_idx, 0);
exit_with_error:
if (0 == _dvfs_cpu_is_active[me])
{
/* In case of idle to active transition */
/* Accumulate idle total time on this CPU */
now = _get_current_time64();
d = now - g_idle_starttime[me];
g_idle_totaltime[me] += d;
}
/* Finally update my state : 1 (active) */
_dvfs_cpu_is_active[me] = 1;
spin_unlock_irqrestore(flags);
}
@ -410,9 +664,11 @@ int lc823450_dvfs_set_freq(int freq)
idx = FREQ_080;
break;
#ifndef CONFIG_DVFS_EXCLUDE_40M
case 40:
idx = FREQ_040;
break;
#endif
default:
ret = -1;

View File

@ -59,11 +59,14 @@ extern "C"
* Public Functions
****************************************************************************/
void lc823450_dvfs_get_idletime(uint64_t idaletime[]);
void lc823450_dvfs_set_min(uint8_t id, uint16_t mhz);
void lc823450_dvfs_enter_idle(void);
void lc823450_dvfs_exit_idle(int irq);
int lc823450_dvfs_set_freq(int freq);
void lc823450_dvfs_tick_callback(void);
int lc823450_dvfs_oneshot(int irq, uint32_t *regs, FAR void *arg);
int dvfs_procfs_register(void);

View File

@ -484,6 +484,10 @@ FAR struct i2s_dev_s *lc823450_i2sdev_initialize(void)
irq_attach(LC823450_IRQ_AUDIOBUF0, _i2s_isr, NULL);
/* Enable IRQ for Audio Buffer */
up_enable_irq(LC823450_IRQ_AUDIOBUF0);
#ifdef CONFIG_SMP
/* Restore the original affinity */
@ -491,10 +495,6 @@ FAR struct i2s_dev_s *lc823450_i2sdev_initialize(void)
nxsig_usleep(10 * 1000);
#endif
/* Enable IRQ for Audio Buffer */
up_enable_irq(LC823450_IRQ_AUDIOBUF0);
/* Success exit */
return &priv->dev;

View File

@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/lc823450/lc823450_idle.c
*
* Copyright (C) 2014-2017 Sony Corporation. All rights reserved.
* Copyright (C) 2014-2018 Sony Corporation. All rights reserved.
* Author: Masayuki Ishikawa <Masayuki.Ishikawa@jp.sony.com>
* Author: Masatoshi Tateishi <Masatoshi.Tateishi@jp.sony.com>
*
@ -57,35 +57,8 @@
* Private Data
****************************************************************************/
#ifdef CONFIG_LC823450_SLEEP_MODE
static int32_t g_in_sleep;
static uint64_t g_sleep_t0;
#endif /* CONFIG_LC823450_SLEEP_MODE */
static uint32_t g_idle_counter[2];
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: up_get_current_time()
****************************************************************************/
#ifdef CONFIG_LC823450_SLEEP_MODE
static uint64_t up_get_current_time(void)
{
struct timespec ts;
#ifdef CONFIG_CLOCK_MONOTONIC
clock_gettime(CLOCK_MONOTONIC, &ts);
#else
clock_gettime(CLOCK_REALTIME, &ts);
#endif
return (uint64_t)ts.tv_sec * NSEC_PER_SEC + (uint64_t)ts.tv_nsec;
}
#endif /* CONFIG_LC823450_SLEEP_MODE */
/****************************************************************************
* Public Functions
****************************************************************************/
@ -113,21 +86,18 @@ void up_idle(void)
sched_process_timer();
#else
#ifdef CONFIG_LC823450_SLEEP_MODE
/* DVFS and LED control must be done with local interrupts disabled */
irqstate_t flags;
flags = enter_critical_section();
g_sleep_t0 = up_get_current_time();
g_in_sleep = 1;
flags = up_irq_save();
#ifdef CONFIG_LC823450_SLEEP_MODE
/* Clear SLEEPDEEP flag */
uint32_t regval = getreg32(NVIC_SYSCON);
regval &= ~NVIC_SYSCON_SLEEPDEEP;
putreg32(regval, NVIC_SYSCON);
leave_critical_section(flags);
#endif /* CONFIG_LC823450_SLEEP_MODE */
#endif
#ifdef CONFIG_DVFS
lc823450_dvfs_enter_idle();
@ -135,6 +105,8 @@ void up_idle(void)
board_autoled_off(LED_CPU0 + up_cpu_index());
up_irq_restore(flags);
/* Sleep until an interrupt occurs to save power */
asm("WFI");
@ -144,22 +116,3 @@ void up_idle(void)
#endif
}
/****************************************************************************
* Name: up_update_idle_time()
*
* Description:
* up_update_idle_time() is the logic that will update idle time
*
****************************************************************************/
#ifdef CONFIG_LC823450_SLEEP_MODE
void up_update_idle_time(void)
{
if (g_in_sleep)
{
g_in_sleep = 0;
uint64_t t1 = up_get_current_time();
sched_add_idl_tm(t1 - g_sleep_t0);
}
}
#endif /* CONFIG_LC823450_SLEEP_MODE */

View File

@ -717,10 +717,6 @@ void up_ack_irq(int irq)
}
#endif
#ifdef CONFIG_LC823450_SLEEP_MODE
extern void up_update_idle_time(void);
up_update_idle_time();
#endif
}
/****************************************************************************

View File

@ -68,12 +68,16 @@
* Pre-processor Definitions
****************************************************************************/
#define DVFS_LINELEN 64
#define DVFS_LINELEN 128
#ifndef MIN
# define MIN(a,b) (a < b ? a : b)
#endif
#ifndef CONFIG_SMP_NCPUS
# define CONFIG_SMP_NCPUS 1
#endif
/****************************************************************************
* Private Types
****************************************************************************/
@ -129,7 +133,9 @@ static const struct procfs_entry_s g_procfs_dvfs =
****************************************************************************/
extern int8_t g_dvfs_enabled;
extern int8_t g_dvfs_auto;
extern uint16_t g_dvfs_cur_freq;
extern uint32_t g_dvfs_freq_stat[3];
/****************************************************************************
@ -203,6 +209,8 @@ static ssize_t dvfs_read(FAR struct file *filep, FAR char *buffer,
size_t remaining;
size_t totalsize;
off_t offset = filep->f_pos;
int i;
uint64_t idletime[CONFIG_SMP_NCPUS];
finfo("buffer=%p buflen=%d\n", buffer, (int)buflen);
@ -230,6 +238,42 @@ static ssize_t dvfs_read(FAR struct file *filep, FAR char *buffer,
"enable %d \n", g_dvfs_enabled);
copysize = procfs_memcpy(priv->line, linesize, buffer, remaining, &offset);
totalsize += copysize;
buffer += copysize;
remaining -= copysize;
linesize = snprintf(priv->line,
DVFS_LINELEN,
"auto %d \n", g_dvfs_auto);
copysize = procfs_memcpy(priv->line, linesize, buffer, remaining, &offset);
totalsize += copysize;
buffer += copysize;
remaining -= copysize;
linesize = snprintf(priv->line,
DVFS_LINELEN,
"fstat %d %d %d \n",
g_dvfs_freq_stat[0],
g_dvfs_freq_stat[1],
g_dvfs_freq_stat[2]);
copysize = procfs_memcpy(priv->line, linesize, buffer, remaining, &offset);
totalsize += copysize;
buffer += copysize;
remaining -= copysize;
lc823450_dvfs_get_idletime(idletime);
for (i = 0; i < CONFIG_SMP_NCPUS; i++)
{
linesize = snprintf(priv->line,
DVFS_LINELEN,
"idle%d %lld \n",
i, idletime[i]);
copysize = procfs_memcpy(priv->line, linesize, buffer, remaining, &offset);
totalsize += copysize;
buffer += copysize;
remaining -= copysize;
}
/* Update the file offset */
@ -251,8 +295,7 @@ static ssize_t dvfs_write(FAR struct file *filep, FAR const char *buffer,
char line[DVFS_LINELEN];
char cmd[16];
int n;
int freq;
int enable;
int tmp;
n = MIN(buflen, DVFS_LINELEN - 1);
strncpy(line, buffer, n);
@ -264,13 +307,18 @@ static ssize_t dvfs_write(FAR struct file *filep, FAR const char *buffer,
if (0 == strcmp(cmd, "cur_freq"))
{
freq = atoi(line + (n + 1));
(void)lc823450_dvfs_set_freq(freq);
tmp = atoi(line + (n + 1));
(void)lc823450_dvfs_set_freq(tmp);
}
else if (0 == strcmp(cmd, "enable"))
{
enable = atoi(line + (n + 1));
g_dvfs_enabled = enable;
tmp = atoi(line + (n + 1));
g_dvfs_enabled = tmp;
}
else if (0 == strcmp(cmd, "auto"))
{
tmp = atoi(line + (n + 1));
g_dvfs_auto = tmp;
}
else
{

View File

@ -59,6 +59,7 @@
#include "lc823450_dma.h"
#include "lc823450_gpio.h"
#include "lc823450_syscontrol.h"
#include "lc823450_timer.h"
#ifdef CONFIG_LC823450_SDC_DMA
# include <semaphore.h>

View File

@ -1,5 +1,5 @@
/****************************************************************************
* arch/arm/src/lc823450/lc823450_timerisr.c
* arch/arm/src/lc823450/lc823450_timer.c
*
* Copyright (C) 2014-2017 Sony Corporation. All rights reserved.
* Author: Masatoshi Tateishi <Masatoshi.Tateishi@jp.sony.com>
@ -61,6 +61,7 @@
#include "lc823450_syscontrol.h"
#include "lc823450_clockconfig.h"
#include "lc823450_serial.h"
#include "lc823450_timer.h"
#ifdef CONFIG_DVFS
# include "lc823450_dvfs2.h"
@ -116,6 +117,17 @@
# define rMT30CNT (LC823450_MTM3_REGBASE + LC823450_MTM_0CNT)
#endif /* CONFIG_PROFILE */
#ifdef CONFIG_DVFS
# define rMT01STS (LC823450_MTM0_REGBASE + LC823450_MTM_1STS)
# define rMT01A (LC823450_MTM0_REGBASE + LC823450_MTM_1A)
# define rMT01B (LC823450_MTM0_REGBASE + LC823450_MTM_1B)
# define rMT01CTL (LC823450_MTM0_REGBASE + LC823450_MTM_1CTL)
# define rMT01PSCL (LC823450_MTM0_REGBASE + LC823450_MTM_1PSCL)
# define rMT01TIER (LC823450_MTM0_REGBASE + LC823450_MTM_1TIER)
# define rMT01CNT (LC823450_MTM0_REGBASE + LC823450_MTM_1CNT)
# define rMT0OPR (LC823450_MTM0_REGBASE + LC823450_MTM_OPR)
#endif
#ifndef container_of
# define container_of(ptr, type, member) \
((type *)((void *)(ptr) - offsetof(type, member)))
@ -618,17 +630,79 @@ void arm_timer_initialize(void)
up_enable_irq(LC823450_IRQ_SYSTICK);
#endif
#ifdef CONFIG_DVFS
/* attach timer interrupt handler */
(void)irq_attach(LC823450_IRQ_MTIMER01, (xcpt_t)lc823450_dvfs_oneshot, NULL);
/* enable MTM0-ch1 */
up_enable_irq(LC823450_IRQ_MTIMER01);
#endif
}
/****************************************************************************
* Name: up_hr_gettime
* Name: lc823450_mtm_start_oneshot
* NOTE: Assumption: MTM0-ch0 is running (i.e. tick timer)
****************************************************************************/
#ifdef CONFIG_DVFS
void lc823450_mtm_start_oneshot(int msec)
{
uint32_t r = MTM_RELOAD; /* 10ms */
r /= 10; /* 1ms */
r *= msec;
putreg32(0, rMT01A); /* AEVT counter */
putreg32(r - 1, rMT01B); /* BEVT counter */
/* Clear the counter by BEVT */
putreg32(0x80, rMT01CTL);
/* Set prescaler to 9 : (1/10) */
putreg32(9, rMT01PSCL);
/* Enable BEVT Interrupt */
putreg32(1 << 1, rMT01TIER);
/* Enable MTM0-ch1 */
modifyreg32(rMT0OPR, 0, 1 << 1);
}
#endif
/****************************************************************************
* Name: lc823450_mtm_stop_oneshot
****************************************************************************/
#ifdef CONFIG_DVFS
void lc823450_mtm_stop_oneshot(void)
{
/* Clear the interrupt (BEVT) */
putreg32(1 << 1, rMT01STS);
/* Disable MTM0-ch1 */
modifyreg32(rMT0OPR, 1 << 1, 0);
}
#endif
/****************************************************************************
* Name: up_rtc_gettime
*
* Description:
* This function is used in clock_gettime() to obtain high resolution time.
*
****************************************************************************/
int up_hr_gettime(FAR struct timespec *tp)
int up_rtc_gettime(FAR struct timespec *tp)
{
uint64_t secs;
uint64_t nsecs;

View File

@ -0,0 +1,79 @@
/****************************************************************************
* arch/arm/src/lc823450/lc823450_timer.h
*
* Copyright (C) 2018 Sony Corporation. All rights reserved.
* Author: Masayuki Ishikawa <Masayuki.Ishikawa@jp.sony.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __ARCH_ARM_SRC_LC823450_LC823450_TIMER_H
#define __ARCH_ARM_SRC_LC823450_LC823450_TIMER_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#ifndef __ASSEMBLY__
/****************************************************************************
* Public Data
****************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
#ifdef CONFIG_HRT_TIMER
int up_hrttimer_usleep(unsigned int usec);
#endif
#ifdef CONFIG_DVFS
void lc823450_mtm_start_oneshot(int msec);
void lc823450_mtm_stop_oneshot(void);
#endif
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_ARM_SRC_LC823450_LC823450_TIMER_H */

View File

@ -65,14 +65,6 @@ index 687f50ca..8418eff8 100644
/****************************************************************************
If other deadlocks or ASSERT() still happen, please try the following.
$ cd nuttx; git revert e238c8b0904988b966c3b33e7df2ba3faba52e2b
This will revert the changes for clock_systimer() for 64bit so that it can
use spinlock to protect the internal data. We think that there still exist
race conditions somewhere in SMP logic but the revert might relax the conditions.
Other Status
^^^^^^^^^^^^
@ -281,13 +273,20 @@ By default, DVFS is disabled. To enable,
nsh> echo "enable 1" > /proc/dvfs
In addition, you can change CPU frequency to 160/80/40. To change the
frequency, enable the DVFS first then do the following.
In addition, you can change CPU frequency to 160/80/40 manually.
To change the frequency, enable the DVFS first then do the following.
nsh> echo "cur_freq 80" > /proc/dvfs.
Currently, DVFS works in manual mode and Vdd1 is fixed to 1.2V
which will be changed in the future version.
If you want to run in autonomous mode,
nsh> echo "auto 1" > /proc/dvfs.
In autonomous mode, you don't need to set cur_freq. Instead,
cur_freq will show the current CPU frequency.
NOTE: Currently Vdd1 is fixed to 1.2V which will be changed
in the future version.
TODO
^^^^

View File

@ -106,7 +106,7 @@ CONFIG_RAM_SIZE=1044480
CONFIG_RAM_START=0x02001000
CONFIG_RAW_BINARY=y
CONFIG_READLINE_CMD_HISTORY=y
CONFIG_RTC_DATETIME=y
CONFIG_RTC_HIRES=y
CONFIG_RTC=y
CONFIG_SCHED_ATEXIT=y
CONFIG_SCHED_CHILD_STATUS=y

View File

@ -86,7 +86,6 @@ CONFIG_NET_ROUTE=y
CONFIG_NET_SOCKOPTS=y
CONFIG_NET_STATISTICS=y
CONFIG_NET_TCP_RWND_CONTROL=y
CONFIG_NET_TCP_WRITE_BUFFERS=y
CONFIG_NET_TCP=y
CONFIG_NET_UDP=y
CONFIG_NETUTILS_CODECS=y
@ -142,7 +141,7 @@ CONFIG_RAM_START=0x02001000
CONFIG_RAW_BINARY=y
CONFIG_READLINE_CMD_HISTORY=y
CONFIG_RNDIS=y
CONFIG_RTC_DATETIME=y
CONFIG_RTC_HIRES=y
CONFIG_RTC=y
CONFIG_SCHED_ATEXIT=y
CONFIG_SCHED_CHILD_STATUS=y
@ -153,6 +152,7 @@ CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_INSTRUMENTATION_BUFFER=y
CONFIG_SCHED_INSTRUMENTATION_PREEMPTION=y
CONFIG_SCHED_INSTRUMENTATION=y
CONFIG_SCHED_LPWORKPRIORITY=60
CONFIG_SCHED_LPWORK=y
CONFIG_SCHED_ONEXIT_MAX=32
CONFIG_SCHED_ONEXIT=y