037c9ea0a4
Summary The naming standard at https://cwiki.apache.org/confluence/display/NUTTX/Naming+FAQ requires that all MCU-private files begin with the name of the architecture, not up_. This PR addresses only these name changes for the up_*.h files. There are only three, but almost 1680 files that include them: up_arch.h up_internal.h up_vfork.h The only change to the files is from including up_arch.h to arm_arch.h (for example). The entire job required to be compatible with that Naming Convention will also require changing the naming of the up_() functions that are used only within arch/arm and board/arm. Impact There should be not impact of this change (other that one step toward more consistent naming). Testing stm32f4discovery:netnsh
826 lines
24 KiB
C
826 lines
24 KiB
C
/****************************************************************************
|
|
* 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.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#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 "arm_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 Prototypes
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* 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 Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* 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;
|
|
}
|