You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
631 lines
18 KiB
631 lines
18 KiB
/*
|
|
* Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <common/debug.h>
|
|
#include <lib/mmio.h>
|
|
#include <lib/utils_def.h>
|
|
|
|
#include "avs_driver.h"
|
|
#include "cpg_registers.h"
|
|
#include "rcar_def.h"
|
|
#include "rcar_private.h"
|
|
|
|
#if (AVS_SETTING_ENABLE == 1)
|
|
#if PMIC_ROHM_BD9571
|
|
/* Read PMIC register for debug. 1:enable / 0:disable */
|
|
#define AVS_READ_PMIC_REG_ENABLE 0
|
|
/* The re-try number of times of the AVS setting. */
|
|
#define AVS_RETRY_NUM (1U)
|
|
#endif /* PMIC_ROHM_BD9571 */
|
|
|
|
/* Base address of Adaptive Voltage Scaling module registers*/
|
|
#define AVS_BASE (0xE60A0000U)
|
|
/* Adaptive Dynamic Voltage ADJust Parameter2 registers */
|
|
#define ADVADJP2 (AVS_BASE + 0x013CU)
|
|
|
|
/* Mask VOLCOND bit in ADVADJP2 registers */
|
|
#define ADVADJP2_VOLCOND_MASK (0x000001FFU) /* VOLCOND[8:0] */
|
|
|
|
#if PMIC_ROHM_BD9571
|
|
/* I2C for DVFS bit in CPG registers for module standby and software reset*/
|
|
#define CPG_SYS_DVFS_BIT (0x04000000U)
|
|
#endif /* PMIC_ROHM_BD9571 */
|
|
/* ADVFS Module bit in CPG registers for module standby and software reset*/
|
|
#define CPG_SYS_ADVFS_BIT (0x02000000U)
|
|
|
|
#if PMIC_ROHM_BD9571
|
|
/* Base address of IICDVFS registers*/
|
|
#define IIC_DVFS_BASE (0xE60B0000U)
|
|
/* IIC bus data register */
|
|
#define IIC_ICDR (IIC_DVFS_BASE + 0x0000U)
|
|
/* IIC bus control register */
|
|
#define IIC_ICCR (IIC_DVFS_BASE + 0x0004U)
|
|
/* IIC bus status register */
|
|
#define IIC_ICSR (IIC_DVFS_BASE + 0x0008U)
|
|
/* IIC interrupt control register */
|
|
#define IIC_ICIC (IIC_DVFS_BASE + 0x000CU)
|
|
/* IIC clock control register low */
|
|
#define IIC_ICCL (IIC_DVFS_BASE + 0x0010U)
|
|
/* IIC clock control register high */
|
|
#define IIC_ICCH (IIC_DVFS_BASE + 0x0014U)
|
|
|
|
/* Bit in ICSR register */
|
|
#define ICSR_BUSY (0x10U)
|
|
#define ICSR_AL (0x08U)
|
|
#define ICSR_TACK (0x04U)
|
|
#define ICSR_WAIT (0x02U)
|
|
#define ICSR_DTE (0x01U)
|
|
|
|
/* Bit in ICIC register */
|
|
#define ICIC_TACKE (0x04U)
|
|
#define ICIC_WAITE (0x02U)
|
|
#define ICIC_DTEE (0x01U)
|
|
|
|
/* I2C bus interface enable */
|
|
#define ICCR_ENABLE (0x80U)
|
|
/* Start condition */
|
|
#define ICCR_START (0x94U)
|
|
/* Stop condition */
|
|
#define ICCR_STOP (0x90U)
|
|
/* Restart condition with change to receive mode change */
|
|
#define ICCR_START_RECV (0x81U)
|
|
/* Stop condition for receive mode */
|
|
#define ICCR_STOP_RECV (0xC0U)
|
|
|
|
/* Low-level period of SCL */
|
|
#define ICCL_FREQ_8p33M (0x07U) /* for CP Phy 8.3333MHz */
|
|
#define ICCL_FREQ_10M (0x09U) /* for CP Phy 10MHz */
|
|
#define ICCL_FREQ_12p5M (0x0BU) /* for CP Phy 12.5MHz */
|
|
#define ICCL_FREQ_16p66M (0x0EU) /* for CP Phy 16.6666MHz */
|
|
/* High-level period of SCL */
|
|
#define ICCH_FREQ_8p33M (0x01U) /* for CP Phy 8.3333MHz */
|
|
#define ICCH_FREQ_10M (0x02U) /* for CP Phy 10MHz */
|
|
#define ICCH_FREQ_12p5M (0x03U) /* for CP Phy 12.5MHz */
|
|
#define ICCH_FREQ_16p66M (0x05U) /* for CP Phy 16.6666MHz */
|
|
|
|
/* PMIC */
|
|
/* ROHM BD9571 slave address + (W) */
|
|
#define PMIC_W_SLAVE_ADDRESS (0x60U)
|
|
/* ROHM BD9571 slave address + (R) */
|
|
#define PMIC_R_SLAVE_ADDRESS (0x61U)
|
|
/* ROHM BD9571 DVFS SetVID register */
|
|
#define PMIC_DVFS_SETVID (0x54U)
|
|
#endif /* PMIC_ROHM_BD9571 */
|
|
|
|
/* Individual information */
|
|
#define EFUSE_AVS0 (0U)
|
|
#define EFUSE_AVS_NUM ARRAY_SIZE(init_vol_tbl)
|
|
|
|
typedef struct {
|
|
uint32_t avs; /* AVS code */
|
|
uint8_t vol; /* Voltage */
|
|
} initial_voltage_t;
|
|
|
|
static const initial_voltage_t init_vol_tbl[] = {
|
|
/* AVS code, ROHM BD9571 DVFS SetVID register */
|
|
{0x00U, 0x53U}, /* AVS0, 0.83V */
|
|
{0x01U, 0x52U}, /* AVS1, 0.82V */
|
|
{0x02U, 0x51U}, /* AVS2, 0.81V */
|
|
{0x04U, 0x50U}, /* AVS3, 0.80V */
|
|
{0x08U, 0x4FU}, /* AVS4, 0.79V */
|
|
{0x10U, 0x4EU}, /* AVS5, 0.78V */
|
|
{0x20U, 0x4DU}, /* AVS6, 0.77V */
|
|
{0x40U, 0x4CU} /* AVS7, 0.76V */
|
|
};
|
|
|
|
#if PMIC_ROHM_BD9571
|
|
/* Kind of AVS settings status */
|
|
typedef enum {
|
|
avs_status_none = 0,
|
|
avs_status_init,
|
|
avs_status_start_condition,
|
|
avs_status_set_slave_addr,
|
|
avs_status_write_reg_addr,
|
|
avs_status_write_reg_data,
|
|
avs_status_stop_condition,
|
|
avs_status_end,
|
|
avs_status_complete,
|
|
avs_status_al_start,
|
|
avs_status_al_transfer,
|
|
avs_status_nack,
|
|
avs_status_error_stop,
|
|
ave_status_error_end
|
|
} avs_status_t;
|
|
|
|
/* Kind of AVS error */
|
|
typedef enum {
|
|
avs_error_none = 0,
|
|
avs_error_al,
|
|
avs_error_nack
|
|
} avs_error_t;
|
|
|
|
static avs_status_t avs_status;
|
|
static uint32_t avs_retry;
|
|
#endif /* PMIC_ROHM_BD9571 */
|
|
static uint32_t efuse_avs = EFUSE_AVS0;
|
|
|
|
#if PMIC_ROHM_BD9571
|
|
/* prototype */
|
|
static avs_error_t avs_check_error(void);
|
|
static void avs_set_iic_clock(void);
|
|
#if AVS_READ_PMIC_REG_ENABLE == 1
|
|
static uint8_t avs_read_pmic_reg(uint8_t addr);
|
|
static void avs_poll(uint8_t bit_pos, uint8_t val);
|
|
#endif
|
|
#endif /* PMIC_ROHM_BD9571 */
|
|
#endif /* (AVS_SETTING_ENABLE==1) */
|
|
|
|
/*
|
|
* Initialize to enable the AVS setting.
|
|
*/
|
|
void rcar_avs_init(void)
|
|
{
|
|
#if (AVS_SETTING_ENABLE == 1)
|
|
uint32_t val;
|
|
|
|
#if PMIC_ROHM_BD9571
|
|
/* Initialize AVS status */
|
|
avs_status = avs_status_init;
|
|
#endif /* PMIC_ROHM_BD9571 */
|
|
|
|
/* Enable clock supply to ADVFS. */
|
|
mstpcr_write(CPG_SMSTPCR9, CPG_MSTPSR9, CPG_SYS_ADVFS_BIT);
|
|
|
|
/* Read AVS code (Initial values are derived from eFuse) */
|
|
val = mmio_read_32(ADVADJP2) & ADVADJP2_VOLCOND_MASK;
|
|
|
|
for (efuse_avs = 0U; efuse_avs < EFUSE_AVS_NUM; efuse_avs++) {
|
|
if (val == init_vol_tbl[efuse_avs].avs)
|
|
break;
|
|
}
|
|
|
|
if (efuse_avs >= EFUSE_AVS_NUM)
|
|
efuse_avs = EFUSE_AVS0; /* Not applicable */
|
|
#if PMIC_ROHM_BD9571
|
|
/* Enable clock supply to DVFS. */
|
|
mstpcr_write(CPG_SMSTPCR9, CPG_MSTPSR9, CPG_SYS_DVFS_BIT);
|
|
|
|
/* Disable I2C module and All internal registers initialized. */
|
|
mmio_write_8(IIC_ICCR, 0x00U);
|
|
while ((mmio_read_8(IIC_ICCR) & ICCR_ENABLE) != 0U) {
|
|
/* Disable I2C module and all internal registers initialized. */
|
|
mmio_write_8(IIC_ICCR, 0x00U);
|
|
}
|
|
|
|
/* Set next status */
|
|
avs_status = avs_status_start_condition;
|
|
|
|
#endif /* PMIC_ROHM_BD9571 */
|
|
#endif /* (AVS_SETTING_ENABLE==1) */
|
|
}
|
|
|
|
/*
|
|
* Set the value of register corresponding to the voltage
|
|
* by transfer of I2C to PIMC.
|
|
*/
|
|
void rcar_avs_setting(void)
|
|
{
|
|
#if (AVS_SETTING_ENABLE == 1)
|
|
#if PMIC_ROHM_BD9571
|
|
avs_error_t err;
|
|
|
|
switch (avs_status) {
|
|
case avs_status_start_condition:
|
|
/* Set ICCR.ICE=1 to activate the I2C module. */
|
|
mmio_write_8(IIC_ICCR, mmio_read_8(IIC_ICCR) | ICCR_ENABLE);
|
|
/* Set frequency of 400kHz */
|
|
avs_set_iic_clock();
|
|
/* Set ICIC.TACKE=1, ICIC.WAITE=1, ICIC.DTEE=1 to */
|
|
/* enable interrupt control. */
|
|
mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC)
|
|
| ICIC_TACKE | ICIC_WAITE | ICIC_DTEE);
|
|
/* Write H'94 in ICCR to issue start condition */
|
|
mmio_write_8(IIC_ICCR, ICCR_START);
|
|
/* Set next status */
|
|
avs_status = avs_status_set_slave_addr;
|
|
break;
|
|
case avs_status_set_slave_addr:
|
|
/* Check error. */
|
|
err = avs_check_error();
|
|
if (err == avs_error_al) {
|
|
/* Recovery sequence of just after start. */
|
|
avs_status = avs_status_al_start;
|
|
} else if (err == avs_error_nack) {
|
|
/* Recovery sequence of detected NACK */
|
|
avs_status = avs_status_nack;
|
|
} else {
|
|
/* Was data transmission enabled ? */
|
|
if ((mmio_read_8(IIC_ICSR) & ICSR_DTE) == ICSR_DTE) {
|
|
/* Clear ICIC.DTEE to disable a DTE interrupt */
|
|
mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC)
|
|
& (uint8_t) (~ICIC_DTEE));
|
|
/* Send PMIC slave address + (W) */
|
|
mmio_write_8(IIC_ICDR, PMIC_W_SLAVE_ADDRESS);
|
|
/* Set next status */
|
|
avs_status = avs_status_write_reg_addr;
|
|
}
|
|
}
|
|
break;
|
|
case avs_status_write_reg_addr:
|
|
/* Check error. */
|
|
err = avs_check_error();
|
|
if (err == avs_error_al) {
|
|
/* Recovery sequence of during data transfer. */
|
|
avs_status = avs_status_al_transfer;
|
|
} else if (err == avs_error_nack) {
|
|
/* Recovery sequence of detected NACK */
|
|
avs_status = avs_status_nack;
|
|
} else {
|
|
/* If wait state after data transmission. */
|
|
if ((mmio_read_8(IIC_ICSR) & ICSR_WAIT) == ICSR_WAIT) {
|
|
/* Write PMIC DVFS_SetVID address */
|
|
mmio_write_8(IIC_ICDR, PMIC_DVFS_SETVID);
|
|
/* Clear ICSR.WAIT to exit from wait state. */
|
|
mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR)
|
|
& (uint8_t) (~ICSR_WAIT));
|
|
/* Set next status */
|
|
avs_status = avs_status_write_reg_data;
|
|
}
|
|
}
|
|
break;
|
|
case avs_status_write_reg_data:
|
|
/* Check error. */
|
|
err = avs_check_error();
|
|
if (err == avs_error_al) {
|
|
/* Recovery sequence of during data transfer. */
|
|
avs_status = avs_status_al_transfer;
|
|
} else if (err == avs_error_nack) {
|
|
/* Recovery sequence of detected NACK */
|
|
avs_status = avs_status_nack;
|
|
} else {
|
|
/* If wait state after data transmission. */
|
|
if ((mmio_read_8(IIC_ICSR) & ICSR_WAIT) == ICSR_WAIT) {
|
|
/* Dose efuse_avs exceed the number of */
|
|
/* the tables? */
|
|
if (efuse_avs >= EFUSE_AVS_NUM) {
|
|
ERROR("%s%s=%u\n", "AVS number of ",
|
|
"eFuse is out of range. number",
|
|
efuse_avs);
|
|
/* Infinite loop */
|
|
panic();
|
|
}
|
|
/* Write PMIC DVFS_SetVID value */
|
|
mmio_write_8(IIC_ICDR,
|
|
init_vol_tbl[efuse_avs].vol);
|
|
/* Clear ICSR.WAIT to exit from wait state. */
|
|
mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR)
|
|
& (uint8_t) (~ICSR_WAIT));
|
|
/* Set next status */
|
|
avs_status = avs_status_stop_condition;
|
|
}
|
|
}
|
|
break;
|
|
case avs_status_stop_condition:
|
|
err = avs_check_error();
|
|
if (err == avs_error_al) {
|
|
/* Recovery sequence of during data transfer. */
|
|
avs_status = avs_status_al_transfer;
|
|
} else if (err == avs_error_nack) {
|
|
/* Recovery sequence of detected NACK */
|
|
avs_status = avs_status_nack;
|
|
} else {
|
|
/* If wait state after data transmission. */
|
|
if ((mmio_read_8(IIC_ICSR) & ICSR_WAIT) == ICSR_WAIT) {
|
|
/* Write H'90 in ICCR to issue stop condition */
|
|
mmio_write_8(IIC_ICCR, ICCR_STOP);
|
|
/* Clear ICSR.WAIT to exit from wait state. */
|
|
mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR)
|
|
& (uint8_t) (~ICSR_WAIT));
|
|
/* Set next status */
|
|
avs_status = avs_status_end;
|
|
}
|
|
}
|
|
break;
|
|
case avs_status_end:
|
|
/* Is this module not busy?. */
|
|
if ((mmio_read_8(IIC_ICSR) & ICSR_BUSY) == 0U) {
|
|
/* Set ICCR=H'00 to disable the I2C module. */
|
|
mmio_write_8(IIC_ICCR, 0x00U);
|
|
/* Set next status */
|
|
avs_status = avs_status_complete;
|
|
}
|
|
break;
|
|
case avs_status_al_start:
|
|
/* Clear ICSR.AL bit */
|
|
mmio_write_8(IIC_ICSR, (mmio_read_8(IIC_ICSR)
|
|
& (uint8_t) (~ICSR_AL)));
|
|
/* Transmit a clock pulse */
|
|
mmio_write_8(IIC_ICDR, init_vol_tbl[EFUSE_AVS0].vol);
|
|
/* Set next status */
|
|
avs_status = avs_status_error_stop;
|
|
break;
|
|
case avs_status_al_transfer:
|
|
/* Clear ICSR.AL bit */
|
|
mmio_write_8(IIC_ICSR, (mmio_read_8(IIC_ICSR)
|
|
& (uint8_t) (~ICSR_AL)));
|
|
/* Set next status */
|
|
avs_status = avs_status_error_stop;
|
|
break;
|
|
case avs_status_nack:
|
|
/* Write H'90 in ICCR to issue stop condition */
|
|
mmio_write_8(IIC_ICCR, ICCR_STOP);
|
|
/* Disable a WAIT and DTEE interrupt. */
|
|
mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC)
|
|
& (uint8_t) (~(ICIC_WAITE | ICIC_DTEE)));
|
|
/* Clear ICSR.TACK bit */
|
|
mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR)
|
|
& (uint8_t) (~ICSR_TACK));
|
|
/* Set next status */
|
|
avs_status = ave_status_error_end;
|
|
break;
|
|
case avs_status_error_stop:
|
|
/* If wait state after data transmission. */
|
|
if ((mmio_read_8(IIC_ICSR) & ICSR_WAIT) == ICSR_WAIT) {
|
|
/* Write H'90 in ICCR to issue stop condition */
|
|
mmio_write_8(IIC_ICCR, ICCR_STOP);
|
|
/* Clear ICSR.WAIT to exit from wait state. */
|
|
mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR)
|
|
& (uint8_t) (~ICSR_WAIT));
|
|
/* Set next status */
|
|
avs_status = ave_status_error_end;
|
|
}
|
|
break;
|
|
case ave_status_error_end:
|
|
/* Is this module not busy?. */
|
|
if ((mmio_read_8(IIC_ICSR) & ICSR_BUSY) == 0U) {
|
|
/* Set ICCR=H'00 to disable the I2C module. */
|
|
mmio_write_8(IIC_ICCR, 0x00U);
|
|
/* Increment the re-try number of times. */
|
|
avs_retry++;
|
|
/* Set start a re-try to status. */
|
|
avs_status = avs_status_start_condition;
|
|
}
|
|
break;
|
|
case avs_status_complete:
|
|
/* After "avs_status" became the "avs_status_complete", */
|
|
/* "avs_setting()" function may be called. */
|
|
break;
|
|
default:
|
|
/* This case is not possible. */
|
|
ERROR("AVS setting is in invalid status. status=%u\n",
|
|
avs_status);
|
|
/* Infinite loop */
|
|
panic();
|
|
break;
|
|
}
|
|
#endif /* PMIC_ROHM_BD9571 */
|
|
#endif /* (AVS_SETTING_ENABLE==1) */
|
|
}
|
|
|
|
/*
|
|
* Finish the AVS setting.
|
|
*/
|
|
void rcar_avs_end(void)
|
|
{
|
|
#if (AVS_SETTING_ENABLE == 1)
|
|
uint32_t mstp;
|
|
|
|
#if PMIC_ROHM_BD9571
|
|
/* While status is not completion, be repeated. */
|
|
while (avs_status != avs_status_complete)
|
|
rcar_avs_setting();
|
|
|
|
NOTICE("AVS setting succeeded. DVFS_SetVID=0x%x\n",
|
|
init_vol_tbl[efuse_avs].vol);
|
|
|
|
#if AVS_READ_PMIC_REG_ENABLE == 1
|
|
{
|
|
uint8_t addr = PMIC_DVFS_SETVID;
|
|
uint8_t value = avs_read_pmic_reg(addr);
|
|
|
|
NOTICE("Read PMIC register. address=0x%x value=0x%x\n",
|
|
addr, value);
|
|
}
|
|
#endif
|
|
|
|
/* Bit of the module which wants to disable clock supply. */
|
|
mstp = CPG_SYS_DVFS_BIT;
|
|
/* Disables the supply of clock signal to a module. */
|
|
cpg_write(CPG_SMSTPCR9, mmio_read_32(CPG_SMSTPCR9) | mstp);
|
|
#endif /* PMIC_ROHM_BD9571 */
|
|
|
|
/* Bit of the module which wants to disable clock supply. */
|
|
mstp = CPG_SYS_ADVFS_BIT;
|
|
/* Disables the supply of clock signal to a module. */
|
|
cpg_write(CPG_SMSTPCR9, mmio_read_32(CPG_SMSTPCR9) | mstp);
|
|
|
|
#endif /* (AVS_SETTING_ENABLE==1) */
|
|
}
|
|
|
|
#if (AVS_SETTING_ENABLE == 1)
|
|
#if PMIC_ROHM_BD9571
|
|
/*
|
|
* Check error and judge re-try.
|
|
*/
|
|
static avs_error_t avs_check_error(void)
|
|
{
|
|
avs_error_t ret;
|
|
|
|
if ((mmio_read_8(IIC_ICSR) & ICSR_AL) == ICSR_AL) {
|
|
NOTICE("%s AVS status=%d Retry=%u\n",
|
|
"Loss of arbitration is detected.", avs_status, avs_retry);
|
|
/* Check of retry number of times */
|
|
if (avs_retry >= AVS_RETRY_NUM) {
|
|
ERROR("AVS setting failed in retry. max=%u\n",
|
|
AVS_RETRY_NUM);
|
|
/* Infinite loop */
|
|
panic();
|
|
}
|
|
/* Set the error detected to error status. */
|
|
ret = avs_error_al;
|
|
} else if ((mmio_read_8(IIC_ICSR) & ICSR_TACK) == ICSR_TACK) {
|
|
NOTICE("%s AVS status=%d Retry=%u\n",
|
|
"Non-acknowledge is detected.", avs_status, avs_retry);
|
|
/* Check of retry number of times */
|
|
if (avs_retry >= AVS_RETRY_NUM) {
|
|
ERROR("AVS setting failed in retry. max=%u\n",
|
|
AVS_RETRY_NUM);
|
|
/* Infinite loop */
|
|
panic();
|
|
}
|
|
/* Set the error detected to error status. */
|
|
ret = avs_error_nack;
|
|
} else {
|
|
/* Not error. */
|
|
ret = avs_error_none;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Set I2C for DVFS clock.
|
|
*/
|
|
static void avs_set_iic_clock(void)
|
|
{
|
|
uint32_t md_pin;
|
|
|
|
/* Read Mode pin register. */
|
|
md_pin = mmio_read_32(RCAR_MODEMR) & CHECK_MD13_MD14;
|
|
/* Set the module clock (CP phy) for the IIC-DVFS. */
|
|
/* CP phy is EXTAL / 2. */
|
|
switch (md_pin) {
|
|
case MD14_MD13_TYPE_0: /* EXTAL = 16.6666MHz */
|
|
mmio_write_8(IIC_ICCL, ICCL_FREQ_8p33M);
|
|
mmio_write_8(IIC_ICCH, ICCH_FREQ_8p33M);
|
|
break;
|
|
case MD14_MD13_TYPE_1: /* EXTAL = 20MHz */
|
|
mmio_write_8(IIC_ICCL, ICCL_FREQ_10M);
|
|
mmio_write_8(IIC_ICCH, ICCH_FREQ_10M);
|
|
break;
|
|
case MD14_MD13_TYPE_2: /* EXTAL = 25MHz (H3/M3) */
|
|
mmio_write_8(IIC_ICCL, ICCL_FREQ_12p5M);
|
|
mmio_write_8(IIC_ICCH, ICCH_FREQ_12p5M);
|
|
break;
|
|
case MD14_MD13_TYPE_3: /* EXTAL = 33.3333MHz */
|
|
mmio_write_8(IIC_ICCL, ICCL_FREQ_16p66M);
|
|
mmio_write_8(IIC_ICCH, ICCH_FREQ_16p66M);
|
|
break;
|
|
default: /* This case is not possible. */
|
|
/* CP Phy frequency is to be set for the 16.66MHz */
|
|
mmio_write_8(IIC_ICCL, ICCL_FREQ_16p66M);
|
|
mmio_write_8(IIC_ICCH, ICCH_FREQ_16p66M);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if AVS_READ_PMIC_REG_ENABLE == 1
|
|
/*
|
|
* Read the value of the register of PMIC.
|
|
*/
|
|
static uint8_t avs_read_pmic_reg(uint8_t addr)
|
|
{
|
|
uint8_t reg;
|
|
|
|
/* Set ICCR.ICE=1 to activate the I2C module. */
|
|
mmio_write_8(IIC_ICCR, mmio_read_8(IIC_ICCR) | ICCR_ENABLE);
|
|
|
|
/* Set frequency of 400kHz */
|
|
avs_set_iic_clock();
|
|
|
|
/*
|
|
* Set ICIC.WAITE=1, ICIC.DTEE=1 to enable data transmission
|
|
* interrupt and wait interrupt.
|
|
*/
|
|
mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) | ICIC_WAITE | ICIC_DTEE);
|
|
|
|
/* Write H'94 in ICCR to issue start condition */
|
|
mmio_write_8(IIC_ICCR, ICCR_START);
|
|
|
|
/* Wait for a until ICSR.DTE becomes 1. */
|
|
avs_poll(ICSR_DTE, 1U);
|
|
|
|
/* Clear ICIC.DTEE to disable a DTE interrupt. */
|
|
mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) & (uint8_t) (~ICIC_DTEE));
|
|
/* Send slave address of PMIC */
|
|
mmio_write_8(IIC_ICDR, PMIC_W_SLAVE_ADDRESS);
|
|
|
|
/* Wait for a until ICSR.WAIT becomes 1. */
|
|
avs_poll(ICSR_WAIT, 1U);
|
|
|
|
/* write PMIC address */
|
|
mmio_write_8(IIC_ICDR, addr);
|
|
/* Clear ICSR.WAIT to exit from WAIT status. */
|
|
mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) & (uint8_t) (~ICSR_WAIT));
|
|
|
|
/* Wait for a until ICSR.WAIT becomes 1. */
|
|
avs_poll(ICSR_WAIT, 1U);
|
|
|
|
/* Write H'94 in ICCR to issue restart condition */
|
|
mmio_write_8(IIC_ICCR, ICCR_START);
|
|
/* Clear ICSR.WAIT to exit from WAIT status. */
|
|
mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) & (uint8_t) (~ICSR_WAIT));
|
|
/* Set ICIC.DTEE=1 to enable data transmission interrupt. */
|
|
mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) | ICIC_DTEE);
|
|
|
|
/* Wait for a until ICSR.DTE becomes 1. */
|
|
avs_poll(ICSR_DTE, 1U);
|
|
|
|
/* Clear ICIC.DTEE to disable a DTE interrupt. */
|
|
mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) & (uint8_t) (~ICIC_DTEE));
|
|
/* Send slave address of PMIC */
|
|
mmio_write_8(IIC_ICDR, PMIC_R_SLAVE_ADDRESS);
|
|
|
|
/* Wait for a until ICSR.WAIT becomes 1. */
|
|
avs_poll(ICSR_WAIT, 1U);
|
|
|
|
/* Write H'81 to ICCR to issue the repeated START condition */
|
|
/* for changing the transmission mode to the receive mode. */
|
|
mmio_write_8(IIC_ICCR, ICCR_START_RECV);
|
|
/* Clear ICSR.WAIT to exit from WAIT status. */
|
|
mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) & (uint8_t) (~ICSR_WAIT));
|
|
|
|
/* Wait for a until ICSR.WAIT becomes 1. */
|
|
avs_poll(ICSR_WAIT, 1U);
|
|
|
|
/* Set ICCR to H'C0 for the STOP condition */
|
|
mmio_write_8(IIC_ICCR, ICCR_STOP_RECV);
|
|
/* Clear ICSR.WAIT to exit from WAIT status. */
|
|
mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) & (uint8_t) (~ICSR_WAIT));
|
|
/* Set ICIC.DTEE=1 to enable data transmission interrupt. */
|
|
mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) | ICIC_DTEE);
|
|
|
|
/* Wait for a until ICSR.DTE becomes 1. */
|
|
avs_poll(ICSR_DTE, 1U);
|
|
|
|
/* Receive DVFS SetVID register */
|
|
/* Clear ICIC.DTEE to disable a DTE interrupt. */
|
|
mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) & (uint8_t) (~ICIC_DTEE));
|
|
/* Receive DVFS SetVID register */
|
|
reg = mmio_read_8(IIC_ICDR);
|
|
|
|
/* Wait until ICSR.BUSY is cleared. */
|
|
avs_poll(ICSR_BUSY, 0U);
|
|
|
|
/* Set ICCR=H'00 to disable the I2C module. */
|
|
mmio_write_8(IIC_ICCR, 0x00U);
|
|
|
|
return reg;
|
|
}
|
|
|
|
/*
|
|
* Wait processing by the polling.
|
|
*/
|
|
static void avs_poll(uint8_t bit_pos, uint8_t val)
|
|
{
|
|
uint8_t bit_val = 0U;
|
|
|
|
if (val != 0U)
|
|
bit_val = bit_pos;
|
|
|
|
while (1) {
|
|
if ((mmio_read_8(IIC_ICSR) & bit_pos) == bit_val)
|
|
break;
|
|
}
|
|
}
|
|
#endif /* AVS_READ_PMIC_REG_ENABLE */
|
|
#endif /* PMIC_ROHM_BD9571 */
|
|
#endif /* (AVS_SETTING_ENABLE==1) */
|