Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
Arm Trusted Firmware
Commits
a51443fa
Unverified
Commit
a51443fa
authored
Oct 18, 2018
by
Soby Mathew
Committed by
GitHub
Oct 18, 2018
Browse files
Merge pull request #1582 from ldts/rcar_gen3/upstream
rcar_gen3: initial support
parents
0059be2d
84433c50
Changes
147
Show whitespace changes
Inline
Side-by-side
drivers/renesas/rcar/emmc/emmc_interrupt.c
0 → 100644
View file @
a51443fa
/*
* Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights
* reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "emmc_config.h"
#include "emmc_def.h"
#include "emmc_hal.h"
#include "emmc_registers.h"
#include "emmc_std.h"
#include "rcar_def.h"
#include <mmio.h>
#include <stddef.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
&
RCAR_CUT_MASK
;
if
((
prr_data
&
RCAR_PRODUCT_MASK
)
==
RCAR_PRODUCT_H3
)
{
if
(
cut_ver
==
RCAR_CUT_VER10
)
{
end_bit
=
BIT17
;
}
else
if
(
cut_ver
==
RCAR_CUT_VER11
)
{
end_bit
=
BIT17
;
}
else
{
end_bit
=
BIT20
;
}
}
else
if
((
prr_data
&
RCAR_PRODUCT_MASK
)
==
RCAR_PRODUCT_M3
)
{
if
(
cut_ver
==
RCAR_CUT_VER10
)
{
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 occured */
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 occured */
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 occured */
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
;
}
drivers/renesas/rcar/emmc/emmc_mount.c
0 → 100644
View file @
a51443fa
/*
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <debug.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 "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
)
&
(
RCAR_PRODUCT_MASK
|
RCAR_CUT_MASK
);
if
(
reg
==
RCAR_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
==
RCAR_PRODUCT_H3_CUT20
)
||
(
reg
==
RCAR_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
resultCalc
;
/* 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 */
resultCalc
=
emmc_calc_tran_speed
(
&
freq
);
/* Card spec is calculated from TRAN_SPEED(CSD). */
if
(
resultCalc
==
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 selction */
if
((
MMC_52MHZ
==
freq
)
||
(
MMC_26MHZ
==
freq
))
{
/* 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
;
}
mmc_drv_obj
.
bus_width
=
(
HAL_MEMCARD_DATA_WIDTH
)
(
width
>>
2
);
/* 2 = 8bit, 1 = 4bit, 0 =1bit */
/* 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
)
&
(
RCAR_PRODUCT_MASK
|
RCAR_CUT_MASK
);
if
((
reg
==
RCAR_PRODUCT_H3_CUT20
)
||
(
reg
==
RCAR_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
]
=
{
10000
,
100000
,
1000000
,
10000000
,
0
,
0
,
0
,
0
};
/**< frequency unit (1/10) */
const
uint32_t
mult
[
16
]
=
{
0
,
10
,
12
,
13
,
15
,
20
,
26
,
30
,
35
,
40
,
45
,
52
,
55
,
60
,
70
,
80
};
uint32_t
maxFreq
;
uint32_t
result
;
uint32_t
tran_speed
=
EMMC_CSD_TRAN_SPEED
();
/* 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
;
maxFreq
=
unit
[
tran_speed
&
EMMC_TRANSPEED_FREQ_UNIT_MASK
]
*
mult
[(
tran_speed
&
EMMC_TRANSPEED_MULT_MASK
)
>>
EMMC_TRANSPEED_MULT_SHIFT
];
if
(
maxFreq
==
0
)
{
result
=
0
;
}
else
if
(
MMC_FREQ_52MHZ
<=
maxFreq
)
*
freq
=
MMC_52MHZ
;
else
if
(
MMC_FREQ_26MHZ
<=
maxFreq
)
*
freq
=
MMC_26MHZ
;
else
if
(
MMC_FREQ_20MHZ
<=
maxFreq
)
*
freq
=
MMC_20MHZ
;
else
*
freq
=
MMC_400KHZ
;
return
result
;
}
static
uint32_t
emmc_set_timeout_register_value
(
uint32_t
freq
)
{
uint32_t
timeoutCnt
;
/* SD_OPTION - Timeout Counter */
switch
(
freq
)
{
case
1U
:
timeoutCnt
=
0xE0U
;
break
;
/* SDCLK * 2^27 */
case
2U
:
timeoutCnt
=
0xE0U
;
break
;
/* SDCLK * 2^27 */
case
4U
:
timeoutCnt
=
0xD0U
;
break
;
/* SDCLK * 2^26 */
case
8U
:
timeoutCnt
=
0xC0U
;
break
;
/* SDCLK * 2^25 */
case
16U
:
timeoutCnt
=
0xB0U
;
break
;
/* SDCLK * 2^24 */
case
32U
:
timeoutCnt
=
0xA0U
;
break
;
/* SDCLK * 2^23 */
case
64U
:
timeoutCnt
=
0x90U
;
break
;
/* SDCLK * 2^22 */
case
128U
:
timeoutCnt
=
0x80U
;
break
;
/* SDCLK * 2^21 */
case
256U
:
timeoutCnt
=
0x70U
;
break
;
/* SDCLK * 2^20 */
case
512U
:
timeoutCnt
=
0x70U
;
break
;
/* SDCLK * 2^20 */
default:
timeoutCnt
=
0xE0U
;
break
;
/* SDCLK * 2^27 */
}
return
timeoutCnt
;
}
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
;
}
drivers/renesas/rcar/emmc/emmc_read.c
0 → 100644
View file @
a51443fa
/*
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include "emmc_config.h"
#include "emmc_hal.h"
#include "emmc_std.h"
#include "emmc_registers.h"
#include "emmc_def.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
);
SETR_32
(
CC_EXT_MODE
,
(
CC_EXT_MODE_CLEAR
|
CC_EXT_MODE_DMASDRW_ENABLE
));
/* SD_BUF Read/Write DMA Transfer 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
;
}
drivers/renesas/rcar/emmc/emmc_registers.h
0 → 100644
View file @
a51443fa
/*
* Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file emmc_registers.h
* @brief emmc boot driver is expecting this header file. HS-MMC module header file.
*
*/
#ifndef __EMMC_REGISTERS_H__
#define __EMMC_REGISTERS_H__
/* ************************ HEADER (INCLUDE) SECTION *********************** */
/* ***************** MACROS, CONSTANTS, COMPILATION FLAGS ****************** */
/* MMC channel select */
#define MMC_CH0 (0U)
/* SDHI2/MMC0 */
#define MMC_CH1 (1U)
/* SDHI3/MMC1 */
#if RCAR_LSI == RCAR_E3
#define USE_MMC_CH (MMC_CH1)
/* R-Car E3 */
#else
/* RCAR_LSI == RCAR_E3 */
#define USE_MMC_CH (MMC_CH0)
/* R-Car H3/M3/M3N */
#endif
/* RCAR_LSI == RCAR_E3 */
#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)
/** @brief Clock Pulse Generator (CPG) registers
*/
#define CPG_BASE (0xE6150000U)
#define CPG_MSTPSR3 (CPG_BASE+0x0048U)
/* Module stop status register 3 */
#define CPG_SMSTPCR3 (CPG_BASE+0x013CU)
/* System module stop control register 3 */
#define CPG_SD2CKCR (CPG_BASE+0x0268U)
/* SDHI2 clock frequency control register */
#define CPG_SD3CKCR (CPG_BASE+0x026CU)
/* SDHI3 clock frequency control register */
#define CPG_CPGWPR (CPG_BASE+0x0900U)
/* CPG Write Protect Register */
#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)
/** brief 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)
/** @brief 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 */
/** @brief 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 The write value should always be 1. HWM_0003 */
/** @brief SOFT_RST
*/
#define SOFT_RST_SDRST 0x00000001UL
/** @brief 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
/** @brief SD_OPTION
*/
#define SD_OPTION_TIMEOUT_CNT_MASK 0x000000F0UL
/** @brief 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 High speed mode 26Mhz */
#define MMC_52MHZ 4UL
/* 200MHz * 1/4 = 50 MHz High speed 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
/** @brief 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 */
/** @brief 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
/** @brief 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. */
/** @brief 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
/** @brief DM_DTRAN_ADDR
*/
#define DM_DTRAN_ADDR_WRITE_MASK 0xFFFFFFF8UL
/** @brief DM_CM_DTRAN_CTRL
*/
#define DM_CM_DTRAN_CTRL_START 0x00000001UL
/** @brief 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 */
/* ********************** STRUCTURES, TYPE DEFINITIONS ********************* */
/* ********************** DECLARATION OF EXTERNAL DATA ********************* */
/* ************************** FUNCTION PROTOTYPES ************************** */
/* ********************************* CODE ********************************** */
#endif
/* __EMMC_REGISTERS_H__ */
/* ******************************** END ************************************ */
drivers/renesas/rcar/emmc/emmc_std.h
0 → 100644
View file @
a51443fa
/*
* Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file emmc_std.h
* @brief eMMC boot is expecting this header file
*
*/
#ifndef __EMMC_STD_H__
#define __EMMC_STD_H__
#include "emmc_hal.h"
/* ************************ HEADER (INCLUDE) SECTION *********************** */
/* ***************** MACROS, CONSTANTS, COMPILATION FLAGS ****************** */
#ifndef FALSE
#define FALSE 0U
#endif
#ifndef TRUE
#define TRUE 1U
#endif
/** @brief 64bit registers
**/
#define SETR_64(r, v) (*(volatile uint64_t *)(r) = (v))
#define GETR_64(r) (*(volatile uint64_t *)(r))
/** @brief 32bit registers
**/
#define SETR_32(r, v) (*(volatile uint32_t *)(r) = (v))
#define GETR_32(r) (*(volatile uint32_t *)(r))
/** @brief 16bit registers
*/
#define SETR_16(r, v) (*(volatile uint16_t *)(r) = (v))
#define GETR_16(r) (*(volatile uint16_t *)(r))
/** @brief 8bit registers
*/
#define SETR_8(r, v) (*(volatile uint8_t *)(r) = (v))
#define GETR_8(r) (*(volatile uint8_t *)(r))
/** @brief 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))
/** @brief 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))
/** @brief for 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 */
/** @brief 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 */
/** @brief 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. Non-masked error bit was set in the card status */
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
;
/** @brief 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
/** @brief Response
*/
/** R1 */
#define EMMC_R1_ERROR_MASK 0xFDBFE080U
/* Type 'E' bit and bit14(must be 0). ignore bit22 */
#define EMMC_R1_ERROR_MASK_WITHOUT_CRC (0xFD3FE080U)
/* Ignore bit23 (Not check CRC error) */
#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 */
#define EMMC_SWITCH_PARTITION_CONFIG 0x03B30000UL
/**< Partition config = 0x00 */
#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
/** @brief for TAAC mask
*/
#define TAAC_TIME_UNIT_MASK (0x07)
#define TAAC_MULTIPLIER_FACTOR_MASK (0x0F)
/* ********************** STRUCTURES, TYPE DEFINITIONS ********************* */
/** @brief 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
;
/** @brief 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
;
/** @brief eMMC boot driver error information
*/
typedef
struct
{
uint16_t
num
;
/**< error no */
uint16_t
code
;
/**< error code */
volatile
uint32_t
info1
;
/**< SD_INFO1 register value. (hardware dependence) */
volatile
uint32_t
info2
;
/**< SD_INFO2 register value. (hardware dependence) */
volatile
uint32_t
status1
;
/**< SD_ERR_STS1 register value. (hardware dependence) */
volatile
uint32_t
status2
;
/**< SD_ERR_STS2 register value. (hardware dependence) */
volatile
uint32_t
dm_info1
;
/**< DM_CM_INFO1 register value. (hardware dependence) */
volatile
uint32_t
dm_info2
;
/**< DM_CM_INFO2 register value. (hardware dependence) */
}
st_error_info
;
/** @brief Command information
*/
typedef
struct
{
HAL_MEMCARD_COMMAND
cmd
;
/**< Command information */
uint32_t
arg
;
/**< argument */
HAL_MEMCARD_OPERATION
dir
;
/**< direction */
uint32_t
hw
;
/**< H/W dependence. SD_CMD register value. */
}
st_command_info
;
/** @brief 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 */
uint32_t
max_freq
;
/**< Max frequency (Card Spec)[Hz]. It changes dynamically by CSD and EXT_CSD. */
uint32_t
request_freq
;
/**< request freq [Hz] (400K, 26MHz, 52MHz, etc) */
uint32_t
current_freq
;
/**< current MMC clock[Hz] (the closest frequency supported by HW) */
/* state flag */
HAL_MEMCARD_PRESENCE_STATUS
card_present
;
/**< presence status of the memory card */
uint32_t
card_power_enable
;
/**< True : Power ON */
uint32_t
clock_enable
;
/**< True : Clock ON */
uint32_t
initialize
;
/**< True : initialize complete. */
uint32_t
access_mode
;
/**< True : sector access, FALSE : byte access */
uint32_t
mount
;
/**< True : mount complete. */
uint32_t
selected
;
/**< True : selected card. */
HAL_MEMCARD_DATA_TRANSFER_MODE
transfer_mode
;
/**< 0: DMA, 1:PIO */
uint32_t
image_num
;
/**< loaded ISSW image No. ISSW have copy image. */
EMMC_R1_STATE
current_state
;
/**< card state */
volatile
uint32_t
during_cmd_processing
;
/**< True : during command processing */
volatile
uint32_t
during_transfer
;
/**< True : during transfer */
volatile
uint32_t
during_dma_transfer
;
/**< True : during transfer (DMA)*/
volatile
uint32_t
dma_error_flag
;
/**< True : occurred DMAC error */
volatile
uint32_t
force_terminate
;
/**< force terminate flag */
volatile
uint32_t
state_machine_blocking
;
/**< state machine blocking flag : True or False */
volatile
uint32_t
get_partition_access_flag
;
/**< True : get partition access processing */
EMMC_PARTITION_ID
boot_partition_en
;
/**< Boot partition */
EMMC_PARTITION_ID
partition_access
;
/**< Current access partition */
/* timeout */
uint32_t
hs_timing
;
/**< high speed */
/* timeout */
uint32_t
data_timeout
;
/**< read and write data timeout.*/
/* retry */
uint32_t
retries_after_fail
;
/**< how many times to try after fail, for instance sending command */
/* 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
;
/**< pointer to buffer 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 */
uint32_t
low_clock_mode_enable
;
/**< True : clock mode is low. (MMC clock = Max26MHz) */
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
);
/* ********************** DECLARATION OF EXTERNAL DATA ********************* */
/* ************************** FUNCTION PROTOTYPES ************************** */
uint32_t
emmc_get_csd_time
(
void
);
#define MMC_DEBUG
/* ********************************* CODE ********************************** */
/* ******************************** END ************************************ */
#endif
/* __EMMC_STD_H__ */
drivers/renesas/rcar/emmc/emmc_utility.c
0 → 100644
View file @
a51443fa
/*
* 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"
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
;
}
drivers/renesas/rcar/iic_dvfs/iic_dvfs.c
0 → 100644
View file @
a51443fa
/*
* Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <mmio.h>
#include <debug.h>
#include "rcar_def.h"
#include "cpg_registers.h"
#include "iic_dvfs.h"
#include "rcar_private.h"
#define DVFS_RETRY_MAX (2U)
#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_0 (0x07)
#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_1 (0x09)
#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_2 (0x0B)
#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_3 (0x0E)
#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_E (0x15)
#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_0 (0x01)
#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_1 (0x02)
#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_2 (0x03)
#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_3 (0x05)
#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_E (0x07)
#define CPG_BIT_SMSTPCR9_DVFS (0x04000000)
#define IIC_DVFS_REG_BASE (0xE60B0000)
#define IIC_DVFS_REG_ICDR (IIC_DVFS_REG_BASE + 0x0000)
#define IIC_DVFS_REG_ICCR (IIC_DVFS_REG_BASE + 0x0004)
#define IIC_DVFS_REG_ICSR (IIC_DVFS_REG_BASE + 0x0008)
#define IIC_DVFS_REG_ICIC (IIC_DVFS_REG_BASE + 0x000C)
#define IIC_DVFS_REG_ICCL (IIC_DVFS_REG_BASE + 0x0010)
#define IIC_DVFS_REG_ICCH (IIC_DVFS_REG_BASE + 0x0014)
#define IIC_DVFS_BIT_ICSR_BUSY (0x10)
#define IIC_DVFS_BIT_ICSR_AL (0x08)
#define IIC_DVFS_BIT_ICSR_TACK (0x04)
#define IIC_DVFS_BIT_ICSR_WAIT (0x02)
#define IIC_DVFS_BIT_ICSR_DTE (0x01)
#define IIC_DVFS_BIT_ICCR_ENABLE (0x80)
#define IIC_DVFS_SET_ICCR_START (0x94)
#define IIC_DVFS_SET_ICCR_STOP (0x90)
#define IIC_DVFS_SET_ICCR_RETRANSMISSION (0x94)
#define IIC_DVFS_SET_ICCR_CHANGE (0x81)
#define IIC_DVFS_SET_ICCR_STOP_READ (0xC0)
#define IIC_DVFS_BIT_ICIC_TACKE (0x04)
#define IIC_DVFS_BIT_ICIC_WAITE (0x02)
#define IIC_DVFS_BIT_ICIC_DTEE (0x01)
#define DVFS_READ_MODE (0x01)
#define DVFS_WRITE_MODE (0x00)
#define IIC_DVFS_SET_DUMMY (0x52)
#define IIC_DVFS_SET_BUSY_LOOP (500000000U)
typedef
enum
{
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_RECIEVE
,
DVFS_DONE
,
}
DVFS_STATE_T
;
#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
,
DVFS_STATE_T
*
state
,
uint32_t
*
err
,
uint8_t
mode
)
{
uint8_t
icsr_al
=
0
,
icsr_tack
=
0
;
uint8_t
reg
,
stop
;
uint32_t
i
=
0
;
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
==
0
&&
icsr_tack
==
0
)
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
==
0
);
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
=
0
;
do
{
reg
=
mmio_read_8
(
IIC_DVFS_REG_ICSR
)
&
IIC_DVFS_BIT_ICSR_BUSY
;
if
(
reg
==
0
)
break
;
if
(
i
++
>
IIC_DVFS_SET_BUSY_LOOP
)
panic
();
}
while
(
1
);
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
=
0
;
while
((
mmio_read_8
(
IIC_DVFS_REG_ICSR
)
&
IIC_DVFS_BIT_ICSR_BUSY
)
!=
0
)
{
if
(
i
++
>
IIC_DVFS_SET_BUSY_LOOP
)
panic
();
}
mmio_write_8
(
IIC_DVFS_REG_ICCR
,
0
);
(
*
err
)
++
;
if
(
*
err
>
DVFS_RETRY_MAX
)
return
DVFS_ERROR
;
*
state
=
DVFS_START
;
return
DVFS_PROCESS
;
}
IIC_DVFS_FUNC
(
start
,
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
)
&
RCAR_PRODUCT_MASK
;
if
(
lsi_product
==
RCAR_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
,
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
,
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
,
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
,
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
=
0
;
i
<
IIC_DVFS_SET_BUSY_LOOP
;
i
++
)
{
if
(
mmio_read_8
(
IIC_DVFS_REG_ICSR
)
&
IIC_DVFS_BIT_ICSR_BUSY
)
continue
;
goto
done
;
}
panic
();
done:
mmio_write_8
(
IIC_DVFS_REG_ICCR
,
0
);
return
DVFS_COMPLETE
;
}
IIC_DVFS_FUNC
(
write_reg_addr_read
,
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
,
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
,
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_RECIEVE
;
return
result
;
}
IIC_DVFS_FUNC
(
change_send_to_recieve
,
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
,
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
,
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
)
{
DVFS_STATE_T
state
=
DVFS_START
;
int32_t
result
=
DVFS_PROCESS
;
uint32_t
err
=
0
;
mstpcr_write
(
SCMSTPCR9
,
CPG_MSTPSR9
,
CPG_BIT_SMSTPCR9_DVFS
);
mmio_write_8
(
IIC_DVFS_REG_ICCR
,
0
);
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
)
{
DVFS_STATE_T
state
=
DVFS_START
;
int32_t
result
=
DVFS_PROCESS
;
uint32_t
err
=
0
;
mstpcr_write
(
SCMSTPCR9
,
CPG_MSTPSR9
,
CPG_BIT_SMSTPCR9_DVFS
);
mmio_write_8
(
IIC_DVFS_REG_ICCR
,
0
);
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_RECIEVE
:
result
=
dvfs_change_send_to_recieve
(
&
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
;
}
drivers/renesas/rcar/iic_dvfs/iic_dvfs.h
0 → 100644
View file @
a51443fa
/*
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef IIC_DVFS_H__
#define IIC_DVFS_H__
/* PMIC slave */
#define PMIC (0x30)
#define BKUP_MODE_CNT (0x20)
#define DVFS_SET_VID (0x54)
#define REG_KEEP10 (0x79)
/* EEPROM slave */
#define EEPROM (0x50)
#define BOARD_ID (0x70)
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
drivers/renesas/rcar/io/io_common.h
0 → 100644
View file @
a51443fa
/*
* 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
drivers/renesas/rcar/io/io_emmcdrv.c
0 → 100644
View file @
a51443fa
/*
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <debug.h>
#include <io_driver.h>
#include <io_storage.h>
#include <string.h>
#include "io_common.h"
#include "io_emmcdrv.h"
#include "io_private.h"
#include "emmc_config.h"
#include "emmc_hal.h"
#include "emmc_std.h"
#include "emmc_def.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
;
ssize_t
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
,
ssize_t
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%lx(%d) len=0x%lx(%d)
\n
"
,
buffer
,
current_file
.
partition
,
current_file
.
file_pos
,
sector_add
,
length
,
sector_num
);
if
(
buffer
+
length
-
1
<=
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
+=
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
)
{
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
((
PARTITION_ID_BOOT_1
==
emmcdrv_bootpartition
)
||
(
PARTITION_ID_BOOT_2
==
emmcdrv_bootpartition
))
{
current_file
.
partition
=
emmcdrv_bootpartition
;
NOTICE
(
"BL2: eMMC boot from partition %d
\n
"
,
emmcdrv_bootpartition
);
goto
done
;
}
return
IO_FAIL
;
}
if
(
PARTITION_ID_USER
==
block_spec
->
partition
||
PARTITION_ID_BOOT_1
==
block_spec
->
partition
||
PARTITION_ID_BOOT_2
==
block_spec
->
partition
)
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
)
&
current_file
;
return
IO_SUCCESS
;
}
static
int32_t
emmcdrv_block_close
(
io_entity_t
*
entity
)
{
memset
((
void
*
)
&
current_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
;
}
drivers/renesas/rcar/io/io_emmcdrv.h
0 → 100644
View file @
a51443fa
/*
* 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
drivers/renesas/rcar/io/io_memdrv.c
0 → 100644
View file @
a51443fa
/*
* Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <debug.h>
#include <io_driver.h>
#include <io_storage.h>
#include <string.h>
#include "io_common.h"
#include "io_private.h"
#include "io_memdrv.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
;
ssize_t
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
)
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
)
&
current_file
;
return
IO_SUCCESS
;
}
static
int32_t
memdrv_block_seek
(
io_entity_t
*
entity
,
int32_t
mode
,
ssize_t
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%lx len=%ld(0x%lx)
\n
"
,
buffer
,
fp
->
base
+
fp
->
file_pos
,
length
,
length
);
if
(
FLASH_MEMORY_SIZE
<
fp
->
file_pos
+
length
)
{
ERROR
(
"BL2: check load image (source address)
\n
"
);
return
IO_FAIL
;
}
rcar_dma_exec
(
buffer
,
fp
->
base
+
fp
->
file_pos
,
length
);
fp
->
file_pos
+=
length
;
*
cnt
=
length
;
return
IO_SUCCESS
;
}
static
int32_t
memdrv_block_close
(
io_entity_t
*
entity
)
{
entity
->
info
=
0U
;
memset
((
void
*
)
&
current_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
;
}
drivers/renesas/rcar/io/io_memdrv.h
0 → 100644
View file @
a51443fa
/*
* 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
drivers/renesas/rcar/io/io_private.h
0 → 100644
View file @
a51443fa
/*
* 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
drivers/renesas/rcar/io/io_rcar.c
0 → 100644
View file @
a51443fa
/*
* Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <auth_mod.h>
#include <bl_common.h>
#include <debug.h>
#include <errno.h>
#include <firmware_image_package.h>
#include <io_driver.h>
#include <io_storage.h>
#include <platform.h>
#include <platform_def.h>
#include <stdint.h>
#include <string.h>
#include <uuid.h>
#include <mmio.h>
#include <arch_helpers.h>
#include "io_rcar.h"
#include "io_common.h"
#include "io_private.h"
extern
int32_t
plat_get_drv_source
(
uint32_t
id
,
uintptr_t
*
dev
,
uintptr_t
*
image_spec
);
extern
int
auth_mod_verify_img
(
unsigned
int
img_id
,
void
*
ptr
,
unsigned
int
len
);
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
+
2
<
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
(
"load_bl33x: failed to get offset
\n
"
);
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
(
"Failed to open FIP (%i)
\n
"
,
rc
);
loaded
=
IO_FAIL
;
return
loaded
;
}
rc
=
io_seek
(
handle
,
IO_SEEK_SET
,
offset
);
if
(
rc
!=
IO_SUCCESS
)
{
WARN
(
"load_bl33x: failed to seek
\n
"
);
loaded
=
IO_FAIL
;
return
loaded
;
}
rc
=
check_load_area
(
dst
,
len
);
if
(
rc
!=
IO_SUCCESS
)
{
WARN
(
"load_bl33x: check load area
\n
"
);
loaded
=
IO_FAIL
;
return
loaded
;
}
rc
=
io_read
(
handle
,
dst
,
len
,
&
cnt
);
if
(
rc
!=
IO_SUCCESS
)
{
WARN
(
"load_bl33x: failed to read
\n
"
);
loaded
=
IO_FAIL
;
return
loaded
;
}
#if TRUSTED_BOARD_BOOT
rc
=
auth_mod_verify_img
(
img
[
i
],
(
void
*
)
dst
,
len
);
if
(
rc
)
{
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
)
=
{
0
};
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
(
"rcar_file_open : Only one open file at a time.
\n
"
);
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
)
{
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
)
&
current_file
;
return
IO_SUCCESS
;
}
rcar_read_certificate
((
uint64_t
)
cert
,
&
len
,
&
dst
);
/*----------------*
* Baylibre: HACK *
*----------------*/
if
(
BL31_IMAGE_ID
==
spec
->
offset
&&
len
<
RCAR_TRUSTED_SRAM_SIZE
)
{
WARN
(
"r-car ignoring the BL31 size from certificate,"
"using RCAR_TRUSTED_SRAM_SIZE instead
\n
"
);
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
)
&
current_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
)
{
*
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
(
"rcar_file_read: failed to seek
\n
"
);
goto
error
;
}
if
(
load_bl33x_counter
==
RCAR_COUNT_LOAD_BL33
)
{
rc
=
check_load_area
(
buffer
,
length
);
if
(
rc
!=
IO_SUCCESS
)
{
WARN
(
"rcar_file_read: load area err
\n
"
);
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
)
memset
(
&
current_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
;
}
drivers/renesas/rcar/io/io_rcar.h
0 → 100644
View file @
a51443fa
/*
* 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
drivers/renesas/rcar/pwrc/call_sram.S
0 → 100644
View file @
a51443fa
/*
*
Copyright
(
c
)
2018
,
Renesas
Electronics
Corporation
.
All
rights
reserved
.
*
*
SPDX
-
License
-
Identifier
:
BSD
-
3
-
Clause
*/
#include <arch.h>
#include <asm_macros.S>
#include "rcar_def.h"
.
global
rcar_pwrc_switch_stack
.
global
rcar_pwrc_save_generic_timer
.
global
rcar_pwrc_restore_generic_timer
#define OFFSET_SP_X9_X10 (0x00)
#define OFFSET_CNTFID0 (0x10)
#define OFFSET_CNTPCT_EL0 (0x18)
#define OFFSET_TIMER_COUNT (0x20)
/*
*
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
/*
x0
:
stack
pointer
base
address
*/
func
rcar_pwrc_save_generic_timer
stp
x9
,
x10
,
[
x0
,
#
OFFSET_SP_X9_X10
]
/
*
save
CNTFID0
and
cntpct_el0
*/
mov_imm
x10
,
(
RCAR_CNTC_BASE
+
CNTFID_OFF
)
ldr
x9
,
[
x10
]
mrs
x10
,
cntpct_el0
stp
x9
,
x10
,
[
x0
,
#
OFFSET_CNTFID0
]
ldp
x9
,
x10
,
[
x0
,
#
OFFSET_SP_X9_X10
]
ret
endfunc
rcar_pwrc_save_generic_timer
/*
x0
:
Stack
pointer
base
address
*/
func
rcar_pwrc_restore_generic_timer
stp
x9
,
x10
,
[
x0
,
#
OFFSET_SP_X9_X10
]
/
*
restore
CNTFID0
and
cntpct_el0
*/
ldr
x10
,
[
x0
,
#
OFFSET_CNTFID0
]
mov_imm
x9
,
(
RCAR_CNTC_BASE
+
CNTFID_OFF
)
str
x10
,
[
x9
]
ldp
x9
,
x10
,
[
x0
,
#
OFFSET_CNTPCT_EL0
]
add
x9
,
x9
,
x10
str
x9
,
[
x0
,
#
OFFSET_TIMER_COUNT
]
ldp
x9
,
x10
,
[
x0
,
#
OFFSET_SP_X9_X10
]
ret
endfunc
rcar_pwrc_restore_generic_timer
drivers/renesas/rcar/pwrc/pwrc.c
0 → 100644
View file @
a51443fa
/*
* Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <arch_helpers.h>
#include <assert.h>
#include <bakery_lock.h>
#include <debug.h>
#include <mmio.h>
#include <string.h>
#include <xlat_tables_v2.h>
#include "iic_dvfs.h"
#include "rcar_def.h"
#include "rcar_private.h"
#include "pwrc.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_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_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_CONV_MICROSEC (1000000U)
#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
#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 __ASSEMBLY__
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
#if RCAR_SYSTEM_SUSPEND
static
void
__attribute__
((
section
(
".system_ram"
)))
rcar_pwrc_micro_delay
(
uint64_t
micro_sec
)
{
uint64_t
freq
,
base
,
val
;
uint64_t
wait_time
=
0
;
freq
=
read_cntfrq_el0
();
base
=
read_cntpct_el0
();
while
(
micro_sec
>
wait_time
)
{
val
=
read_cntpct_el0
()
-
base
;
wait_time
=
val
*
RCAR_CONV_MICROSEC
/
freq
;
}
}
#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
&
RCAR_PRODUCT_MASK
;
cut
=
reg
&
RCAR_CUT_MASK
;
c
=
rcar_pwrc_get_mpidr_cluster
(
mpidr
);
dst
=
IS_CA53
(
c
)
?
RCAR_CA53CPUCMCR
:
RCAR_CA57CPUCMCR
;
if
(
RCAR_PRODUCT_M3
==
product
&&
cut
<=
RCAR_M3_CUT_VER11
)
goto
done
;
if
(
RCAR_PRODUCT_H3
==
product
&&
cut
<=
RCAR_CUT_VER20
)
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
();
}
#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
&
RCAR_PRODUCT_MASK
;
cut
=
reg
&
RCAR_CUT_MASK
;
if
(
product
==
RCAR_PRODUCT_M3
)
goto
self_refresh
;
if
(
product
==
RCAR_PRODUCT_H3
&&
cut
<
RCAR_CUT_VER20
)
goto
self_refresh
;
mmio_write_32
(
DBSC4_REG_DBSYSCNT0
,
DBSC4_SET_DBSYSCNT0_WRITE_ENABLE
);
self_refresh:
/* Set the Self-Refresh mode */
mmio_write_32
(
DBSC4_REG_DBACEN
,
0
);
if
(
product
==
RCAR_PRODUCT_H3
&&
cut
<
RCAR_CUT_VER20
)
rcar_pwrc_micro_delay
(
100
);
else
if
(
product
==
RCAR_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
==
RCAR_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_pwrc_micro_delay
(
1U
);
if
(
product
==
RCAR_PRODUCT_M3
)
return
;
if
(
product
==
RCAR_PRODUCT_H3
&&
cut
<
RCAR_CUT_VER20
)
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
&
RCAR_PRODUCT_MASK
;
if
(
product
!=
RCAR_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_code_copy_to_system_ram
();
rcar_pwrc_save_generic_timer
(
rcar_stack_generic_timer
);
/* 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
;
#endif
rcar_pwrc_code_copy_to_system_ram
();
#if PMIC_ROHM_BD9571
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
;
rcar_pwrc_code_copy_to_system_ram
();
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
&
(
1
<<
(
STATE_CA53_CPU
+
RCAR_CA53CPU_NUM_MAX
)))
return
RCAR_CLUSTER_CA57
;
if
(
reg
&
(
1
<<
(
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
;
}
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
&
(
1
<<
(
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
;
}
drivers/renesas/rcar/pwrc/pwrc.h
0 → 100644
View file @
a51443fa
/*
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef RCAR_PWRC_H__
#define RCAR_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 (1 << 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 __ASSEMBLY__
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
);
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
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
void
rcar_pwrc_save_generic_timer
(
uint64_t
*
rcar_stack_generic_timer
);
extern
uint32_t
rcar_pwrc_switch_stack
(
uintptr_t
jump
,
uintptr_t
stack
,
void
*
arg
);
extern
uint64_t
rcar_stack_generic_timer
[
5
];
#endif
#endif
drivers/renesas/rcar/rom/rom_api.c
0 → 100644
View file @
a51443fa
/*
* Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <mmio.h>
#include <stdint.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 */
#define API_TABLE_MAX (4U)
/* 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
)
&
RCAR_PRODUCT_MASK
;
cut_ver
=
mmio_read_32
(
RCAR_PRR
)
&
RCAR_CUT_MASK
;
switch
(
product
)
{
case
RCAR_PRODUCT_H3
:
if
(
cut_ver
==
RCAR_CUT_VER10
)
index
=
OLD_API_TABLE1
;
else
if
(
cut_ver
==
RCAR_CUT_VER11
)
index
=
OLD_API_TABLE1
;
else
if
(
cut_ver
==
RCAR_CUT_VER20
)
index
=
OLD_API_TABLE2
;
else
/* Later than H3 Ver.2.0 */
index
=
NEW_API_TABLE
;
break
;
case
RCAR_PRODUCT_M3
:
if
(
cut_ver
==
RCAR_CUT_VER10
)
index
=
OLD_API_TABLE3
;
else
/* M3 Ver.1.1 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 */
};
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 */
};
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
);
}
Prev
1
2
3
4
5
6
…
8
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment