This commit is contained in:
刘可亮
2024-06-04 19:00:30 +08:00
parent 990c72f5be
commit 0a13af6a1d
1668 changed files with 342810 additions and 37726 deletions

View File

@@ -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;

View File

@@ -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");

View File

@@ -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 { \

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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 != ':') {

View File

@@ -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 */

View File

@@ -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');

View File

@@ -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;

View 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;
}

View 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);
}

View 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_ */

View File

@@ -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
}
}

View File

@@ -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,

View File

@@ -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);