mirror of
https://gitee.com/Vancouver2017/luban-lite-t3e-pro.git
synced 2025-12-14 18:38:55 +00:00
V1.0.5
This commit is contained in:
@@ -333,21 +333,25 @@ int usb_hc_hw_fast_init(int id)
|
||||
|
||||
/* Disable all interrupts */
|
||||
writel(0, &hcor->usbintr);
|
||||
aicos_mdelay(10);
|
||||
|
||||
/* Clear pending interrupts. Bits in the USBSTS register are cleared by
|
||||
* writing a '1' to the corresponding bit.
|
||||
*/
|
||||
writel(EHCI_INT_ALLINTS, &hcor->usbsts);
|
||||
aicos_mdelay(10);
|
||||
|
||||
/* Start the host controller by setting the RUN bit in the USBCMD register. */
|
||||
regval = readl(&hcor->usbcmd);
|
||||
regval |= EHCI_USBCMD_RUN;
|
||||
writel(regval, &hcor->usbcmd);
|
||||
aicos_mdelay(10);
|
||||
|
||||
/* Route all ports to this host controller by setting the CONFIG flag. */
|
||||
regval = readl(&hcor->configflag);
|
||||
regval |= EHCI_CONFIGFLAG;
|
||||
writel(regval, &hcor->configflag);
|
||||
aicos_mdelay(10);
|
||||
|
||||
/* Wait for the EHCI to run (i.e., no longer report halted) */
|
||||
ret = usb_ehci_wait_usbsts(id, EHCI_USBSTS_HALTED, 0, 100 * 1000);
|
||||
@@ -360,11 +364,14 @@ int usb_hc_hw_fast_init(int id)
|
||||
regval = readl(&hcor->portsc[0]);
|
||||
regval |= EHCI_PORTSC_PP;
|
||||
writel(regval, &hcor->portsc[0]);
|
||||
aicos_mdelay(10);
|
||||
|
||||
/* Enable EHCI interrupts. Interrupts are still disabled at the level of
|
||||
* the interrupt controller.
|
||||
*/
|
||||
writel(EHCI_HANDLED_INTS, &hcor->usbintr);
|
||||
aicos_mdelay(10);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -728,7 +735,7 @@ int usbh_ep_free(usbh_epinfo_t ep)
|
||||
static int usb_ehci_reset(int id)
|
||||
{
|
||||
u32 regval = 0;
|
||||
u64 start_us;
|
||||
u64 start_ms;
|
||||
volatile struct ehci_hcor_s *hcor;
|
||||
|
||||
hcor = (struct ehci_hcor_s *)USB_EHCI_HCOR_BASE(id);
|
||||
@@ -741,16 +748,17 @@ static int usb_ehci_reset(int id)
|
||||
*/
|
||||
|
||||
writel(0, &hcor->usbcmd);
|
||||
aicos_mdelay(10);
|
||||
|
||||
/* "... Software should not set [HCRESET] to a one when the HCHalted bit in
|
||||
* the USBSTS register is a zero. Attempting to reset an actively running
|
||||
* host controller will result in undefined behavior."
|
||||
*/
|
||||
|
||||
start_us = aic_get_time_us();
|
||||
start_ms = aic_get_time_ms();
|
||||
do {
|
||||
/* Wait and update the timeout counter */
|
||||
if ((aic_get_time_us() - start_us) > 1000)
|
||||
if ((aic_get_time_ms() - start_ms) > 1000)
|
||||
break;
|
||||
|
||||
/* Get the current value of the USBSTS register. This loop will
|
||||
@@ -774,13 +782,14 @@ static int usb_ehci_reset(int id)
|
||||
regval = readl(&hcor->usbcmd);
|
||||
regval |= EHCI_USBCMD_HCRESET;
|
||||
writel(regval, &hcor->usbcmd);
|
||||
aicos_mdelay(10);
|
||||
|
||||
/* Wait for the HCReset bit to become clear */
|
||||
|
||||
start_us = aic_get_time_us();
|
||||
start_ms = aic_get_time_ms();
|
||||
do {
|
||||
/* Wait and update the timeout counter */
|
||||
if ((aic_get_time_us() - start_us) > 1000)
|
||||
if ((aic_get_time_ms() - start_ms) > 1000)
|
||||
break;
|
||||
|
||||
/* Get the current value of the USBCMD register. This loop will
|
||||
@@ -788,6 +797,7 @@ static int usb_ehci_reset(int id)
|
||||
* HCReset bit is no longer set in the USBSTS register.
|
||||
*/
|
||||
|
||||
aicos_mdelay(1);
|
||||
regval = readl(&hcor->usbcmd);
|
||||
} while ((regval & EHCI_USBCMD_HCRESET) != 0);
|
||||
|
||||
@@ -898,13 +908,14 @@ int usbh_get_port_connect_status(int id, int port)
|
||||
* to preserve the values of all R/W bits (RO bits don't matter)
|
||||
*/
|
||||
writel(portsc, &hcor->portsc[port - 1]);
|
||||
aicos_mdelay(10);
|
||||
|
||||
return connected;
|
||||
}
|
||||
|
||||
int usbh_reset_port(int port, int id)
|
||||
{
|
||||
u64 start_us;
|
||||
u64 start_ms;
|
||||
u32 regval;
|
||||
volatile struct ehci_hcor_s *hcor;
|
||||
|
||||
@@ -914,12 +925,12 @@ int usbh_reset_port(int port, int id)
|
||||
regval &= ~EHCI_PORTSC_PE;
|
||||
regval |= EHCI_PORTSC_RESET;
|
||||
writel(regval, &hcor->portsc[port - 1]);
|
||||
|
||||
aic_mdelay(3);
|
||||
aic_mdelay(20);
|
||||
|
||||
regval = readl(&hcor->portsc[port - 1]);
|
||||
regval &= ~EHCI_PORTSC_RESET;
|
||||
writel(regval, &hcor->portsc[port - 1]);
|
||||
aic_mdelay(20);
|
||||
|
||||
/* Wait for the port reset to complete
|
||||
*
|
||||
@@ -935,9 +946,9 @@ int usbh_reset_port(int port, int id)
|
||||
* this bit from a one to a zero ..."
|
||||
*/
|
||||
|
||||
start_us = aic_get_time_us();
|
||||
start_ms = aic_get_time_ms();
|
||||
while ((readl(&hcor->portsc[port - 1]) & EHCI_PORTSC_RESET) != 0) {
|
||||
if ((aic_get_time_us() - start_us) > 3000)
|
||||
if ((aic_get_time_ms() - start_ms) > 100)
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
@@ -1443,7 +1454,7 @@ static int usb_ehci_transfer_wait(int id, struct usb_ehci_epinfo_s *epinfo,
|
||||
|
||||
static void ehci_disable_async(int id)
|
||||
{
|
||||
u32 regval;
|
||||
u32 regval, ret = 0;
|
||||
volatile struct ehci_hcor_s *hcor;
|
||||
|
||||
hcor = (struct ehci_hcor_s *)USB_EHCI_HCOR_BASE(id);
|
||||
@@ -1452,12 +1463,14 @@ static void ehci_disable_async(int id)
|
||||
regval &= ~(EHCI_USBCMD_ASEN);
|
||||
writel(regval, &hcor->usbcmd);
|
||||
|
||||
usb_ehci_wait_usbsts(id, EHCI_USBSTS_ASS, 0, USBHOST_CONTROL_TRANSFER_TIMEOUT);
|
||||
ret = usb_ehci_wait_usbsts(id, EHCI_USBSTS_ASS, 0, USBHOST_CONTROL_TRANSFER_TIMEOUT);
|
||||
if (ret)
|
||||
pr_err("usb ehci wait usbsts failed, ret=%d\n", ret);
|
||||
}
|
||||
|
||||
static void ehci_enable_async(int id)
|
||||
{
|
||||
u32 regval;
|
||||
u32 regval, ret = 0;
|
||||
volatile struct ehci_hcor_s *hcor;
|
||||
|
||||
hcor = (struct ehci_hcor_s *)USB_EHCI_HCOR_BASE(id);
|
||||
@@ -1470,7 +1483,9 @@ static void ehci_enable_async(int id)
|
||||
regval |= (EHCI_USBCMD_ASEN);
|
||||
writel(regval, &hcor->usbcmd);
|
||||
|
||||
usb_ehci_wait_usbsts(id, EHCI_USBSTS_ASS, EHCI_USBSTS_ASS, USBHOST_CONTROL_TRANSFER_TIMEOUT);
|
||||
ret = usb_ehci_wait_usbsts(id, EHCI_USBSTS_ASS, EHCI_USBSTS_ASS, USBHOST_CONTROL_TRANSFER_TIMEOUT);
|
||||
if (ret)
|
||||
pr_err("usb ehci wait usbsts failed, ret=%d\n", ret);
|
||||
}
|
||||
|
||||
static int usb_ehci_control_init(struct usb_ehci_epinfo_s *epinfo,
|
||||
@@ -1721,6 +1736,7 @@ int usbh_ep_bulk_transfer(usbh_epinfo_t ep, u8 *buffer, u32 buflen, u32 timeout,
|
||||
|
||||
ret = usb_ehci_ioc_setup(epinfo);
|
||||
if (ret < 0) {
|
||||
pr_err("%s, line %d: setup failed.\n", __func__, __LINE__);
|
||||
goto errout_with_setup;
|
||||
}
|
||||
|
||||
@@ -1728,6 +1744,7 @@ int usbh_ep_bulk_transfer(usbh_epinfo_t ep, u8 *buffer, u32 buflen, u32 timeout,
|
||||
|
||||
ret = usb_ehci_bulk_init(epinfo, buffer, buflen);
|
||||
if (ret < 0) {
|
||||
pr_err("%s, line %d: setup failed.\n", __func__, __LINE__);
|
||||
goto errout_with_iocwait;
|
||||
}
|
||||
|
||||
@@ -1736,6 +1753,7 @@ int usbh_ep_bulk_transfer(usbh_epinfo_t ep, u8 *buffer, u32 buflen, u32 timeout,
|
||||
/* And wait for the transfer to complete */
|
||||
ret = usb_ehci_transfer_wait(id, epinfo, timeout);
|
||||
if (ret < 0) {
|
||||
pr_err("%s, line %d: wait tmo.\n", __func__, __LINE__);
|
||||
goto errout_with_iocwait;
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -78,17 +78,23 @@ static inline int usbh_msc_scsi_testunitready(struct usbh_msc *msc_class)
|
||||
|
||||
usbh_msc_cbw_dump(cbw);
|
||||
/* Send the CBW */
|
||||
aicos_mdelay(50);
|
||||
nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (u8 *)cbw,
|
||||
USB_SIZEOF_MSC_CBW,
|
||||
CONFIG_USBHOST_MSC_TIMEOUT, msc_class->id);
|
||||
if (nbytes < 0)
|
||||
if (nbytes < 0) {
|
||||
pr_err("Testunitready:Failed to send CBW,ret:%d\n", nbytes);
|
||||
goto out;
|
||||
}
|
||||
/* Receive the CSW */
|
||||
aicos_mdelay(50);
|
||||
nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer,
|
||||
USB_SIZEOF_MSC_CSW,
|
||||
CONFIG_USBHOST_MSC_TIMEOUT, msc_class->id);
|
||||
if (nbytes >= 0) {
|
||||
usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer);
|
||||
} else {
|
||||
pr_err("Testunitready:Failed to receive CSW,ret:%d\n", nbytes);
|
||||
}
|
||||
out:
|
||||
return nbytes < 0 ? (int)nbytes : 0;
|
||||
@@ -152,23 +158,30 @@ static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
|
||||
|
||||
usbh_msc_cbw_dump(cbw);
|
||||
/* Send the CBW */
|
||||
aicos_mdelay(20);
|
||||
nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (u8 *)cbw,
|
||||
USB_SIZEOF_MSC_CBW,
|
||||
CONFIG_USBHOST_MSC_TIMEOUT, msc_class->id);
|
||||
if (nbytes < 0)
|
||||
if (nbytes < 0) {
|
||||
pr_err("Inquiry:Failed to send CBW,ret:%d\n", nbytes);
|
||||
goto out;
|
||||
}
|
||||
/* Receive the sense data response */
|
||||
aicos_mdelay(20);
|
||||
nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer,
|
||||
SCSIRESP_INQUIRY_SIZEOF,
|
||||
CONFIG_USBHOST_MSC_TIMEOUT, msc_class->id);
|
||||
if (nbytes < 0)
|
||||
goto out;
|
||||
/* Receive the CSW */
|
||||
aicos_mdelay(20);
|
||||
nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer,
|
||||
USB_SIZEOF_MSC_CSW,
|
||||
CONFIG_USBHOST_MSC_TIMEOUT, msc_class->id);
|
||||
if (nbytes >= 0) {
|
||||
usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer);
|
||||
} else {
|
||||
pr_err("Inquiry:Failed to receive CSW,ret:%d\n", nbytes);
|
||||
}
|
||||
out:
|
||||
return nbytes < 0 ? (int)nbytes : 0;
|
||||
@@ -191,26 +204,35 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
|
||||
|
||||
usbh_msc_cbw_dump(cbw);
|
||||
/* Send the CBW */
|
||||
aicos_mdelay(20);
|
||||
nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (u8 *)cbw,
|
||||
USB_SIZEOF_MSC_CBW,
|
||||
CONFIG_USBHOST_MSC_TIMEOUT, msc_class->id);
|
||||
if (nbytes < 0)
|
||||
if (nbytes < 0) {
|
||||
pr_err("Readcapacity10:Failed to send CBW,ret:%d\n", nbytes);
|
||||
goto out;
|
||||
}
|
||||
/* Receive the sense data response */
|
||||
aicos_mdelay(20);
|
||||
nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer,
|
||||
SCSIRESP_READCAPACITY10_SIZEOF,
|
||||
CONFIG_USBHOST_MSC_TIMEOUT, msc_class->id);
|
||||
if (nbytes < 0)
|
||||
if (nbytes < 0) {
|
||||
pr_err("Readcapacity10:Failed to receive data response,ret:%d\n", nbytes);
|
||||
goto out;
|
||||
}
|
||||
/* Save the capacity information */
|
||||
msc_class->blocknum = GET_BE32(&msc_class->tx_buffer[0]) + 1;
|
||||
msc_class->blocksize = GET_BE32(&msc_class->tx_buffer[4]);
|
||||
/* Receive the CSW */
|
||||
aicos_mdelay(20);
|
||||
nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer,
|
||||
USB_SIZEOF_MSC_CSW,
|
||||
CONFIG_USBHOST_MSC_TIMEOUT, msc_class->id);
|
||||
if (nbytes >= 0) {
|
||||
usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer);
|
||||
} else {
|
||||
pr_err("Readcapacity10:Failed to receive CSW,ret:%d\n", nbytes);
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -310,11 +332,13 @@ int usbh_msc_connect(struct usbh_hubport *hport, u8 intf, int id)
|
||||
pr_err("Fail to scsi_testunitready\r\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = usbh_msc_scsi_inquiry(msc_class);
|
||||
if (ret < 0) {
|
||||
pr_err("Fail to scsi_inquiry\r\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = usbh_msc_scsi_readcapacity10(msc_class);
|
||||
if (ret < 0) {
|
||||
pr_err("Fail to scsi_readcapacity10\r\n");
|
||||
|
||||
@@ -70,7 +70,7 @@ struct CSW {
|
||||
|
||||
/*Length of template descriptor: 23 bytes*/
|
||||
#define MSC_DESCRIPTOR_LEN (9 + 7 + 7)
|
||||
#define CONFIG_USBHOST_MSC_TIMEOUT 2000
|
||||
#define CONFIG_USBHOST_MSC_TIMEOUT 2000000
|
||||
|
||||
#define SET_BE32(field, value) \
|
||||
do { \
|
||||
|
||||
@@ -101,7 +101,7 @@ int usbh_get_connect_id(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
aicos_udelay(1500);
|
||||
aicos_mdelay(2);
|
||||
ret = usbh_portchange_wait(id);
|
||||
if (ret) {
|
||||
pr_warn("usb %d port change wait failed.\n", id);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <stdio.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
@@ -43,6 +43,16 @@ struct tiny_console {
|
||||
|
||||
static struct tiny_console *g_console = NULL;
|
||||
|
||||
void show_version(void)
|
||||
{
|
||||
char ver[] = PRJ_CHIP;
|
||||
|
||||
ver[0] = toupper(ver[0]);
|
||||
printf("Welcome to ArtInChip Luban-Lite %d.%d.%d [Baremetal %s Inside]\n",
|
||||
LL_VERSION, LL_SUBVERSION, LL_REVISION, ver);
|
||||
printf("Built on %s %s\n", __DATE__, __TIME__);
|
||||
}
|
||||
|
||||
static int putnchar(const char *str, int n)
|
||||
{
|
||||
int i;
|
||||
@@ -153,6 +163,12 @@ static int console_history(MAYBE_UNUSED(int argc), MAYBE_UNUSED(char *argv[]))
|
||||
return CONSOLE_OK;
|
||||
}
|
||||
|
||||
static int console_version(MAYBE_UNUSED(int argc), MAYBE_UNUSED(char *argv[]))
|
||||
{
|
||||
show_version();
|
||||
return CONSOLE_OK;
|
||||
}
|
||||
|
||||
static int dummy_proc(MAYBE_UNUSED(int argc), MAYBE_UNUSED(char *argv[]))
|
||||
{
|
||||
return CONSOLE_OK;
|
||||
@@ -963,6 +979,7 @@ void console_init(void)
|
||||
|
||||
console_register_cmd("help", console_help, "Show all commands.");
|
||||
console_register_cmd("history", console_history, "Show history.");
|
||||
console_register_cmd("version", console_version, "Show version.");
|
||||
|
||||
for (p = cmd_start; p < cmd_end; p++) {
|
||||
if (p->initialized)
|
||||
@@ -991,3 +1008,28 @@ int console_get_ctrlc(void)
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int console_confirm_yesno(void)
|
||||
{
|
||||
int i;
|
||||
char str_input[5];
|
||||
|
||||
i = 0;
|
||||
while (i < sizeof(str_input)) {
|
||||
str_input[i] = getchar();
|
||||
if (str_input[i] != 0xff) {
|
||||
printf("%c", str_input[i]);
|
||||
if (str_input[i] == '\r')
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
printf("\n\n");
|
||||
|
||||
if (strncmp(str_input, "y\r", 2) == 0 ||
|
||||
strncmp(str_input, "Y\r", 2) == 0 ||
|
||||
strncmp(str_input, "yes\r", 4) == 0 ||
|
||||
strncmp(str_input, "YES\r", 4) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -61,6 +61,27 @@ int efuse_read(u32 addr, void *data, u32 size)
|
||||
return (int)(size - rest);
|
||||
}
|
||||
|
||||
int efuse_read_chip_id(void *data)
|
||||
{
|
||||
int version = 0;
|
||||
|
||||
version = hal_efuse_get_version();
|
||||
switch (version) {
|
||||
case 0x100:
|
||||
case 0x101:
|
||||
case 0x102:
|
||||
case 0x103:
|
||||
case 0x105:
|
||||
efuse_read(0x10, data, 0x10);
|
||||
break;
|
||||
default:
|
||||
pr_err("not support read chip id");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int efuse_program(u32 addr, const void *data, u32 size)
|
||||
{
|
||||
u32 wid, wval, rest, cnt;
|
||||
|
||||
@@ -238,6 +238,9 @@ struct mtd_partition *mtd_parts_parse(char *parts)
|
||||
char *p;
|
||||
p = parts;
|
||||
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
while ((*p != '\0') && (*p != ':'))
|
||||
p++;
|
||||
if (*p != ':') {
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
* dwj <weijie.ding@artinchip.com>
|
||||
*/
|
||||
|
||||
#define PRCM_CPU_STATUS 0x8800010C
|
||||
#define PRCM_SE_CONTEXT_ADDR 0x88000114
|
||||
#define PRCM_SESS_CPU_STATUS 0x88000114
|
||||
#define PRCM_SE_CONTEXT_ADDR 0x88000120
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
@@ -40,14 +40,13 @@ se_save_context_and_suspend:
|
||||
mfcr r1, cr<15, 1> //save INT-sp
|
||||
stw r1, (r0, 104)
|
||||
|
||||
/* save se context addr to 0x88000114 */
|
||||
/* save se context addr to PRCM_SE_CONTEXT_ADDR */
|
||||
lrw r1, PRCM_SE_CONTEXT_ADDR
|
||||
stw r0, (r1, 0)
|
||||
|
||||
/* Update CPU status to PRCM bank register */
|
||||
lrw r1, PRCM_CPU_STATUS
|
||||
ldw r2, (r1, 0)
|
||||
ori r2, r2, 0x4
|
||||
lrw r1, PRCM_SESS_CPU_STATUS
|
||||
lrw r2, 1
|
||||
stw r2, (r1, 0)
|
||||
|
||||
sync
|
||||
@@ -89,15 +88,14 @@ se_restore_context_and_resume:
|
||||
ldw r1, (r0, 104)
|
||||
mtcr r1, cr<15, 1>
|
||||
|
||||
/* clear se context addr to 0 in 0x88000114 */
|
||||
/* clear se context addr to 0 in PRCM_SE_CONTEXT_ADDR */
|
||||
lrw r1, PRCM_SE_CONTEXT_ADDR
|
||||
lrw r2, 0
|
||||
stw r2, (r1, 0)
|
||||
|
||||
/* clear CPU status to PRCM bank register */
|
||||
lrw r1, PRCM_CPU_STATUS
|
||||
ldw r2, (r1, 0)
|
||||
bclri r2, 0x2 //bit2 clear
|
||||
lrw r1, PRCM_SESS_CPU_STATUS
|
||||
lrw r2, 0
|
||||
stw r2, (r1, 0)
|
||||
|
||||
/* restore r1~r15 */
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Artinchip Technology Co., Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include <uart.h>
|
||||
#ifdef AICUPG_LOG_BUFFER_SUPPORT
|
||||
#include <log_buf.h>
|
||||
#endif
|
||||
|
||||
#define PORT console_uart_id
|
||||
static int console_uart_id;
|
||||
@@ -21,6 +29,10 @@ void stdio_unset_uart(int id)
|
||||
|
||||
int putchar_port(int c)
|
||||
{
|
||||
#ifdef AICUPG_LOG_BUFFER_SUPPORT
|
||||
log_buf_write((char *)&c, 1);
|
||||
#endif
|
||||
|
||||
if (enable_uart_id == console_uart_id) {
|
||||
if (c == '\n')
|
||||
uart_putchar(PORT, '\r');
|
||||
|
||||
@@ -20,10 +20,6 @@
|
||||
#define MAX_MMC_DEV_NUM 3
|
||||
#define CONFIG_SYS_MMC_MAX_BLK_COUNT 300
|
||||
|
||||
#define be32_to_cpu(x) \
|
||||
((0x000000ff & ((x) >> 24)) | (0x0000ff00 & ((x) >> 8)) | \
|
||||
(0x00ff0000 & ((x) << 8)) | (0xff000000 & ((x) << 24)))
|
||||
|
||||
static void *mmc_dev[MAX_MMC_DEV_NUM];
|
||||
static struct aic_sdmc_pdata sdmc_pdata[] = {
|
||||
#if defined(AIC_USING_SDMC0)
|
||||
@@ -299,8 +295,59 @@ static int mmc_send_ext_csd(struct aic_sdmc *host, u8 *ext_csd)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mmc_switch(struct aic_sdmc *host, u8 set, u8 index, u8 value)
|
||||
{
|
||||
struct aic_sdmc_cmd cmd = {0};
|
||||
int err;
|
||||
|
||||
cmd.cmd_code = MMC_CMD_SWITCH;
|
||||
cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
|
||||
(index << 16) | (value << 8) | set;
|
||||
|
||||
err = mmc_send_cmd(host, &cmd, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mmc_select_bus_width(struct aic_sdmc *host)
|
||||
{
|
||||
int err = 0;
|
||||
u32 ext_csd_bus_width;
|
||||
|
||||
/* buswidth 1 not need to switch */
|
||||
if (host->pdata->buswidth == SDMC_CTYPE_1BIT)
|
||||
return 0;
|
||||
else if (host->dev->card_caps & MMC_MODE_4BIT &&
|
||||
host->pdata->buswidth == SDMC_CTYPE_4BIT)
|
||||
/* Set the card to use 4 bit*/
|
||||
ext_csd_bus_width = EXT_CSD_BUS_WIDTH_4;
|
||||
else if (host->dev->card_caps & MMC_MODE_8BIT &&
|
||||
host->pdata->buswidth == SDMC_CTYPE_8BIT)
|
||||
/* Set the card to use 8 bit*/
|
||||
ext_csd_bus_width = EXT_CSD_BUS_WIDTH_8;
|
||||
else
|
||||
/* Default use 1 bit */
|
||||
ext_csd_bus_width = EXT_CSD_BUS_WIDTH_1;
|
||||
|
||||
/* card configuration */
|
||||
err = mmc_switch(host, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_BUS_WIDTH,
|
||||
ext_csd_bus_width);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* host configuration */
|
||||
aic_sdmc_set_cfg(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mmc_get_capabilities(struct aic_sdmc *host, u8 *ext_csd)
|
||||
{
|
||||
char cardtype = ext_csd[EXT_CSD_CARD_TYPE];
|
||||
|
||||
host->dev->card_caps = 0;
|
||||
|
||||
/* Only version 4 supports high-speed */
|
||||
@@ -308,8 +355,13 @@ static int mmc_get_capabilities(struct aic_sdmc *host, u8 *ext_csd)
|
||||
return 0;
|
||||
|
||||
/* Default is 4-line mode */
|
||||
host->dev->card_caps |= MMC_MODE_4BIT;
|
||||
host->dev->card_caps |= MMC_MODE_HS;
|
||||
host->dev->card_caps |= MMC_MODE_4BIT | MMC_MODE_HC;
|
||||
|
||||
if (cardtype & EXT_CSD_CARD_TYPE_26)
|
||||
host->dev->card_caps |= MMC_MODE_HS;
|
||||
|
||||
if (cardtype & EXT_CSD_CARD_TYPE_52)
|
||||
host->dev->card_caps |= MMC_MODE_HS_52MHz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -535,10 +587,13 @@ static int mmc_get_csd(struct aic_sdmc *host)
|
||||
erase_gmul = (cmd.resp[2] & 0x000003e0) >> 5;
|
||||
host->dev->erase_grp_size = (erase_gsz + 1) * (erase_gmul + 1);
|
||||
|
||||
capacity = (csize + 1) << (cmult + 2);
|
||||
capacity *= host->dev->read_bl_len;
|
||||
capacity = (csize + 1) << (cmult + 2);
|
||||
capacity *= host->dev->read_bl_len;
|
||||
host->dev->card_capacity = (u32)(capacity >> 10); /* in KB */
|
||||
|
||||
if (host->dev->read_bl_len > MMC_MAX_BLOCK_LEN)
|
||||
host->dev->read_bl_len = MMC_MAX_BLOCK_LEN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -569,6 +624,10 @@ static int sd_startup(struct aic_sdmc *host)
|
||||
host->pdata->buswidth == SDMC_CTYPE_4BIT) {
|
||||
sd_select_bus_width(host, 4);
|
||||
aic_sdmc_set_cfg(host);
|
||||
} else {
|
||||
host->pdata->buswidth = SDMC_CTYPE_1BIT;
|
||||
sd_select_bus_width(host, 1);
|
||||
aic_sdmc_set_cfg(host);
|
||||
}
|
||||
|
||||
if (host->dev->card_caps & MMC_MODE_HS) {
|
||||
@@ -592,7 +651,7 @@ static int emmc_startup(struct aic_sdmc *host)
|
||||
/* check ext_csd version and capacity */
|
||||
err = mmc_send_ext_csd(host, ext_csd);
|
||||
/* update mmcdev version */
|
||||
switch (ext_csd[192]) {
|
||||
switch (ext_csd[EXT_CSD_REV]) {
|
||||
case 0:
|
||||
host->dev->version = MMC_VERSION_4;
|
||||
break;
|
||||
@@ -620,8 +679,8 @@ static int emmc_startup(struct aic_sdmc *host)
|
||||
}
|
||||
|
||||
/* Check Read only ext_csd[160] whether support partition. */
|
||||
if (ext_csd[160] & PART_SUPPORT)
|
||||
host->dev->part_config = ext_csd[179];
|
||||
if (ext_csd[EXT_CSD_PARTITION_SUPPORT] & PART_SUPPORT)
|
||||
host->dev->part_config = ext_csd[EXT_CSD_PART_CONF];
|
||||
}
|
||||
|
||||
if (host->dev->version >= MMC_VERSION_4_2) {
|
||||
@@ -648,16 +707,12 @@ static int emmc_startup(struct aic_sdmc *host)
|
||||
/* Restrict card's capabilities by what the host can do */
|
||||
host->dev->card_caps &= host->dev->host_caps;
|
||||
|
||||
if (host->dev->card_caps & MMC_MODE_4BIT &&
|
||||
host->pdata->buswidth == SDMC_CTYPE_4BIT) {
|
||||
/* Set the card to use 4 bit*/
|
||||
aic_sdmc_set_cfg(host);
|
||||
} else if (host->dev->card_caps & MMC_MODE_8BIT &&
|
||||
host->pdata->buswidth == SDMC_CTYPE_8BIT) {
|
||||
/* Set the card to use 8 bit*/
|
||||
aic_sdmc_set_cfg(host);
|
||||
}
|
||||
/* Select bus width */
|
||||
err = mmc_select_bus_width(host);
|
||||
if (err != 0)
|
||||
return err;
|
||||
|
||||
/* Select clock */
|
||||
if (host->dev->card_caps & MMC_MODE_HS) {
|
||||
if (host->dev->card_caps & MMC_MODE_HS_52MHz)
|
||||
host->dev->clock = 52000000;
|
||||
@@ -686,6 +741,8 @@ static int mmc_go_identify_mode(struct aic_sdmc *host)
|
||||
|
||||
err = mmc_send_cmd(host, &cmd, NULL);
|
||||
|
||||
memcpy(host->cid, cmd.resp, 16);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -971,10 +1028,10 @@ u32 mmc_berase(struct aic_sdmc *host, u32 start, u32 blkcnt)
|
||||
int err = 0;
|
||||
u32 blk = 0, blk_r = 0;
|
||||
u64 timeout = 1000000;
|
||||
u64 start_us = aic_get_time_us();
|
||||
u64 start_us = 0;
|
||||
|
||||
pr_err("host->dev->erase_grp_size:%d\n", host->dev->erase_grp_size);
|
||||
while (blk < blkcnt) {
|
||||
start_us = aic_get_time_us();
|
||||
blk_r = ((blkcnt - blk) > host->dev->erase_grp_size) ?
|
||||
host->dev->erase_grp_size :
|
||||
(blkcnt - blk);
|
||||
@@ -1000,7 +1057,7 @@ void mmc_setup_cfg(struct aic_sdmc *host)
|
||||
{
|
||||
host->dev->freq_min = SDMC_CLOCK_MIN;
|
||||
host->dev->freq_max = SDMC_CLOCK_MAX;
|
||||
host->dev->host_caps = MMC_MODE_HC;
|
||||
host->dev->host_caps = MMC_MODE_HC | MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
|
||||
host->dev->valid_ocr = MMC_VDD_32_33 | MMC_VDD_33_34;
|
||||
host->dev->voltages = MMC_VDD_29_30 | MMC_VDD_30_31 | MMC_VDD_31_32 |
|
||||
MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_34_35 |
|
||||
@@ -1093,6 +1150,23 @@ struct aic_sdmc *find_mmc_dev_by_index(int id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s32 mmc_switch_part(struct aic_sdmc *host, u32 part_num)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (part_num == MMC_PART_RPMB)
|
||||
err = mmc_switch(host, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF, part_num);
|
||||
else
|
||||
err = mmc_select_bus_width(host);
|
||||
|
||||
if (err) {
|
||||
pr_err("mmc switch part %d failed.\n", part_num);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 mmc_init(int id)
|
||||
{
|
||||
struct aic_sdmc *host = NULL;
|
||||
|
||||
572
bsp/artinchip/drv_bare/sdmc/rpmb.c
Normal file
572
bsp/artinchip/drv_bare/sdmc/rpmb.c
Normal file
@@ -0,0 +1,572 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Artinchip Technology Co., Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Xiong Hao <hao.xiong@artinchip.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <aic_common.h>
|
||||
#include <aic_core.h>
|
||||
#include <aic_soc.h>
|
||||
#include <aic_hal.h>
|
||||
#include <mmc.h>
|
||||
#include "sdmc.h"
|
||||
#include "rpmb_sha256.h"
|
||||
|
||||
/* Request codes */
|
||||
#define RPMB_REQ_KEY 1
|
||||
#define RPMB_REQ_WCOUNTER 2
|
||||
#define RPMB_REQ_WRITE_DATA 3
|
||||
#define RPMB_REQ_READ_DATA 4
|
||||
#define RPMB_REQ_STATUS 5
|
||||
|
||||
/* Response code */
|
||||
#define RPMB_RESP_KEY 0x0100
|
||||
#define RPMB_RESP_WCOUNTER 0x0200
|
||||
#define RPMB_RESP_WRITE_DATA 0x0300
|
||||
#define RPMB_RESP_READ_DATA 0x0400
|
||||
|
||||
/* Error codes */
|
||||
#define RPMB_OK 0
|
||||
#define RPMB_ERR_GENERAL 1
|
||||
#define RPMB_ERR_AUTH 2
|
||||
#define RPMB_ERR_COUNTER 3
|
||||
#define RPMB_ERR_ADDRESS 4
|
||||
#define RPMB_ERR_WRITE 5
|
||||
#define RPMB_ERR_READ 6
|
||||
#define RPMB_ERR_KEY 7
|
||||
#define RPMB_ERR_CNT_EXPIRED 0x80
|
||||
#define RPMB_ERR_MSK 0x7
|
||||
|
||||
/* Sizes of RPMB data frame */
|
||||
#define RPMB_SZ_STUFF 196
|
||||
#define RPMB_SZ_MAC 32
|
||||
#define RPMB_SZ_DATA 256
|
||||
#define RPMB_SZ_NONCE 16
|
||||
|
||||
#define SHA256_BLOCK_SIZE 64
|
||||
|
||||
/* Error messages */
|
||||
static const char *const rpmb_err_msg[] = {
|
||||
"",
|
||||
"General failure",
|
||||
"Authentication failure",
|
||||
"Counter failure",
|
||||
"Address failure",
|
||||
"Write failure",
|
||||
"Read failure",
|
||||
"Authentication key not yet programmed",
|
||||
};
|
||||
|
||||
/* Structure of RPMB data frame. */
|
||||
struct s_rpmb {
|
||||
unsigned char stuff[RPMB_SZ_STUFF];
|
||||
unsigned char mac[RPMB_SZ_MAC];
|
||||
unsigned char data[RPMB_SZ_DATA];
|
||||
unsigned char nonce[RPMB_SZ_NONCE];
|
||||
unsigned int write_counter;
|
||||
unsigned short address;
|
||||
unsigned short block_count;
|
||||
unsigned short result;
|
||||
unsigned short request;
|
||||
};
|
||||
|
||||
static void mmc_trace_before_send(struct aic_sdmc_cmd *cmd)
|
||||
{
|
||||
#ifdef SDMC_DUMP_CMD
|
||||
printf("CMD_SEND: %d\n", cmd->cmd_code);
|
||||
printf("\t\tARG\t\t\t 0x%08x\n", cmd->arg);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void mmc_trace_after_send(struct aic_sdmc_cmd *cmd)
|
||||
{
|
||||
#ifdef SDMC_DUMP_CMD
|
||||
int i;
|
||||
u8 *ptr;
|
||||
|
||||
switch (cmd->resp_type) {
|
||||
case MMC_RSP_NONE:
|
||||
printf("\t\tRSP_NONE\n\n");
|
||||
break;
|
||||
case MMC_RSP_R1:
|
||||
printf("\t\tRSP_R1,5,6,7 \t\t 0x%08x \n", cmd->resp[0]);
|
||||
break;
|
||||
case MMC_RSP_R1b:
|
||||
printf("\t\tRSP_R1B\t\t 0x%08x \n", cmd->resp[0]);
|
||||
break;
|
||||
case MMC_RSP_R2:
|
||||
printf("\t\tRSP_R2\t\t\t 0x%08x \n", cmd->resp[0]);
|
||||
printf("\t\t \t\t 0x%08x \n", cmd->resp[1]);
|
||||
printf("\t\t \t\t 0x%08x \n", cmd->resp[2]);
|
||||
printf("\t\t \t\t 0x%08x \n", cmd->resp[3]);
|
||||
printf("\n");
|
||||
printf("\t\t\t\t\tDUMPING DATA\n\n");
|
||||
for (i = 0; i < 4; i++) {
|
||||
int j;
|
||||
printf("\t\t\t\t\t%03d - ", i * 4);
|
||||
ptr = (u8 *)&cmd->resp[i];
|
||||
ptr += 3;
|
||||
for (j = 0; j < 4; j++)
|
||||
printf("%02x ", *ptr--);
|
||||
printf("\n");
|
||||
}
|
||||
break;
|
||||
case MMC_RSP_R3:
|
||||
printf("\t\tRSP_R3,4\t\t 0x%08x \n", cmd->resp[0]);
|
||||
break;
|
||||
default:
|
||||
printf("\t\tERROR MMCSD rsp not supported 0x%x\n", cmd->resp_type);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int mmc_send_cmd(struct aic_sdmc *host, struct aic_sdmc_cmd *cmd,
|
||||
struct aic_sdmc_data *data)
|
||||
{
|
||||
memset(cmd->resp, 0, sizeof(cmd->resp));
|
||||
|
||||
mmc_trace_before_send(cmd);
|
||||
aic_sdmc_request(host, cmd, data);
|
||||
mmc_trace_after_send(cmd);
|
||||
|
||||
return cmd->err;
|
||||
}
|
||||
|
||||
static int mmc_set_blockcount(struct aic_sdmc *host, unsigned int blockcount,
|
||||
bool is_rel_write)
|
||||
{
|
||||
struct aic_sdmc_cmd cmd = { 0 };
|
||||
|
||||
cmd.cmd_code = MMC_CMD_SET_BLOCK_COUNT;
|
||||
cmd.arg = blockcount & 0x0000FFFF;
|
||||
if (is_rel_write)
|
||||
cmd.arg |= 1 << 31;
|
||||
cmd.resp_type = MMC_RSP_R1;
|
||||
|
||||
return mmc_send_cmd(host, &cmd, NULL);
|
||||
}
|
||||
|
||||
static int mmc_rpmb_request(struct aic_sdmc *host, const struct s_rpmb *s,
|
||||
unsigned int count, bool is_rel_write)
|
||||
{
|
||||
struct aic_sdmc_cmd cmd = { 0 };
|
||||
struct aic_sdmc_data data;
|
||||
int ret;
|
||||
|
||||
ret = mmc_set_blockcount(host, count, is_rel_write);
|
||||
if (ret) {
|
||||
#ifdef SDMC_RPMB_TRACE
|
||||
printf("%s:mmc_set_blockcount-> %d\n", __func__, ret);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
cmd.cmd_code = MMC_CMD_WRITE_MULTIPLE_BLOCK;
|
||||
cmd.arg = 0;
|
||||
cmd.resp_type = MMC_RSP_R1;
|
||||
|
||||
//if (host->quirks & SDHCI_QUIRK_BROKEN_R1B)
|
||||
// cmd.resp_type = MMC_RSP_R1;
|
||||
|
||||
data.buf = (unsigned char *)s;
|
||||
data.blks = 1;
|
||||
data.blksize = MMC_BLOCK_SIZE;
|
||||
data.flags = MMC_DATA_WRITE;
|
||||
|
||||
ret = mmc_send_cmd(host, &cmd, &data);
|
||||
if (ret) {
|
||||
#ifdef SDMC_RPMB_TRACE
|
||||
printf("%s:mmc_send_cmd-> %d\n", __func__, ret);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mmc_rpmb_response(struct aic_sdmc *host, struct s_rpmb *s,
|
||||
unsigned short expected)
|
||||
{
|
||||
struct aic_sdmc_cmd cmd = { 0 };
|
||||
struct aic_sdmc_data data;
|
||||
int ret;
|
||||
|
||||
ret = mmc_set_blockcount(host, 1, false);
|
||||
if (ret) {
|
||||
#ifdef SDMC_RPMB_TRACE
|
||||
printf("%s:mmc_set_blockcount-> %d\n", __func__, ret);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
cmd.cmd_code = MMC_CMD_READ_MULTIPLE_BLOCK;
|
||||
cmd.arg = 0;
|
||||
cmd.resp_type = MMC_RSP_R1;
|
||||
|
||||
data.buf = (unsigned char *)s;
|
||||
data.blks = 1;
|
||||
data.blksize = MMC_BLOCK_SIZE;
|
||||
data.flags = MMC_DATA_READ;
|
||||
|
||||
ret = mmc_send_cmd(host, &cmd, &data);
|
||||
if (ret) {
|
||||
#ifdef SDMC_RPMB_TRACE
|
||||
printf("%s:mmc_send_cmd-> %d\n", __func__, ret);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
/* Check the response and the status */
|
||||
if (be16_to_cpu(s->request) != expected) {
|
||||
#ifdef SDMC_RPMB_TRACE
|
||||
printf("%s:response= %x\n", __func__, be16_to_cpu(s->request));
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
ret = be16_to_cpu(s->result);
|
||||
if (ret) {
|
||||
printf("%s %s\n", rpmb_err_msg[ret & RPMB_ERR_MSK],
|
||||
(ret & RPMB_ERR_CNT_EXPIRED) ? "Write counter has expired" : "");
|
||||
}
|
||||
|
||||
/* Return the status of the command */
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mmc_rpmb_status(struct aic_sdmc *host, unsigned short expected)
|
||||
{
|
||||
ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
|
||||
|
||||
memset(rpmb_frame, 0, sizeof(struct s_rpmb));
|
||||
rpmb_frame->request = cpu_to_be16(RPMB_REQ_STATUS);
|
||||
if (mmc_rpmb_request(host, rpmb_frame, 1, false))
|
||||
return -1;
|
||||
|
||||
/* Read the result */
|
||||
return mmc_rpmb_response(host, rpmb_frame, expected);
|
||||
}
|
||||
|
||||
static void rpmb_hmac(unsigned char *key, unsigned char *buff, int len,
|
||||
unsigned char *output)
|
||||
{
|
||||
sha256_context ctx;
|
||||
int i;
|
||||
unsigned char k_ipad[SHA256_BLOCK_SIZE];
|
||||
unsigned char k_opad[SHA256_BLOCK_SIZE];
|
||||
|
||||
sha256_starts(&ctx);
|
||||
|
||||
/* According to RFC 4634, the HMAC transform looks like:
|
||||
SHA(K XOR opad, SHA(K XOR ipad, text))
|
||||
|
||||
where K is an n byte key.
|
||||
ipad is the byte 0x36 repeated blocksize times
|
||||
opad is the byte 0x5c repeated blocksize times
|
||||
and text is the data being protected.
|
||||
*/
|
||||
|
||||
for (i = 0; i < RPMB_SZ_MAC; i++) {
|
||||
k_ipad[i] = key[i] ^ 0x36;
|
||||
k_opad[i] = key[i] ^ 0x5c;
|
||||
}
|
||||
/* remaining pad bytes are '\0' XOR'd with ipad and opad values */
|
||||
for (; i < SHA256_BLOCK_SIZE; i++) {
|
||||
k_ipad[i] = 0x36;
|
||||
k_opad[i] = 0x5c;
|
||||
}
|
||||
sha256_update(&ctx, k_ipad, SHA256_BLOCK_SIZE);
|
||||
sha256_update(&ctx, buff, len);
|
||||
sha256_finish(&ctx, output);
|
||||
|
||||
/* Init context for second pass */
|
||||
sha256_starts(&ctx);
|
||||
|
||||
/* start with outer pad */
|
||||
sha256_update(&ctx, k_opad, SHA256_BLOCK_SIZE);
|
||||
|
||||
/* then results of 1st hash */
|
||||
sha256_update(&ctx, output, RPMB_SZ_MAC);
|
||||
|
||||
/* finish up 2nd pass */
|
||||
sha256_finish(&ctx, output);
|
||||
}
|
||||
|
||||
int mmc_rpmb_get_counter(struct aic_sdmc *host, unsigned long *pcounter)
|
||||
{
|
||||
int ret;
|
||||
ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
|
||||
|
||||
/* Fill the request */
|
||||
memset(rpmb_frame, 0, sizeof(struct s_rpmb));
|
||||
rpmb_frame->request = cpu_to_be16(RPMB_REQ_WCOUNTER);
|
||||
if (mmc_rpmb_request(host, rpmb_frame, 1, false))
|
||||
return -1;
|
||||
|
||||
/* Read the result */
|
||||
ret = mmc_rpmb_response(host, rpmb_frame, RPMB_RESP_WCOUNTER);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*pcounter = be32_to_cpu(rpmb_frame->write_counter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmc_rpmb_set_key(struct aic_sdmc *host, void *key)
|
||||
{
|
||||
ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
|
||||
/* Fill the request */
|
||||
memset(rpmb_frame, 0, sizeof(struct s_rpmb));
|
||||
rpmb_frame->request = cpu_to_be16(RPMB_REQ_KEY);
|
||||
memcpy(rpmb_frame->mac, key, RPMB_SZ_MAC);
|
||||
|
||||
if (mmc_rpmb_request(host, rpmb_frame, 1, true))
|
||||
return -1;
|
||||
|
||||
/* read the operation status */
|
||||
return mmc_rpmb_status(host, RPMB_RESP_KEY);
|
||||
}
|
||||
|
||||
int mmc_rpmb_read(struct aic_sdmc *host, void *addr, unsigned short blk,
|
||||
unsigned short cnt, unsigned char *key)
|
||||
{
|
||||
ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
/* Fill the request */
|
||||
memset(rpmb_frame, 0, sizeof(struct s_rpmb));
|
||||
rpmb_frame->address = cpu_to_be16(blk + i);
|
||||
rpmb_frame->request = cpu_to_be16(RPMB_REQ_READ_DATA);
|
||||
if (mmc_rpmb_request(host, rpmb_frame, 1, false))
|
||||
break;
|
||||
|
||||
/* Read the result */
|
||||
if (mmc_rpmb_response(host, rpmb_frame, RPMB_RESP_READ_DATA))
|
||||
break;
|
||||
|
||||
/* Check the HMAC if key is provided */
|
||||
if (key) {
|
||||
unsigned char ret_hmac[RPMB_SZ_MAC];
|
||||
|
||||
rpmb_hmac(key, rpmb_frame->data, 284, ret_hmac);
|
||||
if (memcmp(ret_hmac, rpmb_frame->mac, RPMB_SZ_MAC)) {
|
||||
printf("MAC error on block #%d\n", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Copy data */
|
||||
memcpy(addr + i * RPMB_SZ_DATA, rpmb_frame->data, RPMB_SZ_DATA);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int mmc_rpmb_write(struct aic_sdmc *host, void *addr, unsigned short blk,
|
||||
unsigned short cnt, unsigned char *key)
|
||||
{
|
||||
ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
|
||||
unsigned long wcount;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
if (mmc_rpmb_get_counter(host, &wcount)) {
|
||||
printf("Cannot read RPMB write counter\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Fill the request */
|
||||
memset(rpmb_frame, 0, sizeof(struct s_rpmb));
|
||||
memcpy(rpmb_frame->data, addr + i * RPMB_SZ_DATA, RPMB_SZ_DATA);
|
||||
rpmb_frame->address = cpu_to_be16(blk + i);
|
||||
rpmb_frame->block_count = cpu_to_be16(1);
|
||||
rpmb_frame->write_counter = cpu_to_be32(wcount);
|
||||
rpmb_frame->request = cpu_to_be16(RPMB_REQ_WRITE_DATA);
|
||||
/* Computes HMAC */
|
||||
rpmb_hmac(key, rpmb_frame->data, 284, rpmb_frame->mac);
|
||||
|
||||
if (mmc_rpmb_request(host, rpmb_frame, 1, true))
|
||||
break;
|
||||
|
||||
/* Get status */
|
||||
if (mmc_rpmb_status(host, RPMB_RESP_WRITE_DATA))
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static int send_write_mult_block(struct aic_sdmc *host,
|
||||
const struct s_rpmb *frm, unsigned short cnt)
|
||||
{
|
||||
struct aic_sdmc_cmd cmd = {
|
||||
.cmd_code = MMC_CMD_WRITE_MULTIPLE_BLOCK,
|
||||
.resp_type = MMC_RSP_R1,
|
||||
};
|
||||
struct aic_sdmc_data data = {
|
||||
.buf = (unsigned char *)frm,
|
||||
.blks = cnt,
|
||||
.blksize = sizeof(*frm),
|
||||
.flags = MMC_DATA_WRITE,
|
||||
};
|
||||
|
||||
return mmc_send_cmd(host, &cmd, &data);
|
||||
}
|
||||
|
||||
static int send_read_mult_block(struct aic_sdmc *host, struct s_rpmb *frm,
|
||||
unsigned short cnt)
|
||||
{
|
||||
struct aic_sdmc_cmd cmd = {
|
||||
.cmd_code = MMC_CMD_READ_MULTIPLE_BLOCK,
|
||||
.resp_type = MMC_RSP_R1,
|
||||
};
|
||||
struct aic_sdmc_data data = {
|
||||
.buf = (unsigned char *)frm,
|
||||
.blks = cnt,
|
||||
.blksize = sizeof(*frm),
|
||||
.flags = MMC_DATA_READ,
|
||||
};
|
||||
|
||||
return mmc_send_cmd(host, &cmd, &data);
|
||||
}
|
||||
|
||||
static int rpmb_route_write_req(struct aic_sdmc *host, struct s_rpmb *req,
|
||||
unsigned short req_cnt, struct s_rpmb *rsp,
|
||||
unsigned short rsp_cnt)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Send the write request.
|
||||
*/
|
||||
ret = mmc_set_blockcount(host, req_cnt, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = send_write_mult_block(host, req, req_cnt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Read the result of the request.
|
||||
*/
|
||||
ret = mmc_set_blockcount(host, 1, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memset(rsp, 0, sizeof(*rsp));
|
||||
rsp->request = cpu_to_be16(RPMB_REQ_STATUS);
|
||||
ret = send_write_mult_block(host, rsp, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mmc_set_blockcount(host, 1, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return send_read_mult_block(host, rsp, 1);
|
||||
}
|
||||
|
||||
static int rpmb_route_read_req(struct aic_sdmc *host, struct s_rpmb *req,
|
||||
unsigned short req_cnt, struct s_rpmb *rsp,
|
||||
unsigned short rsp_cnt)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Send the read request.
|
||||
*/
|
||||
ret = mmc_set_blockcount(host, 1, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = send_write_mult_block(host, req, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Read the result of the request.
|
||||
*/
|
||||
|
||||
ret = mmc_set_blockcount(host, rsp_cnt, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return send_read_mult_block(host, rsp, rsp_cnt);
|
||||
}
|
||||
|
||||
static int rpmb_route_frames(struct aic_sdmc *host, struct s_rpmb *req,
|
||||
unsigned short req_cnt, struct s_rpmb *rsp,
|
||||
unsigned short rsp_cnt)
|
||||
{
|
||||
unsigned short n;
|
||||
|
||||
/*
|
||||
* If multiple request frames are provided, make sure that all are
|
||||
* of the same type.
|
||||
*/
|
||||
for (n = 1; n < req_cnt; n++)
|
||||
if (req[n].request != req->request)
|
||||
return -EINVAL;
|
||||
|
||||
switch (be16_to_cpu(req->request)) {
|
||||
case RPMB_REQ_KEY:
|
||||
if (req_cnt != 1 || rsp_cnt != 1)
|
||||
return -EINVAL;
|
||||
return rpmb_route_write_req(host, req, req_cnt, rsp, rsp_cnt);
|
||||
|
||||
case RPMB_REQ_WRITE_DATA:
|
||||
if (!req_cnt || rsp_cnt != 1)
|
||||
return -EINVAL;
|
||||
return rpmb_route_write_req(host, req, req_cnt, rsp, rsp_cnt);
|
||||
|
||||
case RPMB_REQ_WCOUNTER:
|
||||
if (req_cnt != 1 || rsp_cnt != 1)
|
||||
return -EINVAL;
|
||||
return rpmb_route_read_req(host, req, req_cnt, rsp, rsp_cnt);
|
||||
|
||||
case RPMB_REQ_READ_DATA:
|
||||
if (req_cnt != 1 || !req_cnt)
|
||||
return -EINVAL;
|
||||
return rpmb_route_read_req(host, req, req_cnt, rsp, rsp_cnt);
|
||||
|
||||
default:
|
||||
pr_debug("Unsupported message type: %d\n",
|
||||
be16_to_cpu(req->request));
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int mmc_rpmb_route_frames(struct aic_sdmc *host, void *req,
|
||||
unsigned long reqlen, void *rsp, unsigned long rsplen)
|
||||
{
|
||||
/*
|
||||
* Whoever crafted the data supplied to this function knows how to
|
||||
* format the PRMB frames and which response is expected. If
|
||||
* there's some unexpected mismatch it's more helpful to report an
|
||||
* error immediately than trying to guess what was the intention
|
||||
* and possibly just delay an eventual error which will be harder
|
||||
* to track down.
|
||||
*/
|
||||
void *rpmb_data = NULL;
|
||||
int ret;
|
||||
|
||||
if (reqlen % sizeof(struct s_rpmb) || rsplen % sizeof(struct s_rpmb))
|
||||
return -EINVAL;
|
||||
|
||||
if (!IS_ALIGNED((uintptr_t)req, ARCH_DMA_MINALIGN)) {
|
||||
/* Memory alignment is required by MMC driver */
|
||||
rpmb_data = malloc(reqlen);
|
||||
if (!rpmb_data)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(rpmb_data, req, reqlen);
|
||||
req = rpmb_data;
|
||||
}
|
||||
|
||||
ret = rpmb_route_frames(host, req, reqlen / sizeof(struct s_rpmb), rsp,
|
||||
rsplen / sizeof(struct s_rpmb));
|
||||
free(rpmb_data);
|
||||
return ret;
|
||||
}
|
||||
283
bsp/artinchip/drv_bare/sdmc/rpmb_sha256.c
Normal file
283
bsp/artinchip/drv_bare/sdmc/rpmb_sha256.c
Normal file
@@ -0,0 +1,283 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* FIPS-180-2 compliant SHA-256 implementation
|
||||
*
|
||||
* Copyright (C) 2001-2003 Christophe Devine
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <aic_common.h>
|
||||
#include "rpmb_sha256.h"
|
||||
|
||||
const uint8_t sha256_der_prefix[SHA256_DER_LEN] = {
|
||||
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
|
||||
0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
|
||||
};
|
||||
|
||||
/*
|
||||
* 32-bit integer manipulation macros (big endian)
|
||||
*/
|
||||
#ifndef GET_UINT32_BE
|
||||
#define GET_UINT32_BE(n, b, i) \
|
||||
{ \
|
||||
(n) = ((unsigned long)(b)[(i)] << 24) | \
|
||||
((unsigned long)(b)[(i) + 1] << 16) | \
|
||||
((unsigned long)(b)[(i) + 2] << 8) | \
|
||||
((unsigned long)(b)[(i) + 3]); \
|
||||
}
|
||||
#endif
|
||||
#ifndef PUT_UINT32_BE
|
||||
#define PUT_UINT32_BE(n, b, i) \
|
||||
{ \
|
||||
(b)[(i)] = (unsigned char)((n) >> 24); \
|
||||
(b)[(i) + 1] = (unsigned char)((n) >> 16); \
|
||||
(b)[(i) + 2] = (unsigned char)((n) >> 8); \
|
||||
(b)[(i) + 3] = (unsigned char)((n)); \
|
||||
}
|
||||
#endif
|
||||
|
||||
void sha256_starts(sha256_context *ctx)
|
||||
{
|
||||
ctx->total[0] = 0;
|
||||
ctx->total[1] = 0;
|
||||
|
||||
ctx->state[0] = 0x6A09E667;
|
||||
ctx->state[1] = 0xBB67AE85;
|
||||
ctx->state[2] = 0x3C6EF372;
|
||||
ctx->state[3] = 0xA54FF53A;
|
||||
ctx->state[4] = 0x510E527F;
|
||||
ctx->state[5] = 0x9B05688C;
|
||||
ctx->state[6] = 0x1F83D9AB;
|
||||
ctx->state[7] = 0x5BE0CD19;
|
||||
}
|
||||
|
||||
static void sha256_process(sha256_context *ctx, const uint8_t data[64])
|
||||
{
|
||||
uint32_t temp1, temp2;
|
||||
uint32_t W[64];
|
||||
uint32_t A, B, C, D, E, F, G, H;
|
||||
|
||||
GET_UINT32_BE(W[0], data, 0);
|
||||
GET_UINT32_BE(W[1], data, 4);
|
||||
GET_UINT32_BE(W[2], data, 8);
|
||||
GET_UINT32_BE(W[3], data, 12);
|
||||
GET_UINT32_BE(W[4], data, 16);
|
||||
GET_UINT32_BE(W[5], data, 20);
|
||||
GET_UINT32_BE(W[6], data, 24);
|
||||
GET_UINT32_BE(W[7], data, 28);
|
||||
GET_UINT32_BE(W[8], data, 32);
|
||||
GET_UINT32_BE(W[9], data, 36);
|
||||
GET_UINT32_BE(W[10], data, 40);
|
||||
GET_UINT32_BE(W[11], data, 44);
|
||||
GET_UINT32_BE(W[12], data, 48);
|
||||
GET_UINT32_BE(W[13], data, 52);
|
||||
GET_UINT32_BE(W[14], data, 56);
|
||||
GET_UINT32_BE(W[15], data, 60);
|
||||
|
||||
#define SHR(x, n) ((x & 0xFFFFFFFF) >> n)
|
||||
#define ROTR(x, n) (SHR(x, n) | (x << (32 - n)))
|
||||
|
||||
#define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
|
||||
#define S1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
|
||||
|
||||
#define S2(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
|
||||
#define S3(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
|
||||
|
||||
#define F0(x, y, z) ((x & y) | (z & (x | y)))
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
|
||||
#define R(t) (W[t] = S1(W[t - 2]) + W[t - 7] + S0(W[t - 15]) + W[t - 16])
|
||||
|
||||
#define P(a, b, c, d, e, f, g, h, x, K) \
|
||||
{ \
|
||||
temp1 = h + S3(e) + F1(e, f, g) + K + x; \
|
||||
temp2 = S2(a) + F0(a, b, c); \
|
||||
d += temp1; \
|
||||
h = temp1 + temp2; \
|
||||
}
|
||||
|
||||
A = ctx->state[0];
|
||||
B = ctx->state[1];
|
||||
C = ctx->state[2];
|
||||
D = ctx->state[3];
|
||||
E = ctx->state[4];
|
||||
F = ctx->state[5];
|
||||
G = ctx->state[6];
|
||||
H = ctx->state[7];
|
||||
|
||||
P(A, B, C, D, E, F, G, H, W[0], 0x428A2F98);
|
||||
P(H, A, B, C, D, E, F, G, W[1], 0x71374491);
|
||||
P(G, H, A, B, C, D, E, F, W[2], 0xB5C0FBCF);
|
||||
P(F, G, H, A, B, C, D, E, W[3], 0xE9B5DBA5);
|
||||
P(E, F, G, H, A, B, C, D, W[4], 0x3956C25B);
|
||||
P(D, E, F, G, H, A, B, C, W[5], 0x59F111F1);
|
||||
P(C, D, E, F, G, H, A, B, W[6], 0x923F82A4);
|
||||
P(B, C, D, E, F, G, H, A, W[7], 0xAB1C5ED5);
|
||||
P(A, B, C, D, E, F, G, H, W[8], 0xD807AA98);
|
||||
P(H, A, B, C, D, E, F, G, W[9], 0x12835B01);
|
||||
P(G, H, A, B, C, D, E, F, W[10], 0x243185BE);
|
||||
P(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3);
|
||||
P(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74);
|
||||
P(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE);
|
||||
P(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7);
|
||||
P(B, C, D, E, F, G, H, A, W[15], 0xC19BF174);
|
||||
P(A, B, C, D, E, F, G, H, R(16), 0xE49B69C1);
|
||||
P(H, A, B, C, D, E, F, G, R(17), 0xEFBE4786);
|
||||
P(G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6);
|
||||
P(F, G, H, A, B, C, D, E, R(19), 0x240CA1CC);
|
||||
P(E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F);
|
||||
P(D, E, F, G, H, A, B, C, R(21), 0x4A7484AA);
|
||||
P(C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC);
|
||||
P(B, C, D, E, F, G, H, A, R(23), 0x76F988DA);
|
||||
P(A, B, C, D, E, F, G, H, R(24), 0x983E5152);
|
||||
P(H, A, B, C, D, E, F, G, R(25), 0xA831C66D);
|
||||
P(G, H, A, B, C, D, E, F, R(26), 0xB00327C8);
|
||||
P(F, G, H, A, B, C, D, E, R(27), 0xBF597FC7);
|
||||
P(E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3);
|
||||
P(D, E, F, G, H, A, B, C, R(29), 0xD5A79147);
|
||||
P(C, D, E, F, G, H, A, B, R(30), 0x06CA6351);
|
||||
P(B, C, D, E, F, G, H, A, R(31), 0x14292967);
|
||||
P(A, B, C, D, E, F, G, H, R(32), 0x27B70A85);
|
||||
P(H, A, B, C, D, E, F, G, R(33), 0x2E1B2138);
|
||||
P(G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC);
|
||||
P(F, G, H, A, B, C, D, E, R(35), 0x53380D13);
|
||||
P(E, F, G, H, A, B, C, D, R(36), 0x650A7354);
|
||||
P(D, E, F, G, H, A, B, C, R(37), 0x766A0ABB);
|
||||
P(C, D, E, F, G, H, A, B, R(38), 0x81C2C92E);
|
||||
P(B, C, D, E, F, G, H, A, R(39), 0x92722C85);
|
||||
P(A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1);
|
||||
P(H, A, B, C, D, E, F, G, R(41), 0xA81A664B);
|
||||
P(G, H, A, B, C, D, E, F, R(42), 0xC24B8B70);
|
||||
P(F, G, H, A, B, C, D, E, R(43), 0xC76C51A3);
|
||||
P(E, F, G, H, A, B, C, D, R(44), 0xD192E819);
|
||||
P(D, E, F, G, H, A, B, C, R(45), 0xD6990624);
|
||||
P(C, D, E, F, G, H, A, B, R(46), 0xF40E3585);
|
||||
P(B, C, D, E, F, G, H, A, R(47), 0x106AA070);
|
||||
P(A, B, C, D, E, F, G, H, R(48), 0x19A4C116);
|
||||
P(H, A, B, C, D, E, F, G, R(49), 0x1E376C08);
|
||||
P(G, H, A, B, C, D, E, F, R(50), 0x2748774C);
|
||||
P(F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5);
|
||||
P(E, F, G, H, A, B, C, D, R(52), 0x391C0CB3);
|
||||
P(D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A);
|
||||
P(C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F);
|
||||
P(B, C, D, E, F, G, H, A, R(55), 0x682E6FF3);
|
||||
P(A, B, C, D, E, F, G, H, R(56), 0x748F82EE);
|
||||
P(H, A, B, C, D, E, F, G, R(57), 0x78A5636F);
|
||||
P(G, H, A, B, C, D, E, F, R(58), 0x84C87814);
|
||||
P(F, G, H, A, B, C, D, E, R(59), 0x8CC70208);
|
||||
P(E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA);
|
||||
P(D, E, F, G, H, A, B, C, R(61), 0xA4506CEB);
|
||||
P(C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7);
|
||||
P(B, C, D, E, F, G, H, A, R(63), 0xC67178F2);
|
||||
|
||||
ctx->state[0] += A;
|
||||
ctx->state[1] += B;
|
||||
ctx->state[2] += C;
|
||||
ctx->state[3] += D;
|
||||
ctx->state[4] += E;
|
||||
ctx->state[5] += F;
|
||||
ctx->state[6] += G;
|
||||
ctx->state[7] += H;
|
||||
}
|
||||
|
||||
void sha256_update(sha256_context *ctx, const uint8_t *input, uint32_t length)
|
||||
{
|
||||
uint32_t left, fill;
|
||||
|
||||
if (!length)
|
||||
return;
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += length;
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if (ctx->total[0] < length)
|
||||
ctx->total[1]++;
|
||||
|
||||
if (left && length >= fill) {
|
||||
memcpy((void *)(ctx->buffer + left), (void *)input, fill);
|
||||
sha256_process(ctx, ctx->buffer);
|
||||
length -= fill;
|
||||
input += fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while (length >= 64) {
|
||||
sha256_process(ctx, input);
|
||||
length -= 64;
|
||||
input += 64;
|
||||
}
|
||||
|
||||
if (length)
|
||||
memcpy((void *)(ctx->buffer + left), (void *)input, length);
|
||||
}
|
||||
|
||||
static uint8_t sha256_padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
void sha256_finish(sha256_context *ctx, uint8_t digest[32])
|
||||
{
|
||||
uint32_t last, padn;
|
||||
uint32_t high, low;
|
||||
uint8_t msglen[8];
|
||||
|
||||
high = ((ctx->total[0] >> 29) | (ctx->total[1] << 3));
|
||||
low = (ctx->total[0] << 3);
|
||||
|
||||
PUT_UINT32_BE(high, msglen, 0);
|
||||
PUT_UINT32_BE(low, msglen, 4);
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = (last < 56) ? (56 - last) : (120 - last);
|
||||
|
||||
sha256_update(ctx, sha256_padding, padn);
|
||||
sha256_update(ctx, msglen, 8);
|
||||
|
||||
PUT_UINT32_BE(ctx->state[0], digest, 0);
|
||||
PUT_UINT32_BE(ctx->state[1], digest, 4);
|
||||
PUT_UINT32_BE(ctx->state[2], digest, 8);
|
||||
PUT_UINT32_BE(ctx->state[3], digest, 12);
|
||||
PUT_UINT32_BE(ctx->state[4], digest, 16);
|
||||
PUT_UINT32_BE(ctx->state[5], digest, 20);
|
||||
PUT_UINT32_BE(ctx->state[6], digest, 24);
|
||||
PUT_UINT32_BE(ctx->state[7], digest, 28);
|
||||
}
|
||||
|
||||
/*
|
||||
* Output = SHA-256( input buffer ). Trigger the watchdog every 'chunk_sz'
|
||||
* bytes of input processed.
|
||||
*/
|
||||
void sha256_csum_wd(const unsigned char *input, unsigned int ilen,
|
||||
unsigned char *output, unsigned int chunk_sz)
|
||||
{
|
||||
sha256_context ctx;
|
||||
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
|
||||
const unsigned char *end;
|
||||
unsigned char *curr;
|
||||
int chunk;
|
||||
#endif
|
||||
|
||||
sha256_starts(&ctx);
|
||||
|
||||
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
|
||||
curr = (unsigned char *)input;
|
||||
end = input + ilen;
|
||||
while (curr < end) {
|
||||
chunk = end - curr;
|
||||
if (chunk > chunk_sz)
|
||||
chunk = chunk_sz;
|
||||
sha256_update(&ctx, curr, chunk);
|
||||
curr += chunk;
|
||||
WATCHDOG_RESET();
|
||||
}
|
||||
#else
|
||||
sha256_update(&ctx, input, ilen);
|
||||
#endif
|
||||
|
||||
sha256_finish(&ctx, output);
|
||||
}
|
||||
35
bsp/artinchip/drv_bare/sdmc/rpmb_sha256.h
Normal file
35
bsp/artinchip/drv_bare/sdmc/rpmb_sha256.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Artinchip Technology Co., Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Xiong Hao <hao.xiong@artinchip.com>
|
||||
*/
|
||||
|
||||
#ifndef __BL_SHA256_H_
|
||||
#define __BL_SHA256_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SHA256_SUM_LEN 32
|
||||
#define SHA256_DER_LEN 19
|
||||
|
||||
extern const uint8_t sha256_der_prefix[];
|
||||
|
||||
/* Reset watchdog each time we process this many bytes */
|
||||
#define CHUNKSZ_SHA256 (64 * 1024)
|
||||
|
||||
typedef struct {
|
||||
uint32_t total[2];
|
||||
uint32_t state[8];
|
||||
uint8_t buffer[64];
|
||||
} sha256_context;
|
||||
|
||||
void sha256_starts(sha256_context *ctx);
|
||||
void sha256_update(sha256_context *ctx, const uint8_t *input, uint32_t length);
|
||||
void sha256_finish(sha256_context *ctx, uint8_t digest[32]);
|
||||
|
||||
void sha256_csum_wd(const unsigned char *input, unsigned int ilen,
|
||||
unsigned char *output, unsigned int chunk_sz);
|
||||
|
||||
#endif /* __BL_SHA256_H_ */
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#define SD_CHECK_PIN ("PC.6")
|
||||
|
||||
static bool g_sdcard_hotplug_flag = 0;
|
||||
|
||||
irqreturn_t sdcard_detect_irq_handler(int irq, void *args)
|
||||
{
|
||||
u8 pin;
|
||||
@@ -33,18 +35,10 @@ irqreturn_t sdcard_detect_irq_handler(int irq, void *args)
|
||||
|
||||
if (value) {
|
||||
printf("card removal detected!\n");
|
||||
mmc_deinit(1);
|
||||
#if defined(LPKG_USING_DFS_ELMFAT) && defined(AIC_SDMC_DRV)
|
||||
if (dfs_unmount("/sdcard") < 0)
|
||||
printf("Failed to umount SD Card with FatFS\n");
|
||||
#endif
|
||||
g_sdcard_hotplug_flag = 1;
|
||||
} else {
|
||||
printf("card insertion detected!\n");
|
||||
mmc_init(1);
|
||||
#if defined(LPKG_USING_DFS_ELMFAT) && defined(AIC_SDMC_DRV)
|
||||
if (dfs_mount("sd1", "/sdcard", "elm", 0, DEVICE_TYPE_SDMC_DISK) < 0)
|
||||
printf("Failed to mount SD Card with FatFS\n");
|
||||
#endif
|
||||
g_sdcard_hotplug_flag = 0;
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
@@ -80,3 +74,24 @@ void sdcard_hotplug_init(void)
|
||||
sdcard_detect_pin_init();
|
||||
}
|
||||
|
||||
void sdcard_hotplug_act(void)
|
||||
{
|
||||
static bool last_removal_stat = 0;
|
||||
|
||||
if (g_sdcard_hotplug_flag && !last_removal_stat) {
|
||||
last_removal_stat = 1;
|
||||
mmc_deinit(1);
|
||||
#if defined(LPKG_USING_DFS_ELMFAT) && defined(AIC_SDMC_DRV)
|
||||
if (dfs_unmount("/sdcard") < 0)
|
||||
printf("Failed to umount SD Card with FatFS\n");
|
||||
#endif
|
||||
} else if (!g_sdcard_hotplug_flag && last_removal_stat) {
|
||||
last_removal_stat = 0;
|
||||
mmc_init(1);
|
||||
#if defined(LPKG_USING_DFS_ELMFAT) && defined(AIC_SDMC_DRV)
|
||||
if (dfs_mount("sd1", "/sdcard", "elm", 0, DEVICE_TYPE_SDMC_DISK) < 0)
|
||||
printf("Failed to mount SD Card with FatFS\n");
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,9 +66,10 @@ static int aic_sdmc_data_transfer(struct aic_sdmc *host,
|
||||
for (;;) {
|
||||
mask = hal_sdmc_int_stat(&host->host);
|
||||
if (mask & (SDMC_DATA_ERR | SDMC_DATA_TOUT)) {
|
||||
pr_err("Data error! size %d/%d, mode %s, status 0x%x\n",
|
||||
pr_err("Data error! size %d/%d, mode %s-%s, status 0x%x\n",
|
||||
size * 4, total,
|
||||
host->fifo_mode ? "FIFO" : "IDMA", mask);
|
||||
host->fifo_mode ? "FIFO" : "IDMA",
|
||||
data->flags == MMC_DATA_READ ? "Read" : "Write", mask);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
@@ -357,7 +358,7 @@ static int aic_sdmc_setup_bus(struct aic_sdmc *host, u32 freq)
|
||||
host->index, aic_sdmc_buswidth(host->pdata->buswidth),
|
||||
sclk / 1000, freq / 1000,
|
||||
div ? sclk / mux / div / 2 / 1000 : sclk / mux / 1000,
|
||||
mux, div);
|
||||
mux, div * 2);
|
||||
|
||||
hal_sdmc_set_div(&host->host, div);
|
||||
hal_sdmc_set_cmd(&host->host,
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <mmc.h>
|
||||
|
||||
// #define SDMC_DUMP_CMD
|
||||
// #define SDMC_RPMB_TRACE
|
||||
|
||||
void aic_sdmc_request(struct aic_sdmc *host, struct aic_sdmc_cmd *cmd,
|
||||
struct aic_sdmc_data *data);
|
||||
|
||||
Reference in New Issue
Block a user