Unverified Commit a51443fa authored by Soby Mathew's avatar Soby Mathew Committed by GitHub
Browse files

Merge pull request #1582 from ldts/rcar_gen3/upstream

rcar_gen3: initial support
parents 0059be2d 84433c50
...@@ -11,6 +11,10 @@ build/ ...@@ -11,6 +11,10 @@ build/
# Ignore build products from tools # Ignore build products from tools
tools/**/*.o tools/**/*.o
tools/renesas/rcar_layout_create/*.bin
tools/renesas/rcar_layout_create/*.srec
tools/renesas/rcar_layout_create/*.map
tools/renesas/rcar_layout_create/*.elf
tools/fiptool/fiptool tools/fiptool/fiptool
tools/fiptool/fiptool.exe tools/fiptool/fiptool.exe
tools/cert_create/src/*.o tools/cert_create/src/*.o
......
Description
===========
"R-Car" is the nickname for Renesas' system-on-chip (SoC) family for
car information systems designed for the next-generation of automotive
computing for the age of autonomous vehicles.
The scalable R-Car hardware platform and flexible software platform
cover the full product range, from the premium class to the entry
level. Plug-ins are available for multiple open-source software tools.
Renesas R-Car Gen3 evaluation boards:
-------------------------------------
+------------+-----------------+-----------------------------+
| | Standard | Low Cost Boards (LCB) |
+============+=================+=============================+
| R-Car H3 | - Salvator-X | - R-Car Starter Kit Premier |
| | - Salvator-XS | |
+------------+-----------------+-----------------------------+
| R-Car M3-W | - Salvator-X | |
| | - Salvator-XS | - R-Car Starter Kit Pro |
+------------+-----------------+-----------------------------+
| R-Car M3-N | - Salvator-X | |
| | - Salvator-XS | |
+------------+-----------------+-----------------------------+
| R-Car V3M | - Eagle | - Starter Kit |
+------------+-----------------+-----------------------------+
| R-Car V3H | - Condor | - Starter Kit |
+------------+-----------------+-----------------------------+
| R-Car D3 | - Draak | |
+------------+-----------------+-----------------------------+
`boards info <https://elinux.org/R-Car>`__
The current TF-A port has been tested on the R-Car H3 Salvator-X
Soc_id r8a7795 revision ES1.1 (uses a Secure Payload Dispatcher)
::
ARM CA57 (ARMv8) 1.5 GHz quad core, with NEON/VFPv4, L1$ I/D
48K/32K, L2$ 2MB
ARM CA53 (ARMv8) 1.2 GHz quad core, with NEON/VFPv4, L1$ I/D 32K/32K,
L2$ 512K
Memory controller for LPDDR4-3200 4GB in 2 channels, each 64-bit wide
Two- and three-dimensional graphics engines,
Video processing units,
3 channels Display Output,
6 channels Video Input,
SD card host interface,
USB3.0 and USB2.0 interfaces,
CAN interfaces
Ethernet AVB
PCI Express Interfaces
Memories
INTERNAL 384KB SYSTEM RAM
DDR 4 GB LPDDR4
HYPERFLASH 64 MB HYPER FLASH (512 MBITS, 160 MHZ, 320 MBYTES/S)
QSPI FLASH 16MB QSPI (128 MBITS,80 MHZ,80 MBYTES/S)1 HEADER QSPI
MODULE
EMMC 32 GB EMMC (HS400 240 MBYTES/S)
MICROSD-CARD SLOT (SDR104 100 MBYTES/S)
Overview
--------
On the rcar-gen3 the BOOTROM starts the cpu at EL3; for this port BL2
will therefore be entered at this exception level (the Renesas' ATF
reference tree [1] resets into EL1 before entering BL2 - see its
bl2.ld.S)
BL2 initializes DDR (and on some platforms i2c to interface to the
PMIC) before determining the boot reason (cold or warm).
During suspend all CPUs are switched off and the DDR is put in backup
mode (some kind of self-refresh mode). This means that BL2 is always
entered in a cold boot scenario.
Once BL2 boots, it determines the boot reason, writes it to shared
memory (BOOT_KIND_BASE) together with the BL31 parameters
(PARAMS_BASE) and jumps to BL31.
To all effects, BL31 is as if it is being entered in reset mode since
it still needs to initialize the rest of the cores; this is the reason
behind using direct shared memory access to BOOT_KIND_BASE _and_
PARAMS_BASE instead of using registers to get to those locations (see
el3_common_macros.S and bl31_entrypoint.S for the RESET_TO_BL31 use
case).
Depending on the boot reason BL31 initializes the rest of the cores:
in case of suspend, it uses a MBOX memory region to recover the
program counters.
[1] https://github.com/renesas-rcar/arm-trusted-firmware
How to build
============
The TF-A build options depend on the target board so you will have to
refer to those specific instructions. What follows is customized to
the H3 SiP Salvator-X development system used in this port.
Build Tested:
-------------
RCAR_OPT="LSI=H3 RCAR_DRAM_SPLIT=1 RCAR_LOSSY_ENABLE=1"
MBEDTLS_DIR=$mbedtls_src
$ MBEDTLS_DIR=$mbedtls_src_tree make clean bl2 bl31 rcar_layout_tool \
PLAT=rcar ${RCAR_OPT} SPD=opteed
System Tested:
--------------------
* mbed_tls:
git@github.com:ARMmbed/mbedtls.git [devel]
commit 552754a6ee82bab25d1bdf28c8261a4518e65e4d
Merge: 68dbc94 f34a4c1
Author: Simon Butcher <simon.butcher@arm.com>
Date: Thu Aug 30 00:57:28 2018 +0100
* optee_os:
https://github.com/BayLibre/optee_os
Until it gets merged into OP-TEE, the port requires Renesas'
Trusted Environment with a modification to support power
management.
commit 80105192cba9e704ebe8df7ab84095edc2922f84
Author: Jorge Ramirez-Ortiz <jramirez@baylibre.com>
Date: Thu Aug 30 16:49:49 2018 +0200
plat-rcar: cpu-suspend: handle the power level
Signed-off-by: Jorge Ramirez-Ortiz <jramirez@baylibre.com>
* u-boot:
The port has beent tested using mainline uboot.
commit 4cdeda511f8037015b568396e6dcc3d8fb41e8c0
Author: Fabio Estevam <festevam@gmail.com>
Date: Tue Sep 4 10:23:12 2018 -0300
* linux:
The port has beent tested using mainline kernel.
commit 7876320f88802b22d4e2daf7eb027dd14175a0f8
Author: Linus Torvalds <torvalds@linux-foundation.org>
Date: Sun Sep 16 11:52:37 2018 -0700
Linux 4.19-rc4
TF-A Build Procedure
--------------------
- Fetch all the above 4 repositories.
- Prepare the AARCH64 toolchain.
- Build u-boot using r8a7795_salvator-x_defconfig.
Result: u-boot-elf.srec
.. code:: bash
make CROSS_COMPILE=aarch64-linux-gnu-
r8a7795_salvator-x_defconfig
make CROSS_COMPILE=aarch64-linux-gnu-
- Build atf
Result: bootparam_sa0.srec, cert_header_sa6.srec, bl2.srec, bl31.srec
.. code:: bash
RCAR_OPT="LSI=H3 RCAR_DRAM_SPLIT=1 RCAR_LOSSY_ENABLE=1"
MBEDTLS_DIR=$mbedtls_src_tree make clean bl2 bl31 rcar \
PLAT=rcar ${RCAR_OPT} SPD=opteed
- Build optee-os
Result: tee.srec
.. code:: bash
make -j8 PLATFORM="rcar" CFG_ARM64_core=y
Install Procedure
-----------------
- Boot the board in Mini-monitor mode and enable access to the
Hyperflash.
- Use the XSL2 Mini-monitor utility to accept all the SREC ascii
transfers over serial.
Boot trace
==========
Notice that BL31 traces are not accessible via the console and that in
order to verbose the BL2 output you will have to compile TF-A with
LOG_LEVEL=50 and DEBUG=1
::
Initial Program Loader(CA57) Rev.1.0.22
NOTICE: BL2: PRR is R-Car H3 Ver.1.1
NOTICE: BL2: Board is Salvator-X Rev.1.0
NOTICE: BL2: Boot device is HyperFlash(80MHz)
NOTICE: BL2: LCM state is CM
NOTICE: AVS setting succeeded. DVFS_SetVID=0x53
NOTICE: BL2: DDR1600(rev.0.33)NOTICE: [COLD_BOOT]NOTICE: ..0
NOTICE: BL2: DRAM Split is 4ch
NOTICE: BL2: QoS is default setting(rev.0.37)
NOTICE: BL2: Lossy Decomp areas
NOTICE: Entry 0: DCMPAREACRAx:0x80000540 DCMPAREACRBx:0x570
NOTICE: Entry 1: DCMPAREACRAx:0x40000000 DCMPAREACRBx:0x0
NOTICE: Entry 2: DCMPAREACRAx:0x20000000 DCMPAREACRBx:0x0
NOTICE: BL2: v2.0(release):v2.0-rc0-32-gbcda69a
NOTICE: BL2: Built : 16:41:23, Oct 2 2018
NOTICE: BL2: Normal boot
INFO: BL2: Doing platform setup
INFO: BL2: Loading image id 3
NOTICE: BL2: dst=0xe6322000 src=0x8180000 len=512(0x200)
NOTICE: BL2: dst=0x43f00000 src=0x8180400 len=6144(0x1800)
WARNING: r-car ignoring the BL31 size from certificate,using
RCAR_TRUSTED_SRAM_SIZE instead
INFO: Loading image id=3 at address 0x44000000
NOTICE: rcar_file_len: len: 0x0003e000
NOTICE: BL2: dst=0x44000000 src=0x81c0000 len=253952(0x3e000)
INFO: Image id=3 loaded: 0x44000000 - 0x4403e000
INFO: BL2: Loading image id 4
INFO: Loading image id=4 at address 0x44100000
NOTICE: rcar_file_len: len: 0x00100000
NOTICE: BL2: dst=0x44100000 src=0x8200000 len=1048576(0x100000)
INFO: Image id=4 loaded: 0x44100000 - 0x44200000
INFO: BL2: Loading image id 5
INFO: Loading image id=5 at address 0x50000000
NOTICE: rcar_file_len: len: 0x00100000
NOTICE: BL2: dst=0x50000000 src=0x8640000 len=1048576(0x100000)
INFO: Image id=5 loaded: 0x50000000 - 0x50100000
NOTICE: BL2: Booting BL31
INFO: Entry point address = 0x44000000
INFO: SPSR = 0x3cd
VERBOSE: Argument #0 = 0xe6325578
VERBOSE: Argument #1 = 0x0
VERBOSE: Argument #2 = 0x0
VERBOSE: Argument #3 = 0x0
VERBOSE: Argument #4 = 0x0
VERBOSE: Argument #5 = 0x0
VERBOSE: Argument #6 = 0x0
VERBOSE: Argument #7 = 0x0
U-Boot 2018.09-rc3-00028-g3711616 (Sep 27 2018 - 18:50:24 +0200)
CPU: Renesas Electronics R8A7795 rev 1.1
Model: Renesas Salvator-X board based on r8a7795 ES2.0+
DRAM: 3.5 GiB
Flash: 64 MiB
MMC: sd@ee100000: 0, sd@ee140000: 1, sd@ee160000: 2
Loading Environment from MMC... OK
In: serial@e6e88000
Out: serial@e6e88000
Err: serial@e6e88000
Net: eth0: ethernet@e6800000
Hit any key to stop autoboot: 0
=>
/*
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights
* reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <debug.h>
#include <mmio.h>
#include <platform.h>
#include <platform_def.h>
#include <stddef.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 MFISSOFTMDR (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_el1(read_sctlr_el1() & ~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_el1(read_sctlr_el1() | SCTLR_C_BIT);
#endif
#endif
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(MFISSOFTMDR) & 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
}
/*
* Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <mmio.h>
#include <debug.h>
#include <utils_def.h>
#include "cpg_registers.h"
#include "avs_driver.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 */
#define PMIC_W_SLAVE_ADDRESS (0x60U) /* ROHM BD9571 slave address + (W) */
#define PMIC_R_SLAVE_ADDRESS (0x61U) /* ROHM BD9571 slave address + (R) */
#define PMIC_DVFS_SETVID (0x54U) /* ROHM BD9571 DVFS SetVID register */
#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, RHOM 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("AVS number of eFuse is out "
"of a range. number=%u\n",
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("Loss of arbitration is detected. "
"AVS status=%d Retry=%u\n", 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("Non-acknowledge is detected. "
"AVS status=%d Retry=%u\n", 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) */
/*
* 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__ */
/*
* Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights
* reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#include <iic_dvfs.h>
#include "board.h"
#include "utils_def.h"
#ifndef BOARD_DEFAULT
#if (RCAR_LSI == RCAR_E3)
#define BOARD_DEFAULT (BOARD_EBISU << BOARD_CODE_SHIFT)
#else
#define BOARD_DEFAULT (BOARD_SALVATOR_X << BOARD_CODE_SHIFT)
#endif
#endif
#define BOARD_CODE_MASK (0xF8)
#define BOARD_REV_MASK (0x07)
#define BOARD_CODE_SHIFT (0x03)
#define BOARD_ID_UNKNOWN (0xFF)
#define SXS_ID { 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
#define SX_ID { 0x10U, 0x11U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
#define SKP_ID { 0x10U, 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
#define SK_ID { 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
#define EB4_ID { 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
#define EB_ID { 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
#define KK_ID { 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
const char *g_board_tbl[] = {
[BOARD_STARTER_KIT_PRE] = "Starter Kit Premier",
[BOARD_STARTER_KIT] = "Starter Kit",
[BOARD_SALVATOR_XS] = "Salvator-XS",
[BOARD_SALVATOR_X] = "Salvator-X",
[BOARD_EBISU_4D] = "Ebisu-4D",
[BOARD_KRIEK] = "Kriek",
[BOARD_EBISU] = "Ebisu",
[BOARD_UNKNOWN] = "unknown"
};
int32_t rcar_get_board_type(uint32_t *type, uint32_t *rev)
{
int32_t ret = 0;
const uint8_t board_tbl[][8] = {
[BOARD_STARTER_KIT_PRE] = SKP_ID,
[BOARD_SALVATOR_XS] = SXS_ID,
[BOARD_STARTER_KIT] = SK_ID,
[BOARD_SALVATOR_X] = SX_ID,
[BOARD_EBISU_4D] = EB4_ID,
[BOARD_EBISU] = EB_ID,
[BOARD_KRIEK] = KK_ID,
};
static uint8_t board_id = BOARD_ID_UNKNOWN;
if (board_id != BOARD_ID_UNKNOWN)
goto get_type;
#if PMIC_ROHM_BD9571
/* Board ID detection from EEPROM */
ret = rcar_iic_dvfs_receive(EEPROM, BOARD_ID, &board_id);
if (ret) {
board_id = BOARD_ID_UNKNOWN;
goto get_type;
}
if (board_id == BOARD_ID_UNKNOWN)
board_id = BOARD_DEFAULT;
#else
board_id = BOARD_DEFAULT;
#endif
get_type:
*type = ((uint32_t) board_id & BOARD_CODE_MASK) >> BOARD_CODE_SHIFT;
if (*type >= ARRAY_SIZE(board_tbl)) {
/* no revision information, set Rev0.0. */
*rev = 0;
return ret;
}
*rev = board_tbl[*type][(uint8_t) (board_id & BOARD_REV_MASK)];
return ret;
}
/*
* Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights
* reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef BOARD_H_
#define BOARD_H_
#define BOARD_SALVATOR_X (0x00)
#define BOARD_KRIEK (0x01)
#define BOARD_STARTER_KIT (0x02)
#define BOARD_SALVATOR_XS (0x04)
#define BOARD_EBISU (0x08)
#define BOARD_STARTER_KIT_PRE (0x0B)
#define BOARD_EBISU_4D (0x0DU)
#define BOARD_UNKNOWN (BOARD_EBISU_4D + 1U)
#define BOARD_REV_UNKNOWN (0xFF)
extern const char *g_board_tbl[];
/************************************************************************
* Revisions are expressed in 8 bits.
* The upper 4 bits are major version.
* The lower 4 bits are minor version.
************************************************************************/
#define GET_BOARD_MAJOR(a) ((uint32_t)(a) >> 0x4)
#define GET_BOARD_MINOR(a) ((uint32_t)(a) & 0xF)
#define GET_BOARD_NAME(a) (g_board_tbl[(a)])
int32_t rcar_get_board_type(uint32_t *type, uint32_t *rev);
#endif
/*
* Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <mmio.h>
#include "rcar_private.h"
void
#if IMAGE_BL31
__attribute__ ((section(".system_ram")))
#endif
cpg_write(uintptr_t regadr, uint32_t regval)
{
uint32_t value = (regval);
mmio_write_32((uintptr_t) RCAR_CPGWPR, ~value);
mmio_write_32(regadr, value);
}
void
#if IMAGE_BL31
__attribute__ ((section(".system_ram")))
#endif
mstpcr_write(uint32_t mstpcr, uint32_t mstpsr, uint32_t target_bit)
{
uint32_t reg;
reg = mmio_read_32(mstpcr);
reg &= ~target_bit;
cpg_write(mstpcr, reg);
while ((mmio_read_32(mstpsr) & target_bit) != 0U) {
}
}
/*
* Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <asm_macros.S>
.globl console_init
.globl console_putc
.globl console_uninit
.globl console_core_init
.globl console_core_putc
.globl console_core_getc
.globl console_flush
.extern rcar_log_init
.extern rcar_set_log_data
/* -----------------------------------------------
* int console_core_init(unsigned long base_addr,
* unsigned int uart_clk, unsigned int baud_rate)
* Function to initialize the log area. This
* function will be accessed by console_init and
* crash reporting.
* Return 1 on SUCCESS, 0 on error
* In: x0 - Not used
* w1 - Not used
* w2 - Not used
* -----------------------------------------------
*/
func console_core_init
b rcar_log_init
endfunc console_core_init
func console_init
b console_core_init
endfunc console_init
/* --------------------------------------------------------
* int console_core_putc(int c, unsigned long base_addr)
* Function to output a character over the log area.
* Return 1 on SUCCESS, 0 on error
* In : w0 - Not used
* x1 - Not used
* --------------------------------------------------------
*/
func console_core_putc
b rcar_set_log_data
endfunc console_core_putc
func console_putc
b console_core_putc
endfunc console_putc
/* ---------------------------------------------
* int console_core_getc(unsigned long base_addr)
* Function to get a character from the console.
* It returns the character grabbed on success
* or -1 on error.
* In : x0 - console base address
* Clobber list : x0, x1
* ---------------------------------------------
*/
func console_core_getc
ret
endfunc console_core_getc
/* -----------------------------------------------
* void console_uninit(void)
* Function to finish the use of console driver.
* -----------------------------------------------
*/
func console_uninit
ret
endfunc console_uninit
/* ---------------------------------------------
* int console_flush(void)
* Function to force a write of all buffered
* data that hasn't been output. It returns 0
* upon successful completion, otherwise it
* returns -1.
* Clobber list : x0, x1
* ---------------------------------------------
*/
func console_flush
mov w0, #0
ret
endfunc console_flush
/*
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <debug.h>
#include <stdarg.h>
#include <stdint.h>
#include <arch_helpers.h>
#include <platform_def.h>
#include <bakery_lock.h>
#include "rcar_def.h"
#include "rcar_private.h"
#include "rcar_printf.h"
#define INDEX_TIMER_COUNT (4U)
extern RCAR_INSTANTIATE_LOCK typedef struct log_head {
uint8_t head[4];
uint32_t index;
uint32_t size;
uint8_t res[4];
} 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)
{
static const uint8_t const_header[] = "TLOG";
logmap_t *t_log;
int16_t init_flag = 0;
t_log = (logmap_t *) RCAR_BL31_LOG_BASE;
if (memcmp
((const void *)t_log->header.head, (const void *)const_header,
sizeof(t_log->header.head)) != 0) {
/*
* 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) {
(void)memset((void *)t_log->log_data, 0,
(size_t) RCAR_BL31_LOG_MAX);
(void)memcpy((void *)t_log->header.head,
(const void *)const_header,
sizeof(t_log->header.head));
t_log->header.index = 0U;
t_log->header.size = 0U;
#ifndef IMAGE_BL2
rcar_stack_generic_timer[INDEX_TIMER_COUNT] = 0U;
#endif
}
rcar_lock_init();
return 1;
}
/*
* Copyright (c) 2015-2017, 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);
#if IMAGE_BL31
extern uint64_t rcar_stack_generic_timer[5];
#endif
#endif
/*
* Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <mmio.h>
#define SCLK 8 /* GP_6_8 */
#define SSTBZ 3 /* GP_2_3 */
#define MOSI 7 /* GP_6_7 */
#define CPLD_ADDR_RESET 0x80 /* RW */
/* LSI Multiplexed Pin Setting Mask Register */
#define PFC_PMMR 0xE6060000
/* General output registers */
#define GPIO_OUTDT2 0xE6052008
#define GPIO_OUTDT6 0xE6055408
/* General input/output switching registers */
#define GPIO_INOUTSEL2 0xE6052004
#define GPIO_INOUTSEL6 0xE6055404
/* GPIO/perihperal function select */
#define PFC_GPSR2 0xE6060108
#define PFC_GPSR6 0xE6060118
static void gpio_set_value(uint32_t addr, uint8_t gpio, uint32_t val)
{
uint32_t reg;
reg = mmio_read_32(addr);
if (val)
reg |= (1 << gpio);
else
reg &= ~(1 << gpio);
mmio_write_32(addr, reg);
}
static void gpio_direction_output(uint32_t addr, uint8_t gpio)
{
uint32_t reg;
reg = mmio_read_32(addr);
reg |= (1 << gpio);
mmio_write_32(addr, reg);
}
static void gpio_pfc(uint32_t addr, uint8_t gpio)
{
uint32_t reg;
reg = mmio_read_32(addr);
reg &= ~(1 << gpio);
mmio_write_32(PFC_PMMR, ~reg);
mmio_write_32(addr, reg);
}
static void cpld_write(uint8_t addr, uint32_t data)
{
int i;
for (i = 0; i < 32; i++) {
/* MSB first */
gpio_set_value(GPIO_OUTDT6, MOSI, data & (1 << 31));
gpio_set_value(GPIO_OUTDT6, SCLK, 1);
data <<= 1;
gpio_set_value(GPIO_OUTDT6, SCLK, 0);
}
for (i = 0; i < 8; i++) {
/* MSB first */
gpio_set_value(GPIO_OUTDT6, MOSI, addr & 0x80);
gpio_set_value(GPIO_OUTDT6, SCLK, 1);
addr <<= 1;
gpio_set_value(GPIO_OUTDT6, SCLK, 0);
}
/* WRITE */
gpio_set_value(GPIO_OUTDT6, MOSI, 1);
gpio_set_value(GPIO_OUTDT2, SSTBZ, 0);
gpio_set_value(GPIO_OUTDT6, SCLK, 1);
gpio_set_value(GPIO_OUTDT6, SCLK, 0);
gpio_set_value(GPIO_OUTDT2, SSTBZ, 1);
}
static void cpld_init(void)
{
gpio_pfc(PFC_GPSR6, SCLK);
gpio_pfc(PFC_GPSR2, SSTBZ);
gpio_pfc(PFC_GPSR6, MOSI);
gpio_set_value(GPIO_OUTDT6, SCLK, 0);
gpio_set_value(GPIO_OUTDT2, SSTBZ, 1);
gpio_set_value(GPIO_OUTDT6, MOSI, 0);
gpio_direction_output(GPIO_INOUTSEL6, SCLK);
gpio_direction_output(GPIO_INOUTSEL2, SSTBZ);
gpio_direction_output(GPIO_INOUTSEL6, MOSI);
}
void rcar_cpld_reset_cpu(void)
{
cpld_init();
cpld_write(CPLD_ADDR_RESET, 1);
}
/*
* Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <asm_macros.S>
#include "micro_delay.h"
#define CPG_BASE (0xE6150000)
#define CPG_SMSTPCR1 (0x0134)
#define CPG_CPGWPR (0x0900)
/* Module bit for TMU ch3-5 */
#define MSTPCR1_TMU1 (1 << 24)
#define TMU3_BASE (0xE6FC0000)
#define TMU_TSTR (0x0004)
#define TMU_TCOR (0x0008)
#define TMU_TCNT (0x000C)
#define TMU_TCR (0x0010)
/* Start bit for TMU ch3 */
#define TSTR1_TMU3 (1 << 0)
#define MIDR_CA57 (0x0D07 << MIDR_PN_SHIFT)
#define MIDR_CA53 (0x0D03 << MIDR_PN_SHIFT)
.globl rcar_micro_delay
#if (TMU3_MEASUREMENT == 1)
.globl tmu3_init
.globl tmu3_start
.globl tmu3_stop
.globl tcnt3_snapshot
#endif
/* Aligned with the cache line */
.align 6
func rcar_micro_delay
cbz x0, micro_delay_e
mrs x1, midr_el1
and x1, x1, #MIDR_PN_MASK << MIDR_PN_SHIFT
mov w2, #MIDR_CA53
cmp w1, w2
b.eq micro_delay_ca53
b micro_delay_ca57
micro_delay_e:
ret
endfunc rcar_micro_delay
func micro_delay_ca57
ca57_loop_1:
mov x1, #185
ca57_loop_2:
subs x1, x1, #1
b.ne ca57_loop_2
subs x0, x0, #1
b.ne ca57_loop_1
ret
endfunc micro_delay_ca57
func micro_delay_ca53
ca53_loop_1:
mov x1, #134
ca53_loop_2:
subs x1, x1, #1
b.ne ca53_loop_2
subs x0, x0, #1
b.ne ca53_loop_1
ret
endfunc micro_delay_ca53
#if (TMU3_MEASUREMENT == 1)
func tmu3_init
ldr x2, =CPG_BASE
ldr w0, [x2, #CPG_SMSTPCR1]
ldr w1, [x2, #CPG_MSTPSR1]
ldr w2, #MSTPCR1_TMU1
bl mstpcr_write
ret
endfunc tmu3_init
func tmu3_start
ldr x0, =TMU3_BASE
mov w1, #0xFFFFFFFF
str w1, [x0, TMU_TCNT]
ldr x0, =TMU3_BASE
ldrb w1, [x0, TMU_TSTR]
orr w1, w1, #TSTR1_TMU3
strb w1, [x0, TMU_TSTR]
ret
endfunc tmu3_start
func tcnt3_snapshot
ldr x0, =TMU3_BASE
ldr w0, [x0, TMU_TCNT]
ret
endfunc tcnt3_snapshot
func tmu3_stop
ldr x0, =TMU3_BASE
ldrb w1, [x0, TMU_TSTR]
and w1, w1, #~TSTR1_TMU3
strb w1, [x0, TMU_TSTR]
ret
endfunc tmu3_stop
#endif
/*
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MICRO_DELAY_H__
#define MICRO_DELAY_H__
#define TMU3_MEASUREMENT (0)
#ifndef __ASSEMBLY__
#include "stdint.h"
void rcar_micro_delay(uint32_t count_us);
#if (TMU3_MEASUREMENT == 1)
void tmu3_start(void);
void tmu3_init(void);
void tmu3_stop(void);
uint32_t tcnt3_snapshot(void);
#endif
#endif
#endif
/*
* Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#include <arch_helpers.h>
#include <string.h>
#include <mmio.h>
#include "rcar_def.h"
#include "cpg_registers.h"
#include "debug.h"
#include "rcar_private.h"
/* DMA CHANNEL setting (0/16/32) */
#define DMA_CH 0
#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 - source address invalid (0x%x), "
"length (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 - destination address invalid (0x%lx), "
"length (0x%x)\n", dst, dma_len);
panic();
}
dma_start(dst, src, dma_len);
dma_end();
}
void rcar_dma_init(void)
{
dma_enable();
dma_setup();
}
/*
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <debug.h>
#include "emmc_config.h"
#include "emmc_hal.h"
#include "emmc_std.h"
#include "emmc_registers.h"
#include "emmc_def.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 (HAL_MEMCARD_DMA == mmc_drv_obj.transfer_mode) {
SETR_32(CC_EXT_MODE, CC_EXT_MODE_CLEAR); /* W (CC_EXT_MODE, H'0000_1010) SD_BUF DMA transfer disabled */
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 (HAL_MEMCARD_DMA == mmc_drv_obj.transfer_mode) {
SETR_32(CC_EXT_MODE, CC_EXT_MODE_CLEAR); /* W (CC_EXT_MODE, H'0000_1010) SD_BUF DMA transfer disabled */
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;
}
/*
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file emmc_config.h
* @brief Configuration file
*
*/
#ifndef __EMMC_CONFIG_H__
#define __EMMC_CONFIG_H__
/* ************************ HEADER (INCLUDE) SECTION *********************** */
/* ***************** MACROS, CONSTANTS, COMPILATION FLAGS ****************** */
/** @brief MMC driver config
*/
#define EMMC_RCA 1UL /* RCA */
#define EMMC_RW_DATA_TIMEOUT 0x40UL /* 314ms (freq = 400KHz, timeout Counter = 0x04(SDCLK * 2^17) */
#define EMMC_RETRY_COUNT 0 /* how many times to try after fail. Don't change. */
#define EMMC_CMD_MAX 60UL /* Don't change. */
/** @brief etc
*/
#define LOADIMAGE_FLAGS_DMA_ENABLE 0x00000001UL
/* ********************** STRUCTURES, TYPE DEFINITIONS ********************* */
/* ********************** DECLARATION OF EXTERNAL DATA ********************* */
/* ************************** FUNCTION PROTOTYPES ************************** */
/* ********************************* CODE ********************************** */
#endif /* #ifndef __EMMC_CONFIG_H__ */
/* ******************************** END ************************************ */
/*
* 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 /* #define __EMMC_DEF_H__ */
/* ******************************** END ************************************ */
/*
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file emmc_hal.h
* @brief emmc boot driver is expecting this header file
*
*/
#ifndef __EMMC_HAL_H__
#define __EMMC_HAL_H__
/* ************************ HEADER (INCLUDE) SECTION *********************** */
#include <stdint.h>
/* ***************** MACROS, CONSTANTS, COMPILATION FLAGS ****************** */
/** @brief 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
/** @brief Memory card response types
*/
#define HAL_MEMCARD_COMMAND_INDEX_MASK 0x0003f
/* ********************** STRUCTURES, TYPE DEFINITIONS ********************* */
/** @brief 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, /**< A non-masked error bit was set in the card status */
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;
/** @brief memory access operation
*/
typedef enum {
HAL_MEMCARD_READ = 0U, /**< read */
HAL_MEMCARD_WRITE = 1U /**< write */
} HAL_MEMCARD_OPERATION;
/** @brief 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 */
/** @brief 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 */
/** @brief mode of data transfer
*/
typedef enum {
HAL_MEMCARD_DMA = 0U,
HAL_MEMCARD_NOT_DMA = 1U
} HAL_MEMCARD_DATA_TRANSFER_MODE;
/** @brief 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;
/** @brief 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;
/** @brief 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;
/** @brief 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;
/** @brief Memory card command codes.
*/
typedef enum {
/* class 0 and class 1 */
CMD0_GO_IDLE_STATE = 0 | HAL_MEMCARD_RESPONSE_NONE | HAL_MEMCARD_COMMAND_TYPE_BC | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD0 */
CMD1_SEND_OP_COND = 1 | HAL_MEMCARD_RESPONSE_R3 | HAL_MEMCARD_COMMAND_TYPE_BCR | HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | HAL_MEMCARD_COMMAND_NORMAL, /* CMD1 */
CMD2_ALL_SEND_CID_MMC = 2 | HAL_MEMCARD_RESPONSE_R2 | HAL_MEMCARD_COMMAND_TYPE_BCR | HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | HAL_MEMCARD_COMMAND_NORMAL, /* CMD2 */
CMD2_ALL_SEND_CID_SD =
2 | HAL_MEMCARD_RESPONSE_R2 | HAL_MEMCARD_COMMAND_TYPE_BCR |
HAL_MEMCARD_COMMAND_CARD_TYPE_SD | HAL_MEMCARD_COMMAND_NORMAL,
CMD3_SET_RELATIVE_ADDR = 3 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | HAL_MEMCARD_COMMAND_NORMAL, /* CMD3 */
CMD3_SEND_RELATIVE_ADDR =
3 | HAL_MEMCARD_RESPONSE_R6 | HAL_MEMCARD_COMMAND_TYPE_AC |
HAL_MEMCARD_COMMAND_CARD_TYPE_SD | HAL_MEMCARD_COMMAND_NORMAL,
CMD4_SET_DSR = 4 | HAL_MEMCARD_RESPONSE_NONE | HAL_MEMCARD_COMMAND_TYPE_BC | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD4 */
CMD5_SLEEP_AWAKE = 5 | HAL_MEMCARD_RESPONSE_R1b | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | HAL_MEMCARD_COMMAND_NORMAL, /* CMD5 */
CMD6_SWITCH = 6 | HAL_MEMCARD_RESPONSE_R1b | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | HAL_MEMCARD_COMMAND_NORMAL, /* CMD6 */
CMD6_SWITCH_FUNC =
6 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_AC |
HAL_MEMCARD_COMMAND_CARD_TYPE_SD | HAL_MEMCARD_COMMAND_NORMAL,
ACMD6_SET_BUS_WIDTH =
6 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_AC |
HAL_MEMCARD_COMMAND_CARD_TYPE_SD | HAL_MEMCARD_COMMAND_APP,
CMD7_SELECT_CARD = 7 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD7 */
CMD7_SELECT_CARD_PROG = 7 | HAL_MEMCARD_RESPONSE_R1b | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD7(from Disconnected State to Programming State) */
CMD7_DESELECT_CARD =
7 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_AC |
HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL,
CMD8_SEND_EXT_CSD = 8 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | HAL_MEMCARD_COMMAND_NORMAL, /* CMD8 */
CMD8_SEND_IF_COND =
8 | HAL_MEMCARD_RESPONSE_R7 | HAL_MEMCARD_COMMAND_TYPE_BCR |
HAL_MEMCARD_COMMAND_CARD_TYPE_SD | HAL_MEMCARD_COMMAND_NORMAL,
CMD9_SEND_CSD = 9 | HAL_MEMCARD_RESPONSE_R2 | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD9 */
CMD10_SEND_CID = 10 | HAL_MEMCARD_RESPONSE_R2 | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD10 */
CMD11_READ_DAT_UNTIL_STOP = 11 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | HAL_MEMCARD_COMMAND_CARD_TYPE_SD | HAL_MEMCARD_COMMAND_NORMAL, /* CMD11 */
CMD12_STOP_TRANSMISSION = 12 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD12 */
CMD12_STOP_TRANSMISSION_WRITE = 12 | HAL_MEMCARD_RESPONSE_R1b | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD12(R1b : write case) */
CMD13_SEND_STATUS = 13 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD13 */
ACMD13_SD_STATUS =
13 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_ADTC_READ |
HAL_MEMCARD_COMMAND_CARD_TYPE_SD | HAL_MEMCARD_COMMAND_APP,
CMD14_BUSTEST_R = 14 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | HAL_MEMCARD_COMMAND_NORMAL, /* CMD14 */
CMD15_GO_INACTIVE_STATE = 15 | HAL_MEMCARD_RESPONSE_NONE | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD15 */
/* class 2 */
CMD16_SET_BLOCKLEN = 16 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD16 */
CMD17_READ_SINGLE_BLOCK = 17 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD17 */
CMD18_READ_MULTIPLE_BLOCK = 18 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD18 */
CMD19_BUS_TEST_W = 19 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | HAL_MEMCARD_COMMAND_NORMAL, /* CMD19 */
/* class 3 */
CMD20_WRITE_DAT_UNTIL_STOP = 20 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | HAL_MEMCARD_COMMAND_NORMAL, /* CMD20 */
CMD21 = 21, /* CMD21 */
CMD22 = 22, /* CMD22 */
ACMD22_SEND_NUM_WR_BLOCKS =
22 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_AC |
HAL_MEMCARD_COMMAND_CARD_TYPE_SD | HAL_MEMCARD_COMMAND_APP,
/* class 4 */
CMD23_SET_BLOCK_COUNT = 23 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | HAL_MEMCARD_COMMAND_NORMAL, /* CMD23 */
ACMD23_SET_WR_BLK_ERASE_COUNT =
23 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_AC |
HAL_MEMCARD_COMMAND_CARD_TYPE_SD | HAL_MEMCARD_COMMAND_APP,
CMD24_WRITE_BLOCK = 24 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD24 */
CMD25_WRITE_MULTIPLE_BLOCK = 25 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD25 */
CMD26_PROGRAM_CID = 26 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | HAL_MEMCARD_COMMAND_NORMAL, /* CMD26 */
CMD27_PROGRAM_CSD = 27 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD27 */
/* class 6 */
CMD28_SET_WRITE_PROT = 28 | HAL_MEMCARD_RESPONSE_R1b | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD28 */
CMD29_CLR_WRITE_PROT = 29 | HAL_MEMCARD_RESPONSE_R1b | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD29 */
CMD30_SEND_WRITE_PROT = 30 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD30 */
CMD30_SEND_WRITE_PROT_TYPE = 31 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD31 */
/* class 5 */
CMD32_ERASE_WR_BLK_START = 32 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_SD | HAL_MEMCARD_COMMAND_NORMAL, /* CMD32 */
CMD33_ERASE_WR_BLK_END = 33 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_SD | HAL_MEMCARD_COMMAND_NORMAL, /* CMD33 */
CMD34 = 34, /* CMD34 */
CMD35_ERASE_GROUP_START = 35 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | HAL_MEMCARD_COMMAND_NORMAL, /* CMD35 */
CMD36_ERASE_GROUP_END = 36 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | HAL_MEMCARD_COMMAND_NORMAL, /* CMD36 */
CMD37 = 37, /* CMD37 */
CMD38_ERASE = 38 | HAL_MEMCARD_RESPONSE_R1b | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD38 */
/* class 9 */
CMD39_FASTIO = 39 | HAL_MEMCARD_RESPONSE_R4 | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | HAL_MEMCARD_COMMAND_NORMAL, /* CMD39 */
CMD40_GO_IRQSTATE = 40 | HAL_MEMCARD_RESPONSE_R5 | HAL_MEMCARD_COMMAND_TYPE_BCR | HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | HAL_MEMCARD_COMMAND_NORMAL, /* CMD40 */
CMD41 = 41, /* CMD41 */
ACMD41_SD_SEND_OP_COND =
41 | HAL_MEMCARD_RESPONSE_R3 | HAL_MEMCARD_COMMAND_TYPE_BCR |
HAL_MEMCARD_COMMAND_CARD_TYPE_SD | HAL_MEMCARD_COMMAND_APP,
/* class 7 */
CMD42_LOCK_UNLOCK = 42 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD42 */
ACMD42_SET_CLR_CARD_DETECT =
42 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_AC |
HAL_MEMCARD_COMMAND_CARD_TYPE_SD | HAL_MEMCARD_COMMAND_APP,
CMD43 = 43, /* CMD43 */
CMD44 = 44, /* CMD44 */
CMD45 = 45, /* CMD45 */
CMD46 = 46, /* CMD46 */
CMD47 = 47, /* CMD47 */
CMD48 = 48, /* CMD48 */
CMD49 = 49, /* CMD49 */
CMD50 = 50, /* CMD50 */
CMD51 = 51, /* CMD51 */
ACMD51_SEND_SCR =
51 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_ADTC_READ |
HAL_MEMCARD_COMMAND_CARD_TYPE_SD | HAL_MEMCARD_COMMAND_APP,
CMD52 = 52, /* CMD52 */
CMD53 = 53, /* CMD53 */
CMD54 = 54, /* CMD54 */
/* class 8 */
CMD55_APP_CMD = 55 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_AC | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD55 */
CMD56_GEN_CMD = 56 | HAL_MEMCARD_RESPONSE_R1 | HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | HAL_MEMCARD_COMMAND_NORMAL, /* CMD56 */
CMD57 = 57, /* CMD57 */
CMD58 = 58, /* CMD58 */
CMD59 = 59, /* CMD59 */
CMD60 = 60, /* CMD60 */
CMD61 = 61, /* CMD61 */
CMD62 = 62, /* CMD62 */
CMD63 = 63 /* CMD63 */
} HAL_MEMCARD_COMMAND;
/** @brief 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
*
* @note 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 implemention year. (2000 = 0, 2001 = 1, ...)<br>
* bits [7:0] API implemention week.<br>
* Example: API specification 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;
/** @brief 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;
/* ********************** DECLARATION OF EXTERNAL DATA ********************* */
/* ************************** FUNCTION PROTOTYPES ************************** */
/* ********************************* CODE ********************************** */
#endif /* __EMMC_HAL_H__ */
/* ******************************** END ************************************ */
/*
* Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stddef.h>
#include <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); /* Automatic Control=Disable, Clock Output=Disable */
return EMMC_SUCCESS;
}
static EMMC_ERROR_CODE emmc_reset_controller(void)
{
EMMC_ERROR_CODE retult;
/* initialize mmc driver */
emmc_drv_init();
/* initialize H/W */
retult = emmc_dev_init();
if (EMMC_SUCCESS != retult) {
return retult;
}
mmc_drv_obj.initialize = TRUE;
return retult;
}
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 retult;
retult = emmc_reset_controller();
if (EMMC_SUCCESS != retult) {
return retult;
}
emmc_driver_config();
return EMMC_SUCCESS;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment