diff options
Diffstat (limited to 'drivers/renesas/common')
43 files changed, 8539 insertions, 0 deletions
diff --git a/drivers/renesas/common/auth/auth_mod.c b/drivers/renesas/common/auth/auth_mod.c new file mode 100644 index 000000000..4aa86e2a4 --- /dev/null +++ b/drivers/renesas/common/auth/auth_mod.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights + * reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stddef.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <lib/mmio.h> +#include <plat/common/platform.h> + +#include <platform_def.h> +#include "rom_api.h" + +typedef int32_t(*secure_boot_api_f) (uint32_t a, uint32_t b, void *c); +extern int32_t rcar_get_certificate(const int32_t name, uint32_t *cert_addr); + +#define RCAR_IMAGE_ID_MAX (10) +#define RCAR_CERT_MAGIC_NUM (0xE291F358U) +#define RCAR_BOOT_KEY_CERT (0xE6300C00U) +#define RCAR_BOOT_KEY_CERT_NEW (0xE6300F00U) +#define RST_BASE (0xE6160000U) +#define RST_MODEMR (RST_BASE + 0x0060U) +#define MFISOFTMDR (0xE6260600U) +#define MODEMR_MD5_MASK (0x00000020U) +#define MODEMR_MD5_SHIFT (5U) +#define SOFTMD_BOOTMODE_MASK (0x00000001U) +#define SOFTMD_NORMALBOOT (0x1U) + +static secure_boot_api_f secure_boot_api; + +int auth_mod_get_parent_id(unsigned int img_id, unsigned int *parent_id) +{ + return 1; +} + +int auth_mod_verify_img(unsigned int img_id, void *ptr, unsigned int len) +{ + int32_t ret = 0, index = 0; + uint32_t cert_addr = 0U; + static const struct img_to_cert_t { + uint32_t id; + int32_t cert; + const char *name; + } image[RCAR_IMAGE_ID_MAX] = { + { BL31_IMAGE_ID, SOC_FW_CONTENT_CERT_ID, "BL31" }, + { BL32_IMAGE_ID, TRUSTED_OS_FW_CONTENT_CERT_ID, "BL32" }, + { BL33_IMAGE_ID, NON_TRUSTED_FW_CONTENT_CERT_ID, "BL33" }, + { BL332_IMAGE_ID, BL332_CERT_ID, "BL332" }, + { BL333_IMAGE_ID, BL333_CERT_ID, "BL333" }, + { BL334_IMAGE_ID, BL334_CERT_ID, "BL334" }, + { BL335_IMAGE_ID, BL335_CERT_ID, "BL335" }, + { BL336_IMAGE_ID, BL336_CERT_ID, "BL336" }, + { BL337_IMAGE_ID, BL337_CERT_ID, "BL337" }, + { BL338_IMAGE_ID, BL338_CERT_ID, "BL338" }, + }; + +#if IMAGE_BL2 + switch (img_id) { + case TRUSTED_KEY_CERT_ID: + case SOC_FW_KEY_CERT_ID: + case TRUSTED_OS_FW_KEY_CERT_ID: + case NON_TRUSTED_FW_KEY_CERT_ID: + case BL332_KEY_CERT_ID: + case BL333_KEY_CERT_ID: + case BL334_KEY_CERT_ID: + case BL335_KEY_CERT_ID: + case BL336_KEY_CERT_ID: + case BL337_KEY_CERT_ID: + case BL338_KEY_CERT_ID: + case SOC_FW_CONTENT_CERT_ID: + case TRUSTED_OS_FW_CONTENT_CERT_ID: + case NON_TRUSTED_FW_CONTENT_CERT_ID: + case BL332_CERT_ID: + case BL333_CERT_ID: + case BL334_CERT_ID: + case BL335_CERT_ID: + case BL336_CERT_ID: + case BL337_CERT_ID: + case BL338_CERT_ID: + return ret; + case BL31_IMAGE_ID: + case BL32_IMAGE_ID: + case BL33_IMAGE_ID: + case BL332_IMAGE_ID: + case BL333_IMAGE_ID: + case BL334_IMAGE_ID: + case BL335_IMAGE_ID: + case BL336_IMAGE_ID: + case BL337_IMAGE_ID: + case BL338_IMAGE_ID: + goto verify_image; + default: + return -1; + } + +verify_image: + for (index = 0; index < RCAR_IMAGE_ID_MAX; index++) { + if (img_id != image[index].id) + continue; + + ret = rcar_get_certificate(image[index].cert, &cert_addr); + break; + } + + if (ret || (index == RCAR_IMAGE_ID_MAX)) { + ERROR("Verification Failed for image id = %d\n", img_id); + return ret; + } +#if RCAR_BL2_DCACHE == 1 + /* clean and disable */ + write_sctlr_el3(read_sctlr_el3() & ~SCTLR_C_BIT); + dcsw_op_all(DCCISW); +#endif + ret = (mmio_read_32(RCAR_BOOT_KEY_CERT_NEW) == RCAR_CERT_MAGIC_NUM) ? + secure_boot_api(RCAR_BOOT_KEY_CERT_NEW, cert_addr, NULL) : + secure_boot_api(RCAR_BOOT_KEY_CERT, cert_addr, NULL); + if (ret) + ERROR("Verification Failed 0x%x, %s\n", ret, image[index].name); + +#if RCAR_BL2_DCACHE == 1 + /* enable */ + write_sctlr_el3(read_sctlr_el3() | SCTLR_C_BIT); +#endif /* RCAR_BL2_DCACHE */ + +#endif /* IMAGE_BL2 */ + return ret; +} + +static int32_t normal_boot_verify(uint32_t a, uint32_t b, void *c) +{ + return 0; +} + +void auth_mod_init(void) +{ +#if RCAR_SECURE_BOOT + uint32_t soft_md = mmio_read_32(MFISOFTMDR) & SOFTMD_BOOTMODE_MASK; + uint32_t md = mmio_read_32(RST_MODEMR) & MODEMR_MD5_MASK; + uint32_t lcs, ret; + + secure_boot_api = (secure_boot_api_f) &rcar_rom_secure_boot_api; + + ret = rcar_rom_get_lcs(&lcs); + if (ret) { + ERROR("BL2: Failed to get the LCS. (%d)\n", ret); + panic(); + } + + switch (lcs) { + case LCS_SE: + if (soft_md == SOFTMD_NORMALBOOT) + secure_boot_api = &normal_boot_verify; + break; + case LCS_SD: + secure_boot_api = &normal_boot_verify; + break; + default: + if (md >> MODEMR_MD5_SHIFT) + secure_boot_api = &normal_boot_verify; + } + + NOTICE("BL2: %s boot\n", + secure_boot_api == &normal_boot_verify ? "Normal" : "Secure"); +#else + NOTICE("BL2: Normal boot\n"); + secure_boot_api = &normal_boot_verify; +#endif +} diff --git a/drivers/renesas/common/avs/avs_driver.c b/drivers/renesas/common/avs/avs_driver.c new file mode 100644 index 000000000..2c939cd59 --- /dev/null +++ b/drivers/renesas/common/avs/avs_driver.c @@ -0,0 +1,630 @@ +/* + * 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) */ diff --git a/drivers/renesas/common/avs/avs_driver.h b/drivers/renesas/common/avs/avs_driver.h new file mode 100644 index 000000000..aa773b604 --- /dev/null +++ b/drivers/renesas/common/avs/avs_driver.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights + * reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AVS_DRIVER_H +#define AVS_DRIVER_H + +/* AVS Setting. 1:enable / 0:disable */ +#ifndef AVS_SETTING_ENABLE +#define AVS_SETTING_ENABLE 1 +#endif /* AVS_SETTING_ENABLE */ + +void rcar_avs_init(void); +void rcar_avs_setting(void); +void rcar_avs_end(void); + +#endif /* AVS_DRIVER_H */ diff --git a/drivers/renesas/common/common.c b/drivers/renesas/common/common.c new file mode 100644 index 000000000..9b7c1eb16 --- /dev/null +++ b/drivers/renesas/common/common.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <lib/mmio.h> + +#include "rcar_private.h" + +#if IMAGE_BL31 +void __attribute__ ((section(".system_ram"))) cpg_write(uintptr_t regadr, uint32_t regval) +#else +void cpg_write(uintptr_t regadr, uint32_t regval) +#endif +{ + uint32_t value = regval; + + mmio_write_32((uintptr_t) RCAR_CPGWPR, ~value); + mmio_write_32(regadr, value); +} + +#if IMAGE_BL31 +void __attribute__ ((section(".system_ram"))) mstpcr_write(uint32_t mstpcr, uint32_t mstpsr, + uint32_t target_bit) +#else +void mstpcr_write(uint32_t mstpcr, uint32_t mstpsr, uint32_t target_bit) +#endif +{ + uint32_t reg; + + reg = mmio_read_32(mstpcr); + reg &= ~target_bit; + cpg_write(mstpcr, reg); + while ((mmio_read_32(mstpsr) & target_bit) != 0U) { + } +} diff --git a/drivers/renesas/common/console/rcar_console.S b/drivers/renesas/common/console/rcar_console.S new file mode 100644 index 000000000..29baa67a4 --- /dev/null +++ b/drivers/renesas/common/console/rcar_console.S @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2018-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <console_macros.S> +#include <drivers/renesas/rcar/console/console.h> + + .globl console_rcar_register + .globl console_rcar_init + .globl console_rcar_putc + .globl console_rcar_flush + + .extern rcar_log_init + .extern rcar_set_log_data + + /* ----------------------------------------------- + * int console_rcar_register( + * uintptr_t base, uint32_t clk, uint32_t baud, + * console_t *console) + * Function to initialize and register a new rcar + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * In: x0 - UART register base address + * w1 - UART clock in Hz + * w2 - Baud rate + * x3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : x0, x1, x2, x6, x7, x14 + * ----------------------------------------------- + */ +func console_rcar_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_BASE] + + bl rcar_log_init + cbz x0, register_fail + + mov x0, x6 + mov x30, x7 + finish_console_register rcar, putc=1, getc=0, flush=1 + +register_fail: + ret x7 +endfunc console_rcar_register + + /* --------------------------------------------- + * int console_rcar_init(unsigned long base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by crash reporting. + * In: x0 - console base address + * w1 - Uart clock in Hz + * w2 - Baud rate + * Out: return 1 on success + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func console_rcar_init + mov w0, #0 + ret +endfunc console_rcar_init + + /* -------------------------------------------------------- + * int console_rcar_putc(int c, console_t *console) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : w0 - character to be printed + * x1 - pointer to console_t structure + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_rcar_putc + b rcar_set_log_data +endfunc console_rcar_putc + + /* --------------------------------------------- + * void console_rcar_flush(void) + * Function to force a write of all buffered + * data that hasn't been output. It returns void + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_rcar_flush + ret +endfunc console_rcar_flush diff --git a/drivers/renesas/common/console/rcar_printf.c b/drivers/renesas/common/console/rcar_printf.c new file mode 100644 index 000000000..ad074fe05 --- /dev/null +++ b/drivers/renesas/common/console/rcar_printf.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdarg.h> +#include <stdint.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <lib/bakery_lock.h> + +#include "rcar_def.h" +#include "rcar_private.h" +#include "rcar_printf.h" + +#define INDEX_TIMER_COUNT (4U) + +#define RCAR_LOG_HEAD (('T' << 0) | ('L' << 8) | ('O' << 16) | ('G' << 24)) + +/* + * The log is initialized and used before BL31 xlat tables are initialized, + * therefore the log memory is a device memory at that point. Make sure the + * memory is correclty aligned and accessed only with up-to 32bit, aligned, + * writes. + */ +CASSERT((RCAR_BL31_LOG_BASE & 0x7) == 0, assert_bl31_log_base_unaligned); +CASSERT((RCAR_BL31_LOG_MAX & 0x7) == 0, assert_bl31_log_max_unaligned); + +extern RCAR_INSTANTIATE_LOCK typedef struct log_head { + uint32_t head; + uint32_t index; + uint32_t size; + uint32_t res; +} loghead_t; + +typedef struct log_map { + loghead_t header; + uint8_t log_data[RCAR_BL31_LOG_MAX]; + uint8_t res_data[RCAR_LOG_RES_SIZE]; +} logmap_t; + +int32_t rcar_set_log_data(int32_t c) +{ + logmap_t *t_log; + + t_log = (logmap_t *) RCAR_BL31_LOG_BASE; + + rcar_lock_get(); + + /* + * If index is broken, then index and size initialize + */ + if (t_log->header.index >= (uint32_t) RCAR_BL31_LOG_MAX) { + t_log->header.index = 0U; + t_log->header.size = 0U; + } + /* + * data store to log area then index and size renewal + */ + t_log->log_data[t_log->header.index] = (uint8_t) c; + t_log->header.index++; + if (t_log->header.size < t_log->header.index) { + t_log->header.size = t_log->header.index; + } + if (t_log->header.index >= (uint32_t) RCAR_BL31_LOG_MAX) { + t_log->header.index = 0U; + } + + rcar_lock_release(); + + return 1; +} + +int32_t rcar_log_init(void) +{ + logmap_t *t_log = (logmap_t *)RCAR_BL31_LOG_BASE; + uint32_t *log_data = (uint32_t *)t_log->log_data; + int16_t init_flag = 0; + int i; + + if (t_log->header.head != RCAR_LOG_HEAD) { + /* + * Log header is not "TLOG", then log area initialize + */ + init_flag = 1; + } + if (t_log->header.index >= (uint32_t) RCAR_BL31_LOG_MAX) { + /* + * index is broken, then log area initialize + */ + init_flag = 1; + } + if (init_flag == 1) { + for (i = 0; i < RCAR_BL31_LOG_MAX; i += 4) + *log_data++ = 0; + + t_log->header.head = RCAR_LOG_HEAD; + t_log->header.index = 0U; + t_log->header.size = 0U; + } + rcar_lock_init(); + + return 1; +} diff --git a/drivers/renesas/common/console/rcar_printf.h b/drivers/renesas/common/console/rcar_printf.h new file mode 100644 index 000000000..5da70e636 --- /dev/null +++ b/drivers/renesas/common/console/rcar_printf.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RCAR_PRINTF_H +#define RCAR_PRINTF_H + +#include <string.h> + +int32_t rcar_set_log_data(int32_t c); +int32_t rcar_log_init(void); + +#endif /* RCAR_PRINTF_H */ diff --git a/drivers/renesas/common/ddr_regs.h b/drivers/renesas/common/ddr_regs.h new file mode 100644 index 000000000..ba26c69c8 --- /dev/null +++ b/drivers/renesas/common/ddr_regs.h @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BOOT_INIT_DRAM_REGDEF_H_ +#define BOOT_INIT_DRAM_REGDEF_H_ + +/* DBSC registers */ +#define DBSC_DBSYSCONF0 0xE6790000U +#define DBSC_DBSYSCONF1 0xE6790004U +#define DBSC_DBPHYCONF0 0xE6790010U +#define DBSC_DBKIND 0xE6790020U +#define DBSC_DBMEMCONF(ch, cs) (0xE6790030U + 0x10U * (ch) + 0x04U * (cs)) +#define DBSC_DBMEMCONF_0_0 0xE6790030U +#define DBSC_DBMEMCONF_0_1 0xE6790034U +#define DBSC_DBMEMCONF_0_2 0xE6790038U +#define DBSC_DBMEMCONF_0_3 0xE679003CU +#define DBSC_DBMEMCONF_1_2 0xE6790048U +#define DBSC_DBMEMCONF_1_3 0xE679004CU +#define DBSC_DBMEMCONF_1_0 0xE6790040U +#define DBSC_DBMEMCONF_1_1 0xE6790044U +#define DBSC_DBMEMCONF_2_0 0xE6790050U +#define DBSC_DBMEMCONF_2_1 0xE6790054U +#define DBSC_DBMEMCONF_2_2 0xE6790058U +#define DBSC_DBMEMCONF_2_3 0xE679005CU +#define DBSC_DBMEMCONF_3_0 0xE6790060U +#define DBSC_DBMEMCONF_3_1 0xE6790064U +#define DBSC_DBMEMCONF_3_2 0xE6790068U +#define DBSC_DBMEMCONF_3_3 0xE679006CU +#define DBSC_DBSYSCNT0 0xE6790100U +#define DBSC_DBSVCR1 0xE6790104U +#define DBSC_DBSTATE0 0xE6790108U +#define DBSC_DBSTATE1 0xE679010CU +#define DBSC_DBINTEN 0xE6790180U +#define DBSC_DBINTSTAT0 0xE6790184U +#define DBSC_DBACEN 0xE6790200U +#define DBSC_DBRFEN 0xE6790204U +#define DBSC_DBCMD 0xE6790208U +#define DBSC_DBWAIT 0xE6790210U +#define DBSC_DBSYSCTRL0 0xE6790280U +#define DBSC_DBTR(x) (0xE6790300U + 0x04U * (x)) +#define DBSC_DBTR0 0xE6790300U +#define DBSC_DBTR1 0xE6790304U +#define DBSC_DBTR2 0xE6790308U +#define DBSC_DBTR3 0xE679030CU +#define DBSC_DBTR4 0xE6790310U +#define DBSC_DBTR5 0xE6790314U +#define DBSC_DBTR6 0xE6790318U +#define DBSC_DBTR7 0xE679031CU +#define DBSC_DBTR8 0xE6790320U +#define DBSC_DBTR9 0xE6790324U +#define DBSC_DBTR10 0xE6790328U +#define DBSC_DBTR11 0xE679032CU +#define DBSC_DBTR12 0xE6790330U +#define DBSC_DBTR13 0xE6790334U +#define DBSC_DBTR14 0xE6790338U +#define DBSC_DBTR15 0xE679033CU +#define DBSC_DBTR16 0xE6790340U +#define DBSC_DBTR17 0xE6790344U +#define DBSC_DBTR18 0xE6790348U +#define DBSC_DBTR19 0xE679034CU +#define DBSC_DBTR20 0xE6790350U +#define DBSC_DBTR21 0xE6790354U +#define DBSC_DBTR22 0xE6790358U +#define DBSC_DBTR23 0xE679035CU +#define DBSC_DBTR24 0xE6790360U +#define DBSC_DBTR25 0xE6790364U +#define DBSC_DBTR26 0xE6790368U +#define DBSC_DBBL 0xE6790400U +#define DBSC_DBRFCNF1 0xE6790414U +#define DBSC_DBRFCNF2 0xE6790418U +#define DBSC_DBTSPCNF 0xE6790420U +#define DBSC_DBCALCNF 0xE6790424U +#define DBSC_DBRNK(x) (0xE6790430U + 0x04U * (x)) +#define DBSC_DBRNK2 0xE6790438U +#define DBSC_DBRNK3 0xE679043CU +#define DBSC_DBRNK4 0xE6790440U +#define DBSC_DBRNK5 0xE6790444U +#define DBSC_DBPDNCNF 0xE6790450U +#define DBSC_DBODT(x) (0xE6790460U + 0x04U * (x)) +#define DBSC_DBODT0 0xE6790460U +#define DBSC_DBODT1 0xE6790464U +#define DBSC_DBODT2 0xE6790468U +#define DBSC_DBODT3 0xE679046CU +#define DBSC_DBODT4 0xE6790470U +#define DBSC_DBODT5 0xE6790474U +#define DBSC_DBODT6 0xE6790478U +#define DBSC_DBODT7 0xE679047CU +#define DBSC_DBADJ0 0xE6790500U +#define DBSC_DBDBICNT 0xE6790518U +#define DBSC_DBDFIPMSTRCNF 0xE6790520U +#define DBSC_DBDFICUPDCNF 0xE679052CU +#define DBSC_DBDFISTAT(ch) (0xE6790600U + 0x40U * (ch)) +#define DBSC_DBDFISTAT_0 0xE6790600U +#define DBSC_DBDFISTAT_1 0xE6790640U +#define DBSC_DBDFISTAT_2 0xE6790680U +#define DBSC_DBDFISTAT_3 0xE67906C0U +#define DBSC_DBDFICNT(ch) (0xE6790604U + 0x40U * (ch)) +#define DBSC_DBDFICNT_0 0xE6790604U +#define DBSC_DBDFICNT_1 0xE6790644U +#define DBSC_DBDFICNT_2 0xE6790684U +#define DBSC_DBDFICNT_3 0xE67906C4U +#define DBSC_DBPDCNT0(ch) (0xE6790610U + 0x40U * (ch)) +#define DBSC_DBPDCNT0_0 0xE6790610U +#define DBSC_DBPDCNT0_1 0xE6790650U +#define DBSC_DBPDCNT0_2 0xE6790690U +#define DBSC_DBPDCNT0_3 0xE67906D0U +#define DBSC_DBPDCNT1(ch) (0xE6790614U + 0x40U * (ch)) +#define DBSC_DBPDCNT1_0 0xE6790614U +#define DBSC_DBPDCNT1_1 0xE6790654U +#define DBSC_DBPDCNT1_2 0xE6790694U +#define DBSC_DBPDCNT1_3 0xE67906D4U +#define DBSC_DBPDCNT2(ch) (0xE6790618U + 0x40U * (ch)) +#define DBSC_DBPDCNT2_0 0xE6790618U +#define DBSC_DBPDCNT2_1 0xE6790658U +#define DBSC_DBPDCNT2_2 0xE6790698U +#define DBSC_DBPDCNT2_3 0xE67906D8U +#define DBSC_DBPDCNT3(ch) (0xE679061CU + 0x40U * (ch)) +#define DBSC_DBPDCNT3_0 0xE679061CU +#define DBSC_DBPDCNT3_1 0xE679065CU +#define DBSC_DBPDCNT3_2 0xE679069CU +#define DBSC_DBPDCNT3_3 0xE67906DCU +#define DBSC_DBPDLK(ch) (0xE6790620U + 0x40U * (ch)) +#define DBSC_DBPDLK_0 0xE6790620U +#define DBSC_DBPDLK_1 0xE6790660U +#define DBSC_DBPDLK_2 0xE67906a0U +#define DBSC_DBPDLK_3 0xE67906e0U +#define DBSC_DBPDRGA(ch) (0xE6790624U + 0x40U * (ch)) +#define DBSC_DBPDRGD(ch) (0xE6790628U + 0x40U * (ch)) +#define DBSC_DBPDRGA_0 0xE6790624U +#define DBSC_DBPDRGD_0 0xE6790628U +#define DBSC_DBPDRGA_1 0xE6790664U +#define DBSC_DBPDRGD_1 0xE6790668U +#define DBSC_DBPDRGA_2 0xE67906A4U +#define DBSC_DBPDRGD_2 0xE67906A8U +#define DBSC_DBPDRGA_3 0xE67906E4U +#define DBSC_DBPDRGD_3 0xE67906E8U +#define DBSC_DBPDSTAT(ch) (0xE6790630U + 0x40U * (ch)) +#define DBSC_DBPDSTAT_0 0xE6790630U +#define DBSC_DBPDSTAT_1 0xE6790670U +#define DBSC_DBPDSTAT_2 0xE67906B0U +#define DBSC_DBPDSTAT_3 0xE67906F0U +#define DBSC_DBBUS0CNF0 0xE6790800U +#define DBSC_DBBUS0CNF1 0xE6790804U +#define DBSC_DBCAM0CNF1 0xE6790904U +#define DBSC_DBCAM0CNF2 0xE6790908U +#define DBSC_DBCAM0CNF3 0xE679090CU +#define DBSC_DBBSWAP 0xE67909F0U +#define DBSC_DBBCAMDIS 0xE67909FCU +#define DBSC_DBSCHCNT0 0xE6791000U +#define DBSC_DBSCHCNT1 0xE6791004U +#define DBSC_DBSCHSZ0 0xE6791010U +#define DBSC_DBSCHRW0 0xE6791020U +#define DBSC_DBSCHRW1 0xE6791024U +#define DBSC_DBSCHQOS_0(x) (0xE6791030U + 0x10U * (x)) +#define DBSC_DBSCHQOS_1(x) (0xE6791034U + 0x10U * (x)) +#define DBSC_DBSCHQOS_2(x) (0xE6791038U + 0x10U * (x)) +#define DBSC_DBSCHQOS_3(x) (0xE679103CU + 0x10U * (x)) +#define DBSC_DBSCHQOS00 0xE6791030U +#define DBSC_DBSCHQOS01 0xE6791034U +#define DBSC_DBSCHQOS02 0xE6791038U +#define DBSC_DBSCHQOS03 0xE679103CU +#define DBSC_DBSCHQOS10 0xE6791040U +#define DBSC_DBSCHQOS11 0xE6791044U +#define DBSC_DBSCHQOS12 0xE6791048U +#define DBSC_DBSCHQOS13 0xE679104CU +#define DBSC_DBSCHQOS20 0xE6791050U +#define DBSC_DBSCHQOS21 0xE6791054U +#define DBSC_DBSCHQOS22 0xE6791058U +#define DBSC_DBSCHQOS23 0xE679105CU +#define DBSC_DBSCHQOS30 0xE6791060U +#define DBSC_DBSCHQOS31 0xE6791064U +#define DBSC_DBSCHQOS32 0xE6791068U +#define DBSC_DBSCHQOS33 0xE679106CU +#define DBSC_DBSCHQOS40 0xE6791070U +#define DBSC_DBSCHQOS41 0xE6791074U +#define DBSC_DBSCHQOS42 0xE6791078U +#define DBSC_DBSCHQOS43 0xE679107CU +#define DBSC_DBSCHQOS50 0xE6791080U +#define DBSC_DBSCHQOS51 0xE6791084U +#define DBSC_DBSCHQOS52 0xE6791088U +#define DBSC_DBSCHQOS53 0xE679108CU +#define DBSC_DBSCHQOS60 0xE6791090U +#define DBSC_DBSCHQOS61 0xE6791094U +#define DBSC_DBSCHQOS62 0xE6791098U +#define DBSC_DBSCHQOS63 0xE679109CU +#define DBSC_DBSCHQOS70 0xE67910A0U +#define DBSC_DBSCHQOS71 0xE67910A4U +#define DBSC_DBSCHQOS72 0xE67910A8U +#define DBSC_DBSCHQOS73 0xE67910ACU +#define DBSC_DBSCHQOS80 0xE67910B0U +#define DBSC_DBSCHQOS81 0xE67910B4U +#define DBSC_DBSCHQOS82 0xE67910B8U +#define DBSC_DBSCHQOS83 0xE67910BCU +#define DBSC_DBSCHQOS90 0xE67910C0U +#define DBSC_DBSCHQOS91 0xE67910C4U +#define DBSC_DBSCHQOS92 0xE67910C8U +#define DBSC_DBSCHQOS93 0xE67910CCU +#define DBSC_DBSCHQOS100 0xE67910D0U +#define DBSC_DBSCHQOS101 0xE67910D4U +#define DBSC_DBSCHQOS102 0xE67910D8U +#define DBSC_DBSCHQOS103 0xE67910DCU +#define DBSC_DBSCHQOS110 0xE67910E0U +#define DBSC_DBSCHQOS111 0xE67910E4U +#define DBSC_DBSCHQOS112 0xE67910E8U +#define DBSC_DBSCHQOS113 0xE67910ECU +#define DBSC_DBSCHQOS120 0xE67910F0U +#define DBSC_DBSCHQOS121 0xE67910F4U +#define DBSC_DBSCHQOS122 0xE67910F8U +#define DBSC_DBSCHQOS123 0xE67910FCU +#define DBSC_DBSCHQOS130 0xE6791100U +#define DBSC_DBSCHQOS131 0xE6791104U +#define DBSC_DBSCHQOS132 0xE6791108U +#define DBSC_DBSCHQOS133 0xE679110CU +#define DBSC_DBSCHQOS140 0xE6791110U +#define DBSC_DBSCHQOS141 0xE6791114U +#define DBSC_DBSCHQOS142 0xE6791118U +#define DBSC_DBSCHQOS143 0xE679111CU +#define DBSC_DBSCHQOS150 0xE6791120U +#define DBSC_DBSCHQOS151 0xE6791124U +#define DBSC_DBSCHQOS152 0xE6791128U +#define DBSC_DBSCHQOS153 0xE679112CU +#define DBSC_DBSCTR0 0xE6791700U +#define DBSC_DBSCTR1 0xE6791708U +#define DBSC_DBSCHRW2 0xE679170CU +#define DBSC_SCFCTST01(x) (0xE6791700U + 0x08U * (x)) +#define DBSC_SCFCTST0 0xE6791700U +#define DBSC_SCFCTST1 0xE6791708U +#define DBSC_SCFCTST2 0xE679170CU +#define DBSC_DBMRRDR(chab) (0xE6791800U + 0x04U * (chab)) +#define DBSC_DBMRRDR_0 0xE6791800U +#define DBSC_DBMRRDR_1 0xE6791804U +#define DBSC_DBMRRDR_2 0xE6791808U +#define DBSC_DBMRRDR_3 0xE679180CU +#define DBSC_DBMRRDR_4 0xE6791810U +#define DBSC_DBMRRDR_5 0xE6791814U +#define DBSC_DBMRRDR_6 0xE6791818U +#define DBSC_DBMRRDR_7 0xE679181CU +#define DBSC_DBMEMSWAPCONF0 0xE6792000U + +/* CPG registers */ +#define CPG_BASE 0xE6150000U +#define CPG_FRQCRB (CPG_BASE + 0x0004U) +#define CPG_PLLECR (CPG_BASE + 0x00D0U) +#define CPG_MSTPSR5 (CPG_BASE + 0x003CU) +#define CPG_SRCR4 (CPG_BASE + 0x00BCU) +#define CPG_PLL3CR (CPG_BASE + 0x00DCU) +#define CPG_ZB3CKCR (CPG_BASE + 0x0380U) +#define CPG_FRQCRD (CPG_BASE + 0x00E4U) +#define CPG_SMSTPCR5 (CPG_BASE + 0x0144U) +#define CPG_CPGWPR (CPG_BASE + 0x0900U) +#define CPG_SRSTCLR4 (CPG_BASE + 0x0950U) + +#endif /* BOOT_INIT_DRAM_REGDEF_H_*/ diff --git a/drivers/renesas/common/delay/micro_delay.c b/drivers/renesas/common/delay/micro_delay.c new file mode 100644 index 000000000..a5e2a6928 --- /dev/null +++ b/drivers/renesas/common/delay/micro_delay.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <arch_helpers.h> + +#include "micro_delay.h" + +#define RCAR_CONV_MICROSEC 1000000U + +void +#if IMAGE_BL31 + __attribute__ ((section(".system_ram"))) +#endif + rcar_micro_delay(uint64_t micro_sec) +{ + uint64_t freq; + uint64_t base_count; + uint64_t get_count; + uint64_t wait_time = 0U; + + freq = read_cntfrq_el0(); + base_count = read_cntpct_el0(); + while (micro_sec > wait_time) { + get_count = read_cntpct_el0(); + wait_time = ((get_count - base_count) * RCAR_CONV_MICROSEC) / freq; + } +} diff --git a/drivers/renesas/common/delay/micro_delay.h b/drivers/renesas/common/delay/micro_delay.h new file mode 100644 index 000000000..37b71f80a --- /dev/null +++ b/drivers/renesas/common/delay/micro_delay.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MICRO_DELAY_H +#define MICRO_DELAY_H + +#ifndef __ASSEMBLER__ +#include <stdint.h> +void rcar_micro_delay(uint64_t micro_sec); +#endif + +#endif /* MICRO_DELAY_H */ diff --git a/drivers/renesas/common/dma/dma_driver.c b/drivers/renesas/common/dma/dma_driver.c new file mode 100644 index 000000000..44ee98592 --- /dev/null +++ b/drivers/renesas/common/dma/dma_driver.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> +#include <string.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <lib/mmio.h> + +#include "cpg_registers.h" +#include "rcar_def.h" +#include "rcar_private.h" + +/* DMA CHANNEL setting (0/16/32) */ +#if RCAR_LSI == RCAR_V3M +#define DMA_CH 16 +#else +#define DMA_CH 0 +#endif + +#if (DMA_CH == 0) +#define SYS_DMAC_BIT ((uint32_t)1U << 19U) +#define DMA_BASE (0xE6700000U) +#elif (DMA_CH == 16) +#define SYS_DMAC_BIT ((uint32_t)1U << 18U) +#define DMA_BASE (0xE7300000U) +#elif (DMA_CH == 32) +#define SYS_DMAC_BIT ((uint32_t)1U << 17U) +#define DMA_BASE (0xE7320000U) +#else +#define SYS_DMAC_BIT ((uint32_t)1U << 19U) +#define DMA_BASE (0xE6700000U) +#endif + +/* DMA operation */ +#define DMA_DMAOR (DMA_BASE + 0x0060U) +/* DMA secure control */ +#define DMA_DMASEC (DMA_BASE + 0x0030U) +/* DMA channel clear */ +#define DMA_DMACHCLR (DMA_BASE + 0x0080U) +/* DMA source address */ +#define DMA_DMASAR (DMA_BASE + 0x8000U) +/* DMA destination address */ +#define DMA_DMADAR (DMA_BASE + 0x8004U) +/* DMA transfer count */ +#define DMA_DMATCR (DMA_BASE + 0x8008U) +/* DMA channel control */ +#define DMA_DMACHCR (DMA_BASE + 0x800CU) +/* DMA fixed destination address */ +#define DMA_DMAFIXDAR (DMA_BASE + 0x8014U) + +#define DMA_USE_CHANNEL (0x00000001U) +#define DMAOR_INITIAL (0x0301U) +#define DMACHCLR_CH_ALL (0x0000FFFFU) +#define DMAFIXDAR_32BIT_SHIFT (32U) +#define DMAFIXDAR_DAR_MASK (0x000000FFU) +#define DMADAR_BOUNDARY_ADDR (0x100000000ULL) +#define DMATCR_CNT_SHIFT (6U) +#define DMATCR_MAX (0x00FFFFFFU) +#define DMACHCR_TRN_MODE (0x00105409U) +#define DMACHCR_DE_BIT (0x00000001U) +#define DMACHCR_TE_BIT (0x00000002U) +#define DMACHCR_CHE_BIT (0x80000000U) + +#define DMA_SIZE_UNIT FLASH_TRANS_SIZE_UNIT +#define DMA_FRACTION_MASK (0xFFU) +#define DMA_DST_LIMIT (0x10000000000ULL) + +/* transfer length limit */ +#define DMA_LENGTH_LIMIT ((DMATCR_MAX * (1U << DMATCR_CNT_SHIFT)) \ + & ~DMA_FRACTION_MASK) + +static void dma_enable(void) +{ + mstpcr_write(CPG_SMSTPCR2, CPG_MSTPSR2, SYS_DMAC_BIT); +} + +static void dma_setup(void) +{ + mmio_write_16(DMA_DMAOR, 0); + mmio_write_32(DMA_DMACHCLR, DMACHCLR_CH_ALL); +} + +static void dma_start(uintptr_t dst, uint32_t src, uint32_t len) +{ + mmio_write_16(DMA_DMAOR, DMAOR_INITIAL); + mmio_write_32(DMA_DMAFIXDAR, (dst >> DMAFIXDAR_32BIT_SHIFT) & + DMAFIXDAR_DAR_MASK); + mmio_write_32(DMA_DMADAR, dst & UINT32_MAX); + mmio_write_32(DMA_DMASAR, src); + mmio_write_32(DMA_DMATCR, len >> DMATCR_CNT_SHIFT); + mmio_write_32(DMA_DMASEC, DMA_USE_CHANNEL); + mmio_write_32(DMA_DMACHCR, DMACHCR_TRN_MODE); +} + +static void dma_end(void) +{ + while ((mmio_read_32(DMA_DMACHCR) & DMACHCR_TE_BIT) == 0) { + if ((mmio_read_32(DMA_DMACHCR) & DMACHCR_CHE_BIT) != 0U) { + ERROR("BL2: DMA - Channel Address Error\n"); + panic(); + break; + } + } + /* DMA transfer Disable */ + mmio_clrbits_32(DMA_DMACHCR, DMACHCR_DE_BIT); + while ((mmio_read_32(DMA_DMACHCR) & DMACHCR_DE_BIT) != 0) + ; + + mmio_write_32(DMA_DMASEC, 0); + mmio_write_16(DMA_DMAOR, 0); + mmio_write_32(DMA_DMACHCLR, DMA_USE_CHANNEL); +} + +void rcar_dma_exec(uintptr_t dst, uint32_t src, uint32_t len) +{ + uint32_t dma_len = len; + + if (len & DMA_FRACTION_MASK) + dma_len = (len + DMA_SIZE_UNIT) & ~DMA_FRACTION_MASK; + + if (!dma_len || dma_len > DMA_LENGTH_LIMIT) { + ERROR("BL2: DMA - size invalid, length (0x%x)\n", dma_len); + panic(); + } + + if (src & DMA_FRACTION_MASK) { + ERROR("BL2: DMA - src address invalid (0x%x), len=(0x%x)\n", + src, dma_len); + panic(); + } + + if ((dst & UINT32_MAX) + dma_len > DMADAR_BOUNDARY_ADDR || + (dst + dma_len > DMA_DST_LIMIT) || + (dst & DMA_FRACTION_MASK)) { + ERROR("BL2: DMA - dest address invalid (0x%lx), len=(0x%x)\n", + dst, dma_len); + panic(); + } + + dma_start(dst, src, dma_len); + dma_end(); +} + +void rcar_dma_init(void) +{ + dma_enable(); + dma_setup(); +} diff --git a/drivers/renesas/common/emmc/emmc_cmd.c b/drivers/renesas/common/emmc/emmc_cmd.c new file mode 100644 index 000000000..d255bffc9 --- /dev/null +++ b/drivers/renesas/common/emmc/emmc_cmd.c @@ -0,0 +1,493 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> + +#include "emmc_config.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_registers.h" +#include "emmc_std.h" +#include "micro_delay.h" + +static void emmc_little_to_big(uint8_t *p, uint32_t value) +{ + if (p == NULL) + return; + + p[0] = (uint8_t) (value >> 24); + p[1] = (uint8_t) (value >> 16); + p[2] = (uint8_t) (value >> 8); + p[3] = (uint8_t) value; + +} + +static void emmc_softreset(void) +{ + int32_t loop = 10000; + int32_t retry = 1000; + + /* flag clear */ + mmc_drv_obj.during_cmd_processing = FALSE; + mmc_drv_obj.during_transfer = FALSE; + mmc_drv_obj.during_dma_transfer = FALSE; + mmc_drv_obj.state_machine_blocking = FALSE; + mmc_drv_obj.force_terminate = FALSE; + mmc_drv_obj.dma_error_flag = FALSE; + + /* during operation ? */ + if ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) == 0) + goto reset; + + /* wait CMDSEQ = 0 */ + while (loop > 0) { + if ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) == 0) + break; /* ready */ + + loop--; + if ((loop == 0) && (retry > 0)) { + rcar_micro_delay(1000U); /* wait 1ms */ + loop = 10000; + retry--; + } + } + +reset: + /* reset */ + SETR_32(SOFT_RST, (GETR_32(SOFT_RST) & (~SOFT_RST_SDRST))); + SETR_32(SOFT_RST, (GETR_32(SOFT_RST) | SOFT_RST_SDRST)); + + /* initialize */ + SETR_32(SD_INFO1, 0x00000000U); + SETR_32(SD_INFO2, SD_INFO2_CLEAR); + SETR_32(SD_INFO1_MASK, 0x00000000U); /* all interrupt disable */ + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); /* all interrupt disable */ +} + +static void emmc_read_response(uint32_t *response) +{ + uint8_t *p; + + if (response == NULL) + return; + + /* read response */ + if (mmc_drv_obj.response_length != EMMC_MAX_RESPONSE_LENGTH) { + *response = GETR_32(SD_RSP10); /* [39:8] */ + return; + } + + /* CSD or CID */ + p = (uint8_t *) (response); + emmc_little_to_big(p, ((GETR_32(SD_RSP76) << 8) + | (GETR_32(SD_RSP54) >> 24))); /* [127:96] */ + emmc_little_to_big(p + 4, ((GETR_32(SD_RSP54) << 8) + | (GETR_32(SD_RSP32) >> 24))); /* [95:64] */ + emmc_little_to_big(p + 8, ((GETR_32(SD_RSP32) << 8) + | (GETR_32(SD_RSP10) >> 24))); /* [63:32] */ + emmc_little_to_big(p + 12, (GETR_32(SD_RSP10) << 8)); +} + +static EMMC_ERROR_CODE emmc_response_check(uint32_t *response, + uint32_t error_mask) +{ + + HAL_MEMCARD_RESPONSE_TYPE response_type = + ((HAL_MEMCARD_RESPONSE_TYPE)mmc_drv_obj.cmd_info.cmd & HAL_MEMCARD_RESPONSE_TYPE_MASK); + + if (response == NULL) + return EMMC_ERR_PARAM; + + if (response_type == HAL_MEMCARD_RESPONSE_NONE) + return EMMC_SUCCESS; + + + if (response_type <= HAL_MEMCARD_RESPONSE_R1b) { + /* R1 or R1b */ + mmc_drv_obj.current_state = + (EMMC_R1_STATE) ((*response & EMMC_R1_STATE_MASK) >> + EMMC_R1_STATE_SHIFT); + if ((*response & error_mask) != 0) { + if ((0x80 & *response) != 0) { + ERROR("BL2: emmc SWITCH_ERROR\n"); + } + return EMMC_ERR_CARD_STATUS_BIT; + } + return EMMC_SUCCESS; + } + + if (response_type == HAL_MEMCARD_RESPONSE_R4) { + if ((*response & EMMC_R4_STATUS) != 0) + return EMMC_ERR_CARD_STATUS_BIT; + } + + return EMMC_SUCCESS; +} + +static void emmc_WaitCmd2Cmd_8Cycle(void) +{ + uint32_t dataL, wait = 0; + + dataL = GETR_32(SD_CLK_CTRL); + dataL &= 0x000000FF; + + switch (dataL) { + case 0xFF: + case 0x00: + case 0x01: + case 0x02: + case 0x04: + case 0x08: + case 0x10: + case 0x20: + wait = 10U; + break; + case 0x40: + wait = 20U; + break; + case 0x80: + wait = 30U; + break; + } + + rcar_micro_delay(wait); +} + +static void cmdErrSdInfo2Log(void) +{ + ERROR("BL2: emmc ERR SD_INFO2 = 0x%x\n", mmc_drv_obj.error_info.info2); +} + +static void emmc_data_transfer_dma(void) +{ + mmc_drv_obj.during_dma_transfer = TRUE; + mmc_drv_obj.dma_error_flag = FALSE; + + SETR_32(SD_INFO1_MASK, 0x00000000U); + SETR_32(SD_INFO2_MASK, (SD_INFO2_ALL_ERR | SD_INFO2_CLEAR)); + + /* DMAC setting */ + if (mmc_drv_obj.cmd_info.dir == HAL_MEMCARD_WRITE) { + /* transfer complete interrupt enable */ + SETR_32(DM_CM_INFO1_MASK, + (DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH0_ENABLE)); + SETR_32(DM_CM_INFO2_MASK, + (DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH0_ENABLE)); + /* BUFF --> FIFO */ + SETR_32(DM_CM_DTRAN_MODE, (DM_CM_DTRAN_MODE_CH0 | + DM_CM_DTRAN_MODE_BIT_WIDTH)); + } else { + /* transfer complete interrupt enable */ + SETR_32(DM_CM_INFO1_MASK, + (DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH1_ENABLE)); + SETR_32(DM_CM_INFO2_MASK, + (DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH1_ENABLE)); + /* FIFO --> BUFF */ + SETR_32(DM_CM_DTRAN_MODE, (DM_CM_DTRAN_MODE_CH1 + | DM_CM_DTRAN_MODE_BIT_WIDTH)); + } + SETR_32(DM_DTRAN_ADDR, (((uintptr_t) mmc_drv_obj.buff_address_virtual & + DM_DTRAN_ADDR_WRITE_MASK))); + + SETR_32(DM_CM_DTRAN_CTRL, DM_CM_DTRAN_CTRL_START); +} + +EMMC_ERROR_CODE emmc_exec_cmd(uint32_t error_mask, uint32_t *response) +{ + EMMC_ERROR_CODE rtn_code = EMMC_SUCCESS; + HAL_MEMCARD_RESPONSE_TYPE response_type; + HAL_MEMCARD_COMMAND_TYPE cmd_type; + EMMC_INT_STATE state; + uint32_t err_not_care_flag = FALSE; + + /* parameter check */ + if (response == NULL) { + emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD, EMMC_ERR_PARAM); + return EMMC_ERR_PARAM; + } + + /* state check */ + if (mmc_drv_obj.clock_enable != TRUE) { + emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + if (mmc_drv_obj.state_machine_blocking == TRUE) { + emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD, EMMC_ERR); + return EMMC_ERR; + } + + state = ESTATE_BEGIN; + response_type = + ((HAL_MEMCARD_RESPONSE_TYPE)mmc_drv_obj.cmd_info.cmd & + HAL_MEMCARD_RESPONSE_TYPE_MASK); + cmd_type = + ((HAL_MEMCARD_COMMAND_TYPE) mmc_drv_obj.cmd_info.cmd & + HAL_MEMCARD_COMMAND_TYPE_MASK); + + /* state machine */ + while ((mmc_drv_obj.force_terminate != TRUE) && (state != ESTATE_END)) { + /* The interrupt factor flag is observed. */ + emmc_interrupt(); + + /* wait interrupt */ + if (mmc_drv_obj.state_machine_blocking == TRUE) + continue; + + switch (state) { + case ESTATE_BEGIN: + /* Busy check */ + if ((mmc_drv_obj.error_info.info2 & SD_INFO2_CBSY) != 0) { + emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD, + EMMC_ERR_CARD_BUSY); + return EMMC_ERR_CARD_BUSY; + } + + /* clear register */ + SETR_32(SD_INFO1, 0x00000000U); + SETR_32(SD_INFO2, SD_INFO2_CLEAR); + SETR_32(SD_INFO1_MASK, SD_INFO1_INFO0); + SETR_32(SD_INFO2_MASK, + (SD_INFO2_ALL_ERR | SD_INFO2_CLEAR)); + + state = ESTATE_ISSUE_CMD; + /* through */ + + case ESTATE_ISSUE_CMD: + /* ARG */ + SETR_32(SD_ARG, mmc_drv_obj.cmd_info.arg); + /* issue cmd */ + SETR_32(SD_CMD, mmc_drv_obj.cmd_info.hw); + /* Set driver flag */ + mmc_drv_obj.during_cmd_processing = TRUE; + mmc_drv_obj.state_machine_blocking = TRUE; + + if (response_type == HAL_MEMCARD_RESPONSE_NONE) { + state = ESTATE_NON_RESP_CMD; + } else { + state = ESTATE_RCV_RESP; + } + + break; + + case ESTATE_NON_RESP_CMD: + /* interrupt disable */ + SETR_32(SD_INFO1_MASK, 0x00000000U); + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); + + /* check interrupt */ + if ((mmc_drv_obj.int_event2 & SD_INFO2_ALL_ERR) != 0) { + /* error interrupt */ + cmdErrSdInfo2Log(); + rtn_code = EMMC_ERR_INFO2; + state = ESTATE_ERROR; + } else if ((mmc_drv_obj.int_event1 & SD_INFO1_INFO0) == + 0) { + /* not receive expected interrupt */ + rtn_code = EMMC_ERR_RESPONSE; + state = ESTATE_ERROR; + } else { + emmc_WaitCmd2Cmd_8Cycle(); + state = ESTATE_END; + } + break; + + case ESTATE_RCV_RESP: + /* interrupt disable */ + SETR_32(SD_INFO1_MASK, 0x00000000U); + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); + + /* check interrupt */ + if ((mmc_drv_obj.int_event2 & SD_INFO2_ALL_ERR) != 0) { + if ((mmc_drv_obj.get_partition_access_flag == + TRUE) + && ((mmc_drv_obj.int_event2 & SD_INFO2_ERR6) + != 0U)) { + err_not_care_flag = TRUE; + rtn_code = EMMC_ERR_CMD_TIMEOUT; + } else { + /* error interrupt */ + cmdErrSdInfo2Log(); + rtn_code = EMMC_ERR_INFO2; + } + state = ESTATE_ERROR; + break; + } else if ((mmc_drv_obj.int_event1 & SD_INFO1_INFO0) == + 0) { + /* not receive expected interrupt */ + rtn_code = EMMC_ERR_RESPONSE; + state = ESTATE_ERROR; + break; + } + + /* read response */ + emmc_read_response(response); + + /* check response */ + rtn_code = emmc_response_check(response, error_mask); + if (rtn_code != EMMC_SUCCESS) { + state = ESTATE_ERROR; + break; + } + + if (response_type == HAL_MEMCARD_RESPONSE_R1b) { + /* R1b */ + SETR_32(SD_INFO2_MASK, + (SD_INFO2_ALL_ERR | SD_INFO2_CLEAR)); + state = ESTATE_RCV_RESPONSE_BUSY; + } else { + state = ESTATE_CHECK_RESPONSE_COMPLETE; + } + break; + + case ESTATE_RCV_RESPONSE_BUSY: + /* check interrupt */ + if ((mmc_drv_obj.int_event2 & SD_INFO2_ALL_ERR) != 0) { + /* error interrupt */ + cmdErrSdInfo2Log(); + rtn_code = EMMC_ERR_INFO2; + state = ESTATE_ERROR; + break; + } + /* DAT0 not Busy */ + if ((SD_INFO2_DAT0 & mmc_drv_obj.error_info.info2) != 0) { + state = ESTATE_CHECK_RESPONSE_COMPLETE; + break; + } + break; + + case ESTATE_CHECK_RESPONSE_COMPLETE: + if (cmd_type >= HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE) { + state = ESTATE_DATA_TRANSFER; + } else { + emmc_WaitCmd2Cmd_8Cycle(); + state = ESTATE_END; + } + break; + + case ESTATE_DATA_TRANSFER: + /* ADTC command */ + mmc_drv_obj.during_transfer = TRUE; + mmc_drv_obj.state_machine_blocking = TRUE; + + if (mmc_drv_obj.transfer_mode == HAL_MEMCARD_DMA) { + /* DMA */ + emmc_data_transfer_dma(); + } else { + /* PIO */ + /* interrupt enable (FIFO read/write enable) */ + if (mmc_drv_obj.cmd_info.dir == + HAL_MEMCARD_WRITE) { + SETR_32(SD_INFO2_MASK, + (SD_INFO2_BWE | SD_INFO2_ALL_ERR + | SD_INFO2_CLEAR)); + } else { + SETR_32(SD_INFO2_MASK, + (SD_INFO2_BRE | SD_INFO2_ALL_ERR + | SD_INFO2_CLEAR)); + } + } + state = ESTATE_DATA_TRANSFER_COMPLETE; + break; + + case ESTATE_DATA_TRANSFER_COMPLETE: + /* check interrupt */ + if ((mmc_drv_obj.int_event2 & SD_INFO2_ALL_ERR) != 0) { + /* error interrupt */ + cmdErrSdInfo2Log(); + rtn_code = EMMC_ERR_INFO2; + state = ESTATE_TRANSFER_ERROR; + break; + } + + /* DMAC error ? */ + if (mmc_drv_obj.dma_error_flag == TRUE) { + /* Error occurred in DMAC driver. */ + rtn_code = EMMC_ERR_FROM_DMAC_TRANSFER; + state = ESTATE_TRANSFER_ERROR; + } else if (mmc_drv_obj.during_dma_transfer == TRUE) { + /* DMAC not finished. unknown error */ + rtn_code = EMMC_ERR; + state = ESTATE_TRANSFER_ERROR; + } else { + SETR_32(SD_INFO1_MASK, SD_INFO1_INFO2); + SETR_32(SD_INFO2_MASK, + (SD_INFO2_ALL_ERR | SD_INFO2_CLEAR)); + + mmc_drv_obj.state_machine_blocking = TRUE; + + state = ESTATE_ACCESS_END; + } + break; + + case ESTATE_ACCESS_END: + + /* clear flag */ + if (mmc_drv_obj.transfer_mode == HAL_MEMCARD_DMA) { + /* W (CC_EXT_MODE, H'0000_1010) SD_BUF DMA transfer disabled */ + SETR_32(CC_EXT_MODE, CC_EXT_MODE_CLEAR); + SETR_32(SD_STOP, 0x00000000U); + mmc_drv_obj.during_dma_transfer = FALSE; + } + + SETR_32(SD_INFO1_MASK, 0x00000000U); + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); + SETR_32(SD_INFO1, 0x00000000U); + SETR_32(SD_INFO2, SD_INFO2_CLEAR); + + if ((mmc_drv_obj.int_event1 & SD_INFO1_INFO2) != 0) { + emmc_WaitCmd2Cmd_8Cycle(); + state = ESTATE_END; + } else { + state = ESTATE_ERROR; + } + break; + + case ESTATE_TRANSFER_ERROR: + /* The error occurred in the Data transfer. */ + if (mmc_drv_obj.transfer_mode == HAL_MEMCARD_DMA) { + /* W (CC_EXT_MODE, H'0000_1010) SD_BUF DMA transfer disabled */ + SETR_32(CC_EXT_MODE, CC_EXT_MODE_CLEAR); + SETR_32(SD_STOP, 0x00000000U); + mmc_drv_obj.during_dma_transfer = FALSE; + } + /* through */ + + case ESTATE_ERROR: + if (err_not_care_flag == TRUE) { + mmc_drv_obj.during_cmd_processing = FALSE; + } else { + emmc_softreset(); + emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD, + rtn_code); + } + return rtn_code; + + default: + state = ESTATE_END; + break; + } /* switch (state) */ + } /* while ( (mmc_drv_obj.force_terminate != TRUE) && (state != ESTATE_END) ) */ + + /* force terminate */ + if (mmc_drv_obj.force_terminate == TRUE) { + /* timeout timer is expired. Or, PIO data transfer error. */ + /* Timeout occurred in the DMA transfer. */ + if (mmc_drv_obj.during_dma_transfer == TRUE) { + mmc_drv_obj.during_dma_transfer = FALSE; + } + ERROR("BL2: emmc exec_cmd:EMMC_ERR_FORCE_TERMINATE\n"); + emmc_softreset(); + + return EMMC_ERR_FORCE_TERMINATE; /* error information has already been written. */ + } + + /* success */ + mmc_drv_obj.during_cmd_processing = FALSE; + mmc_drv_obj.during_transfer = FALSE; + + return EMMC_SUCCESS; +} diff --git a/drivers/renesas/common/emmc/emmc_config.h b/drivers/renesas/common/emmc/emmc_config.h new file mode 100644 index 000000000..16b6b8aa9 --- /dev/null +++ b/drivers/renesas/common/emmc/emmc_config.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMMC_CONFIG_H +#define EMMC_CONFIG_H + +/* RCA */ +#define EMMC_RCA 1UL +/* 314ms (freq = 400KHz, timeout Counter = 0x04(SDCLK * 2^17) */ +#define EMMC_RW_DATA_TIMEOUT 0x40UL +/* how many times to try after fail. Don't change. */ +#define EMMC_RETRY_COUNT 0 +#define EMMC_CMD_MAX 60UL /* Don't change. */ + +#define LOADIMAGE_FLAGS_DMA_ENABLE 0x00000001UL + +#endif /* EMMC_CONFIG_H */ diff --git a/drivers/renesas/common/emmc/emmc_def.h b/drivers/renesas/common/emmc/emmc_def.h new file mode 100644 index 000000000..178c795b9 --- /dev/null +++ b/drivers/renesas/common/emmc/emmc_def.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file emmc_def.h + * @brief eMMC boot is expecting this header file + * + */ + +#ifndef EMMC_DEF_H +#define EMMC_DEF_H + +#include "emmc_std.h" + +/* ************************ HEADER (INCLUDE) SECTION *********************** */ + +/* ***************** MACROS, CONSTANTS, COMPILATION FLAGS ****************** */ +#define EMMC_POWER_ON (1U) + +/* ********************** STRUCTURES, TYPE DEFINITIONS ********************* */ + +/* ********************** DECLARATION OF EXTERNAL DATA ********************* */ +extern st_mmc_base mmc_drv_obj; + +/* ************************** FUNCTION PROTOTYPES ************************** */ + +/** @brief for assembler program + */ +uint32_t _rom_emmc_finalize(void); + +/** @brief eMMC driver API + */ +EMMC_ERROR_CODE rcar_emmc_init(void); +EMMC_ERROR_CODE emmc_terminate(void); +EMMC_ERROR_CODE rcar_emmc_memcard_power(uint8_t mode); +EMMC_ERROR_CODE rcar_emmc_mount(void); +EMMC_ERROR_CODE emmc_set_request_mmc_clock(uint32_t *freq); +EMMC_ERROR_CODE emmc_send_idle_cmd(uint32_t arg); +EMMC_ERROR_CODE emmc_select_partition(EMMC_PARTITION_ID id); +EMMC_ERROR_CODE emmc_read_sector(uint32_t *buff_address_virtual, + uint32_t sector_number, uint32_t count, + uint32_t feature_flags); +EMMC_ERROR_CODE emmc_write_sector(uint32_t *buff_address_virtual, + uint32_t sector_number, uint32_t count, + uint32_t feature_flags); +EMMC_ERROR_CODE emmc_erase_sector(uint32_t *start_address, + uint32_t *end_address); +uint32_t emmc_bit_field(uint8_t *data, uint32_t top, uint32_t bottom); + +/** @brief interrupt service + */ +uint32_t emmc_interrupt(void); + +/** @brief DMA + */ + +/** @brief send command API + */ +EMMC_ERROR_CODE emmc_exec_cmd(uint32_t error_mask, uint32_t *response); +void emmc_make_nontrans_cmd(HAL_MEMCARD_COMMAND cmd, uint32_t arg); +void emmc_make_trans_cmd(HAL_MEMCARD_COMMAND cmd, uint32_t arg, + uint32_t *buff_address_virtual, uint32_t len, + HAL_MEMCARD_OPERATION dir, + HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode); +EMMC_ERROR_CODE emmc_set_ext_csd(uint32_t arg); + +/** @brief for error information + */ +void emmc_write_error_info(uint16_t func_no, EMMC_ERROR_CODE error_code); +void emmc_write_error_info_func_no(uint16_t func_no); + +/* ********************************* CODE ********************************** */ + +#endif /* EMMC_DEF_H */ +/* ******************************** END ************************************ */ diff --git a/drivers/renesas/common/emmc/emmc_hal.h b/drivers/renesas/common/emmc/emmc_hal.h new file mode 100644 index 000000000..0a8551719 --- /dev/null +++ b/drivers/renesas/common/emmc/emmc_hal.h @@ -0,0 +1,535 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMMC_HAL_H +#define EMMC_HAL_H + +/* memory card error/status types */ +#define HAL_MEMCARD_OUT_OF_RANGE 0x80000000L +#define HAL_MEMCARD_ADDRESS_ERROR 0x40000000L +#define HAL_MEMCARD_BLOCK_LEN_ERROR 0x20000000L +#define HAL_MEMCARD_ERASE_SEQ_ERROR 0x10000000L +#define HAL_MEMCARD_ERASE_PARAM 0x08000000L +#define HAL_MEMCARD_WP_VIOLATION 0x04000000L +#define HAL_MEMCARD_CARD_IS_LOCKED 0x02000000L +#define HAL_MEMCARD_LOCK_UNLOCK_FAILED 0x01000000L +#define HAL_MEMCARD_COM_CRC_ERROR 0x00800000L +#define HAL_MEMCARD_ILEGAL_COMMAND 0x00400000L +#define HAL_MEMCARD_CARD_ECC_FAILED 0x00200000L +#define HAL_MEMCARD_CC_ERROR 0x00100000L +#define HAL_MEMCARD_ERROR 0x00080000L +#define HAL_MEMCARD_UNDERRUN 0x00040000L +#define HAL_MEMCARD_OVERRUN 0x00020000L +#define HAL_MEMCARD_CIDCSD_OVERWRITE 0x00010000L +#define HAL_MEMCARD_WP_ERASE_SKIP 0x00008000L +#define HAL_MEMCARD_CARD_ECC_DISABLED 0x00004000L +#define HAL_MEMCARD_ERASE_RESET 0x00002000L +#define HAL_MEMCARD_CARD_STATE 0x00001E00L +#define HAL_MEMCARD_CARD_READY_FOR_DATA 0x00000100L +#define HAL_MEMCARD_APP_CMD 0x00000020L +#define HAL_MEMCARD_SWITCH_ERROR 0x00000080L +#define HAL_MEMCARD_AKE_SEQ_ERROR 0x00000008L +#define HAL_MEMCARD_NO_ERRORS 0x00000000L + +/* Memory card response types */ +#define HAL_MEMCARD_COMMAND_INDEX_MASK 0x0003f + +/* Type of the return value. */ +typedef enum { + HAL_MEMCARD_FAIL = 0U, + HAL_MEMCARD_OK = 1U, + HAL_MEMCARD_DMA_ALLOC_FAIL = 2U, /* DMA channel allocation failed */ + HAL_MEMCARD_DMA_TRANSFER_FAIL = 3U, /* DMA transfer failed */ + HAL_MEMCARD_CARD_STATUS_ERROR = 4U, /* card status non-masked error */ + HAL_MEMCARD_CMD_TIMEOUT = 5U, /* Command timeout occurred */ + HAL_MEMCARD_DATA_TIMEOUT = 6U, /* Data timeout occurred */ + HAL_MEMCARD_CMD_CRC_ERROR = 7U, /* Command CRC error occurred */ + HAL_MEMCARD_DATA_CRC_ERROR = 8U /* Data CRC error occurred */ +} HAL_MEMCARD_RETURN; + +/* memory access operation */ +typedef enum { + HAL_MEMCARD_READ = 0U, /* read */ + HAL_MEMCARD_WRITE = 1U /* write */ +} HAL_MEMCARD_OPERATION; + +/* Type of data width on memorycard bus */ +typedef enum { + HAL_MEMCARD_DATA_WIDTH_1_BIT = 0U, + HAL_MEMCARD_DATA_WIDTH_4_BIT = 1U, + HAL_MEMCARD_DATA_WIDTH_8_BIT = 2U +} HAL_MEMCARD_DATA_WIDTH; /* data (bus) width types */ + +/* Presence of the memory card */ +typedef enum { + HAL_MEMCARD_CARD_IS_IN = 0U, + HAL_MEMCARD_CARD_IS_OUT = 1U +} HAL_MEMCARD_PRESENCE_STATUS; /* presence status of the memory card */ + +/* mode of data transfer */ +typedef enum { + HAL_MEMCARD_DMA = 0U, + HAL_MEMCARD_NOT_DMA = 1U +} HAL_MEMCARD_DATA_TRANSFER_MODE; + +/* Memory card response types. */ +typedef enum hal_memcard_response_type { + HAL_MEMCARD_RESPONSE_NONE = 0x00000U, + HAL_MEMCARD_RESPONSE_R1 = 0x00100U, + HAL_MEMCARD_RESPONSE_R1b = 0x00200U, + HAL_MEMCARD_RESPONSE_R2 = 0x00300U, + HAL_MEMCARD_RESPONSE_R3 = 0x00400U, + HAL_MEMCARD_RESPONSE_R4 = 0x00500U, + HAL_MEMCARD_RESPONSE_R5 = 0x00600U, + HAL_MEMCARD_RESPONSE_R6 = 0x00700U, + HAL_MEMCARD_RESPONSE_R7 = 0x00800U, + HAL_MEMCARD_RESPONSE_TYPE_MASK = 0x00f00U +} HAL_MEMCARD_RESPONSE_TYPE; + +/* Memory card command types. */ +typedef enum hal_memcard_command_type { + HAL_MEMCARD_COMMAND_TYPE_BC = 0x00000U, + HAL_MEMCARD_COMMAND_TYPE_BCR = 0x01000U, + HAL_MEMCARD_COMMAND_TYPE_AC = 0x02000U, + HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE = 0x03000U, + HAL_MEMCARD_COMMAND_TYPE_ADTC_READ = 0x04000U, + HAL_MEMCARD_COMMAND_TYPE_MASK = 0x07000U +} HAL_MEMCARD_COMMAND_TYPE; + +/* Type of memory card */ +typedef enum hal_memcard_command_card_type { + HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON = 0x00000U, + HAL_MEMCARD_COMMAND_CARD_TYPE_MMC = 0x08000U, + HAL_MEMCARD_COMMAND_CARD_TYPE_SD = 0x10000U, + HAL_MEMCARD_COMMAND_CARD_TYPE_MASK = 0x18000U +} HAL_MEMCARD_COMMAND_CARD_TYPE; + +/* Memory card application command. */ +typedef enum hal_memcard_command_app_norm { + HAL_MEMCARD_COMMAND_NORMAL = 0x00000U, + HAL_MEMCARD_COMMAND_APP = 0x20000U, + HAL_MEMCARD_COMMAND_APP_NORM_MASK = 0x20000U +} HAL_MEMCARD_COMMAND_APP_NORM; + +/* Memory card command codes. */ +typedef enum { +/* class 0 and class 1 */ + /* CMD0 */ + CMD0_GO_IDLE_STATE = + 0U | (uint32_t)HAL_MEMCARD_RESPONSE_NONE | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BC | + (uint32_t) HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD1 */ + CMD1_SEND_OP_COND = + 1U | (uint32_t)HAL_MEMCARD_RESPONSE_R3 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BCR | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD2 */ + CMD2_ALL_SEND_CID_MMC = + 2U | (uint32_t)HAL_MEMCARD_RESPONSE_R2 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BCR | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + CMD2_ALL_SEND_CID_SD = + 2U | (uint32_t)HAL_MEMCARD_RESPONSE_R2 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BCR | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD3 */ + CMD3_SET_RELATIVE_ADDR = + 3U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + CMD3_SEND_RELATIVE_ADDR = + 3U | (uint32_t)HAL_MEMCARD_RESPONSE_R6 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD4 */ + CMD4_SET_DSR = + 4U | (uint32_t)HAL_MEMCARD_RESPONSE_NONE | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD5 */ + CMD5_SLEEP_AWAKE = + 5U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD6 */ + CMD6_SWITCH = + 6U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + CMD6_SWITCH_FUNC = + 6U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + ACMD6_SET_BUS_WIDTH = + 6U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + /* CMD7 */ + CMD7_SELECT_CARD = + 7U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD7(from Disconnected State to Programming State) */ + CMD7_SELECT_CARD_PROG = + 7U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + CMD7_DESELECT_CARD = + 7U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD8 */ + CMD8_SEND_EXT_CSD = + 8U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + CMD8_SEND_IF_COND = + 8U | (uint32_t)HAL_MEMCARD_RESPONSE_R7 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BCR | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD9 */ + CMD9_SEND_CSD = + 9U | (uint32_t)HAL_MEMCARD_RESPONSE_R2 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD10 */ + CMD10_SEND_CID = + 10U | (uint32_t)HAL_MEMCARD_RESPONSE_R2 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD11 */ + CMD11_READ_DAT_UNTIL_STOP = + 11U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD12 */ + CMD12_STOP_TRANSMISSION = + 12U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD12(R1b : write case) */ + CMD12_STOP_TRANSMISSION_WRITE = + 12U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD13 */ + CMD13_SEND_STATUS = + 13U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + ACMD13_SD_STATUS = + 13U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + /* CMD14 */ + CMD14_BUSTEST_R = + 14U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD15 */ + CMD15_GO_INACTIVE_STATE = + 15U | (uint32_t)HAL_MEMCARD_RESPONSE_NONE | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + +/* class 2 */ + /* CMD16 */ + CMD16_SET_BLOCKLEN = + 16U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD17 */ + CMD17_READ_SINGLE_BLOCK = + 17U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD18 */ + CMD18_READ_MULTIPLE_BLOCK = + 18U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD19 */ + CMD19_BUS_TEST_W = + 19U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + +/* class 3 */ + /* CMD20 */ + CMD20_WRITE_DAT_UNTIL_STOP = + 20U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD21 */ + CMD21 = 21U, + /* CMD22 */ + CMD22 = 22U, + ACMD22_SEND_NUM_WR_BLOCKS = + 22U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + +/* class 4 */ + /* CMD23 */ + CMD23_SET_BLOCK_COUNT = + 23U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + ACMD23_SET_WR_BLK_ERASE_COUNT = + 23U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + /* CMD24 */ + CMD24_WRITE_BLOCK = + 24U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD25 */ + CMD25_WRITE_MULTIPLE_BLOCK = + 25U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD26 */ + CMD26_PROGRAM_CID = + 26U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD27 */ + CMD27_PROGRAM_CSD = + 27U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + +/* class 6 */ + /* CMD28 */ + CMD28_SET_WRITE_PROT = + 28U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD29 */ + CMD29_CLR_WRITE_PROT = + 29U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD30 */ + CMD30_SEND_WRITE_PROT = + 30U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD31 */ + CMD30_SEND_WRITE_PROT_TYPE = + 31U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + +/* class 5 */ + /* CMD32 */ + CMD32_ERASE_WR_BLK_START = + 32U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD33 */ + CMD33_ERASE_WR_BLK_END = + 33U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD34 */ + CMD34 = 34U, + /* CMD35 */ + CMD35_ERASE_GROUP_START = + 35U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD36 */ + CMD36_ERASE_GROUP_END = + 36U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD37 */ + CMD37 = 37U, + /* CMD38 */ + CMD38_ERASE = + 38U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + +/* class 9 */ + /* CMD39 */ + CMD39_FASTIO = + 39U | (uint32_t)HAL_MEMCARD_RESPONSE_R4 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD40 */ + CMD40_GO_IRQSTATE = + 40U | (uint32_t)HAL_MEMCARD_RESPONSE_R5 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BCR | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD41 */ + CMD41 = 41, + ACMD41_SD_SEND_OP_COND = + 41U | (uint32_t)HAL_MEMCARD_RESPONSE_R3 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BCR | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + +/* class 7 */ + /* CMD42 */ + CMD42_LOCK_UNLOCK = + 42U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + ACMD42_SET_CLR_CARD_DETECT = + 42U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + CMD43 = 43U, /* CMD43 */ + CMD44 = 44U, /* CMD44 */ + CMD45 = 45U, /* CMD45 */ + CMD46 = 46U, /* CMD46 */ + CMD47 = 47U, /* CMD47 */ + CMD48 = 48U, /* CMD48 */ + CMD49 = 49U, /* CMD49 */ + CMD50 = 50U, /* CMD50 */ + CMD51 = 51U, /* CMD51 */ + ACMD51_SEND_SCR = + 51U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + CMD52 = 52U, /* CMD52 */ + CMD53 = 53U, /* CMD53 */ + CMD54 = 54U, /* CMD54 */ + +/* class 8 */ + /* CMD55 */ + CMD55_APP_CMD = + 55U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD56 */ + CMD56_GEN_CMD = + 56U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + CMD57 = 57U, /* CMD57 */ + CMD58 = 58U, /* CMD58 */ + CMD59 = 59U, /* CMD59 */ + CMD60 = 60U, /* CMD60 */ + CMD61 = 61U, /* CMD61 */ + CMD62 = 62U, /* CMD62 */ + CMD63 = 63U /* CMD63 */ +} HAL_MEMCARD_COMMAND; + +/* + * Configuration structure from HAL layer. + * + * If some field is not available it should be filled with 0xFF. + * The API version is 32-bit unsigned integer telling the version of the API. + * The integer is divided to four sections which each can be treated as a 8-bit + * unsigned number: + * Bits 31-24 make the most significant part of the version number. This number + * starts from 1 i.e. the second version of the API will be 0x02xxxxxx. This + * number changes only, if the API itself changes so much that it is not + * compatible anymore with older releases. + * Bits 23-16 API minor version number. For example API version 2.1 would be + * 0x0201xxxx. + * Bits 15-8 are the number of the year when release is done. The 0 is year + * 2000, 1 is year 2001 and so on + * Bits 7- are the week number when release is done. First full week of the + * year is 1 + * + * Example: let's assume that release 2.1 is done on week 10 year 2008 + * the version will get the value 0x0201080A + */ +typedef struct { + /* + * Version of the chipset API implementation + * + * bits [31:24] API specification major version number.<br> + * bits [23:16] API specification minor version number.<br> + * bits [15:8] API implementation year. (2000 = 0, 2001 = 1, ...) + * bits [7:0] API implementation week. + * Example: API spec version 4.0, implementation w46 2008 => 0x0400082E + */ + uint32_t api_version; + + /* maximum block count which can be transferred at once */ + uint32_t max_block_count; + + /* maximum clock frequence in Hz supported by HW */ + uint32_t max_clock_freq; + + /* maximum data bus width supported by HW */ + uint16_t max_data_width; + + /* Is high-speed mode supported by HW (yes=1, no=0) */ + uint8_t hs_mode_supported; + + /* Is memory card removable (yes=1, no=0) */ + uint8_t card_removable; + +} HAL_MEMCARD_HW_CONF; + +/* Configuration structure to HAL layer. */ +typedef struct { + /* how many times to try after fail, for instance sending command */ + uint32_t retries_after_fail; +} HAL_MEMCARD_INIT_CONF; + +#endif /* EMMC_HAL_H */ diff --git a/drivers/renesas/common/emmc/emmc_init.c b/drivers/renesas/common/emmc/emmc_init.c new file mode 100644 index 000000000..354aa3c82 --- /dev/null +++ b/drivers/renesas/common/emmc/emmc_init.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stddef.h> + +#include <lib/mmio.h> + +#include "emmc_config.h" +#include "emmc_hal.h" +#include "emmc_std.h" +#include "emmc_registers.h" +#include "emmc_def.h" +#include "rcar_private.h" + +st_mmc_base mmc_drv_obj; + +EMMC_ERROR_CODE rcar_emmc_memcard_power(uint8_t mode) +{ + + if (mode == TRUE) { + /* power on (Vcc&Vccq is always power on) */ + mmc_drv_obj.card_power_enable = TRUE; + } else { + /* power off (Vcc&Vccq is always power on) */ + mmc_drv_obj.card_power_enable = FALSE; + mmc_drv_obj.mount = FALSE; + mmc_drv_obj.selected = FALSE; + } + + return EMMC_SUCCESS; +} +static inline void emmc_set_retry_count(uint32_t retry) +{ + mmc_drv_obj.retries_after_fail = retry; +} + +static inline void emmc_set_data_timeout(uint32_t data_timeout) +{ + mmc_drv_obj.data_timeout = data_timeout; +} + +static void emmc_memset(uint8_t *buff, uint8_t data, uint32_t cnt) +{ + if (buff == NULL) { + return; + } + + while (cnt > 0) { + *buff++ = data; + cnt--; + } +} + +static void emmc_driver_config(void) +{ + emmc_set_retry_count(EMMC_RETRY_COUNT); + emmc_set_data_timeout(EMMC_RW_DATA_TIMEOUT); +} + +static void emmc_drv_init(void) +{ + emmc_memset((uint8_t *) (&mmc_drv_obj), 0, sizeof(st_mmc_base)); + mmc_drv_obj.card_present = HAL_MEMCARD_CARD_IS_IN; + mmc_drv_obj.data_timeout = EMMC_RW_DATA_TIMEOUT; + mmc_drv_obj.bus_width = HAL_MEMCARD_DATA_WIDTH_1_BIT; +} + +static EMMC_ERROR_CODE emmc_dev_finalize(void) +{ + EMMC_ERROR_CODE result; + uint32_t dataL; + + /* + * MMC power off + * the power supply of eMMC device is always turning on. + * RST_n : Hi --> Low level. + */ + result = rcar_emmc_memcard_power(FALSE); + + /* host controller reset */ + SETR_32(SD_INFO1, 0x00000000U); /* all interrupt clear */ + SETR_32(SD_INFO2, SD_INFO2_CLEAR); /* all interrupt clear */ + SETR_32(SD_INFO1_MASK, 0x00000000U); /* all interrupt disable */ + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); /* all interrupt disable */ + SETR_32(SD_CLK_CTRL, 0x00000000U); /* MMC clock stop */ + + dataL = mmio_read_32(CPG_SMSTPCR3); + if ((dataL & CPG_MSTP_MMC) == 0U) { + dataL |= (CPG_MSTP_MMC); + mmio_write_32(CPG_CPGWPR, (~dataL)); + mmio_write_32(CPG_SMSTPCR3, dataL); + } + + return result; +} + +static EMMC_ERROR_CODE emmc_dev_init(void) +{ + /* Enable clock supply to eMMC. */ + mstpcr_write(CPG_SMSTPCR3, CPG_MSTPSR3, CPG_MSTP_MMC); + + /* Set SD clock */ + mmio_write_32(CPG_CPGWPR, ~((uint32_t) (BIT9 | BIT0))); /* SD phy 200MHz */ + + /* Stop SDnH clock & SDn=200MHz */ + mmio_write_32(CPG_SDxCKCR, (BIT9 | BIT0)); + + /* MMCIF initialize */ + SETR_32(SD_INFO1, 0x00000000U); /* all interrupt clear */ + SETR_32(SD_INFO2, SD_INFO2_CLEAR); /* all interrupt clear */ + SETR_32(SD_INFO1_MASK, 0x00000000U); /* all interrupt disable */ + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); /* all interrupt disable */ + + SETR_32(HOST_MODE, 0x00000000U); /* SD_BUF access width = 64-bit */ + SETR_32(SD_OPTION, 0x0000C0EEU); /* Bus width = 1bit, timeout=MAX */ + SETR_32(SD_CLK_CTRL, 0x00000000U); /* Disable Automatic Control & Clock Output */ + + return EMMC_SUCCESS; +} + +static EMMC_ERROR_CODE emmc_reset_controller(void) +{ + EMMC_ERROR_CODE result; + + /* initialize mmc driver */ + emmc_drv_init(); + + /* initialize H/W */ + result = emmc_dev_init(); + if (result == EMMC_SUCCESS) { + mmc_drv_obj.initialize = TRUE; + } + + return result; + +} + +EMMC_ERROR_CODE emmc_terminate(void) +{ + EMMC_ERROR_CODE result; + + result = emmc_dev_finalize(); + + emmc_memset((uint8_t *) (&mmc_drv_obj), 0, sizeof(st_mmc_base)); + + return result; +} + +EMMC_ERROR_CODE rcar_emmc_init(void) +{ + EMMC_ERROR_CODE result; + + result = emmc_reset_controller(); + if (result == EMMC_SUCCESS) { + emmc_driver_config(); + } + + return result; +} diff --git a/drivers/renesas/common/emmc/emmc_interrupt.c b/drivers/renesas/common/emmc/emmc_interrupt.c new file mode 100644 index 000000000..092fdfb72 --- /dev/null +++ b/drivers/renesas/common/emmc/emmc_interrupt.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights + * reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stddef.h> + +#include <lib/mmio.h> + +#include "emmc_config.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_registers.h" +#include "emmc_std.h" +#include "rcar_def.h" + +static EMMC_ERROR_CODE emmc_trans_sector(uint32_t *buff_address_virtual); + +uint32_t emmc_interrupt(void) +{ + EMMC_ERROR_CODE result; + uint32_t prr_data; + uint32_t cut_ver; + uint32_t end_bit; + + prr_data = mmio_read_32((uintptr_t) RCAR_PRR); + cut_ver = prr_data & PRR_CUT_MASK; + if ((prr_data & PRR_PRODUCT_MASK) == PRR_PRODUCT_H3) { + if (cut_ver == PRR_PRODUCT_10) { + end_bit = BIT17; + } else if (cut_ver == PRR_PRODUCT_11) { + end_bit = BIT17; + } else { + end_bit = BIT20; + } + } else if ((prr_data & PRR_PRODUCT_MASK) == PRR_PRODUCT_M3) { + if (cut_ver == PRR_PRODUCT_10) { + end_bit = BIT17; + } else { + end_bit = BIT20; + } + } else { + end_bit = BIT20; + } + + /* SD_INFO */ + mmc_drv_obj.error_info.info1 = GETR_32(SD_INFO1); + mmc_drv_obj.error_info.info2 = GETR_32(SD_INFO2); + + /* SD_INFO EVENT */ + mmc_drv_obj.int_event1 = + mmc_drv_obj.error_info.info1 & GETR_32(SD_INFO1_MASK); + mmc_drv_obj.int_event2 = + mmc_drv_obj.error_info.info2 & GETR_32(SD_INFO2_MASK); + + /* ERR_STS */ + mmc_drv_obj.error_info.status1 = GETR_32(SD_ERR_STS1); + mmc_drv_obj.error_info.status2 = GETR_32(SD_ERR_STS2); + + /* DM_CM_INFO */ + mmc_drv_obj.error_info.dm_info1 = GETR_32(DM_CM_INFO1); + mmc_drv_obj.error_info.dm_info2 = GETR_32(DM_CM_INFO2); + + /* DM_CM_INFO EVENT */ + mmc_drv_obj.dm_event1 = + mmc_drv_obj.error_info.dm_info1 & GETR_32(DM_CM_INFO1_MASK); + mmc_drv_obj.dm_event2 = + mmc_drv_obj.error_info.dm_info2 & GETR_32(DM_CM_INFO2_MASK); + + /* ERR SD_INFO2 */ + if ((SD_INFO2_ALL_ERR & mmc_drv_obj.int_event2) != 0) { + SETR_32(SD_INFO1_MASK, 0x00000000U); /* interrupt disable */ + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); /* interrupt disable */ + SETR_32(SD_INFO1, 0x00000000U); /* interrupt clear */ + SETR_32(SD_INFO2, SD_INFO2_CLEAR); /* interrupt clear */ + mmc_drv_obj.state_machine_blocking = FALSE; + } + + /* PIO Transfer */ + /* BWE/BRE */ + else if (((SD_INFO2_BWE | SD_INFO2_BRE) & mmc_drv_obj.int_event2)) { + /* BWE */ + if (SD_INFO2_BWE & mmc_drv_obj.int_event2) { + SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BWE)); + } + /* BRE */ + else { + SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BRE)); + } + + result = emmc_trans_sector(mmc_drv_obj.buff_address_virtual); + mmc_drv_obj.buff_address_virtual += EMMC_BLOCK_LENGTH; + mmc_drv_obj.remain_size -= EMMC_BLOCK_LENGTH; + + if (result != EMMC_SUCCESS) { + /* data transfer error */ + emmc_write_error_info(EMMC_FUNCNO_NONE, result); + + /* Panic */ + SETR_32(SD_INFO1_MASK, 0x00000000U); + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); + SETR_32(SD_INFO1, 0x00000000U); + /* interrupt clear */ + SETR_32(SD_INFO2, SD_INFO2_CLEAR); + mmc_drv_obj.force_terminate = TRUE; + } else { + mmc_drv_obj.during_transfer = FALSE; + } + mmc_drv_obj.state_machine_blocking = FALSE; + } + + /* DMA_TRANSFER */ + /* DM_CM_INFO1: DMA-ch0 transfer complete or error occurred */ + else if ((BIT16 & mmc_drv_obj.dm_event1) != 0) { + SETR_32(DM_CM_INFO1, 0x00000000U); + SETR_32(DM_CM_INFO2, 0x00000000U); + /* interrupt clear */ + SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BWE)); + /* DM_CM_INFO2: DMA-ch0 error occurred */ + if ((BIT16 & mmc_drv_obj.dm_event2) != 0) { + mmc_drv_obj.dma_error_flag = TRUE; + } else { + mmc_drv_obj.during_dma_transfer = FALSE; + mmc_drv_obj.during_transfer = FALSE; + } + /* wait next interrupt */ + mmc_drv_obj.state_machine_blocking = FALSE; + } + /* DM_CM_INFO1: DMA-ch1 transfer complete or error occurred */ + else if ((end_bit & mmc_drv_obj.dm_event1) != 0U) { + SETR_32(DM_CM_INFO1, 0x00000000U); + SETR_32(DM_CM_INFO2, 0x00000000U); + /* interrupt clear */ + SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BRE)); + /* DM_CM_INFO2: DMA-ch1 error occurred */ + if ((BIT17 & mmc_drv_obj.dm_event2) != 0) { + mmc_drv_obj.dma_error_flag = TRUE; + } else { + mmc_drv_obj.during_dma_transfer = FALSE; + mmc_drv_obj.during_transfer = FALSE; + } + /* wait next interrupt */ + mmc_drv_obj.state_machine_blocking = FALSE; + } + + /* Response end */ + else if ((SD_INFO1_INFO0 & mmc_drv_obj.int_event1) != 0) { + /* interrupt clear */ + SETR_32(SD_INFO1, (GETR_32(SD_INFO1) & ~SD_INFO1_INFO0)); + mmc_drv_obj.state_machine_blocking = FALSE; + } + /* Access end */ + else if ((SD_INFO1_INFO2 & mmc_drv_obj.int_event1) != 0) { + /* interrupt clear */ + SETR_32(SD_INFO1, (GETR_32(SD_INFO1) & ~SD_INFO1_INFO2)); + mmc_drv_obj.state_machine_blocking = FALSE; + } else { + /* nothing to do. */ + } + + return (uint32_t) 0; +} + +static EMMC_ERROR_CODE emmc_trans_sector(uint32_t *buff_address_virtual) +{ + uint32_t length, i; + uint64_t *bufPtrLL; + + if (buff_address_virtual == NULL) { + return EMMC_ERR_PARAM; + } + + if ((mmc_drv_obj.during_transfer != TRUE) + || (mmc_drv_obj.remain_size == 0)) { + return EMMC_ERR_STATE; + } + + bufPtrLL = (uint64_t *) buff_address_virtual; + length = mmc_drv_obj.remain_size; + + /* data transefer */ + for (i = 0; i < (length >> 3); i++) { + /* Write */ + if (mmc_drv_obj.cmd_info.dir == HAL_MEMCARD_WRITE) { + SETR_64(SD_BUF0, *bufPtrLL); /* buffer --> FIFO */ + } + /* Read */ + else { + /* Checks when the read data reaches SD_SIZE. */ + /* The BRE bit is cleared at emmc_interrupt function. */ + if (((i % + (uint32_t) (EMMC_BLOCK_LENGTH >> + EMMC_BUF_SIZE_SHIFT)) == 0U) + && (i != 0U)) { + /* BRE check */ + while (((GETR_32(SD_INFO2)) & SD_INFO2_BRE) == + 0U) { + /* ERROR check */ + if (((GETR_32(SD_INFO2)) & + SD_INFO2_ALL_ERR) != 0U) { + return EMMC_ERR_TRANSFER; + } + } + /* BRE clear */ + SETR_32(SD_INFO2, + (uint32_t) (GETR_32(SD_INFO2) & + ~SD_INFO2_BRE)); + } + *bufPtrLL = GETR_64(SD_BUF0); /* FIFO --> buffer */ + } + bufPtrLL++; + } + + return EMMC_SUCCESS; +} diff --git a/drivers/renesas/common/emmc/emmc_mount.c b/drivers/renesas/common/emmc/emmc_mount.c new file mode 100644 index 000000000..e04afd4cf --- /dev/null +++ b/drivers/renesas/common/emmc/emmc_mount.c @@ -0,0 +1,686 @@ +/* + * 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 "emmc_config.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_registers.h" +#include "emmc_std.h" +#include "micro_delay.h" +#include "rcar_def.h" + +static EMMC_ERROR_CODE emmc_clock_ctrl(uint8_t mode); +static EMMC_ERROR_CODE emmc_card_init(void); +static EMMC_ERROR_CODE emmc_high_speed(void); +static EMMC_ERROR_CODE emmc_bus_width(uint32_t width); +static uint32_t emmc_set_timeout_register_value(uint32_t freq); +static void set_sd_clk(uint32_t clkDiv); +static uint32_t emmc_calc_tran_speed(uint32_t *freq); +static void emmc_get_partition_access(void); +static void emmc_set_bootpartition(void); + +static void emmc_set_bootpartition(void) +{ + uint32_t reg; + + reg = mmio_read_32(RCAR_PRR) & (PRR_PRODUCT_MASK | PRR_CUT_MASK); + if (reg == PRR_PRODUCT_M3_CUT10) { + mmc_drv_obj.boot_partition_en = + (EMMC_PARTITION_ID) ((mmc_drv_obj.ext_csd_data[179] & + EMMC_BOOT_PARTITION_EN_MASK) >> + EMMC_BOOT_PARTITION_EN_SHIFT); + } else if ((reg == PRR_PRODUCT_H3_CUT20) + || (reg == PRR_PRODUCT_M3_CUT11)) { + mmc_drv_obj.boot_partition_en = mmc_drv_obj.partition_access; + } else { + if ((mmio_read_32(MFISBTSTSR) & MFISBTSTSR_BOOT_PARTITION) != + 0U) { + mmc_drv_obj.boot_partition_en = PARTITION_ID_BOOT_2; + } else { + mmc_drv_obj.boot_partition_en = PARTITION_ID_BOOT_1; + } + } +} + +static EMMC_ERROR_CODE emmc_card_init(void) +{ + int32_t retry; + uint32_t freq = MMC_400KHZ; /* 390KHz */ + EMMC_ERROR_CODE result; + uint32_t result_calc; + + /* state check */ + if ((mmc_drv_obj.initialize != TRUE) + || (mmc_drv_obj.card_power_enable != TRUE) + || ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) != 0) + ) { + emmc_write_error_info(EMMC_FUNCNO_CARD_INIT, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* clock on (force change) */ + mmc_drv_obj.current_freq = 0; + mmc_drv_obj.max_freq = MMC_20MHZ; + result = emmc_set_request_mmc_clock(&freq); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return EMMC_ERR; + } + + rcar_micro_delay(1000U); /* wait 1ms */ + + /* Get current access partition */ + emmc_get_partition_access(); + + /* CMD0, arg=0x00000000 */ + result = emmc_send_idle_cmd(0x00000000); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + rcar_micro_delay(200U); /* wait 74clock 390kHz(189.74us) */ + + /* CMD1 */ + emmc_make_nontrans_cmd(CMD1_SEND_OP_COND, EMMC_HOST_OCR_VALUE); + for (retry = 300; retry > 0; retry--) { + result = + emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + if ((mmc_drv_obj.r3_ocr & EMMC_OCR_STATUS_BIT) != 0) { + break; /* card is ready. exit loop */ + } + rcar_micro_delay(1000U); /* wait 1ms */ + } + + if (retry == 0) { + emmc_write_error_info(EMMC_FUNCNO_CARD_INIT, EMMC_ERR_TIMEOUT); + return EMMC_ERR_TIMEOUT; + } + + switch (mmc_drv_obj.r3_ocr & EMMC_OCR_ACCESS_MODE_MASK) { + case EMMC_OCR_ACCESS_MODE_SECT: + mmc_drv_obj.access_mode = TRUE; /* sector mode */ + break; + default: + /* unknown value */ + emmc_write_error_info(EMMC_FUNCNO_CARD_INIT, EMMC_ERR); + return EMMC_ERR; + } + + /* CMD2 */ + emmc_make_nontrans_cmd(CMD2_ALL_SEND_CID_MMC, 0x00000000); + mmc_drv_obj.response = (uint32_t *) (&mmc_drv_obj.cid_data[0]); /* use CID special buffer */ + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + /* CMD3 */ + emmc_make_nontrans_cmd(CMD3_SET_RELATIVE_ADDR, EMMC_RCA << 16); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + /* CMD9 (CSD) */ + emmc_make_nontrans_cmd(CMD9_SEND_CSD, EMMC_RCA << 16); + mmc_drv_obj.response = (uint32_t *) (&mmc_drv_obj.csd_data[0]); /* use CSD special buffer */ + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + /* card version check */ + if (EMMC_CSD_SPEC_VARS() < 4) { + emmc_write_error_info(EMMC_FUNCNO_CARD_INIT, + EMMC_ERR_ILLEGAL_CARD); + return EMMC_ERR_ILLEGAL_CARD; + } + + /* CMD7 (select card) */ + emmc_make_nontrans_cmd(CMD7_SELECT_CARD, EMMC_RCA << 16); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + mmc_drv_obj.selected = TRUE; + + /* + * card speed check + * Card spec is calculated from TRAN_SPEED(CSD) + */ + result_calc = emmc_calc_tran_speed(&freq); + if (result_calc == 0) { + emmc_write_error_info(EMMC_FUNCNO_CARD_INIT, + EMMC_ERR_ILLEGAL_CARD); + return EMMC_ERR_ILLEGAL_CARD; + } + mmc_drv_obj.max_freq = freq; /* max frequency (card spec) */ + + result = emmc_set_request_mmc_clock(&freq); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return EMMC_ERR; + } + + /* set read/write timeout */ + mmc_drv_obj.data_timeout = emmc_set_timeout_register_value(freq); + SETR_32(SD_OPTION, + ((GETR_32(SD_OPTION) & ~(SD_OPTION_TIMEOUT_CNT_MASK)) | + mmc_drv_obj.data_timeout)); + + /* SET_BLOCKLEN(512byte) */ + /* CMD16 */ + emmc_make_nontrans_cmd(CMD16_SET_BLOCKLEN, EMMC_BLOCK_LENGTH); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + /* Transfer Data Length */ + SETR_32(SD_SIZE, EMMC_BLOCK_LENGTH); + + /* CMD8 (EXT_CSD) */ + emmc_make_trans_cmd(CMD8_SEND_EXT_CSD, 0x00000000, + (uint32_t *) (&mmc_drv_obj.ext_csd_data[0]), + EMMC_MAX_EXT_CSD_LENGTH, HAL_MEMCARD_READ, + HAL_MEMCARD_NOT_DMA); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + /* + * CMD12 is not send. + * If BUS initialization is failed, user must be execute Bus initialization again. + * Bus initialization is start CMD0(soft reset command). + */ + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + /* Set boot partition */ + emmc_set_bootpartition(); + + return EMMC_SUCCESS; +} + +static EMMC_ERROR_CODE emmc_high_speed(void) +{ + uint32_t freq; /* High speed mode clock frequency */ + EMMC_ERROR_CODE result; + uint8_t cardType; + + /* state check */ + if (mmc_drv_obj.selected != TRUE) { + emmc_write_error_info(EMMC_FUNCNO_HIGH_SPEED, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* max frequency */ + cardType = (uint8_t) mmc_drv_obj.ext_csd_data[EMMC_EXT_CSD_CARD_TYPE]; + if ((cardType & EMMC_EXT_CSD_CARD_TYPE_52MHZ) != 0) + freq = MMC_52MHZ; + else if ((cardType & EMMC_EXT_CSD_CARD_TYPE_26MHZ) != 0) + freq = MMC_26MHZ; + else + freq = MMC_20MHZ; + + /* Hi-Speed-mode selection */ + if ((freq == MMC_52MHZ) || (freq == MMC_26MHZ)) { + /* CMD6 */ + emmc_make_nontrans_cmd(CMD6_SWITCH, EMMC_SWITCH_HS_TIMING); + result = + emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_HIGH_SPEED); + return result; + } + + mmc_drv_obj.hs_timing = TIMING_HIGH_SPEED; /* High-Speed */ + } + + /* set mmc clock */ + mmc_drv_obj.max_freq = freq; + result = emmc_set_request_mmc_clock(&freq); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_HIGH_SPEED); + return EMMC_ERR; + } + + /* set read/write timeout */ + mmc_drv_obj.data_timeout = emmc_set_timeout_register_value(freq); + SETR_32(SD_OPTION, + ((GETR_32(SD_OPTION) & ~(SD_OPTION_TIMEOUT_CNT_MASK)) | + mmc_drv_obj.data_timeout)); + + /* CMD13 */ + emmc_make_nontrans_cmd(CMD13_SEND_STATUS, EMMC_RCA << 16); + result = + emmc_exec_cmd(EMMC_R1_ERROR_MASK_WITHOUT_CRC, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_HIGH_SPEED); + return result; + } + + return EMMC_SUCCESS; +} + +static EMMC_ERROR_CODE emmc_clock_ctrl(uint8_t mode) +{ + uint32_t value; + + /* busy check */ + if ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) != 0) { + emmc_write_error_info(EMMC_FUNCNO_SET_CLOCK, + EMMC_ERR_CARD_BUSY); + return EMMC_ERR; + } + + if (mode == TRUE) { + /* clock ON */ + value = + ((GETR_32(SD_CLK_CTRL) | MMC_SD_CLK_START) & + SD_CLK_WRITE_MASK); + SETR_32(SD_CLK_CTRL, value); /* on */ + mmc_drv_obj.clock_enable = TRUE; + } else { + /* clock OFF */ + value = + ((GETR_32(SD_CLK_CTRL) & MMC_SD_CLK_STOP) & + SD_CLK_WRITE_MASK); + SETR_32(SD_CLK_CTRL, value); /* off */ + mmc_drv_obj.clock_enable = FALSE; + } + + return EMMC_SUCCESS; +} + +static EMMC_ERROR_CODE emmc_bus_width(uint32_t width) +{ + EMMC_ERROR_CODE result = EMMC_ERR; + + /* parameter check */ + if ((width != 8) && (width != 4) && (width != 1)) { + emmc_write_error_info(EMMC_FUNCNO_BUS_WIDTH, EMMC_ERR_PARAM); + return EMMC_ERR_PARAM; + } + + /* state check */ + if (mmc_drv_obj.selected != TRUE) { + emmc_write_error_info(EMMC_FUNCNO_BUS_WIDTH, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* 2 = 8bit, 1 = 4bit, 0 =1bit */ + mmc_drv_obj.bus_width = (HAL_MEMCARD_DATA_WIDTH) (width >> 2); + + /* CMD6 */ + emmc_make_nontrans_cmd(CMD6_SWITCH, + (EMMC_SWITCH_BUS_WIDTH_1 | + (mmc_drv_obj.bus_width << 8))); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + /* occurred error */ + mmc_drv_obj.bus_width = HAL_MEMCARD_DATA_WIDTH_1_BIT; + goto EXIT; + } + + switch (mmc_drv_obj.bus_width) { + case HAL_MEMCARD_DATA_WIDTH_1_BIT: + SETR_32(SD_OPTION, + ((GETR_32(SD_OPTION) & ~(BIT15 | BIT13)) | BIT15)); + break; + case HAL_MEMCARD_DATA_WIDTH_4_BIT: + SETR_32(SD_OPTION, (GETR_32(SD_OPTION) & ~(BIT15 | BIT13))); + break; + case HAL_MEMCARD_DATA_WIDTH_8_BIT: + SETR_32(SD_OPTION, + ((GETR_32(SD_OPTION) & ~(BIT15 | BIT13)) | BIT13)); + break; + default: + goto EXIT; + } + + /* CMD13 */ + emmc_make_nontrans_cmd(CMD13_SEND_STATUS, EMMC_RCA << 16); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + goto EXIT; + } + + /* CMD8 (EXT_CSD) */ + emmc_make_trans_cmd(CMD8_SEND_EXT_CSD, 0x00000000, + (uint32_t *) (&mmc_drv_obj.ext_csd_data[0]), + EMMC_MAX_EXT_CSD_LENGTH, HAL_MEMCARD_READ, + HAL_MEMCARD_NOT_DMA); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + goto EXIT; + } + + return EMMC_SUCCESS; + +EXIT: + emmc_write_error_info(EMMC_FUNCNO_BUS_WIDTH, result); + ERROR("BL2: emmc bus_width error end\n"); + return result; +} + +EMMC_ERROR_CODE emmc_select_partition(EMMC_PARTITION_ID id) +{ + EMMC_ERROR_CODE result; + uint32_t arg; + uint32_t partition_config; + + /* state check */ + if (mmc_drv_obj.mount != TRUE) { + emmc_write_error_info(EMMC_FUNCNO_NONE, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* id = PARTITION_ACCESS(Bit[2:0]) */ + if ((id & ~PARTITION_ID_MASK) != 0) { + emmc_write_error_info(EMMC_FUNCNO_NONE, EMMC_ERR_PARAM); + return EMMC_ERR_PARAM; + } + + /* EXT_CSD[179] value */ + partition_config = + (uint32_t) mmc_drv_obj.ext_csd_data[EMMC_EXT_CSD_PARTITION_CONFIG]; + if ((partition_config & PARTITION_ID_MASK) == id) { + result = EMMC_SUCCESS; + } else { + + partition_config = + (uint32_t) ((partition_config & ~PARTITION_ID_MASK) | id); + arg = EMMC_SWITCH_PARTITION_CONFIG | (partition_config << 8); + + result = emmc_set_ext_csd(arg); + } + + return result; +} + +static void set_sd_clk(uint32_t clkDiv) +{ + uint32_t dataL; + + dataL = (GETR_32(SD_CLK_CTRL) & (~SD_CLK_CTRL_CLKDIV_MASK)); + + switch (clkDiv) { + case 1: + dataL |= 0x000000FFU; + break; /* 1/1 */ + case 2: + dataL |= 0x00000000U; + break; /* 1/2 */ + case 4: + dataL |= 0x00000001U; + break; /* 1/4 */ + case 8: + dataL |= 0x00000002U; + break; /* 1/8 */ + case 16: + dataL |= 0x00000004U; + break; /* 1/16 */ + case 32: + dataL |= 0x00000008U; + break; /* 1/32 */ + case 64: + dataL |= 0x00000010U; + break; /* 1/64 */ + case 128: + dataL |= 0x00000020U; + break; /* 1/128 */ + case 256: + dataL |= 0x00000040U; + break; /* 1/256 */ + case 512: + dataL |= 0x00000080U; + break; /* 1/512 */ + } + + SETR_32(SD_CLK_CTRL, dataL); + mmc_drv_obj.current_freq = (uint32_t) clkDiv; +} + +static void emmc_get_partition_access(void) +{ + uint32_t reg; + EMMC_ERROR_CODE result; + + reg = mmio_read_32(RCAR_PRR) & (PRR_PRODUCT_MASK | PRR_CUT_MASK); + if ((reg == PRR_PRODUCT_H3_CUT20) || (reg == PRR_PRODUCT_M3_CUT11)) { + SETR_32(SD_OPTION, 0x000060EEU); /* 8 bits width */ + /* CMD8 (EXT_CSD) */ + emmc_make_trans_cmd(CMD8_SEND_EXT_CSD, 0x00000000U, + (uint32_t *) (&mmc_drv_obj.ext_csd_data[0]), + EMMC_MAX_EXT_CSD_LENGTH, + HAL_MEMCARD_READ, HAL_MEMCARD_NOT_DMA); + mmc_drv_obj.get_partition_access_flag = TRUE; + result = + emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + mmc_drv_obj.get_partition_access_flag = FALSE; + if (result == EMMC_SUCCESS) { + mmc_drv_obj.partition_access = + (EMMC_PARTITION_ID) (mmc_drv_obj.ext_csd_data[179] + & PARTITION_ID_MASK); + } else if (result == EMMC_ERR_CMD_TIMEOUT) { + mmc_drv_obj.partition_access = PARTITION_ID_BOOT_1; + } else { + emmc_write_error_info(EMMC_FUNCNO_GET_PERTITION_ACCESS, + result); + panic(); + } + SETR_32(SD_OPTION, 0x0000C0EEU); /* Initialize */ + } +} + +static uint32_t emmc_calc_tran_speed(uint32_t *freq) +{ + const uint32_t unit[8] = { 10000U, 100000U, 1000000U, 10000000U, + 0U, 0U, 0U, 0U }; /* frequency unit (1/10) */ + const uint32_t mult[16] = { 0U, 10U, 12U, 13U, 15U, 20U, 26U, 30U, 35U, + 40U, 45U, 52U, 55U, 60U, 70U, 80U }; + uint32_t tran_speed = EMMC_CSD_TRAN_SPEED(); + uint32_t max_freq; + uint32_t result; + + /* + * tran_speed = 0x32 + * unit[tran_speed&0x7] = uint[0x2] = 1000000 + * mult[(tran_speed&0x78)>>3] = mult[0x30>>3] = mult[6] = 26 + * 1000000 * 26 = 26000000 (26MHz) + */ + + result = 1; + max_freq = + unit[tran_speed & EMMC_TRANSPEED_FREQ_UNIT_MASK] * + mult[(tran_speed & EMMC_TRANSPEED_MULT_MASK) >> + EMMC_TRANSPEED_MULT_SHIFT]; + + if (max_freq == 0) { + result = 0; + } else if (max_freq >= MMC_FREQ_52MHZ) { + *freq = MMC_52MHZ; + } else if (max_freq >= MMC_FREQ_26MHZ) { + *freq = MMC_26MHZ; + } else if (max_freq >= MMC_FREQ_20MHZ) { + *freq = MMC_20MHZ; + } else { + *freq = MMC_400KHZ; + } + + return result; +} + +static uint32_t emmc_set_timeout_register_value(uint32_t freq) +{ + uint32_t timeout_cnt; /* SD_OPTION - Timeout Counter */ + + switch (freq) { + case 1U: + timeout_cnt = 0xE0U; + break; /* SDCLK * 2^27 */ + case 2U: + timeout_cnt = 0xE0U; + break; /* SDCLK * 2^27 */ + case 4U: + timeout_cnt = 0xD0U; + break; /* SDCLK * 2^26 */ + case 8U: + timeout_cnt = 0xC0U; + break; /* SDCLK * 2^25 */ + case 16U: + timeout_cnt = 0xB0U; + break; /* SDCLK * 2^24 */ + case 32U: + timeout_cnt = 0xA0U; + break; /* SDCLK * 2^23 */ + case 64U: + timeout_cnt = 0x90U; + break; /* SDCLK * 2^22 */ + case 128U: + timeout_cnt = 0x80U; + break; /* SDCLK * 2^21 */ + case 256U: + timeout_cnt = 0x70U; + break; /* SDCLK * 2^20 */ + case 512U: + timeout_cnt = 0x70U; + break; /* SDCLK * 2^20 */ + default: + timeout_cnt = 0xE0U; + break; /* SDCLK * 2^27 */ + } + + return timeout_cnt; +} + +EMMC_ERROR_CODE emmc_set_ext_csd(uint32_t arg) +{ + EMMC_ERROR_CODE result; + + /* CMD6 */ + emmc_make_nontrans_cmd(CMD6_SWITCH, arg); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; + } + + /* CMD13 */ + emmc_make_nontrans_cmd(CMD13_SEND_STATUS, EMMC_RCA << 16); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; + } + + /* CMD8 (EXT_CSD) */ + emmc_make_trans_cmd(CMD8_SEND_EXT_CSD, 0x00000000, + (uint32_t *) (&mmc_drv_obj.ext_csd_data[0]), + EMMC_MAX_EXT_CSD_LENGTH, HAL_MEMCARD_READ, + HAL_MEMCARD_NOT_DMA); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; + } + return EMMC_SUCCESS; +} + +EMMC_ERROR_CODE emmc_set_request_mmc_clock(uint32_t *freq) +{ + /* parameter check */ + if (freq == NULL) { + emmc_write_error_info(EMMC_FUNCNO_SET_CLOCK, EMMC_ERR_PARAM); + return EMMC_ERR_PARAM; + } + + /* state check */ + if ((mmc_drv_obj.initialize != TRUE) + || (mmc_drv_obj.card_power_enable != TRUE)) { + emmc_write_error_info(EMMC_FUNCNO_SET_CLOCK, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* clock is already running in the desired frequency. */ + if ((mmc_drv_obj.clock_enable == TRUE) + && (mmc_drv_obj.current_freq == *freq)) { + return EMMC_SUCCESS; + } + + /* busy check */ + if ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) != 0) { + emmc_write_error_info(EMMC_FUNCNO_SET_CLOCK, + EMMC_ERR_CARD_BUSY); + return EMMC_ERR; + } + + set_sd_clk(*freq); + mmc_drv_obj.clock_enable = FALSE; + + return emmc_clock_ctrl(TRUE); /* clock on */ +} + +EMMC_ERROR_CODE rcar_emmc_mount(void) +{ + EMMC_ERROR_CODE result; + + /* state check */ + if ((mmc_drv_obj.initialize != TRUE) + || (mmc_drv_obj.card_power_enable != TRUE) + || ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) != 0) + ) { + emmc_write_error_info(EMMC_FUNCNO_MOUNT, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* initialize card (IDLE state --> Transfer state) */ + result = emmc_card_init(); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + if (emmc_clock_ctrl(FALSE) != EMMC_SUCCESS) { + /* nothing to do. */ + } + return result; + } + + /* Switching high speed mode */ + result = emmc_high_speed(); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_HIGH_SPEED); + if (emmc_clock_ctrl(FALSE) != EMMC_SUCCESS) { + /* nothing to do. */ + } + return result; + } + + /* Changing the data bus width */ + result = emmc_bus_width(8); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_BUS_WIDTH); + if (emmc_clock_ctrl(FALSE) != EMMC_SUCCESS) { + /* nothing to do. */ + } + return result; + } + + /* mount complete */ + mmc_drv_obj.mount = TRUE; + + return EMMC_SUCCESS; +} diff --git a/drivers/renesas/common/emmc/emmc_read.c b/drivers/renesas/common/emmc/emmc_read.c new file mode 100644 index 000000000..96e73ca56 --- /dev/null +++ b/drivers/renesas/common/emmc/emmc_read.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> + +#include "emmc_config.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_registers.h" +#include "emmc_std.h" + +#define MIN_EMMC(a, b) (((a) < (b)) ? (a) : (b)) +#define EMMC_RW_SECTOR_COUNT_MAX 0x0000ffffU + +static EMMC_ERROR_CODE emmc_multiple_block_read(uint32_t *buff_address_virtual, + uint32_t sector_number, uint32_t count, + HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode) +{ + EMMC_ERROR_CODE result; + + /* parameter check */ + if ((count > EMMC_RW_SECTOR_COUNT_MAX) + || (count == 0) + || ((transfer_mode != HAL_MEMCARD_DMA) + && (transfer_mode != HAL_MEMCARD_NOT_DMA)) + ) { + emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, EMMC_ERR_PARAM); + return EMMC_ERR_PARAM; + } + + /* CMD23 */ + emmc_make_nontrans_cmd(CMD23_SET_BLOCK_COUNT, count); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; + } + SETR_32(SD_SECCNT, count); + SETR_32(SD_STOP, 0x00000100); + /* SD_BUF Read/Write DMA Transfer enable */ + SETR_32(CC_EXT_MODE, (CC_EXT_MODE_CLEAR | CC_EXT_MODE_DMASDRW_ENABLE)); + + /* CMD18 */ + emmc_make_trans_cmd(CMD18_READ_MULTIPLE_BLOCK, sector_number, + buff_address_virtual, + count << EMMC_SECTOR_SIZE_SHIFT, HAL_MEMCARD_READ, + transfer_mode); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; /* CMD18 error code */ + } + + /* CMD13 */ + emmc_make_nontrans_cmd(CMD13_SEND_STATUS, EMMC_RCA << 16); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; + } +#if RCAR_BL2_DCACHE == 1 + if (transfer_mode == HAL_MEMCARD_NOT_DMA) { + flush_dcache_range((uint64_t) buff_address_virtual, + ((size_t) count << EMMC_SECTOR_SIZE_SHIFT)); + } +#endif /* RCAR_BL2_DCACHE == 1 */ + + /* ready status check */ + if ((mmc_drv_obj.r1_card_status & EMMC_R1_READY) == 0) { + emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, + EMMC_ERR_CARD_BUSY); + return EMMC_ERR_CARD_BUSY; + } + + /* state check */ + if (mmc_drv_obj.current_state != EMMC_R1_STATE_TRAN) { + emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, + EMMC_ERR_CARD_STATE); + return EMMC_ERR_CARD_STATE; + } + + return EMMC_SUCCESS; +} + +EMMC_ERROR_CODE emmc_read_sector(uint32_t *buff_address_virtual, + uint32_t sector_number, + uint32_t count, uint32_t feature_flags) +{ + uint32_t trans_count; + uint32_t remain; + EMMC_ERROR_CODE result; + HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode; + + /* parameter check */ + if (count == 0) { + emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, EMMC_ERR_PARAM); + return EMMC_ERR_PARAM; + } + + /* state check */ + if (mmc_drv_obj.mount != TRUE) { + emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* DMA? */ + if ((feature_flags & LOADIMAGE_FLAGS_DMA_ENABLE) != 0) { + transfer_mode = HAL_MEMCARD_DMA; + } else { + transfer_mode = HAL_MEMCARD_NOT_DMA; + } + + remain = count; + while (remain != 0) { + trans_count = MIN_EMMC(remain, EMMC_RW_SECTOR_COUNT_MAX); + result = + emmc_multiple_block_read(buff_address_virtual, + sector_number, trans_count, + transfer_mode); + if (result != EMMC_SUCCESS) { + return result; + } + + buff_address_virtual += (EMMC_BLOCK_LENGTH_DW * trans_count); + sector_number += trans_count; + remain -= trans_count; + } + + return EMMC_SUCCESS; +} diff --git a/drivers/renesas/common/emmc/emmc_registers.h b/drivers/renesas/common/emmc/emmc_registers.h new file mode 100644 index 000000000..392abb8fb --- /dev/null +++ b/drivers/renesas/common/emmc/emmc_registers.h @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMMC_REGISTERS_H +#define EMMC_REGISTERS_H + +/* MMC channel select */ +#define MMC_CH0 (0U) /* SDHI2/MMC0 */ +#define MMC_CH1 (1U) /* SDHI3/MMC1 */ + +#if (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RZ_G2M) +#define USE_MMC_CH (MMC_CH1) /* R-Car E3 or RZ/G2M */ +#else /* RCAR_LSI == RCAR_E3 || RCAR_LSI == RZ_G2M */ +#define USE_MMC_CH (MMC_CH0) /* R-Car H3/M3/M3N */ +#endif /* RCAR_LSI == RCAR_E3 || RCAR_LSI == RZ_G2M */ + +#define BIT0 (0x00000001U) +#define BIT1 (0x00000002U) +#define BIT2 (0x00000004U) +#define BIT3 (0x00000008U) +#define BIT4 (0x00000010U) +#define BIT5 (0x00000020U) +#define BIT6 (0x00000040U) +#define BIT7 (0x00000080U) +#define BIT8 (0x00000100U) +#define BIT9 (0x00000200U) +#define BIT10 (0x00000400U) +#define BIT11 (0x00000800U) +#define BIT12 (0x00001000U) +#define BIT13 (0x00002000U) +#define BIT14 (0x00004000U) +#define BIT15 (0x00008000U) +#define BIT16 (0x00010000U) +#define BIT17 (0x00020000U) +#define BIT18 (0x00040000U) +#define BIT19 (0x00080000U) +#define BIT20 (0x00100000U) +#define BIT21 (0x00200000U) +#define BIT22 (0x00400000U) +#define BIT23 (0x00800000U) +#define BIT24 (0x01000000U) +#define BIT25 (0x02000000U) +#define BIT26 (0x04000000U) +#define BIT27 (0x08000000U) +#define BIT28 (0x10000000U) +#define BIT29 (0x20000000U) +#define BIT30 (0x40000000U) +#define BIT31 (0x80000000U) + +/* Clock Pulse Generator (CPG) registers */ +#define CPG_BASE (0xE6150000U) +/* Module stop status register 3 */ +#define CPG_MSTPSR3 (CPG_BASE + 0x0048U) +/* System module stop control register 3 */ +#define CPG_SMSTPCR3 (CPG_BASE + 0x013CU) +/* SDHI2 clock frequency control register */ +#define CPG_SD2CKCR (CPG_BASE + 0x0268U) +/* SDHI3 clock frequency control register */ +#define CPG_SD3CKCR (CPG_BASE + 0x026CU) +/* CPG Write Protect Register */ +#define CPG_CPGWPR (CPG_BASE + 0x0900U) + +#if USE_MMC_CH == MMC_CH0 +#define CPG_SDxCKCR (CPG_SD2CKCR) /* SDHI2/MMC0 */ +#else /* USE_MMC_CH == MMC_CH0 */ +#define CPG_SDxCKCR (CPG_SD3CKCR) /* SDHI3/MMC1 */ +#endif /* USE_MMC_CH == MMC_CH0 */ + +/* Boot Status register */ +#define MFISBTSTSR (0xE6260604U) + +#define MFISBTSTSR_BOOT_PARTITION (0x00000010U) + +/* eMMC registers */ +#define MMC0_SD_BASE (0xEE140000U) +#define MMC1_SD_BASE (0xEE160000U) + +#if USE_MMC_CH == MMC_CH0 +#define MMC_SD_BASE (MMC0_SD_BASE) +#else /* USE_MMC_CH == MMC_CH0 */ +#define MMC_SD_BASE (MMC1_SD_BASE) +#endif /* USE_MMC_CH == MMC_CH0 */ + +#define SD_CMD (MMC_SD_BASE + 0x0000U) +#define SD_PORTSEL (MMC_SD_BASE + 0x0008U) +#define SD_ARG (MMC_SD_BASE + 0x0010U) +#define SD_ARG1 (MMC_SD_BASE + 0x0018U) +#define SD_STOP (MMC_SD_BASE + 0x0020U) +#define SD_SECCNT (MMC_SD_BASE + 0x0028U) +#define SD_RSP10 (MMC_SD_BASE + 0x0030U) +#define SD_RSP1 (MMC_SD_BASE + 0x0038U) +#define SD_RSP32 (MMC_SD_BASE + 0x0040U) +#define SD_RSP3 (MMC_SD_BASE + 0x0048U) +#define SD_RSP54 (MMC_SD_BASE + 0x0050U) +#define SD_RSP5 (MMC_SD_BASE + 0x0058U) +#define SD_RSP76 (MMC_SD_BASE + 0x0060U) +#define SD_RSP7 (MMC_SD_BASE + 0x0068U) +#define SD_INFO1 (MMC_SD_BASE + 0x0070U) +#define SD_INFO2 (MMC_SD_BASE + 0x0078U) +#define SD_INFO1_MASK (MMC_SD_BASE + 0x0080U) +#define SD_INFO2_MASK (MMC_SD_BASE + 0x0088U) +#define SD_CLK_CTRL (MMC_SD_BASE + 0x0090U) +#define SD_SIZE (MMC_SD_BASE + 0x0098U) +#define SD_OPTION (MMC_SD_BASE + 0x00A0U) +#define SD_ERR_STS1 (MMC_SD_BASE + 0x00B0U) +#define SD_ERR_STS2 (MMC_SD_BASE + 0x00B8U) +#define SD_BUF0 (MMC_SD_BASE + 0x00C0U) +#define SDIO_MODE (MMC_SD_BASE + 0x00D0U) +#define SDIO_INFO1 (MMC_SD_BASE + 0x00D8U) +#define SDIO_INFO1_MASK (MMC_SD_BASE + 0x00E0U) +#define CC_EXT_MODE (MMC_SD_BASE + 0x0360U) +#define SOFT_RST (MMC_SD_BASE + 0x0380U) +#define VERSION (MMC_SD_BASE + 0x0388U) +#define HOST_MODE (MMC_SD_BASE + 0x0390U) +#define DM_CM_DTRAN_MODE (MMC_SD_BASE + 0x0820U) +#define DM_CM_DTRAN_CTRL (MMC_SD_BASE + 0x0828U) +#define DM_CM_RST (MMC_SD_BASE + 0x0830U) +#define DM_CM_INFO1 (MMC_SD_BASE + 0x0840U) +#define DM_CM_INFO1_MASK (MMC_SD_BASE + 0x0848U) +#define DM_CM_INFO2 (MMC_SD_BASE + 0x0850U) +#define DM_CM_INFO2_MASK (MMC_SD_BASE + 0x0858U) +#define DM_DTRAN_ADDR (MMC_SD_BASE + 0x0880U) + +/* SD_INFO1 Registers */ +#define SD_INFO1_HPIRES 0x00010000UL /* Response Reception Completion */ +#define SD_INFO1_INFO10 0x00000400UL /* Indicates the SDDAT3 state */ +#define SD_INFO1_INFO9 0x00000200UL /* SDDAT3 Card Insertion */ +#define SD_INFO1_INFO8 0x00000100UL /* SDDAT3 Card Removal */ +#define SD_INFO1_INFO7 0x00000080UL /* Write Protect */ +#define SD_INFO1_INFO5 0x00000020UL /* Indicates the ISDCD state */ +#define SD_INFO1_INFO4 0x00000010UL /* ISDCD Card Insertion */ +#define SD_INFO1_INFO3 0x00000008UL /* ISDCD Card Removal */ +#define SD_INFO1_INFO2 0x00000004UL /* Access end */ +#define SD_INFO1_INFO0 0x00000001UL /* Response end */ + +/* SD_INFO2 Registers */ +#define SD_INFO2_ILA 0x00008000UL /* Illegal Access Error */ +#define SD_INFO2_CBSY 0x00004000UL /* Command Type Register Busy */ +#define SD_INFO2_SCLKDIVEN 0x00002000UL +#define SD_INFO2_BWE 0x00000200UL /* SD_BUF Write Enable */ +#define SD_INFO2_BRE 0x00000100UL /* SD_BUF Read Enable */ +#define SD_INFO2_DAT0 0x00000080UL /* SDDAT0 */ +#define SD_INFO2_ERR6 0x00000040UL /* Response Timeout */ +#define SD_INFO2_ERR5 0x00000020UL /* SD_BUF Illegal Read Access */ +#define SD_INFO2_ERR4 0x00000010UL /* SD_BUF Illegal Write Access */ +#define SD_INFO2_ERR3 0x00000008UL /* Data Timeout */ +#define SD_INFO2_ERR2 0x00000004UL /* END Error */ +#define SD_INFO2_ERR1 0x00000002UL /* CRC Error */ +#define SD_INFO2_ERR0 0x00000001UL /* CMD Error */ +#define SD_INFO2_ALL_ERR 0x0000807FUL +#define SD_INFO2_CLEAR 0x00000800UL /* BIT11 write value should always be 1. HWM_0003 */ + +/* SOFT_RST */ +#define SOFT_RST_SDRST 0x00000001UL + +/* SD_CLK_CTRL */ +#define SD_CLK_CTRL_SDCLKOFFEN 0x00000200UL +#define SD_CLK_CTRL_SCLKEN 0x00000100UL +#define SD_CLK_CTRL_CLKDIV_MASK 0x000000FFUL +#define SD_CLOCK_ENABLE 0x00000100UL +#define SD_CLOCK_DISABLE 0x00000000UL +#define SD_CLK_WRITE_MASK 0x000003FFUL +#define SD_CLK_CLKDIV_CLEAR_MASK 0xFFFFFF0FUL + +/* SD_OPTION */ +#define SD_OPTION_TIMEOUT_CNT_MASK 0x000000F0UL + +/* + * MMC Clock Frequency + * 200MHz * 1/x = output clock + */ +#define MMC_CLK_OFF 0UL /* Clock output is disabled */ +#define MMC_400KHZ 512UL /* 200MHz * 1/512 = 390 KHz */ +#define MMC_20MHZ 16UL /* 200MHz * 1/16 = 12.5 MHz Normal speed mode */ +#define MMC_26MHZ 8UL /* 200MHz * 1/8 = 25 MHz HS mode 26Mhz */ +#define MMC_52MHZ 4UL /* 200MHz * 1/4 = 50 MHz HS mode 52Mhz */ +#define MMC_100MHZ 2UL /* 200MHz * 1/2 = 100 MHz */ +#define MMC_200MHZ 1UL /* 200MHz * 1/1 = 200 MHz */ + +#define MMC_FREQ_52MHZ 52000000UL +#define MMC_FREQ_26MHZ 26000000UL +#define MMC_FREQ_20MHZ 20000000UL + +/* MMC Clock DIV */ +#define MMC_SD_CLK_START 0x00000100UL /* CLOCK On */ +#define MMC_SD_CLK_STOP (~0x00000100UL) /* CLOCK stop */ +#define MMC_SD_CLK_DIV1 0x000000FFUL /* 1/1 */ +#define MMC_SD_CLK_DIV2 0x00000000UL /* 1/2 */ +#define MMC_SD_CLK_DIV4 0x00000001UL /* 1/4 */ +#define MMC_SD_CLK_DIV8 0x00000002UL /* 1/8 */ +#define MMC_SD_CLK_DIV16 0x00000004UL /* 1/16 */ +#define MMC_SD_CLK_DIV32 0x00000008UL /* 1/32 */ +#define MMC_SD_CLK_DIV64 0x00000010UL /* 1/64 */ +#define MMC_SD_CLK_DIV128 0x00000020UL /* 1/128 */ +#define MMC_SD_CLK_DIV256 0x00000040UL /* 1/256 */ +#define MMC_SD_CLK_DIV512 0x00000080UL /* 1/512 */ + +/* DM_CM_DTRAN_MODE */ +#define DM_CM_DTRAN_MODE_CH0 0x00000000UL /* CH0(downstream) */ +#define DM_CM_DTRAN_MODE_CH1 0x00010000UL /* CH1(upstream) */ +#define DM_CM_DTRAN_MODE_BIT_WIDTH 0x00000030UL + +/* CC_EXT_MODE */ +#define CC_EXT_MODE_DMASDRW_ENABLE 0x00000002UL /* SD_BUF Read/Write DMA Transfer */ +#define CC_EXT_MODE_CLEAR 0x00001010UL /* BIT 12 & 4 always 1. */ + +/* DM_CM_INFO_MASK */ +#define DM_CM_INFO_MASK_CLEAR 0xFFFCFFFEUL +#define DM_CM_INFO_CH0_ENABLE 0x00010001UL +#define DM_CM_INFO_CH1_ENABLE 0x00020001UL + +/* DM_DTRAN_ADDR */ +#define DM_DTRAN_ADDR_WRITE_MASK 0xFFFFFFF8UL + +/* DM_CM_DTRAN_CTRL */ +#define DM_CM_DTRAN_CTRL_START 0x00000001UL + +/* SYSC Registers */ +#if USE_MMC_CH == MMC_CH0 +#define CPG_MSTP_MMC (BIT12) /* SDHI2/MMC0 */ +#else /* USE_MMC_CH == MMC_CH0 */ +#define CPG_MSTP_MMC (BIT11) /* SDHI3/MMC1 */ +#endif /* USE_MMC_CH == MMC_CH0 */ + +#endif /* EMMC_REGISTERS_H */ diff --git a/drivers/renesas/common/emmc/emmc_std.h b/drivers/renesas/common/emmc/emmc_std.h new file mode 100644 index 000000000..087c6e91d --- /dev/null +++ b/drivers/renesas/common/emmc/emmc_std.h @@ -0,0 +1,475 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMMC_STD_H +#define EMMC_STD_H + +#include "emmc_hal.h" + +#ifndef FALSE +#define FALSE 0U +#endif +#ifndef TRUE +#define TRUE 1U +#endif + +/* 64bit registers */ +#define SETR_64(r, v) (*(volatile uint64_t *)(r) = (v)) +#define GETR_64(r) (*(volatile uint64_t *)(r)) + +/* 32bit registers */ +#define SETR_32(r, v) (*(volatile uint32_t *)(r) = (v)) +#define GETR_32(r) (*(volatile uint32_t *)(r)) + +/* 16bit registers */ +#define SETR_16(r, v) (*(volatile uint16_t *)(r) = (v)) +#define GETR_16(r) (*(volatile uint16_t *)(r)) + +/* 8bit registers */ +#define SETR_8(r, v) (*(volatile uint8_t *)(r) = (v)) +#define GETR_8(r) (*(volatile uint8_t *)(r)) + +/* CSD register Macros */ +#define EMMC_GET_CID(x, y) (emmc_bit_field(mmc_drv_obj.cid_data, (x), (y))) + +#define EMMC_CID_MID() (EMMC_GET_CID(127, 120)) +#define EMMC_CID_CBX() (EMMC_GET_CID(113, 112)) +#define EMMC_CID_OID() (EMMC_GET_CID(111, 104)) +#define EMMC_CID_PNM1() (EMMC_GET_CID(103, 88)) +#define EMMC_CID_PNM2() (EMMC_GET_CID(87, 56)) +#define EMMC_CID_PRV() (EMMC_GET_CID(55, 48)) +#define EMMC_CID_PSN() (EMMC_GET_CID(47, 16)) +#define EMMC_CID_MDT() (EMMC_GET_CID(15, 8)) +#define EMMC_CID_CRC() (EMMC_GET_CID(7, 1)) + +/* CSD register Macros */ +#define EMMC_GET_CSD(x, y) (emmc_bit_field(mmc_drv_obj.csd_data, (x), (y))) + +#define EMMC_CSD_CSD_STRUCTURE() (EMMC_GET_CSD(127, 126)) +#define EMMC_CSD_SPEC_VARS() (EMMC_GET_CSD(125, 122)) +#define EMMC_CSD_TAAC() (EMMC_GET_CSD(119, 112)) +#define EMMC_CSD_NSAC() (EMMC_GET_CSD(111, 104)) +#define EMMC_CSD_TRAN_SPEED() (EMMC_GET_CSD(103, 96)) +#define EMMC_CSD_CCC() (EMMC_GET_CSD(95, 84)) +#define EMMC_CSD_READ_BL_LEN() (EMMC_GET_CSD(83, 80)) +#define EMMC_CSD_READ_BL_PARTIAL() (EMMC_GET_CSD(79, 79)) +#define EMMC_CSD_WRITE_BLK_MISALIGN() (EMMC_GET_CSD(78, 78)) +#define EMMC_CSD_READ_BLK_MISALIGN() (EMMC_GET_CSD(77, 77)) +#define EMMC_CSD_DSR_IMP() (EMMC_GET_CSD(76, 76)) +#define EMMC_CSD_C_SIZE() (EMMC_GET_CSD(73, 62)) +#define EMMC_CSD_VDD_R_CURR_MIN() (EMMC_GET_CSD(61, 59)) +#define EMMC_CSD_VDD_R_CURR_MAX() (EMMC_GET_CSD(58, 56)) +#define EMMC_CSD_VDD_W_CURR_MIN() (EMMC_GET_CSD(55, 53)) +#define EMMC_CSD_VDD_W_CURR_MAX() (EMMC_GET_CSD(52, 50)) +#define EMMC_CSD_C_SIZE_MULT() (EMMC_GET_CSD(49, 47)) +#define EMMC_CSD_ERASE_GRP_SIZE() (EMMC_GET_CSD(46, 42)) +#define EMMC_CSD_ERASE_GRP_MULT() (EMMC_GET_CSD(41, 37)) +#define EMMC_CSD_WP_GRP_SIZE() (EMMC_GET_CSD(36, 32)) +#define EMMC_CSD_WP_GRP_ENABLE() (EMMC_GET_CSD(31, 31)) +#define EMMC_CSD_DEFALT_ECC() (EMMC_GET_CSD(30, 29)) +#define EMMC_CSD_R2W_FACTOR() (EMMC_GET_CSD(28, 26)) +#define EMMC_CSD_WRITE_BL_LEN() (EMMC_GET_CSD(25, 22)) +#define EMMC_CSD_WRITE_BL_PARTIAL() (EMMC_GET_CSD(21, 21)) +#define EMMC_CSD_CONTENT_PROT_APP() (EMMC_GET_CSD(16, 16)) +#define EMMC_CSD_FILE_FORMAT_GRP() (EMMC_GET_CSD(15, 15)) +#define EMMC_CSD_COPY() (EMMC_GET_CSD(14, 14)) +#define EMMC_CSD_PERM_WRITE_PROTECT() (EMMC_GET_CSD(13, 13)) +#define EMMC_CSD_TMP_WRITE_PROTECT() (EMMC_GET_CSD(12, 12)) +#define EMMC_CSD_FILE_FORMAT() (EMMC_GET_CSD(11, 10)) +#define EMMC_CSD_ECC() (EMMC_GET_CSD(9, 8)) +#define EMMC_CSD_CRC() (EMMC_GET_CSD(7, 1)) + +/* sector access */ +#define EMMC_4B_BOUNDARY_CHECK_MASK 0x00000003 +#define EMMC_SECTOR_SIZE_SHIFT 9U /* 512 = 2^9 */ +#define EMMC_SECTOR_SIZE 512 +#define EMMC_BLOCK_LENGTH 512 +#define EMMC_BLOCK_LENGTH_DW 128 +#define EMMC_BUF_SIZE_SHIFT 3U /* 8byte = 2^3 */ + +/* eMMC specification clock */ +#define EMMC_CLOCK_SPEC_400K 400000UL /* initialize clock 400KHz */ +#define EMMC_CLOCK_SPEC_20M 20000000UL /* normal speed 20MHz */ +#define EMMC_CLOCK_SPEC_26M 26000000UL /* high speed 26MHz */ +#define EMMC_CLOCK_SPEC_52M 52000000UL /* high speed 52MHz */ +#define EMMC_CLOCK_SPEC_100M 100000000UL /* high speed 100MHz */ + +/* EMMC driver error code. (extended HAL_MEMCARD_RETURN) */ +typedef enum { + EMMC_ERR = 0, /* unknown error */ + EMMC_SUCCESS, /* OK */ + EMMC_ERR_FROM_DMAC, /* DMAC allocation error */ + EMMC_ERR_FROM_DMAC_TRANSFER, /* DMAC transfer error */ + EMMC_ERR_CARD_STATUS_BIT, /* card status error */ + EMMC_ERR_CMD_TIMEOUT, /* command timeout error */ + EMMC_ERR_DATA_TIMEOUT, /* data timeout error */ + EMMC_ERR_CMD_CRC, /* command CRC error */ + EMMC_ERR_DATA_CRC, /* data CRC error */ + EMMC_ERR_PARAM, /* parameter error */ + EMMC_ERR_RESPONSE, /* response error */ + EMMC_ERR_RESPONSE_BUSY, /* response busy error */ + EMMC_ERR_TRANSFER, /* data transfer error */ + EMMC_ERR_READ_SECTOR, /* read sector error */ + EMMC_ERR_WRITE_SECTOR, /* write sector error */ + EMMC_ERR_STATE, /* state error */ + EMMC_ERR_TIMEOUT, /* timeout error */ + EMMC_ERR_ILLEGAL_CARD, /* illegal card */ + EMMC_ERR_CARD_BUSY, /* Busy state */ + EMMC_ERR_CARD_STATE, /* card state error */ + EMMC_ERR_SET_TRACE, /* trace information error */ + EMMC_ERR_FROM_TIMER, /* Timer error */ + EMMC_ERR_FORCE_TERMINATE, /* Force terminate */ + EMMC_ERR_CARD_POWER, /* card power fail */ + EMMC_ERR_ERASE_SECTOR, /* erase sector error */ + EMMC_ERR_INFO2 /* exec cmd error info2 */ +} EMMC_ERROR_CODE; + +/* Function number */ +#define EMMC_FUNCNO_NONE 0U +#define EMMC_FUNCNO_DRIVER_INIT 1U +#define EMMC_FUNCNO_CARD_POWER_ON 2U +#define EMMC_FUNCNO_MOUNT 3U +#define EMMC_FUNCNO_CARD_INIT 4U +#define EMMC_FUNCNO_HIGH_SPEED 5U +#define EMMC_FUNCNO_BUS_WIDTH 6U +#define EMMC_FUNCNO_MULTI_BOOT_SELECT_PARTITION 7U +#define EMMC_FUNCNO_MULTI_BOOT_READ_SECTOR 8U +#define EMMC_FUNCNO_TRANS_DATA_READ_SECTOR 9U +#define EMMC_FUNCNO_UBOOT_IMAGE_SELECT_PARTITION 10U +#define EMMC_FUNCNO_UBOOT_IMAGE_READ_SECTOR 11U +#define EMMC_FUNCNO_SET_CLOCK 12U +#define EMMC_FUNCNO_EXEC_CMD 13U +#define EMMC_FUNCNO_READ_SECTOR 14U +#define EMMC_FUNCNO_WRITE_SECTOR 15U +#define EMMC_FUNCNO_ERASE_SECTOR 16U +#define EMMC_FUNCNO_GET_PERTITION_ACCESS 17U +/* + * Response + * R1 + * Type 'E' bit and bit14(must be 0). ignore bit22 + */ +#define EMMC_R1_ERROR_MASK 0xFDBFE080U +/* Ignore bit23 (Not check CRC error) */ +#define EMMC_R1_ERROR_MASK_WITHOUT_CRC (0xFD3FE080U) +#define EMMC_R1_STATE_MASK 0x00001E00U /* [12:9] */ +#define EMMC_R1_READY 0x00000100U /* bit8 */ +#define EMMC_R1_STATE_SHIFT 9 + +/* R4 */ +#define EMMC_R4_RCA_MASK 0xFFFF0000UL +#define EMMC_R4_STATUS 0x00008000UL + +/* CSD */ +#define EMMC_TRANSPEED_FREQ_UNIT_MASK 0x07 /* bit[2:0] */ +#define EMMC_TRANSPEED_FREQ_UNIT_SHIFT 0 +#define EMMC_TRANSPEED_MULT_MASK 0x78 /* bit[6:3] */ +#define EMMC_TRANSPEED_MULT_SHIFT 3 + +/* OCR */ +#define EMMC_HOST_OCR_VALUE 0x40FF8080 +#define EMMC_OCR_STATUS_BIT 0x80000000L /* Card power up status bit */ +#define EMMC_OCR_ACCESS_MODE_MASK 0x60000000L /* bit[30:29] */ +#define EMMC_OCR_ACCESS_MODE_SECT 0x40000000L +#define EMMC_OCR_ACCESS_MODE_BYTE 0x00000000L + +/* EXT_CSD */ +#define EMMC_EXT_CSD_S_CMD_SET 504 +#define EMMC_EXT_CSD_INI_TIMEOUT_AP 241 +#define EMMC_EXT_CSD_PWR_CL_DDR_52_360 239 +#define EMMC_EXT_CSD_PWR_CL_DDR_52_195 238 +#define EMMC_EXT_CSD_MIN_PERF_DDR_W_8_52 235 +#define EMMC_EXT_CSD_MIN_PERF_DDR_R_8_52 234 +#define EMMC_EXT_CSD_TRIM_MULT 232 +#define EMMC_EXT_CSD_SEC_FEATURE_SUPPORT 231 +#define EMMC_EXT_CSD_SEC_ERASE_MULT 229 +#define EMMC_EXT_CSD_BOOT_INFO 228 +#define EMMC_EXT_CSD_BOOT_SIZE_MULTI 226 +#define EMMC_EXT_CSD_ACC_SIZE 225 +#define EMMC_EXT_CSD_HC_ERASE_GRP_SIZE 224 +#define EMMC_EXT_CSD_ERASE_TIMEOUT_MULT 223 +#define EMMC_EXT_CSD_PEL_WR_SEC_C 222 +#define EMMC_EXT_CSD_HC_WP_GRP_SIZE 221 +#define EMMC_EXT_CSD_S_C_VCC 220 +#define EMMC_EXT_CSD_S_C_VCCQ 219 +#define EMMC_EXT_CSD_S_A_TIMEOUT 217 +#define EMMC_EXT_CSD_SEC_COUNT 215 +#define EMMC_EXT_CSD_MIN_PERF_W_8_52 210 +#define EMMC_EXT_CSD_MIN_PERF_R_8_52 209 +#define EMMC_EXT_CSD_MIN_PERF_W_8_26_4_52 208 +#define EMMC_EXT_CSD_MIN_PERF_R_8_26_4_52 207 +#define EMMC_EXT_CSD_MIN_PERF_W_4_26 206 +#define EMMC_EXT_CSD_MIN_PERF_R_4_26 205 +#define EMMC_EXT_CSD_PWR_CL_26_360 203 +#define EMMC_EXT_CSD_PWR_CL_52_360 202 +#define EMMC_EXT_CSD_PWR_CL_26_195 201 +#define EMMC_EXT_CSD_PWR_CL_52_195 200 +#define EMMC_EXT_CSD_CARD_TYPE 196 +#define EMMC_EXT_CSD_CSD_STRUCTURE 194 +#define EMMC_EXT_CSD_EXT_CSD_REV 192 +#define EMMC_EXT_CSD_CMD_SET 191 +#define EMMC_EXT_CSD_CMD_SET_REV 189 +#define EMMC_EXT_CSD_POWER_CLASS 187 +#define EMMC_EXT_CSD_HS_TIMING 185 +#define EMMC_EXT_CSD_BUS_WIDTH 183 +#define EMMC_EXT_CSD_ERASED_MEM_CONT 181 +#define EMMC_EXT_CSD_PARTITION_CONFIG 179 +#define EMMC_EXT_CSD_BOOT_CONFIG_PROT 178 +#define EMMC_EXT_CSD_BOOT_BUS_WIDTH 177 +#define EMMC_EXT_CSD_ERASE_GROUP_DEF 175 +#define EMMC_EXT_CSD_BOOT_WP 173 +#define EMMC_EXT_CSD_USER_WP 171 +#define EMMC_EXT_CSD_FW_CONFIG 169 +#define EMMC_EXT_CSD_RPMB_SIZE_MULT 168 +#define EMMC_EXT_CSD_RST_n_FUNCTION 162 +#define EMMC_EXT_CSD_PARTITIONING_SUPPORT 160 +#define EMMC_EXT_CSD_MAX_ENH_SIZE_MULT 159 +#define EMMC_EXT_CSD_PARTITIONS_ATTRIBUTE 156 +#define EMMC_EXT_CSD_PARTITION_SETTING_COMPLETED 155 +#define EMMC_EXT_CSD_GP_SIZE_MULT 154 +#define EMMC_EXT_CSD_ENH_SIZE_MULT 142 +#define EMMC_EXT_CSD_ENH_START_ADDR 139 +#define EMMC_EXT_CSD_SEC_BAD_BLK_MGMNT 134 + +#define EMMC_EXT_CSD_CARD_TYPE_26MHZ 0x01 +#define EMMC_EXT_CSD_CARD_TYPE_52MHZ 0x02 +#define EMMC_EXT_CSD_CARD_TYPE_DDR_52MHZ_12V 0x04 +#define EMMC_EXT_CSD_CARD_TYPE_DDR_52MHZ_18V 0x08 +#define EMMC_EXT_CSD_CARD_TYPE_52MHZ_MASK 0x0e + +/* SWITCH (CMD6) argument */ +#define EXTCSD_ACCESS_BYTE (BIT25 | BIT24) +#define EXTCSD_SET_BITS BIT24 + +#define HS_TIMING_ADD (185 << 16) /* H'b9 */ +#define HS_TIMING_1 (1 << 8) +#define HS_TIMING_HS200 (2 << 8) +#define HS_TIMING_HS400 (3 << 8) + +#define BUS_WIDTH_ADD (183 << 16) /* H'b7 */ +#define BUS_WIDTH_1 (0 << 8) +#define BUS_WIDTH_4 (1 << 8) +#define BUS_WIDTH_8 (2 << 8) +#define BUS_WIDTH_4DDR (5 << 8) +#define BUS_WIDTH_8DDR (6 << 8) + +#define EMMC_SWITCH_HS_TIMING (EXTCSD_ACCESS_BYTE | HS_TIMING_ADD |\ + HS_TIMING_1) /* H'03b90100 */ +#define EMMC_SWITCH_HS_TIMING_OFF (EXTCSD_ACCESS_BYTE |\ + HS_TIMING_ADD) /* H'03b90000 */ + +#define EMMC_SWITCH_BUS_WIDTH_1 (EXTCSD_ACCESS_BYTE | BUS_WIDTH_ADD |\ + BUS_WIDTH_1) /* H'03b70000 */ +#define EMMC_SWITCH_BUS_WIDTH_4 (EXTCSD_ACCESS_BYTE | BUS_WIDTH_ADD |\ + BUS_WIDTH_4) /* H'03b70100 */ +#define EMMC_SWITCH_BUS_WIDTH_8 (EXTCSD_ACCESS_BYTE | BUS_WIDTH_ADD |\ + BUS_WIDTH_8) /* H'03b70200 */ +#define EMMC_SWITCH_BUS_WIDTH_4DDR (EXTCSD_ACCESS_BYTE | BUS_WIDTH_ADD |\ + BUS_WIDTH_4DDR) /* H'03b70500 */ +#define EMMC_SWITCH_BUS_WIDTH_8DDR (EXTCSD_ACCESS_BYTE | BUS_WIDTH_ADD |\ + BUS_WIDTH_8DDR) /* H'03b70600 */ +/* Partition config = 0x00 */ +#define EMMC_SWITCH_PARTITION_CONFIG 0x03B30000UL + +#define TIMING_HIGH_SPEED 1UL +#define EMMC_BOOT_PARTITION_EN_MASK 0x38U +#define EMMC_BOOT_PARTITION_EN_SHIFT 3U + +/* Bus width */ +#define EMMC_BUSWIDTH_1BIT CE_CMD_SET_DATW_1BIT +#define EMMC_BUSWIDTH_4BIT CE_CMD_SET_DATW_4BIT +#define EMMC_BUSWIDTH_8BIT CE_CMD_SET_DATW_8BIT + +/* for st_mmc_base */ +#define EMMC_MAX_RESPONSE_LENGTH 17 +#define EMMC_MAX_CID_LENGTH 16 +#define EMMC_MAX_CSD_LENGTH 16 +#define EMMC_MAX_EXT_CSD_LENGTH 512U +#define EMMC_RES_REG_ALIGNED 4U +#define EMMC_BUF_REG_ALIGNED 8U + +/* TAAC mask */ +#define TAAC_TIME_UNIT_MASK (0x07) +#define TAAC_MULTIPLIER_FACTOR_MASK (0x0F) + +/* Partition id */ +typedef enum { + PARTITION_ID_USER = 0x0, /* User Area */ + PARTITION_ID_BOOT_1 = 0x1, /* boot partition 1 */ + PARTITION_ID_BOOT_2 = 0x2, /* boot partition 2 */ + PARTITION_ID_RPMB = 0x3, /* Replay Protected Memory Block */ + PARTITION_ID_GP_1 = 0x4, /* General Purpose partition 1 */ + PARTITION_ID_GP_2 = 0x5, /* General Purpose partition 2 */ + PARTITION_ID_GP_3 = 0x6, /* General Purpose partition 3 */ + PARTITION_ID_GP_4 = 0x7, /* General Purpose partition 4 */ + PARTITION_ID_MASK = 0x7 /* [2:0] */ +} EMMC_PARTITION_ID; + +/* card state in R1 response [12:9] */ +typedef enum { + EMMC_R1_STATE_IDLE = 0, + EMMC_R1_STATE_READY, + EMMC_R1_STATE_IDENT, + EMMC_R1_STATE_STBY, + EMMC_R1_STATE_TRAN, + EMMC_R1_STATE_DATA, + EMMC_R1_STATE_RCV, + EMMC_R1_STATE_PRG, + EMMC_R1_STATE_DIS, + EMMC_R1_STATE_BTST, + EMMC_R1_STATE_SLEP +} EMMC_R1_STATE; + +typedef enum { + ESTATE_BEGIN = 0, + ESTATE_ISSUE_CMD, + ESTATE_NON_RESP_CMD, + ESTATE_RCV_RESP, + ESTATE_RCV_RESPONSE_BUSY, + ESTATE_CHECK_RESPONSE_COMPLETE, + ESTATE_DATA_TRANSFER, + ESTATE_DATA_TRANSFER_COMPLETE, + ESTATE_ACCESS_END, + ESTATE_TRANSFER_ERROR, + ESTATE_ERROR, + ESTATE_END +} EMMC_INT_STATE; + +/* eMMC boot driver error information */ +typedef struct { + uint16_t num; /* error no */ + uint16_t code; /* error code */ + + volatile uint32_t info1; /* SD_INFO1. (hw dependent) */ + volatile uint32_t info2; /* SD_INFO2. (hw dependent) */ + volatile uint32_t status1; /* SD_ERR_STS1. (hw dependent) */ + volatile uint32_t status2; /* SD_ERR_STS2. (hw dependent) */ + volatile uint32_t dm_info1; /* DM_CM_INFO1. (hw dependent) */ + volatile uint32_t dm_info2; /* DM_CM_INFO2. (hw dependent) */ +} st_error_info; + +/* Command information */ +typedef struct { + HAL_MEMCARD_COMMAND cmd; /* Command information */ + uint32_t arg; /* argument */ + HAL_MEMCARD_OPERATION dir; /* direction */ + uint32_t hw; /* SD_CMD register value. */ +} st_command_info; + +/* MMC driver base */ +typedef struct { + st_error_info error_info; /* error information */ + st_command_info cmd_info; /* command information */ + + /* for data transfer */ + uint32_t *buff_address_virtual; /* Dest or Src buff */ + uint32_t *buff_address_physical; /* Dest or Src buff */ + HAL_MEMCARD_DATA_WIDTH bus_width; /* bus width */ + + uint32_t trans_size; /* transfer size for this command */ + uint32_t remain_size; /* remain size for this command */ + uint32_t response_length; /* response length for this command */ + uint32_t sector_size; /* sector_size */ + + /* clock */ + uint32_t base_clock; /* MMC host controller clock */ + /* + * Max freq (Card Spec)[Hz]. It changes dynamically by CSD and + * EXT_CSD. + */ + uint32_t max_freq; + /* request freq [Hz] (400K, 26MHz, 52MHz, etc) */ + uint32_t request_freq; + /* current MMC clock[Hz] (the closest frequency supported by HW) */ + uint32_t current_freq; + + /* state flag */ + /* presence status of the memory card */ + HAL_MEMCARD_PRESENCE_STATUS card_present; + + uint32_t card_power_enable; + uint32_t clock_enable; + /* True : initialize complete. */ + uint32_t initialize; + /* True : sector access, FALSE : byte access */ + uint32_t access_mode; + /* True : mount complete. */ + uint32_t mount; + /* True : selected card. */ + uint32_t selected; + /* 0: DMA, 1:PIO */ + HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode; + + /* loaded ISSW image No. ISSW have copy image. */ + uint32_t image_num; + /* card state */ + EMMC_R1_STATE current_state; + /* True : during command processing */ + volatile uint32_t during_cmd_processing; + /* True : during transfer */ + volatile uint32_t during_transfer; + /* True : during transfer (DMA) */ + volatile uint32_t during_dma_transfer; + /* True : occurred DMAC error */ + volatile uint32_t dma_error_flag; + /* force terminate flag */ + volatile uint32_t force_terminate; + /* state machine blocking flag : True or False */ + volatile uint32_t state_machine_blocking; + /* True : get partition access processing */ + volatile uint32_t get_partition_access_flag; + + EMMC_PARTITION_ID boot_partition_en; /* Boot partition */ + EMMC_PARTITION_ID partition_access; /* Current access partition */ + + /* timeout */ + uint32_t hs_timing; + + /* read and write data timeout */ + uint32_t data_timeout; + + /* retry */ + uint32_t retries_after_fail; + + /* interrupt */ + volatile uint32_t int_event1; /* interrupt SD_INFO1 Event */ + volatile uint32_t int_event2; /* interrupt SD_INFO2 Event */ + volatile uint32_t dm_event1; /* interrupt DM_CM_INFO1 Event */ + volatile uint32_t dm_event2; /* interrupt DM_CM_INFO2 Event */ + + /* response */ + uint32_t *response; /* buffer ptr for executing command. */ + uint32_t r1_card_status; /* R1 response data */ + uint32_t r3_ocr; /* R3 response data */ + uint32_t r4_resp; /* R4 response data */ + uint32_t r5_resp; /* R5 response data */ + + /* True : clock mode is low. (MMC clock = Max26MHz) */ + uint32_t low_clock_mode_enable; + + uint32_t reserved2; + uint32_t reserved3; + uint32_t reserved4; + + /* CSD registers (4byte align) */ + uint8_t csd_data[EMMC_MAX_CSD_LENGTH] /* CSD */ + __attribute__ ((aligned(EMMC_RES_REG_ALIGNED))); + /* CID registers (4byte align) */ + uint8_t cid_data[EMMC_MAX_CID_LENGTH] /* CID */ + __attribute__ ((aligned(EMMC_RES_REG_ALIGNED))); + /* EXT CSD registers (8byte align) */ + uint8_t ext_csd_data[EMMC_MAX_EXT_CSD_LENGTH] /* EXT_CSD */ + __attribute__ ((aligned(EMMC_BUF_REG_ALIGNED))); + /* Response registers (4byte align) */ + uint8_t response_data[EMMC_MAX_RESPONSE_LENGTH] /* other response */ + __attribute__ ((aligned(EMMC_RES_REG_ALIGNED))); +} st_mmc_base; + +typedef int (*func) (void); + +uint32_t emmc_get_csd_time(void); + +#define MMC_DEBUG +#endif /* EMMC_STD_H */ diff --git a/drivers/renesas/common/emmc/emmc_utility.c b/drivers/renesas/common/emmc/emmc_utility.c new file mode 100644 index 000000000..2e88abc75 --- /dev/null +++ b/drivers/renesas/common/emmc/emmc_utility.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> + +#include "emmc_config.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_registers.h" +#include "emmc_std.h" + +static const uint32_t cmd_reg_hw[EMMC_CMD_MAX + 1] = { + 0x00000000, /* CMD0 */ + 0x00000701, /* CMD1 */ + 0x00000002, /* CMD2 */ + 0x00000003, /* CMD3 */ + 0x00000004, /* CMD4 */ + 0x00000505, /* CMD5 */ + 0x00000406, /* CMD6 */ + 0x00000007, /* CMD7 */ + 0x00001C08, /* CMD8 */ + 0x00000009, /* CMD9 */ + 0x0000000A, /* CMD10 */ + 0x00000000, /* reserved */ + 0x0000000C, /* CMD12 */ + 0x0000000D, /* CMD13 */ + 0x00001C0E, /* CMD14 */ + 0x0000000F, /* CMD15 */ + 0x00000010, /* CMD16 */ + 0x00000011, /* CMD17 */ + 0x00007C12, /* CMD18 */ + 0x00000C13, /* CMD19 */ + 0x00000000, + 0x00001C15, /* CMD21 */ + 0x00000000, + 0x00000017, /* CMD23 */ + 0x00000018, /* CMD24 */ + 0x00006C19, /* CMD25 */ + 0x00000C1A, /* CMD26 */ + 0x0000001B, /* CMD27 */ + 0x0000001C, /* CMD28 */ + 0x0000001D, /* CMD29 */ + 0x0000001E, /* CMD30 */ + 0x00001C1F, /* CMD31 */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000423, /* CMD35 */ + 0x00000424, /* CMD36 */ + 0x00000000, + 0x00000026, /* CMD38 */ + 0x00000427, /* CMD39 */ + 0x00000428, /* CMD40(send cmd) */ + 0x00000000, + 0x0000002A, /* CMD42 */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000C31, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00007C35, + 0x00006C36, + 0x00000037, /* CMD55 */ + 0x00000038, /* CMD56(Read) */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 +}; + +uint32_t emmc_bit_field(uint8_t *data, uint32_t top, uint32_t bottom) +{ + uint32_t value; + + uint32_t index_top = (uint32_t) (15 - (top >> 3)); + uint32_t index_bottom = (uint32_t) (15 - (bottom >> 3)); + + if (index_top == index_bottom) { + value = data[index_top]; + } else if ((index_top + 1) == index_bottom) { + value = + (uint32_t) ((data[index_top] << 8) | data[index_bottom]); + } else if ((index_top + 2) == index_bottom) { + value = + (uint32_t) ((data[index_top] << 16) | + (data[index_top + 1] << 8) | data[index_top + + 2]); + } else { + value = + (uint32_t) ((data[index_top] << 24) | + (data[index_top + 1] << 16) | + (data[index_top + 2] << 8) | + data[index_top + 3]); + } + + value = ((value >> (bottom & 0x07)) & ((1 << (top - bottom + 1)) - 1)); + + return value; +} + +void emmc_write_error_info(uint16_t func_no, EMMC_ERROR_CODE error_code) +{ + + mmc_drv_obj.error_info.num = func_no; + mmc_drv_obj.error_info.code = (uint16_t) error_code; + + ERROR("BL2: emmc err:func_no=0x%x code=0x%x\n", func_no, error_code); +} + +void emmc_write_error_info_func_no(uint16_t func_no) +{ + + mmc_drv_obj.error_info.num = func_no; + + ERROR("BL2: emmc err:func_no=0x%x\n", func_no); +} + +void emmc_make_nontrans_cmd(HAL_MEMCARD_COMMAND cmd, uint32_t arg) +{ + /* command information */ + mmc_drv_obj.cmd_info.cmd = cmd; + mmc_drv_obj.cmd_info.arg = arg; + mmc_drv_obj.cmd_info.dir = HAL_MEMCARD_READ; + mmc_drv_obj.cmd_info.hw = + cmd_reg_hw[cmd & HAL_MEMCARD_COMMAND_INDEX_MASK]; + + /* clear data transfer information */ + mmc_drv_obj.trans_size = 0; + mmc_drv_obj.remain_size = 0; + mmc_drv_obj.buff_address_virtual = NULL; + mmc_drv_obj.buff_address_physical = NULL; + + /* response information */ + mmc_drv_obj.response_length = 6; + + switch (mmc_drv_obj.cmd_info.cmd & HAL_MEMCARD_RESPONSE_TYPE_MASK) { + case HAL_MEMCARD_RESPONSE_NONE: + mmc_drv_obj.response = (uint32_t *) mmc_drv_obj.response_data; + mmc_drv_obj.response_length = 0; + break; + case HAL_MEMCARD_RESPONSE_R1: + mmc_drv_obj.response = &mmc_drv_obj.r1_card_status; + break; + case HAL_MEMCARD_RESPONSE_R1b: + mmc_drv_obj.cmd_info.hw |= BIT10; /* bit10 = R1 busy bit */ + mmc_drv_obj.response = &mmc_drv_obj.r1_card_status; + break; + case HAL_MEMCARD_RESPONSE_R2: + mmc_drv_obj.response = (uint32_t *) mmc_drv_obj.response_data; + mmc_drv_obj.response_length = 17; + break; + case HAL_MEMCARD_RESPONSE_R3: + mmc_drv_obj.response = &mmc_drv_obj.r3_ocr; + break; + case HAL_MEMCARD_RESPONSE_R4: + mmc_drv_obj.response = &mmc_drv_obj.r4_resp; + break; + case HAL_MEMCARD_RESPONSE_R5: + mmc_drv_obj.response = &mmc_drv_obj.r5_resp; + break; + default: + mmc_drv_obj.response = (uint32_t *) mmc_drv_obj.response_data; + break; + } +} + +void emmc_make_trans_cmd(HAL_MEMCARD_COMMAND cmd, uint32_t arg, + uint32_t *buff_address_virtual, + uint32_t len, + HAL_MEMCARD_OPERATION dir, + HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode) +{ + emmc_make_nontrans_cmd(cmd, arg); /* update common information */ + + /* for data transfer command */ + mmc_drv_obj.cmd_info.dir = dir; + mmc_drv_obj.buff_address_virtual = buff_address_virtual; + mmc_drv_obj.buff_address_physical = buff_address_virtual; + mmc_drv_obj.trans_size = len; + mmc_drv_obj.remain_size = len; + mmc_drv_obj.transfer_mode = transfer_mode; +} + +EMMC_ERROR_CODE emmc_send_idle_cmd(uint32_t arg) +{ + EMMC_ERROR_CODE result; + uint32_t freq; + + /* initialize state */ + mmc_drv_obj.mount = FALSE; + mmc_drv_obj.selected = FALSE; + mmc_drv_obj.during_transfer = FALSE; + mmc_drv_obj.during_cmd_processing = FALSE; + mmc_drv_obj.during_dma_transfer = FALSE; + mmc_drv_obj.dma_error_flag = FALSE; + mmc_drv_obj.force_terminate = FALSE; + mmc_drv_obj.state_machine_blocking = FALSE; + + mmc_drv_obj.bus_width = HAL_MEMCARD_DATA_WIDTH_1_BIT; + mmc_drv_obj.max_freq = MMC_20MHZ; /* 20MHz */ + mmc_drv_obj.current_state = EMMC_R1_STATE_IDLE; + + /* CMD0 (MMC clock is current frequency. if Data transfer mode, 20MHz or higher.) */ + emmc_make_nontrans_cmd(CMD0_GO_IDLE_STATE, arg); /* CMD0 */ + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; + } + + /* change MMC clock(400KHz) */ + freq = MMC_400KHZ; + result = emmc_set_request_mmc_clock(&freq); + if (result != EMMC_SUCCESS) { + return result; + } + + return EMMC_SUCCESS; +} diff --git a/drivers/renesas/common/iic_dvfs/iic_dvfs.c b/drivers/renesas/common/iic_dvfs/iic_dvfs.c new file mode 100644 index 000000000..e1c9a5bd4 --- /dev/null +++ b/drivers/renesas/common/iic_dvfs/iic_dvfs.c @@ -0,0 +1,600 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <lib/mmio.h> + +#include "cpg_registers.h" +#include "iic_dvfs.h" +#include "rcar_def.h" +#include "rcar_private.h" + +#define DVFS_RETRY_MAX (2U) + +#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_0 (0x07U) +#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_1 (0x09U) +#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_2 (0x0BU) +#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_3 (0x0EU) +#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_E (0x15U) + +#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_0 (0x01U) +#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_1 (0x02U) +#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_2 (0x03U) +#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_3 (0x05U) +#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_E (0x07U) + +#define CPG_BIT_SMSTPCR9_DVFS (0x04000000U) + +#define IIC_DVFS_REG_BASE (0xE60B0000U) +#define IIC_DVFS_REG_ICDR (IIC_DVFS_REG_BASE + 0x0000U) +#define IIC_DVFS_REG_ICCR (IIC_DVFS_REG_BASE + 0x0004U) +#define IIC_DVFS_REG_ICSR (IIC_DVFS_REG_BASE + 0x0008U) +#define IIC_DVFS_REG_ICIC (IIC_DVFS_REG_BASE + 0x000CU) +#define IIC_DVFS_REG_ICCL (IIC_DVFS_REG_BASE + 0x0010U) +#define IIC_DVFS_REG_ICCH (IIC_DVFS_REG_BASE + 0x0014U) + +#define IIC_DVFS_BIT_ICSR_BUSY (0x10U) +#define IIC_DVFS_BIT_ICSR_AL (0x08U) +#define IIC_DVFS_BIT_ICSR_TACK (0x04U) +#define IIC_DVFS_BIT_ICSR_WAIT (0x02U) +#define IIC_DVFS_BIT_ICSR_DTE (0x01U) + +#define IIC_DVFS_BIT_ICCR_ENABLE (0x80U) +#define IIC_DVFS_SET_ICCR_START (0x94U) +#define IIC_DVFS_SET_ICCR_STOP (0x90U) +#define IIC_DVFS_SET_ICCR_RETRANSMISSION (0x94U) +#define IIC_DVFS_SET_ICCR_CHANGE (0x81U) +#define IIC_DVFS_SET_ICCR_STOP_READ (0xC0U) + +#define IIC_DVFS_BIT_ICIC_TACKE (0x04U) +#define IIC_DVFS_BIT_ICIC_WAITE (0x02U) +#define IIC_DVFS_BIT_ICIC_DTEE (0x01U) + +#define DVFS_READ_MODE (0x01U) +#define DVFS_WRITE_MODE (0x00U) + +#define IIC_DVFS_SET_DUMMY (0x52U) +#define IIC_DVFS_SET_BUSY_LOOP (500000000U) + +enum dvfs_state_t { + DVFS_START = 0, + DVFS_STOP, + DVFS_RETRANSMIT, + DVFS_READ, + DVFS_STOP_READ, + DVFS_SET_SLAVE_READ, + DVFS_SET_SLAVE, + DVFS_WRITE_ADDR, + DVFS_WRITE_DATA, + DVFS_CHANGE_SEND_TO_RECEIVE, + DVFS_DONE, +}; + +#define DVFS_PROCESS (1) +#define DVFS_COMPLETE (0) +#define DVFS_ERROR (-1) + +#if IMAGE_BL31 +#define IIC_DVFS_FUNC(__name, ...) \ +static int32_t __attribute__ ((section(".system_ram"))) \ +dvfs_ ##__name(__VA_ARGS__) + +#define RCAR_DVFS_API(__name, ...) \ +int32_t __attribute__ ((section(".system_ram"))) \ +rcar_iic_dvfs_ ##__name(__VA_ARGS__) + +#else +#define IIC_DVFS_FUNC(__name, ...) \ +static int32_t dvfs_ ##__name(__VA_ARGS__) + +#define RCAR_DVFS_API(__name, ...) \ +int32_t rcar_iic_dvfs_ ##__name(__VA_ARGS__) +#endif + +IIC_DVFS_FUNC(check_error, enum dvfs_state_t *state, uint32_t *err, uint8_t mode) +{ + uint8_t icsr_al = 0U, icsr_tack = 0U; + uint8_t reg, stop; + uint32_t i = 0U; + + stop = mode == DVFS_READ_MODE ? IIC_DVFS_SET_ICCR_STOP_READ : + IIC_DVFS_SET_ICCR_STOP; + + reg = mmio_read_8(IIC_DVFS_REG_ICSR); + icsr_al = (reg & IIC_DVFS_BIT_ICSR_AL) == IIC_DVFS_BIT_ICSR_AL; + icsr_tack = (reg & IIC_DVFS_BIT_ICSR_TACK) == IIC_DVFS_BIT_ICSR_TACK; + + if (icsr_al == 0U && icsr_tack == 0U) { + return DVFS_PROCESS; + } + + if (icsr_al) { + reg = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_AL; + mmio_write_8(IIC_DVFS_REG_ICSR, reg); + + if (*state == DVFS_SET_SLAVE) { + mmio_write_8(IIC_DVFS_REG_ICDR, IIC_DVFS_SET_DUMMY); + } + + do { + reg = mmio_read_8(IIC_DVFS_REG_ICSR) & + IIC_DVFS_BIT_ICSR_WAIT; + } while (reg == 0U); + + mmio_write_8(IIC_DVFS_REG_ICCR, stop); + + reg = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, reg); + + i = 0U; + do { + reg = mmio_read_8(IIC_DVFS_REG_ICSR) & + IIC_DVFS_BIT_ICSR_BUSY; + if (reg == 0U) { + break; + } + + if (i++ > IIC_DVFS_SET_BUSY_LOOP) { + panic(); + } + + } while (true); + + mmio_write_8(IIC_DVFS_REG_ICCR, 0x00U); + + (*err)++; + if (*err > DVFS_RETRY_MAX) { + return DVFS_ERROR; + } + + *state = DVFS_START; + + return DVFS_PROCESS; + + } + + /* icsr_tack */ + mmio_write_8(IIC_DVFS_REG_ICCR, stop); + + reg = mmio_read_8(IIC_DVFS_REG_ICIC); + reg &= ~(IIC_DVFS_BIT_ICIC_WAITE | IIC_DVFS_BIT_ICIC_DTEE); + mmio_write_8(IIC_DVFS_REG_ICIC, reg); + + reg = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_TACK; + mmio_write_8(IIC_DVFS_REG_ICSR, reg); + + i = 0U; + while ((mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_BUSY) != 0U) { + if (i++ > IIC_DVFS_SET_BUSY_LOOP) { + panic(); + } + } + + mmio_write_8(IIC_DVFS_REG_ICCR, 0U); + (*err)++; + + if (*err > DVFS_RETRY_MAX) { + return DVFS_ERROR; + } + + *state = DVFS_START; + + return DVFS_PROCESS; +} + +IIC_DVFS_FUNC(start, enum dvfs_state_t *state) +{ + uint8_t iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_E; + uint8_t icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_E; + int32_t result = DVFS_PROCESS; + uint32_t reg, lsi_product; + uint8_t mode; + + mode = mmio_read_8(IIC_DVFS_REG_ICCR) | IIC_DVFS_BIT_ICCR_ENABLE; + mmio_write_8(IIC_DVFS_REG_ICCR, mode); + + lsi_product = mmio_read_32(RCAR_PRR) & PRR_PRODUCT_MASK; + if (lsi_product == PRR_PRODUCT_E3) { + goto start; + } + + reg = mmio_read_32(RCAR_MODEMR) & CHECK_MD13_MD14; + switch (reg) { + case MD14_MD13_TYPE_0: + iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_0; + icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_0; + break; + case MD14_MD13_TYPE_1: + iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_1; + icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_1; + break; + case MD14_MD13_TYPE_2: + iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_2; + icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_2; + break; + default: + iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_3; + icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_3; + break; + } +start: + mmio_write_8(IIC_DVFS_REG_ICCL, iccl); + mmio_write_8(IIC_DVFS_REG_ICCH, icch); + + mode = mmio_read_8(IIC_DVFS_REG_ICIC) + | IIC_DVFS_BIT_ICIC_TACKE + | IIC_DVFS_BIT_ICIC_WAITE | IIC_DVFS_BIT_ICIC_DTEE; + + mmio_write_8(IIC_DVFS_REG_ICIC, mode); + mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_START); + + *state = DVFS_SET_SLAVE; + + return result; +} + +IIC_DVFS_FUNC(set_slave, enum dvfs_state_t *state, uint32_t *err, uint8_t slave) +{ + uint8_t mode; + int32_t result; + uint8_t address; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_DTE; + if (mode != IIC_DVFS_BIT_ICSR_DTE) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICIC) & ~IIC_DVFS_BIT_ICIC_DTEE; + mmio_write_8(IIC_DVFS_REG_ICIC, mode); + + address = slave << 1; + mmio_write_8(IIC_DVFS_REG_ICDR, address); + + *state = DVFS_WRITE_ADDR; + + return result; +} + +IIC_DVFS_FUNC(write_addr, enum dvfs_state_t *state, uint32_t *err, uint8_t reg_addr) +{ + uint8_t mode; + int32_t result; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICDR, reg_addr); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + *state = DVFS_WRITE_DATA; + + return result; +} + +IIC_DVFS_FUNC(write_data, enum dvfs_state_t *state, uint32_t *err, + uint8_t reg_data) +{ + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICDR, reg_data); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + *state = DVFS_STOP; + + return result; +} + +IIC_DVFS_FUNC(stop, enum dvfs_state_t *state, uint32_t *err) +{ + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_STOP); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + *state = DVFS_DONE; + + return result; +} + +IIC_DVFS_FUNC(done, void) +{ + uint32_t i; + + for (i = 0U; i < IIC_DVFS_SET_BUSY_LOOP; i++) { + if ((mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_BUSY) != 0U) { + continue; + } + goto done; + } + + panic(); +done: + mmio_write_8(IIC_DVFS_REG_ICCR, 0U); + + return DVFS_COMPLETE; +} + +IIC_DVFS_FUNC(write_reg_addr_read, enum dvfs_state_t *state, uint32_t *err, + uint8_t reg_addr) +{ + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICDR, reg_addr); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + *state = DVFS_RETRANSMIT; + + return result; +} + +IIC_DVFS_FUNC(retransmit, enum dvfs_state_t *state, uint32_t *err) +{ + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_RETRANSMISSION); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + mode = mmio_read_8(IIC_DVFS_REG_ICIC) | IIC_DVFS_BIT_ICIC_DTEE; + mmio_write_8(IIC_DVFS_REG_ICIC, mode); + + *state = DVFS_SET_SLAVE_READ; + + return result; +} + +IIC_DVFS_FUNC(set_slave_read, enum dvfs_state_t *state, uint32_t *err, + uint8_t slave) +{ + uint8_t address; + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_DTE; + if (mode != IIC_DVFS_BIT_ICSR_DTE) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICIC) & ~IIC_DVFS_BIT_ICIC_DTEE; + mmio_write_8(IIC_DVFS_REG_ICIC, mode); + + address = ((uint8_t) (slave << 1) + DVFS_READ_MODE); + mmio_write_8(IIC_DVFS_REG_ICDR, address); + + *state = DVFS_CHANGE_SEND_TO_RECEIVE; + + return result; +} + +IIC_DVFS_FUNC(change_send_to_receive, enum dvfs_state_t *state, uint32_t *err) +{ + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_CHANGE); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + *state = DVFS_STOP_READ; + + return result; +} + +IIC_DVFS_FUNC(stop_read, enum dvfs_state_t *state, uint32_t *err) +{ + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_READ_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_STOP_READ); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + mode = mmio_read_8(IIC_DVFS_REG_ICIC) | IIC_DVFS_BIT_ICIC_DTEE; + mmio_write_8(IIC_DVFS_REG_ICIC, mode); + + *state = DVFS_READ; + + return result; +} + +IIC_DVFS_FUNC(read, enum dvfs_state_t *state, uint8_t *reg_data) +{ + uint8_t mode; + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_DTE; + if (mode != IIC_DVFS_BIT_ICSR_DTE) { + return DVFS_PROCESS; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICIC) & ~IIC_DVFS_BIT_ICIC_DTEE; + mmio_write_8(IIC_DVFS_REG_ICIC, mode); + + *reg_data = mmio_read_8(IIC_DVFS_REG_ICDR); + *state = DVFS_DONE; + + return DVFS_PROCESS; +} + +RCAR_DVFS_API(send, uint8_t slave, uint8_t reg_addr, uint8_t reg_data) +{ + enum dvfs_state_t state = DVFS_START; + int32_t result = DVFS_PROCESS; + uint32_t err = 0U; + + mstpcr_write(SCMSTPCR9, CPG_MSTPSR9, CPG_BIT_SMSTPCR9_DVFS); + mmio_write_8(IIC_DVFS_REG_ICCR, 0U); +again: + switch (state) { + case DVFS_START: + result = dvfs_start(&state); + break; + case DVFS_SET_SLAVE: + result = dvfs_set_slave(&state, &err, slave); + break; + case DVFS_WRITE_ADDR: + result = dvfs_write_addr(&state, &err, reg_addr); + break; + case DVFS_WRITE_DATA: + result = dvfs_write_data(&state, &err, reg_data); + break; + case DVFS_STOP: + result = dvfs_stop(&state, &err); + break; + case DVFS_DONE: + result = dvfs_done(); + break; + default: + panic(); + break; + } + + if (result == DVFS_PROCESS) { + goto again; + } + + return result; +} + +RCAR_DVFS_API(receive, uint8_t slave, uint8_t reg, uint8_t *data) +{ + enum dvfs_state_t state = DVFS_START; + int32_t result = DVFS_PROCESS; + uint32_t err = 0U; + + mstpcr_write(SCMSTPCR9, CPG_MSTPSR9, CPG_BIT_SMSTPCR9_DVFS); + mmio_write_8(IIC_DVFS_REG_ICCR, 0U); +again: + switch (state) { + case DVFS_START: + result = dvfs_start(&state); + break; + case DVFS_SET_SLAVE: + result = dvfs_set_slave(&state, &err, slave); + break; + case DVFS_WRITE_ADDR: + result = dvfs_write_reg_addr_read(&state, &err, reg); + break; + case DVFS_RETRANSMIT: + result = dvfs_retransmit(&state, &err); + break; + case DVFS_SET_SLAVE_READ: + result = dvfs_set_slave_read(&state, &err, slave); + break; + case DVFS_CHANGE_SEND_TO_RECEIVE: + result = dvfs_change_send_to_receive(&state, &err); + break; + case DVFS_STOP_READ: + result = dvfs_stop_read(&state, &err); + break; + case DVFS_READ: + result = dvfs_read(&state, data); + break; + case DVFS_DONE: + result = dvfs_done(); + break; + default: + panic(); + break; + } + + if (result == DVFS_PROCESS) { + goto again; + } + + return result; +} diff --git a/drivers/renesas/common/iic_dvfs/iic_dvfs.h b/drivers/renesas/common/iic_dvfs/iic_dvfs.h new file mode 100644 index 000000000..244c06cfd --- /dev/null +++ b/drivers/renesas/common/iic_dvfs/iic_dvfs.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IIC_DVFS_H +#define IIC_DVFS_H + +/* PMIC slave */ +#define PMIC (0x30U) +#define BKUP_MODE_CNT (0x20U) +#define DVFS_SET_VID (0x54U) +#define REG_KEEP10 (0x79U) + +/* EEPROM slave */ +#define EEPROM (0x50U) +#define BOARD_ID (0x70U) + +int32_t rcar_iic_dvfs_receive(uint8_t slave, uint8_t reg, uint8_t *data); +int32_t rcar_iic_dvfs_send(uint8_t slave, uint8_t regr, uint8_t data); + +#endif /* IIC_DVFS_H */ diff --git a/drivers/renesas/common/io/io_common.h b/drivers/renesas/common/io/io_common.h new file mode 100644 index 000000000..6eb77777a --- /dev/null +++ b/drivers/renesas/common/io/io_common.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_COMMON_H +#define IO_COMMON_H + +typedef struct io_drv_spec { + size_t offset; + size_t length; + uint32_t partition; +} io_drv_spec_t; + +#endif /* IO_COMMON_H */ diff --git a/drivers/renesas/common/io/io_emmcdrv.c b/drivers/renesas/common/io/io_emmcdrv.c new file mode 100644 index 000000000..c2b5f7c08 --- /dev/null +++ b/drivers/renesas/common/io/io_emmcdrv.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <string.h> + +#include <common/debug.h> +#include <drivers/io/io_driver.h> +#include <drivers/io/io_storage.h> + +#include "emmc_config.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_std.h" +#include "io_common.h" +#include "io_emmcdrv.h" +#include "io_private.h" + +static int32_t emmcdrv_dev_open(const uintptr_t spec __attribute__ ((unused)), + io_dev_info_t **dev_info); +static int32_t emmcdrv_dev_close(io_dev_info_t *dev_info); + +typedef struct { + uint32_t in_use; + uintptr_t base; + signed long long file_pos; + EMMC_PARTITION_ID partition; +} file_state_t; + +static file_state_t current_file = { 0 }; + +static EMMC_PARTITION_ID emmcdrv_bootpartition = PARTITION_ID_USER; + +static io_type_t device_type_emmcdrv(void) +{ + return IO_TYPE_MEMMAP; +} + +static int32_t emmcdrv_block_seek(io_entity_t *entity, int32_t mode, + signed long long offset) +{ + if (mode != IO_SEEK_SET) { + return IO_FAIL; + } + + ((file_state_t *) entity->info)->file_pos = offset; + + return IO_SUCCESS; +} + +static int32_t emmcdrv_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read) +{ + file_state_t *fp = (file_state_t *) entity->info; + uint32_t sector_add, sector_num, emmc_dma = 0; + int32_t result = IO_SUCCESS; + + sector_add = current_file.file_pos >> EMMC_SECTOR_SIZE_SHIFT; + sector_num = (length + EMMC_SECTOR_SIZE - 1U) >> EMMC_SECTOR_SIZE_SHIFT; + + NOTICE("BL2: Load dst=0x%lx src=(p:%d)0x%llx(%d) len=0x%lx(%d)\n", + buffer, + current_file.partition, current_file.file_pos, + sector_add, length, sector_num); + + if ((buffer + length - 1U) <= (uintptr_t)UINT32_MAX) { + emmc_dma = LOADIMAGE_FLAGS_DMA_ENABLE; + } + + if (emmc_read_sector((uint32_t *) buffer, sector_add, sector_num, + emmc_dma) != EMMC_SUCCESS) { + result = IO_FAIL; + } + + *length_read = length; + fp->file_pos += (signed long long)length; + + return result; +} + +static int32_t emmcdrv_block_open(io_dev_info_t *dev_info, + const uintptr_t spec, io_entity_t *entity) +{ + const io_drv_spec_t *block_spec = (io_drv_spec_t *) spec; + + if (current_file.in_use != 0U) { + WARN("mmc_block: Only one open spec at a time\n"); + return IO_RESOURCES_EXHAUSTED; + } + + current_file.file_pos = 0; + current_file.in_use = 1; + + if (emmcdrv_bootpartition == PARTITION_ID_USER) { + emmcdrv_bootpartition = mmc_drv_obj.boot_partition_en; + if ((emmcdrv_bootpartition == PARTITION_ID_BOOT_1) || + (emmcdrv_bootpartition == PARTITION_ID_BOOT_2)) { + current_file.partition = emmcdrv_bootpartition; + + NOTICE("BL2: eMMC boot from partition %d\n", + emmcdrv_bootpartition); + goto done; + } + return IO_FAIL; + } + + if ((block_spec->partition == PARTITION_ID_USER) || + (block_spec->partition == PARTITION_ID_BOOT_1) || + (block_spec->partition == PARTITION_ID_BOOT_2)) { + current_file.partition = block_spec->partition; + } else { + current_file.partition = emmcdrv_bootpartition; + } + +done: + if (emmc_select_partition(current_file.partition) != EMMC_SUCCESS) { + return IO_FAIL; + } + + entity->info = (uintptr_t) ¤t_file; + + return IO_SUCCESS; +} + +static int32_t emmcdrv_block_close(io_entity_t *entity) +{ + memset((void *)¤t_file, 0, sizeof(current_file)); + entity->info = 0U; + + return IO_SUCCESS; +} + +static const io_dev_funcs_t emmcdrv_dev_funcs = { + .type = &device_type_emmcdrv, + .open = &emmcdrv_block_open, + .seek = &emmcdrv_block_seek, + .size = NULL, + .read = &emmcdrv_block_read, + .write = NULL, + .close = &emmcdrv_block_close, + .dev_init = NULL, + .dev_close = &emmcdrv_dev_close +}; + +static const io_dev_info_t emmcdrv_dev_info = { + .funcs = &emmcdrv_dev_funcs, + .info = (uintptr_t) 0 +}; + +static const io_dev_connector_t emmcdrv_dev_connector = { + &emmcdrv_dev_open, +}; + +static int32_t emmcdrv_dev_open(const uintptr_t spec __attribute__ ((unused)), + io_dev_info_t **dev_info) +{ + *dev_info = (io_dev_info_t *) &emmcdrv_dev_info; + + return IO_SUCCESS; +} + +static int32_t emmcdrv_dev_close(io_dev_info_t *dev_info) +{ + return IO_SUCCESS; +} + +int32_t rcar_register_io_dev_emmcdrv(const io_dev_connector_t **dev_con) +{ + int32_t rc; + + rc = io_register_device(&emmcdrv_dev_info); + if (rc == IO_SUCCESS) { + *dev_con = &emmcdrv_dev_connector; + } + + return rc; +} diff --git a/drivers/renesas/common/io/io_emmcdrv.h b/drivers/renesas/common/io/io_emmcdrv.h new file mode 100644 index 000000000..95070f24b --- /dev/null +++ b/drivers/renesas/common/io/io_emmcdrv.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_EMMCDRV_H +#define IO_EMMCDRV_H + +struct io_dev_connector; +int32_t rcar_register_io_dev_emmcdrv(const io_dev_connector_t **connector); + +#endif /* IO_EMMCDRV_H */ diff --git a/drivers/renesas/common/io/io_memdrv.c b/drivers/renesas/common/io/io_memdrv.c new file mode 100644 index 000000000..1f31c0fb9 --- /dev/null +++ b/drivers/renesas/common/io/io_memdrv.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <string.h> + +#include <common/debug.h> +#include <drivers/io/io_driver.h> +#include <drivers/io/io_storage.h> + +#include "io_common.h" +#include "io_memdrv.h" +#include "io_private.h" +#include "rcar_def.h" + +extern void rcar_dma_exec(uintptr_t dst, uint32_t src, uint32_t len); + +static int32_t memdrv_dev_open(const uintptr_t dev __attribute__ ((unused)), + io_dev_info_t **dev_info); +static int32_t memdrv_dev_close(io_dev_info_t *dev_info); + +/* + * As we need to be able to keep state for seek, only one file can be open + * at a time. Make this a structure and point to the entity->info. When we + * can malloc memory we can change this to support more open files. + */ +typedef struct { + uint32_t in_use; + uintptr_t base; + signed long long file_pos; +} file_state_t; + +static file_state_t current_file = { 0 }; + +static io_type_t device_type_memdrv(void) +{ + return IO_TYPE_MEMMAP; +} + +static int32_t memdrv_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity) +{ + const io_drv_spec_t *block_spec = (io_drv_spec_t *) spec; + + /* + * Since we need to track open state for seek() we only allow one open + * spec at a time. When we have dynamic memory we can malloc and set + * entity->info. + */ + if (current_file.in_use != 0U) { + return IO_RESOURCES_EXHAUSTED; + } + + /* File cursor offset for seek and incremental reads etc. */ + current_file.base = block_spec->offset; + current_file.file_pos = 0; + current_file.in_use = 1; + + entity->info = (uintptr_t) ¤t_file; + + return IO_SUCCESS; +} + +static int32_t memdrv_block_seek(io_entity_t *entity, int32_t mode, + signed long long offset) +{ + if (mode != IO_SEEK_SET) { + return IO_FAIL; + } + + ((file_state_t *) entity->info)->file_pos = offset; + + return IO_SUCCESS; +} + +static int32_t memdrv_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *cnt) +{ + file_state_t *fp; + + fp = (file_state_t *) entity->info; + + NOTICE("BL2: dst=0x%lx src=0x%llx len=%ld(0x%lx)\n", + buffer, (unsigned long long)fp->base + + (unsigned long long)fp->file_pos, length, length); + + if (FLASH_MEMORY_SIZE < (fp->file_pos + (signed long long)length)) { + ERROR("BL2: check load image (source address)\n"); + return IO_FAIL; + } + + rcar_dma_exec(buffer, fp->base + (uintptr_t)fp->file_pos, length); + fp->file_pos += (signed long long)length; + *cnt = length; + + return IO_SUCCESS; +} + +static int32_t memdrv_block_close(io_entity_t *entity) +{ + entity->info = 0U; + + memset((void *)¤t_file, 0, sizeof(current_file)); + + return IO_SUCCESS; +} + +static const io_dev_funcs_t memdrv_dev_funcs = { + .type = &device_type_memdrv, + .open = &memdrv_block_open, + .seek = &memdrv_block_seek, + .size = NULL, + .read = &memdrv_block_read, + .write = NULL, + .close = &memdrv_block_close, + .dev_init = NULL, + .dev_close = &memdrv_dev_close, +}; + +static const io_dev_info_t memdrv_dev_info = { + .funcs = &memdrv_dev_funcs, + .info = 0, +}; + +static const io_dev_connector_t memdrv_dev_connector = { + .dev_open = &memdrv_dev_open +}; + +static int32_t memdrv_dev_open(const uintptr_t dev __attribute__ ((unused)), + io_dev_info_t **dev_info) +{ + *dev_info = (io_dev_info_t *) &memdrv_dev_info; + + return IO_SUCCESS; +} + +static int32_t memdrv_dev_close(io_dev_info_t *dev_info) +{ + return IO_SUCCESS; +} + +int32_t rcar_register_io_dev_memdrv(const io_dev_connector_t **dev_con) +{ + int32_t result; + + result = io_register_device(&memdrv_dev_info); + if (result == IO_SUCCESS) { + *dev_con = &memdrv_dev_connector; + } + + return result; +} diff --git a/drivers/renesas/common/io/io_memdrv.h b/drivers/renesas/common/io/io_memdrv.h new file mode 100644 index 000000000..90e68123e --- /dev/null +++ b/drivers/renesas/common/io/io_memdrv.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_MEMDRV_H +#define IO_MEMDRV_H + +struct io_dev_connector; +int32_t rcar_register_io_dev_memdrv(const io_dev_connector_t **connector); + +#endif /* IO_MEMDRV_H */ diff --git a/drivers/renesas/common/io/io_private.h b/drivers/renesas/common/io/io_private.h new file mode 100644 index 000000000..207523a73 --- /dev/null +++ b/drivers/renesas/common/io/io_private.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_PRIVATE_H +#define IO_PRIVATE_H + +/* + * Return codes reported by 'io_*' APIs + * The value of fail should not overlap with define of the errno. + * The errno is in "include/lib/stdlib/sys/errno.h". + */ +#define IO_SUCCESS (0) +#define IO_FAIL (-0x81) +#define IO_NOT_SUPPORTED (-0x82) +#define IO_RESOURCES_EXHAUSTED (-0x83) + +#endif /* IO_PRIVATE_H */ diff --git a/drivers/renesas/common/io/io_rcar.c b/drivers/renesas/common/io/io_rcar.c new file mode 100644 index 000000000..c3e8319de --- /dev/null +++ b/drivers/renesas/common/io/io_rcar.c @@ -0,0 +1,654 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <errno.h> +#include <stdint.h> +#include <string.h> + +#include <arch_helpers.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <drivers/auth/auth_mod.h> +#include <drivers/io/io_driver.h> +#include <drivers/io/io_storage.h> +#include <lib/mmio.h> +#include <plat/common/platform.h> +#include <tools_share/firmware_image_package.h> +#include <tools_share/uuid.h> + +#include "io_rcar.h" +#include "io_common.h" +#include "io_private.h" +#include <platform_def.h> + +extern int32_t plat_get_drv_source(uint32_t id, uintptr_t *dev, + uintptr_t *image_spec); + +static int32_t rcar_dev_open(const uintptr_t dev_spec __attribute__ ((unused)), + io_dev_info_t **dev_info); +static int32_t rcar_dev_close(io_dev_info_t *dev_info); + +typedef struct { + const int32_t name; + const uint32_t offset; + const uint32_t attr; +} plat_rcar_name_offset_t; + +typedef struct { + /* + * Put position above the struct to allow {0} on static init. + * It is a workaround for a known bug in GCC + * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119 + */ + uint32_t position; + uint32_t no_load; + uintptr_t offset; + uint32_t size; + uintptr_t dst; + uintptr_t partition; /* for eMMC */ + /* RCAR_EMMC_PARTITION_BOOT_0 */ + /* RCAR_EMMC_PARTITION_BOOT_1 */ + /* RCAR_EMMC_PARTITION_USER */ +} file_state_t; + +#define RCAR_GET_FLASH_ADR(a, b) ((uint32_t)((0x40000U * (a)) + (b))) +#define RCAR_ATTR_SET_CALCADDR(a) ((a) & 0xF) +#define RCAR_ATTR_SET_ISNOLOAD(a) (((a) & 0x1) << 16U) +#define RCAR_ATTR_SET_CERTOFF(a) (((a) & 0xF) << 8U) +#define RCAR_ATTR_SET_ALL(a, b, c) ((uint32_t)(RCAR_ATTR_SET_CALCADDR(a) |\ + RCAR_ATTR_SET_ISNOLOAD(b) |\ + RCAR_ATTR_SET_CERTOFF(c))) + +#define RCAR_ATTR_GET_CALCADDR(a) ((a) & 0xFU) +#define RCAR_ATTR_GET_ISNOLOAD(a) (((a) >> 16) & 0x1U) +#define RCAR_ATTR_GET_CERTOFF(a) ((uint32_t)(((a) >> 8) & 0xFU)) + +#define RCAR_MAX_BL3X_IMAGE (8U) +#define RCAR_SECTOR6_CERT_OFFSET (0x400U) +#define RCAR_SDRAM_certESS (0x43F00000U) +#define RCAR_CERT_SIZE (0x800U) +#define RCAR_CERT_INFO_SIZE_OFFSET (0x264U) +#define RCAR_CERT_INFO_DST_OFFSET (0x154U) +#define RCAR_CERT_INFO_SIZE_OFFSET1 (0x364U) +#define RCAR_CERT_INFO_DST_OFFSET1 (0x1D4U) +#define RCAR_CERT_INFO_SIZE_OFFSET2 (0x464U) +#define RCAR_CERT_INFO_DST_OFFSET2 (0x254U) +#define RCAR_CERT_LOAD (1U) + +#define RCAR_FLASH_CERT_HEADER RCAR_GET_FLASH_ADR(6U, 0U) +#define RCAR_EMMC_CERT_HEADER (0x00030000U) + +#define RCAR_COUNT_LOAD_BL33 (2U) +#define RCAR_COUNT_LOAD_BL33X (3U) + +static const plat_rcar_name_offset_t name_offset[] = { + {BL31_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(0, 0, 0)}, + + /* BL3-2 is optional in the platform */ + {BL32_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(1, 0, 1)}, + {BL33_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(2, 0, 2)}, + {BL332_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(3, 0, 3)}, + {BL333_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(4, 0, 4)}, + {BL334_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(5, 0, 5)}, + {BL335_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(6, 0, 6)}, + {BL336_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(7, 0, 7)}, + {BL337_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(8, 0, 8)}, + {BL338_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(9, 0, 9)}, +}; + +#if TRUSTED_BOARD_BOOT +static const plat_rcar_name_offset_t cert_offset[] = { + /* Certificates */ + {TRUSTED_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, + {SOC_FW_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, + {TRUSTED_OS_FW_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, + {NON_TRUSTED_FW_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, + {SOC_FW_CONTENT_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, + {TRUSTED_OS_FW_CONTENT_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 1)}, + {NON_TRUSTED_FW_CONTENT_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 2)}, + {BL332_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 3)}, + {BL333_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 4)}, + {BL334_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 5)}, + {BL335_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 6)}, + {BL336_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 7)}, + {BL337_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 8)}, + {BL338_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 9)}, +}; +#endif /* TRUSTED_BOARD_BOOT */ + +static file_state_t current_file = { 0 }; + +static uintptr_t rcar_handle, rcar_spec; +static uint64_t rcar_image_header[RCAR_MAX_BL3X_IMAGE + 2U] = { 0U }; +static uint64_t rcar_image_header_prttn[RCAR_MAX_BL3X_IMAGE + 2U] = { 0U }; +static uint64_t rcar_image_number = { 0U }; +static uint32_t rcar_cert_load = { 0U }; + +static io_type_t device_type_rcar(void) +{ + return IO_TYPE_FIRMWARE_IMAGE_PACKAGE; +} + +int32_t rcar_get_certificate(const int32_t name, uint32_t *cert) +{ +#if TRUSTED_BOARD_BOOT + int32_t i; + + for (i = 0; i < ARRAY_SIZE(cert_offset); i++) { + if (name != cert_offset[i].name) { + continue; + } + + *cert = RCAR_CERT_SIZE; + *cert *= RCAR_ATTR_GET_CERTOFF(cert_offset[i].attr); + *cert += RCAR_SDRAM_certESS; + return 0; + } +#endif + return -EINVAL; +} + +static int32_t file_to_offset(const int32_t name, uintptr_t *offset, + uint32_t *cert, uint32_t *no_load, + uintptr_t *partition) +{ + uint32_t addr; + int32_t i; + + for (i = 0; i < ARRAY_SIZE(name_offset); i++) { + if (name != name_offset[i].name) { + continue; + } + + addr = RCAR_ATTR_GET_CALCADDR(name_offset[i].attr); + if (rcar_image_number + 2U < addr) { + continue; + } + + *offset = rcar_image_header[addr]; + *cert = RCAR_CERT_SIZE; + *cert *= RCAR_ATTR_GET_CERTOFF(name_offset[i].attr); + *cert += RCAR_SDRAM_certESS; + *no_load = RCAR_ATTR_GET_ISNOLOAD(name_offset[i].attr); + *partition = rcar_image_header_prttn[addr]; + return IO_SUCCESS; + } + +#if TRUSTED_BOARD_BOOT + for (i = 0; i < ARRAY_SIZE(cert_offset); i++) { + if (name != cert_offset[i].name) { + continue; + } + + *no_load = RCAR_ATTR_GET_ISNOLOAD(cert_offset[i].attr); + *partition = 0U; + *offset = 0U; + *cert = 0U; + return IO_SUCCESS; + } +#endif + return -EINVAL; +} + +#define RCAR_BOOT_KEY_CERT_NEW (0xE6300F00U) +#define RCAR_CERT_MAGIC_NUM (0xE291F358U) + +void rcar_read_certificate(uint64_t cert, uint32_t *len, uintptr_t *dst) +{ + uint32_t seed, val, info_1, info_2; + uintptr_t size, dsth, dstl; + + cert &= 0xFFFFFFFFU; + + seed = mmio_read_32(RCAR_BOOT_KEY_CERT_NEW); + val = mmio_read_32(RCAR_BOOT_KEY_CERT_NEW + 0xC); + info_1 = (val >> 18) & 0x3U; + val = mmio_read_32(cert + 0xC); + info_2 = (val >> 21) & 0x3; + + if (seed == RCAR_CERT_MAGIC_NUM) { + if (info_1 != 1) { + ERROR("BL2: Cert is invalid.\n"); + *dst = 0; + *len = 0; + return; + } + + if (info_2 > 2) { + ERROR("BL2: Cert is invalid.\n"); + *dst = 0; + *len = 0; + return; + } + + switch (info_2) { + case 2: + size = cert + RCAR_CERT_INFO_SIZE_OFFSET2; + dstl = cert + RCAR_CERT_INFO_DST_OFFSET2; + break; + case 1: + size = cert + RCAR_CERT_INFO_SIZE_OFFSET1; + dstl = cert + RCAR_CERT_INFO_DST_OFFSET1; + break; + case 0: + size = cert + RCAR_CERT_INFO_SIZE_OFFSET; + dstl = cert + RCAR_CERT_INFO_DST_OFFSET; + break; + } + + *len = mmio_read_32(size) * 4U; + dsth = dstl + 4U; + *dst = ((uintptr_t) mmio_read_32(dsth) << 32) + + ((uintptr_t) mmio_read_32(dstl)); + return; + } + + size = cert + RCAR_CERT_INFO_SIZE_OFFSET; + *len = mmio_read_32(size) * 4U; + dstl = cert + RCAR_CERT_INFO_DST_OFFSET; + dsth = dstl + 4U; + *dst = ((uintptr_t) mmio_read_32(dsth) << 32) + + ((uintptr_t) mmio_read_32(dstl)); +} + +static int32_t check_load_area(uintptr_t dst, uintptr_t len) +{ + uint32_t legacy = dst + len <= UINT32_MAX - 1 ? 1 : 0; + uintptr_t dram_start, dram_end; + uintptr_t prot_start, prot_end; + int32_t result = IO_SUCCESS; + + dram_start = legacy ? DRAM1_BASE : DRAM_40BIT_BASE; + + dram_end = legacy ? DRAM1_BASE + DRAM1_SIZE : + DRAM_40BIT_BASE + DRAM_40BIT_SIZE; + + prot_start = legacy ? DRAM_PROTECTED_BASE : DRAM_40BIT_PROTECTED_BASE; + + prot_end = prot_start + DRAM_PROTECTED_SIZE; + + if (dst < dram_start || dst > dram_end - len) { + ERROR("BL2: dst address is on the protected area.\n"); + result = IO_FAIL; + goto done; + } + + /* load image is within SDRAM protected area */ + if (dst >= prot_start && dst < prot_end) { + ERROR("BL2: dst address is on the protected area.\n"); + result = IO_FAIL; + } + + if (dst < prot_start && dst > prot_start - len) { + ERROR("BL2: loaded data is on the protected area.\n"); + result = IO_FAIL; + } +done: + if (result == IO_FAIL) { + ERROR("BL2: Out of range : dst=0x%lx len=0x%lx\n", dst, len); + } + + return result; +} + +static int32_t load_bl33x(void) +{ + static int32_t loaded = IO_NOT_SUPPORTED; + uintptr_t dst, partition, handle; + uint32_t noload, cert, len, i; + uintptr_t offset; + int32_t rc; + size_t cnt; + const int32_t img[] = { + BL33_IMAGE_ID, + BL332_IMAGE_ID, + BL333_IMAGE_ID, + BL334_IMAGE_ID, + BL335_IMAGE_ID, + BL336_IMAGE_ID, + BL337_IMAGE_ID, + BL338_IMAGE_ID + }; + + if (loaded != IO_NOT_SUPPORTED) { + return loaded; + } + + for (i = 1; i < rcar_image_number; i++) { + rc = file_to_offset(img[i], &offset, &cert, &noload, + &partition); + if (rc != IO_SUCCESS) { + WARN("%s: failed to get offset\n", __func__); + loaded = IO_FAIL; + return loaded; + } + + rcar_read_certificate((uint64_t) cert, &len, &dst); + ((io_drv_spec_t *) rcar_spec)->partition = partition; + + rc = io_open(rcar_handle, rcar_spec, &handle); + if (rc != IO_SUCCESS) { + WARN("%s: Failed to open FIP (%i)\n", __func__, rc); + loaded = IO_FAIL; + return loaded; + } + + rc = io_seek(handle, IO_SEEK_SET, offset); + if (rc != IO_SUCCESS) { + WARN("%s: failed to seek\n", __func__); + loaded = IO_FAIL; + return loaded; + } + + rc = check_load_area(dst, len); + if (rc != IO_SUCCESS) { + WARN("%s: check load area\n", __func__); + loaded = IO_FAIL; + return loaded; + } + + rc = io_read(handle, dst, len, &cnt); + if (rc != IO_SUCCESS) { + WARN("%s: failed to read\n", __func__); + loaded = IO_FAIL; + return loaded; + } +#if TRUSTED_BOARD_BOOT + rc = auth_mod_verify_img(img[i], (void *)dst, len); + if (rc != 0) { + memset((void *)dst, 0x00, len); + loaded = IO_FAIL; + return loaded; + } +#endif + io_close(handle); + } + + loaded = IO_SUCCESS; + + return loaded; +} + +static int32_t rcar_dev_init(io_dev_info_t *dev_info, const uintptr_t name) +{ + uint64_t header[64] __aligned(FLASH_TRANS_SIZE_UNIT) = {0UL}; + uintptr_t handle; + ssize_t offset; + uint32_t i; + int32_t rc; + size_t cnt; + + /* Obtain a reference to the image by querying the platform layer */ + rc = plat_get_drv_source(name, &rcar_handle, &rcar_spec); + if (rc != IO_SUCCESS) { + WARN("Failed to obtain reference to img %ld (%i)\n", name, rc); + return IO_FAIL; + } + + if (rcar_cert_load == RCAR_CERT_LOAD) { + return IO_SUCCESS; + } + + rc = io_open(rcar_handle, rcar_spec, &handle); + if (rc != IO_SUCCESS) { + WARN("Failed to access img %ld (%i)\n", name, rc); + return IO_FAIL; + } + + /* + * get start address list + * [0] address num + * [1] BL33-1 image address + * [2] BL33-2 image address + * [3] BL33-3 image address + * [4] BL33-4 image address + * [5] BL33-5 image address + * [6] BL33-6 image address + * [7] BL33-7 image address + * [8] BL33-8 image address + */ + offset = name == EMMC_DEV_ID ? RCAR_EMMC_CERT_HEADER : + RCAR_FLASH_CERT_HEADER; + rc = io_seek(handle, IO_SEEK_SET, offset); + if (rc != IO_SUCCESS) { + WARN("Firmware Image Package header failed to seek\n"); + goto error; + } +#if RCAR_BL2_DCACHE == 1 + inv_dcache_range((uint64_t) header, sizeof(header)); +#endif + rc = io_read(handle, (uintptr_t) &header, sizeof(header), &cnt); + if (rc != IO_SUCCESS) { + WARN("Firmware Image Package header failed to read\n"); + goto error; + } + + rcar_image_number = header[0]; + for (i = 0; i < rcar_image_number + 2; i++) { + rcar_image_header[i] = header[i * 2 + 1]; + rcar_image_header_prttn[i] = header[i * 2 + 2]; + } + + if (rcar_image_number == 0 || rcar_image_number > RCAR_MAX_BL3X_IMAGE) { + WARN("Firmware Image Package header check failed.\n"); + goto error; + } + + rc = io_seek(handle, IO_SEEK_SET, offset + RCAR_SECTOR6_CERT_OFFSET); + if (rc != IO_SUCCESS) { + WARN("Firmware Image Package header failed to seek cert\n"); + goto error; + } +#if RCAR_BL2_DCACHE == 1 + inv_dcache_range(RCAR_SDRAM_certESS, + RCAR_CERT_SIZE * (2 + rcar_image_number)); +#endif + rc = io_read(handle, RCAR_SDRAM_certESS, + RCAR_CERT_SIZE * (2 + rcar_image_number), &cnt); + if (rc != IO_SUCCESS) { + WARN("cert file read error.\n"); + goto error; + } + + rcar_cert_load = RCAR_CERT_LOAD; +error: + + if (rc != IO_SUCCESS) { + rc = IO_FAIL; + } + + io_close(handle); + + return rc; + +} + +static int32_t rcar_file_open(io_dev_info_t *info, const uintptr_t file_spec, + io_entity_t *entity) +{ + const io_drv_spec_t *spec = (io_drv_spec_t *) file_spec; + uintptr_t partition, offset, dst; + uint32_t noload, cert, len; + int32_t rc; + + /* + * Only one file open at a time. We need to track state (ie, file + * cursor position). Since the header lives at offset zero, this entry + * should never be zero in an active file. + * Once the system supports dynamic memory allocation we will allow more + * than one open file at a time. + */ + if (current_file.offset != 0U) { + WARN("%s: Only one open file at a time.\n", __func__); + return IO_RESOURCES_EXHAUSTED; + } + + rc = file_to_offset(spec->offset, &offset, &cert, &noload, &partition); + if (rc != IO_SUCCESS) { + WARN("Failed to open file name %ld (%i)\n", spec->offset, rc); + return IO_FAIL; + } + + if (noload != 0U) { + current_file.offset = 1; + current_file.dst = 0; + current_file.size = 1; + current_file.position = 0; + current_file.no_load = noload; + current_file.partition = 0; + entity->info = (uintptr_t) ¤t_file; + + return IO_SUCCESS; + } + + rcar_read_certificate((uint64_t) cert, &len, &dst); + + /* Baylibre: HACK */ + if (spec->offset == BL31_IMAGE_ID && len < RCAR_TRUSTED_SRAM_SIZE) { + WARN("%s,%s\n", "r-car ignoring the BL31 size from certificate", + "using RCAR_TRUSTED_SRAM_SIZE instead"); + len = RCAR_TRUSTED_SRAM_SIZE; + } + + current_file.partition = partition; + current_file.no_load = noload; + current_file.offset = offset; + current_file.position = 0; + current_file.size = len; + current_file.dst = dst; + entity->info = (uintptr_t) ¤t_file; + + return IO_SUCCESS; +} + +static int32_t rcar_file_len(io_entity_t *entity, size_t *length) +{ + *length = ((file_state_t *) entity->info)->size; + + NOTICE("%s: len: 0x%08lx\n", __func__, *length); + + return IO_SUCCESS; +} + +static int32_t rcar_file_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *cnt) +{ + file_state_t *fp = (file_state_t *) entity->info; + ssize_t offset = fp->offset + fp->position; + uintptr_t handle; + int32_t rc; + +#ifdef SPD_NONE + static uint32_t load_bl33x_counter = 1; +#else + static uint32_t load_bl33x_counter; +#endif + if (current_file.no_load != 0U) { + *cnt = length; + return IO_SUCCESS; + } + + ((io_drv_spec_t *) rcar_spec)->partition = fp->partition; + + rc = io_open(rcar_handle, rcar_spec, &handle); + if (rc != IO_SUCCESS) { + WARN("Failed to open FIP (%i)\n", rc); + return IO_FAIL; + } + + rc = io_seek(handle, IO_SEEK_SET, offset); + if (rc != IO_SUCCESS) { + WARN("%s: failed to seek\n", __func__); + goto error; + } + + if (load_bl33x_counter == RCAR_COUNT_LOAD_BL33) { + rc = check_load_area(buffer, length); + if (rc != IO_SUCCESS) { + WARN("%s: load area err\n", __func__); + goto error; + } + } + + rc = io_read(handle, buffer, length, cnt); + if (rc != IO_SUCCESS) { + WARN("Failed to read payload (%i)\n", rc); + goto error; + } + + fp->position += *cnt; + io_close(handle); + + load_bl33x_counter += 1; + if (load_bl33x_counter == RCAR_COUNT_LOAD_BL33X) { + return load_bl33x(); + } + + return IO_SUCCESS; +error: + io_close(handle); + return IO_FAIL; +} + +static int32_t rcar_file_close(io_entity_t *entity) +{ + if (current_file.offset != 0U) { + memset(¤t_file, 0, sizeof(current_file)); + } + + entity->info = 0U; + + return IO_SUCCESS; +} + +static const io_dev_funcs_t rcar_dev_funcs = { + .type = &device_type_rcar, + .open = &rcar_file_open, + .seek = NULL, + .size = &rcar_file_len, + .read = &rcar_file_read, + .write = NULL, + .close = &rcar_file_close, + .dev_init = &rcar_dev_init, + .dev_close = &rcar_dev_close, +}; + +static const io_dev_info_t rcar_dev_info = { + .funcs = &rcar_dev_funcs, + .info = (uintptr_t) 0 +}; + +static const io_dev_connector_t rcar_dev_connector = { + .dev_open = &rcar_dev_open +}; + +static int32_t rcar_dev_open(const uintptr_t dev_spec __attribute__ ((unused)), + io_dev_info_t **dev_info) +{ + *dev_info = (io_dev_info_t *) &rcar_dev_info; + + return IO_SUCCESS; +} + +static int32_t rcar_dev_close(io_dev_info_t *dev_info) +{ + rcar_handle = 0; + rcar_spec = 0; + + return IO_SUCCESS; +} + +int32_t rcar_register_io_dev(const io_dev_connector_t **dev_con) +{ + int32_t result; + + result = io_register_device(&rcar_dev_info); + if (result == IO_SUCCESS) { + *dev_con = &rcar_dev_connector; + } + + return result; +} diff --git a/drivers/renesas/common/io/io_rcar.h b/drivers/renesas/common/io/io_rcar.h new file mode 100644 index 000000000..c26a61767 --- /dev/null +++ b/drivers/renesas/common/io/io_rcar.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_RCAR_H +#define IO_RCAR_H + +int32_t rcar_register_io_dev(const io_dev_connector_t **dev_con); +int32_t rcar_get_certificate(const int32_t name, uint32_t *cert); +void rcar_read_certificate(uint64_t cert, uint32_t *size, uintptr_t *dest); + +#endif /* IO_RCAR_H */ diff --git a/drivers/renesas/common/pfc_regs.h b/drivers/renesas/common/pfc_regs.h new file mode 100644 index 000000000..418773366 --- /dev/null +++ b/drivers/renesas/common/pfc_regs.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PFC_REGS_H +#define PFC_REGS_H + +/* GPIO base address */ +#define GPIO_BASE (0xE6050000U) + +/* GPIO registers */ +#define GPIO_IOINTSEL0 (GPIO_BASE + 0x0000U) +#define GPIO_INOUTSEL0 (GPIO_BASE + 0x0004U) +#define GPIO_OUTDT0 (GPIO_BASE + 0x0008U) +#define GPIO_INDT0 (GPIO_BASE + 0x000CU) +#define GPIO_INTDT0 (GPIO_BASE + 0x0010U) +#define GPIO_INTCLR0 (GPIO_BASE + 0x0014U) +#define GPIO_INTMSK0 (GPIO_BASE + 0x0018U) +#define GPIO_MSKCLR0 (GPIO_BASE + 0x001CU) +#define GPIO_POSNEG0 (GPIO_BASE + 0x0020U) +#define GPIO_EDGLEVEL0 (GPIO_BASE + 0x0024U) +#define GPIO_FILONOFF0 (GPIO_BASE + 0x0028U) +#define GPIO_INTMSKS0 (GPIO_BASE + 0x0038U) +#define GPIO_MSKCLRS0 (GPIO_BASE + 0x003CU) +#define GPIO_OUTDTSEL0 (GPIO_BASE + 0x0040U) +#define GPIO_OUTDTH0 (GPIO_BASE + 0x0044U) +#define GPIO_OUTDTL0 (GPIO_BASE + 0x0048U) +#define GPIO_BOTHEDGE0 (GPIO_BASE + 0x004CU) +#define GPIO_IOINTSEL1 (GPIO_BASE + 0x1000U) +#define GPIO_INOUTSEL1 (GPIO_BASE + 0x1004U) +#define GPIO_OUTDT1 (GPIO_BASE + 0x1008U) +#define GPIO_INDT1 (GPIO_BASE + 0x100CU) +#define GPIO_INTDT1 (GPIO_BASE + 0x1010U) +#define GPIO_INTCLR1 (GPIO_BASE + 0x1014U) +#define GPIO_INTMSK1 (GPIO_BASE + 0x1018U) +#define GPIO_MSKCLR1 (GPIO_BASE + 0x101CU) +#define GPIO_POSNEG1 (GPIO_BASE + 0x1020U) +#define GPIO_EDGLEVEL1 (GPIO_BASE + 0x1024U) +#define GPIO_FILONOFF1 (GPIO_BASE + 0x1028U) +#define GPIO_INTMSKS1 (GPIO_BASE + 0x1038U) +#define GPIO_MSKCLRS1 (GPIO_BASE + 0x103CU) +#define GPIO_OUTDTSEL1 (GPIO_BASE + 0x1040U) +#define GPIO_OUTDTH1 (GPIO_BASE + 0x1044U) +#define GPIO_OUTDTL1 (GPIO_BASE + 0x1048U) +#define GPIO_BOTHEDGE1 (GPIO_BASE + 0x104CU) +#define GPIO_IOINTSEL2 (GPIO_BASE + 0x2000U) +#define GPIO_INOUTSEL2 (GPIO_BASE + 0x2004U) +#define GPIO_OUTDT2 (GPIO_BASE + 0x2008U) +#define GPIO_INDT2 (GPIO_BASE + 0x200CU) +#define GPIO_INTDT2 (GPIO_BASE + 0x2010U) +#define GPIO_INTCLR2 (GPIO_BASE + 0x2014U) +#define GPIO_INTMSK2 (GPIO_BASE + 0x2018U) +#define GPIO_MSKCLR2 (GPIO_BASE + 0x201CU) +#define GPIO_POSNEG2 (GPIO_BASE + 0x2020U) +#define GPIO_EDGLEVEL2 (GPIO_BASE + 0x2024U) +#define GPIO_FILONOFF2 (GPIO_BASE + 0x2028U) +#define GPIO_INTMSKS2 (GPIO_BASE + 0x2038U) +#define GPIO_MSKCLRS2 (GPIO_BASE + 0x203CU) +#define GPIO_OUTDTSEL2 (GPIO_BASE + 0x2040U) +#define GPIO_OUTDTH2 (GPIO_BASE + 0x2044U) +#define GPIO_OUTDTL2 (GPIO_BASE + 0x2048U) +#define GPIO_BOTHEDGE2 (GPIO_BASE + 0x204CU) +#define GPIO_IOINTSEL3 (GPIO_BASE + 0x3000U) +#define GPIO_INOUTSEL3 (GPIO_BASE + 0x3004U) +#define GPIO_OUTDT3 (GPIO_BASE + 0x3008U) +#define GPIO_INDT3 (GPIO_BASE + 0x300CU) +#define GPIO_INTDT3 (GPIO_BASE + 0x3010U) +#define GPIO_INTCLR3 (GPIO_BASE + 0x3014U) +#define GPIO_INTMSK3 (GPIO_BASE + 0x3018U) +#define GPIO_MSKCLR3 (GPIO_BASE + 0x301CU) +#define GPIO_POSNEG3 (GPIO_BASE + 0x3020U) +#define GPIO_EDGLEVEL3 (GPIO_BASE + 0x3024U) +#define GPIO_FILONOFF3 (GPIO_BASE + 0x3028U) +#define GPIO_INTMSKS3 (GPIO_BASE + 0x3038U) +#define GPIO_MSKCLRS3 (GPIO_BASE + 0x303CU) +#define GPIO_OUTDTSEL3 (GPIO_BASE + 0x3040U) +#define GPIO_OUTDTH3 (GPIO_BASE + 0x3044U) +#define GPIO_OUTDTL3 (GPIO_BASE + 0x3048U) +#define GPIO_BOTHEDGE3 (GPIO_BASE + 0x304CU) +#define GPIO_IOINTSEL4 (GPIO_BASE + 0x4000U) +#define GPIO_INOUTSEL4 (GPIO_BASE + 0x4004U) +#define GPIO_OUTDT4 (GPIO_BASE + 0x4008U) +#define GPIO_INDT4 (GPIO_BASE + 0x400CU) +#define GPIO_INTDT4 (GPIO_BASE + 0x4010U) +#define GPIO_INTCLR4 (GPIO_BASE + 0x4014U) +#define GPIO_INTMSK4 (GPIO_BASE + 0x4018U) +#define GPIO_MSKCLR4 (GPIO_BASE + 0x401CU) +#define GPIO_POSNEG4 (GPIO_BASE + 0x4020U) +#define GPIO_EDGLEVEL4 (GPIO_BASE + 0x4024U) +#define GPIO_FILONOFF4 (GPIO_BASE + 0x4028U) +#define GPIO_INTMSKS4 (GPIO_BASE + 0x4038U) +#define GPIO_MSKCLRS4 (GPIO_BASE + 0x403CU) +#define GPIO_OUTDTSEL4 (GPIO_BASE + 0x4040U) +#define GPIO_OUTDTH4 (GPIO_BASE + 0x4044U) +#define GPIO_OUTDTL4 (GPIO_BASE + 0x4048U) +#define GPIO_BOTHEDGE4 (GPIO_BASE + 0x404CU) +#define GPIO_IOINTSEL5 (GPIO_BASE + 0x5000U) +#define GPIO_INOUTSEL5 (GPIO_BASE + 0x5004U) +#define GPIO_OUTDT5 (GPIO_BASE + 0x5008U) +#define GPIO_INDT5 (GPIO_BASE + 0x500CU) +#define GPIO_INTDT5 (GPIO_BASE + 0x5010U) +#define GPIO_INTCLR5 (GPIO_BASE + 0x5014U) +#define GPIO_INTMSK5 (GPIO_BASE + 0x5018U) +#define GPIO_MSKCLR5 (GPIO_BASE + 0x501CU) +#define GPIO_POSNEG5 (GPIO_BASE + 0x5020U) +#define GPIO_EDGLEVEL5 (GPIO_BASE + 0x5024U) +#define GPIO_FILONOFF5 (GPIO_BASE + 0x5028U) +#define GPIO_INTMSKS5 (GPIO_BASE + 0x5038U) +#define GPIO_MSKCLRS5 (GPIO_BASE + 0x503CU) +#define GPIO_OUTDTSEL5 (GPIO_BASE + 0x5040U) +#define GPIO_OUTDTH5 (GPIO_BASE + 0x5044U) +#define GPIO_OUTDTL5 (GPIO_BASE + 0x5048U) +#define GPIO_BOTHEDGE5 (GPIO_BASE + 0x504CU) +#define GPIO_IOINTSEL6 (GPIO_BASE + 0x5400U) +#define GPIO_INOUTSEL6 (GPIO_BASE + 0x5404U) +#define GPIO_OUTDT6 (GPIO_BASE + 0x5408U) +#define GPIO_INTDT6 (GPIO_BASE + 0x5410U) +#define GPIO_INTCLR6 (GPIO_BASE + 0x5414U) +#define GPIO_INTMSK6 (GPIO_BASE + 0x5418U) +#define GPIO_MSKCLR6 (GPIO_BASE + 0x541CU) +#define GPIO_POSNEG6 (GPIO_BASE + 0x5420U) +#define GPIO_EDGLEVEL6 (GPIO_BASE + 0x5424U) +#define GPIO_FILONOFF6 (GPIO_BASE + 0x5428U) +#define GPIO_INTMSKS6 (GPIO_BASE + 0x5438U) +#define GPIO_MSKCLRS6 (GPIO_BASE + 0x543CU) +#define GPIO_OUTDTSEL6 (GPIO_BASE + 0x5440U) +#define GPIO_OUTDTH6 (GPIO_BASE + 0x5444U) +#define GPIO_OUTDTL6 (GPIO_BASE + 0x5448U) +#define GPIO_BOTHEDGE6 (GPIO_BASE + 0x544CU) +#define GPIO_IOINTSEL7 (GPIO_BASE + 0x5800U) +#define GPIO_INOUTSEL7 (GPIO_BASE + 0x5804U) +#define GPIO_OUTDT7 (GPIO_BASE + 0x5808U) +#define GPIO_INDT7 (GPIO_BASE + 0x580CU) +#define GPIO_INTDT7 (GPIO_BASE + 0x5810U) +#define GPIO_INTCLR7 (GPIO_BASE + 0x5814U) +#define GPIO_INTMSK7 (GPIO_BASE + 0x5818U) +#define GPIO_MSKCLR7 (GPIO_BASE + 0x581CU) +#define GPIO_POSNEG7 (GPIO_BASE + 0x5820U) +#define GPIO_EDGLEVEL7 (GPIO_BASE + 0x5824U) +#define GPIO_FILONOFF7 (GPIO_BASE + 0x5828U) +#define GPIO_INTMSKS7 (GPIO_BASE + 0x5838U) +#define GPIO_MSKCLRS7 (GPIO_BASE + 0x583CU) +#define GPIO_OUTDTSEL7 (GPIO_BASE + 0x5840U) +#define GPIO_OUTDTH7 (GPIO_BASE + 0x5844U) +#define GPIO_OUTDTL7 (GPIO_BASE + 0x5848U) +#define GPIO_BOTHEDGE7 (GPIO_BASE + 0x584CU) + +/* Pin functon base address */ +#define PFC_BASE (0xE6060000U) + +/* Pin functon registers */ +#define PFC_PMMR (PFC_BASE + 0x0000U) +#define PFC_GPSR0 (PFC_BASE + 0x0100U) +#define PFC_GPSR1 (PFC_BASE + 0x0104U) +#define PFC_GPSR2 (PFC_BASE + 0x0108U) +#define PFC_GPSR3 (PFC_BASE + 0x010CU) +#define PFC_GPSR4 (PFC_BASE + 0x0110U) +#define PFC_GPSR5 (PFC_BASE + 0x0114U) +#define PFC_GPSR6 (PFC_BASE + 0x0118U) +#define PFC_GPSR7 (PFC_BASE + 0x011CU) +#define PFC_IPSR0 (PFC_BASE + 0x0200U) +#define PFC_IPSR1 (PFC_BASE + 0x0204U) +#define PFC_IPSR2 (PFC_BASE + 0x0208U) +#define PFC_IPSR3 (PFC_BASE + 0x020CU) +#define PFC_IPSR4 (PFC_BASE + 0x0210U) +#define PFC_IPSR5 (PFC_BASE + 0x0214U) +#define PFC_IPSR6 (PFC_BASE + 0x0218U) +#define PFC_IPSR7 (PFC_BASE + 0x021CU) +#define PFC_IPSR8 (PFC_BASE + 0x0220U) +#define PFC_IPSR9 (PFC_BASE + 0x0224U) +#define PFC_IPSR10 (PFC_BASE + 0x0228U) +#define PFC_IPSR11 (PFC_BASE + 0x022CU) +#define PFC_IPSR12 (PFC_BASE + 0x0230U) +#define PFC_IPSR13 (PFC_BASE + 0x0234U) +#define PFC_IPSR14 (PFC_BASE + 0x0238U) +#define PFC_IPSR15 (PFC_BASE + 0x023CU) +#define PFC_IPSR16 (PFC_BASE + 0x0240U) +#define PFC_IPSR17 (PFC_BASE + 0x0244U) +#define PFC_IPSR18 (PFC_BASE + 0x0248U) +#define PFC_DRVCTRL0 (PFC_BASE + 0x0300U) +#define PFC_DRVCTRL1 (PFC_BASE + 0x0304U) +#define PFC_DRVCTRL2 (PFC_BASE + 0x0308U) +#define PFC_DRVCTRL3 (PFC_BASE + 0x030CU) +#define PFC_DRVCTRL4 (PFC_BASE + 0x0310U) +#define PFC_DRVCTRL5 (PFC_BASE + 0x0314U) +#define PFC_DRVCTRL6 (PFC_BASE + 0x0318U) +#define PFC_DRVCTRL7 (PFC_BASE + 0x031CU) +#define PFC_DRVCTRL8 (PFC_BASE + 0x0320U) +#define PFC_DRVCTRL9 (PFC_BASE + 0x0324U) +#define PFC_DRVCTRL10 (PFC_BASE + 0x0328U) +#define PFC_DRVCTRL11 (PFC_BASE + 0x032CU) +#define PFC_DRVCTRL12 (PFC_BASE + 0x0330U) +#define PFC_DRVCTRL13 (PFC_BASE + 0x0334U) +#define PFC_DRVCTRL14 (PFC_BASE + 0x0338U) +#define PFC_DRVCTRL15 (PFC_BASE + 0x033CU) +#define PFC_DRVCTRL16 (PFC_BASE + 0x0340U) +#define PFC_DRVCTRL17 (PFC_BASE + 0x0344U) +#define PFC_DRVCTRL18 (PFC_BASE + 0x0348U) +#define PFC_DRVCTRL19 (PFC_BASE + 0x034CU) +#define PFC_DRVCTRL20 (PFC_BASE + 0x0350U) +#define PFC_DRVCTRL21 (PFC_BASE + 0x0354U) +#define PFC_DRVCTRL22 (PFC_BASE + 0x0358U) +#define PFC_DRVCTRL23 (PFC_BASE + 0x035CU) +#define PFC_DRVCTRL24 (PFC_BASE + 0x0360U) +#define PFC_POCCTRL0 (PFC_BASE + 0x0380U) +#define PFC_IOCTRL31 (PFC_BASE + 0x0384U) +#define PFC_POCCTRL2 (PFC_BASE + 0x0388U) +#define PFC_TDSELCTRL0 (PFC_BASE + 0x03C0U) +#define PFC_IOCTRL (PFC_BASE + 0x03E0U) +#define PFC_TSREG (PFC_BASE + 0x03E4U) +#define PFC_PUEN0 (PFC_BASE + 0x0400U) +#define PFC_PUEN1 (PFC_BASE + 0x0404U) +#define PFC_PUEN2 (PFC_BASE + 0x0408U) +#define PFC_PUEN3 (PFC_BASE + 0x040CU) +#define PFC_PUEN4 (PFC_BASE + 0x0410U) +#define PFC_PUEN5 (PFC_BASE + 0x0414U) +#define PFC_PUEN6 (PFC_BASE + 0x0418U) +#define PFC_PUD0 (PFC_BASE + 0x0440U) +#define PFC_PUD1 (PFC_BASE + 0x0444U) +#define PFC_PUD2 (PFC_BASE + 0x0448U) +#define PFC_PUD3 (PFC_BASE + 0x044CU) +#define PFC_PUD4 (PFC_BASE + 0x0450U) +#define PFC_PUD5 (PFC_BASE + 0x0454U) +#define PFC_PUD6 (PFC_BASE + 0x0458U) +#define PFC_MOD_SEL0 (PFC_BASE + 0x0500U) +#define PFC_MOD_SEL1 (PFC_BASE + 0x0504U) +#define PFC_MOD_SEL2 (PFC_BASE + 0x0508U) + +#endif /* PFC_REGS_H */ diff --git a/drivers/renesas/common/pwrc/call_sram.S b/drivers/renesas/common/pwrc/call_sram.S new file mode 100644 index 000000000..aa8644cb9 --- /dev/null +++ b/drivers/renesas/common/pwrc/call_sram.S @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> + +.global rcar_pwrc_switch_stack + +/* + * x0 : jump address, + * x1 : stack address, + * x2 : arg, + * x3 : stack address (temporary) + */ +func rcar_pwrc_switch_stack + + /* lr to stack */ + stp x29, x30, [sp,#-16] + + /* change stack pointer */ + mov x3, sp + mov sp, x1 + + /* save stack pointer */ + sub sp, sp, #16 + stp x0, x3, [sp] + + /* data synchronization barrier */ + dsb sy + + /* jump to code */ + mov x1, x0 + mov x0, x2 + blr x1 + + /* load stack pointer */ + ldp x0, x2, [sp,#0] + + /* change stack pointer */ + mov sp, x2 + + /* return */ + ldp x29, x30, [sp,#-16] + ret +endfunc rcar_pwrc_switch_stack diff --git a/drivers/renesas/common/pwrc/pwrc.c b/drivers/renesas/common/pwrc/pwrc.c new file mode 100644 index 000000000..c0f015f04 --- /dev/null +++ b/drivers/renesas/common/pwrc/pwrc.c @@ -0,0 +1,871 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <string.h> + +#include <arch.h> +#include <arch_helpers.h> +#include <common/debug.h> +#include <lib/bakery_lock.h> +#include <lib/mmio.h> +#include <lib/xlat_tables/xlat_tables_v2.h> +#include <plat/common/platform.h> + +#include "iic_dvfs.h" +#include "micro_delay.h" +#include "pwrc.h" +#include "rcar_def.h" +#include "rcar_private.h" + +/* + * Someday there will be a generic power controller api. At the moment each + * platform has its own pwrc so just exporting functions should be acceptable. + */ +RCAR_INSTANTIATE_LOCK + +#define WUP_IRQ_SHIFT (0U) +#define WUP_FIQ_SHIFT (8U) +#define WUP_CSD_SHIFT (16U) +#define BIT_SOFTRESET (1U << 15) +#define BIT_CA53_SCU (1U << 21) +#define BIT_CA57_SCU (1U << 12) +#define REQ_RESUME (1U << 1) +#define REQ_OFF (1U << 0) +#define STATUS_PWRUP (1U << 4) +#define STATUS_PWRDOWN (1U << 0) +#define STATE_CA57_CPU (27U) +#define STATE_CA53_CPU (22U) +#define MODE_L2_DOWN (0x00000002U) +#define CPU_PWR_OFF (0x00000003U) +#define RCAR_PSTR_MASK (0x00000003U) +#define ST_ALL_STANDBY (0x00003333U) +/* Suspend to ram */ +#define DBSC4_REG_BASE (0xE6790000U) +#define DBSC4_REG_DBSYSCNT0 (DBSC4_REG_BASE + 0x0100U) +#define DBSC4_REG_DBACEN (DBSC4_REG_BASE + 0x0200U) +#define DBSC4_REG_DBCMD (DBSC4_REG_BASE + 0x0208U) +#define DBSC4_REG_DBRFEN (DBSC4_REG_BASE + 0x0204U) +#define DBSC4_REG_DBWAIT (DBSC4_REG_BASE + 0x0210U) +#define DBSC4_REG_DBCALCNF (DBSC4_REG_BASE + 0x0424U) +#define DBSC4_REG_DBDFIPMSTRCNF (DBSC4_REG_BASE + 0x0520U) +#define DBSC4_REG_DBPDLK0 (DBSC4_REG_BASE + 0x0620U) +#define DBSC4_REG_DBPDRGA0 (DBSC4_REG_BASE + 0x0624U) +#define DBSC4_REG_DBPDRGD0 (DBSC4_REG_BASE + 0x0628U) +#define DBSC4_REG_DBCAM0CTRL0 (DBSC4_REG_BASE + 0x0940U) +#define DBSC4_REG_DBCAM0STAT0 (DBSC4_REG_BASE + 0x0980U) +#define DBSC4_REG_DBCAM1STAT0 (DBSC4_REG_BASE + 0x0990U) +#define DBSC4_REG_DBCAM2STAT0 (DBSC4_REG_BASE + 0x09A0U) +#define DBSC4_REG_DBCAM3STAT0 (DBSC4_REG_BASE + 0x09B0U) +#define DBSC4_BIT_DBACEN_ACCEN ((uint32_t)(1U << 0)) +#define DBSC4_BIT_DBRFEN_ARFEN ((uint32_t)(1U << 0)) +#define DBSC4_BIT_DBCAMxSTAT0 (0x00000001U) +#define DBSC4_BIT_DBDFIPMSTRCNF_PMSTREN (0x00000001U) +#define DBSC4_SET_DBCMD_OPC_PRE (0x04000000U) +#define DBSC4_SET_DBCMD_OPC_SR (0x0A000000U) +#define DBSC4_SET_DBCMD_OPC_PD (0x08000000U) +#define DBSC4_SET_DBCMD_OPC_MRW (0x0E000000U) +#define DBSC4_SET_DBCMD_CH_ALL (0x00800000U) +#define DBSC4_SET_DBCMD_RANK_ALL (0x00040000U) +#define DBSC4_SET_DBCMD_ARG_ALL (0x00000010U) +#define DBSC4_SET_DBCMD_ARG_ENTER (0x00000000U) +#define DBSC4_SET_DBCMD_ARG_MRW_ODTC (0x00000B00U) +#define DBSC4_SET_DBSYSCNT0_WRITE_ENABLE (0x00001234U) +#define DBSC4_SET_DBSYSCNT0_WRITE_DISABLE (0x00000000U) +#define DBSC4_SET_DBPDLK0_PHY_ACCESS (0x0000A55AU) +#define DBSC4_SET_DBPDRGA0_ACIOCR0 (0x0000001AU) +#define DBSC4_SET_DBPDRGD0_ACIOCR0 (0x33C03C11U) +#define DBSC4_SET_DBPDRGA0_DXCCR (0x00000020U) +#define DBSC4_SET_DBPDRGD0_DXCCR (0x00181006U) +#define DBSC4_SET_DBPDRGA0_PGCR1 (0x00000003U) +#define DBSC4_SET_DBPDRGD0_PGCR1 (0x0380C600U) +#define DBSC4_SET_DBPDRGA0_ACIOCR1 (0x0000001BU) +#define DBSC4_SET_DBPDRGD0_ACIOCR1 (0xAAAAAAAAU) +#define DBSC4_SET_DBPDRGA0_ACIOCR3 (0x0000001DU) +#define DBSC4_SET_DBPDRGD0_ACIOCR3 (0xAAAAAAAAU) +#define DBSC4_SET_DBPDRGA0_ACIOCR5 (0x0000001FU) +#define DBSC4_SET_DBPDRGD0_ACIOCR5 (0x000000AAU) +#define DBSC4_SET_DBPDRGA0_DX0GCR2 (0x000000A2U) +#define DBSC4_SET_DBPDRGD0_DX0GCR2 (0xAAAA0000U) +#define DBSC4_SET_DBPDRGA0_DX1GCR2 (0x000000C2U) +#define DBSC4_SET_DBPDRGD0_DX1GCR2 (0xAAAA0000U) +#define DBSC4_SET_DBPDRGA0_DX2GCR2 (0x000000E2U) +#define DBSC4_SET_DBPDRGD0_DX2GCR2 (0xAAAA0000U) +#define DBSC4_SET_DBPDRGA0_DX3GCR2 (0x00000102U) +#define DBSC4_SET_DBPDRGD0_DX3GCR2 (0xAAAA0000U) +#define DBSC4_SET_DBPDRGA0_ZQCR (0x00000090U) +#define DBSC4_SET_DBPDRGD0_ZQCR_MD19_0 (0x04058904U) +#define DBSC4_SET_DBPDRGD0_ZQCR_MD19_1 (0x04058A04U) +#define DBSC4_SET_DBPDRGA0_DX0GCR0 (0x000000A0U) +#define DBSC4_SET_DBPDRGD0_DX0GCR0 (0x7C0002E5U) +#define DBSC4_SET_DBPDRGA0_DX1GCR0 (0x000000C0U) +#define DBSC4_SET_DBPDRGD0_DX1GCR0 (0x7C0002E5U) +#define DBSC4_SET_DBPDRGA0_DX2GCR0 (0x000000E0U) +#define DBSC4_SET_DBPDRGD0_DX2GCR0 (0x7C0002E5U) +#define DBSC4_SET_DBPDRGA0_DX3GCR0 (0x00000100U) +#define DBSC4_SET_DBPDRGD0_DX3GCR0 (0x7C0002E5U) +#define DBSC4_SET_DBPDRGA0_DX0GCR1 (0x000000A1U) +#define DBSC4_SET_DBPDRGD0_DX0GCR1 (0x55550000U) +#define DBSC4_SET_DBPDRGA0_DX1GCR1 (0x000000C1U) +#define DBSC4_SET_DBPDRGD0_DX1GCR1 (0x55550000U) +#define DBSC4_SET_DBPDRGA0_DX2GCR1 (0x000000E1U) +#define DBSC4_SET_DBPDRGD0_DX2GCR1 (0x55550000U) +#define DBSC4_SET_DBPDRGA0_DX3GCR1 (0x00000101U) +#define DBSC4_SET_DBPDRGD0_DX3GCR1 (0x55550000U) +#define DBSC4_SET_DBPDRGA0_DX0GCR3 (0x000000A3U) +#define DBSC4_SET_DBPDRGD0_DX0GCR3 (0x00008484U) +#define DBSC4_SET_DBPDRGA0_DX1GCR3 (0x000000C3U) +#define DBSC4_SET_DBPDRGD0_DX1GCR3 (0x00008484U) +#define DBSC4_SET_DBPDRGA0_DX2GCR3 (0x000000E3U) +#define DBSC4_SET_DBPDRGD0_DX2GCR3 (0x00008484U) +#define DBSC4_SET_DBPDRGA0_DX3GCR3 (0x00000103U) +#define DBSC4_SET_DBPDRGD0_DX3GCR3 (0x00008484U) +#define RST_BASE (0xE6160000U) +#define RST_MODEMR (RST_BASE + 0x0060U) +#define RST_MODEMR_BIT0 (0x00000001U) + +#define RCAR_CNTCR_OFF (0x00U) +#define RCAR_CNTCVL_OFF (0x08U) +#define RCAR_CNTCVU_OFF (0x0CU) +#define RCAR_CNTFID_OFF (0x20U) + +#define RCAR_CNTCR_EN ((uint32_t)1U << 0U) +#define RCAR_CNTCR_FCREQ(x) ((uint32_t)(x) << 8U) + +#if PMIC_ROHM_BD9571 +#define BIT_BKUP_CTRL_OUT ((uint8_t)(1U << 4)) +#define PMIC_BKUP_MODE_CNT (0x20U) +#define PMIC_QLLM_CNT (0x27U) +#define PMIC_RETRY_MAX (100U) +#endif /* PMIC_ROHM_BD9571 */ +#define SCTLR_EL3_M_BIT ((uint32_t)1U << 0) +#define RCAR_CA53CPU_NUM_MAX (4U) +#define RCAR_CA57CPU_NUM_MAX (4U) +#define IS_A53A57(c) ((c) == RCAR_CLUSTER_A53A57) +#define IS_CA57(c) ((c) == RCAR_CLUSTER_CA57) +#define IS_CA53(c) ((c) == RCAR_CLUSTER_CA53) + +#ifndef __ASSEMBLER__ +IMPORT_SYM(unsigned long, __system_ram_start__, SYSTEM_RAM_START); +IMPORT_SYM(unsigned long, __system_ram_end__, SYSTEM_RAM_END); +IMPORT_SYM(unsigned long, __SRAM_COPY_START__, SRAM_COPY_START); +#endif + +uint32_t rcar_pwrc_status(uint64_t mpidr) +{ + uint32_t ret = 0; + uint64_t cm, cpu; + uint32_t reg; + uint32_t c; + + rcar_lock_get(); + + c = rcar_pwrc_get_cluster(); + cm = mpidr & MPIDR_CLUSTER_MASK; + + if (!IS_A53A57(c) && cm != 0) { + ret = RCAR_INVALID; + goto done; + } + + reg = mmio_read_32(RCAR_PRR); + cpu = mpidr & MPIDR_CPU_MASK; + + if (IS_CA53(c)) + if (reg & (1 << (STATE_CA53_CPU + cpu))) + ret = RCAR_INVALID; + if (IS_CA57(c)) + if (reg & (1 << (STATE_CA57_CPU + cpu))) + ret = RCAR_INVALID; +done: + rcar_lock_release(); + + return ret; +} + +static void scu_power_up(uint64_t mpidr) +{ + uintptr_t reg_pwrsr, reg_cpumcr, reg_pwron, reg_pwrer; + uint32_t c, sysc_reg_bit; + + c = rcar_pwrc_get_mpidr_cluster(mpidr); + reg_cpumcr = IS_CA57(c) ? RCAR_CA57CPUCMCR : RCAR_CA53CPUCMCR; + sysc_reg_bit = IS_CA57(c) ? BIT_CA57_SCU : BIT_CA53_SCU; + reg_pwron = IS_CA57(c) ? RCAR_PWRONCR5 : RCAR_PWRONCR3; + reg_pwrer = IS_CA57(c) ? RCAR_PWRER5 : RCAR_PWRER3; + reg_pwrsr = IS_CA57(c) ? RCAR_PWRSR5 : RCAR_PWRSR3; + + if ((mmio_read_32(reg_pwrsr) & STATUS_PWRDOWN) == 0) + return; + + if (mmio_read_32(reg_cpumcr) != 0) + mmio_write_32(reg_cpumcr, 0); + + mmio_setbits_32(RCAR_SYSCIER, sysc_reg_bit); + mmio_setbits_32(RCAR_SYSCIMR, sysc_reg_bit); + + do { + while ((mmio_read_32(RCAR_SYSCSR) & REQ_RESUME) == 0) + ; + mmio_write_32(reg_pwron, 1); + } while (mmio_read_32(reg_pwrer) & 1); + + while ((mmio_read_32(RCAR_SYSCISR) & sysc_reg_bit) == 0) + ; + mmio_write_32(RCAR_SYSCISR, sysc_reg_bit); + while ((mmio_read_32(reg_pwrsr) & STATUS_PWRUP) == 0) + ; +} + +void rcar_pwrc_cpuon(uint64_t mpidr) +{ + uint32_t res_data, on_data; + uintptr_t res_reg, on_reg; + uint32_t limit, c; + uint64_t cpu; + + rcar_lock_get(); + + c = rcar_pwrc_get_mpidr_cluster(mpidr); + res_reg = IS_CA53(c) ? RCAR_CA53RESCNT : RCAR_CA57RESCNT; + on_reg = IS_CA53(c) ? RCAR_CA53WUPCR : RCAR_CA57WUPCR; + limit = IS_CA53(c) ? 0x5A5A0000 : 0xA5A50000; + + res_data = mmio_read_32(res_reg) | limit; + scu_power_up(mpidr); + cpu = mpidr & MPIDR_CPU_MASK; + on_data = 1 << cpu; + mmio_write_32(RCAR_CPGWPR, ~on_data); + mmio_write_32(on_reg, on_data); + mmio_write_32(res_reg, res_data & (~(1 << (3 - cpu)))); + + rcar_lock_release(); +} + +void rcar_pwrc_cpuoff(uint64_t mpidr) +{ + uint32_t c; + uintptr_t reg; + uint64_t cpu; + + rcar_lock_get(); + + cpu = mpidr & MPIDR_CPU_MASK; + c = rcar_pwrc_get_mpidr_cluster(mpidr); + reg = IS_CA53(c) ? RCAR_CA53CPU0CR : RCAR_CA57CPU0CR; + + if (read_mpidr_el1() != mpidr) + panic(); + + mmio_write_32(RCAR_CPGWPR, ~CPU_PWR_OFF); + mmio_write_32(reg + cpu * 0x0010, CPU_PWR_OFF); + + rcar_lock_release(); +} + +void rcar_pwrc_enable_interrupt_wakeup(uint64_t mpidr) +{ + uint32_t c, shift_irq, shift_fiq; + uintptr_t reg; + uint64_t cpu; + + rcar_lock_get(); + + cpu = mpidr & MPIDR_CPU_MASK; + c = rcar_pwrc_get_mpidr_cluster(mpidr); + reg = IS_CA53(c) ? RCAR_WUPMSKCA53 : RCAR_WUPMSKCA57; + + shift_irq = WUP_IRQ_SHIFT + cpu; + shift_fiq = WUP_FIQ_SHIFT + cpu; + + mmio_write_32(reg, ~((uint32_t) 1 << shift_irq) & + ~((uint32_t) 1 << shift_fiq)); + rcar_lock_release(); +} + +void rcar_pwrc_disable_interrupt_wakeup(uint64_t mpidr) +{ + uint32_t c, shift_irq, shift_fiq; + uintptr_t reg; + uint64_t cpu; + + rcar_lock_get(); + + cpu = mpidr & MPIDR_CPU_MASK; + c = rcar_pwrc_get_mpidr_cluster(mpidr); + reg = IS_CA53(c) ? RCAR_WUPMSKCA53 : RCAR_WUPMSKCA57; + + shift_irq = WUP_IRQ_SHIFT + cpu; + shift_fiq = WUP_FIQ_SHIFT + cpu; + + mmio_write_32(reg, ((uint32_t) 1 << shift_irq) | + ((uint32_t) 1 << shift_fiq)); + rcar_lock_release(); +} + +void rcar_pwrc_clusteroff(uint64_t mpidr) +{ + uint32_t c, product, cut, reg; + uintptr_t dst; + + rcar_lock_get(); + + reg = mmio_read_32(RCAR_PRR); + product = reg & PRR_PRODUCT_MASK; + cut = reg & PRR_CUT_MASK; + + c = rcar_pwrc_get_mpidr_cluster(mpidr); + dst = IS_CA53(c) ? RCAR_CA53CPUCMCR : RCAR_CA57CPUCMCR; + + if (product == PRR_PRODUCT_M3 && cut < PRR_PRODUCT_30) { + goto done; + } + + if (product == PRR_PRODUCT_H3 && cut <= PRR_PRODUCT_20) { + goto done; + } + + /* all of the CPUs in the cluster is in the CoreStandby mode */ + mmio_write_32(dst, MODE_L2_DOWN); +done: + rcar_lock_release(); +} + +static uint64_t rcar_pwrc_saved_cntpct_el0; +static uint32_t rcar_pwrc_saved_cntfid; + +#if RCAR_SYSTEM_SUSPEND +static void rcar_pwrc_save_timer_state(void) +{ + rcar_pwrc_saved_cntpct_el0 = read_cntpct_el0(); + + rcar_pwrc_saved_cntfid = + mmio_read_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTFID_OFF)); +} +#endif /* RCAR_SYSTEM_SUSPEND */ + +void rcar_pwrc_restore_timer_state(void) +{ + /* Stop timer before restoring counter value */ + mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCR_OFF), 0U); + + mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCVL_OFF), + (uint32_t)(rcar_pwrc_saved_cntpct_el0 & 0xFFFFFFFFU)); + mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCVU_OFF), + (uint32_t)(rcar_pwrc_saved_cntpct_el0 >> 32U)); + + mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTFID_OFF), + rcar_pwrc_saved_cntfid); + + /* Start generic timer back */ + write_cntfrq_el0((u_register_t)plat_get_syscnt_freq2()); + + mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCR_OFF), + (RCAR_CNTCR_FCREQ(0U) | RCAR_CNTCR_EN)); +} + +#if !PMIC_ROHM_BD9571 +void rcar_pwrc_system_reset(void) +{ + mmio_write_32(RCAR_SRESCR, 0x5AA50000U | BIT_SOFTRESET); +} +#endif /* PMIC_ROHM_BD9571 */ + +#define RST_CA53_CPU0_BARH (0xE6160080U) +#define RST_CA53_CPU0_BARL (0xE6160084U) +#define RST_CA57_CPU0_BARH (0xE61600C0U) +#define RST_CA57_CPU0_BARL (0xE61600C4U) + +void rcar_pwrc_setup(void) +{ + uintptr_t rst_barh; + uintptr_t rst_barl; + uint32_t i, j; + uint64_t reset = (uint64_t) (&plat_secondary_reset) & 0xFFFFFFFF; + + const uint32_t cluster[PLATFORM_CLUSTER_COUNT] = { + RCAR_CLUSTER_CA53, + RCAR_CLUSTER_CA57 + }; + const uintptr_t reg_barh[PLATFORM_CLUSTER_COUNT] = { + RST_CA53_CPU0_BARH, + RST_CA57_CPU0_BARH + }; + const uintptr_t reg_barl[PLATFORM_CLUSTER_COUNT] = { + RST_CA53_CPU0_BARL, + RST_CA57_CPU0_BARL + }; + + for (i = 0; i < PLATFORM_CLUSTER_COUNT; i++) { + rst_barh = reg_barh[i]; + rst_barl = reg_barl[i]; + for (j = 0; j < rcar_pwrc_get_cpu_num(cluster[i]); j++) { + mmio_write_32(rst_barh, 0); + mmio_write_32(rst_barl, (uint32_t) reset); + rst_barh += 0x10; + rst_barl += 0x10; + } + } + + rcar_lock_init(); +} + +#if RCAR_SYSTEM_SUSPEND +#define DBCAM_FLUSH(__bit) \ +do { \ + ; \ +} while (!(mmio_read_32(DBSC4_REG_DBCAM##__bit##STAT0) & DBSC4_BIT_DBCAMxSTAT0)) + + +static void __attribute__ ((section(".system_ram"))) + rcar_pwrc_set_self_refresh(void) +{ + uint32_t reg = mmio_read_32(RCAR_PRR); + uint32_t cut, product; + + product = reg & PRR_PRODUCT_MASK; + cut = reg & PRR_CUT_MASK; + + if (product == PRR_PRODUCT_M3 && cut < PRR_PRODUCT_30) { + goto self_refresh; + } + + if (product == PRR_PRODUCT_H3 && cut < PRR_PRODUCT_20) { + goto self_refresh; + } + + mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_ENABLE); + +self_refresh: + + /* DFI_PHYMSTR_ACK setting */ + mmio_write_32(DBSC4_REG_DBDFIPMSTRCNF, + mmio_read_32(DBSC4_REG_DBDFIPMSTRCNF) & + (~DBSC4_BIT_DBDFIPMSTRCNF_PMSTREN)); + + /* Set the Self-Refresh mode */ + mmio_write_32(DBSC4_REG_DBACEN, 0); + + if (product == PRR_PRODUCT_H3 && cut < PRR_PRODUCT_20) + rcar_micro_delay(100); + else if (product == PRR_PRODUCT_H3) { + mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1); + DBCAM_FLUSH(0); + DBCAM_FLUSH(1); + DBCAM_FLUSH(2); + DBCAM_FLUSH(3); + mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 0); + } else if (product == PRR_PRODUCT_M3) { + mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1); + DBCAM_FLUSH(0); + DBCAM_FLUSH(1); + mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 0); + } else { + mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1); + DBCAM_FLUSH(0); + mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 0); + } + + /* Set the SDRAM calibration configuration register */ + mmio_write_32(DBSC4_REG_DBCALCNF, 0); + + reg = DBSC4_SET_DBCMD_OPC_PRE | DBSC4_SET_DBCMD_CH_ALL | + DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ALL; + mmio_write_32(DBSC4_REG_DBCMD, reg); + while (mmio_read_32(DBSC4_REG_DBWAIT)) + ; + + /* Self-Refresh entry command */ + reg = DBSC4_SET_DBCMD_OPC_SR | DBSC4_SET_DBCMD_CH_ALL | + DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER; + mmio_write_32(DBSC4_REG_DBCMD, reg); + while (mmio_read_32(DBSC4_REG_DBWAIT)) + ; + + /* Mode Register Write command. (ODT disabled) */ + reg = DBSC4_SET_DBCMD_OPC_MRW | DBSC4_SET_DBCMD_CH_ALL | + DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_MRW_ODTC; + mmio_write_32(DBSC4_REG_DBCMD, reg); + while (mmio_read_32(DBSC4_REG_DBWAIT)) + ; + + /* Power Down entry command */ + reg = DBSC4_SET_DBCMD_OPC_PD | DBSC4_SET_DBCMD_CH_ALL | + DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER; + mmio_write_32(DBSC4_REG_DBCMD, reg); + while (mmio_read_32(DBSC4_REG_DBWAIT)) + ; + + /* Set the auto-refresh enable register */ + mmio_write_32(DBSC4_REG_DBRFEN, 0U); + rcar_micro_delay(1U); + + if (product == PRR_PRODUCT_M3 && cut < PRR_PRODUCT_30) + return; + + if (product == PRR_PRODUCT_H3 && cut < PRR_PRODUCT_20) + return; + + mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_DISABLE); +} + +static void __attribute__ ((section(".system_ram"))) +rcar_pwrc_set_self_refresh_e3(void) +{ + uint32_t ddr_md; + uint32_t reg; + + ddr_md = (mmio_read_32(RST_MODEMR) >> 19) & RST_MODEMR_BIT0; + + /* Write enable */ + mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_ENABLE); + mmio_write_32(DBSC4_REG_DBACEN, 0); + DBCAM_FLUSH(0); + + reg = DBSC4_SET_DBCMD_OPC_PRE | DBSC4_SET_DBCMD_CH_ALL | + DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ALL; + mmio_write_32(DBSC4_REG_DBCMD, reg); + while (mmio_read_32(DBSC4_REG_DBWAIT)) + ; + + reg = DBSC4_SET_DBCMD_OPC_SR | DBSC4_SET_DBCMD_CH_ALL | + DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER; + mmio_write_32(DBSC4_REG_DBCMD, reg); + while (mmio_read_32(DBSC4_REG_DBWAIT)) + ; + + /* + * Set the auto-refresh enable register + * Set the ARFEN bit to 0 in the DBRFEN + */ + mmio_write_32(DBSC4_REG_DBRFEN, 0); + + mmio_write_32(DBSC4_REG_DBPDLK0, DBSC4_SET_DBPDLK0_PHY_ACCESS); + + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR0); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR0); + + /* DDR_DXCCR */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DXCCR); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DXCCR); + + /* DDR_PGCR1 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_PGCR1); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_PGCR1); + + /* DDR_ACIOCR1 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR1); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR1); + + /* DDR_ACIOCR3 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR3); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR3); + + /* DDR_ACIOCR5 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR5); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR5); + + /* DDR_DX0GCR2 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR2); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR2); + + /* DDR_DX1GCR2 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR2); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR2); + + /* DDR_DX2GCR2 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR2); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR2); + + /* DDR_DX3GCR2 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR2); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR2); + + /* DDR_ZQCR */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ZQCR); + + mmio_write_32(DBSC4_REG_DBPDRGD0, ddr_md == 0 ? + DBSC4_SET_DBPDRGD0_ZQCR_MD19_0 : + DBSC4_SET_DBPDRGD0_ZQCR_MD19_1); + + /* DDR_DX0GCR0 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR0); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR0); + + /* DDR_DX1GCR0 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR0); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR0); + + /* DDR_DX2GCR0 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR0); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR0); + + /* DDR_DX3GCR0 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR0); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR0); + + /* DDR_DX0GCR1 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR1); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR1); + + /* DDR_DX1GCR1 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR1); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR1); + + /* DDR_DX2GCR1 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR1); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR1); + + /* DDR_DX3GCR1 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR1); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR1); + + /* DDR_DX0GCR3 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR3); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR3); + + /* DDR_DX1GCR3 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR3); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR3); + + /* DDR_DX2GCR3 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR3); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR3); + + /* DDR_DX3GCR3 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR3); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR3); + + /* Write disable */ + mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_DISABLE); +} + +void __attribute__ ((section(".system_ram"))) __attribute__ ((noinline)) +rcar_pwrc_go_suspend_to_ram(void) +{ +#if PMIC_ROHM_BD9571 + int32_t rc = -1, qllm = -1; + uint8_t mode; + uint32_t i; +#endif + uint32_t reg, product; + + reg = mmio_read_32(RCAR_PRR); + product = reg & PRR_PRODUCT_MASK; + + if (product != PRR_PRODUCT_E3) + rcar_pwrc_set_self_refresh(); + else + rcar_pwrc_set_self_refresh_e3(); + +#if PMIC_ROHM_BD9571 + /* Set QLLM Cnt Disable */ + for (i = 0; (i < PMIC_RETRY_MAX) && (qllm != 0); i++) + qllm = rcar_iic_dvfs_send(PMIC, PMIC_QLLM_CNT, 0); + + /* Set trigger of power down to PMIV */ + for (i = 0; (i < PMIC_RETRY_MAX) && (rc != 0) && (qllm == 0); i++) { + rc = rcar_iic_dvfs_receive(PMIC, PMIC_BKUP_MODE_CNT, &mode); + if (rc == 0) { + mode |= BIT_BKUP_CTRL_OUT; + rc = rcar_iic_dvfs_send(PMIC, PMIC_BKUP_MODE_CNT, mode); + } + } +#endif + wfi(); + + while (1) + ; +} + +void rcar_pwrc_set_suspend_to_ram(void) +{ + uintptr_t jump = (uintptr_t) &rcar_pwrc_go_suspend_to_ram; + uintptr_t stack = (uintptr_t) (DEVICE_SRAM_STACK_BASE + + DEVICE_SRAM_STACK_SIZE); + uint32_t sctlr; + + rcar_pwrc_save_timer_state(); + + /* disable MMU */ + sctlr = (uint32_t) read_sctlr_el3(); + sctlr &= (uint32_t) ~SCTLR_EL3_M_BIT; + write_sctlr_el3((uint64_t) sctlr); + + rcar_pwrc_switch_stack(jump, stack, NULL); +} + +void rcar_pwrc_init_suspend_to_ram(void) +{ +#if PMIC_ROHM_BD9571 + uint8_t mode; + + if (rcar_iic_dvfs_receive(PMIC, PMIC_BKUP_MODE_CNT, &mode)) + panic(); + + mode &= (uint8_t) (~BIT_BKUP_CTRL_OUT); + if (rcar_iic_dvfs_send(PMIC, PMIC_BKUP_MODE_CNT, mode)) + panic(); +#endif +} + +void rcar_pwrc_suspend_to_ram(void) +{ +#if RCAR_SYSTEM_RESET_KEEPON_DDR + int32_t error; + + error = rcar_iic_dvfs_send(PMIC, REG_KEEP10, 0); + if (error) { + ERROR("Failed send KEEP10 init ret=%d\n", error); + return; + } +#endif + rcar_pwrc_set_suspend_to_ram(); +} +#endif + +void rcar_pwrc_code_copy_to_system_ram(void) +{ + int ret __attribute__ ((unused)); /* in assert */ + uint32_t attr; + struct device_sram_t { + uintptr_t base; + size_t len; + } sram = { + .base = (uintptr_t) DEVICE_SRAM_BASE, + .len = DEVICE_SRAM_SIZE, + }; + struct ddr_code_t { + void *base; + size_t len; + } code = { + .base = (void *) SRAM_COPY_START, + .len = SYSTEM_RAM_END - SYSTEM_RAM_START, + }; + + attr = MT_MEMORY | MT_RW | MT_SECURE | MT_EXECUTE_NEVER; + ret = xlat_change_mem_attributes(sram.base, sram.len, attr); + assert(ret == 0); + + memcpy((void *)sram.base, code.base, code.len); + flush_dcache_range((uint64_t) sram.base, code.len); + + /* Invalidate instruction cache */ + plat_invalidate_icache(); + dsb(); + isb(); + + attr = MT_MEMORY | MT_RO | MT_SECURE | MT_EXECUTE; + ret = xlat_change_mem_attributes(sram.base, sram.len, attr); + assert(ret == 0); +} + +uint32_t rcar_pwrc_get_cluster(void) +{ + uint32_t reg; + + reg = mmio_read_32(RCAR_PRR); + + if (reg & (1U << (STATE_CA53_CPU + RCAR_CA53CPU_NUM_MAX))) + return RCAR_CLUSTER_CA57; + + if (reg & (1U << (STATE_CA57_CPU + RCAR_CA57CPU_NUM_MAX))) + return RCAR_CLUSTER_CA53; + + return RCAR_CLUSTER_A53A57; +} + +uint32_t rcar_pwrc_get_mpidr_cluster(uint64_t mpidr) +{ + uint32_t c = rcar_pwrc_get_cluster(); + + if (IS_A53A57(c)) { + if (mpidr & MPIDR_CLUSTER_MASK) + return RCAR_CLUSTER_CA53; + + return RCAR_CLUSTER_CA57; + } + + return c; +} + +#if RCAR_LSI == RCAR_D3 +uint32_t rcar_pwrc_get_cpu_num(uint32_t c) +{ + return 1; +} +#else +uint32_t rcar_pwrc_get_cpu_num(uint32_t c) +{ + uint32_t reg = mmio_read_32(RCAR_PRR); + uint32_t count = 0, i; + + if (IS_A53A57(c) || IS_CA53(c)) { + if (reg & (1 << (STATE_CA53_CPU + RCAR_CA53CPU_NUM_MAX))) + goto count_ca57; + + for (i = 0; i < RCAR_CA53CPU_NUM_MAX; i++) { + if (reg & (1 << (STATE_CA53_CPU + i))) + continue; + count++; + } + } + +count_ca57: + if (IS_A53A57(c) || IS_CA57(c)) { + if (reg & (1U << (STATE_CA57_CPU + RCAR_CA57CPU_NUM_MAX))) + goto done; + + for (i = 0; i < RCAR_CA57CPU_NUM_MAX; i++) { + if (reg & (1 << (STATE_CA57_CPU + i))) + continue; + count++; + } + } + +done: + return count; +} +#endif + +int32_t rcar_pwrc_cpu_on_check(uint64_t mpidr) +{ + uint64_t i; + uint64_t j; + uint64_t cpu_count; + uintptr_t reg_PSTR; + uint32_t status; + uint64_t my_cpu; + int32_t rtn; + uint32_t my_cluster_type; + const uint32_t cluster_type[PLATFORM_CLUSTER_COUNT] = { + RCAR_CLUSTER_CA53, + RCAR_CLUSTER_CA57 + }; + const uintptr_t registerPSTR[PLATFORM_CLUSTER_COUNT] = { + RCAR_CA53PSTR, + RCAR_CA57PSTR + }; + + my_cluster_type = rcar_pwrc_get_cluster(); + + rtn = 0; + my_cpu = mpidr & ((uint64_t)(MPIDR_CPU_MASK)); + for (i = 0U; i < ((uint64_t)(PLATFORM_CLUSTER_COUNT)); i++) { + cpu_count = rcar_pwrc_get_cpu_num(cluster_type[i]); + reg_PSTR = registerPSTR[i]; + for (j = 0U; j < cpu_count; j++) { + if ((my_cluster_type != cluster_type[i]) || (my_cpu != j)) { + status = mmio_read_32(reg_PSTR) >> (j * 4U); + if ((status & 0x00000003U) == 0U) { + rtn--; + } + } + } + } + + return rtn; +} diff --git a/drivers/renesas/common/pwrc/pwrc.h b/drivers/renesas/common/pwrc/pwrc.h new file mode 100644 index 000000000..f73099b0b --- /dev/null +++ b/drivers/renesas/common/pwrc/pwrc.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PWRC_H +#define PWRC_H + +#define PPOFFR_OFF 0x0 +#define PPONR_OFF 0x4 +#define PCOFFR_OFF 0x8 +#define PWKUPR_OFF 0xc +#define PSYSR_OFF 0x10 + +#define PWKUPR_WEN (1ull << 31) + +#define PSYSR_AFF_L2 (1U << 31) +#define PSYSR_AFF_L1 (1 << 30) +#define PSYSR_AFF_L0 (1 << 29) +#define PSYSR_WEN (1 << 28) +#define PSYSR_PC (1 << 27) +#define PSYSR_PP (1 << 26) + +#define PSYSR_WK_SHIFT (24) +#define PSYSR_WK_MASK (0x3) +#define PSYSR_WK(x) (((x) >> PSYSR_WK_SHIFT) & PSYSR_WK_MASK) + +#define WKUP_COLD 0x0 +#define WKUP_RESET 0x1 +#define WKUP_PPONR 0x2 +#define WKUP_GICREQ 0x3 + +#define RCAR_INVALID (0xffffffffU) +#define PSYSR_INVALID 0xffffffff + +#define RCAR_CLUSTER_A53A57 (0U) +#define RCAR_CLUSTER_CA53 (1U) +#define RCAR_CLUSTER_CA57 (2U) + +#ifndef __ASSEMBLER__ +void rcar_pwrc_disable_interrupt_wakeup(uint64_t mpidr); +void rcar_pwrc_enable_interrupt_wakeup(uint64_t mpidr); +void rcar_pwrc_clusteroff(uint64_t mpidr); +void rcar_pwrc_cpuoff(uint64_t mpidr); +void rcar_pwrc_cpuon(uint64_t mpidr); +int32_t rcar_pwrc_cpu_on_check(uint64_t mpidr); +void rcar_pwrc_setup(void); + +uint32_t rcar_pwrc_get_cpu_wkr(uint64_t mpidr); +uint32_t rcar_pwrc_status(uint64_t mpidr); +uint32_t rcar_pwrc_get_cluster(void); +uint32_t rcar_pwrc_get_mpidr_cluster(uint64_t mpidr); +uint32_t rcar_pwrc_get_cpu_num(uint32_t cluster_type); +void rcar_pwrc_restore_timer_state(void); +void plat_secondary_reset(void); + +void rcar_pwrc_code_copy_to_system_ram(void); + +#if !PMIC_ROHM_BD9571 +void rcar_pwrc_system_reset(void); +#endif + +#if RCAR_SYSTEM_SUSPEND +void rcar_pwrc_go_suspend_to_ram(void); +void rcar_pwrc_set_suspend_to_ram(void); +void rcar_pwrc_init_suspend_to_ram(void); +void rcar_pwrc_suspend_to_ram(void); +#endif + +extern uint32_t rcar_pwrc_switch_stack(uintptr_t jump, uintptr_t stack, + void *arg); +#endif + +#endif /* PWRC_H */ diff --git a/drivers/renesas/common/qos_reg.h b/drivers/renesas/common/qos_reg.h new file mode 100644 index 000000000..f2012fa45 --- /dev/null +++ b/drivers/renesas/common/qos_reg.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2017-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_REG_H +#define QOS_REG_H + +#define RCAR_QOS_NONE 3U +#define RCAR_QOS_TYPE_DEFAULT 0U + +#define RCAR_DRAM_SPLIT_LINEAR 0U +#define RCAR_DRAM_SPLIT_4CH 1U +#define RCAR_DRAM_SPLIT_2CH 2U +#define RCAR_DRAM_SPLIT_AUTO 3U +#define RST_BASE (0xE6160000U) +#define RST_MODEMR (RST_BASE + 0x0060U) + +#define DBSC_BASE 0xE6790000U +#define DBSC_DBSYSCNT0 (DBSC_BASE + 0x0100U) +#define DBSC_AXARB (DBSC_BASE + 0x0800U) +#define DBSC_DBCAM0CNF1 (DBSC_BASE + 0x0904U) +#define DBSC_DBCAM0CNF2 (DBSC_BASE + 0x0908U) +#define DBSC_DBCAM0CNF3 (DBSC_BASE + 0x090CU) +#define DBSC_DBSCHCNT0 (DBSC_BASE + 0x1000U) +#define DBSC_DBSCHCNT1 (DBSC_BASE + 0x1004U) +#define DBSC_DBSCHSZ0 (DBSC_BASE + 0x1010U) +#define DBSC_DBSCHRW0 (DBSC_BASE + 0x1020U) +#define DBSC_DBSCHRW1 (DBSC_BASE + 0x1024U) +#define DBSC_DBSCHQOS00 (DBSC_BASE + 0x1030U) +#define DBSC_DBSCHQOS01 (DBSC_BASE + 0x1034U) +#define DBSC_DBSCHQOS02 (DBSC_BASE + 0x1038U) +#define DBSC_DBSCHQOS03 (DBSC_BASE + 0x103CU) +#define DBSC_DBSCHQOS40 (DBSC_BASE + 0x1070U) +#define DBSC_DBSCHQOS41 (DBSC_BASE + 0x1074U) +#define DBSC_DBSCHQOS42 (DBSC_BASE + 0x1078U) +#define DBSC_DBSCHQOS43 (DBSC_BASE + 0x107CU) +#define DBSC_DBSCHQOS90 (DBSC_BASE + 0x10C0U) +#define DBSC_DBSCHQOS91 (DBSC_BASE + 0x10C4U) +#define DBSC_DBSCHQOS92 (DBSC_BASE + 0x10C8U) +#define DBSC_DBSCHQOS93 (DBSC_BASE + 0x10CCU) +#define DBSC_DBSCHQOS120 (DBSC_BASE + 0x10F0U) +#define DBSC_DBSCHQOS121 (DBSC_BASE + 0x10F4U) +#define DBSC_DBSCHQOS122 (DBSC_BASE + 0x10F8U) +#define DBSC_DBSCHQOS123 (DBSC_BASE + 0x10FCU) +#define DBSC_DBSCHQOS130 (DBSC_BASE + 0x1100U) +#define DBSC_DBSCHQOS131 (DBSC_BASE + 0x1104U) +#define DBSC_DBSCHQOS132 (DBSC_BASE + 0x1108U) +#define DBSC_DBSCHQOS133 (DBSC_BASE + 0x110CU) +#define DBSC_DBSCHQOS140 (DBSC_BASE + 0x1110U) +#define DBSC_DBSCHQOS141 (DBSC_BASE + 0x1114U) +#define DBSC_DBSCHQOS142 (DBSC_BASE + 0x1118U) +#define DBSC_DBSCHQOS143 (DBSC_BASE + 0x111CU) +#define DBSC_DBSCHQOS150 (DBSC_BASE + 0x1120U) +#define DBSC_DBSCHQOS151 (DBSC_BASE + 0x1124U) +#define DBSC_DBSCHQOS152 (DBSC_BASE + 0x1128U) +#define DBSC_DBSCHQOS153 (DBSC_BASE + 0x112CU) +#define DBSC_SCFCTST0 (DBSC_BASE + 0x1700U) +#define DBSC_SCFCTST1 (DBSC_BASE + 0x1708U) +#define DBSC_SCFCTST2 (DBSC_BASE + 0x170CU) + +#define AXI_BASE 0xE6784000U +#define AXI_ADSPLCR0 (AXI_BASE + 0x0008U) +#define AXI_ADSPLCR1 (AXI_BASE + 0x000CU) +#define AXI_ADSPLCR2 (AXI_BASE + 0x0010U) +#define AXI_ADSPLCR3 (AXI_BASE + 0x0014U) +#define AXI_MMCR (AXI_BASE + 0x0300U) +#define ADSPLCR0_ADRMODE_DEFAULT ((uint32_t)0U << 31U) +#define ADSPLCR0_ADRMODE_GEN2 ((uint32_t)1U << 31U) +#define ADSPLCR0_SPLITSEL(x) ((uint32_t)(x) << 16U) +#define ADSPLCR0_AREA(x) ((uint32_t)(x) << 8U) +#define ADSPLCR0_SWP 0x0CU + +#define AXI_TR3CR 0xE67D100CU +#define AXI_TR4CR 0xE67D1014U + +#define QOS_BASE0 0xE67E0000U +#define QOSBW_FIX_QOS_BANK0 (QOS_BASE0 + 0x0000U) +#define QOSBW_FIX_QOS_BANK1 (QOS_BASE0 + 0x1000U) +#define QOSBW_BE_QOS_BANK0 (QOS_BASE0 + 0x2000U) +#define QOSBW_BE_QOS_BANK1 (QOS_BASE0 + 0x3000U) +#define QOSCTRL_SL_INIT (QOS_BASE0 + 0x8000U) +#define QOSCTRL_REF_ARS (QOS_BASE0 + 0x8004U) +#define QOSCTRL_STATQC (QOS_BASE0 + 0x8008U) + +#define QOS_BASE1 0xE67F0000U +#define QOSCTRL_RAS (QOS_BASE1 + 0x0000U) +#define QOSCTRL_FIXTH (QOS_BASE1 + 0x0004U) +#define QOSCTRL_RAEN (QOS_BASE1 + 0x0018U) +#define QOSCTRL_REGGD (QOS_BASE1 + 0x0020U) +#define QOSCTRL_DANN (QOS_BASE1 + 0x0030U) +#define QOSCTRL_DANT (QOS_BASE1 + 0x0038U) +#define QOSCTRL_EC (QOS_BASE1 + 0x003CU) +#define QOSCTRL_EMS (QOS_BASE1 + 0x0040U) +#define QOSCTRL_FSS (QOS_BASE1 + 0x0048U) +#define QOSCTRL_INSFC (QOS_BASE1 + 0x0050U) +#define QOSCTRL_BERR (QOS_BASE1 + 0x0054U) +#define QOSCTRL_EARLYR (QOS_BASE1 + 0x0060U) +#define QOSCTRL_RACNT0 (QOS_BASE1 + 0x0080U) +#define QOSCTRL_STATGEN0 (QOS_BASE1 + 0x0088U) + +#define GPU_ACT_GRD 0xFD820808U +#define GPU_ACT0 0xFD820800U +#define GPU_ACT1 0xFD821800U +#define GPU_ACT2 0xFD822800U +#define GPU_ACT3 0xFD823800U +#define GPU_ACT4 0xFD824800U +#define GPU_ACT5 0xFD825800U +#define GPU_ACT6 0xFD826800U +#define GPU_ACT7 0xFD827800U + +#define RT_ACT0 0xFFC50800U +#define RT_ACT1 0xFFC51800U + +#define CPU_ACT0 0xF1300800U +#define CPU_ACT1 0xF1340800U +#define CPU_ACT2 0xF1380800U +#define CPU_ACT3 0xF13C0800U + +#define RCAR_REWT_TRAINING_DISABLE 0U +#define RCAR_REWT_TRAINING_ENABLE 1U + +#define QOSWT_FIX_WTQOS_BANK0 (QOSBW_FIX_QOS_BANK0 + 0x0800U) +#define QOSWT_FIX_WTQOS_BANK1 (QOSBW_FIX_QOS_BANK1 + 0x0800U) +#define QOSWT_BE_WTQOS_BANK0 (QOSBW_BE_QOS_BANK0 + 0x0800U) +#define QOSWT_BE_WTQOS_BANK1 (QOSBW_BE_QOS_BANK1 + 0x0800U) +#define QOSWT_WTEN (QOS_BASE0 + 0x8030U) +#define QOSWT_WTREF (QOS_BASE0 + 0x8034U) +#define QOSWT_WTSET0 (QOS_BASE0 + 0x8038U) +#define QOSWT_WTSET1 (QOS_BASE0 + 0x803CU) + +#endif /* QOS_REG_H */ diff --git a/drivers/renesas/common/rom/rom_api.c b/drivers/renesas/common/rom/rom_api.c new file mode 100644 index 000000000..fda28150e --- /dev/null +++ b/drivers/renesas/common/rom/rom_api.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include <lib/mmio.h> + +#include "rcar_def.h" +#include "rom_api.h" + +typedef uint32_t(*rom_secure_boot_api_f) (uint32_t *key, uint32_t *cert, + rom_read_flash_f pFuncReadFlash); + +typedef uint32_t(*rom_get_lcs_api_f) (uint32_t *lcs); + +#define OLD_API_TABLE1 (0U) /* H3 Ver.1.0/Ver.1.1 */ +#define OLD_API_TABLE2 (1U) /* H3 Ver.2.0 */ +#define OLD_API_TABLE3 (2U) /* M3 Ver.1.0 */ +#define NEW_API_TABLE (3U) /* H3 Ver.3.0, M3 Ver.1.1 or later, M3N, E3, D3, V3M WS2.0 */ +#define NEW_API_TABLE2 (4U) /* V3M WS1.0 */ +#define API_TABLE_MAX (5U) /* table max */ + /* Later than H3 Ver.2.0 */ + +static uint32_t get_table_index(void) +{ + uint32_t product; + uint32_t cut_ver; + uint32_t index; + + product = mmio_read_32(RCAR_PRR) & PRR_PRODUCT_MASK; + cut_ver = mmio_read_32(RCAR_PRR) & PRR_CUT_MASK; + + switch (product) { + case PRR_PRODUCT_H3: + if (cut_ver == PRR_PRODUCT_10) + index = OLD_API_TABLE1; + else if (cut_ver == PRR_PRODUCT_11) + index = OLD_API_TABLE1; + else if (cut_ver == PRR_PRODUCT_20) + index = OLD_API_TABLE2; + else + /* Later than H3 Ver.2.0 */ + index = NEW_API_TABLE; + break; + case PRR_PRODUCT_M3: + if (cut_ver == PRR_PRODUCT_10) + index = OLD_API_TABLE3; + else + /* M3 Ver.1.1 or later */ + index = NEW_API_TABLE; + break; + case PRR_PRODUCT_V3M: + if (cut_ver == PRR_PRODUCT_10) + /* V3M WS1.0 */ + index = NEW_API_TABLE2; + else + /* V3M WS2.0 or later */ + index = NEW_API_TABLE; + break; + default: + index = NEW_API_TABLE; + break; + } + + return index; +} + +uint32_t rcar_rom_secure_boot_api(uint32_t *key, uint32_t *cert, + rom_read_flash_f read_flash) +{ + static const uintptr_t rom_api_table[API_TABLE_MAX] = { + 0xEB10DD64U, /* H3 Ver.1.0/Ver.1.1 */ + 0xEB116ED4U, /* H3 Ver.2.0 */ + 0xEB1102FCU, /* M3 Ver.1.0 */ + 0xEB100180U, /* H3 Ver.3.0, M3 Ver.1.1 or later, M3N, E3, D3, V3M WS2.0 */ + 0xEB110128U, /* V3M WS1.0 */ + }; + rom_secure_boot_api_f secure_boot; + uint32_t index; + + index = get_table_index(); + secure_boot = (rom_secure_boot_api_f) rom_api_table[index]; + + return secure_boot(key, cert, read_flash); +} + +uint32_t rcar_rom_get_lcs(uint32_t *lcs) +{ + static const uintptr_t rom_get_lcs_table[API_TABLE_MAX] = { + 0xEB10DFE0U, /* H3 Ver.1.0/Ver.1.1 */ + 0xEB117150U, /* H3 Ver.2.0 */ + 0xEB110578U, /* M3 Ver.1.0 */ + 0xEB10018CU, /* H3 Ver.3.0, M3 Ver.1.1 or later, M3N, E3, D3, V3M WS2.0 */ + 0xEB1103A4U, /* V3M WS1.0 */ + }; + rom_get_lcs_api_f get_lcs; + uint32_t index; + + index = get_table_index(); + get_lcs = (rom_get_lcs_api_f) rom_get_lcs_table[index]; + + return get_lcs(lcs); +} diff --git a/drivers/renesas/common/rom/rom_api.h b/drivers/renesas/common/rom/rom_api.h new file mode 100644 index 000000000..1d5b03d7f --- /dev/null +++ b/drivers/renesas/common/rom/rom_api.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ROM_API_H +#define ROM_API_H + +#include <stdint.h> + +#define SBROM_OK (0x00000000U) +#define SBROM_ILLEGAL_INPUT_PARAM_ERR (0x0B000001U) +#define SBROM_ILLEGAL_OEM_HASH_VALUE_ERR (0x0B000008U) +#define SBROM_ILLEGAL_LCS_FOR_OPERATION_ERR (0x0B000010U) +#define SBROM_HASH_NOT_PROGRAMMED_ERR (0x0B000100U) +#define SBROM_PUB_KEY_HASH_VALIDATION_FAILURE (0xF1000006U) +#define SBROM_RSA_SIG_VERIFICATION_FAILED (0xF1000007U) + +#define LCS_CM (0x0U) +#define LCS_DM (0x1U) +#define LCS_SD (0x3U) +#define LCS_SE (0x5U) +#define LCS_FA (0x7U) + +typedef uint32_t(*rom_read_flash_f) (uint64_t src, uint8_t *dst, uint32_t len); +uint32_t rcar_rom_secure_boot_api(uint32_t *key, uint32_t *cert, + rom_read_flash_f f); +uint32_t rcar_rom_get_lcs(uint32_t *lcs); + +#endif /* ROM_API_H */ diff --git a/drivers/renesas/common/rpc/rpc_driver.c b/drivers/renesas/common/rpc/rpc_driver.c new file mode 100644 index 000000000..63de5b851 --- /dev/null +++ b/drivers/renesas/common/rpc/rpc_driver.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> +#include <string.h> + +#include <common/debug.h> +#include <lib/mmio.h> + +#include "cpg_registers.h" +#include "rcar_def.h" +#include "rcar_private.h" +#include "rpc_registers.h" + +#define MSTPSR9_RPC_BIT (0x00020000U) +#define RPC_CMNCR_MD_BIT (0x80000000U) +#define RPC_PHYCNT_CAL BIT(31) +#define RPC_PHYCNT_STRTIM_M3V1 (0x6 << 15UL) +#define RPC_PHYCNT_STRTIM (0x7 << 15UL) + +static void rpc_enable(void) +{ + /* Enable clock supply to RPC. */ + mstpcr_write(CPG_SMSTPCR9, CPG_MSTPSR9, MSTPSR9_RPC_BIT); +} + +static void rpc_setup(void) +{ + uint32_t product, cut, reg, phy_strtim; + + if (mmio_read_32(RPC_CMNCR) & RPC_CMNCR_MD_BIT) + mmio_clrbits_32(RPC_CMNCR, RPC_CMNCR_MD_BIT); + + product = mmio_read_32(RCAR_PRR) & PRR_PRODUCT_MASK; + cut = mmio_read_32(RCAR_PRR) & PRR_CUT_MASK; + + if ((product == PRR_PRODUCT_M3) && (cut < PRR_PRODUCT_30)) + phy_strtim = RPC_PHYCNT_STRTIM_M3V1; + else + phy_strtim = RPC_PHYCNT_STRTIM; + + reg = mmio_read_32(RPC_PHYCNT); + reg &= ~RPC_PHYCNT_STRTIM; + reg |= phy_strtim; + mmio_write_32(RPC_PHYCNT, reg); + reg |= RPC_PHYCNT_CAL; + mmio_write_32(RPC_PHYCNT, reg); +} + +void rcar_rpc_init(void) +{ + rpc_enable(); + rpc_setup(); +} diff --git a/drivers/renesas/common/rpc/rpc_registers.h b/drivers/renesas/common/rpc/rpc_registers.h new file mode 100644 index 000000000..79aea8599 --- /dev/null +++ b/drivers/renesas/common/rpc/rpc_registers.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RPC_REGISTERS_H +#define RPC_REGISTERS_H + +#define RPC_BASE (0xEE200000U) +#define RPC_CMNCR (RPC_BASE + 0x0000U) +#define RPC_SSLDR (RPC_BASE + 0x0004U) +#define RPC_DRCR (RPC_BASE + 0x000CU) +#define RPC_DRCMR (RPC_BASE + 0x0010U) +#define RPC_DRENR (RPC_BASE + 0x001CU) +#define RPC_SMCR (RPC_BASE + 0x0020U) +#define RPC_SMCMR (RPC_BASE + 0x0024U) +#define RPC_SMENR (RPC_BASE + 0x0030U) +#define RPC_CMNSR (RPC_BASE + 0x0048U) +#define RPC_DRDMCR (RPC_BASE + 0x0058U) +#define RPC_DRDRENR (RPC_BASE + 0x005CU) +#define RPC_PHYCNT (RPC_BASE + 0x007CU) +#define RPC_PHYINT (RPC_BASE + 0x0088U) + +#endif /* RPC_REGISTERS_H */ diff --git a/drivers/renesas/common/scif/scif.S b/drivers/renesas/common/scif/scif.S new file mode 100644 index 000000000..beb8dd838 --- /dev/null +++ b/drivers/renesas/common/scif/scif.S @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <console_macros.S> +#include <drivers/renesas/rcar/console/console.h> + +#define SCIF_INTERNAL_CLK 0 +#define SCIF_EXTARNAL_CLK 1 +#define SCIF_CLK SCIF_INTERNAL_CLK + +/* product register */ +#define PRR (0xFFF00044) +#define PRR_PRODUCT_MASK (0x00007F00) +#define PRR_CUT_MASK (0x000000FF) +#define PRR_PRODUCT_H3_VER_10 (0x00004F00) +#define PRR_PRODUCT_E3 (0x00005700) +#define PRR_PRODUCT_D3 (0x00005800) + +/* module stop */ +#define CPG_BASE (0xE6150000) +#define CPG_SMSTPCR2 (0x0138) +#define CPG_SMSTPCR3 (0x013C) +#define CPG_MSTPSR2 (0x0040) +#define CPG_MSTPSR3 (0x0048) +#define MSTP207 (1 << 7) +#define MSTP310 (1 << 10) +#define CPG_CPGWPR (0x0900) + +/* scif */ +#define SCIF0_BASE (0xE6E60000) +#define SCIF2_BASE (0xE6E88000) +#define SCIF_SCSMR (0x00) +#define SCIF_SCBRR (0x04) +#define SCIF_SCSCR (0x08) +#define SCIF_SCFTDR (0x0C) +#define SCIF_SCFSR (0x10) +#define SCIF_SCFRDR (0x14) +#define SCIF_SCFCR (0x18) +#define SCIF_SCFDR (0x1C) +#define SCIF_SCSPTR (0x20) +#define SCIF_SCLSR (0x24) +#define SCIF_DL (0x30) +#define SCIF_CKS (0x34) + +#if RCAR_LSI == RCAR_V3M +#define SCIF_BASE SCIF0_BASE +#define CPG_SMSTPCR CPG_SMSTPCR2 +#define CPG_MSTPSR CPG_MSTPSR2 +#define MSTP MSTP207 +#else +#define SCIF_BASE SCIF2_BASE +#define CPG_SMSTPCR CPG_SMSTPCR3 +#define CPG_MSTPSR CPG_MSTPSR3 +#define MSTP MSTP310 +#endif + +/* mode pin */ +#define RST_MODEMR (0xE6160060) +#define MODEMR_MD12 (0x00001000) + +#define SCSMR_CA_MASK (1 << 7) +#define SCSMR_CA_ASYNC (0x0000) +#define SCSMR_CHR_MASK (1 << 6) +#define SCSMR_CHR_8 (0x0000) +#define SCSMR_PE_MASK (1 << 5) +#define SCSMR_PE_DIS (0x0000) +#define SCSMR_STOP_MASK (1 << 3) +#define SCSMR_STOP_1 (0x0000) +#define SCSMR_CKS_MASK (3 << 0) +#define SCSMR_CKS_DIV1 (0x0000) +#define SCSMR_INIT_DATA (SCSMR_CA_ASYNC + \ + SCSMR_CHR_8 + \ + SCSMR_PE_DIS + \ + SCSMR_STOP_1 + \ + SCSMR_CKS_DIV1) +#define SCBRR_115200BPS (17) +#define SCBRR_115200BPSON (16) +#define SCBRR_115200BPS_E3_SSCG (15) +#define SCBRR_230400BPS (8) + +#define SCSCR_TE_MASK (1 << 5) +#define SCSCR_TE_DIS (0x0000) +#define SCSCR_TE_EN (0x0020) +#define SCSCR_RE_MASK (1 << 4) +#define SCSCR_RE_DIS (0x0000) +#define SCSCR_RE_EN (0x0010) +#define SCSCR_CKE_MASK (3 << 0) +#define SCSCR_CKE_INT (0x0000) +#define SCSCR_CKE_BRG (0x0002) +#if SCIF_CLK == SCIF_EXTARNAL_CLK +#define SCSCR_CKE_INT_CLK (SCSCR_CKE_BRG) +#else +#define SCFSR_TEND_MASK (1 << 6) +#define SCFSR_TEND_TRANS_END (0x0040) +#define SCSCR_CKE_INT_CLK (SCSCR_CKE_INT) +#endif +#define SCFSR_INIT_DATA (0x0000) +#define SCFCR_TTRG_MASK (3 << 4) +#define SCFCR_TTRG_8 (0x0000) +#define SCFCR_TTRG_0 (0x0030) +#define SCFCR_TFRST_MASK (1 << 2) +#define SCFCR_TFRST_DIS (0x0000) +#define SCFCR_TFRST_EN (0x0004) +#define SCFCR_RFRS_MASK (1 << 1) +#define SCFCR_RFRS_DIS (0x0000) +#define SCFCR_RFRS_EN (0x0002) +#define SCFCR_INIT_DATA (SCFCR_TTRG_8) +#define SCFDR_T_MASK (0x1f << 8) +#define DL_INIT_DATA (8) +#define CKS_CKS_DIV_MASK (1 << 15) +#define CKS_CKS_DIV_CLK (0x0000) +#define CKS_XIN_MASK (1 << 14) +#define CKS_XIN_SCIF_CLK (0x0000) +#define CKS_INIT_DATA (CKS_CKS_DIV_CLK + CKS_XIN_SCIF_CLK) + + .globl console_rcar_register + .globl console_rcar_init + .globl console_rcar_putc + .globl console_rcar_flush + + /* + * ----------------------------------------------- + * int console_rcar_register( + * uintptr_t base, uint32_t clk, uint32_t baud, + * console_t *console) + * Function to initialize and register a new rcar + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * In: x0 - UART register base address + * w1 - UART clock in Hz + * w2 - Baud rate + * x3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : x0, x1, x2, x6, x7, x14 + * ----------------------------------------------- + */ +func console_rcar_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_BASE] + + bl console_rcar_init + + mov x0, x6 + mov x30, x7 + finish_console_register rcar, putc=1, getc=0, flush=1 + +register_fail: + ret x7 +endfunc console_rcar_register + + /* + * int console_rcar_init(unsigned long base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_rcar_register + * and crash reporting. + * In: x0 - console base address + * w1 - Uart clock in Hz + * w2 - Baud rate + * Out: return 1 on success + * Clobber list : x1, x2 + */ +func console_rcar_init + ldr x0, =CPG_BASE + ldr w1, [x0, #CPG_SMSTPCR] + and w1, w1, #~MSTP + mvn w2, w1 + str w2, [x0, #CPG_CPGWPR] + str w1, [x0, #CPG_SMSTPCR] +5: + ldr w1, [x0, #CPG_MSTPSR] + and w1, w1, #MSTP + cbnz w1, 5b + + ldr x0, =SCIF_BASE + /* Clear bits TE and RE in SCSCR to 0 */ + mov w1, #(SCSCR_TE_DIS + SCSCR_RE_DIS) + strh w1, [x0, #SCIF_SCSCR] + /* Set bits TFRST and RFRST in SCFCR to 1 */ + ldrh w1, [x0, #SCIF_SCFCR] + orr w1, w1, #(SCFCR_TFRST_EN + SCFCR_RFRS_EN) + strh w1, [x0, #SCIF_SCFCR] + /* + * Read flags of ER, DR, BRK, and RDF in SCFSR and those of TO and ORER + * in SCLSR, then clear them to 0 + */ + mov w1, #SCFSR_INIT_DATA + strh w1, [x0, #SCIF_SCFSR] + mov w1, #0 + strh w1, [x0, #SCIF_SCLSR] + /* Set bits CKE[1:0] in SCSCR */ + ldrh w1, [x0, #SCIF_SCSCR] + and w1, w1, #~SCSCR_CKE_MASK + mov w2, #SCSCR_CKE_INT_CLK + orr w1, w1, w2 + strh w1, [x0, #SCIF_SCSCR] + /* Set data transfer format in SCSMR */ + mov w1, #SCSMR_INIT_DATA + strh w1, [x0, #SCIF_SCSMR] + /* Set value in SCBRR */ +#if SCIF_CLK == SCIF_INTERNAL_CLK + ldr x1, =PRR + ldr w1, [x1] + and w1, w1, #(PRR_PRODUCT_MASK | PRR_CUT_MASK) + mov w2, #PRR_PRODUCT_H3_VER_10 + cmp w1, w2 + beq 3f + and w1, w1, #PRR_PRODUCT_MASK + mov w2, #PRR_PRODUCT_D3 + cmp w1, w2 + beq 4f + and w1, w1, #PRR_PRODUCT_MASK + mov w2, #PRR_PRODUCT_E3 + cmp w1, w2 + bne 5f + + ldr x1, =RST_MODEMR + ldr w1, [x1] + and w1, w1, #MODEMR_MD12 + mov w2, #MODEMR_MD12 + cmp w1, w2 + bne 5f + + mov w1, #SCBRR_115200BPS_E3_SSCG + b 2f +5: + mov w1, #SCBRR_115200BPS + b 2f +4: + mov w1, #SCBRR_115200BPSON + b 2f +3: + mov w1, #SCBRR_230400BPS +2: + strb w1, [x0, SCIF_SCBRR] +#else + mov w1, #DL_INIT_DATA + strh w1, [x0, #SCIF_DL] + mov w1, #CKS_INIT_DATA + strh w1, [x0, #SCIF_CKS] +#endif + /* 1-bit interval elapsed */ + mov w1, #100 +1: + subs w1, w1, #1 + cbnz w1, 1b + /* + * Set bits RTRG[1:0], TTRG[1:0], and MCE in SCFCR + * Clear bits FRST and RFRST to 0 + */ + mov w1, #SCFCR_INIT_DATA + strh w1, [x0, #SCIF_SCFCR] + /* Set bits TE and RE in SCSCR to 1 */ + ldrh w1, [x0, #SCIF_SCSCR] + orr w1, w1, #(SCSCR_TE_EN + SCSCR_RE_EN) + strh w1, [x0, #SCIF_SCSCR] + mov x0, #1 + + ret +endfunc console_rcar_init + + /* + * int console_rcar_putc(int c, unsigned int base_addr) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : w0 - character to be printed + * x1 - pointer to console_t structure + * Out : return -1 on error else return character. + * Clobber list : x2 + */ +func console_rcar_putc + ldr x1, =SCIF_BASE + cmp w0, #0xA + /* Prepend '\r' to '\n' */ + bne 2f +1: + /* Check if the transmit FIFO is full */ + ldrh w2, [x1, #SCIF_SCFDR] + ubfx w2, w2, #8, #5 + cmp w2, #16 + bcs 1b + mov w2, #0x0D + strb w2, [x1, #SCIF_SCFTDR] +2: + /* Check if the transmit FIFO is full */ + ldrh w2, [x1, #SCIF_SCFDR] + ubfx w2, w2, #8, #5 + cmp w2, #16 + bcs 2b + strb w0, [x1, #SCIF_SCFTDR] + + /* Clear TEND flag */ + ldrh w2, [x1, #SCIF_SCFSR] + and w2, w2, #~SCFSR_TEND_MASK + strh w2, [x1, #SCIF_SCFSR] + + ret +endfunc console_rcar_putc + + /* + * void console_rcar_flush(void) + * Function to force a write of all buffered + * data that hasn't been output. It returns void + * Clobber list : x0, x1 + */ +func console_rcar_flush + ldr x0, =SCIF_BASE +1: + /* Check TEND flag */ + ldrh w1, [x0, #SCIF_SCFSR] + and w1, w1, #SCFSR_TEND_MASK + cmp w1, #SCFSR_TEND_TRANS_END + bne 1b + + ldr x0, =SCIF_BASE + ldrh w1, [x0, #SCIF_SCSCR] + and w1, w1, #~(SCSCR_TE_EN + SCSCR_RE_EN) + strh w1, [x0, #SCIF_SCSCR] + + ret +endfunc console_rcar_flush diff --git a/drivers/renesas/common/watchdog/swdt.c b/drivers/renesas/common/watchdog/swdt.c new file mode 100644 index 000000000..05987ab70 --- /dev/null +++ b/drivers/renesas/common/watchdog/swdt.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/arm/gicv2.h> +#include <lib/mmio.h> + +#include "rcar_def.h" + +extern void gicd_set_icenabler(uintptr_t base, unsigned int id); + +#define RST_BASE (0xE6160000U) +#define RST_WDTRSTCR (RST_BASE + 0x0054U) +#define SWDT_BASE (0xE6030000U) +#define SWDT_WTCNT (SWDT_BASE + 0x0000U) +#define SWDT_WTCSRA (SWDT_BASE + 0x0004U) +#define SWDT_WTCSRB (SWDT_BASE + 0x0008U) +#define SWDT_GICD_BASE (0xF1010000U) +#define SWDT_GICC_BASE (0xF1020000U) +#define SWDT_GICD_CTLR (SWDT_GICD_BASE + 0x0000U) +#define SWDT_GICD_IGROUPR (SWDT_GICD_BASE + 0x0080U) +#define SWDT_GICD_ISPRIORITYR (SWDT_GICD_BASE + 0x0400U) +#define SWDT_GICC_CTLR (SWDT_GICC_BASE + 0x0000U) +#define SWDT_GICC_PMR (SWDT_GICC_BASE + 0x0004U) +#define SWDT_GICD_ITARGETSR (SWDT_GICD_BASE + 0x0800U) +#define IGROUPR_NUM (16U) +#define ISPRIORITY_NUM (128U) +#define ITARGET_MASK (0x03U) + +#define WDTRSTCR_UPPER_BYTE (0xA55A0000U) +#define WTCSRA_UPPER_BYTE (0xA5A5A500U) +#define WTCSRB_UPPER_BYTE (0xA5A5A500U) +#define WTCNT_UPPER_BYTE (0x5A5A0000U) +#define WTCNT_RESET_VALUE (0xF488U) +#define WTCSRA_BIT_CKS (0x0007U) +#define WTCSRB_BIT_CKS (0x003FU) +#define SWDT_RSTMSK (1U << 1U) +#define WTCSRA_WOVFE (1U << 3U) +#define WTCSRA_WRFLG (1U << 5U) +#define SWDT_ENABLE (1U << 7U) + +#define WDTRSTCR_MASK_ALL (0x0000FFFFU) +#define WTCSRA_MASK_ALL (0x000000FFU) +#define WTCNT_INIT_DATA (WTCNT_UPPER_BYTE + WTCNT_RESET_VALUE) +#define WTCSRA_INIT_DATA (WTCSRA_UPPER_BYTE + 0x0FU) +#define WTCSRB_INIT_DATA (WTCSRB_UPPER_BYTE + 0x21U) + +#if RCAR_LSI == RCAR_D3 +#define WTCNT_COUNT_8p13k (0x10000U - 40760U) +#else +#define WTCNT_COUNT_8p13k (0x10000U - 40687U) +#endif +#define WTCNT_COUNT_8p13k_H3VER10 (0x10000U - 20343U) +#define WTCNT_COUNT_8p22k (0x10000U - 41115U) +#define WTCNT_COUNT_7p81k (0x10000U - 39062U) +#define WTCSRA_CKS_DIV16 (0x00000002U) + +static void swdt_disable(void) +{ + uint32_t rmsk; + + rmsk = mmio_read_32(RST_WDTRSTCR) & WDTRSTCR_MASK_ALL; + rmsk |= SWDT_RSTMSK; + mmio_write_32(RST_WDTRSTCR, WDTRSTCR_UPPER_BYTE | rmsk); + + mmio_write_32(SWDT_WTCNT, WTCNT_INIT_DATA); + mmio_write_32(SWDT_WTCSRA, WTCSRA_INIT_DATA); + mmio_write_32(SWDT_WTCSRB, WTCSRB_INIT_DATA); + + /* Set the interrupt clear enable register */ + gicd_set_icenabler(RCAR_GICD_BASE, ARM_IRQ_SEC_WDT); +} + +void rcar_swdt_init(void) +{ + uint32_t rmsk, sr; +#if (RCAR_LSI != RCAR_E3) + uint32_t reg, val, product_cut, chk_data; + + reg = mmio_read_32(RCAR_PRR); + product_cut = reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK); + + reg = mmio_read_32(RCAR_MODEMR); + chk_data = reg & CHECK_MD13_MD14; +#endif + /* stop watchdog */ + if (mmio_read_32(SWDT_WTCSRA) & SWDT_ENABLE) + mmio_write_32(SWDT_WTCSRA, WTCSRA_UPPER_BYTE); + + mmio_write_32(SWDT_WTCSRA, WTCSRA_UPPER_BYTE | + WTCSRA_WOVFE | WTCSRA_CKS_DIV16); + +#if (RCAR_LSI == RCAR_E3) + mmio_write_32(SWDT_WTCNT, WTCNT_UPPER_BYTE | WTCNT_COUNT_7p81k); +#else + val = WTCNT_UPPER_BYTE; + + switch (chk_data) { + case MD14_MD13_TYPE_0: + case MD14_MD13_TYPE_2: + val |= WTCNT_COUNT_8p13k; + break; + case MD14_MD13_TYPE_1: + val |= WTCNT_COUNT_8p22k; + break; + case MD14_MD13_TYPE_3: + val |= product_cut == (PRR_PRODUCT_H3 | PRR_PRODUCT_10) ? + WTCNT_COUNT_8p13k_H3VER10 : WTCNT_COUNT_8p13k; + break; + default: + ERROR("MODEMR ERROR value = %x\n", chk_data); + panic(); + break; + } + + mmio_write_32(SWDT_WTCNT, val); +#endif + rmsk = mmio_read_32(RST_WDTRSTCR) & WDTRSTCR_MASK_ALL; + rmsk |= SWDT_RSTMSK | WDTRSTCR_UPPER_BYTE; + mmio_write_32(RST_WDTRSTCR, rmsk); + + while ((mmio_read_8(SWDT_WTCSRA) & WTCSRA_WRFLG) != 0U) + ; + + /* Start the System WatchDog Timer */ + sr = mmio_read_32(SWDT_WTCSRA) & WTCSRA_MASK_ALL; + mmio_write_32(SWDT_WTCSRA, (WTCSRA_UPPER_BYTE | sr | SWDT_ENABLE)); +} + +void rcar_swdt_release(void) +{ + uintptr_t itarget = SWDT_GICD_ITARGETSR + + (ARM_IRQ_SEC_WDT & ~ITARGET_MASK); + uint32_t i; + + /* Disable FIQ interrupt */ + write_daifset(DAIF_FIQ_BIT); + /* FIQ interrupts are not taken to EL3 */ + write_scr_el3(read_scr_el3() & ~SCR_FIQ_BIT); + + swdt_disable(); + gicv2_cpuif_disable(); + + for (i = 0; i < IGROUPR_NUM; i++) + mmio_write_32(SWDT_GICD_IGROUPR + i * 4, 0U); + + for (i = 0; i < ISPRIORITY_NUM; i++) + mmio_write_32(SWDT_GICD_ISPRIORITYR + i * 4, 0U); + + mmio_write_32(itarget, 0U); + mmio_write_32(SWDT_GICD_CTLR, 0U); + mmio_write_32(SWDT_GICC_CTLR, 0U); + mmio_write_32(SWDT_GICC_PMR, 0U); +} + +void rcar_swdt_exec(uint64_t p) +{ + gicv2_end_of_interrupt(ARM_IRQ_SEC_WDT); + rcar_swdt_release(); + ERROR("\n"); + ERROR("System WDT overflow, occurred address is %p\n", (void *)p); + panic(); +} |