nuttx/arch/arm/src/cxd56xx/cxd56_pmic.c
SPRESENSE d560ce65ff cxd56xx: spresense: Add some improvements and fix bugs for Spresense board
- Add new functions of GNSS
- Support the lower PWM frequency
- Add CONFIG_CPUFREQ_RELEASE_LOCK
- Add high speed ADC support
- Add HPADC input gain configuration
- Add eMMC device
- Frame buffer support
- Fix SD/GNSS/sensor drivers not worked
- Build errors
- Fix nxstyle issues
2020-07-28 09:13:05 +02:00

1592 lines
38 KiB
C

/****************************************************************************
* arch/arm/src/cxd56xx/cxd56_pmic.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 <debug.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <assert.h>
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <nuttx/wqueue.h>
#include <arch/chip/pm.h>
#include "cxd56_pmic.h"
#ifdef CONFIG_CXD56_PMIC
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
enum pmic_cmd_type_e
{
/* basic */
PMIC_CMD_READ = 0x00,
PMIC_CMD_WRITE,
PMIC_CMD_GPO,
PMIC_CMD_LOADSW,
PMIC_CMD_DDCLDO,
PMIC_CMD_INTSTATUS,
PMIC_CMD_SETPREVSYS,
PMIC_CMD_GETPREVSYS,
PMIC_CMD_SETVSYS,
PMIC_CMD_GETVSYS,
/* charger */
PMIC_CMD_GAUGE = 0x10,
PMIC_CMD_GET_USB_PORT_TYPE,
PMIC_CMD_GET_CHG_STATE,
PMIC_CMD_SET_CHG_VOLTAGE,
PMIC_CMD_GET_CHG_VOLTAGE,
PMIC_CMD_SET_CHG_CURRENT,
PMIC_CMD_GET_CHG_CURRENT,
PMIC_CMD_SET_CHG_TEMPERATURE_MODE,
PMIC_CMD_GET_CHG_TEMPERATURE_MODE,
PMIC_CMD_SET_RECHG_VOLTAGE,
PMIC_CMD_GET_RECHG_VOLTAGE,
PMIC_CMD_PRESET_CHG_CURRENT,
PMIC_CMD_CHG_START,
PMIC_CMD_CHG_STOP,
PMIC_CMD_CHG_PAUSE,
PMIC_CMD_CHG_ENABLE,
PMIC_CMD_CHG_DISABLE,
/* power monitor */
PMIC_CMD_POWER_MONITOR_ENABLE = 0x30,
PMIC_CMD_POWER_MONITOR_STATUS,
PMIC_CMD_POWER_MONITOR_SET,
PMIC_CMD_POWER_MONITOR_GET,
PMIC_CMD_AFE,
PMIC_CMD_SET_CHG_IFIN,
PMIC_CMD_GET_CHG_IFIN,
PMIC_CMD_SET_CHG_TEMPERATURE_TABLE,
PMIC_CMD_GET_CHG_TEMPERATURE_TABLE,
};
/* Register CNT_USB2 [1:0] USB_CUR_LIM constants */
#define PMIC_CUR_LIM_2_5MA 0
#define PMIC_CUR_LIM_100MA 1
#define PMIC_CUR_LIM_500MA 2
/* Register CNT_CHG1 [6:5] VO_CHG_DET4 constants */
#define PMIC_CHG_DET_MINUS400 0
#define PMIC_CHG_DET_MINUS350 1
#define PMIC_CHG_DET_MINUS300 2
#define PMIC_CHG_DET_MINUS250 3
/* Register CNT_CHG2 [7:5] SET_CHG_IFIN constants */
#define PMIC_CHG_IFIN_50 0
#define PMIC_CHG_IFIN_40 1
#define PMIC_CHG_IFIN_30 2
#define PMIC_CHG_IFIN_20 3
#define PMIC_CHG_IFIN_10 4
/* RTC Register */
#define PMIC_REG_RTC (0x40)
#define PMIC_REG_RRQ_TIME (0x46)
#define PMIC_REG_RTC_ALM (0x58)
#define PMIC_REG_LRQ_ALM (0x5E)
#define PMIC_REG_RRQ_LRQ_STATUS (0x60)
/* Register RRQ_LRQ_STATUS */
#define RRQ_TIME_STATE (1 << 4)
#define LRQ_TIME_STATE (1 << 3)
#define LRQ_OFST_STATE (1 << 2)
#define LRQ_WU_STATE (1 << 1)
#define LRQ_ALM_STATE (1 << 0)
/****************************************************************************
* Private Types
****************************************************************************/
/* FarAPI interface structures */
struct pmic_afe_s
{
int voltage;
int current;
int temperature;
};
struct pmic_temp_mode_s
{
int low;
int high;
};
extern int fw_pm_pmiccontrol(int cmd, void *arg);
/****************************************************************************
* Private Data
****************************************************************************/
#ifdef CONFIG_CXD56_PMIC_INT
static pmic_notify_t g_pmic_notify[PMIC_NOTIFY_MAX];
static struct work_s g_irqwork;
#endif /* CONFIG_CXD56_PMIC_INT */
/****************************************************************************
* Private Functions
****************************************************************************/
#ifdef CONFIG_CXD56_PMIC_INT
/****************************************************************************
* Name: is_notify_registerd
*
* Description:
* Return whether any notification is registered or not
*
****************************************************************************/
static bool is_notify_registerd(void)
{
int i;
for (i = PMIC_NOTIFY_ALARM; i < PMIC_NOTIFY_MAX; i++)
{
if (g_pmic_notify[i])
{
return true;
}
}
return false;
}
/****************************************************************************
* Name: pmic_int_worker
*
* Description:
* Work queue for pmic interrupt
*
****************************************************************************/
static void pmic_int_worker(void *arg)
{
int i;
uint8_t stat;
irqstate_t flags;
int irq = CXD56_IRQ_PMIC;
/* Get interrupt cause with clear and call the registered callback */
cxd56_pmic_get_interrupt_status(&stat);
for (i = PMIC_NOTIFY_ALARM; i < PMIC_NOTIFY_MAX; i++)
{
if ((stat & (1 << i)) && g_pmic_notify[i])
{
g_pmic_notify[i](arg);
}
}
/* Prevent from the race condition with up_pmic_set_notify() */
flags = enter_critical_section();
/* After processing of each notification, enable the pmic interrupt again */
if (is_notify_registerd())
{
up_enable_irq(irq);
}
leave_critical_section(flags);
}
/****************************************************************************
* Name: pmic_int_handler
*
* Description:
* Interrupt handler for pmic interrupt
*
****************************************************************************/
static int pmic_int_handler(int irq, void *context, void *arg)
{
int ret;
/* Schedule the callback to occur on the low-priority worker thread */
DEBUGASSERT(work_available(&g_irqwork));
ret = work_queue(LPWORK, &g_irqwork, pmic_int_worker, NULL, 0);
if (ret < 0)
{
logerr("ERROR: work_queue failed: %d\n", ret);
}
/* Disable any further pmic interrupts */
up_disable_irq(irq);
return OK;
}
#endif /* CONFIG_CXD56_PMIC_INT */
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: cxd56_pmic_get_interrupt_status
*
* Description:
* Get Raw Interrupt Status register. And furthermore, if status is set,
* then clear the interrupt. Register's description is below:
*
* 7 6 5 4 3 2 1 0
* +---------------+-----+-----+-----+-----+
* | x x x x |VSYS |WKUPL|WKUPS|ALARM| target of status
* +---------------+-----+-----+-----+-----+
*
* Input Parameter:
* status - a pointer to the polled value of interrupt status
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
* status - return the value of interrupt status register
*
****************************************************************************/
int cxd56_pmic_get_interrupt_status(uint8_t *status)
{
return fw_pm_pmiccontrol(PMIC_CMD_INTSTATUS, status);
}
/****************************************************************************
* Name: cxd56_pmic_set_gpo_reg
*
* Description:
* Set GPO register. Register's description is below:
*
* 7 6 5 4 3 2 1 0
* +---+---+---+---+---+---+---+---+
* |CH3|CH2|CH1|CH0|CH3|CH2|CH1|CH0| target of setbit0/clrbit0
* +---+---+---+---+---+---+---+---+
* +---+---+---+---+---+---+---+---+
* |CH7|CH6|CH5|CH4|CH7|CH6|CH5|CH4| target of setbit1/clrbit1
* +---+---+---+---+---+---+---+---+
* |<- 0: Hi-Z ->|<- 0: Low ->|
* |<- 1: Output ->|<- 1: High ->|
*
* Input Parameter:
* setbitX - set bit that 1 is set
* clrbitX - clear bit that 1 is set
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
* setbitX - return the current value of register
*
****************************************************************************/
int cxd56_pmic_set_gpo_reg(uint8_t *setbit0, uint8_t *clrbit0,
uint8_t *setbit1, uint8_t *clrbit1)
{
struct pmic_gpo_arg_s
{
uint8_t *setbit0;
uint8_t *clrbit0;
uint8_t *setbit1;
uint8_t *clrbit1;
}
arg =
{
.setbit0 = setbit0,
.clrbit0 = clrbit0,
.setbit1 = setbit1,
.clrbit1 = clrbit1,
};
return fw_pm_pmiccontrol(PMIC_CMD_GPO, &arg);
}
/****************************************************************************
* Name: cxd56_pmic_set_gpo
*
* Description:
* Set High/Low to the specified GPO channel(s)
*
* Input Parameter:
* chset - GPO Channel number(s)
* value - true if output high, false if output low.
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_set_gpo(uint8_t chset, bool value)
{
uint8_t setbit0 = 0;
uint8_t clrbit0 = 0;
uint8_t setbit1 = 0;
uint8_t clrbit1 = 0;
uint8_t set;
/* Set GPO0~3 */
set = chset & 0xf;
if (set)
{
if (value)
{
setbit0 = (set << 4) | set;
}
else
{
setbit0 = (set << 4);
clrbit0 = set;
}
}
/* Set GPO4~7 */
set = (chset >> 4) & 0xf;
if (set)
{
if (value)
{
setbit1 = (set << 4) | set;
}
else
{
setbit1 = (set << 4);
clrbit1 = set;
}
}
return cxd56_pmic_set_gpo_reg(&setbit0, &clrbit0, &setbit1, &clrbit1);
}
/****************************************************************************
* Name: cxd56_pmic_set_gpo_hiz
*
* Description:
* Set Hi-Z to the specified GPO channel(s)
*
* Input Parameter:
* chset - GPO Channel number(s)
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_set_gpo_hiz(uint8_t chset)
{
uint8_t setbit0 = 0;
uint8_t clrbit0 = 0;
uint8_t setbit1 = 0;
uint8_t clrbit1 = 0;
uint8_t set;
/* Set GPO0~3 */
set = chset & 0xf;
if (set)
{
clrbit0 = (set << 4) | set;
}
/* Set GPO4~7 */
set = (chset >> 4) & 0xf;
if (set)
{
clrbit1 = (set << 4) | set;
}
return cxd56_pmic_set_gpo_reg(&setbit0, &clrbit0, &setbit1, &clrbit1);
}
/****************************************************************************
* Name: cxd56_pmic_get_gpo
*
* Description:
* Get the value from the specified GPO channel(s)
*
* Input Parameter:
* chset : GPO Channel number(s)
*
* Returned Value:
* Return true if all of the specified chset are high. Else, return false
*
****************************************************************************/
bool cxd56_pmic_get_gpo(uint8_t chset)
{
uint8_t setbit0 = 0;
uint8_t clrbit0 = 0;
uint8_t setbit1 = 0;
uint8_t clrbit1 = 0;
uint8_t set;
cxd56_pmic_set_gpo_reg(&setbit0, &clrbit0, &setbit1, &clrbit1);
set = ((setbit1 & 0xf) << 4) | (setbit0 & 0xf);
/* If all of the specified chset is high, return true */
if ((set & chset) == chset)
{
return true;
}
return false;
}
/****************************************************************************
* Name: cxd56_pmic_get_gpo_hiz
*
* Description:
* Get the tristate value from the specified GPO channel(s)
*
* Input Parameter:
* chset : GPO Channel number(s)
*
* Returned Value:
* Return 0(off), 1(on) or -1(HiZ)
*
****************************************************************************/
int cxd56_pmic_get_gpo_hiz(uint8_t chset)
{
uint8_t setbit0 = 0;
uint8_t clrbit0 = 0;
uint8_t setbit1 = 0;
uint8_t clrbit1 = 0;
uint8_t set;
uint8_t hiz;
cxd56_pmic_set_gpo_reg(&setbit0, &clrbit0, &setbit1, &clrbit1);
set = ((setbit1 & 0xf) << 4) | (setbit0 & 0xf);
hiz = ((setbit1) & 0xf0) | ((setbit0 & 0xf0) >> 4);
/* If all of the specified chset is hiz, return -1 */
if ((hiz & chset) != chset)
{
return -1;
}
/* If all of the specified chset is high, return 1 */
if ((set & chset) == chset)
{
return 1;
}
return 0;
}
/****************************************************************************
* Name: cxd56_pmic_set_loadswitch_reg
*
* Description:
* Set LoadSwitch register. Register's description is below:
*
* 7 6 5 4 3 2 1 0
* +---+---+---+---+---+---+---+---+
* | - | - | - |CH4|CH3|CH2| 1 | 1 | target of setbit/clrbit
* +---+---+---+---+---+---+---+---+
* |<- 0: Off->|
* |<- 1: On ->|
*
* Input Parameter:
* setbit - set bit that 1 is set
* clrbit - clear bit that 1 is set
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
* setbit - return the current value of register
*
****************************************************************************/
int cxd56_pmic_set_loadswitch_reg(uint8_t *setbit, uint8_t *clrbit)
{
struct pmic_loadswitch_arg_s
{
uint8_t *setbit;
uint8_t *clrbit;
}
arg =
{
.setbit = setbit,
.clrbit = clrbit,
};
return fw_pm_pmiccontrol(PMIC_CMD_LOADSW, &arg);
}
/****************************************************************************
* Name: cxd56_pmic_set_loadswitch
*
* Description:
* Set On/Off to the specified LoadSwitch channel(s)
*
* Input Parameter:
* chset - LoadSwitch Channel number(s)
* value - true if set on, false if set off.
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_set_loadswitch(uint8_t chset, bool value)
{
uint8_t setbit = 0;
uint8_t clrbit = 0;
if (value)
{
setbit = chset;
}
else
{
clrbit = chset;
}
return cxd56_pmic_set_loadswitch_reg(&setbit, &clrbit);
}
/****************************************************************************
* Name: cxd56_pmic_get_loadswitch
*
* Description:
* Get the value from the specified LoadSwitch channel(s)
*
* Input Parameter:
* chset - LoadSwitch Channel number(s)
*
* Returned Value:
* Return true if all of the specified chset are on.
* Otherwise, return false
*
****************************************************************************/
bool cxd56_pmic_get_loadswitch(uint8_t chset)
{
uint8_t setbit = 0;
uint8_t clrbit = 0;
cxd56_pmic_set_loadswitch_reg(&setbit, &clrbit);
return ((setbit & chset) == chset);
}
/****************************************************************************
* Name: cxd56_pmic_set_ddc_ldo_reg
*
* Description:
* Set DDC/LDO register. Register's description is below:
*
* 7 6 5 4 3 2 1 0
* +----+----+----+----+----+----+----+----+
* | | |LDO |DDC |LDO |DDC |LDO |DDC | target of setbit/clrbit
* | - | - |PERI|CORE|ANA |ANA |EMMC|IO |
* +----+----+----+----+----+----+----+----+
* |<- 0: Off ->|
* |<- 1: On ->|
*
* Input Parameter:
* setbit - set bit that 1 is set
* clrbit - clear bit that 1 is set
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
* setbit - return the current value of register
*
****************************************************************************/
int cxd56_pmic_set_ddc_ldo_reg(uint8_t *setbit, uint8_t *clrbit)
{
struct pmic_ddc_ldo_arg_s
{
uint8_t *setbit;
uint8_t *clrbit;
}
arg =
{
.setbit = setbit,
.clrbit = clrbit,
};
return fw_pm_pmiccontrol(PMIC_CMD_DDCLDO, &arg);
}
/****************************************************************************
* Name: cxd56_pmic_set_ddc_ldo
*
* Description:
* Set On/Off to the specified DDC/LDO channel(s)
*
* Input Parameter:
* chset - DDC/LO Channel number(s)
* value - true if set on, false if set off.
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_set_ddc_ldo(uint8_t chset, bool value)
{
uint8_t setbit = 0;
uint8_t clrbit = 0;
if (value)
{
setbit = chset;
}
else
{
clrbit = chset;
}
return cxd56_pmic_set_ddc_ldo_reg(&setbit, &clrbit);
}
/****************************************************************************
* Name: cxd56_pmic_get_ddc_ldo
*
* Description:
* Get the value from the specified DDC/LDO channel(s)
*
* Input Parameter:
* chset - DDC/LDO Channel number(s)
*
* Returned Value:
* Return true if all of the specified chset are on.
* Otherwise, return false
*
****************************************************************************/
bool cxd56_pmic_get_ddc_ldo(uint8_t chset)
{
uint8_t setbit = 0;
uint8_t clrbit = 0;
cxd56_pmic_set_ddc_ldo_reg(&setbit, &clrbit);
return ((setbit & chset) == chset);
}
/****************************************************************************
* Name: cxd56_pmic_get_rtc
*
* Description:
* Get the RTC value from PMIC
*
* Input Parameter:
* count - the pointer to the returned RTC counter value
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_get_rtc(uint64_t *count)
{
int ret = 0;
uint8_t data;
uint8_t rtc[6];
if (!count) return -EINVAL;
data = 0x1;
ret = cxd56_pmic_write(PMIC_REG_RRQ_TIME, &data, sizeof(data));
if (ret) goto error;
do
{
ret = cxd56_pmic_read(PMIC_REG_RRQ_LRQ_STATUS, &data, sizeof(data));
if (ret) goto error;
}
while (!(RRQ_TIME_STATE & data));
ret = cxd56_pmic_read(PMIC_REG_RTC, rtc, sizeof(rtc));
if (ret) goto error;
*count =
(((uint64_t)((rtc[5] << 24) | (rtc[4] << 16) | (rtc[3] << 8) |
rtc[2]) << 15) | ((rtc[1] << 8) | rtc[0]));
error:
return ret;
}
/****************************************************************************
* Name: cxd56_pmic_get_gauge
*
* Description:
* Get the set of values (voltage, current and temperature) from PMIC.
*
* Input Parameter:
* gauge - Set of gauge related values
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_get_gauge(FAR struct pmic_gauge_s *gauge)
{
return fw_pm_pmiccontrol(PMIC_CMD_AFE, gauge);
}
/****************************************************************************
* Name: cxd56_pmic_getlowervol
*
* Description:
* Get lower limit of voltage for system to be running.
*
* Input Parameter:
* voltage - Lower limit voltage (mv)
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_getlowervol(FAR int *voltage)
{
return fw_pm_pmiccontrol(PMIC_CMD_GETVSYS, voltage);
}
/****************************************************************************
* Name: cxd56_pmic_setlowervol
*
* Description:
* Set lower limit of voltage for system to be running.
*
* Input Parameter:
* voltage - Lower limit voltage (mv)
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_setlowervol(int voltage)
{
return fw_pm_pmiccontrol(PMIC_CMD_SETVSYS, (void *)voltage);
}
/****************************************************************************
* Name: cxd56_pmic_getnotifyvol
*
* Description:
* Get voltage for the low battery notification
*
* Input Parameter:
* voltage - Low battery voltage (mv)
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_getnotifyvol(FAR int *voltage)
{
return fw_pm_pmiccontrol(PMIC_CMD_GETPREVSYS, voltage);
}
/****************************************************************************
* Name: cxd56_pmic_setnotifyvol
*
* Description:
* Set voltage for the low battery notification
*
* Input Parameter:
* voltage - Low battery voltage (mv)
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_setnotifyvol(int voltage)
{
return fw_pm_pmiccontrol(PMIC_CMD_SETPREVSYS, (void *)voltage);
}
/****************************************************************************
* Name: cxd56_pmic_getchargevol
*
* Description:
* Get charge voltage
*
* Input Parameter:
* voltage - Possible values are every 50 between 4000 to 4400 (mv)
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_getchargevol(FAR int *voltage)
{
int val;
int ret;
ret = fw_pm_pmiccontrol(PMIC_CMD_GET_CHG_VOLTAGE, &val);
if (ret)
{
return -EIO;
}
val &= 0xf;
/* Convert register value to actual voltage (mv) */
if (val <= 8)
{
*voltage = 4000 + (val * 50);
}
else
{
*voltage = 4200;
}
return OK;
}
/****************************************************************************
* Name: cxd56_pmic_setchargevol
*
* Description:
* Set charge voltage
*
* Input Parameter:
* voltage - Available values are every 50 between 4000 to 4400 (mv)
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_setchargevol(int voltage)
{
int val;
/* Sanity check */
if (voltage < 4000 || voltage > 4400)
{
return -EINVAL;
}
if (voltage % 50)
{
return -EINVAL;
}
/* Register setting values are every 50mv between 4.0V to 4.4V */
val = (voltage - 4000) / 50;
return fw_pm_pmiccontrol(PMIC_CMD_SET_CHG_VOLTAGE, (void *)val);
}
/****************************************************************************
* Name: cxd56_pmic_getchargecurrent
*
* Description:
* Get charge current value
*
* Input Parameter:
* current - Possible values are 2, 100 and 500 (mA). However,
* 2 means 2.5 mA actually.
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_getchargecurrent(FAR int *current)
{
int val;
int ret;
ret = fw_pm_pmiccontrol(PMIC_CMD_GET_CHG_CURRENT, &val);
if (ret)
{
return ret;
}
/* Convert register value to current */
switch (val & 0x3)
{
case PMIC_CUR_LIM_2_5MA:
*current = 2;
break;
case PMIC_CUR_LIM_100MA:
*current = 100;
break;
case PMIC_CUR_LIM_500MA:
*current = 500;
break;
default:
return -EFAULT;
}
return OK;
}
/****************************************************************************
* Name: cxd56_pmic_setchargecurrent
*
* Description:
* Set charge current value
*
* Input Parameter:
* current - Available values are 2, 100 and 500 (mA). However, 2 means
* 2.5 mA actually.
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_setchargecurrent(int current)
{
int val;
/* Replace current values for CNT_USB2 [1:0] USB_CUR_LIM */
switch (current)
{
case 2:
val = PMIC_CUR_LIM_2_5MA;
break;
case 100:
val = PMIC_CUR_LIM_100MA;
break;
case 500:
val = PMIC_CUR_LIM_500MA;
break;
default:
return -EFAULT;
}
return fw_pm_pmiccontrol(PMIC_CMD_SET_CHG_CURRENT, (void *)val);
}
/****************************************************************************
* Name: cxd56_pmic_getporttype
*
* Description:
* Get USB port type
*
* Input Parameter:
* porttype - PMIC_PORTTYPE_SDP or PMIC_PORTTYPE_DCPCDP
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_getporttype(FAR int *porttype)
{
return fw_pm_pmiccontrol(PMIC_CMD_GET_USB_PORT_TYPE, porttype);
}
/****************************************************************************
* Name: cxd56_pmic_getchargestate
*
* Description:
* Read charging status
*
* Input Parameter:
* state - Charging status (see PMIC_STAT_* definitions)
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_getchargestate(uint8_t *state)
{
struct pmic_afe_s arg;
int val;
int ret;
/* Update charge state */
ret = fw_pm_pmiccontrol(PMIC_CMD_AFE, &arg);
if (ret)
{
return ret;
}
/* Get actual charging state (CNT_USB1) */
ret = fw_pm_pmiccontrol(PMIC_CMD_GET_CHG_STATE, &val);
*state = val & 0xff;
return ret;
}
/****************************************************************************
* Name: cxd56_pmic_setrechargevol
*
* Description:
* Set threshold voltage against full charge for automatic restart
* charging.
*
* Input Parameter:
* mv - Available values are -400, -350, -300 and -250 (mv)
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_setrechargevol(int mv)
{
int val;
/* Convert voltage to register value */
switch (mv)
{
case -400:
val = PMIC_CHG_DET_MINUS400;
break;
case -350:
val = PMIC_CHG_DET_MINUS350;
break;
case -300:
val = PMIC_CHG_DET_MINUS300;
break;
case -250:
val = PMIC_CHG_DET_MINUS250;
break;
default:
return -EINVAL;
}
return fw_pm_pmiccontrol(PMIC_CMD_SET_RECHG_VOLTAGE, (void *)val);
}
/****************************************************************************
* Name: cxd56_pmic_getrechargevol
*
* Description:
* Get threshold voltage against full charge for automatic restart
* charging.
*
* Input Parameter:
* mv - Possible values are -400, -350, -300 and -250 (mv)
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_getrechargevol(FAR int *mv)
{
int val;
int ret;
ret = fw_pm_pmiccontrol(PMIC_CMD_GET_RECHG_VOLTAGE, &val);
if (ret)
{
return ret;
}
/* Convert register value to voltage */
switch (val)
{
case PMIC_CHG_DET_MINUS400:
*mv = -400;
break;
case PMIC_CHG_DET_MINUS350:
*mv = -350;
break;
case PMIC_CHG_DET_MINUS300:
*mv = -300;
break;
case PMIC_CHG_DET_MINUS250:
*mv = -250;
break;
default:
return -EINVAL;
}
return OK;
}
/****************************************************************************
* Name: cxd56_pmic_setchargecompcurrent
*
* Description:
* Set current value setting for determine fully charged.
*
* Input Parameter:
* current - Possible values are 50, 40, 30, 20 and 10 (mA)
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_setchargecompcurrent(int current)
{
int val;
/* Convert current (mA) to register value */
switch (current)
{
case 50:
val = PMIC_CHG_IFIN_50;
break;
case 40:
val = PMIC_CHG_IFIN_40;
break;
case 30:
val = PMIC_CHG_IFIN_30;
break;
case 20:
val = PMIC_CHG_IFIN_20;
break;
case 10:
val = PMIC_CHG_IFIN_10;
break;
default:
return -EINVAL;
break;
}
return fw_pm_pmiccontrol(PMIC_CMD_SET_CHG_IFIN, (void *)val);
}
/****************************************************************************
* Name: cxd56_pmic_getchargecompcurrent
*
* Description:
* Get current value setting for determine fully charged.
*
* Input Parameter:
* current - Available values are 50, 40, 30, 20 and 10 (mA)
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_getchargecompcurrent(FAR int *current)
{
int val;
int ret;
ret = fw_pm_pmiccontrol(PMIC_CMD_GET_CHG_IFIN, &val);
if (ret)
{
return ret;
}
/* Convert register value to current (mA) */
switch (val)
{
case PMIC_CHG_IFIN_50:
*current = 50;
break;
case PMIC_CHG_IFIN_40:
*current = 40;
break;
case PMIC_CHG_IFIN_30:
*current = 30;
break;
case PMIC_CHG_IFIN_20:
*current = 20;
break;
case PMIC_CHG_IFIN_10:
*current = 10;
break;
default:
*current = 0;
ret = -EFAULT;
break;
}
return ret;
}
/****************************************************************************
* Name: cxd56_pmic_gettemptable
*
* Description:
* Get temperature detect resistance table
*
* Input Parameter:
* table - Settings values for temperature detecting (see CXD5247GF
* specification for more detail)
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_gettemptable(FAR struct pmic_temp_table_s *table)
{
/* SET_T60 (70h) - SET_T0_2 (78h) */
return fw_pm_pmiccontrol(PMIC_CMD_GET_CHG_TEMPERATURE_TABLE, table);
}
/****************************************************************************
* Name: cxd56_pmic_settemptable
*
* Description:
* Set temperature detect resistance table
*
* Input Parameter:
* table - Settings values for temperature detecting (see CXD5247GF
* specification for more detail)
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_settemptable(FAR struct pmic_temp_table_s *table)
{
return fw_pm_pmiccontrol(PMIC_CMD_SET_CHG_TEMPERATURE_TABLE, table);
}
/****************************************************************************
* Name: cxd56_pmic_setchargemode
*
* Description:
* Set charging mode in each low/high temperatures.
* In lower than 10 degrees Celsius, charging mode will be changed on/off
* and weak (half of charge current) according to setting.
* In higher than 45 degrees Celsius, charging mode will be charged on/off
* and weak (-0.15V from charge voltage) according to setting.
*
* Input Parameter:
* low - Charging mode in low temperature (see PMIC_CHGMODE_*)
* high - Charging mode in high temperature (see PMIC_CHGMODE_*)
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_setchargemode(int low, int high)
{
struct pmic_temp_mode_s arg;
/* CNT_CHG3
* [3:2] SEL_CHG_THL: <-> low
* [1:0] SEL_CHG_THH: <-> high
*/
/* Sanity check */
if (low == PMIC_CHGMODE_ON || low == PMIC_CHGMODE_OFF ||
low == PMIC_CHGMODE_WEAK)
{
arg.low = low;
}
else
{
return -EINVAL;
}
if (high == PMIC_CHGMODE_ON || high == PMIC_CHGMODE_OFF ||
high == PMIC_CHGMODE_WEAK)
{
arg.high = high;
}
else
{
return -EINVAL;
}
return fw_pm_pmiccontrol(PMIC_CMD_SET_CHG_TEMPERATURE_MODE, &arg);
}
/****************************************************************************
* Name: cxd56_pmic_getchargemode
*
* Description:
* Get charging mode in each low/high temperatures.
* In lower than 10 degrees Celsius, charging mode will be changed on/off
* and weak (half of charge current) according to setting.
* In higher than 45 degrees Celsius, charging mode will be charged on/off
* and weak (-0.15V from charge voltage) according to setting.
*
* Input Parameter:
* low - Charging mode in low temperature (see PMIC_CHG_*)
* high - Charging mode in high temperature (see PMIC_CHG_*)
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_getchargemode(FAR int *low, FAR int *high)
{
struct pmic_temp_mode_s arg;
int ret;
ret = fw_pm_pmiccontrol(PMIC_CMD_GET_CHG_TEMPERATURE_MODE, &arg);
if (ret)
{
return ret;
}
*low = arg.low;
*high = arg.high;
return OK;
}
#ifdef CONFIG_CXD56_PMIC_BATMONITOR
/****************************************************************************
* Battery monitor for debug
****************************************************************************/
int cxd56_pmic_monitor_enable(FAR struct pmic_mon_s *ptr)
{
return fw_pm_pmiccontrol(PMIC_CMD_POWER_MONITOR_ENABLE, ptr);
}
int cxd56_pmic_monitor_status(FAR struct pmic_mon_status_s *ptr)
{
return fw_pm_pmiccontrol(PMIC_CMD_POWER_MONITOR_STATUS, ptr);
}
int cxd56_pmic_monitor_set(FAR struct pmic_mon_set_s *ptr)
{
return fw_pm_pmiccontrol(PMIC_CMD_POWER_MONITOR_SET, ptr);
}
int cxd56_pmic_monitor_get(FAR struct pmic_mon_log_s *ptr)
{
return fw_pm_pmiccontrol(PMIC_CMD_POWER_MONITOR_GET, ptr);
}
#endif
#ifdef CONFIG_CXD56_PMIC_INT
/****************************************************************************
* Name: up_pmic_set_notify
*
* Description:
* Register a callback for pmic interrupt
*
* Input Parameter:
* kind - A kind of pmic interrupt defined as pmic_notify_e
* cb - A callback function for a kind of pmic interrupt
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int up_pmic_set_notify(int kind, pmic_notify_t cb)
{
static int is_first = 1;
irqstate_t flags;
int irq = CXD56_IRQ_PMIC;
int delayed_work = 0;
if ((kind < PMIC_NOTIFY_ALARM) || (PMIC_NOTIFY_MAX <= kind))
{
return -EINVAL;
}
/* attach interrupt handler only for the first time */
if (is_first)
{
irq_attach(irq, pmic_int_handler, NULL);
is_first = 0;
}
flags = enter_critical_section();
g_pmic_notify[kind] = cb;
if (is_notify_registerd())
{
/* If up_enable_irq() is called when interrupt is pending,
* an assertion may occur because workqueue is not prepared yet.
* As the workaround, call worker directly and in the worker
* both interrupt clear and enable processing are performed.
*/
delayed_work = 1;
}
else
{
up_disable_irq(irq);
}
leave_critical_section(flags);
if (delayed_work)
{
pmic_int_worker(NULL);
}
return 0;
}
#endif /* CONFIG_CXD56_PMIC_INT */
/****************************************************************************
* Name: cxd56_pmic_read
*
* Description:
* Read the value from the specified sub address
*
* Input Parameter:
* addr - sub address
* buf - pointer to read buffer
* size - byte count of read
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_read(uint8_t addr, void *buf, uint32_t size)
{
struct pmic_trans_arg_s
{
uint8_t addr;
void *buf;
uint32_t size;
}
arg =
{
.addr = addr,
.buf = buf,
.size = size,
};
return fw_pm_pmiccontrol(PMIC_CMD_READ, &arg);
}
/****************************************************************************
* Name: cxd56_pmic_write
*
* Description:
* Write the value to the specified sub address
*
* Input Parameter:
* addr - sub address
* buf - pointer to write buffer
* size - byte count of write
*
* Returned Value:
* Return 0 on success. Otherwise, return a negated errno.
*
****************************************************************************/
int cxd56_pmic_write(uint8_t addr, void *buf, uint32_t size)
{
struct pmic_trans_arg_s
{
uint8_t addr;
void *buf;
uint32_t size;
}
arg =
{
.addr = addr,
.buf = buf,
.size = size,
};
return fw_pm_pmiccontrol(PMIC_CMD_WRITE, &arg);
}
#endif /* CONFIG_CXD56_PMIC */