[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/bsp/lk/platform/mt2635/debug.c b/src/bsp/lk/platform/mt2635/debug.c
new file mode 100644
index 0000000..da63a05
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/debug.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <stdarg.h>
+#include <reg.h>
+#include <stdio.h>
+#include <kernel/thread.h>
+#include <dev/uart.h>
+#include <platform/debug.h>
+#include <platform/mt2635.h>
+#include <target/debugconfig.h>
+#include <reg.h>
+
+/* DEBUG_UART must be defined to 0 or 1 */
+#if defined(DEBUG_UART) && DEBUG_UART == 0
+#define DEBUG_UART_BASE UART0_BASE
+#elif defined(DEBUG_UART) && DEBUG_UART == 1
+#define DEBUG_UART_BASE UART1_BASE
+#else
+#error define DEBUG_UART to something valid
+#endif
+
+void platform_dputc(char c)
+{
+ if (c == '\n')
+ uart_putc(DEBUG_UART, '\r');
+ uart_putc(DEBUG_UART, c);
+}
+
+int platform_dgetc(char *c, bool wait)
+{
+ int ret = uart_getc(DEBUG_UART, wait);
+ if (ret == -1)
+ return -1;
+ *c = ret;
+ return 0;
+}
+
+void platform_pputc(char c)
+{
+ if (c == '\n')
+ uart_pputc(DEBUG_UART, '\r');
+ uart_pputc(DEBUG_UART, c);
+}
+
+int platform_pgetc(char *c, bool wait)
+{
+ int ret = uart_pgetc(DEBUG_UART);
+ if (ret < 0)
+ return ret;
+ *c = ret;
+ return 0;
+}
+
diff --git a/src/bsp/lk/platform/mt2635/drivers/efuse/vefuse.c b/src/bsp/lk/platform/mt2635/drivers/efuse/vefuse.c
new file mode 100644
index 0000000..25d7181
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/drivers/efuse/vefuse.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include <debug.h>
+#include <printf.h>
+#include <platform/mt_reg_base.h>
+#include <platform/pmic.h>
+#include <reg.h>
+
+
+void enable_vefuse(void)
+{
+ pmic_set_efuse(2000);
+ pmic_enable_efuse(1);
+}
+
+void disable_vefuse(void)
+{
+ pmic_enable_efuse(0);
+}
diff --git a/src/bsp/lk/platform/mt2635/drivers/key/mtk_key.c b/src/bsp/lk/platform/mt2635/drivers/key/mtk_key.c
new file mode 100644
index 0000000..d0ec32d
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/drivers/key/mtk_key.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <reg.h>
+#include <platform/mt_reg_base.h>
+#include <debug.h>
+#include <platform/mtk_key.h>
+
+#define GPIO_DIN84 (PERIPHERAL_BASE_VIRT + 0x211220)
+
+bool check_download_key(void)
+{
+ return (readl(GPIO_DIN84) & (1U << 20)) == 0;
+}
diff --git a/src/bsp/lk/platform/mt2635/drivers/mmc/mmc_core.c b/src/bsp/lk/platform/mt2635/drivers/mmc/mmc_core.c
new file mode 100644
index 0000000..82932f3
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/drivers/mmc/mmc_core.c
@@ -0,0 +1,1196 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*=======================================================================*/
+/* HEADER FILES */
+/*=======================================================================*/
+#include <config.h>
+#include <platform/msdc.h>
+#include <platform/mmc_core.h>
+#include <platform/mmc_rpmb.h>
+#include <platform/mmc_ioctl.h>
+#include <lib/bio.h>
+#include <lib/heap.h>
+#include <lib/partition.h>
+#include <string.h>
+#include <err.h>
+#include <kernel/mutex.h>
+
+#define CMD_RETRIES (5)
+#define CMD_TIMEOUT (100) /* 100ms */
+
+static int mmc_set_ext_csd(struct mmc_card *card, u8 addr, u8 value);
+
+typedef struct {
+ bdev_t bdev;
+ u32 part_id;
+ struct mmc_host *host;
+ struct mmc_card *card;
+} mmc_dev_t;
+
+static const unsigned int tran_exp[] = {
+ 10000, 100000, 1000000, 10000000,
+ 0, 0, 0, 0
+};
+
+static const unsigned char mmc_tran_mant[] = {
+ 0, 10, 12, 13, 15, 20, 26, 30,
+ 35, 40, 45, 52, 55, 60, 70, 80,
+};
+
+static u32 unstuff_bits(u32 *resp, u32 start, u32 size)
+{
+ const u32 __mask = (1 << (size)) - 1;
+ const int __off = 3 - ((start) / 32);
+ const int __shft = (start) & 31;
+ u32 __res;
+
+ __res = resp[__off] >> __shft;
+ if ((size) + __shft >= 32)
+ __res |= resp[__off-1] << (32 - __shft);
+ return __res & __mask;
+}
+
+#define UNSTUFF_BITS(r,s,sz) unstuff_bits(r,s,sz)
+
+static int mmc_switch_part(mmc_dev_t *dev)
+{
+ int err = MMC_ERR_NONE;
+ struct mmc_card *card;
+ struct mmc_host *host;
+ u8 cfg;
+
+ host = dev->host;
+ if (host->curr_part == dev->part_id)
+ /* already set to specific partition */
+ return MMC_ERR_NONE;
+
+ if (dev->part_id > EXT_CSD_PART_CFG_GP_PART_4) {
+ dprintf(CRITICAL, "[MSDC] Unsupported partid: %u\n", dev->part_id);
+ return MMC_ERR_INVALID;
+ }
+
+ card = dev->card;
+ ASSERT(card);
+
+ cfg = card->ext_csd.part_cfg;
+ cfg = (cfg & ~0x7) | dev->part_id;
+ err = mmc_set_ext_csd(card, EXT_CSD_PART_CFG, cfg);
+ if (err)
+ dprintf(CRITICAL, "[MSDC] switch to part %u failed!\n", dev->part_id);
+ else
+ card->ext_csd.part_cfg = cfg;
+
+ return err;
+}
+
+static int mmc_cmd(struct mmc_host *host, struct mmc_command *cmd)
+{
+ int err;
+ int retry = cmd->retries;
+
+ do {
+ err = msdc_cmd(host, cmd);
+ if (err == MMC_ERR_NONE)
+ break;
+ } while (retry--);
+
+ return err;
+}
+
+static u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
+{
+ int bit;
+
+ ocr &= host->ocr_avail;
+
+ bit = __builtin_ffs(ocr);
+ if (bit) {
+ bit -= 1;
+ ocr &= 3 << bit;
+ } else {
+ ocr = 0;
+ }
+ return ocr;
+}
+
+static inline int mmc_go_idle(struct mmc_host *host)
+{
+ struct mmc_command cmd = {
+ MMC_CMD_GO_IDLE_STATE, 0, RESP_NONE, {0}, CMD_TIMEOUT, CMD_RETRIES, 0
+ };
+ return mmc_cmd(host, &cmd);
+}
+
+static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
+{
+ int i, err = 0;
+ struct mmc_command cmd = {
+ MMC_CMD_SEND_OP_COND, 0, RESP_R3, {0}, CMD_TIMEOUT, 0, 0
+ };
+
+ cmd.arg = ocr;
+
+ for (i = 100; i; i--) {
+ err = mmc_cmd(host, &cmd);
+ if (err)
+ break;
+
+ /* if we're just probing, do a single pass */
+ if (ocr == 0)
+ break;
+
+ if (cmd.resp[0] & MMC_CARD_BUSY)
+ break;
+
+ err = MMC_ERR_TIMEOUT;
+
+ spin(10000);
+
+ }
+
+ if (!err && rocr)
+ *rocr = cmd.resp[0];
+
+ return err;
+}
+
+static int mmc_all_send_cid(struct mmc_host *host)
+{
+ struct mmc_command cmd = {
+ MMC_CMD_ALL_SEND_CID, 0, RESP_R2, {0}, CMD_TIMEOUT, CMD_RETRIES, 0
+ };
+ return mmc_cmd(host, &cmd);
+}
+
+static int mmc_send_relative_addr(struct mmc_host *host,
+ struct mmc_card *card, unsigned int *rca)
+{
+ struct mmc_command cmd = {
+ MMC_CMD_SET_RELATIVE_ADDR, 0, RESP_R1, {0}, CMD_TIMEOUT, CMD_RETRIES, 0
+ };
+ cmd.arg = *rca << 16;
+ return mmc_cmd(host, &cmd);
+}
+
+static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
+{
+ struct mmc_command cmd = {
+ MMC_CMD_SELECT_CARD, 0, RESP_R1B, {0}, CMD_TIMEOUT, CMD_RETRIES, 0
+ };
+ cmd.arg = card->rca << 16;
+ return mmc_cmd(host, &cmd);
+}
+
+static int mmc_send_status(struct mmc_host *host, struct mmc_card *card,
+ u32 *status)
+{
+ int err;
+ struct mmc_command cmd = {
+ MMC_CMD_SEND_STATUS, 0, RESP_R1, {0}, CMD_TIMEOUT, CMD_RETRIES, 0
+ };
+ cmd.arg = card->rca << 16;
+
+ err = mmc_cmd(host, &cmd);
+ if (err == MMC_ERR_NONE)
+ *status = cmd.resp[0];
+ return err;
+}
+
+static int mmc_switch(struct mmc_host *host, struct mmc_card *card,
+ u8 set, u8 index, u8 value)
+{
+ int err;
+ u32 status = 0, count = 0;
+ struct mmc_command cmd = {
+ MMC_CMD_SWITCH, 0, RESP_R1B, {0}, CMD_TIMEOUT, CMD_RETRIES, 0
+ };
+
+ cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | (index << 16) |
+ (value << 8) | set;
+
+ err = mmc_cmd(host, &cmd);
+ if (err != MMC_ERR_NONE)
+ return err;
+
+ do {
+ err = mmc_send_status(host, card, &status);
+ if (err) {
+ dprintf(CRITICAL, "[eMMC] Fail to send status %d\n", err);
+ break;
+ }
+ if (status & R1_SWITCH_ERROR) {
+ dprintf(CRITICAL, "[eMMC] switch error. arg(0x%x)\n", cmd.arg);
+ return MMC_ERR_FAILED;
+ }
+ if (count++ >= 600000) {
+ dprintf(CRITICAL, "[%s]: timeout happend, count=%d, status=0x%x\n",
+ __func__, count, status);
+ break;
+ }
+ } while (!(status & R1_READY_FOR_DATA) || (R1_CURRENT_STATE(status) == 7));
+
+ if (!err && (index == EXT_CSD_PART_CFG))
+ host->curr_part = value & 0x7;
+
+ return err;
+}
+
+static int mmc_read_csds(struct mmc_host *host, struct mmc_card *card)
+{
+ int err;
+ struct mmc_command cmd = {
+ MMC_CMD_SEND_CSD, 0, RESP_R2, {0}, CMD_TIMEOUT * 100, CMD_RETRIES, 0
+ };
+
+ cmd.arg = card->rca << 16;
+
+ err = mmc_cmd(host, &cmd);
+ if (err == MMC_ERR_NONE) {
+ unsigned int e, m;
+ card->csd.mmca_vsn = UNSTUFF_BITS(&cmd.resp[0], 122, 4);
+ m = UNSTUFF_BITS(&cmd.resp[0], 99, 4);
+ e = UNSTUFF_BITS(&cmd.resp[0], 96, 3);
+ card->csd.max_dtr = tran_exp[e] * mmc_tran_mant[m];
+ e = UNSTUFF_BITS(&cmd.resp[0], 47, 3);
+ m = UNSTUFF_BITS(&cmd.resp[0], 62, 12);
+ card->csd.capacity = (1 + m) << (e + 2);
+ card->csd.read_blkbits = UNSTUFF_BITS(&cmd.resp[0], 80, 4);
+ }
+
+ return err;
+}
+
+static void mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
+{
+ card->ext_csd.sectors =
+ ext_csd[EXT_CSD_SEC_CNT + 0] << 0 |
+ ext_csd[EXT_CSD_SEC_CNT + 1] << 8 |
+ ext_csd[EXT_CSD_SEC_CNT + 2] << 16 |
+ ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
+
+ card->ext_csd.rev = ext_csd[EXT_CSD_REV];
+ card->ext_csd.boot_info = ext_csd[EXT_CSD_BOOT_INFO];
+ card->ext_csd.boot_part_sz = ext_csd[EXT_CSD_BOOT_SIZE_MULT] * 128 * 1024;
+ card->ext_csd.rpmb_sz = ext_csd[EXT_CSD_RPMB_SIZE_MULT] * 128 * 1024;
+
+ if (card->ext_csd.sectors)
+ mmc_card_set_blockaddr(card);
+
+ if ((ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_DDR_52_1_2V) ||
+ (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_DDR_52)) {
+ card->ext_csd.ddr_support = 1;
+ card->ext_csd.hs_max_dtr = 52000000;
+ } else if (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_52) {
+ card->ext_csd.hs_max_dtr = 52000000;
+ } else if ((ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_26)) {
+ card->ext_csd.hs_max_dtr = 26000000;
+ } else {
+ /* MMC v4 spec says this cannot happen */
+ dprintf(CRITICAL, "[eMMC] MMCv4 but HS unsupported\n");
+ }
+
+ card->ext_csd.part_cfg = ext_csd[EXT_CSD_PART_CFG];
+ card->ext_csd.sec_support = ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT];
+ card->ext_csd.reset_en = ext_csd[EXT_CSD_RST_N_FUNC];
+
+ return;
+}
+
+/* Read and decode extended CSD. */
+static int mmc_read_ext_csd(struct mmc_host *host, struct mmc_card *card)
+{
+ int err = MMC_ERR_NONE;
+ u8 *ext_csd;
+ int result = MMC_ERR_NONE;
+ struct mmc_data data;
+ addr_t base = host->base;
+ struct mmc_command cmd = {
+ MMC_CMD_SEND_EXT_CSD, 0, RESP_R1, {0}, CMD_TIMEOUT, CMD_RETRIES, 0
+ };
+
+ if (card->csd.mmca_vsn < CSD_SPEC_VER_4) {
+ dprintf(INFO, "[eMMC] MMCA_VSN: %d. Skip EXT_CSD\n",
+ card->csd.mmca_vsn);
+ return MMC_ERR_NONE;
+ }
+
+ /*
+ * As the ext_csd is so large and mostly unused, we don't store the
+ * raw block in mmc_card.
+ */
+ ext_csd = malloc(512);
+ ASSERT(ext_csd);
+ memset(ext_csd, 0, 512);
+
+ msdc_reset_tune_counter(host);
+
+ do {
+ MSDC_DMA_ON;
+ MSDC_CLR_FIFO();
+ MSDC_WRITE32(SDC_BLK_NUM, 1);
+ host->blklen = 512;
+ msdc_set_timeout(host, 100000000, 0);
+ err = mmc_cmd(host, &cmd);
+ if (err != MMC_ERR_NONE) {
+ dprintf(CRITICAL, "mmc cmd failed\n");
+ goto out;
+ }
+
+ data.cmd = &cmd;
+ data.blks = 1;
+ data.buf = ext_csd;
+ data.timeout = 100;
+ err = msdc_dma_transfer(host, &data);
+ MSDC_DMA_OFF;
+ if (err != MMC_ERR_NONE) {
+ if (msdc_abort_handler(host, 1))
+ dprintf(CRITICAL, "[eMMC] data abort failed\n");
+ result = msdc_tune_read(host);
+ }
+ } while (err && result != MMC_ERR_READTUNEFAIL);
+ msdc_reset_tune_counter(host);
+ mmc_decode_ext_csd(card, ext_csd);
+
+out:
+ free(ext_csd);
+ return err;
+}
+
+static int mmc_erase_start(struct mmc_card *card, u32 blknr)
+{
+ struct mmc_command cmd = {
+ MMC_CMD_ERASE_GROUP_START, 0, RESP_R1, {0}, CMD_TIMEOUT, 3, 0
+ };
+ cmd.arg = blknr;
+ return mmc_cmd(card->host, &cmd);
+}
+
+static int mmc_erase_end(struct mmc_card *card, u32 blknr)
+{
+ struct mmc_command cmd = {
+ MMC_CMD_ERASE_GROUP_END, 0, RESP_R1, {0}, CMD_TIMEOUT, 3, 0
+ };
+ cmd.arg = blknr;
+ return mmc_cmd(card->host, &cmd);
+}
+
+static int mmc_erase(struct mmc_card *card, u32 arg)
+{
+ int err;
+ u32 status;
+ struct mmc_command cmd = {
+ MMC_CMD_ERASE, 0, RESP_R1B, {0}, CMD_TIMEOUT, 3, 0
+ };
+ cmd.arg = arg;
+
+ if (arg & MMC_ERASE_SECURE_REQ) {
+ if (!(card->ext_csd.sec_support & EXT_CSD_SEC_FEATURE_ER_EN))
+ return MMC_ERR_INVALID;
+ }
+ if ((arg & MMC_ERASE_GC_REQ) || (arg & MMC_ERASE_TRIM)) {
+ if (!(card->ext_csd.sec_support & EXT_CSD_SEC_FEATURE_GB_CL_EN))
+ return MMC_ERR_INVALID;
+ }
+
+ err = mmc_cmd(card->host, &cmd);
+ if (err)
+ return err;
+
+ do {
+ err = mmc_send_status(card->host, card, &status);
+ if (err)
+ break;
+ if (R1_STATUS(status) != 0)
+ break;
+ } while (R1_CURRENT_STATE(status) == 7);
+
+ return err;
+}
+
+static int mmc_do_trim(struct mmc_card *card, off_t start_addr, size_t len)
+{
+ int err = MMC_ERR_NONE;
+ off_t end_addr;
+
+ if (len < card->blklen) {
+ dprintf(CRITICAL, "%s: invalid len: %d\n", __func__, (int)len);
+ return MMC_ERR_INVALID;
+ }
+
+ end_addr =((start_addr + len) / card->blklen - 1) * card->blklen;
+
+ if (mmc_card_highcaps(card)) {
+ start_addr >>= MMC_BLOCK_BITS_SHFT;
+ end_addr >>= MMC_BLOCK_BITS_SHFT;
+ }
+
+ err = mmc_erase_start(card, start_addr);
+ if (err)
+ goto error;
+
+ err = mmc_erase_end(card, end_addr);
+ if (err)
+ goto error;
+
+ err = mmc_erase(card, MMC_ERASE_TRIM);
+
+error:
+ if (err)
+ dprintf(CRITICAL, "%s: erase range (0x%llx~0x%llx) failed,Err<%d>\n",
+ __func__, start_addr, end_addr, err);
+
+ return err;
+}
+
+static void mmc_set_clock(struct mmc_host *host, int ddr, unsigned int hz)
+{
+ if (hz >= host->f_max) {
+ hz = host->f_max;
+ } else if (hz < host->f_min) {
+ hz = host->f_min;
+ }
+ msdc_config_clock(host, ddr > 0 ? 1 : 0, hz);
+}
+
+static int mmc_set_ext_csd(struct mmc_card *card, u8 addr, u8 value)
+{
+ int err;
+
+ /* can't write */
+ if (192 <= addr || !card)
+ return MMC_ERR_INVALID;
+
+ err = mmc_switch(card->host, card, EXT_CSD_CMD_SET_NORMAL, addr, value);
+
+ if (err == MMC_ERR_NONE)
+ err = mmc_read_ext_csd(card->host, card);
+
+ return err;
+}
+
+static int mmc_set_bus_width(struct mmc_host *host, struct mmc_card *card, int width)
+{
+ int err = MMC_ERR_NONE;
+ u32 arg = 0;
+
+ if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
+ goto out;
+
+ if (width == HOST_BUS_WIDTH_8) {
+ if (host->caps & MMC_CAP_8_BIT_DATA) {
+ arg = ((host->caps & MMC_CAP_DDR) && card->ext_csd.ddr_support) ?
+ EXT_CSD_BUS_WIDTH_8_DDR : EXT_CSD_BUS_WIDTH_8;
+ } else {
+ width = HOST_BUS_WIDTH_4;
+ }
+ }
+ if (width == HOST_BUS_WIDTH_4) {
+ if (host->caps & MMC_CAP_4_BIT_DATA) {
+ arg = ((host->caps & MMC_CAP_DDR) && card->ext_csd.ddr_support) ?
+ EXT_CSD_BUS_WIDTH_4_DDR : EXT_CSD_BUS_WIDTH_4;
+ } else {
+ width = HOST_BUS_WIDTH_1;
+ }
+ }
+ if (width == HOST_BUS_WIDTH_1)
+ arg = EXT_CSD_BUS_WIDTH_1;
+
+ err = mmc_switch(host, card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, arg);
+ if (err != MMC_ERR_NONE) {
+ dprintf(CRITICAL, "[eMMC] Switch to bus width(%d) failed\n", arg);
+ goto out;
+ }
+ if (arg == EXT_CSD_BUS_WIDTH_8_DDR || arg == EXT_CSD_BUS_WIDTH_4_DDR) {
+ mmc_card_set_ddr(card);
+ } else {
+ mmc_card_clr_ddr(card);
+ }
+ mmc_set_clock(host, card->state, host->sclk);
+
+ msdc_config_bus(host, width);
+
+out:
+ return err;
+}
+
+static int mmc_set_reset_func(struct mmc_card *card, u8 enable)
+{
+ int err = MMC_ERR_FAILED;
+
+ if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
+ goto out;
+
+ if (card->ext_csd.reset_en == 0) {
+ err = mmc_set_ext_csd(card, EXT_CSD_RST_N_FUNC, enable);
+ if (err == MMC_ERR_NONE)
+ card->ext_csd.reset_en = enable;
+ } else {
+ /* no need set */
+ return MMC_ERR_NONE;
+ }
+out:
+ return err;
+}
+
+static int mmc_set_boot_bus(struct mmc_card *card, u8 rst_bwidth, u8 mode, u8 bwidth)
+{
+ int err = MMC_ERR_FAILED;
+ u8 arg;
+
+ if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
+ goto out;
+
+ arg = mode | rst_bwidth | bwidth;
+
+ err = mmc_set_ext_csd(card, EXT_CSD_BOOT_BUS_WIDTH, arg);
+out:
+ return err;
+}
+
+static int mmc_set_part_config(struct mmc_card *card, u8 cfg)
+{
+ int err = MMC_ERR_FAILED;
+
+ if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
+ goto out;
+
+ err = mmc_set_ext_csd(card, EXT_CSD_PART_CFG, cfg);
+out:
+ return err;
+}
+
+static int mmc_boot_config(struct mmc_card *card, u8 acken, u8 enpart, u8 buswidth, u8 busmode)
+{
+ int err = MMC_ERR_FAILED;
+ u8 val;
+ u8 rst_bwidth = 0;
+ u8 cfg;
+
+ if (card->csd.mmca_vsn < CSD_SPEC_VER_4 ||
+ !card->ext_csd.boot_info || card->ext_csd.rev < 3) {
+ dprintf(CRITICAL, "revsion boot_info version check failed\n");
+ goto out;
+ }
+
+ cfg = card->ext_csd.part_cfg;
+ /* configure boot partition */
+ val = acken | enpart | (cfg & 0x7);
+ err = mmc_set_part_config(card, val);
+ if (err != MMC_ERR_NONE)
+ goto out;
+ else
+ card->ext_csd.part_cfg = val;
+
+ /* configure boot bus mode and width */
+ rst_bwidth = (buswidth != EXT_CSD_BOOT_BUS_WIDTH_1 ? 1 : 0) << 2;
+ dprintf(INFO, "%s =====Set boot Bus Width<%d>=======\n", __func__, buswidth);
+ dprintf(INFO, "%s =====Set boot Bus mode<%d>=======\n", __func__, busmode);
+ err = mmc_set_boot_bus(card, rst_bwidth, busmode, buswidth);
+out:
+
+ return err;
+}
+
+static int emmc_boot_prepare(struct mmc_card *card)
+{
+ int err = MMC_ERR_NONE;
+
+ err = mmc_boot_config(card, EXT_CSD_PART_CFG_EN_ACK,
+ EXT_CSD_PART_CFG_EN_BOOT_PART_1,
+ EXT_CSD_BOOT_BUS_WIDTH_1,
+ EXT_CSD_BOOT_BUS_MODE_DEFT);
+ if (err) {
+ dprintf(CRITICAL, "failed to emmc_boot_prepare\n");
+ goto exit;
+ }
+
+ err = mmc_set_reset_func(card, 1);
+exit:
+ return err;
+}
+
+static int mmc_dev_bread(struct mmc_card *card, unsigned long blknr, u32 blkcnt, u8 *dst)
+{
+ struct mmc_host *host = card->host;
+ u32 blksz = host->blklen;
+ int tune = 0;
+ int retry = 3;
+ int err;
+ unsigned long src;
+
+ src = mmc_card_highcaps(card) ? blknr : blknr * blksz;
+
+ do {
+ if (!tune) {
+ err = host->blk_read(host, (uchar *)dst, src, blkcnt);
+ } else {
+#ifdef FEATURE_MMC_RD_TUNING
+ err = msdc_tune_bread(host, (uchar *)dst, src, blkcnt);
+#endif
+ if (err && (host->sclk > (host->f_max >> 4)))
+ mmc_set_clock(host, card->state, host->sclk >> 1);
+ }
+ if (err == MMC_ERR_NONE) {
+ break;
+ }
+
+ if (err == MMC_ERR_BADCRC || err == MMC_ERR_ACMD_RSPCRC || err == MMC_ERR_CMD_RSPCRC) {
+ tune = 1;
+ retry++;
+ } else if (err == MMC_ERR_READTUNEFAIL || err == MMC_ERR_CMDTUNEFAIL) {
+ dprintf(CRITICAL, "[eMMC] Fail to tuning,%s",
+ (err == MMC_ERR_CMDTUNEFAIL) ?
+ "cmd tune failed!\n" : "read tune failed!\n");
+ break;
+ }
+ } while (retry--);
+
+ return err;
+}
+
+static int mmc_dev_bwrite(struct mmc_card *card, unsigned long blknr,
+ u32 blkcnt, const u8 *src)
+{
+ struct mmc_host *host = card->host;
+ u32 blksz = host->blklen;
+ u32 status;
+ int tune = 0;
+ int retry = 3;
+ int err;
+ unsigned long dst;
+
+ dst = mmc_card_highcaps(card) ? blknr : blknr * blksz;
+
+ do {
+ if (!tune) {
+ err = host->blk_write(host, dst, (uchar *)src, blkcnt);
+ } else {
+#ifdef FEATURE_MMC_WR_TUNING
+ err = msdc_tune_bwrite(host, dst, (uchar *)src, blkcnt);
+#endif
+ if (err && (host->sclk > (host->f_max >> 4)))
+ mmc_set_clock(host, card->state, host->sclk >> 1);
+ }
+ if (err == MMC_ERR_NONE) {
+ do {
+ err = mmc_send_status(host, card, &status);
+ if (err) {
+ dprintf(CRITICAL, "[eMMC] Fail to send status %d\n", err);
+ break;
+ }
+ } while (!(status & R1_READY_FOR_DATA) ||
+ (R1_CURRENT_STATE(status) == 7));
+ dprintf(INFO, "[eMMC] Write %d bytes (DONE)\n", blkcnt * blksz);
+ break;
+ }
+
+ if (err == MMC_ERR_BADCRC || err == MMC_ERR_ACMD_RSPCRC || err == MMC_ERR_CMD_RSPCRC) {
+ tune = 1;
+ retry++;
+ } else if (err == MMC_ERR_WRITETUNEFAIL || err == MMC_ERR_CMDTUNEFAIL) {
+ dprintf(CRITICAL, "[eMMC] Fail to tuning,%s",
+ (err == MMC_ERR_CMDTUNEFAIL) ?
+ "cmd tune failed!\n" : "write tune failed!\n");
+ break;
+ }
+ } while (retry--);
+
+ return err;
+}
+
+static ssize_t mmc_block_read(struct bdev *dev, void *buf, bnum_t block,
+ uint count)
+{
+ mmc_dev_t *__dev = (mmc_dev_t *)dev;
+ struct mmc_host *host = __dev->host;
+ struct mmc_card *card = __dev->card;
+ u32 maxblks = host->max_phys_segs;
+ u32 leftblks, totalblks = count;
+ ssize_t ret = 0;
+
+ mutex_acquire(&host->lock);
+ if (mmc_switch_part(__dev)) {
+ ret = ERR_IO;
+ goto done;
+ }
+
+ do {
+ leftblks = ((count > maxblks) ? maxblks : count);
+ if (mmc_dev_bread(card, (unsigned long)block, leftblks, buf)) {
+ ret = ERR_IO;
+ goto done;
+ }
+ block += leftblks;
+ buf += maxblks * dev->block_size;
+ count -= leftblks;
+ } while (count);
+
+ if (dev->block_size * totalblks > 0x7fffffffU)
+ /* ssize_t is defined as signed, should take a look here */
+ dprintf(CRITICAL, "[MSDC] %s: WARN! The return size is overflow! 0x%x\n",
+ __func__, (unsigned int)(dev->block_size * totalblks));
+
+done:
+ mutex_release(&host->lock);
+ return ret ? ret : (ssize_t)(dev->block_size * totalblks);
+}
+
+static ssize_t mmc_block_write(struct bdev *dev, const void *buf, bnum_t block,
+ uint count)
+{
+ mmc_dev_t *__dev = (mmc_dev_t *)dev;
+ struct mmc_host *host = __dev->host;
+ struct mmc_card *card = __dev->card;
+ u32 maxblks = host->max_phys_segs;
+ u32 leftblks, totalblks = count;
+ ssize_t ret = 0;
+
+ mutex_acquire(&host->lock);
+ if (mmc_switch_part(__dev)) {
+ ret = ERR_IO;
+ goto done;
+ }
+
+ do {
+ leftblks = ((count > maxblks) ? maxblks : count);
+ if (mmc_dev_bwrite(card, (unsigned long)block, leftblks, buf)) {
+ ret = ERR_IO;
+ goto done;
+ }
+ block += leftblks;
+ buf = (u8 *)buf + maxblks * dev->block_size;
+ count -= leftblks;
+ } while (count);
+
+ if (dev->block_size * totalblks > 0x7fffffffU)
+ /* ssize_t is defined as signed, should take a look here */
+ dprintf(CRITICAL, "[MSDC] %s: WARN! The return size is overflow! 0x%x\n",
+ __func__, (unsigned int)(dev->block_size * totalblks));
+
+done:
+ mutex_release(&host->lock);
+ return ret ? ret: (ssize_t)(dev->block_size * totalblks);
+}
+
+static ssize_t mmc_wrap_erase(struct bdev *bdev, off_t offset, size_t len)
+{
+ mmc_dev_t *dev = (mmc_dev_t *)bdev;
+ struct mmc_host *host = dev->host;
+ ssize_t ret = 0;
+
+ mutex_acquire(&host->lock);
+ if (mmc_switch_part(dev)) {
+ ret = ERR_IO;
+ goto done;
+ }
+
+ /* ATTENTION:
+ * We use TRIM here, which is block-based(512B) wipping,
+ * If using ERASE here, please ensure the offset & size are
+ * erase-group aligned,
+ * OTHERWISE, some valid data may be wiped. refer to JEDEC spec:
+ * The Device will ignore all LSB's below the Erase Group size,
+ * effectively ROUNDING the address DOWN to the Erase Group boundary. */
+ ASSERT(dev && len);
+ if ((offset % MMC_BLOCK_SIZE) || (len % MMC_BLOCK_SIZE)) {
+ dprintf(CRITICAL, "%s: offset(0x%llx)/len(%u) is not block-aligned!\n",
+ __func__, offset, (unsigned int)len);
+ ret = ERR_IO;
+ goto done;
+ }
+
+ ASSERT(dev->card);
+ if (mmc_do_trim(dev->card, offset, len)) {
+ ret = ERR_IO;
+ goto done;
+ }
+
+done:
+ mutex_release(&host->lock);
+ return ret ? ret: (ssize_t)len;
+}
+
+static ssize_t mmc_rpmb_dummy_read(struct bdev *dev, void *buf, bnum_t block,
+ uint count)
+{
+ return 0;
+}
+
+static ssize_t mmc_rpmb_dummy_write(struct bdev *dev, const void *buf, bnum_t block,
+ uint count)
+{
+ return 0;
+}
+
+static ssize_t mmc_rpmb_dummy_erase(struct bdev *bdev, off_t offset, size_t len)
+{
+ return 0;
+}
+
+static int mmc_set_block_count(struct mmc_host *host, unsigned int blockcount,
+ bool is_rel_write)
+{
+ struct mmc_command cmd = {0};
+
+ cmd.opcode = MMC_CMD_SET_BLOCK_COUNT;
+ cmd.arg = blockcount & 0x0000FFFF;
+ if (is_rel_write)
+ cmd.arg |= 1 << 31;
+ cmd.rsptyp = RESP_R1;
+
+ return mmc_cmd(host, &cmd);
+}
+
+static int mmc_rpmb_ioctl_cmd(struct bdev *dev, struct mmc_ioc_cmd *arg)
+{
+ mmc_dev_t *__dev = (mmc_dev_t *)dev;
+ struct mmc_host *host = __dev->host;
+ //struct mmc_card *card = __dev->card;
+ struct mmc_command cmd = {0};
+ struct mmc_data data = {0};
+ addr_t base = host->base;
+ int ret = 0;
+ int old_autocmd = msdc_get_autocmd(host);
+
+ msdc_set_autocmd(host, 0);
+ cmd.opcode = arg->opcode;
+ cmd.arg = arg->arg;
+ cmd.rsptyp = arg->flags; /* arg->flags must be type of enum of RESP_NONE ~ RESP_R1B */
+
+ if (arg->blocks) {
+ ret = mmc_set_block_count(host, arg->blocks,
+ arg->write_flag & (1 << 31));
+ if (ret != MMC_ERR_NONE) {
+ dprintf(CRITICAL, "mmc cmd23 failed!\n");
+ goto out;
+ }
+ }
+
+ if (arg->blocks) {
+ MSDC_DMA_ON;
+ MSDC_CLR_FIFO();
+ MSDC_WRITE32(SDC_BLK_NUM, arg->blocks);
+ host->blklen = 512;
+ msdc_set_timeout(host, 100000000, 0);
+ ret = mmc_cmd(host, &cmd);
+ if (ret != MMC_ERR_NONE) {
+ dprintf(CRITICAL, "mmc cmd failed\n");
+ goto out;
+ }
+
+ data.cmd = &cmd;
+ data.blks = arg->blocks;
+ data.buf = (uchar *)arg->data_ptr;
+ data.timeout = 100;
+ ret = msdc_dma_transfer(host, &data);
+ MSDC_DMA_OFF;
+
+ } else {
+ ret = mmc_cmd(host, &cmd);
+ }
+
+out:
+ msdc_set_autocmd(host, old_autocmd);
+ return ret;
+}
+
+static int mmc_rpmb_ioctl(struct bdev *dev, int request, void *argp)
+{
+ mmc_dev_t *__dev = (mmc_dev_t *)dev;
+ struct mmc_host *host = __dev->host;
+ int ret = 0;
+
+ mutex_acquire(&host->lock);
+ if (mmc_switch_part(__dev)) {
+ ret = ERR_IO;
+ goto done;
+ }
+
+ switch (request) {
+ case MMC_IOC_CMD:
+ ret = mmc_rpmb_ioctl_cmd(dev, (struct mmc_ioc_cmd *)argp);
+ break;
+ default:
+ ret = ERR_INVALID_ARGS;
+ break;
+ }
+
+done:
+ mutex_release(&host->lock);
+ return ret;
+}
+
+static int mmc_init_mem_card(struct mmc_host *host, struct mmc_card *card, u32 ocr)
+{
+ int err;
+
+ /*
+ * Sanity check the voltages that the card claims to
+ * support.
+ */
+ if (ocr & 0x7F)
+ ocr &= ~0x7F;
+
+ ocr = host->ocr = mmc_select_voltage(host, ocr);
+
+ /*
+ * Can we support the voltage(s) of the card(s)?
+ */
+ if (!host->ocr) {
+ err = MMC_ERR_FAILED;
+ goto out;
+ }
+
+ err = mmc_go_idle(host);
+ if (err != MMC_ERR_NONE) {
+ dprintf(CRITICAL, "[eMMC] Fail in GO_IDLE_STATE cmd\n");
+ goto out;
+ }
+
+ /* host support HCS[30] */
+ ocr |= (1 << 30);
+
+ /* send operation condition */
+ /* The extra bit indicates that we support high capacity */
+ err = mmc_send_op_cond(host, ocr, &card->ocr);
+ if (err != MMC_ERR_NONE) {
+ dprintf(CRITICAL, "[eMMC] Fail in SEND_OP_COND cmd\n");
+ goto out;
+ }
+
+ /* set hcs bit if a high-capacity card */
+ card->state |= ((card->ocr >> 30) & 0x1) ? MMC_STATE_HIGHCAPS : 0;
+ /* send cid */
+ err = mmc_all_send_cid(host);
+ if (err != MMC_ERR_NONE) {
+ dprintf(CRITICAL, "[eMMC] Fail in SEND_CID cmd\n");
+ goto out;
+ }
+
+ /* assign a rca */
+ card->rca = 0x1;
+
+ /* set/send rca */
+ err = mmc_send_relative_addr(host, card, &card->rca);
+ if (err != MMC_ERR_NONE) {
+ dprintf(CRITICAL, "[eMMC] Fail in SEND_RCA cmd\n");
+ goto out;
+ }
+
+ /* send csd */
+ err = mmc_read_csds(host, card);
+ if (err != MMC_ERR_NONE) {
+ dprintf(CRITICAL, "[eMMC] Fail in SEND_CSD cmd\n");
+ goto out;
+ }
+
+ /* select this card */
+ err = mmc_select_card(host, card);
+ if (err != MMC_ERR_NONE) {
+ dprintf(CRITICAL, "[eMMC] Fail in select card cmd\n");
+ goto out;
+ }
+
+ /* send ext csd */
+ err = mmc_read_ext_csd(host, card);
+ if (err != MMC_ERR_NONE) {
+ dprintf(CRITICAL, "[eMMC] Fail in SEND_EXT_CSD cmd\n");
+ goto out;
+ }
+
+ /* activate high speed (if supported) */
+ if ((card->ext_csd.hs_max_dtr != 0) && (host->caps & MMC_CAP_MMC_HIGHSPEED)) {
+ err = mmc_switch(host, card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1);
+ if (err == MMC_ERR_NONE) {
+ dprintf(INFO, "[eMMC] Switched to High-Speed mode!\n");
+ mmc_card_set_highspeed(card);
+ }
+ }
+
+ /* set bus width */
+ mmc_set_bus_width(host, card, HOST_BUS_WIDTH_8);
+
+ /* compute bus speed. */
+ card->maxhz = (unsigned int)-1;
+
+ if (mmc_card_highspeed(card)) {
+ if (card->maxhz > card->ext_csd.hs_max_dtr)
+ card->maxhz = card->ext_csd.hs_max_dtr;
+ } else if (card->maxhz > card->csd.max_dtr) {
+ card->maxhz = card->csd.max_dtr;
+ }
+
+ if (mmc_card_blockaddr(card)) {
+ /* The EXT_CSD sector count is in number or 512 byte sectors. */
+ card->blklen = MMC_BLOCK_SIZE;
+ card->nblks = card->ext_csd.sectors;
+ } else {
+ /* The CSD capacity field is in units of read_blkbits.
+ * set_capacity takes units of 512 bytes.
+ */
+ card->blklen = MMC_BLOCK_SIZE;
+ card->nblks = card->csd.capacity << (card->csd.read_blkbits - 9);
+ }
+
+ dprintf(CRITICAL,"[eMMC] Size: %d MB, Max.Speed: %d kHz, blklen(%d), nblks(%d), ro(%d)\n",
+ ((card->nblks / 1024) * card->blklen) / 1024 , card->maxhz / 1000,
+ card->blklen, card->nblks, mmc_card_readonly(card));
+
+ card->ready = 1;
+
+ dprintf(INFO, "[eMMC] Initialized\n");
+out:
+ return err;
+}
+
+static int mmc_init_card(struct mmc_host *host, struct mmc_card *card)
+{
+ int err;
+ u32 ocr;
+
+ dprintf(INFO, "[%s]: start\n", __func__);
+ memset(card, 0, sizeof(struct mmc_card));
+
+ mmc_card_set_present(card);
+ mmc_card_set_host(card, host);
+ mmc_card_set_unknown(card);
+
+ err = mmc_go_idle(host);
+ if (err != MMC_ERR_NONE) {
+ dprintf(CRITICAL, "[eMMC] Fail in GO_IDLE_STATE cmd\n");
+ goto out;
+ }
+
+ /* query operation condition */
+ err = mmc_send_op_cond(host, 0, &ocr);
+ if (err != MMC_ERR_NONE) {
+ dprintf(CRITICAL, "[eMMC] Fail in MMC_CMD_SEND_OP_COND/SD_ACMD_SEND_OP_COND cmd\n");
+ goto out;
+ }
+
+ err = mmc_init_mem_card(host, card, ocr);
+ if (err) {
+ dprintf(CRITICAL, "failed to mmc_init_mem_card err = %d\n", err);
+ goto out;
+ }
+
+ /* change clock */
+ mmc_set_clock(host, card->state, card->maxhz);
+
+out:
+ if (err) {
+ dprintf(CRITICAL, "[%s]: failed, err=%d\n", __func__, err);
+ return err;
+ }
+ host->card = card;
+ dprintf(INFO, "[%s]: finish successfully\n",__func__);
+ return 0;
+}
+
+static inline int mmc_init_host(struct mmc_host *host)
+{
+ mutex_init(&host->lock);
+ return msdc_init(host);
+}
+
+static void mmc_bio_ops(const void *name, const int part_id, const int nblks,
+ struct mmc_host *host, struct mmc_card *card)
+{
+ mmc_dev_t *dev;
+
+ dev = malloc(sizeof(mmc_dev_t));
+ /* malloc fail */
+ ASSERT(dev);
+ /* construct the block device */
+ memset(dev, 0, sizeof(mmc_dev_t));
+
+ /* setup partition id*/
+ dev->part_id = part_id;
+ /* setup host */
+ dev->host = host;
+ /* setup card */
+ dev->card = card;
+ /* bio block device register */
+ bio_initialize_bdev(&dev->bdev, name,
+ card->blklen, nblks,
+ 0, NULL, BIO_FLAGS_NONE);
+ /* override our block device hooks */
+ if (part_id == EXT_CSD_PART_CFG_RPMB_PART) {
+ dev->bdev.read_block = mmc_rpmb_dummy_read;
+ dev->bdev.write_block = mmc_rpmb_dummy_write;
+ dev->bdev.erase = mmc_rpmb_dummy_erase;
+ dev->bdev.ioctl = mmc_rpmb_ioctl;
+ } else {
+ dev->bdev.read_block = mmc_block_read;
+ dev->bdev.write_block = mmc_block_write;
+ dev->bdev.erase = mmc_wrap_erase;
+ }
+ dev->bdev.erase_byte = 0x0;
+ bio_register_device(&dev->bdev);
+
+ partition_publish(dev->bdev.name, 0x0);
+}
+
+int emmc_init(void)
+{
+ int err = MMC_ERR_NONE;
+ struct mmc_host *host;
+ struct mmc_card *card;
+ int boot_part_nblks = 0;
+ int rpmb_part_nblks = 0;
+
+ host = malloc(sizeof(struct mmc_host));
+ /* malloc fail */
+ ASSERT(host);
+ /* construct the block device */
+ memset(host, 0, sizeof(struct mmc_host));
+
+ card = malloc(sizeof(struct mmc_card));
+ /* malloc fail */
+ ASSERT(card);
+ /* construct the block device */
+ memset(card, 0, sizeof(struct mmc_card));
+
+ err = mmc_init_host(host);
+
+ if (err == MMC_ERR_NONE)
+ err = mmc_init_card(host, card);
+ /* mmc init fail */
+ ASSERT(err == MMC_ERR_NONE);
+
+ err = emmc_boot_prepare(card);
+ ASSERT(err == MMC_ERR_NONE);
+
+ mmc_bio_ops("mmc0", EXT_CSD_PART_CFG_DEFT_PART, card->nblks, host, card);
+ boot_part_nblks = card->ext_csd.boot_part_sz/card->blklen;
+ mmc_bio_ops("mmc0boot0", EXT_CSD_PART_CFG_BOOT_PART_1, boot_part_nblks,
+ host, card);
+ mmc_bio_ops("mmc0boot1", EXT_CSD_PART_CFG_BOOT_PART_2, boot_part_nblks,
+ host, card);
+ rpmb_part_nblks = card->ext_csd.rpmb_sz/card->blklen;
+ mmc_bio_ops("mmc0rpmb", EXT_CSD_PART_CFG_RPMB_PART, rpmb_part_nblks,
+ host, card);
+
+ return err;
+}
diff --git a/src/bsp/lk/platform/mt2635/drivers/mmc/mmc_rpmb.c b/src/bsp/lk/platform/mt2635/drivers/mmc/mmc_rpmb.c
new file mode 100644
index 0000000..232a577
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/drivers/mmc/mmc_rpmb.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <lib/bio.h>
+#include <platform/mmc_ioctl.h>
+#include <platform/mmc_rpmb.h>
+#include <debug.h>
+
+static void reverse_endian(void *data, size_t size)
+{
+ unsigned int i;
+ char tmp;
+ char *swp = (char *)data;
+
+ for (i = 0 ; i< (size/2); ++i) {
+ tmp = swp[i];
+ swp[i] = swp[size-1-i];
+ swp[size-1-i] = tmp;
+ }
+}
+
+int mmc_rpmb_set_key(u8 *key)
+{
+ int ret;
+ bdev_t *rpdev;
+ struct mmc_ioc_cmd *idata;
+ unsigned char *rpmb_pkt;
+
+ idata = malloc(sizeof(struct mmc_ioc_cmd));
+ if (idata == NULL) {
+ return -2;
+ }
+ rpmb_pkt = malloc(512);
+ if (rpmb_pkt == NULL) {
+ free(idata);
+ return -2;
+ }
+
+ memset(idata, 0, sizeof(struct mmc_ioc_cmd));
+ memset(rpmb_pkt, 0, 512);
+
+ rpdev = bio_open("mmc0rpmb");
+ if (rpdev == NULL) {
+ free(rpmb_pkt);
+ free(idata);
+ return -3;
+ }
+
+ /* get wc for status */
+ rpmb_pkt[0] = 2;
+
+ idata->flags = RESP_R1;
+ idata->opcode = MMC_CMD_WRITE_MULTIPLE_BLOCK;
+ idata->blksz = 512;
+ idata->blocks = 1;
+ idata->write_flag = 1;
+ reverse_endian(rpmb_pkt, 512);
+ mmc_ioc_cmd_set_data((*idata), rpmb_pkt);
+
+ ret = bio_ioctl(rpdev, MMC_IOC_CMD, idata);
+ if (ret != 0)
+ goto rpmb_end;
+
+ memset(idata, 0, sizeof(struct mmc_ioc_cmd));
+ memset(rpmb_pkt, 0, 512);
+ idata->flags = RESP_R1;
+ idata->opcode = MMC_CMD_READ_MULTIPLE_BLOCK;
+ idata->blksz = 512;
+ idata->blocks = 1;
+ idata->write_flag = 0;
+ mmc_ioc_cmd_set_data((*idata), rpmb_pkt);
+
+ ret = bio_ioctl(rpdev, MMC_IOC_CMD, idata);
+ if (ret != 0)
+ goto rpmb_end;
+
+ reverse_endian(rpmb_pkt, 512);
+ /* check result */
+ ret = *(unsigned short *)&rpmb_pkt[2];
+ if (ret != 7) { /* 7 means not programmed yet */
+ if (ret == 0) /* no error, key is programmed already */
+ ret = -7;
+ goto rpmb_end;
+ }
+ dprintf(INFO, "ret=%d, key not programmed yet\n", ret);
+
+ memset(idata, 0, sizeof(struct mmc_ioc_cmd));
+ memset(rpmb_pkt, 0, sizeof(struct mmc_rpmb_cfg));
+
+ rpmb_pkt[0] = 1;
+
+ idata->flags = RESP_R1;
+ idata->opcode = MMC_CMD_WRITE_MULTIPLE_BLOCK;
+ idata->blksz = 512;
+ idata->blocks = 1;
+ idata->write_flag = 1 << 31;
+ reverse_endian(rpmb_pkt, 512);
+ memcpy(&rpmb_pkt[RPMB_MAC_BEG], key, 32);
+ mmc_ioc_cmd_set_data((*idata), rpmb_pkt);
+
+ ret = bio_ioctl(rpdev, MMC_IOC_CMD, idata);
+ if (ret != 0)
+ goto rpmb_end;
+
+ memset(idata, 0, sizeof(struct mmc_ioc_cmd));
+ memset(rpmb_pkt, 0, sizeof(struct mmc_rpmb_cfg));
+
+ idata->flags = RESP_R1;
+ idata->opcode = MMC_CMD_READ_MULTIPLE_BLOCK;
+ idata->blksz = 512;
+ idata->blocks = 1;
+ idata->write_flag = 0;
+ mmc_ioc_cmd_set_data((*idata), rpmb_pkt);
+
+ ret = bio_ioctl(rpdev, MMC_IOC_CMD, idata);
+ if (ret != 0)
+ goto rpmb_end;
+
+ reverse_endian(rpmb_pkt, 512);
+
+ ret = ((unsigned short *)&rpmb_pkt)[2];
+
+rpmb_end:
+ free(rpmb_pkt);
+ free(idata);
+ bio_close(rpdev);
+ return ret;
+}
diff --git a/src/bsp/lk/platform/mt2635/drivers/mmc/msdc.c b/src/bsp/lk/platform/mt2635/drivers/mmc/msdc.c
new file mode 100644
index 0000000..92dce4d
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/drivers/mmc/msdc.c
@@ -0,0 +1,1969 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#define MSDC_DEBUG_KICKOFF
+
+#include <platform/msdc.h>
+#include <platform/mmc_core.h>
+#include <kernel/event.h>
+#include <kernel/vm.h>
+#include <platform/interrupts.h>
+#include <platform/mt_irq.h>
+#include <string.h>
+#include <assert.h>
+
+#define CMD_RETRIES (5)
+#define CMD_TIMEOUT (100) /* 100ms */
+
+#define PERI_MSDC_SRCSEL (0xc100000c)
+
+/* Tuning Parameter */
+#define DEFAULT_DEBOUNCE (8) /* 8 cycles */
+#define DEFAULT_DTOC (40) /* data timeout counter. 65536x40 sclk. */
+#define DEFAULT_WDOD (0) /* write data output delay. no delay. */
+#define DEFAULT_BSYDLY (8) /* card busy delay. 8 extend sclk */
+
+/* Declarations */
+static int msdc_send_cmd(struct mmc_host *host, struct mmc_command *cmd);
+static int msdc_wait_cmd_done(struct mmc_host *host, struct mmc_command *cmd);
+static int msdc_tune_cmdrsp(struct mmc_host *host, struct mmc_command *cmd);
+
+typedef struct {
+ int autocmd;
+ int rdsmpl;
+ int wdsmpl;
+ int rsmpl;
+ int start_bit;
+} msdc_priv_t;
+
+static int msdc_rsp[] = {
+ 0, /* RESP_NONE */
+ 1, /* RESP_R1 */
+ 2, /* RESP_R2 */
+ 3, /* RESP_R3 */
+ 4, /* RESP_R4 */
+ 1, /* RESP_R5 */
+ 1, /* RESP_R6 */
+ 1, /* RESP_R7 */
+ 7, /* RESP_R1b */
+};
+
+struct msdc_cust {
+ unsigned char clk_src; /* host clock source */
+ unsigned char hclk_src; /* host clock source */
+ unsigned char cmd_edge; /* command latch edge */
+ unsigned char data_edge; /* data latch edge */
+#define MSDC_SMPL_RISING (0)
+#define MSDC_SMPL_FALLING (1)
+#define MSDC_SMPL_SEPERATE (2)
+ unsigned char clk_drv; /* clock pad driving */
+ unsigned char cmd_drv; /* command pad driving */
+ unsigned char dat_drv; /* data pad driving */
+ unsigned char rst_drv; /* reset pin pad driving */
+ unsigned char ds_drv; /* ds pad driving */
+ unsigned char data_pins; /* data pins */
+ unsigned int data_offset; /* data address offset */
+ unsigned int flags; /* hardware capability flags */
+#define MSDC_CD_PIN_EN (1 << 0) /* card detection pin is wired */
+#define MSDC_WP_PIN_EN (1 << 1) /* write protection pin is wired */
+#define MSDC_RST_PIN_EN (1 << 2) /* emmc reset pin is wired */
+#define MSDC_SDIO_IRQ (1 << 3) /* use internal sdio irq (bus) */
+#define MSDC_EXT_SDIO_IRQ (1 << 4) /* use external sdio irq */
+#define MSDC_REMOVABLE (1 << 5) /* removable slot */
+#define MSDC_SYS_SUSPEND (1 << 6) /* suspended by system */
+#define MSDC_HIGHSPEED (1 << 7) /* high-speed mode support */
+#define MSDC_UHS1 (1 << 8) /* uhs-1 mode support */
+#define MSDC_DDR (1 << 9) /* ddr mode support */
+#define MSDC_HS200 (1 << 10) /* hs200 mode support(eMMC4.5) */
+#define MSDC_HS400 (1 << 11) /* hs200 mode support(eMMC5.0) */
+} msdc_cap = {
+ MSDC30_CLKSRC_DEFAULT, /* host clock source */
+ MSDC50_CLKSRC4HCLK_182MHZ, /* host clock source */
+ MSDC_SMPL_RISING, /* command latch edge */
+ MSDC_SMPL_RISING, /* data latch edge */
+ MSDC_DRVN_GEAR1, /* clock pad driving */
+ MSDC_DRVN_GEAR1, /* command pad driving */
+ MSDC_DRVN_GEAR1, /* data pad driving */
+ MSDC_DRVN_GEAR1, /* rst pad driving */
+ MSDC_DRVN_GEAR1, /* ds pad driving */
+ 8, /* data pins */
+ 0, /* data address offset */
+ MSDC_HIGHSPEED
+};
+
+static event_t msdc_int_event;
+static u32 g_int_status = 0;
+static msdc_priv_t msdc_priv;
+static u32 hclks_msdc30[] = { 26000000, 208000000, 200000000, 156000000,
+ 182000000, 156000000, 178280000
+ };
+
+/* add function for MSDC_PAD_CTL handle */
+#ifndef FPGA_PLATFORM
+static void msdc_set_smt(struct mmc_host *host, int smt)
+{
+ MSDC_SET_FIELD(MSDC0_SMT, MSDC0_SMT_CLK_MASK, smt);
+ MSDC_SET_FIELD(MSDC0_SMT, MSDC0_SMT_CMD_MASK, smt);
+ MSDC_SET_FIELD(MSDC0_SMT, MSDC0_SMT_DAT_MASK, smt);
+}
+
+/* pull up means that host driver the line to HIGH
+ * pull down means that host driver the line to LOW */
+static void msdc_pin_set(struct mmc_host *host, MSDC_PIN_STATE mode)
+{
+ /* driver CLK/DAT pin */
+ ASSERT(host);
+ ASSERT(mode < MSDC_PST_MAX);
+
+ MSDC_SET_FIELD(MSDC0_CMD_PUPD, MSDC0_CMD_PUPD_MASK, mode);
+ MSDC_SET_FIELD(MSDC0_DAT0_PUPD, MSDC0_DAT0_PUPD_MASK, mode);
+ MSDC_SET_FIELD(MSDC0_DAT1_PUPD, MSDC0_DAT1_PUPD_MASK, mode);
+ MSDC_SET_FIELD(MSDC0_DAT2_PUPD, MSDC0_DAT2_PUPD_MASK, mode);
+ MSDC_SET_FIELD(MSDC0_DAT3_PUPD, MSDC0_DAT3_PUPD_MASK, mode);
+ MSDC_SET_FIELD(MSDC0_DAT4_PUPD, MSDC0_DAT4_PUPD_MASK, mode);
+ MSDC_SET_FIELD(MSDC0_DAT5_PUPD, MSDC0_DAT5_PUPD_MASK, mode);
+ MSDC_SET_FIELD(MSDC0_DAT6_PUPD, MSDC0_DAT6_PUPD_MASK, mode);
+ MSDC_SET_FIELD(MSDC0_DAT7_PUPD, MSDC0_DAT7_PUPD_MASK, mode);
+}
+
+/* host can modify from 0-7 */
+static void msdc_set_driving(struct mmc_host *host, struct msdc_cust *msdc_cap)
+{
+ ASSERT(host);
+ ASSERT(msdc_cap);
+
+ if (host && msdc_cap) {
+ MSDC_SET_FIELD(MSDC0_DRV, MSDC0_DRV_CMD_MASK, msdc_cap->cmd_drv);
+ MSDC_SET_FIELD(MSDC0_DRV, MSDC0_DRV_CLK_MASK, msdc_cap->clk_drv);
+ MSDC_SET_FIELD(MSDC0_DRV, MSDC0_DRV_DAT_MASK, msdc_cap->dat_drv);
+ }
+}
+#endif
+
+#ifndef FPGA_PLATFORM /* don't power on/off device and use power-on default volt */
+static int pmic_config_interface(int a, int b, int c, int d)
+{
+ return 0;
+}
+
+static void msdc_set_card_pwr(struct mmc_host *host, int on)
+{
+ unsigned int ret;
+
+ ret = pmic_config_interface(0xAB,0x7,0x7,4); /* VMCH=3.3V */
+
+ if (ret == 0) {
+ if (on) {
+ ret = pmic_config_interface(0xAB,0x1,0x1,0); /* VMCH_EN=1 */
+ } else {
+ ret = pmic_config_interface(0xAB,0x0,0x1,0); /* VMCH_EN=0 */
+ }
+ }
+
+ if (ret != 0) {
+ dprintf(CRITICAL, "PMIC: Set MSDC Host Power Fail\n");
+ } else {
+ spin(3000);
+ }
+}
+
+static void msdc_set_host_pwr(struct mmc_host *host, int on)
+{
+ unsigned int ret;
+
+ ret = pmic_config_interface(0xA7,0x7,0x7,4); /* VMC=3.3V */
+
+ if (ret == 0) {
+ if (on) {
+ ret = pmic_config_interface(0xA7,0x1,0x1,0); /* VMC_EN=1 */
+ } else {
+ ret = pmic_config_interface(0xA7,0x0,0x1,0); /* VMC_EN=0 */
+ }
+ }
+
+ if (ret != 0) {
+ dprintf(CRITICAL, "PMIC: Set MSDC Card Power Fail\n");
+ }
+}
+#else
+#define PWR_GPIO (0x10001E84)
+#define PWR_GPIO_EO (0x10001E88)
+
+#define PWR_MASK_EN (0x1 << 8)
+#define PWR_MASK_VOL_18 (0x1 << 9)
+#define PWR_MASK_VOL_33 (0x1 << 10)
+#define PWR_MASK_L4 (0x1 << 11)
+#define PWR_MSDC_DIR (PWR_MASK_EN | PWR_MASK_VOL_18 | PWR_MASK_VOL_33 | PWR_MASK_L4)
+
+#define MSDC0_PWR_MASK_EN (0x1 << 12)
+#define MSDC0_PWR_MASK_VOL_18 (0x1 << 13)
+#define MSDC0_PWR_MASK_VOL_33 (0x1 << 14)
+#define MSDC0_PWR_MASK_L4 (0x1 << 15)
+#define MSDC0_PWR_MSDC_DIR (MSDC0_PWR_MASK_EN | MSDC0_PWR_MASK_VOL_18 | MSDC0_PWR_MASK_VOL_33 | MSDC0_PWR_MASK_L4)
+
+static void msdc_clr_gpio(u32 bits)
+{
+ u32 l_val = 0;
+
+ switch (bits) {
+ case MSDC0_PWR_MASK_EN:
+ /* check for set before */
+ MSDC_SET_FIELD(PWR_GPIO, (MSDC0_PWR_MASK_EN),0);
+ MSDC_SET_FIELD(PWR_GPIO_EO, (MSDC0_PWR_MASK_EN),0);
+ break;
+ case MSDC0_PWR_MASK_VOL_18:
+ /* check for set before */
+ MSDC_SET_FIELD(PWR_GPIO, (MSDC0_PWR_MASK_VOL_18|MSDC0_PWR_MASK_VOL_33), 0);
+ MSDC_SET_FIELD(PWR_GPIO_EO, (MSDC0_PWR_MASK_VOL_18|MSDC0_PWR_MASK_VOL_33), 0);
+ break;
+ case MSDC0_PWR_MASK_VOL_33:
+ /* check for set before */
+ MSDC_SET_FIELD(PWR_GPIO, (MSDC0_PWR_MASK_VOL_18|MSDC0_PWR_MASK_VOL_33), 0);
+ MSDC_SET_FIELD(PWR_GPIO_EO, (MSDC0_PWR_MASK_VOL_18|MSDC0_PWR_MASK_VOL_33), 0);
+ break;
+ case MSDC0_PWR_MASK_L4:
+ /* check for set before */
+ MSDC_SET_FIELD(PWR_GPIO, MSDC0_PWR_MASK_L4, 0);
+ MSDC_SET_FIELD(PWR_GPIO_EO, MSDC0_PWR_MASK_L4, 0);
+ break;
+ case PWR_MASK_EN:
+ /* check for set before */
+ MSDC_SET_FIELD(PWR_GPIO, PWR_MASK_EN,0);
+ MSDC_SET_FIELD(PWR_GPIO_EO, PWR_MASK_EN,0);
+ break;
+ case PWR_MASK_VOL_18:
+ /* check for set before */
+ MSDC_SET_FIELD(PWR_GPIO, (PWR_MASK_VOL_18|PWR_MASK_VOL_33), 0);
+ MSDC_SET_FIELD(PWR_GPIO_EO, (PWR_MASK_VOL_18|PWR_MASK_VOL_33), 0);
+ break;
+ case PWR_MASK_VOL_33:
+ /* check for set before */
+ MSDC_SET_FIELD(PWR_GPIO, (PWR_MASK_VOL_18|PWR_MASK_VOL_33), 0);
+ MSDC_SET_FIELD(PWR_GPIO_EO, (PWR_MASK_VOL_18|PWR_MASK_VOL_33), 0);
+ break;
+ case PWR_MASK_L4:
+ /* check for set before */
+ MSDC_SET_FIELD(PWR_GPIO, PWR_MASK_L4, 0);
+ MSDC_SET_FIELD(PWR_GPIO_EO, PWR_MASK_L4, 0);
+ break;
+ default:
+ dprintf(CRITICAL, "[%s:%d]invalid value: 0x%x\n", __FILE__, __func__, bits);
+ break;
+ }
+}
+
+static void msdc_set_gpio(u32 bits)
+{
+ u32 l_val = 0;
+
+ switch (bits) {
+ case MSDC0_PWR_MASK_EN:
+ /* check for set before */
+ MSDC_SET_FIELD(PWR_GPIO, MSDC0_PWR_MASK_EN,1);
+ MSDC_SET_FIELD(PWR_GPIO_EO, MSDC0_PWR_MASK_EN,1);
+ break;
+ case MSDC0_PWR_MASK_VOL_18:
+ /* check for set before */
+ MSDC_SET_FIELD(PWR_GPIO, (MSDC0_PWR_MASK_VOL_18|MSDC0_PWR_MASK_VOL_33), 1);
+ MSDC_SET_FIELD(PWR_GPIO_EO, (MSDC0_PWR_MASK_VOL_18|MSDC0_PWR_MASK_VOL_33), 1);
+ break;
+ case MSDC0_PWR_MASK_VOL_33:
+ /* check for set before */
+ MSDC_SET_FIELD(PWR_GPIO, (MSDC0_PWR_MASK_VOL_18|MSDC0_PWR_MASK_VOL_33), 2);
+ MSDC_SET_FIELD(PWR_GPIO_EO, (MSDC0_PWR_MASK_VOL_18|MSDC0_PWR_MASK_VOL_33), 2);
+ break;
+ case MSDC0_PWR_MASK_L4:
+ /* check for set before */
+ MSDC_SET_FIELD(PWR_GPIO, MSDC0_PWR_MASK_L4, 1);
+ MSDC_SET_FIELD(PWR_GPIO_EO, MSDC0_PWR_MASK_L4, 1);
+ break;
+ case PWR_MASK_EN:
+ /* check for set before */
+ MSDC_SET_FIELD(PWR_GPIO, PWR_MASK_EN,1);
+ MSDC_SET_FIELD(PWR_GPIO_EO, PWR_MASK_EN,1);
+ break;
+ case PWR_MASK_VOL_18:
+ /* check for set before */
+ MSDC_SET_FIELD(PWR_GPIO, (PWR_MASK_VOL_18|PWR_MASK_VOL_33), 1);
+ MSDC_SET_FIELD(PWR_GPIO_EO, (PWR_MASK_VOL_18|PWR_MASK_VOL_33), 1);
+ break;
+ case PWR_MASK_VOL_33:
+ /* check for set before */
+ MSDC_SET_FIELD(PWR_GPIO, (PWR_MASK_VOL_18|PWR_MASK_VOL_33), 2);
+ MSDC_SET_FIELD(PWR_GPIO_EO, (PWR_MASK_VOL_18|PWR_MASK_VOL_33), 2);
+ break;
+ case PWR_MASK_L4:
+ /* check for set before */
+ MSDC_SET_FIELD(PWR_GPIO, PWR_MASK_L4, 1);
+ MSDC_SET_FIELD(PWR_GPIO_EO, PWR_MASK_L4, 1);
+ break;
+ default:
+ dprintf(CRITICAL, "[%s:%s]invalid value: 0x%x\n", __FILE__, __func__, bits);
+ break;
+ }
+}
+
+static void msdc_set_card_pwr(struct mmc_host *host, int on)
+{
+ if (on) {
+ msdc_set_gpio(MSDC0_PWR_MASK_VOL_18);
+ msdc_set_gpio(MSDC0_PWR_MASK_L4);
+ msdc_set_gpio(MSDC0_PWR_MASK_EN);
+ } else {
+ msdc_clr_gpio(MSDC0_PWR_MASK_EN);
+ msdc_clr_gpio(MSDC0_PWR_MASK_VOL_18);
+ msdc_clr_gpio(MSDC0_PWR_MASK_L4);
+ }
+ spin(10000);
+}
+
+static void msdc_set_host_level_pwr(struct mmc_host *host, u32 level)
+{
+ msdc_clr_gpio(PWR_MASK_VOL_18);
+ msdc_clr_gpio(PWR_MASK_VOL_33);
+
+ if (level) {
+ msdc_set_gpio(PWR_MASK_VOL_18);
+ } else {
+ msdc_set_gpio(PWR_MASK_VOL_33);
+ }
+ msdc_set_gpio(PWR_MASK_L4);
+}
+
+static void msdc_set_host_pwr(struct mmc_host *host, int on)
+{
+ msdc_set_host_level_pwr(host, 0);
+}
+#endif
+
+static void msdc_set_startbit(struct mmc_host *host, u8 start_bit)
+{
+ addr_t base = host->base;
+ msdc_priv_t *priv = (msdc_priv_t *)host->priv;
+
+ /* set start bit */
+ MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_START_BIT, start_bit);
+ priv->start_bit = start_bit;
+ dprintf(INFO, "start bit = %d, MSDC_CFG[0x%x]\n", start_bit, MSDC_READ32(MSDC_CFG));
+}
+
+#define TYPE_CMD_RESP_EDGE (0)
+#define TYPE_WRITE_CRC_EDGE (1)
+#define TYPE_READ_DATA_EDGE (2)
+#define TYPE_WRITE_DATA_EDGE (3)
+
+static void msdc_set_smpl(struct mmc_host *host, u8 HS400, u8 mode, u8 type)
+{
+ addr_t base = host->base;
+ int i=0;
+ msdc_priv_t *priv = (msdc_priv_t *)host->priv;
+ static u8 read_data_edge[8] = {MSDC_SMPL_RISING, MSDC_SMPL_RISING, MSDC_SMPL_RISING, MSDC_SMPL_RISING,
+ MSDC_SMPL_RISING, MSDC_SMPL_RISING, MSDC_SMPL_RISING, MSDC_SMPL_RISING
+ };
+ static u8 write_data_edge[4] = {MSDC_SMPL_RISING, MSDC_SMPL_RISING, MSDC_SMPL_RISING, MSDC_SMPL_RISING};
+
+ switch (type) {
+ case TYPE_CMD_RESP_EDGE:
+ if (HS400) {
+ // eMMC5.0 only output resp at CLK pin, so no need to select DS pin
+ MSDC_SET_FIELD(EMMC50_CFG0, MSDC_EMMC50_CFG_PADCMD_LATCHCK, 0); //latch cmd resp at CLK pin
+ MSDC_SET_FIELD(EMMC50_CFG0, MSDC_EMMC50_CFG_CMD_RESP_SEL, 0);//latch cmd resp at CLK pin
+ }
+
+ if (mode == MSDC_SMPL_RISING || mode == MSDC_SMPL_FALLING) {
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, mode);
+ priv->rsmpl = mode;
+ } else {
+ dprintf(CRITICAL, "[%s]: invalid resp parameter: HS400=%d, type=%d, mode=%d\n", __func__, HS400, type, mode);
+ }
+ break;
+
+ case TYPE_WRITE_CRC_EDGE:
+ if (HS400) {
+ MSDC_SET_FIELD(EMMC50_CFG0, MSDC_EMMC50_CFG_CRC_STS_SEL, 1);//latch write crc status at DS pin
+ } else {
+ MSDC_SET_FIELD(EMMC50_CFG0, MSDC_EMMC50_CFG_CRC_STS_SEL, 0);//latch write crc status at CLK pin
+ }
+
+ if (mode == MSDC_SMPL_RISING || mode == MSDC_SMPL_FALLING) {
+ if (HS400) {
+ MSDC_SET_FIELD(EMMC50_CFG0, MSDC_EMMC50_CFG_CRC_STS_EDGE, mode);
+ } else {
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_W_D_SMPL_SEL, 0);
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_W_D_SMPL, mode);
+ }
+ priv->wdsmpl = mode;
+ } else if (mode == MSDC_SMPL_SEPERATE && !HS400) {
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_W_D0SPL, write_data_edge[0]); //only dat0 is for write crc status.
+ priv->wdsmpl = mode;
+ } else {
+ dprintf(CRITICAL, "[%s]: invalid crc parameter: HS400=%d, type=%d, mode=%d\n", __func__, HS400, type, mode);
+ }
+ break;
+
+ case TYPE_READ_DATA_EDGE:
+ if (HS400) {
+ msdc_set_startbit(host, START_AT_RISING_AND_FALLING); //for HS400, start bit is output both on rising and falling edge
+ priv->start_bit = START_AT_RISING_AND_FALLING;
+ } else {
+ msdc_set_startbit(host, START_AT_RISING); //for the other mode, start bit is only output on rising edge. but DDR50 can try falling edge if error casued by pad delay
+ priv->start_bit = START_AT_RISING;
+ }
+ if (mode == MSDC_SMPL_RISING || mode == MSDC_SMPL_FALLING) {
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_R_D_SMPL_SEL, 0);
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_R_D_SMPL, mode);
+ priv->rdsmpl = mode;
+ } else if (mode == MSDC_SMPL_SEPERATE) {
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_R_D_SMPL_SEL, 1);
+ for (i=0; i<8; i++)
+ {
+ MSDC_SET_FIELD(MSDC_IOCON, (MSDC_IOCON_R_D0SPL << i), read_data_edge[i]);
+ }
+ priv->rdsmpl = mode;
+ } else {
+ dprintf(CRITICAL, "[%s]: invalid read parameter: HS400=%d, type=%d, mode=%d\n", __func__, HS400, type, mode);
+ }
+ break;
+
+ case TYPE_WRITE_DATA_EDGE:
+ MSDC_SET_FIELD(EMMC50_CFG0, MSDC_EMMC50_CFG_CRC_STS_SEL, 0);//latch write crc status at CLK pin
+
+ if (mode == MSDC_SMPL_RISING|| mode == MSDC_SMPL_FALLING) {
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_W_D_SMPL_SEL, 0);
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_W_D_SMPL, mode);
+ priv->wdsmpl = mode;
+ } else if (mode == MSDC_SMPL_SEPERATE) {
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_W_D_SMPL_SEL, 1);
+ for (i=0; i<4; i++)
+ {
+ MSDC_SET_FIELD(MSDC_IOCON, (MSDC_IOCON_W_D0SPL << i), write_data_edge[i]);//dat0~4 is for SDIO card.
+ }
+ priv->wdsmpl = mode;
+ } else {
+ dprintf(CRITICAL, "[%s]: invalid write parameter: HS400=%d, type=%d, mode=%d\n", __func__, HS400, type, mode);
+ }
+ break;
+
+ default:
+ dprintf(CRITICAL, "[%s]: invalid parameter: HS400=%d, type=%d, mode=%d\n", __func__, HS400, type, mode);
+ break;
+ }
+}
+
+void msdc_set_timeout(struct mmc_host *host, u32 ns, u32 clks)
+{
+ addr_t base = host->base;
+ u32 timeout, clk_ns;
+ u32 mode = 0;
+
+ if (host->sclk == 0) {
+ timeout = 0;
+ } else {
+ clk_ns = 1000000000UL / host->sclk;
+ timeout = (ns + clk_ns - 1) / clk_ns + clks;
+ timeout = (timeout + (1 << 20) - 1) >> 20; /* in 1048576 sclk cycle unit */
+ MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, mode);
+ timeout = mode >= 2 ? timeout * 2 : timeout; //DDR mode will double the clk cycles for data timeout
+ timeout = timeout > 1 ? timeout - 1 : 0;
+ timeout = timeout > 255 ? 255 : timeout;
+ }
+ MSDC_SET_FIELD(SDC_CFG, SDC_CFG_DTOC, timeout);
+ dprintf(INFO, "[MSDC] Set read data timeout: %dns %dclks -> %d (65536 sclk cycles)\n",
+ ns, clks, timeout + 1);
+}
+
+void msdc_set_autocmd(struct mmc_host *host, int cmd)
+{
+ msdc_priv_t *priv = (msdc_priv_t*)host->priv;
+
+ priv->autocmd = cmd;
+}
+
+int msdc_get_autocmd(struct mmc_host *host)
+{
+ msdc_priv_t *priv = (msdc_priv_t*)host->priv;
+
+ return priv->autocmd;
+}
+
+static void msdc_abort(struct mmc_host *host)
+{
+ addr_t base = host->base;
+
+ dprintf(CRITICAL, "[MSDC] Abort: MSDC_FIFOCS=%xh MSDC_PS=%xh SDC_STS=%xh\n",
+ MSDC_READ32(MSDC_FIFOCS), MSDC_READ32(MSDC_PS), MSDC_READ32(SDC_STS));
+ /* reset controller */
+ MSDC_RESET();
+
+ /* clear fifo */
+ MSDC_CLR_FIFO();
+
+ /* make sure txfifo and rxfifo are empty */
+ if (MSDC_TXFIFOCNT() != 0 || MSDC_RXFIFOCNT() != 0) {
+ dprintf(INFO, "[MSDC] Abort: TXFIFO(%d), RXFIFO(%d) != 0\n",
+ MSDC_TXFIFOCNT(), MSDC_RXFIFOCNT());
+ }
+
+ /* clear all interrupts */
+ MSDC_CLR_INT();
+}
+
+static int msdc_get_card_status(struct mmc_host *host, u32 *status)
+{
+ int err;
+ struct mmc_command cmd;
+
+ cmd.opcode = MMC_CMD_SEND_STATUS;
+ cmd.arg = host->card->rca << 16;
+ cmd.rsptyp = RESP_R1;
+ cmd.retries = CMD_RETRIES;
+ cmd.timeout = CMD_TIMEOUT;
+
+ err = msdc_send_cmd(host, &cmd);
+ if (!err)
+ err = msdc_wait_cmd_done(host, &cmd);
+
+ if (err == MMC_ERR_NONE)
+ *status = cmd.resp[0];
+
+ return err;
+}
+
+int msdc_abort_handler(struct mmc_host *host, int abort_card)
+{
+ struct mmc_command stop;
+ u32 status = 0;
+ u32 state = 0;
+
+ while (state != 4) { // until status to "tran"
+ msdc_abort(host);
+ if (msdc_get_card_status(host, &status)) {
+ dprintf(CRITICAL, "Get card status failed\n");
+ return 1;
+ }
+ state = R1_CURRENT_STATE(status);
+ dprintf(INFO, "check card state<%d>\n", state);
+ if (state == 5 || state == 6) {
+ dprintf(INFO, "state<%d> need cmd12 to stop\n", state);
+ if (abort_card) {
+ stop.opcode = MMC_CMD_STOP_TRANSMISSION;
+ stop.rsptyp = RESP_R1B;
+ stop.arg = 0;
+ stop.retries = CMD_RETRIES;
+ stop.timeout = CMD_TIMEOUT;
+ msdc_send_cmd(host, &stop);
+ msdc_wait_cmd_done(host, &stop); // don't tuning
+ } else if (state == 7) { // busy in programing
+ dprintf(INFO, "state<%d> card is busy\n", state);
+ spin(100000);
+ } else if (state != 4) {
+ dprintf(INFO, "state<%d> ??? \n", state);
+ return 1;
+ }
+ }
+ }
+ msdc_abort(host);
+ return 0;
+}
+
+static u32 msdc_intr_wait(struct mmc_host *host, u32 intrs)
+{
+ u32 sts = 0;
+ u32 tmo = UINT_MAX;
+ int ret = 0;
+
+ /* warning that interrupts are not enabled */
+ ret = event_wait_timeout(&msdc_int_event, tmo);
+ if (ret != 0) {
+ addr_t base = host->base;
+ dprintf(CRITICAL, "[%s]: failed to get event INT=0x%x\n",
+ __func__, MSDC_READ32(MSDC_INT));
+ g_int_status = 0;
+ return 0;
+ }
+
+ sts = g_int_status;
+ g_int_status = 0;
+
+ if (~intrs & sts)
+ dprintf(CRITICAL, "[MSDC]<CHECKME> Unexpected INT(0x%x)\n", ~intrs & sts);
+
+ return sts;
+}
+
+static enum handler_return msdc_interrupt_handler(void *arg)
+{
+ struct mmc_host *host = arg;
+ addr_t base = host->base;
+
+ /* Save & Clear the interrupt */
+ g_int_status = MSDC_READ32(MSDC_INT);
+ MSDC_WRITE32(MSDC_INT, g_int_status & host->intr_mask);
+ MSDC_WRITE32(MSDC_INTEN, 0);
+ host->intr_mask = 0;
+
+ /* MUST BE *false*! otherwise, schedule in interrupt */
+ event_signal(&msdc_int_event, false);
+
+ return INT_RESCHEDULE;
+}
+
+static int msdc_send_cmd(struct mmc_host *host, struct mmc_command *cmd)
+{
+ msdc_priv_t *priv = (msdc_priv_t *)host->priv;
+ addr_t base = host->base;
+ u32 opcode = cmd->opcode;
+ u32 rsptyp = cmd->rsptyp;
+ u32 rawcmd;
+ u32 error = MMC_ERR_NONE;
+
+ /* rawcmd :
+ * vol_swt << 30 | auto_cmd << 28 | blklen << 16 | go_irq << 15 |
+ * stop << 14 | rw << 13 | dtype << 11 | rsptyp << 7 | brk << 6 | opcode
+ */
+ rawcmd = (opcode & ~(SD_CMD_BIT | SD_CMD_APP_BIT)) |
+ msdc_rsp[rsptyp] << 7 | host->blklen << 16;
+
+ if (opcode == MMC_CMD_WRITE_MULTIPLE_BLOCK) {
+ rawcmd |= ((2 << 11) | (1 << 13));
+ if (priv->autocmd & MSDC_AUTOCMD12) {
+ rawcmd |= (1 << 28);
+ } else if (priv->autocmd & MSDC_AUTOCMD23) {
+ rawcmd |= (2 << 28);
+ }
+ } else if (opcode == MMC_CMD_WRITE_BLOCK || opcode == MMC_CMD50) {
+ rawcmd |= ((1 << 11) | (1 << 13));
+ } else if (opcode == MMC_CMD_READ_MULTIPLE_BLOCK) {
+ rawcmd |= (2 << 11);
+ if (priv->autocmd & MSDC_AUTOCMD12) {
+ rawcmd |= (1 << 28);
+ } else if (priv->autocmd & MSDC_AUTOCMD23) {
+ rawcmd |= (2 << 28);
+ }
+ } else if (opcode == MMC_CMD_READ_SINGLE_BLOCK ||
+ opcode == SD_ACMD_SEND_SCR ||
+ opcode == SD_CMD_SWITCH ||
+ opcode == MMC_CMD_SEND_EXT_CSD ||
+ opcode == MMC_CMD_SEND_WRITE_PROT ||
+ opcode == MMC_CMD_SEND_WRITE_PROT_TYPE ||
+ opcode == MMC_CMD21) {
+ rawcmd |= (1 << 11);
+ } else if (opcode == MMC_CMD_STOP_TRANSMISSION) {
+ rawcmd |= (1 << 14);
+ rawcmd &= ~(0x0FFF << 16);
+ } else if (opcode == SD_IO_RW_EXTENDED) {
+ if (cmd->arg & 0x80000000) /* R/W flag */
+ rawcmd |= (1 << 13);
+ if ((cmd->arg & 0x08000000) && ((cmd->arg & 0x1FF) > 1))
+ rawcmd |= (2 << 11); /* multiple block mode */
+ else
+ rawcmd |= (1 << 11);
+ } else if (opcode == SD_IO_RW_DIRECT) {
+ if ((cmd->arg & 0x80000000) && ((cmd->arg >> 9) & 0x1FFFF))/* I/O abt */
+ rawcmd |= (1 << 14);
+ } else if (opcode == SD_CMD_VOL_SWITCH) {
+ rawcmd |= (1 << 30);
+ } else if (opcode == SD_CMD_SEND_TUNING_BLOCK) {
+ rawcmd |= (1 << 11); /* CHECKME */
+ if (priv->autocmd & MSDC_AUTOCMD19)
+ rawcmd |= (3 << 28);
+ } else if (opcode == MMC_CMD_GO_IRQ_STATE) {
+ rawcmd |= (1 << 15);
+ } else if (opcode == MMC_CMD_WRITE_DAT_UNTIL_STOP) {
+ rawcmd |= ((1<< 13) | (3 << 11));
+ } else if (opcode == MMC_CMD_READ_DAT_UNTIL_STOP) {
+ rawcmd |= (3 << 11);
+ }
+
+ dprintf(INFO, "+[MSDC] CMD(%d): ARG(0x%x), RAW(0x%x), BLK_NUM(0x%x) RSP(%d)\n",
+ (opcode & ~(SD_CMD_BIT | SD_CMD_APP_BIT)), cmd->arg, rawcmd,
+ MSDC_READ32(SDC_BLK_NUM), rsptyp);
+
+ while (SDC_IS_CMD_BUSY());
+ if ((rsptyp == RESP_R1B) || (opcode == MMC_CMD_WRITE_MULTIPLE_BLOCK) ||
+ opcode == MMC_CMD_WRITE_BLOCK || opcode == MMC_CMD_READ_MULTIPLE_BLOCK ||
+ opcode == MMC_CMD_READ_SINGLE_BLOCK)
+ while (SDC_IS_BUSY());
+
+ SDC_SEND_CMD(rawcmd, cmd->arg);
+
+end:
+ cmd->error = error;
+
+ return error;
+}
+
+static int msdc_wait_cmd_done(struct mmc_host *host, struct mmc_command *cmd)
+{
+ addr_t base = host->base;
+ u32 rsptyp = cmd->rsptyp;
+ u32 status;
+ u32 opcode = (cmd->opcode & ~(SD_CMD_BIT | SD_CMD_APP_BIT));
+ u32 error = MMC_ERR_NONE;
+ u32 wints = MSDC_INT_CMDTMO | MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR |
+ MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO;
+ u32 *resp = &cmd->resp[0];
+ msdc_priv_t *priv = (msdc_priv_t *)host->priv;
+
+ while (1) {
+ /* Wait for interrupt coming */
+ while (((status = MSDC_READ32(MSDC_INT)) & wints) == 0);
+ MSDC_WRITE32(MSDC_INT, (status & wints));
+ if (~wints & status)
+ dprintf(CRITICAL, "[MSDC]<CHECKME> Unexpected INT(0x%x)\n",
+ ~wints & status);
+
+ if (status & MSDC_INT_CMDRDY)
+ break;
+ else if (status & MSDC_INT_RSPCRCERR) {
+ dprintf(CRITICAL, "[MSDC] cmd%d CRCERR! (0x%x)\n", opcode, status);
+ error = MMC_ERR_BADCRC;
+ goto err;
+ } else if (status & MSDC_INT_CMDTMO) {
+ dprintf(CRITICAL, "[MSDC] cmd%d TMO! (0x%x)\n", opcode, status);
+ error = MMC_ERR_TIMEOUT;
+ goto err;
+ } else if (priv->autocmd & MSDC_AUTOCMD23) {
+ if (status & MSDC_INT_ACMDRDY)
+ /* Autocmd rdy is set prior to cmd rdy */
+ continue;
+ else if (status & MSDC_INT_ACMDCRCERR) {
+ dprintf(CRITICAL, "[MSDC] autocmd23 CRCERR! (0x%x)\n", status);
+ error = MMC_ERR_ACMD_RSPCRC;
+ goto err;
+ } else if (status & MSDC_INT_ACMDTMO) {
+ dprintf(CRITICAL, "[MSDC] autocmd23 TMO! (0x%x)\n", status);
+ error = MMC_ERR_ACMD_TIMEOUT;
+ goto err;
+ }
+ } else {
+ dprintf(CRITICAL, "[MSDC] cmd%d UNEXPECT status! (0x%x)\n",
+ opcode, status);
+ error = MMC_ERR_UNEXPECT;
+ goto err;
+ }
+ }
+
+ switch (rsptyp) {
+ case RESP_NONE:
+ dprintf(INFO, "-[MSDC] CMD(%d): RSP(%d)\n",
+ opcode, rsptyp);
+ break;
+ case RESP_R2:
+ *resp++ = MSDC_READ32(SDC_RESP3);
+ *resp++ = MSDC_READ32(SDC_RESP2);
+ *resp++ = MSDC_READ32(SDC_RESP1);
+ *resp++ = MSDC_READ32(SDC_RESP0);
+ dprintf(INFO, "-[MSDC] CMD(%d): RSP(%d) = 0x%x 0x%x 0x%x 0x%x\n",
+ opcode, cmd->rsptyp, cmd->resp[0], cmd->resp[1],
+ cmd->resp[2], cmd->resp[3]);
+ break;
+ default: /* Response types 1, 3, 4, 5, 6, 7(1b) */
+ cmd->resp[0] = MSDC_READ32(SDC_RESP0);
+ dprintf(INFO, "-[MSDC] CMD(%d): RSP(%d) = 0x%x\n",
+ opcode, cmd->rsptyp, cmd->resp[0]);
+ break;
+ }
+
+err:
+ if (rsptyp == RESP_R1B)
+ while ((MSDC_READ32(MSDC_PS) & MSDC_PS_DAT0) != MSDC_PS_DAT0);
+
+ cmd->error = error;
+
+ return error;
+}
+
+int msdc_cmd(struct mmc_host *host, struct mmc_command *cmd)
+{
+ int err;
+
+ err = msdc_send_cmd(host, cmd);
+ if (err != MMC_ERR_NONE)
+ return err;
+
+ err = msdc_wait_cmd_done(host, cmd);
+
+ if (err) {
+ addr_t base = host->base;
+ u32 tmp = MSDC_READ32(SDC_CMD);
+
+ /* check if data is used by the command or not */
+ if (tmp & SDC_CMD_DTYP) {
+ if (msdc_abort_handler(host, 1)) {
+ dprintf(CRITICAL, "[MSDC] abort failed\n");
+ }
+ }
+
+ err = msdc_tune_cmdrsp(host, cmd);
+ }
+
+ return err;
+}
+
+#ifdef MSDC_USE_DMA_MODE
+static void msdc_flush_membuf(void *buf, u32 len)
+{
+ arch_clean_invalidate_cache_range((addr_t)buf,len);
+}
+
+static int msdc_dma_wait_done(struct mmc_host *host, struct mmc_command *cmd)
+{
+ addr_t base = host->base;
+ msdc_priv_t *priv = (msdc_priv_t *)host->priv;
+ u32 status;
+ u32 error = MMC_ERR_NONE;
+ u32 wints = MSDC_INT_XFER_COMPL | MSDC_INT_DATTMO | MSDC_INT_DATCRCERR |
+ MSDC_INT_DXFER_DONE | MSDC_INT_DMAQ_EMPTY |
+ MSDC_INT_ACMDRDY | MSDC_INT_ACMDTMO | MSDC_INT_ACMDCRCERR |
+ MSDC_INT_CMDRDY | MSDC_INT_CMDTMO | MSDC_INT_RSPCRCERR;
+
+ /* Deliver it to irq handler */
+ host->intr_mask = wints;
+
+ do {
+ status = msdc_intr_wait(host, wints);
+
+ if (status & MSDC_INT_XFER_COMPL) {
+ if (mmc_op_multi(cmd->opcode) && (priv->autocmd & MSDC_AUTOCMD12)) {
+ /* acmd rdy should be checked after xfer_done been held */
+ if (status & MSDC_INT_ACMDRDY) {
+ break;
+ } else if (status & MSDC_INT_ACMDTMO) {
+ dprintf(CRITICAL, "[MSDC] ACMD12 timeout(%xh)\n", status);
+ error = MMC_ERR_ACMD_TIMEOUT;
+ goto end;
+ } else if (status & MSDC_INT_ACMDCRCERR) {
+ dprintf(CRITICAL, "[MSDC] ACMD12 CRC error(%xh)\n", status);
+ error = MMC_ERR_ACMD_RSPCRC;
+ goto end;
+ }
+ } else
+ break;
+ }
+
+ if (status == 0 || status & MSDC_INT_DATTMO) {
+ dprintf(CRITICAL, "[MSDC] DMA DAT timeout(%xh)\n", status);
+ error = MMC_ERR_TIMEOUT;
+ goto end;
+ } else if (status & MSDC_INT_DATCRCERR) {
+ dprintf(CRITICAL, "[MSDC] DMA DAT CRC error(%xh)\n", status);
+ error = MMC_ERR_BADCRC;
+ goto end;
+ } else {
+ dprintf(CRITICAL, "[MSDC] Unexpect status(0x%x)\n", status);
+ error = MMC_ERR_UNEXPECT;
+ goto end;
+ }
+ } while (1);
+
+end:
+ if (error)
+ MSDC_RESET();
+
+ return error;
+}
+
+int msdc_dma_transfer(struct mmc_host *host, struct mmc_data *data)
+{
+ addr_t base = host->base;
+ int err;
+ paddr_t pa;
+
+ /* Set dma timeout */
+ msdc_set_timeout(host, data->timeout * 1000000, 0);
+ /* DRAM address */
+#if WITH_KERNEL_VM
+ pa = kvaddr_to_paddr(data->buf);
+#else
+ pa = data->buf;
+#endif
+ if (pa >> 32) {
+ dprintf(CRITICAL, "[MSDC] WARN: 64bit physical address!\n");
+ }
+ MSDC_WRITE32(MSDC_DMA_SA, (u32)pa);
+ MSDC_SET_FIELD(MSDC_DMA_CTRL, MSDC_DMA_CTRL_BURSTSZ, MSDC_DMA_BURST_64B);
+ /* BASIC_DMA mode */
+ MSDC_SET_FIELD(MSDC_DMA_CTRL, MSDC_DMA_CTRL_MODE, 0);
+ /* This is the last buffer */
+ MSDC_SET_FIELD(MSDC_DMA_CTRL, MSDC_DMA_CTRL_LASTBUF, 1);
+ /* Total transfer size */
+ MSDC_WRITE32(MSDC_DMA_LEN, data->blks * host->blklen);
+ /* Set interrupts bit */
+ MSDC_SET_BIT32(MSDC_INTEN,
+ MSDC_INT_XFER_COMPL | MSDC_INT_DATTMO | MSDC_INT_DATCRCERR);
+ /* Clean & Invalidate cache */
+ msdc_flush_membuf(data->buf, data->blks * host->blklen);
+ /* Trigger DMA start */
+ MSDC_SET_FIELD(MSDC_DMA_CTRL, MSDC_DMA_CTRL_START, 1);
+ /* wait DMA transferring done */
+ err = msdc_dma_wait_done(host, data->cmd);
+ if (err) {
+ dprintf(CRITICAL, "[MSDC] DMA failed! err(%d)\n", err);
+ if (msdc_abort_handler(host, 1)) {
+ dprintf(CRITICAL, "[MSDC] eMMC cannot back to TRANS mode!\n");
+ return MMC_ERR_FAILED;
+ }
+ }
+
+ /* Check DMA status and stop DMA transfer */
+ MSDC_SET_FIELD(MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP, 1);
+ while (MSDC_READ32(MSDC_DMA_CFG) & MSDC_DMA_CFG_STS);
+
+ return err;
+}
+
+static int msdc_dma_rw(struct mmc_host *host, u8 *buf, u32 blkaddr, u32 nblks, bool rd)
+{
+ int multi, err;
+ struct mmc_command cmd;
+ struct mmc_data data;
+ addr_t base = host->base;
+
+ ASSERT(nblks <= host->max_phys_segs);
+
+ dprintf(INFO, "[MSDC] %s data %d blks %s 0x%x\n",
+ rd ? "Read" : "Write", nblks, rd ? "from" : "to", blkaddr);
+
+ multi = nblks > 1 ? 1 : 0;
+ /* DMA and block number _MUST_BE_ set prior to issuing command */
+ MSDC_DMA_ON;
+ MSDC_WRITE32(SDC_BLK_NUM, nblks);
+
+ /* send read command */
+ if (rd)
+ cmd.opcode =
+ multi ? MMC_CMD_READ_MULTIPLE_BLOCK : MMC_CMD_READ_SINGLE_BLOCK;
+ else
+ cmd.opcode = multi ? MMC_CMD_WRITE_MULTIPLE_BLOCK : MMC_CMD_WRITE_BLOCK;
+ cmd.arg = blkaddr;
+ cmd.rsptyp = RESP_R1;
+ cmd.retries = 0;
+ cmd.timeout = CMD_TIMEOUT;
+
+ err = msdc_cmd(host, &cmd);
+ if (err != MMC_ERR_NONE)
+ return err;
+
+ data.cmd = &cmd;
+ data.blks = nblks;
+ data.buf = buf;
+ if (rd)
+ data.timeout = 100;
+ else
+ data.timeout = 250;
+
+ err = msdc_dma_transfer(host, &data);
+ MSDC_DMA_OFF;
+
+ return err;
+}
+
+static int msdc_dma_bread(struct mmc_host *host, u8 *dst, u32 src, u32 nblks)
+{
+ return msdc_dma_rw(host, dst, src, nblks, true);
+}
+
+static int msdc_dma_bwrite(struct mmc_host *host, u32 dst, u8 *src, u32 nblks)
+{
+ return msdc_dma_rw(host, src, dst, nblks, false);
+}
+#else
+static int msdc_pio_read_word(struct mmc_host *host, u32 *ptr, u32 size)
+{
+ int err = MMC_ERR_NONE;
+ addr_t base = host->base;
+ u32 ints = MSDC_INT_DATCRCERR | MSDC_INT_DATTMO | MSDC_INT_XFER_COMPL;
+ //u32 timeout = 100000;
+ u32 status;
+ u32 totalsz = size;
+ u8 done = 0;
+ u8 *u8ptr;
+ u32 dcrc=0;
+
+ while (1) {
+ status = MSDC_READ32(MSDC_INT);
+ MSDC_WRITE32(MSDC_INT, status);
+ if (status & ~ints)
+ dprintf(CRITICAL, "[MSDC]<CHECKME> Unexpected INT(0x%x)\n", status);
+ if (status & MSDC_INT_DATCRCERR) {
+ MSDC_GET_FIELD(SDC_DCRC_STS, SDC_DCRC_STS_POS|SDC_DCRC_STS_NEG, dcrc);
+ dprintf(CRITICAL, "[MSDC] DAT CRC error (0x%x), Left:%d/%d bytes, RXFIFO:%d,dcrc:0x%x\n",
+ status, size, totalsz, MSDC_RXFIFOCNT(),dcrc);
+ err = MMC_ERR_BADCRC;
+ break;
+ } else if (status & MSDC_INT_DATTMO) {
+ dprintf(CRITICAL, "[MSDC] DAT TMO error (0x%x), Left: %d/%d bytes, RXFIFO:%d\n",
+ status, size, totalsz, MSDC_RXFIFOCNT());
+ err = MMC_ERR_TIMEOUT;
+ break;
+ } else if (status & MSDC_INT_ACMDCRCERR) {
+ MSDC_GET_FIELD(SDC_DCRC_STS, SDC_DCRC_STS_POS|SDC_DCRC_STS_NEG, dcrc);
+ dprintf(CRITICAL, "[MSDC] AUTOCMD CRC error (0x%x), Left:%d/%d bytes, RXFIFO:%d,dcrc:0x%x\n",
+ status, size, totalsz, MSDC_RXFIFOCNT(),dcrc);
+ err = MMC_ERR_ACMD_RSPCRC;
+ break;
+ } else if (status & MSDC_INT_XFER_COMPL) {
+ done = 1;
+ }
+
+ if (size == 0 && done)
+ break;
+
+ /* Note. RXFIFO count would be aligned to 4-bytes alignment size */
+ if ((size >= MSDC_FIFO_THD) && (MSDC_RXFIFOCNT() >= MSDC_FIFO_THD)) {
+ int left = MSDC_FIFO_THD >> 2;
+ do {
+ *ptr++ = MSDC_FIFO_READ32();
+ } while (--left);
+ size -= MSDC_FIFO_THD;
+ dprintf(INFO, "[MSDC] Read %d bytes, RXFIFOCNT: %d, Left: %d/%d\n",
+ MSDC_FIFO_THD, MSDC_RXFIFOCNT(), size, totalsz);
+ } else if ((size < MSDC_FIFO_THD) && MSDC_RXFIFOCNT() >= size) {
+ while (size) {
+ if (size > 3) {
+ *ptr++ = MSDC_FIFO_READ32();
+ } else {
+ u8ptr = (u8 *)ptr;
+ while (size --)
+ *u8ptr++ = MSDC_FIFO_READ8();
+ }
+ }
+ dprintf(INFO, "[MSDC] Read left bytes, RXFIFOCNT: %d, Left: %d/%d\n",
+ MSDC_RXFIFOCNT(), size, totalsz);
+ }
+ }
+
+ return err;
+}
+
+static int msdc_pio_read(struct mmc_host *host, u32 *ptr, u32 size)
+{
+ int err = msdc_pio_read_word(host, (u32 *)ptr, size);
+
+ if (err != MMC_ERR_NONE) {
+ msdc_abort(host); /* reset internal fifo and state machine */
+ dprintf(CRITICAL, "[MSDC] %d-bit PIO Read Error (%d)\n", 32, err);
+ }
+
+ return err;
+}
+
+static int msdc_pio_write_word(struct mmc_host *host, u32 *ptr, u32 size)
+{
+ int err = MMC_ERR_NONE;
+ addr_t base = host->base;
+ u32 ints = MSDC_INT_DATCRCERR | MSDC_INT_DATTMO | MSDC_INT_XFER_COMPL;
+ //u32 timeout = 250000;
+ u32 status;
+ u8 *u8ptr;
+ msdc_priv_t *priv = (msdc_priv_t *)host->priv;
+
+ while (1) {
+ status = MSDC_READ32(MSDC_INT);
+ MSDC_WRITE32(MSDC_INT, status);
+ if (status & ~ints) {
+ dprintf(CRITICAL, "[MSDC]<CHECKME> Unexpected INT(0x%x)\n", status);
+ }
+ if (status & MSDC_INT_DATCRCERR) {
+ dprintf(CRITICAL, "[MSDC] DAT CRC error (0x%x), Left DAT: %d bytes\n",
+ status, size);
+ err = MMC_ERR_BADCRC;
+ break;
+ } else if (status & MSDC_INT_DATTMO) {
+ dprintf(CRITICAL, "[MSDC] DAT TMO error (0x%x), Left DAT: %d bytes, MSDC_FIFOCS=%xh\n",
+ status, size, MSDC_READ32(MSDC_FIFOCS));
+ err = MMC_ERR_TIMEOUT;
+ break;
+ } else if (status & MSDC_INT_ACMDCRCERR) {
+ dprintf(CRITICAL, "[MSDC] AUTO CMD CRC error (0x%x), Left DAT: %d bytes\n",
+ status, size);
+ err = MMC_ERR_ACMD_RSPCRC;
+ break;
+ } else if (status & MSDC_INT_XFER_COMPL) {
+ if (size == 0) {
+ dprintf(INFO, "[MSDC] all data flushed to card\n");
+ break;
+ } else
+ dprintf(INFO, "[MSDC]<CHECKME> XFER_COMPL before all data written\n");
+ }
+
+ if (size == 0)
+ continue;
+
+ if (size >= MSDC_FIFO_SZ) {
+ if (MSDC_TXFIFOCNT() == 0) {
+ int left = MSDC_FIFO_SZ >> 2;
+ do {
+ MSDC_FIFO_WRITE32(*ptr);
+ ptr++;
+ } while (--left);
+ size -= MSDC_FIFO_SZ;
+ }
+ } else if (size < MSDC_FIFO_SZ && MSDC_TXFIFOCNT() == 0) {
+ while (size ) {
+ if (size > 3) {
+ MSDC_FIFO_WRITE32(*ptr);
+ ptr++;
+ size -= 4;
+ } else {
+ u8ptr = (u8 *)ptr;
+ while (size --) {
+ MSDC_FIFO_WRITE8(*u8ptr);
+ u8ptr++;
+ }
+ }
+ }
+ }
+ }
+
+ return err;
+}
+
+static int msdc_pio_write(struct mmc_host *host, u32 *ptr, u32 size)
+{
+ int err = msdc_pio_write_word(host, (u32 *)ptr, size);
+
+ if (err != MMC_ERR_NONE) {
+ msdc_abort(host); /* reset internal fifo and state machine */
+ dprintf(CRITICAL, "[MSDC] PIO Write Error (%d)\n", err);
+ }
+
+ return err;
+}
+
+static int msdc_pio_bread(struct mmc_host *host, u8 *dst, u32 src, u32 nblks)
+{
+ msdc_priv_t *priv = (msdc_priv_t *)host->priv;
+ addr_t base = host->base;
+ u32 blksz = host->blklen;
+ int err = MMC_ERR_NONE, derr = MMC_ERR_NONE;
+ int multi;
+ struct mmc_command cmd;
+ struct mmc_command stop;
+ u32 *ptr = (u32 *)dst;
+
+ dprintf(INFO, "[MSDC] Read data %d bytes from 0x%x\n", nblks * blksz, src);
+
+ multi = nblks > 1 ? 1 : 0;
+
+ MSDC_CLR_FIFO();
+ MSDC_WRITE32(SDC_BLK_NUM, nblks);
+ msdc_set_timeout(host, 100000000, 0);
+
+ /* send read command */
+ cmd.opcode = multi ? MMC_CMD_READ_MULTIPLE_BLOCK : MMC_CMD_READ_SINGLE_BLOCK;
+ cmd.rsptyp = RESP_R1;
+ cmd.arg = src;
+ cmd.retries = 0;
+ cmd.timeout = CMD_TIMEOUT;
+ err = msdc_cmd(host, &cmd);
+
+ if (err != MMC_ERR_NONE)
+ goto done;
+
+ err = derr = msdc_pio_read(host, (u32 *)ptr, nblks * blksz);
+
+done:
+ if (err != MMC_ERR_NONE) {
+ if (derr != MMC_ERR_NONE) {
+ dprintf(CRITICAL, "[MSDC] Read data error (%d)\n", derr);
+ if (msdc_abort_handler(host, 1))
+ dprintf(CRITICAL, "[MSDC] abort failed\n");
+ } else {
+ dprintf(CRITICAL, "[MSDC] Read error (%d)\n", err);
+ }
+ }
+ return (derr == MMC_ERR_NONE) ? err : derr;
+}
+
+static int msdc_pio_bwrite(struct mmc_host *host, u32 dst, u8 *src, u32 nblks)
+{
+ msdc_priv_t *priv = (msdc_priv_t *)host->priv;
+ addr_t base = host->base;
+ int err = MMC_ERR_NONE, derr = MMC_ERR_NONE;
+ int multi;
+ u32 blksz = host->blklen;
+ struct mmc_command cmd;
+ struct mmc_command stop;
+ u32 *ptr = (u32 *)src;
+
+ dprintf(CRITICAL, "[MSDC] Write data %d bytes to 0x%x\n", nblks * blksz, dst);
+
+ multi = nblks > 1 ? 1 : 0;
+
+ MSDC_CLR_FIFO();
+ MSDC_WRITE32(SDC_BLK_NUM, nblks);
+
+ /* No need since MSDC always waits 8 cycles for write data timeout */
+
+ /* send write command */
+ cmd.opcode = multi ? MMC_CMD_WRITE_MULTIPLE_BLOCK : MMC_CMD_WRITE_BLOCK;
+ cmd.rsptyp = RESP_R1;
+ cmd.arg = dst;
+ cmd.retries = 0;
+ cmd.timeout = CMD_TIMEOUT;
+ err = msdc_cmd(host, &cmd);
+
+ if (err != MMC_ERR_NONE)
+ goto done;
+
+ err = derr = msdc_pio_write(host, (u32 *)ptr, nblks * blksz);
+
+done:
+ if (err != MMC_ERR_NONE) {
+ if (derr != MMC_ERR_NONE) {
+ dprintf(CRITICAL, "[MSDC] Write data error (%d)\n", derr);
+ if (msdc_abort_handler(host, 1))
+ dprintf(CRITICAL, "[MSDC] abort failed\n");
+ } else {
+ dprintf(CRITICAL, "[MSDC] Write error (%d)\n", err);
+ }
+ }
+ return (derr == MMC_ERR_NONE) ? err : derr;
+}
+#endif
+
+
+static void msdc_config_clksrc(struct mmc_host *host, u32 clksrc, u32 hclksrc)
+{
+ // modify the clock
+ ASSERT(host);
+ /* Perloader and LK use 200 is ok, no need change source */
+ host->clksrc = clksrc;
+ host->hclksrc = hclksrc;
+ host->clk = hclks_msdc30[clksrc];
+
+ /* Chaotian, may need update this part of code */
+ dprintf(INFO, "[info][%s] pll_clk %u (%uMHz), pll_hclk %u\n",
+ __func__, host->clksrc, host->clk/1000000, host->hclksrc);
+}
+
+void msdc_config_clock(struct mmc_host *host, int state, u32 hz)
+{
+ msdc_priv_t *priv = host->priv;
+ addr_t base = host->base;
+ u32 mode, hs400_src = 0;
+ u32 div;
+ u32 sclk;
+ u32 u4buswidth=0;
+
+ if (hz >= host->f_max) {
+ hz = host->f_max;
+ } else if (hz < host->f_min) {
+ hz = host->f_min;
+ }
+
+ msdc_config_clksrc(host, host->clksrc, host->hclksrc);
+
+ if (state&MMC_STATE_DDR) {
+ mode = 0x2; /* ddr mode and use divisor */
+ if (hz >= (host->clk >> 2)) {
+ div = 0; /* mean div = 1/2 */
+ sclk = host->clk >> 2; /* sclk = clk/div/2. 2: internal divisor */
+ } else {
+ div = (host->clk + ((hz << 2) - 1)) / (hz << 2);
+ sclk = (host->clk >> 2) / div;
+ div = (div >> 1); /* since there is 1/2 internal divisor */
+ }
+ } else if (hz >= host->clk) {
+ mode = 0x1; /* no divisor and divisor is ignored */
+ div = 0;
+ sclk = host->clk;
+ } else {
+ mode = 0x0; /* use divisor */
+ if (hz >= (host->clk >> 1)) {
+ div = 0; /* mean div = 1/2 */
+ sclk = host->clk >> 1; /* sclk = clk / 2 */
+ } else {
+ div = (host->clk + ((hz << 2) - 1)) / (hz << 2);
+ sclk = (host->clk >> 2) / div;
+ }
+ }
+ host->sclk = sclk;
+
+ /* set clock mode and divisor */
+ MSDC_SET_FIELD(MSDC_CFG, (MSDC_CFG_CKMOD_HS400 | MSDC_CFG_CKMOD |MSDC_CFG_CKDIV),\
+ (hs400_src << 14) | (mode << 12) | div);
+ /* wait clock stable */
+ while (!(MSDC_READ32(MSDC_CFG) & MSDC_CFG_CKSTB));
+
+ if (host->card && mmc_card_hs400(host->card)) {
+ msdc_set_smpl(host, 1, priv->rsmpl, TYPE_CMD_RESP_EDGE);
+ msdc_set_smpl(host, 1, priv->rdsmpl, TYPE_READ_DATA_EDGE);
+ msdc_set_smpl(host, 1, priv->wdsmpl, TYPE_WRITE_CRC_EDGE);
+ MSDC_SET_FIELD(MSDC_PATCH_BIT2, MSDC_PB2_CFGCRCSTS,0);
+ MSDC_SET_FIELD(MSDC_PATCH_BIT2, MSDC_PB2_CRCSTSENSEL,1);
+ } else {
+ msdc_set_smpl(host, 0, priv->rsmpl, TYPE_CMD_RESP_EDGE);
+ msdc_set_smpl(host, 0, priv->rdsmpl, TYPE_READ_DATA_EDGE);
+ msdc_set_smpl(host, 0, priv->wdsmpl, TYPE_WRITE_CRC_EDGE);
+#ifdef MSDC_USE_PATCH_BIT2_TURNING_WITH_ASYNC
+ MSDC_SET_FIELD(MSDC_PATCH_BIT2, MSDC_PB2_CFGCRCSTS,1);
+#else
+ MSDC_SET_FIELD(MSDC_PATCH_BIT2, MSDC_PB2_CFGCRCSTS,0);
+#endif
+ MSDC_SET_FIELD(MSDC_PATCH_BIT2, MSDC_PB2_CRCSTSENSEL,0);
+ }
+ MSDC_GET_FIELD(SDC_CFG,SDC_CFG_BUSWIDTH,u4buswidth);
+
+ dprintf(INFO,
+ "[MSDC] SET_CLK(%dkHz): SCLK(%dkHz) MODE(%d) DIV(%d) DS(%d) RS(%d) buswidth(%s)\n",
+ hz/1000, sclk/1000, mode, div, msdc_cap.data_edge,
+ msdc_cap.cmd_edge,
+ (u4buswidth == 0) ?
+ "1-bit" : (u4buswidth == 1) ?
+ "4-bits" : (u4buswidth == 2) ?
+ "8-bits" : "undefined");
+}
+
+void msdc_config_bus(struct mmc_host *host, u32 width)
+{
+ u32 val,mode, div;
+ addr_t base = host->base;
+
+ val = (width == HOST_BUS_WIDTH_8) ? 2 :
+ (width == HOST_BUS_WIDTH_4) ? 1 : 0;
+
+ MSDC_SET_FIELD(SDC_CFG, SDC_CFG_BUSWIDTH, val);
+ MSDC_GET_FIELD(MSDC_CFG,MSDC_CFG_CKMOD,mode);
+ MSDC_GET_FIELD(MSDC_CFG,MSDC_CFG_CKDIV,div);
+
+ dprintf(INFO, "CLK (%dMHz), SCLK(%dkHz) MODE(%d) DIV(%d) buswidth(%u-bits)\n",
+ host->clk/1000000, host->sclk/1000, mode, div, width);
+}
+
+static void msdc_config_pin(struct mmc_host *host, int mode)
+{
+ dprintf(INFO, "[MSDC] Pins mode(%d), none(0), down(1), up(2), keep(3)\n", mode);
+
+ switch (mode) {
+ case MSDC_PIN_PULL_UP:
+ msdc_pin_set(host,MSDC_PST_PU_50KOHM);
+ break;
+ case MSDC_PIN_PULL_DOWN:
+ msdc_pin_set(host,MSDC_PST_PD_50KOHM);
+ break;
+ case MSDC_PIN_PULL_NONE:
+ default:
+ msdc_pin_set(host,MSDC_PST_PD_50KOHM);
+ break;
+ }
+}
+
+void msdc_clock(struct mmc_host *host, int on)
+{
+ /* Chaotian, may need update this part of code */
+ dprintf(INFO, "[MSDC] Turn %s %s clock \n", on ? "on" : "off", "host");
+}
+
+static void msdc_host_power(struct mmc_host *host, int on)
+{
+ dprintf(INFO, "[MSDC] Turn %s %s power \n", on ? "on" : "off", "host");
+
+ if (on) {
+ MSDC_SET_FIELD(MSDC0_RSTB_PUPD, MSDC0_RSTB_PUPD_MASK, MSDC_PST_PD_50KOHM);
+ spin(10);
+ MSDC_SET_FIELD(MSDC0_RSTB_PUPD, MSDC0_RSTB_PUPD_MASK, MSDC_PST_PU_50KOHM);
+ spin(200);
+ msdc_config_pin(host, MSDC_PIN_PULL_UP);
+ msdc_set_host_pwr(host, 1);
+ msdc_clock(host, 1);
+ } else {
+ msdc_clock(host, 0);
+ msdc_set_host_pwr(host, 0);
+ msdc_config_pin(host, MSDC_PIN_PULL_DOWN);
+ }
+}
+
+static void msdc_card_power(struct mmc_host *host, int on)
+{
+ dprintf(INFO, "[MSDC] Turn %s %s power \n", on ? "on" : "off", "card");
+
+ if (on) {
+ msdc_set_card_pwr(host, 1);
+ } else {
+ msdc_set_card_pwr(host, 0);
+ }
+}
+
+void msdc_power(struct mmc_host *host, u8 mode)
+{
+ if (mode == MMC_POWER_ON || mode == MMC_POWER_UP) {
+ msdc_host_power(host, 1);
+ msdc_card_power(host, 1);
+ } else {
+ msdc_card_power(host, 0);
+ msdc_host_power(host, 0);
+ }
+}
+
+void msdc_reset_tune_counter(struct mmc_host *host)
+{
+ host->time_read = 0;
+}
+
+#ifdef FEATURE_MMC_CM_TUNING
+static int msdc_tune_cmdrsp(struct mmc_host *host, struct mmc_command *cmd)
+{
+ addr_t base = host->base;
+ u32 sel = 0;
+ u32 rsmpl,cur_rsmpl, orig_rsmpl;
+ u32 rrdly,cur_rrdly, orig_rrdly;
+ u32 cntr,cur_cntr,orig_cmdrtc;
+ u32 dl_cksel, cur_dl_cksel, orig_dl_cksel;
+ u32 times = 0;
+ int result = MMC_ERR_CMDTUNEFAIL;
+ u32 tmp = 0;
+
+ if (host->sclk > 100000000) {
+ sel = 1;
+ //MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_RX_SDCLKO_SEL,0);
+ }
+
+ MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, orig_rsmpl);
+ MSDC_GET_FIELD(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRDLY, orig_rrdly);
+ MSDC_GET_FIELD(MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_CMD_RSP, orig_cmdrtc);
+ MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL, orig_dl_cksel);
+
+ dl_cksel = 0;
+ do {
+ cntr = 0;
+ do {
+ rrdly = 0;
+ do {
+ for (rsmpl = 0; rsmpl < 2; rsmpl++) {
+ cur_rsmpl = (orig_rsmpl + rsmpl) % 2;
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, cur_rsmpl);
+ if (host->sclk <= 400000) { //In sd/emmc init flow, fix rising edge for latching cmd response
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, 0);
+ }
+ if (cmd->opcode != MMC_CMD_STOP_TRANSMISSION) {
+ result = msdc_send_cmd(host, cmd);
+ if (result == MMC_ERR_TIMEOUT)
+ rsmpl--;
+ if (result != MMC_ERR_NONE && cmd->opcode != MMC_CMD_STOP_TRANSMISSION) {
+ if (cmd->opcode == MMC_CMD_READ_MULTIPLE_BLOCK || cmd->opcode == MMC_CMD_WRITE_MULTIPLE_BLOCK || cmd->opcode == MMC_CMD_READ_SINGLE_BLOCK ||cmd->opcode == MMC_CMD_WRITE_BLOCK)
+ msdc_abort_handler(host,1);
+ continue;
+ }
+ result = msdc_wait_cmd_done(host, cmd);
+ } else if (cmd->opcode == MMC_CMD_STOP_TRANSMISSION) {
+ result = MMC_ERR_NONE;
+ goto done;
+ } else
+ result = MMC_ERR_BADCRC;
+
+ times++;
+ if (result == MMC_ERR_NONE)
+ goto done;
+ tmp = MSDC_READ32(SDC_CMD);
+ /* check if data is used by the command or not */
+ if (tmp & 0x1800) {
+ if (msdc_abort_handler(host, 1))
+ dprintf(CRITICAL, "[MSDC] abort failed\n");
+ }
+ }
+ cur_rrdly = (orig_rrdly + rrdly + 1) % 32;
+ MSDC_SET_FIELD(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRDLY, cur_rrdly);
+ } while (++rrdly < 32);
+ if (!sel)
+ break;
+ cur_cntr = (orig_cmdrtc + cntr + 1) % 8;
+ MSDC_SET_FIELD(MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_CMD_RSP, cur_cntr);
+ } while (++cntr < 8);
+ /* no need to update data ck sel */
+ if (!sel)
+ break;
+ cur_dl_cksel = (orig_dl_cksel +dl_cksel+1) % 8;
+ MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL, cur_dl_cksel);
+ dl_cksel++;
+ } while (dl_cksel < 8);
+ /* no need to update ck sel */
+ if (result != MMC_ERR_NONE)
+ result = MMC_ERR_CMDTUNEFAIL;
+done:
+
+ dprintf(ALWAYS, "[MSDC] <TUNE_CMD><%d><%s>\n", times, (result == MMC_ERR_NONE) ?"PASS" : "FAIL");
+ return result;
+}
+#endif
+
+#ifdef FEATURE_MMC_RD_TUNING
+int msdc_tune_bread(struct mmc_host *host, u8 *dst, u32 src, u32 nblks)
+{
+ addr_t base = host->base;
+ u32 dcrc = 1, ddr = 0, sel = 0;
+ u32 cur_rxdly0, cur_rxdly1;
+ u32 dsmpl, cur_dsmpl, orig_dsmpl;
+ u32 dsel,cur_dsel,orig_dsel;
+ u32 dl_cksel,cur_dl_cksel,orig_dl_cksel;
+ u32 rxdly;
+ u32 cur_dat0, cur_dat1, cur_dat2, cur_dat3, cur_dat4, cur_dat5,
+ cur_dat6, cur_dat7;
+ u32 orig_dat0, orig_dat1, orig_dat2, orig_dat3, orig_dat4, orig_dat5,
+ orig_dat6, orig_dat7;
+ u32 orig_clkmode;
+ u32 times = 0;
+ int result = MMC_ERR_READTUNEFAIL;
+
+ if (host->sclk > 100000000)
+ sel = 1;
+ if (host->card)
+ ddr = mmc_card_ddr(host->card);
+ MSDC_GET_FIELD(MSDC_CFG,MSDC_CFG_CKMOD,orig_clkmode);
+ MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, orig_dsel);
+ MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL, orig_dl_cksel);
+ MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_DSPL, orig_dsmpl);
+
+ /* Tune Method 2. delay each data line */
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_DDLSEL, 1);
+
+ dl_cksel = 0;
+ do {
+ dsel = 0;
+ do {
+ rxdly = 0;
+ do {
+ for (dsmpl = 0; dsmpl < 2; dsmpl++) {
+ cur_dsmpl = (orig_dsmpl + dsmpl) % 2;
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_DSPL, cur_dsmpl);
+ result = host->blk_read(host, dst, src, nblks);
+ if (result == MMC_ERR_CMDTUNEFAIL || result == MMC_ERR_CMD_RSPCRC || result == MMC_ERR_ACMD_RSPCRC)
+ goto done;
+ MSDC_GET_FIELD(SDC_DCRC_STS, SDC_DCRC_STS_POS|SDC_DCRC_STS_NEG, dcrc);
+
+ if (!ddr)
+ dcrc &= ~SDC_DCRC_STS_NEG;
+
+ /* for debugging */
+ times++;
+ /* no cre error in this data line */
+ if (result == MMC_ERR_NONE && dcrc == 0) {
+ goto done;
+ } else {
+ result = MMC_ERR_BADCRC;
+ }
+ }
+ cur_rxdly0 = MSDC_READ32(MSDC_DAT_RDDLY0);
+ cur_rxdly1 = MSDC_READ32(MSDC_DAT_RDDLY1);
+
+
+ orig_dat0 = (cur_rxdly0 >> 24) & 0x1F;
+ orig_dat1 = (cur_rxdly0 >> 16) & 0x1F;
+ orig_dat2 = (cur_rxdly0 >> 8) & 0x1F;
+ orig_dat3 = (cur_rxdly0 >> 0) & 0x1F;
+ orig_dat4 = (cur_rxdly1 >> 24) & 0x1F;
+ orig_dat5 = (cur_rxdly1 >> 16) & 0x1F;
+ orig_dat6 = (cur_rxdly1 >> 8) & 0x1F;
+ orig_dat7 = (cur_rxdly1 >> 0) & 0x1F;
+
+ if (ddr) {
+ cur_dat0 = (dcrc & (1 << 0) || dcrc & (1 << 8)) ? ((orig_dat0 + 1) % 32) : orig_dat0;
+ cur_dat1 = (dcrc & (1 << 1) || dcrc & (1 << 9)) ? ((orig_dat1 + 1) % 32) : orig_dat1;
+ cur_dat2 = (dcrc & (1 << 2) || dcrc & (1 << 10)) ? ((orig_dat2 + 1) % 32) : orig_dat2;
+ cur_dat3 = (dcrc & (1 << 3) || dcrc & (1 << 11)) ? ((orig_dat3 + 1) % 32) : orig_dat3;
+ cur_dat4 = (dcrc & (1 << 4) || dcrc & (1 << 12)) ? ((orig_dat4 + 1) % 32) : orig_dat4;
+ cur_dat5 = (dcrc & (1 << 5) || dcrc & (1 << 13)) ? ((orig_dat5 + 1) % 32) : orig_dat5;
+ cur_dat6 = (dcrc & (1 << 6) || dcrc & (1 << 14)) ? ((orig_dat6 + 1) % 32) : orig_dat6;
+ cur_dat7 = (dcrc & (1 << 7) || dcrc & (1 << 15)) ? ((orig_dat7 + 1) % 32) : orig_dat7;
+ } else {
+ cur_dat0 = (dcrc & (1 << 0)) ? ((orig_dat0 + 1) % 32) : orig_dat0;
+ cur_dat1 = (dcrc & (1 << 1)) ? ((orig_dat1 + 1) % 32) : orig_dat1;
+ cur_dat2 = (dcrc & (1 << 2)) ? ((orig_dat2 + 1) % 32) : orig_dat2;
+ cur_dat3 = (dcrc & (1 << 3)) ? ((orig_dat3 + 1) % 32) : orig_dat3;
+ cur_dat4 = (dcrc & (1 << 4)) ? ((orig_dat4 + 1) % 32) : orig_dat4;
+ cur_dat5 = (dcrc & (1 << 5)) ? ((orig_dat5 + 1) % 32) : orig_dat5;
+ cur_dat6 = (dcrc & (1 << 6)) ? ((orig_dat6 + 1) % 32) : orig_dat6;
+ cur_dat7 = (dcrc & (1 << 7)) ? ((orig_dat7 + 1) % 32) : orig_dat7;
+ }
+
+ cur_rxdly0 = ((cur_dat0 & 0x1F) << 24) | ((cur_dat1 & 0x1F) << 16) |
+ ((cur_dat2 & 0x1F)<< 8) | ((cur_dat3 & 0x1F) << 0);
+ cur_rxdly1 = ((cur_dat4 & 0x1F) << 24) | ((cur_dat5 & 0x1F) << 16) |
+ ((cur_dat6 & 0x1F) << 8) | ((cur_dat7 & 0x1F) << 0);
+
+ MSDC_WRITE32(MSDC_DAT_RDDLY0, cur_rxdly0);
+ MSDC_WRITE32(MSDC_DAT_RDDLY1, cur_rxdly1);
+ } while (++rxdly < 32);
+ if (!sel)
+ break;
+ cur_dsel = (orig_dsel + dsel + 1) % 32;
+ MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, cur_dsel);
+ } while (++dsel < 32);
+ /* no need to update data ck sel */
+ if (orig_clkmode != 1)
+ break;
+
+ cur_dl_cksel = (orig_dl_cksel + dl_cksel + 1)% 8;
+ MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL, cur_dl_cksel);
+ dl_cksel++;
+ } while (dl_cksel < 8);
+done:
+ dprintf(ALWAYS, "[MSDC] <msdc_tune_bread<%d><%s><cmd%d>@msdc_tune_bread\n",
+ times, (result == MMC_ERR_NONE && dcrc == 0) ? "PASS" : "FAIL",
+ (nblks == 1 ? 17 : 18));
+
+ return result;
+}
+#define READ_TUNING_MAX_HS (2 * 32)
+#define READ_TUNING_MAX_UHS (2 * 32 * 32)
+#define READ_TUNING_MAX_UHS_CLKMOD1 (2 * 32 * 32 *8)
+
+int msdc_tune_read(struct mmc_host *host)
+{
+ return 0;
+#if 0
+ u32 base = host->base;
+ u32 dcrc, ddr = 0, sel = 0;
+ u32 cur_rxdly0 = 0 , cur_rxdly1 = 0;
+ u32 cur_dsmpl = 0, orig_dsmpl;
+ u32 cur_dsel = 0,orig_dsel;
+ u32 cur_dl_cksel = 0,orig_dl_cksel;
+ u32 cur_dat0 = 0, cur_dat1 = 0, cur_dat2 = 0, cur_dat3 = 0, cur_dat4 = 0, cur_dat5 = 0,
+ cur_dat6 = 0, cur_dat7 = 0;
+ u32 orig_dat0, orig_dat1, orig_dat2, orig_dat3, orig_dat4, orig_dat5,
+ orig_dat6, orig_dat7;
+ u32 orig_clkmode;
+ u32 times = 0;
+ int result = MMC_ERR_NONE;
+
+ if (host->sclk > 100000000)
+ sel = 1;
+ if (host->card)
+ ddr = mmc_card_ddr(host->card);
+ MSDC_GET_FIELD(MSDC_CFG,MSDC_CFG_CKMOD,orig_clkmode);
+ //if(orig_clkmode == 1)
+ //MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_RX_SDCLKO_SEL, 0);
+
+ MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, orig_dsel);
+ MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL, orig_dl_cksel);
+ MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_DSPL, orig_dsmpl);
+
+ /* Tune Method 2. delay each data line */
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_DDLSEL, 1);
+
+
+ cur_dsmpl = (orig_dsmpl + 1) ;
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_DSPL, cur_dsmpl % 2);
+ if (cur_dsmpl >= 2) {
+ MSDC_GET_FIELD(SDC_DCRC_STS, SDC_DCRC_STS_POS|SDC_DCRC_STS_NEG, dcrc);
+ if (!ddr) dcrc &= ~SDC_DCRC_STS_NEG;
+
+ cur_rxdly0 = MSDC_READ32(MSDC_DAT_RDDLY0);
+ cur_rxdly1 = MSDC_READ32(MSDC_DAT_RDDLY1);
+
+ orig_dat0 = (cur_rxdly0 >> 24) & 0x1F;
+ orig_dat1 = (cur_rxdly0 >> 16) & 0x1F;
+ orig_dat2 = (cur_rxdly0 >> 8) & 0x1F;
+ orig_dat3 = (cur_rxdly0 >> 0) & 0x1F;
+ orig_dat4 = (cur_rxdly1 >> 24) & 0x1F;
+ orig_dat5 = (cur_rxdly1 >> 16) & 0x1F;
+ orig_dat6 = (cur_rxdly1 >> 8) & 0x1F;
+ orig_dat7 = (cur_rxdly1 >> 0) & 0x1F;
+
+ if (ddr) {
+ cur_dat0 = (dcrc & (1 << 0) || dcrc & (1 << 8)) ? (orig_dat0 + 1) : orig_dat0;
+ cur_dat1 = (dcrc & (1 << 1) || dcrc & (1 << 9)) ? (orig_dat1 + 1) : orig_dat1;
+ cur_dat2 = (dcrc & (1 << 2) || dcrc & (1 << 10)) ? (orig_dat2 + 1) : orig_dat2;
+ cur_dat3 = (dcrc & (1 << 3) || dcrc & (1 << 11)) ? (orig_dat3 + 1) : orig_dat3;
+ cur_dat4 = (dcrc & (1 << 4) || dcrc & (1 << 12)) ? (orig_dat4 + 1) : orig_dat4;
+ cur_dat5 = (dcrc & (1 << 5) || dcrc & (1 << 13)) ? (orig_dat5 + 1) : orig_dat5;
+ cur_dat6 = (dcrc & (1 << 6) || dcrc & (1 << 14)) ? (orig_dat6 + 1) : orig_dat6;
+ cur_dat7 = (dcrc & (1 << 7) || dcrc & (1 << 15)) ? (orig_dat7 + 1) : orig_dat7;
+ } else {
+ cur_dat0 = (dcrc & (1 << 0)) ? (orig_dat0 + 1) : orig_dat0;
+ cur_dat1 = (dcrc & (1 << 1)) ? (orig_dat1 + 1) : orig_dat1;
+ cur_dat2 = (dcrc & (1 << 2)) ? (orig_dat2 + 1) : orig_dat2;
+ cur_dat3 = (dcrc & (1 << 3)) ? (orig_dat3 + 1) : orig_dat3;
+ cur_dat4 = (dcrc & (1 << 4)) ? (orig_dat4 + 1) : orig_dat4;
+ cur_dat5 = (dcrc & (1 << 5)) ? (orig_dat5 + 1) : orig_dat5;
+ cur_dat6 = (dcrc & (1 << 6)) ? (orig_dat6 + 1) : orig_dat6;
+ cur_dat7 = (dcrc & (1 << 7)) ? (orig_dat7 + 1) : orig_dat7;
+ }
+
+ cur_rxdly0 = ((cur_dat0 & 0x1F) << 24) | ((cur_dat1 & 0x1F) << 16) |
+ ((cur_dat2 & 0x1F) << 8) | ((cur_dat3 & 0x1F) << 0);
+ cur_rxdly1 = ((cur_dat4 & 0x1F) << 24) | ((cur_dat5 & 0x1F)<< 16) |
+ ((cur_dat6 & 0x1F) << 8) | ((cur_dat7 & 0x1F) << 0);
+
+ MSDC_WRITE32(MSDC_DAT_RDDLY0, cur_rxdly0);
+ MSDC_WRITE32(MSDC_DAT_RDDLY1, cur_rxdly1);
+ }
+ if (cur_dat0 >= 32 || cur_dat1 >= 32 || cur_dat2 >= 32 || cur_dat3 >= 32 ||
+ cur_dat4 >= 32 || cur_dat5 >= 32 || cur_dat6 >= 32 || cur_dat7 >= 32) {
+ if (sel) {
+
+ cur_dsel = (orig_dsel + 1);
+ MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, cur_dsel % 32);
+
+ }
+ }
+ if (cur_dsel >= 32) {
+ if (orig_clkmode == 1 && sel) {
+
+ cur_dl_cksel = (orig_dl_cksel + 1);
+ MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL, cur_dl_cksel % 8);
+ }
+ }
+ ++(host->time_read);
+ if ((sel == 1 && orig_clkmode == 1 && host->time_read == READ_TUNING_MAX_UHS_CLKMOD1)||
+ (sel == 1 && orig_clkmode != 1 && host->time_read == READ_TUNING_MAX_UHS)||
+ (sel == 0 && orig_clkmode != 1 && host->time_read == READ_TUNING_MAX_HS)) {
+
+ result = MMC_ERR_READTUNEFAIL;
+ }
+
+ return result;
+#endif
+}
+#endif
+
+#ifdef FEATURE_MMC_WR_TUNING
+int msdc_tune_bwrite(struct mmc_host *host, u32 dst, u8 *src, u32 nblks)
+{
+ addr_t base = host->base;
+ u32 sel = 0;
+ u32 wrrdly, cur_wrrdly, orig_wrrdly;
+ u32 dsmpl, cur_dsmpl, orig_dsmpl;
+ u32 d_cntr,orig_d_cntr,cur_d_cntr;
+ u32 rxdly, cur_rxdly0;
+ u32 orig_dat0, orig_dat1, orig_dat2, orig_dat3;
+ u32 cur_dat0, cur_dat1, cur_dat2, cur_dat3;
+ u32 times = 0;
+ int result = MMC_ERR_WRITETUNEFAIL;
+
+ if (host->sclk > 100000000)
+ sel = 1;
+
+ MSDC_GET_FIELD(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, orig_wrrdly);
+ MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_W_D_SMPL, orig_dsmpl);
+ MSDC_GET_FIELD(MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_WRDAT_CRCS, orig_d_cntr);
+
+ /* Tune Method 2. delay data0 line */
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_DDLSEL, 1);
+
+ cur_rxdly0 = MSDC_READ32(MSDC_DAT_RDDLY0);
+
+ orig_dat0 = (cur_rxdly0 >> 24) & 0x1F;
+ orig_dat1 = (cur_rxdly0 >> 16) & 0x1F;
+ orig_dat2 = (cur_rxdly0 >> 8) & 0x1F;
+ orig_dat3 = (cur_rxdly0 >> 0) & 0x1F;
+
+ d_cntr = 0;
+ do {
+ rxdly = 0;
+ do {
+ wrrdly = 0;
+ do {
+ for (dsmpl = 0; dsmpl < 2; dsmpl++) {
+ cur_dsmpl = (orig_dsmpl + dsmpl) % 2;
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_W_D_SMPL, cur_dsmpl);
+ result = host->blk_write(host, dst, src, nblks);
+ if (result == MMC_ERR_CMDTUNEFAIL || result == MMC_ERR_CMD_RSPCRC || result == MMC_ERR_ACMD_RSPCRC)
+ goto done;
+
+ times++;
+ if (result == MMC_ERR_NONE) {
+ goto done;
+ }
+ }
+ cur_wrrdly = ++orig_wrrdly % 32;
+ MSDC_SET_FIELD(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, cur_wrrdly);
+ } while (++wrrdly < 32);
+
+ cur_dat0 = ++orig_dat0 % 32; /* only adjust bit-1 for crc */
+ cur_dat1 = orig_dat1;
+ cur_dat2 = orig_dat2;
+ cur_dat3 = orig_dat3;
+
+ cur_rxdly0 = (cur_dat0 << 24) | (cur_dat1 << 16) |
+ (cur_dat2 << 8) | (cur_dat3 << 0);
+
+ MSDC_WRITE32(MSDC_DAT_RDDLY0, cur_rxdly0);
+ } while (++rxdly < 32);
+
+ /* no need to update data ck sel */
+ if (!sel)
+ break;
+
+ cur_d_cntr= (orig_d_cntr + d_cntr +1 )% 8;
+ MSDC_SET_FIELD(MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_WRDAT_CRCS, cur_d_cntr);
+ d_cntr++;
+ } while (d_cntr < 8);
+done:
+ dprintf(ALWAYS, "[MSDC] <TUNE_BWRITE_%d><%s>\n", times, result == MMC_ERR_NONE ? "PASS" : "FAIL");
+
+ return result;
+}
+#endif
+
+int msdc_init(struct mmc_host *host)
+{
+ addr_t base = MSDC0_BASE;
+ msdc_priv_t *priv;
+
+ dprintf(INFO, "[%s]: Host controller intialization start \n", __func__);
+
+ priv = &msdc_priv;
+ memset(priv, 0, sizeof(msdc_priv_t));
+
+ host->base = base;
+ host->clksrc = msdc_cap.clk_src;
+ host->hclksrc= msdc_cap.hclk_src;
+#ifndef FPGA_PLATFORM
+ host->f_max = hclks_msdc30[host->clksrc];
+#else
+ host->f_max = MSDC_MAX_SCLK;
+#endif
+
+ host->f_min = MSDC_MIN_SCLK;
+ host->blklen = 0;
+ host->priv = (void *)priv;
+ host->caps = MMC_CAP_MULTIWRITE;
+
+ if (msdc_cap.flags & MSDC_HIGHSPEED)
+ host->caps |= (MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED);
+ if (msdc_cap.flags & MSDC_DDR)
+ host->caps |= MMC_CAP_DDR;
+ if (msdc_cap.data_pins == 4)
+ host->caps |= MMC_CAP_4_BIT_DATA;
+ if (msdc_cap.data_pins == 8)
+ host->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA;
+ if (msdc_cap.flags & MSDC_HS200)
+ host->caps |= MMC_CAP_EMMC_HS200;
+ if (msdc_cap.flags & MSDC_HS400)
+ host->caps |= MMC_CAP_EMMC_HS400;
+
+ host->ocr_avail = MMC_VDD_32_33; /* TODO: To be customized */
+
+ /* Configure BASIC_DMA + AUTOCMD12 for better R/W performance
+ * NOTE: ACMD23 only support transferring size of up to 32M */
+ priv->autocmd = MSDC_AUTOCMD12;
+ if (priv->autocmd == MSDC_AUTOCMD23)
+ /* The maximal transferring size is size of *[15:0] number of blocks* */
+ host->max_phys_segs = 0xffff;
+ else
+ /* The maximal transferring size is size of DMA_LENGTH */
+ host->max_phys_segs = (UINT_MAX & ~511) >> MMC_BLOCK_BITS_SHFT;
+
+ priv->rdsmpl = msdc_cap.data_edge;
+ priv->wdsmpl = msdc_cap.data_edge;
+ priv->rsmpl = msdc_cap.cmd_edge;
+
+#ifdef MSDC_USE_DMA_MODE
+ host->blk_read = msdc_dma_bread;
+ host->blk_write = msdc_dma_bwrite;
+ dprintf(INFO, "Transfer method: DMA\n");
+#else
+ host->blk_read = msdc_pio_bread;
+ host->blk_write = msdc_pio_bwrite;
+ dprintf(INFO, "Transfer method: PIO\n");
+#endif
+
+ priv->rdsmpl = msdc_cap.data_edge;
+ priv->rsmpl = msdc_cap.cmd_edge;
+
+ msdc_power(host, MMC_POWER_OFF);
+ msdc_power(host, MMC_POWER_ON);
+
+ /* set to SD/MMC mode */
+ MSDC_SET_FIELD(MSDC_CFG, MSDC_CFG_MODE, MSDC_SDMMC);
+ MSDC_SET_BIT32(MSDC_CFG, MSDC_CFG_PIO);
+
+ MSDC_RESET();
+ MSDC_CLR_FIFO();
+ MSDC_CLR_INT();
+
+ /* reset tuning parameter */
+ //MSDC_WRITE32(MSDC_PAD_CTL0, 0x0098000);
+ //MSDC_WRITE32(MSDC_PAD_CTL1, 0x00A0000);
+ //MSDC_WRITE32(MSDC_PAD_CTL2, 0x00A0000);
+ MSDC_WRITE32(MSDC_PAD_TUNE, 0x0000000);
+ MSDC_WRITE32(MSDC_DAT_RDDLY0, 0x00000000);
+ MSDC_WRITE32(MSDC_DAT_RDDLY1, 0x00000000);
+ MSDC_WRITE32(MSDC_IOCON, 0x00000000);
+
+ MSDC_WRITE32(MSDC_PATCH_BIT1, 0xFFFE00C9);//High 16 bit = 0 mean Power KPI is on, enable ECO for write timeout issue
+ //MSDC_PATCH_BIT1YD:WRDAT_CRCS_TA_CNTR need fix to 3'001 by default,(<50MHz) (>=50MHz set 3'001 as initial value is OK for tunning)
+ //YD:CMD_RSP_TA_CNTR need fix to 3'001 by default(<50MHz)(>=50MHz set 3'001as initial value is OK for tunning)
+ /* 2012-01-07 using internal clock instead of feedback clock */
+ //MSDC_SET_BIT32(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_CK_SEL);
+
+#ifdef MSDC_USE_PATCH_BIT2_TURNING_WITH_ASYNC
+ MSDC_SET_FIELD(MSDC_PATCH_BIT2, MSDC_PB2_CFGCRCSTS,1);
+ MSDC_SET_FIELD(MSDC_PATCH_BIT2, MSDC_PB2_CFGRESP,0);
+#else
+ MSDC_SET_FIELD(MSDC_PATCH_BIT2, MSDC_PB2_CFGCRCSTS,0);
+ MSDC_SET_FIELD(MSDC_PATCH_BIT2, MSDC_PB2_CFGRESP,1);
+#endif
+
+ /* enable wake up events */
+ //MSDC_SET_BIT32(SDC_CFG, SDC_CFG_INSWKUP);
+
+ /* eneable SMT for glitch filter */
+#ifdef FPGA_PLATFORM
+#if 0
+ MSDC_SET_BIT32(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKSMT);
+ MSDC_SET_BIT32(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDSMT);
+ MSDC_SET_BIT32(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATSMT);
+#endif
+#else
+ msdc_set_smt(host,1);
+#endif
+ /* set clk, cmd, dat pad driving */
+ msdc_set_driving(host, &msdc_cap);
+
+ /* set sampling edge */
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, msdc_cap.cmd_edge);
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_DSPL, msdc_cap.data_edge);
+
+ /* write crc timeout detection */
+ MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_PB0_DETWR_CRCTMO, 1);
+
+ msdc_set_startbit(host, START_AT_RISING);
+
+ msdc_config_bus(host, HOST_BUS_WIDTH_1);
+ msdc_config_clock(host, 0, MSDC_MIN_SCLK);
+ msdc_set_timeout(host, 100000000, 0);
+ /* disable SDIO func */
+ MSDC_SET_FIELD(SDC_CFG, SDC_CFG_SDIO, 0);
+ MSDC_SET_FIELD(SDC_CFG, SDC_CFG_SDIOIDE, 0);
+ MSDC_SET_FIELD(SDC_CFG, SDC_CFG_INSWKUP, 0);
+
+ /* Clear all interrupts first */
+ MSDC_CLR_INT();
+ MSDC_WRITE32(MSDC_INTEN, 0);
+
+#ifdef MSDC_USE_DMA_MODE
+ /* Register msdc irq */
+ mt_irq_set_sens(MT_MSDC0_IRQ_ID, LEVEL_SENSITIVE);
+ mt_irq_set_polarity(MT_MSDC0_IRQ_ID, MT65xx_POLARITY_LOW);
+ event_init(&msdc_int_event, false, EVENT_FLAG_AUTOUNSIGNAL);
+ register_int_handler(MT_MSDC0_IRQ_ID, msdc_interrupt_handler, host);
+ unmask_interrupt(MT_MSDC0_IRQ_ID);
+#endif
+
+ dprintf(INFO, "[%s]: Host controller intialization done\n", __func__);
+ return 0;
+}
+
diff --git a/src/bsp/lk/platform/mt2635/drivers/pll/mempll.c b/src/bsp/lk/platform/mt2635/drivers/pll/mempll.c
new file mode 100644
index 0000000..d20481c
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/drivers/pll/mempll.c
@@ -0,0 +1,785 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <reg.h>
+#include <platform/mt2635.h>
+#include <platform/pll.h>
+#include <platform/dramc.h>
+#include <platform/emi.h>
+
+typedef bool BOOL; /* workaround */
+
+#include <platform/wdt.h>
+
+#define USE_SPIN 0
+
+#if USE_SPIN
+
+#define udelay(x) spin(x)
+#define mdelay(x) udelay((x) * 1000)
+
+#else /* !USE_SPIN */
+
+#define my_delay(count) \
+ do { \
+ volatile unsigned int i = count * 26; \
+ for (; i != 0; i--); \
+ } while (0)
+
+#define udelay(x) my_delay(x)
+#define mdelay(x) udelay((x) * 1000)
+
+#endif /* USE_SPIN */
+
+#define write_r(a, v) writel(v, a)
+
+typedef volatile unsigned int *UINT32P;
+
+/* workaround */
+int __attribute__((weak)) mt_get_dram_type(void)
+{
+ return TYPE_LPDDR2;
+}
+
+/***********************
+ * MEMPLL Configuration
+ ***********************/
+#define r_bias_en_stb_time (0x00000000 << 24) //170[31:24]
+#define r_bias_lpf_en_stb_time (0x00000000 << 16) //170[23:16]
+#define r_mempll_en_stb_time (0x00000000 << 8) //170[15:8]
+#define r_dmall_ck_en_stb_time (0x00000000 << 0) //170[7:0]
+
+#define r_dds_en_stb_time (0x00000000 << 24) //171[31:24]
+#define r_div_en_stb_time (0x00000000 << 16) //171[23:16]
+#define r_dmpll2_ck_en_stb_time (0x00000000 << 8) //171[15:8]
+#define r_iso_en_stb_time (0x00000000 << 0) //171[7:0]
+
+#define r_bias_en_stb_dis (0x00000001 << 28) //172[28]
+#define r_bias_en_src_sel (0x00000001 << 24) //172[24]
+#define r_bias_lpf_en_stb_dis (0x00000001 << 20) //172[20]
+#define r_bias_lpf_en_src_sel (0x00000001 << 16) //172[16]
+#define r_mempll4_en_stb_dis (0x00000001 << 15) //172[15]
+#define r_mempll3_en_stb_dis (0x00000001 << 14) //172[14]
+#define r_mempll2_en_stb_dis (0x00000001 << 13) //172[13]
+#define r_mempll_en_stb_dis (0x00000001 << 12) //172[12]
+#define r_mempll4_en_src_sel (0x00000001 << 11) //172[11]
+#define r_mempll3_en_src_sel (0x00000001 << 10) //172[10]
+#define r_mempll2_en_src_sel (0x00000001 << 9) //172[9]
+#define r_mempll_en_src_sel (0x00000001 << 8) //172[8]
+#define r_dmall_ck_en_stb_dis (0x00000001 << 4) //172[4]
+#define r_dmall_ck_en_src_sel (0x00000001 << 0) //172[0]
+
+#define r_dds_en_stb_dis (0x00000001 << 28) //173[28]
+#define r_dds_en_src_sel (0x00000001 << 24) //173[24]
+#define r_div_en_stb_dis (0x00000001 << 20) //173[20]
+#define r_div_en_src_sel (0x00000001 << 16) //173[16]
+#define r_dmpll2_ck_en_stb_dis (0x00000001 << 12) //173[12]
+#define r_dmpll2_ck_en_src_sel (0x00000001 << 8) //173[8]
+#define r_iso_en_stb_dis (0x00000001 << 4) //173[4]
+#define r_iso_en_src_sel (0x00000001 << 0) //173[0]
+
+#define r_dmbyp_pll4 (0x00000001 << 0) //190[0]
+#define r_dmbyp_pll3 (0x00000001 << 1) //190[1]
+#define r_dm1pll_sync_mode (0x00000001 << 2) //190[2]
+#define r_dmall_ck_en (0x00000001 << 4) //190[4]
+#define r_dmpll2_clk_en (0x00000001 << 5) //190[5]
+
+#define pllc1_postdiv_1_0 (0x00000003 << 14) //180[15:14]
+#define pllc1_blp (0x00000001 << 12) //180[12]
+#define pllc1_mempll_n_info_chg (0x00000001 << 0) //189[0]
+#define pllc1_dmss_pcw_ncpo_30_0 (0x7fffffff << 1) //189[31:1]
+#define pllc1_mempll_div_en (0x00000001 <<24) //181[24]
+#define pllc1_mempll_div_6_0 (0x0000007f <<25) //181[31:25]
+#define pllc1_mempll_reserve_2 (0x00000001 <<18) //181[18]
+#define pllc1_mempll_top_reserve_2_0 (0x00000000 <<16) //182[18:16]
+#define pllc1_mempll_bias_en (0x00000001 <<14) //181[14]
+#define pllc1_mempll_bias_lpf_en (0x00000001 <<15) //181[15]
+#define pllc1_mempll_en (0x00000001 << 2) //180[2]
+#define pllc1_mempll_sdm_prd_1 (0x00000001 <<11) //188[11]
+
+#define mempll2_prediv_1_0 (0x00000000 << 0) //182[1:0]
+#define mempll2_vco_div_sel (0x00000001 <<29) //183[29]
+#define mempll2_m4pdiv_1_0 (0x00000003 <<10) //183[11:10],P9
+#define mempll2_fbdiv_6_0 (0x0000007f << 2) //182[8:2],P6
+#define mempll2_fb_mck_sel (0x00000001 << 9) //183[9]
+#define mempll2_fbksel_1_0 (0x00000003 <<10) //182[11:10]
+#define mempll2_bp_br (0x00000003 <<26) //183[27:26]
+#define mempll2_posdiv_1_0 (0x00000000 <<30) //183[31:30]
+#define mempll2_ref_dl_4_0 (0x00000000 <<27) //184[31:27]
+#define mempll2_fb_dl_4_0 (0x00000000 <<22) //184[26:22]
+#define mempll2_en (0x00000001 <<18) //183[18]
+
+#define mempll3_prediv_1_0 (0x00000000 << 0) //184[1:0]
+#define mempll3_vco_div_sel (0x00000001 <<29) //185[29]
+#define mempll3_m4pdiv_1_0 (0x00000003 <<10) //185[11:10]
+#define mempll3_fbdiv_6_0 (0x0000007f << 2) //184[8:2]
+#define mempll3_bp_br (0x00000003 <<26) //185[27:26]
+#define mempll3_fb_mck_sel (0x00000001 << 9) //185[9]
+#define mempll3_fbksel_1_0 (0x00000003 <<10) //184[11:10]
+#define mempll3_posdiv_1_0 (0x00000000 <<30) //185[31:30]
+#define mempll3_ref_dl_4_0 (0x00000000 <<27) //186[31:27]
+#define mempll3_fb_dl_4_0 (0x00000000 <<22) //186[26:22]
+#define mempll3_en (0x00000001 <<18) //185[18]
+
+#define mempll4_prediv_1_0 (0x00000000 << 0) //186[1:0]
+#define mempll4_vco_div_sel (0x00000001 <<29) //187[29]
+#define mempll4_m4pdiv_1_0 (0x00000003 <<10) //187[11:10]
+#define mempll4_fbdiv_6_0 (0x0000007f << 2) //186[8:2]
+#define mempll4_fbksel_1_0 (0x00000003 <<10) //186[11:10]
+#define mempll4_bp_br (0x00000003 <<26) //187[27:26]
+#define mempll4_fb_mck_sel (0x00000001 << 9) //187[9]
+#define mempll4_posdiv_1_0 (0x00000000 <<30) //187[31:30]
+#define mempll4_ref_dl_4_0 (0x00000000 <<27) //188[31:27]
+#define mempll4_fb_dl_4_0 (0x00000000 <<22) //188[26:22]
+#define mempll4_en (0x00000001 <<18) //187[18]
+
+/***********************
+ * MEMPLL Calibration
+ ***********************/
+#define MEMPLL_JMETER_CNT 1024
+#define MEMPLL_JMETER_CONFIDENCE_CNT (MEMPLL_JMETER_CNT/10)
+#define MEMPLL_JMETER_WAIT_TIME_BASE 10 // time base
+#define MEMPLL_JMETER_WAIT_TIMEOUT 1000/MEMPLL_JMETER_WAIT_TIME_BASE // timeout ~ 1000us
+
+
+void mt_mempll_init(int type, int pll_mode)
+{
+ /*********************************
+ * (1) Setup DDRPHY operation mode
+ **********************************/
+
+ *((UINT32P)(DRAMC0_BASE + 0x007c)) |= 0x00000001; //DFREQ_DIV2=1
+ *((UINT32P)(DDRPHY_BASE + 0x007c)) |= 0x00000001;
+
+ if (pll_mode == PLL_MODE_3) {
+ *((UINT32P)(DDRPHY_BASE + (0x0190 <<2))) = 0x00000020; //3PLL sync mode, OK
+ } else if (pll_mode== PLL_MODE_2) {
+ *((UINT32P)(DDRPHY_BASE + (0x0190 <<2))) = 0x00000022;
+ } else { // 1 PLL mode
+ *((UINT32P)(DDRPHY_BASE + (0x0190 <<2))) = 0x00000007; //1PLL sync mode, OK.
+ }
+
+ /*****************************************************************************************
+ * (2) Setup MEMPLL operation case & frequency. May set according to dram type & frequency
+ ******************************************************************************************/
+ *((UINT32P)(DDRPHY_BASE + (0x0170 <<2))) = r_bias_en_stb_time | r_bias_lpf_en_stb_time | r_mempll_en_stb_time | r_dmall_ck_en_stb_time;
+ *((UINT32P)(DDRPHY_BASE + (0x0171 <<2))) = r_dds_en_stb_time | r_div_en_stb_time | r_dmpll2_ck_en_stb_time | r_iso_en_stb_time;
+ *((UINT32P)(DDRPHY_BASE + (0x0172 <<2))) = r_bias_en_stb_dis| r_bias_en_src_sel | r_bias_lpf_en_stb_dis| r_bias_lpf_en_src_sel | r_mempll4_en_stb_dis| r_mempll3_en_stb_dis| r_mempll2_en_stb_dis| r_mempll_en_stb_dis| r_mempll4_en_src_sel | r_mempll3_en_src_sel | r_mempll2_en_src_sel | r_mempll_en_src_sel | r_dmall_ck_en_stb_dis | r_dmall_ck_en_src_sel;
+ *((UINT32P)(DDRPHY_BASE + (0x0173 <<2))) = r_dds_en_stb_dis| r_dds_en_src_sel | r_div_en_stb_dis| r_div_en_src_sel | r_dmpll2_ck_en_stb_dis| r_dmpll2_ck_en_src_sel | r_iso_en_stb_dis| r_iso_en_src_sel;
+
+ // MEMPLL common setting
+ *((UINT32P)(DDRPHY_BASE + (0x0180 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0180 <<2))) & (~pllc1_postdiv_1_0)) | 0x00000000; //RG_MEMPLL_POSDIV[1:0] = 2'b00;
+ *((UINT32P)(DDRPHY_BASE + (0x0180 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0180 <<2))) & (~pllc1_blp)) | (0x00000001 << 12); //RG_MEMPLL_BLP = 1'b1;
+ *((UINT32P)(DDRPHY_BASE + (0x0181 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0181 <<2))) & (~pllc1_mempll_div_6_0)) | (0x00000052 << 25); //RG_MEMPLL_DIV = 7'h52;
+ *((UINT32P)(DDRPHY_BASE + (0x0181 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0181 <<2))) & (~pllc1_mempll_reserve_2)) | (0x00000001 << 18); //RG_MEMPLL_RESERVE[2] = 1;
+
+ *((UINT32P)(DDRPHY_BASE + (0x0182 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0182 <<2))) & (~mempll2_fbksel_1_0)) | 0x00000000; //RG_MEMPLL2_FBKSEL[1:0] = 2'b00;
+ *((UINT32P)(DDRPHY_BASE + (0x0183 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0183 <<2))) & (~mempll2_bp_br)) | (0x00000003 << 26); //RG_MEMPLL2_BP = 1, RG_MEMPLL2_BR=1;
+
+ if ((pll_mode == PLL_MODE_3) || (pll_mode == PLL_MODE_2)) {
+ *((UINT32P)(DDRPHY_BASE + (0x0183 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0183 <<2))) & (~mempll2_fb_mck_sel)) | (0x00000001 << 9); //RG_MEMPLL2_FB_MCK_SEL;
+ }
+
+ *((UINT32P)(DDRPHY_BASE + (0x0184 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0184 <<2))) & (~mempll3_fbksel_1_0)) | 0x00000000; //RG_MEMPLL3_FBKSEL = 2'b00;
+ *((UINT32P)(DDRPHY_BASE + (0x0185 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0185 <<2))) & (~mempll3_bp_br)) | (0x00000003 << 26); //RG_MEMPLL3_BP = 1, RG_MEMPLL3_BR=1;
+
+ if ((pll_mode == PLL_MODE_3) || (pll_mode == PLL_MODE_2)) {
+ *((UINT32P)(DDRPHY_BASE + (0x0185 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0185 <<2))) & (~mempll3_fb_mck_sel)) | (0x00000001 << 9); //RG_MEMPLL3_FB_MCK_SEL = 1;
+ }
+
+ *((UINT32P)(DDRPHY_BASE + (0x0186 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0186 <<2))) & (~mempll4_fbksel_1_0)) | 0x00000000; //RG_MEMPLL4_FBKSEL = 2'b00;
+ *((UINT32P)(DDRPHY_BASE + (0x0187 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0187 <<2))) & (~mempll4_bp_br)) | (0x00000003 << 26); //RG_MEMPLL4_BP = 1, RG_MEMPLL4_BR=1;
+
+ if ((pll_mode == PLL_MODE_3) || (pll_mode == PLL_MODE_2)) {
+ *((UINT32P)(DDRPHY_BASE + (0x0187 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0187 <<2))) & (~mempll4_fb_mck_sel)) | (0x00000001 << 9); //RG_MEMPLL4_FB_MCK_SEL = 1;
+ }
+
+ //MEMPLL different setting for different frequency begin
+ if (type == DDR1333) { // real DDR-1280 (sign-off)
+ *((UINT32P)(DDRPHY_BASE + (0x0183 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0183 <<2))) & (~mempll2_vco_div_sel)) | 0x00000000; //RG_MEMPLL2_VCO_DIV_SEL =0;
+ *((UINT32P)(DDRPHY_BASE + (0x0185 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0185 <<2))) & (~mempll3_vco_div_sel)) | 0x00000000; //RG_MEMPLL3_VCO_DIV_SEL =0;
+ *((UINT32P)(DDRPHY_BASE + (0x0187 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0187 <<2))) & (~mempll4_vco_div_sel)) | 0x00000000; //RG_MEMPLL4_VCO_DIV_SEL =0;
+ // DDR-1333
+ //*((UINT32P)(DDRPHY_BASE + (0x0189 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0189 <<2))) & (~pllc1_dmss_pcw_ncpo_30_0)) | (0x50d8fe7c << 1); //RG_DMSS_PCW_NCPO[30:0]
+ // DDR-1280
+ *((UINT32P)(DDRPHY_BASE + (0x0189 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0189 <<2))) & (~pllc1_dmss_pcw_ncpo_30_0)) | (0x4da21535 << 1); //RG_DMSS_PCW_NCPO[30:0]
+
+ if ((pll_mode == PLL_MODE_3) || (pll_mode == PLL_MODE_2)) {
+ *((UINT32P)(DDRPHY_BASE + (0x0182 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0182 <<2))) & (~mempll2_fbdiv_6_0)) | (0x0000000d << 2); //RG_MEMPLL2_FBDIV = 7'h0d;
+ *((UINT32P)(DDRPHY_BASE + (0x0184 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0184 <<2))) & (~mempll3_fbdiv_6_0)) | (0x0000000d << 2); //RG_MEMPLL3_FBDIV = 7'h0d;
+ *((UINT32P)(DDRPHY_BASE + (0x0186 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0186 <<2))) & (~mempll4_fbdiv_6_0)) | (0x0000000d << 2); //RG_MEMPLL4_FBDIV = 7'h0d;
+ } else {
+ *((UINT32P)(DDRPHY_BASE + (0x0182 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0182 <<2))) & (~mempll2_fbdiv_6_0)) | (0x00000034 << 2); //RG_MEMPLL2_FBDIV = 7'h34;
+ *((UINT32P)(DDRPHY_BASE + (0x0184 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0184 <<2))) & (~mempll3_fbdiv_6_0)) | (0x00000034 << 2); //RG_MEMPLL3_FBDIV = 7'h34;
+ *((UINT32P)(DDRPHY_BASE + (0x0186 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0186 <<2))) & (~mempll4_fbdiv_6_0)) | (0x00000034 << 2); //RG_MEMPLL4_FBDIV = 7'h34;
+ }
+ } else if (type == DDR938) { // for DVFS_low (DVS HQA), the same settings as DDR-1333 other than NCPO
+ *((UINT32P)(DDRPHY_BASE + (0x0183 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0183 <<2))) & (~mempll2_vco_div_sel)) | 0x00000000; //RG_MEMPLL2_VCO_DIV_SEL =0;
+ *((UINT32P)(DDRPHY_BASE + (0x0185 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0185 <<2))) & (~mempll3_vco_div_sel)) | 0x00000000; //RG_MEMPLL3_VCO_DIV_SEL =0;
+ *((UINT32P)(DDRPHY_BASE + (0x0187 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0187 <<2))) & (~mempll4_vco_div_sel)) | 0x00000000; //RG_MEMPLL4_VCO_DIV_SEL =0;
+
+#if 1
+ *((UINT32P)(DDRPHY_BASE + (0x0189 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0189 <<2))) & (~pllc1_dmss_pcw_ncpo_30_0)) | (0x38e3f9f0 << 1); //RG_DMSS_PCW_NCPO[30:0]
+#else // only for debug (lowest bring up frequency DDR-667)
+ *((UINT32P)(DDRPHY_BASE + (0x0189 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0189 <<2))) & (~pllc1_dmss_pcw_ncpo_30_0)) | (0x287442a6 << 1); //RG_DMSS_PCW_NCPO[30:0]
+#endif
+
+ if ((pll_mode == PLL_MODE_3) || (pll_mode == PLL_MODE_2)) {
+ *((UINT32P)(DDRPHY_BASE + (0x0182 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0182 <<2))) & (~mempll2_fbdiv_6_0)) | (0x0000000d << 2); //RG_MEMPLL2_FBDIV = 7'h0d;
+ *((UINT32P)(DDRPHY_BASE + (0x0184 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0184 <<2))) & (~mempll3_fbdiv_6_0)) | (0x0000000d << 2); //RG_MEMPLL3_FBDIV = 7'h0d;
+ *((UINT32P)(DDRPHY_BASE + (0x0186 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0186 <<2))) & (~mempll4_fbdiv_6_0)) | (0x0000000d << 2); //RG_MEMPLL4_FBDIV = 7'h0d;
+ } else {
+ *((UINT32P)(DDRPHY_BASE + (0x0182 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0182 <<2))) & (~mempll2_fbdiv_6_0)) | (0x00000034 << 2); //RG_MEMPLL2_FBDIV = 7'h34;
+ *((UINT32P)(DDRPHY_BASE + (0x0184 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0184 <<2))) & (~mempll3_fbdiv_6_0)) | (0x00000034 << 2); //RG_MEMPLL3_FBDIV = 7'h34;
+ *((UINT32P)(DDRPHY_BASE + (0x0186 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0186 <<2))) & (~mempll4_fbdiv_6_0)) | (0x00000034 << 2); //RG_MEMPLL4_FBDIV = 7'h34;
+ }
+ } else if (type == DDR1466) {
+ *((UINT32P)(DDRPHY_BASE + (0x0183 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0183 <<2))) & (~mempll2_vco_div_sel)) | 0x00000000; //RG_MEMPLL2_VCO_DIV_SEL =0;
+ *((UINT32P)(DDRPHY_BASE + (0x0185 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0185 <<2))) & (~mempll3_vco_div_sel)) | 0x00000000; //RG_MEMPLL3_VCO_DIV_SEL =0;
+ *((UINT32P)(DDRPHY_BASE + (0x0187 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0187 <<2))) & (~mempll4_vco_div_sel)) | 0x00000000; //RG_MEMPLL4_VCO_DIV_SEL =0;
+ *((UINT32P)(DDRPHY_BASE + (0x0189 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0189 <<2))) & (~pllc1_dmss_pcw_ncpo_30_0)) | (0x52902d02 << 1); //RG_DMSS_PCW_NCPO[30:0] = 31'h52902d02;
+ if ((pll_mode == PLL_MODE_3) || (pll_mode == PLL_MODE_2)) {
+ *((UINT32P)(DDRPHY_BASE + (0x0182 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0182 <<2))) & (~mempll2_fbdiv_6_0)) | (0x0000000e << 2); //RG_MEMPLL2_FBDIV = 7'h0e;
+ *((UINT32P)(DDRPHY_BASE + (0x0184 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0184 <<2))) & (~mempll3_fbdiv_6_0)) | (0x0000000e << 2); //RG_MEMPLL3_FBDIV = 7'h0e;
+ *((UINT32P)(DDRPHY_BASE + (0x0186 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0186 <<2))) & (~mempll4_fbdiv_6_0)) | (0x0000000e << 2); //RG_MEMPLL4_FBDIV = 7'h0e;
+ } else {
+ *((UINT32P)(DDRPHY_BASE + (0x0182 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0182 <<2))) & (~mempll2_fbdiv_6_0)) | (0x00000038 << 2); //RG_MEMPLL2_FBDIV = 7'h38;
+ *((UINT32P)(DDRPHY_BASE + (0x0184 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0184 <<2))) & (~mempll3_fbdiv_6_0)) | (0x00000038 << 2); //RG_MEMPLL3_FBDIV = 7'h38;
+ *((UINT32P)(DDRPHY_BASE + (0x0186 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0186 <<2))) & (~mempll4_fbdiv_6_0)) | (0x00000038 << 2); //RG_MEMPLL4_FBDIV = 7'h38;
+ }
+ } else { // DDR-1066
+ *((UINT32P)(DDRPHY_BASE + (0x0189 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0189 <<2))) & (~pllc1_dmss_pcw_ncpo_30_0)) | (0x4c68b439 << 1); //RG_DMSS_PCW_NCPO[30:0] = 31'h4c68b439;
+ if ((pll_mode == PLL_MODE_3) || (pll_mode == PLL_MODE_2)) {
+ *((UINT32P)(DDRPHY_BASE + (0x0182 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0182 <<2))) & (~mempll2_fbdiv_6_0)) | (0x0000000b << 2); //RG_MEMPLL2_FBDIV = 7'h0b;
+ *((UINT32P)(DDRPHY_BASE + (0x0184 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0184 <<2))) & (~mempll3_fbdiv_6_0)) | (0x0000000b << 2); //RG_MEMPLL3_FBDIV = 7'h0b;
+ *((UINT32P)(DDRPHY_BASE + (0x0186 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0186 <<2))) & (~mempll4_fbdiv_6_0)) | (0x0000000b << 2); //RG_MEMPLL4_FBDIV = 7'h0b;
+ } else {
+ *((UINT32P)(DDRPHY_BASE + (0x0182 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0182 <<2))) & (~mempll2_fbdiv_6_0)) | (0x0000002c << 2); //RG_MEMPLL2_FBDIV = 7'h2c;
+ *((UINT32P)(DDRPHY_BASE + (0x0184 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0184 <<2))) & (~mempll3_fbdiv_6_0)) | (0x0000002c << 2); //RG_MEMPLL3_FBDIV = 7'h2c;
+ *((UINT32P)(DDRPHY_BASE + (0x0186 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0186 <<2))) & (~mempll4_fbdiv_6_0)) | (0x0000002c << 2); //RG_MEMPLL4_FBDIV = 7'h2c;
+ }
+ }
+ //MEMPLL different setting for different frequency end
+
+ if (pll_mode == PLL_MODE_2) {
+ *((UINT32P)(DDRPHY_BASE + (0x0190 <<2))) = 0x00000022 | r_dmpll2_clk_en;
+ } else if (pll_mode == PLL_MODE_3) {
+ *((UINT32P)(DDRPHY_BASE + (0x0190 <<2))) = 0x00000020 | r_dmpll2_clk_en; //3PLL sync mode
+ } else { // 1-PLL mode
+ //*((UINT32P)(DDRPHY_BASE + (0x0190 <<2))) = 0x00000007 | r_dmpll2_clk_en; //1PLL sync mode
+ *((UINT32P)(DDRPHY_BASE + (0x0190 <<2))) = 0x00000007 ; //1PLL sync mode
+ }
+
+ /***********************************
+ * (3) Setup MEMPLL power on sequence
+ ************************************/
+
+ udelay(2);
+
+ *((UINT32P)(DDRPHY_BASE + (0x0181 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0181 <<2))) & (~pllc1_mempll_bias_en)) | (0x00000001 << 14); //RG_MEMPLL_BIAS_EN = 1'b1;
+
+ udelay(2);
+
+ *((UINT32P)(DDRPHY_BASE + (0x0181 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0181 <<2))) & (~pllc1_mempll_bias_lpf_en)) | (0x00000001 << 15); //RG_MEMPLL_BIAS_LPF_EN = 1'b1;
+
+ udelay(1000);
+
+ *((UINT32P)(DDRPHY_BASE + (0x0180 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0180 <<2))) & (~pllc1_mempll_en)) | (0x00000001 << 2); //RG_MEMPLL_EN = 1'b1;
+
+ udelay(20);
+
+ *((UINT32P)(DDRPHY_BASE + (0x0181 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0181 <<2))) & (~pllc1_mempll_div_en)) | (0x00000001 << 24); //RG_MEMPLL_DIV_EN = 1'b1;
+
+ udelay(1);
+
+ if ((pll_mode == PLL_MODE_3) || (pll_mode == PLL_MODE_2)) {
+ *((UINT32P)(DDRPHY_BASE + (0x0183 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0183 <<2))) & (~mempll2_en)) | (0x00000001 << 18); //RG_MEMPLL2_EN = 1'b1;
+ *((UINT32P)(DDRPHY_BASE + (0x0185 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0185 <<2))) & (~mempll3_en)) | (0x00000001 << 18); //RG_MEMPLL3_EN = 1'b1;
+ *((UINT32P)(DDRPHY_BASE + (0x0187 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0187 <<2))) & (~mempll4_en)) | (0x00000001 << 18); //RG_MEMPLL4_EN = 1'b1;
+ } else {
+ *((UINT32P)(DDRPHY_BASE + (0x0183 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0183 <<2))) & (~mempll2_en)) | (0x00000001 << 18); //RG_MEMPLL2_EN = 1'b1;
+ *((UINT32P)(DDRPHY_BASE + (0x0185 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0185 <<2))) & (~mempll3_en)) | (0x00000000 << 18); //RG_MEMPLL3_EN = 1'b0;
+ *((UINT32P)(DDRPHY_BASE + (0x0187 <<2))) = (*((UINT32P)(DDRPHY_BASE + (0x0187 <<2))) & (~mempll4_en)) | (0x00000000 << 18); //RG_MEMPLL4_EN = 1'b0;
+ }
+
+ udelay(23);
+
+ if (pll_mode == PLL_MODE_2) {
+ *((UINT32P)(DDRPHY_BASE + (0x0190 <<2))) = 0x00000022 | r_dmpll2_clk_en | r_dmall_ck_en;
+ } else if (pll_mode == PLL_MODE_3) {
+ *((UINT32P)(DDRPHY_BASE + (0x0190 <<2))) = 0x00000020 | r_dmpll2_clk_en | r_dmall_ck_en; //3PLL sync mode
+ } else { // 1-PLL mode
+ *((UINT32P)(DDRPHY_BASE + (0x0190 <<2))) = 0x00000007 | r_dmpll2_clk_en | r_dmall_ck_en; //1PLL sync mode
+ }
+
+ /**********************************
+ * (4) MEMPLL control switch to SPM
+ ***********************************/
+#ifdef fcSWITCH_SPM_CONTROL
+ if ((pll_mode == PLL_MODE_3) || (pll_mode == PLL_MODE_2)) {
+ *((UINT32P)(DDRPHY_BASE + (0x0173 <<2))) = 0x40101000; //[0]ISO_EN_SRC=0,[22]DIV_EN_SC_SRC=0 (pll2off),[16]DIV_EN_SRC=0,[8]PLL2_CK_EN_SRC=1(1pll),[8]PLL2_CK_EN_SRC=0(3pll)
+ } else { // 1-PLL mode
+ *((UINT32P)(DDRPHY_BASE + (0x0173 <<2))) = 0x40101000; //[0]ISO_EN_SRC=0,[22]DIV_EN_SC_SRC=0 (pll2off),[16]DIV_EN_SRC=0,[8]PLL2_CK_EN_SRC=1(1pll),[8]PLL2_CK_EN_SRC=0(3pll)
+ }
+
+ if ((pll_mode == PLL_MODE_3) || (pll_mode == PLL_MODE_2)) {
+ *((UINT32P)(DDRPHY_BASE + (0x0172 <<2))) = 0x0000F010; //[24]BIAS_EN_SRC=0,[16]BIAS_LPF_EN_SRC=0,[8]MEMPLL_EN,[9][10][11]MEMPLL2,3,4_EN_SRC,[0]ALL_CK_EN_SRC=0
+ } else { // 1-PLL mode
+ *((UINT32P)(DDRPHY_BASE + (0x0172 <<2))) = 0x0000FC10; //1PLL mode, MEMPLL3,4_EN no change to spm controller.eep to 1'b0 for power saving.
+ //*((UINT32P)(DDRPHY_BASE + (0x0172 <<2))) = 0x0000F010; // sim ok
+ }
+
+ //*((UINT32P)(DDRPHY_BASE + (0x0170 <<2))) = 0x003C1B96; //setting for delay time
+ *((UINT32P)(DDRPHY_BASE + (0x0170 <<2))) = 0x063C0000; //setting for delay time
+#endif
+
+// MEMPLL configuration end
+}
+
+#ifdef DDRPHY_3PLL_MODE
+int mt_mempll_cali(void)
+{
+ int one_count = 0, zero_count = 0;
+ int pll2_done = 0, pll3_done = 0, pll4_done = 0, ret = 0;
+
+ unsigned int temp = 0, pll2_dl = 0, pll3_dl = 0, pll4_dl = 0;
+ int pll2_phase=0, pll3_phase=0, pll4_phase=0;
+ unsigned int jmeter_wait_count;
+
+ /***********************************************
+ * 1. Set jitter meter clock to internal FB path
+ ************************************************/
+ //temp = readl(0x1000F60C);
+ //write_r(0x1000F60C, temp & ~0x200); // 0x1000F60C[9] = 0 PLL2
+
+ //temp = readl(0x1000F614);
+ //write_r(0x1000F614, temp & ~0x200); // 0x1000F614[9] = 0 PLL3
+
+ //temp = readl(0x1000F61C);
+ //write_r(0x1000F61C, temp & ~0x200); // 0x1000F61C[9] = 0 PLL4
+
+ /***********************************************
+ * 2. Set jitter meter count number
+ ************************************************/
+ // PLL2 0x1000F1CC 0x1000F32C[0]: JMETER_DONE
+ // PLL3 0x1000F1D0 0x1000F32C[1]: JMETER_DONE
+ // PLL4 0x1000F1D4 0x1000F32C[2]: JMETER_DONE
+
+ temp = readl(0x1000F1CC) & 0x0000FFFF;
+ write_r(0x1000F1CC, (temp | (MEMPLL_JMETER_CNT<<16))); // 0x1000F1CC[31:16] PLL2 0x400 = 1024 count
+
+ temp = readl(0x1000F1D0) & 0x0000FFFF;
+ write_r(0x1000F1D0, (temp | (MEMPLL_JMETER_CNT<<16))); // 0x1000F1D0[31:16] PLL3 0x400 = 1024 count
+
+ temp = readl(0x1000F1D4) & 0x0000FFFF;
+ write_r(0x1000F1D4, (temp | (MEMPLL_JMETER_CNT<<16))); // 0x1000F1D4[31:16] PLL4 0x400 = 1024 count
+
+ while (1) {
+ /***********************************************
+ * 3. Adjust delay chain tap number
+ ************************************************/
+ if (!pll2_done) {
+ if (pll2_phase == 0) { // initial phase set to 0 for REF and FBK
+ temp = readl(0x1000F610) & ~0xF8000000;
+ write_r(0x1000F610, (temp | (0x00 << 27 )));
+
+ temp = readl(0x1000F610) & ~0x07C00000;
+ write_r(0x1000F610, (temp | (0x00 << 22)));
+ } else if (pll2_phase == 1) { // REF lag FBK, delay FBK
+ temp = readl(0x1000F610) & ~0xF8000000;
+ write_r(0x1000F610, (temp | (0x00 << 27 )));
+
+ temp = readl(0x1000F610) & ~0x07C00000;
+ write_r(0x1000F610, (temp | (pll2_dl << 22)));
+ } else { // REF lead FBK, delay REF
+ temp = readl(0x1000F610) & ~0xF8000000;
+ write_r(0x1000F610, (temp | (pll2_dl << 27 )));
+
+ temp = readl(0x1000F610) & ~0x07C00000;
+ write_r(0x1000F610, (temp | (0x00 << 22)));
+ }
+ }
+
+ if (!pll3_done) {
+ if (pll3_phase == 0) { // initial phase set to 0 for REF and FBK
+ temp = readl(0x1000F618) & ~0xF8000000;
+ write_r(0x1000F618, (temp | (0x00 << 27 )));
+
+ temp = readl(0x1000F618) & ~0x07C00000;
+ write_r(0x1000F618, (temp | (0x00 << 22)));
+ } else if (pll3_phase == 1) { // REF lag FBK, delay FBK
+ temp = readl(0x1000F618) & ~0xF8000000;
+ write_r(0x1000F618, (temp | (0x00 << 27 )));
+
+ temp = readl(0x1000F618) & ~0x07C00000;
+ write_r(0x1000F618, (temp | (pll3_dl << 22)));
+ } else { // REF lead FBK, delay REF
+ temp = readl(0x1000F618) & ~0xF8000000;
+ write_r(0x1000F618, (temp | (pll3_dl << 27 )));
+
+ temp = readl(0x1000F618) & ~0x07C00000;
+ write_r(0x1000F618, (temp | (0x00 << 22)));
+ }
+ }
+
+ if (!pll4_done) {
+ if (pll4_phase == 0) { // initial phase set to 0 for REF and FBK
+ temp = readl(0x1000F620) & ~0xF8000000;
+ write_r(0x1000F620, (temp | (0x00 << 27 )));
+
+ temp = readl(0x1000F620) & ~0x07C00000;
+ write_r(0x1000F620, (temp | (0x00 << 22)));
+ } else if (pll4_phase == 1) { // REF lag FBK, delay FBK
+ temp = readl(0x1000F620) & ~0xF8000000;
+ write_r(0x1000F620, (temp | (0x00 << 27 )));
+
+ temp = readl(0x1000F620) & ~0x07C00000;
+ write_r(0x1000F620, (temp | (pll4_dl << 22)));
+ } else { // REF lead FBK, delay REF
+ temp = readl(0x1000F620) & ~0xF8000000;
+ write_r(0x1000F620, (temp | (pll4_dl << 27 )));
+
+ temp = readl(0x1000F620) & ~0x07C00000;
+ write_r(0x1000F620, (temp | (0x00 << 22)));
+ }
+ }
+
+ udelay(20); // wait for external loop ready
+
+ /***********************************************
+ * 4. Enable jitter meter
+ ************************************************/
+
+ if (!pll2_done) {
+ temp = readl(0x1000F1CC);
+ write_r(0x1000F1CC, temp | 0x1); // 0x1000F1CC[0]=1 PLL2
+ }
+
+ if (!pll3_done) {
+ temp = readl(0x1000F1D0);
+ write_r(0x1000F1D0, temp | 0x1); // 0x1000F1D0[0]=1 PLL3
+ }
+
+ if (!pll4_done) {
+ temp = readl(0x1000F1D4);
+ write_r(0x1000F1D4, temp | 0x1); // 0x1000F1D4[0]=1 PLL4
+ }
+
+ udelay(80); // wait for jitter meter complete, 1/26MHz*1024
+
+ /*
+ jmeter_wait_count = 0;
+ if (!pll2_done)
+ {
+ while (!(readl(0x1000F32C)&0x00000001))
+ {
+ udelay(MEMPLL_JMETER_WAIT_TIME_BASE);
+ jmeter_wait_count++;
+ if (jmeter_wait_count>MEMPLL_JMETER_WAIT_TIMEOUT)
+ {
+ mcSHOW_ERR_MSG(("[ERROR] PLL2 Jeter Meter Count Timeout > %d us!!\n", MEMPLL_JMETER_WAIT_TIME_BASE*MEMPLL_JMETER_WAIT_TIMEOUT));
+ break;
+ }
+ }
+ }
+
+ jmeter_wait_count = 0;
+ if (!pll3_done)
+ {
+ while (!(readl(0x1000F32C)&0x00000002))
+ {
+ udelay(MEMPLL_JMETER_WAIT_TIME_BASE);
+ jmeter_wait_count++;
+ if (jmeter_wait_count>MEMPLL_JMETER_WAIT_TIMEOUT)
+ {
+ mcSHOW_ERR_MSG(("[ERROR] PLL3 Jeter Meter Count Timeout > %d us!!\n", MEMPLL_JMETER_WAIT_TIME_BASE*MEMPLL_JMETER_WAIT_TIMEOUT));
+ break;
+ }
+ }
+ }
+
+ jmeter_wait_count = 0;
+ if (!pll4_done)
+ {
+ while (!(readl(0x1000F32C)&0x00000004))
+ {
+ udelay(MEMPLL_JMETER_WAIT_TIME_BASE);
+ jmeter_wait_count++;
+ if (jmeter_wait_count>MEMPLL_JMETER_WAIT_TIMEOUT)
+ {
+ mcSHOW_ERR_MSG(("[ERROR] PLL4 Jeter Meter Count Timeout > %d us!!\n", MEMPLL_JMETER_WAIT_TIME_BASE*MEMPLL_JMETER_WAIT_TIMEOUT));
+ break;
+ }
+ }
+ }
+ */
+
+ /***********************************************
+ * 5. Check jitter meter counter value
+ ************************************************/
+ if (!pll2_done) {
+ one_count = readl(0x1000F320) >> 16; // 0x1000F320[31:16] PLL2 one count
+ zero_count = readl(0x1000F320) & 0x0000FFFF; // 0x1000F320[15:0] PLL2 zero count
+
+ if (pll2_phase == 0) {
+ if (one_count > (zero_count+MEMPLL_JMETER_CONFIDENCE_CNT)) {
+ // REF lag FBK
+ pll2_phase = 1;
+ pll2_dl++;
+
+ dprintf(CRITICAL, "[PLL_Phase_Calib] PLL2 initial phase: REF lag FBK, one_cnt/zero_cnt = %d/%d\n", one_count, zero_count);
+ } else if (zero_count > (one_count+MEMPLL_JMETER_CONFIDENCE_CNT)) {
+ // REF lead FBK
+ pll2_phase = 2;
+ pll2_dl++;
+
+ dprintf(CRITICAL, "[PLL_Phase_Calib] PLL2 initial phase: REF lead FBK, one_cnt/zero_cnt = %d/%d\n", one_count, zero_count);
+ } else {
+ // in phase at initial
+ pll2_done = 1;
+
+ dprintf(CRITICAL, "[PLL_Phase_Calib] PLL2 initial phase: REF in-phase FBK, one_cnt/zero_cnt = %d/%d\n", one_count, zero_count);
+ }
+ } else if (pll2_phase == 1) {
+ if ((zero_count+MEMPLL_JMETER_CONFIDENCE_CNT) >= one_count) {
+ pll2_done = 1;
+ dprintf(CRITICAL, "[PLL_Phase_Calib] PLL2 REF_DL: 0x0, FBK_DL: 0x%x, one_cnt/zero_cnt = %d/%d\n", pll2_dl, one_count, zero_count);
+ } else {
+ pll2_dl++;
+ }
+ } else {
+ if ((one_count+MEMPLL_JMETER_CONFIDENCE_CNT) >= zero_count) {
+ pll2_done = 1;
+ dprintf(CRITICAL, "[PLL_Phase_Calib] PLL2 REF_DL: 0x%x, FBK_DL: 0x0, one_cnt/zero_cnt = %d/%d\n", pll2_dl, one_count, zero_count);
+ } else {
+ pll2_dl++;
+ }
+ }
+ }
+
+ if (!pll3_done) {
+ one_count = readl(0x1000F324) >> 16; // 0x1000F324[31:16] PLL3 one count
+ zero_count = readl(0x1000F324) & 0x0000FFFF; // 0x1000F324[15:0] PLL3 zero count
+
+ if (pll3_phase == 0) {
+ if (one_count > (zero_count+MEMPLL_JMETER_CONFIDENCE_CNT)) {
+ // REF lag FBK
+ pll3_phase = 1;
+ pll3_dl++;
+
+ dprintf(CRITICAL, "[PLL_Phase_Calib] PLL3 initial phase: REF lag FBK, one_cnt/zero_cnt = %d/%d\n", one_count, zero_count);
+ } else if (zero_count > (one_count+MEMPLL_JMETER_CONFIDENCE_CNT)) {
+ // REF lead FBK
+ pll3_phase = 2;
+ pll3_dl++;
+
+ dprintf(CRITICAL, "[PLL_Phase_Calib] PLL3 initial phase: REF lead FBK, one_cnt/zero_cnt = %d/%d\n", one_count, zero_count);
+ } else {
+ // in phase at initial
+ pll3_done = 1;
+
+ dprintf(CRITICAL, "[PLL_Phase_Calib] PLL3 initial phase: REF in-phase FBK, one_cnt/zero_cnt = %d/%d\n", one_count, zero_count);
+ }
+ } else if (pll3_phase == 1) {
+ if ((zero_count+MEMPLL_JMETER_CONFIDENCE_CNT) >= one_count) {
+ pll3_done = 1;
+ dprintf(CRITICAL, "[PLL_Phase_Calib] PLL3 REF_DL: 0x0, FBK_DL: 0x%x, one_cnt/zero_cnt = %d/%d\n", pll3_dl, one_count, zero_count);
+ } else {
+ pll3_dl++;
+ }
+ } else {
+ if ((one_count+MEMPLL_JMETER_CONFIDENCE_CNT) >= zero_count) {
+ pll3_done = 1;
+ dprintf(CRITICAL, "[PLL_Phase_Calib] PLL3 REF_DL: 0x%x, FBK_DL: 0x0, one_cnt/zero_cnt = %d/%d\n", pll3_dl, one_count, zero_count);
+ } else {
+ pll3_dl++;
+ }
+ }
+ }
+
+ if (!pll4_done) {
+ one_count = readl(0x1000F328) >> 16; // 0x1000F328[31:16] PLL4 one count
+ zero_count = readl(0x1000F328) & 0x0000FFFF; // 0x1000F328[15:0] PLL4 zero count
+
+ if (pll4_phase == 0) {
+ if (one_count > (zero_count+MEMPLL_JMETER_CONFIDENCE_CNT)) {
+ // REF lag FBK
+ pll4_phase = 1;
+ pll4_dl++;
+
+ dprintf(CRITICAL, "[PLL_Phase_Calib] PLL4 initial phase: REF lag FBK, one_cnt/zero_cnt = %d/%d\n", one_count, zero_count);
+ } else if (zero_count > (one_count+MEMPLL_JMETER_CONFIDENCE_CNT)) {
+ // REF lead FBK
+ pll4_phase = 2;
+ pll4_dl++;
+
+ dprintf(CRITICAL, "[PLL_Phase_Calib] PLL4 initial phase: REF lead FBK, one_cnt/zero_cnt = %d/%d\n", one_count, zero_count);
+ } else {
+ // in phase at initial
+ pll4_done = 1;
+
+ dprintf(CRITICAL, "[PLL_Phase_Calib] PLL4 initial phase: REF in-phase FBK, one_cnt/zero_cnt = %d/%d\n", one_count, zero_count);
+ }
+ } else if (pll4_phase == 1) {
+ if ((zero_count+MEMPLL_JMETER_CONFIDENCE_CNT) >= one_count) {
+ pll4_done = 1;
+ dprintf(CRITICAL, "[PLL_Phase_Calib] PLL4 REF_DL: 0x0, FBK_DL: 0x%x, one_cnt/zero_cnt = %d/%d\n", pll4_dl, one_count, zero_count);
+ } else {
+ pll4_dl++;
+ }
+ } else {
+ if ((one_count+MEMPLL_JMETER_CONFIDENCE_CNT) >= zero_count) {
+ pll4_done = 1;
+ dprintf(CRITICAL, "[PLL_Phase_Calib] PLL4 REF_DL: 0x%x, FBK_DL: 0x0, one_cnt/zero_cnt = %d/%d\n", pll4_dl, one_count, zero_count);
+ } else {
+ pll4_dl++;
+ }
+ }
+ }
+
+ /***********************************************
+ * 6. Reset jitter meter value
+ ************************************************/
+
+ if (!pll2_done) {
+ pll2_dl++;
+ temp = readl(0x1000F1CC);
+ write_r(0x1000F1CC, temp & ~0x1); // 0x1000F1CC[0]=0 PLL2
+ }
+
+ if (!pll3_done) {
+ pll3_dl++;
+ temp = readl(0x1000F1D0);
+ write_r(0x1000F1D0, temp & ~0x1); // 0x1000F1D0[0]=0 PLL3
+ }
+
+ if (!pll4_done) {
+ pll4_dl++;
+ temp = readl(0x1000F1D4);
+ write_r(0x1000F1D4, temp & ~0x1); // 0x1000F1D4[0]=0 PLL4
+ }
+
+ /*************************************************************
+ * Then return to step 1 to adjust next delay chain tap value.
+ * Until we have ~ 50% of one or zero count on jitter meter
+ **************************************************************/
+
+ if (pll2_done && pll3_done && pll4_done) {
+ ret = 0;
+ break;
+ }
+
+ if (pll2_dl >= 32 || pll3_dl >= 32 || pll4_dl >= 32) {
+ ret = -1;
+ break;
+ }
+ }
+
+
+ if (ret != 0) {
+ dprintf(CRITICAL, "[PLL_Phase_Calib] MEMPLL 3PLL mode calibration fail\n");
+#if 0 // for FT, enable it...
+ while (1); // TBD
+#endif
+ }
+
+ /***********************************************
+ * 7. Set jitter meter clock to external FB path
+ ************************************************/
+ /*
+ temp = readl(0x1000F60C);
+ write_r(0x1000F60C, temp | 0x200); // 0x1000F60C[9] = 1 PLL2
+
+ temp = readl(0x1000F614);
+ write_r(0x1000F614, temp | 0x200); // 0x1000F614[9] = 1 PLL3
+
+ temp = readl(0x1000F61C);
+ write_r(0x1000F61C, temp | 0x200); // 0x1000F61C[9] = 1 PLL4
+ */
+ return ret;
+
+}
+#endif
+
+static unsigned int mt_get_mem_freq(void)
+{
+ int output = 0;
+ int i =0;
+ unsigned int temp, clk26cali_0, clk_cfg_8, clk_misc_cfg_1;
+
+ clk26cali_0 = readl(CLK26CALI_0);
+ write_r(CLK26CALI_0, clk26cali_0 | 0x80); // enable fmeter_en
+
+ clk_misc_cfg_1 = readl(CLK_MISC_CFG_1);
+ write_r(CLK_MISC_CFG_1, 0xFFFFFF00); // select divider
+
+ clk_cfg_8 = readl(CLK_CFG_8);
+ write_r(CLK_CFG_8, (14 << 8)); // select abist_cksw
+
+ temp = readl(CLK26CALI_0);
+ write_r(CLK26CALI_0, temp | 0x1); // start fmeter
+
+ /* wait frequency meter finish */
+ while (readl(CLK26CALI_0) & 0x1) {
+ udelay(50);
+ i++;
+ if (i > 10)
+ break;
+ }
+
+ temp = readl(CLK26CALI_1) & 0xFFFF;
+
+ output = (temp * 26000) / 1024; // Khz
+
+ write_r(CLK_CFG_8, clk_cfg_8);
+ write_r(CLK_MISC_CFG_1, clk_misc_cfg_1);
+ write_r(CLK26CALI_0, clk26cali_0);
+
+ if (i>10)
+ return 0;
+ else
+ return output;
+}
+
+/* mt_init_mempll() should be invoked after pmic_init */
+void mt_init_mempll(void)
+{
+ int DDR_type;
+
+ DDR_type = mt_get_dram_type();
+ if (TYPE_LPDDR2 == DDR_type) {
+ mt_mempll_init(DDR1066, PLL_MODE_1);
+ } else {
+ mt_mempll_init(DDR1333, PLL_MODE_1);
+ }
+
+ /* MEMPLL Calibration */
+#ifdef DDRPHY_3PLL_MODE
+ ret = mt_mempll_cali();
+#endif
+
+ //set mem_clk
+ write_r(CLK_CFG_0, 0x01000102); //mem_ck = mempll
+
+ dprintf(CRITICAL, "mt_pll_post_init: mt_get_mem_freq = %dKhz\n", mt_get_mem_freq());
+}
diff --git a/src/bsp/lk/platform/mt2635/drivers/pll/pll.c b/src/bsp/lk/platform/mt2635/drivers/pll/pll.c
new file mode 100644
index 0000000..aa02a3d
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/drivers/pll/pll.c
@@ -0,0 +1,469 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <reg.h>
+#include <platform/mt2635.h>
+#include <platform/pll.h>
+#include <platform/spm.h>
+#include <platform/spm_mtcmos.h>
+
+#define FMETER_EN 0
+#define USE_SPIN 0
+
+#if USE_SPIN
+
+#define udelay(x) spin(x)
+#define mdelay(x) udelay((x) * 1000)
+
+#else /* !USE_SPIN */
+
+#define my_delay(count) \
+ do { \
+ volatile unsigned int i = count * 26; \
+ for (; i != 0; i--); \
+ } while (0)
+
+#define udelay(x) my_delay(x)
+#define mdelay(x) udelay((x) * 1000)
+
+#endif /* USE_SPIN */
+
+#define aor(v, a, o) (((v) & (a)) | (o))
+#define write_r(a, v) writel(v, a)
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+#if FMETER_EN
+
+static u32 mt_fmeter_abist(u32 id, u32 arm_k1, u32 abist_k1)
+{
+ int output = 0;
+ int i = 0;
+ u32 temp, clk26cali_0, clk_cfg_8, clk_misc_cfg_1;
+
+ clk26cali_0 = readl(CLK26CALI_0);
+ write_r(CLK26CALI_0, clk26cali_0 | 0x80); /* enable fmeter_en */
+
+ clk_misc_cfg_1 = readl(CLK_MISC_CFG_1);
+ write_r(CLK_MISC_CFG_1, 0xFFFF0000 | (arm_k1 << 8) | abist_k1);
+ /* select divider */
+
+ clk_cfg_8 = readl(CLK_CFG_8);
+ write_r(CLK_CFG_8, (id << 8)); /* select abist_cksw */
+
+ temp = readl(CLK26CALI_0);
+ write_r(CLK26CALI_0, temp | 0x1); /* start fmeter */
+
+ /* wait frequency meter finish */
+ while ((readl(CLK26CALI_0) & 0x1) && (++i <= 10))
+ udelay(50);
+
+ temp = readl(CLK26CALI_1) & 0xFFFF;
+
+ output = (temp * 26000) * (abist_k1 + 1) * (arm_k1 + 1) / 1024;
+
+ write_r(CLK_CFG_8, clk_cfg_8);
+ write_r(CLK_MISC_CFG_1, clk_misc_cfg_1);
+ write_r(CLK26CALI_0, clk26cali_0);
+
+ if (i > 10)
+ return 0;
+ else
+ return output;
+}
+
+static u32 mt_fmeter_ckgen(u32 id, u32 ckgen_k1)
+{
+ int output = 0;
+ int i = 0;
+ u32 temp, clk26cali_0, clk_cfg_9, clk_misc_cfg_1;
+
+ clk26cali_0 = readl(CLK26CALI_0);
+ write_r(CLK26CALI_0, clk26cali_0 | 0x80); /* enable fmeter_en */
+
+ clk_misc_cfg_1 = readl(CLK_MISC_CFG_1);
+ write_r(CLK_MISC_CFG_1, 0x00FFFFFF | ckgen_k1 << 24);
+ /* select divider */
+
+ clk_cfg_9 = readl(CLK_CFG_9);
+ write_r(CLK_CFG_9, (id << 16)); /* select ckgen_cksw */
+
+ temp = readl(CLK26CALI_0);
+ write_r(CLK26CALI_0, temp | 0x10); /* start fmeter */
+
+ /* wait frequency meter finish */
+ while ((readl(CLK26CALI_0) & 0x10) && (++i <= 10))
+ udelay(50);
+
+ temp = readl(CLK26CALI_2) & 0xFFFF;
+
+ output = (temp * 26000) * (ckgen_k1 + 1) / 1024;
+
+ write_r(CLK_CFG_9, clk_cfg_9);
+ write_r(CLK_MISC_CFG_1, clk_misc_cfg_1);
+ write_r(CLK26CALI_0, clk26cali_0);
+
+ if (i > 10)
+ return 0;
+ else
+ return output;
+}
+
+static u32 mt_get_cpu_freq(void)
+{
+ return mt_fmeter_abist(39, 3, 0);
+}
+
+static u32 mt_get_bus_freq(void)
+{
+ return mt_fmeter_ckgen(1, 0);
+}
+
+static const char *abist_clk[] = {
+ [1] = "AD_MAIN_H546M_CK",
+ [2] = "AD_MAIN_H364M_CK",
+ [3] = "AD_MAIN_H218P4M_CK",
+ [4] = "AD_MAIN_H156M_CK",
+ [5] = "AD_UNIV_624M_CK",
+ [6] = "AD_UNIV_416M_CK",
+ [7] = "AD_UNIV_249P6M_CK",
+ [8] = "AD_UNIV_178P3M_CK",
+ [9] = "AD_UNIV_48M_CK",
+ [10] = "AD_USB_48M_CK",
+ [11] = "AD_MMPLL_CK",
+ [12] = "AD_MSDCPLL_CK",
+ [13] = "AD_DPICLK",
+ [14] = "clkph_MCK_o",
+ [15] = "AD_MEMPLL2_CKOUT0_PRE_ISO",
+ [16] = "AD_APLL1_CK",
+ [17] = "AD_MDPLL1_416M_CK",
+ [18] = "AD_WPLL_245P76M_CK",
+ [19] = "AD_WHPLL_250P25M_CK",
+ [20] = "rtc32k_ck_i",
+ [21] = "AD_SYS_26M_CK",
+ [22] = "AD_VENCPLL_CK",
+ [23] = "AD_TVDPLL_CK",
+ [24] = "D_VENC_H98P6M_CK",
+ [25] = "AD_WHPLL_audio_CK",
+ [33] = "abist_clk1",
+ [34] = "abist_clk2",
+ [35] = "abist_clk3",
+ [36] = "abist_clk4",
+ [37] = "abist_clk5",
+ [38] = "abist_clk6",
+ [39] = "abist_clk7",
+ [40] = "abist_clk8",
+ [41] = "abist_clk9",
+ [42] = "abist_clk10",
+ [43] = "abist_clk11",
+ [44] = "abist_clk12",
+ [45] = "abist_clk13",
+ [46] = "abist_clk14",
+ [47] = "abist_clk15",
+ [48] = "abist_clk16",
+ [49] = "abist_clk17",
+ [50] = "abist_clk18",
+ [51] = "abist_clk19",
+ [52] = "abist_clk20",
+ [53] = "abist_clk21",
+};
+
+static const char *ckgen_clk[] = {
+ [1] = "hf_faxi_ck",
+ [2] = "hd_faxi_ck",
+ [3] = "hf_fdpi0_ck",
+ [4] = "hf_fddrphycfg_ck",
+ [5] = "hf_fmm_ck",
+ [6] = "f_fpwm_ck",
+ [7] = "hf_fvdec_ck",
+ [8] = "hf_fmfg_ck",
+ [9] = "hf_fcamtg_ck",
+ [10] = "f_fuart_ck",
+ [11] = "hf_fspi_ck",
+ [12] = "f_fusb20_ck",
+ [13] = "hf_fmsdc30_0_ck",
+ [14] = "hf_fmsdc30_1_ck",
+ [15] = "hf_fmsdc30_2_ck",
+ [16] = "hf_faudio_ck",
+ [17] = "hf_faud_intbus_ck",
+ [18] = "hf_fpmicspi_ck",
+ [19] = "f_frtc_ck",
+ [20] = "f_f26m_ck",
+ [21] = "f_f32k_md1_ck",
+ [22] = "f_frtc_conn_ck",
+ [23] = "hf_fusb20p1_ck",
+ [24] = "hg_fmipicfg_ck",
+ [25] = "hd_haxi_nli_ck",
+ [26] = "hd_qaxidcm_ck",
+ [27] = "f_ffpc_ck",
+ [28] = "hf_fscam_ck",
+ [29] = "f_fckbus_ck_scan",
+ [30] = "f_fckrtc_ck_scan",
+ [31] = "hf_fatb_ck",
+ [32] = "hf_faud1_ck",
+ [33] = "hf_faud2_ck",
+ [34] = "hf_fmsdc50_0_ck",
+ [35] = "hf_firda_ck",
+ [36] = "hf_firtx_ck",
+ [37] = "hf_fdisppwm",
+ [38] = "hs_fmfg13m_ck",
+};
+
+#endif /* FMETER_EN */
+
+/* mt_pll_post_init() should be invoked after pmic_init */
+void mt_pll_post_init(void)
+{
+ unsigned int temp;
+
+ temp = readl(AP_PLL_CON3);
+ write_r(AP_PLL_CON3, temp & 0xFFF44440); /* Only UNIVPLL SW Control */
+
+ temp = readl(AP_PLL_CON4);
+ write_r(AP_PLL_CON4, temp & 0xFFFFFFF4); /* Only UNIVPLL SW Control */
+
+#if FMETER_EN
+ dprintf(CRITICAL, "mt_get_cpu_freq(): %d KHz\n", mt_get_cpu_freq());
+ dprintf(CRITICAL, "mt_get_bus_freq(): %d KHz\n", mt_get_bus_freq());
+
+ for (temp = 0; temp < ARRAY_SIZE(abist_clk); temp++) {
+ if (!abist_clk[temp])
+ continue;
+
+ dprintf(CRITICAL, "%2u: %s: %d\n", temp, abist_clk[temp],
+ mt_fmeter_abist(temp, 0, 0));
+ }
+
+ for (temp = 0; temp < ARRAY_SIZE(ckgen_clk); temp++) {
+ if (!ckgen_clk[temp])
+ continue;
+
+ dprintf(CRITICAL, "%2u: %s: %d\n", temp, ckgen_clk[temp],
+ mt_fmeter_ckgen(temp, 0));
+ }
+#endif /* FMETER_EN */
+}
+
+void mt_pll_init(void)
+{
+ unsigned int temp;
+
+ write_r(ACLKEN_DIV, 0x12); /* MCU Bus DIV2 */
+
+ write_r(CLKSQ_STB_CON0, 0x98940501); /* reduce CLKSQ disable time */
+
+ write_r(PLL_ISO_CON0, 0x00080008);
+ /* extend PWR/ISO control timing to 1us */
+
+ write_r(AP_PLL_CON6, 0x00000000);
+
+ /*************
+ * xPLL PWR ON
+ **************/
+ temp = readl(ARMPLL_PWR_CON0);
+ write_r(ARMPLL_PWR_CON0, temp | 0x1);
+
+ temp = readl(MAINPLL_PWR_CON0);
+ write_r(MAINPLL_PWR_CON0, temp | 0x1);
+
+ temp = readl(UNIVPLL_PWR_CON0);
+ write_r(UNIVPLL_PWR_CON0, temp | 0x1);
+
+ temp = readl(MMPLL_PWR_CON0);
+ write_r(MMPLL_PWR_CON0, temp | 0x1);
+
+ temp = readl(MSDCPLL_PWR_CON0);
+ write_r(MSDCPLL_PWR_CON0, temp | 0x1);
+
+ temp = readl(VENCPLL_PWR_CON0);
+ write_r(VENCPLL_PWR_CON0, temp | 0x1);
+
+ temp = readl(TVDPLL_PWR_CON0);
+ write_r(TVDPLL_PWR_CON0, temp | 0x1);
+
+ temp = readl(APLL1_PWR_CON0);
+ write_r(APLL1_PWR_CON0, temp | 0x1);
+
+ temp = readl(APLL2_PWR_CON0);
+ write_r(APLL2_PWR_CON0, temp | 0x1);
+
+ udelay(5); /* wait for xPLL_PWR_ON ready (min delay is 1us) */
+
+ /******************
+ * xPLL ISO Disable
+ *******************/
+ temp = readl(ARMPLL_PWR_CON0);
+ write_r(ARMPLL_PWR_CON0, temp & 0xFFFFFFFD);
+
+ temp = readl(MAINPLL_PWR_CON0);
+ write_r(MAINPLL_PWR_CON0, temp & 0xFFFFFFFD);
+
+ temp = readl(UNIVPLL_PWR_CON0);
+ write_r(UNIVPLL_PWR_CON0, temp & 0xFFFFFFFD);
+
+ temp = readl(MMPLL_PWR_CON0);
+ write_r(MMPLL_PWR_CON0, temp & 0xFFFFFFFD);
+
+ temp = readl(MSDCPLL_PWR_CON0);
+ write_r(MSDCPLL_PWR_CON0, temp & 0xFFFFFFFD);
+
+ temp = readl(VENCPLL_PWR_CON0);
+ write_r(VENCPLL_PWR_CON0, temp & 0xFFFFFFFD);
+
+ temp = readl(TVDPLL_PWR_CON0);
+ write_r(TVDPLL_PWR_CON0, temp & 0xFFFFFFFD);
+
+ temp = readl(APLL1_PWR_CON0);
+ write_r(APLL1_PWR_CON0, temp & 0xFFFFFFFD);
+
+ temp = readl(APLL2_PWR_CON0);
+ write_r(APLL2_PWR_CON0, temp & 0xFFFFFFFD);
+
+ /********************
+ * xPLL Frequency Set
+ *********************/
+ write_r(ARMPLL_CON1, 0x810FC000); /* 819MHz */
+
+ write_r(MAINPLL_CON1, 0x800A8000); /* 1092MHz */
+
+ write_r(UNIVPLL_CON1, 0x81180000);
+
+ write_r(MMPLL_CON1, 0x82114EC4); /* 450MHz */
+
+ write_r(MSDCPLL_CON1, 0x810F6276); /* 800MHz */
+
+ write_r(VENCPLL_CON1, 0x831713B1); /* 300MHz */
+
+ write_r(TVDPLL_CON1, 0x8316D89D); /* 297MHz */
+
+ /* APLL1 and APLL2 use the default setting */
+ write_r(APLL2_CON1, 0xB7945EA6); /* 90.3168MHz */
+
+ /***********************
+ * xPLL Frequency Enable
+ ************************/
+ temp = readl(ARMPLL_CON0);
+ write_r(ARMPLL_CON0, temp | 0x1);
+
+ temp = readl(MAINPLL_CON0);
+ write_r(MAINPLL_CON0, temp | 0x1);
+
+ temp = readl(UNIVPLL_CON0);
+ write_r(UNIVPLL_CON0, temp | 0x1);
+
+ temp = readl(MMPLL_CON0);
+ write_r(MMPLL_CON0, temp | 0x1);
+
+ temp = readl(MSDCPLL_CON0);
+ write_r(MSDCPLL_CON0, temp | 0x1);
+
+ temp = readl(VENCPLL_CON0);
+ write_r(VENCPLL_CON0, temp | 0x1);
+
+ temp = readl(TVDPLL_CON0);
+ write_r(TVDPLL_CON0, temp | 0x1);
+
+ temp = readl(APLL1_CON0);
+ write_r(APLL1_CON0, temp | 0x1);
+
+ temp = readl(APLL2_CON0);
+ write_r(APLL2_CON0, temp | 0x1);
+
+ udelay(40); /* wait for PLL stable (min delay is 20us) */
+
+ /***************
+ * xPLL DIV RSTB
+ ****************/
+
+ temp = readl(MAINPLL_CON0);
+ write_r(MAINPLL_CON0, temp | 0x01000000);
+
+ temp = readl(UNIVPLL_CON0);
+ write_r(UNIVPLL_CON0, temp | 0x01000000);
+
+ /**************
+ * INFRA CLKMUX
+ ***************/
+
+ temp = readl(TOP_DCMCTL);
+ write_r(TOP_DCMCTL, temp | 0x1); /* Enable INFRA Bus Divider */
+
+ /**************
+ * Enable Infra DCM
+ ***************/
+ write_r(INFRA_GLOBALCON_DCMDBC,
+ aor(readl(INFRA_GLOBALCON_DCMDBC),
+ ~INFRA_GLOBALCON_DCMDBC_MASK, INFRA_GLOBALCON_DCMDBC_ON));
+ write_r(INFRA_GLOBALCON_DCMFSEL,
+ aor(readl(INFRA_GLOBALCON_DCMFSEL),
+ ~INFRA_GLOBALCON_DCMFSEL_MASK, INFRA_GLOBALCON_DCMFSEL_ON));
+ write_r(INFRA_GLOBALCON_DCMCTL,
+ aor(readl(INFRA_GLOBALCON_DCMCTL),
+ ~INFRA_GLOBALCON_DCMCTL_MASK, INFRA_GLOBALCON_DCMCTL_ON));
+
+ /* CA7: INFRA_TOPCKGEN_CKDIV1[4:0](0x10000008) */
+ temp = readl(TOP_CKDIV1);
+ write_r(TOP_CKDIV1, temp & 0xFFFFFFE0); /* CPU clock divide by 1 */
+
+ /* CA7: INFRA_TOPCKGEN_CKMUXSEL[3:2] (0x10000000) = 4 */
+ temp = readl(TOP_CKMUXSEL);
+ write_r(TOP_CKMUXSEL, temp | 0x4); /* switch CA7_ck to ARMCA7PLL */
+
+ /************
+ * TOP CLKMUX
+ *************/
+
+ write_r(CLK_CFG_0, 0x01000002);
+ /* mm_ck=vencpll, ddrphycfg_ck=26M, mem_ck=26M, axi=syspll_d5 */
+
+ write_r(CLK_CFG_1, 0x01010180);
+ /* camtg=univpll_d26 , mfg_ck=mmpll_ck, vdec_ck=syspll_d2, pwm_ck= gating */
+
+ write_r(CLK_CFG_2, 0x01010100);/* msdc50_0=syspll1_d2, usb20=univpll1_d8, spi_ck=syspll3_d2, uart=26M */
+
+ write_r(CLK_CFG_3, 0x07020202);
+ /* msdc30_3=msdcpll_d16, msdc30_2=msdcpll_d4, msdc30_1=msdcpll_d4, msdc30_0=msdcpll_d2, */
+
+ write_r(CLK_CFG_4, 0x01000100);
+ /* scp_ck=syspll1_d8, pmicspi=26MHz, aud_intbus=syspll1_d4, aud_ck=26M, */
+
+ write_r(CLK_CFG_5, 0x01010101);
+ /* mfg13m=ad_sys_26M_d2, scam_ck=syspll3_d2, dpi0_ck=tvdpll, atb_ck=syspll1_d2, */
+
+ write_r(CLK_CFG_6, 0x01010001);
+ /* irtx_ck=ad_sys_26M_d2 , irda_ck=univpll2_d4, aud2_ck=26M , aud1_ck=apll1, */
+
+ write_r(CLK_CFG_7, 0x00000000);
+ /* NULL, NULL, NULL, disppwm=26M, */
+
+ write_r(CLK_SCP_CFG_0, 0x3FF); /* enable scpsys clock off control */
+ write_r(CLK_SCP_CFG_1, 0x11); /* enable scpsys clock off control */
+
+ /* MTCMOS */
+ write_r(SPM_POWERON_CONFIG_SET, (SPM_PROJECT_CODE << 16) | (1U << 0));
+ spm_mtcmos_ctrl_disp(STA_POWER_ON);
+ spm_mtcmos_ctrl_mdsys2(STA_POWER_ON);
+
+ /* CG */
+ write_r(INFRA_PDN_CLR0, 0xFFFFFFFF);
+ write_r(PERI_PDN_CLR0, 0xFFFFFFFF);
+}
diff --git a/src/bsp/lk/platform/mt2635/drivers/pmic/pmic.c b/src/bsp/lk/platform/mt2635/drivers/pmic/pmic.c
new file mode 100644
index 0000000..cd35f9f
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/drivers/pmic/pmic.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <debug.h>
+#include <platform/pmic_wrap_init.h>
+#include <platform/pmic.h>
+
+static unsigned int pmic_read_interface (unsigned int RegNum, unsigned int *val, unsigned int MASK, unsigned int SHIFT)
+{
+ unsigned int return_value, pmic_reg, rdata;
+
+ return_value = pwrap_wacs2(0, RegNum, 0, &rdata);
+ if (return_value)
+ return return_value;
+
+ pmic_reg = rdata;
+ pmic_reg &= (MASK << SHIFT);
+ *val = (pmic_reg >> SHIFT);
+
+ return return_value;
+}
+
+static unsigned int pmic_config_interface (unsigned int RegNum, unsigned int val, unsigned int MASK, unsigned int SHIFT)
+{
+ unsigned int return_value, pmic_reg, rdata;
+
+ return_value = pwrap_wacs2(0, RegNum, 0, &rdata);
+ if (return_value)
+ return return_value;
+
+ pmic_reg = rdata;
+ pmic_reg &= ~(MASK << SHIFT);
+ pmic_reg |= (val << SHIFT);
+
+ return_value = pwrap_wacs2(1, RegNum, pmic_reg, &rdata);
+ return return_value;
+}
+
+unsigned int pmic_get_register_value(unsigned int RegNum, unsigned int MASK, unsigned int SHIFT)
+{
+ unsigned int val;
+
+ pmic_read_interface (RegNum, &val, MASK, SHIFT);
+ return val;
+}
+
+void upmu_set_reg_value(uint32_t reg, uint32_t reg_val)
+{
+ pmic_config_interface(reg, reg_val, 0xFFFF, 0x0);
+}
+
+unsigned int upmu_get_reg_value(uint32_t reg)
+{
+ unsigned int reg_val = 0;
+
+ pmic_read_interface(reg, ®_val, 0xFFFF, 0x0);
+ return reg_val;
+}
+
+unsigned int pmic_get_vcore(void)
+{
+ unsigned int reg;
+
+ reg = pmic_get_register_value(VCORE_ADDR, VCORE_MASK, VCORE_SHIFT);
+ reg = 600 + (reg * 625 / 100);
+ return reg;
+}
+
+void pmic_set_vcore(unsigned int voltage_mv)
+{
+ unsigned int reg;
+
+ if (voltage_mv < 700)
+ return;
+
+ pmic_config_interface(0x060E, 0x0, 0x3, 0);
+ reg = (voltage_mv - 600) * 100 / 625;
+ pmic_config_interface(VCORE_ADDR, reg, VCORE_MASK, VCORE_SHIFT);
+ dprintf(CRITICAL, "[pmic_set_vcore] vcore: %d mv\r\n", pmic_get_vcore());
+}
+
+void pmic_set_efuse(unsigned int voltage_mv)
+{
+ int index;
+
+ if (voltage_mv <= 1800)
+ index = 0x3;
+ else if (voltage_mv >= 2200)
+ index = 0x7;
+ else
+ index = 0x3 + (voltage_mv - 1800)/100;
+
+ pmic_config_interface(0x0A5E, index, 0x7, 4);
+}
+
+unsigned int pmic_enable_efuse(bool on)
+{
+ unsigned int benable;
+
+ if (on)
+ benable = 0x1;
+ else
+ benable = 0x0;
+
+ pmic_config_interface(EFUSE_ADDR, benable, EFUSE_MASK, EFUSE_SHIFT);
+ dprintf(CRITICAL, "[pmic_enable_efuse] efuse(%d)\r\n", benable);
+
+ return pmic_get_register_value(EFUSE_ADDR, EFUSE_MASK, 15);
+}
+
+void mt_pmic_init(void)
+{
+ int ret;
+
+ ret = pwrap_init_preloader();
+ dprintf(CRITICAL, "[%s] Done, ret(%d)\r\n", __func__, ret);
+}
diff --git a/src/bsp/lk/platform/mt2635/drivers/pmic/pmic_wrap_init.c b/src/bsp/lk/platform/mt2635/drivers/pmic/pmic_wrap_init.c
new file mode 100644
index 0000000..1aa8862
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/drivers/pmic/pmic_wrap_init.c
@@ -0,0 +1,570 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <platform/pmic_wrap_init.h>
+
+typedef uint32_t (*loop_condition_fp)(uint32_t);
+
+static inline uint32_t wait_for_fsm_idle(uint32_t x)
+{
+ return (GET_WACS0_FSM(x) != WACS_FSM_IDLE );
+}
+static inline uint32_t wait_for_fsm_vldclr(uint32_t x)
+{
+ return (GET_WACS0_FSM(x) != WACS_FSM_WFVLDCLR);
+}
+static inline uint32_t wait_for_sync(uint32_t x)
+{
+ return (GET_SYNC_IDLE0(x) != WACS_SYNC_IDLE);
+}
+static inline uint32_t wait_for_idle_and_sync(uint32_t x)
+{
+ return ((GET_WACS2_FSM(x) != WACS_FSM_IDLE) || (GET_SYNC_IDLE2(x) != WACS_SYNC_IDLE)) ;
+}
+static inline uint32_t wait_for_cipher_ready(uint32_t x)
+{
+ return (x != 3) ;
+}
+
+static inline uint32_t wait_for_state_ready_init(loop_condition_fp fp,uint32_t timeout_us,uint32_t *wacs_register,uint32_t *read_reg)
+{
+ uint32_t reg_rdata;
+
+ do {
+ reg_rdata = WRAP_RD32(wacs_register);
+ } while (fp(reg_rdata));
+
+ if (read_reg)
+ *read_reg = reg_rdata;
+
+ return 0;
+}
+
+static inline uint32_t wait_for_state_idle(loop_condition_fp fp,uint32_t timeout_us,uint32_t *wacs_register,uint32_t *wacs_vldclr_register,uint32_t *read_reg)
+{
+ uint32_t reg_rdata;
+
+ do {
+ reg_rdata = WRAP_RD32(wacs_register);
+ if (GET_INIT_DONE0(reg_rdata) != WACS_INIT_DONE) {
+ PWRAPERR("initialization isn't finished \n");
+ return E_PWR_NOT_INIT_DONE;
+ }
+
+ switch (GET_WACS0_FSM( reg_rdata)) {
+ case WACS_FSM_WFVLDCLR:
+ WRAP_WR32(wacs_vldclr_register , 1);
+ PWRAPERR("WACS_FSM = PMIC_WRAP_WACS_VLDCLR\n");
+ break;
+ case WACS_FSM_WFDLE:
+ PWRAPERR("WACS_FSM = WACS_FSM_WFDLE\n");
+ break;
+ case WACS_FSM_REQ:
+ PWRAPERR("WACS_FSM = WACS_FSM_REQ\n");
+ break;
+ default:
+ break;
+ }
+ } while (fp(reg_rdata));
+
+ if (read_reg)
+ *read_reg = reg_rdata;
+
+ return 0;
+}
+
+static inline uint32_t wait_for_state_ready(loop_condition_fp fp,uint32_t timeout_us,uint32_t *wacs_register,uint32_t *read_reg)
+{
+ uint32_t reg_rdata;
+
+ do {
+ reg_rdata = WRAP_RD32(wacs_register);
+ if (GET_INIT_DONE0(reg_rdata) != WACS_INIT_DONE) {
+ PWRAPERR("initialization isn't finished \n");
+ return E_PWR_NOT_INIT_DONE;
+ }
+ } while (fp(reg_rdata));
+
+ if (read_reg)
+ *read_reg = reg_rdata;
+
+ return 0;
+}
+
+int pwrap_wacs2(uint32_t write, uint32_t adr, uint32_t wdata, uint32_t *rdata)
+{
+ uint32_t reg_rdata, wacs_write, wacs_adr, wacs_cmd, return_value;
+
+ if ((write & ~(0x1)) != 0) return E_PWR_INVALID_RW;
+ if ((adr & ~(0xffff)) != 0) return E_PWR_INVALID_ADDR;
+ if ((wdata & ~(0xffff)) != 0) return E_PWR_INVALID_WDAT;
+
+ return_value = wait_for_state_idle(wait_for_fsm_idle,TIMEOUT_WAIT_IDLE,PMIC_WRAP_WACS2_RDATA,PMIC_WRAP_WACS2_VLDCLR,0);
+ if (return_value) {
+ PWRAPERR("wait_for_fsm_idle fail,return_value=%d\n",return_value);
+ return return_value;
+ }
+
+ wacs_write = write << 31;
+ wacs_adr = (adr >> 1) << 16;
+ wacs_cmd = wacs_write | wacs_adr | wdata;
+
+ WRAP_WR32(PMIC_WRAP_WACS2_CMD, wacs_cmd);
+ if (write == 0) {
+ if (NULL == rdata) {
+ return_value= E_PWR_INVALID_ARG;
+ PWRAPERR("rdata is a NULL pointer, return_value=%d\n", return_value);
+ return return_value;
+ }
+
+ return_value = wait_for_state_ready(wait_for_fsm_vldclr, TIMEOUT_READ, PMIC_WRAP_WACS2_RDATA, ®_rdata);
+ if (return_value) {
+ PWRAPERR("wait_for_fsm_vldclr fail,return_value=%d\n",return_value);
+ return return_value;
+ }
+
+ *rdata = GET_WACS0_RDATA(reg_rdata);
+ WRAP_WR32(PMIC_WRAP_WACS2_VLDCLR, 1);
+ }
+
+ return 0;
+}
+
+static int _pwrap_wacs2_nochk(uint32_t write, uint32_t adr, uint32_t wdata, uint32_t *rdata)
+{
+ uint32_t reg_rdata, wacs_write, wacs_adr, wacs_cmd, return_value;
+
+ if ( (write & ~(0x1)) != 0) return E_PWR_INVALID_RW;
+ if ( (adr & ~(0xffff)) != 0) return E_PWR_INVALID_ADDR;
+ if ( (wdata & ~(0xffff)) != 0) return E_PWR_INVALID_WDAT;
+
+ return_value = wait_for_state_ready_init(wait_for_fsm_idle, TIMEOUT_WAIT_IDLE, PMIC_WRAP_WACS2_RDATA, 0);
+ if (return_value) {
+ PWRAPERR("_pwrap_wacs2_nochk write command fail,return_value=%x\n", return_value);
+ return return_value;
+ }
+
+ wacs_write = write << 31;
+ wacs_adr = (adr >> 1) << 16;
+ wacs_cmd = wacs_write | wacs_adr | wdata;
+ WRAP_WR32(PMIC_WRAP_WACS2_CMD, wacs_cmd);
+
+ if (write == 0) {
+ if (NULL == rdata) {
+ PWRAPERR("rdata is a NULL pointer\n");
+ return_value= E_PWR_INVALID_ARG;
+ return return_value;
+ }
+
+ return_value = wait_for_state_ready_init(wait_for_fsm_vldclr, TIMEOUT_READ, PMIC_WRAP_WACS2_RDATA, ®_rdata);
+ if (return_value) {
+ PWRAPERR("wait_for_fsm_vldclr fail,return_value=%d\n",return_value);
+ return return_value;
+ }
+
+ *rdata = GET_WACS0_RDATA(reg_rdata);
+ WRAP_WR32(PMIC_WRAP_WACS2_VLDCLR, 1);
+ }
+
+ return 0;
+}
+
+static int pwrap_read_nochk(uint32_t adr, uint32_t *rdata)
+{
+ return _pwrap_wacs2_nochk(0, adr, 0, rdata);
+}
+
+static int pwrap_write_nochk(uint32_t adr, uint32_t wdata)
+{
+ return _pwrap_wacs2_nochk(1, adr, wdata, 0);
+}
+
+static int _pwrap_init_dio(uint32_t dio_en)
+{
+ uint32_t arb_en_backup, rdata, return_value;
+
+ arb_en_backup = WRAP_RD32(PMIC_WRAP_HIPRIO_ARB_EN);
+ WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, WACS2);
+ pwrap_write_nochk(MT6328_DEW_DIO_EN, dio_en);
+
+ return_value = wait_for_state_ready_init(wait_for_idle_and_sync, TIMEOUT_WAIT_IDLE, PMIC_WRAP_WACS2_RDATA, 0);
+ if (return_value) {
+ PWRAPERR("_pwrap_init_dio fail,return_value=%x\n", return_value);
+ return return_value;
+ }
+
+ WRAP_WR32(PMIC_WRAP_DIO_EN, dio_en);
+ pwrap_read_nochk(MT6328_DEW_READ_TEST, &rdata);
+ if (rdata != MT6328_DEFAULT_VALUE_READ_TEST) {
+ PWRAPERR("[Dio_mode][Read Test] fail,dio_en = %x, READ_TEST rdata=%x, exp=0x5aa5\n", dio_en, rdata);
+ return E_PWR_READ_TEST_FAIL;
+ }
+
+ WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, arb_en_backup);
+ return 0;
+}
+
+static int _pwrap_init_cipher(void)
+{
+ uint32_t arb_en_backup, rdata, return_value;
+
+ arb_en_backup = WRAP_RD32(PMIC_WRAP_HIPRIO_ARB_EN);
+
+ WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, WACS2);
+ WRAP_WR32(PMIC_WRAP_CIPHER_SWRST, 1);
+ WRAP_WR32(PMIC_WRAP_CIPHER_SWRST, 0);
+ WRAP_WR32(PMIC_WRAP_CIPHER_KEY_SEL, 1);
+ WRAP_WR32(PMIC_WRAP_CIPHER_IV_SEL, 2);
+ WRAP_WR32(PMIC_WRAP_CIPHER_EN, 1);
+
+ pwrap_write_nochk(MT6328_DEW_CIPHER_SWRST, 0x1);
+ pwrap_write_nochk(MT6328_DEW_CIPHER_SWRST, 0x0);
+ pwrap_write_nochk(MT6328_DEW_CIPHER_KEY_SEL, 0x1);
+ pwrap_write_nochk(MT6328_DEW_CIPHER_IV_SEL, 0x2);
+ pwrap_write_nochk(MT6328_DEW_CIPHER_EN, 0x1);
+
+ return_value = wait_for_state_ready_init(wait_for_cipher_ready, TIMEOUT_WAIT_IDLE, PMIC_WRAP_CIPHER_RDY, 0);
+ if (return_value) {
+ PWRAPERR("wait for cipher data ready@AP fail,return_value=%x\n", return_value);
+ return return_value;
+ }
+
+ do {
+ pwrap_read_nochk(MT6328_DEW_CIPHER_RDY, &rdata);
+ } while (rdata != 0x1);
+
+ pwrap_write_nochk(MT6328_DEW_CIPHER_MODE, 0x1);
+
+ return_value=wait_for_state_ready_init(wait_for_idle_and_sync, TIMEOUT_WAIT_IDLE, PMIC_WRAP_WACS2_RDATA, 0);
+ if (return_value) {
+ PWRAPERR("wait for cipher mode idle fail,return_value=%x\n", return_value);
+ return return_value;
+ }
+ WRAP_WR32(PMIC_WRAP_CIPHER_MODE, 1);
+
+ pwrap_read_nochk(MT6328_DEW_READ_TEST, &rdata);
+ if (rdata != MT6328_DEFAULT_VALUE_READ_TEST) {
+ PWRAPERR("_pwrap_init_cipher,read test error,error code=%x, rdata=%x\n", 1, rdata);
+ return E_PWR_READ_TEST_FAIL;
+ }
+
+ WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, arb_en_backup);
+ return 0;
+}
+
+static int _pwrap_init_sistrobe(void)
+{
+ uint32_t arb_en_backup, rdata, i;
+ uint32_t tmp1, tmp2, result_faulty = 0;
+ uint32_t result[2]= {0,0};
+ int ind;
+ int leading_one[2]= {-1,-1};
+ int tailing_one[2]= {-1,-1};
+
+ arb_en_backup = WRAP_RD32(PMIC_WRAP_HIPRIO_ARB_EN);
+ WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN ,WACS2);
+
+ for (ind = 0; ind < 24; ind++) {
+ WRAP_WR32(PMIC_WRAP_SI_CK_CON, ((ind >> 2) & 0x7));
+ WRAP_WR32(PMIC_WRAP_SIDLY, (0x3 - (ind & 0x3)));
+
+ _pwrap_wacs2_nochk(0, MT6328_DEW_READ_TEST, 0, &rdata);
+ if ( rdata == MT6328_DEFAULT_VALUE_READ_TEST )
+ result[0] |= (0x1 << ind);
+ }
+
+ result[1] = result[0];
+ for (ind=23; ind>=0; ind--) {
+ if ((result[0] & (0x1 << ind)) && leading_one[0] == -1) {
+ leading_one[0] = ind;
+ }
+ if (leading_one[0] > 0) { break;}
+ }
+ for (ind=23; ind>=0; ind--) {
+ if ((result[1] & (0x1 << ind)) && leading_one[1] == -1) {
+ leading_one[1] = ind;
+ }
+ if (leading_one[1] > 0) { break;}
+ }
+
+ for (ind=0; ind<24; ind++) {
+ if ((result[0] & (0x1 << ind)) && tailing_one[0] == -1) {
+ tailing_one[0] = ind;
+ }
+ if (tailing_one[0] > 0) { break;}
+ }
+ for (ind=0; ind<24; ind++) {
+ if ( (result[1] & (0x1 << ind)) && tailing_one[1] == -1) {
+ tailing_one[1] = ind;
+ }
+ if (tailing_one[1] > 0) { break;}
+ }
+
+ for ( i=0; i<2; i++) {
+ tmp1 = (0x1 << (leading_one[i]+1)) - 1;
+ tmp2 = (0x1 << tailing_one[i]) - 1;
+ if ( (tmp1 - tmp2) != result[i] ) {
+ PWRAPERR("_pwrap_init_sistrobe Fail at PMIC %d, result = %x, leading_one:%d, tailing_one:%d\n", i+1, result[i], leading_one[i], tailing_one[i]);
+ result_faulty = 0x1;
+ }
+ }
+
+ if (result_faulty == 0) {
+ ind = ( (leading_one[0] + tailing_one[0])/2 + (leading_one[1] + tailing_one[1])/2 )/2;
+ WRAP_WR32(PMIC_WRAP_SI_CK_CON , (ind >> 2) & 0x7);
+ WRAP_WR32(PMIC_WRAP_SIDLY , 0x3 - (ind & 0x3));
+
+ WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN , arb_en_backup);
+ return 0;
+ } else {
+ PWRAPERR("_pwrap_init_sistrobe Fail,result_faulty=%x\n", result_faulty);
+ return result_faulty;
+ }
+}
+
+static int _pwrap_reset_spislv(void)
+{
+ uint32_t ret = 0, return_value;
+
+ WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, DISABLE_ALL);
+ WRAP_WR32(PMIC_WRAP_WRAP_EN, DISABLE);
+ WRAP_WR32(PMIC_WRAP_MUX_SEL, MANUAL_MODE);
+ WRAP_WR32(PMIC_WRAP_MAN_EN, ENABLE);
+ WRAP_WR32(PMIC_WRAP_DIO_EN, DISABLE);
+
+ WRAP_WR32(PMIC_WRAP_MAN_CMD , (OP_WR << 13) | (OP_CSL << 8));
+ WRAP_WR32(PMIC_WRAP_MAN_CMD , (OP_WR << 13) | (OP_OUTS << 8));
+ WRAP_WR32(PMIC_WRAP_MAN_CMD , (OP_WR << 13) | (OP_CSH << 8));
+ WRAP_WR32(PMIC_WRAP_MAN_CMD , (OP_WR << 13) | (OP_OUTS << 8));
+ WRAP_WR32(PMIC_WRAP_MAN_CMD , (OP_WR << 13) | (OP_OUTS << 8));
+ WRAP_WR32(PMIC_WRAP_MAN_CMD , (OP_WR << 13) | (OP_OUTS << 8));
+ WRAP_WR32(PMIC_WRAP_MAN_CMD , (OP_WR << 13) | (OP_OUTS << 8));
+
+ return_value = wait_for_state_ready_init(wait_for_sync, TIMEOUT_WAIT_IDLE, PMIC_WRAP_WACS2_RDATA, 0);
+ if (return_value) {
+ PWRAPERR("_pwrap_reset_spislv fail,return_value=%x\n", return_value);
+ ret = E_PWR_TIMEOUT;
+ }
+
+ WRAP_WR32(PMIC_WRAP_MAN_EN, DISABLE);
+ WRAP_WR32(PMIC_WRAP_MUX_SEL, WRAPPER_MODE);
+
+ return ret;
+}
+
+static void __pwrap_soft_reset(void)
+{
+ PWRAPLOG("start reset wrapper\n");
+ WRAP_WR32(INFRA_GLOBALCON_RST0,0x80);
+
+ PWRAPLOG("the reset register =%x\n", WRAP_RD32(INFRA_GLOBALCON_RST0));
+ PWRAPLOG("PMIC_WRAP_STAUPD_GRPEN =0x%x,it should be equal to 0xc\n", WRAP_RD32(PMIC_WRAP_STAUPD_GRPEN));
+ WRAP_WR32(INFRA_GLOBALCON_RST1,0x80);
+ return;
+}
+
+static int _pwrap_init_signature(uint8_t path)
+{
+ int ret;
+ uint32_t rdata;
+
+ PWRAPFUC();
+ if (path == 1) {
+ _pwrap_wacs2_nochk(1, MT6328_DEW_WRITE_TEST, 0x5678, &rdata);
+ WRAP_WR32(PMIC_WRAP_SIG_ADR,MT6328_DEW_WRITE_TEST);
+ WRAP_WR32(PMIC_WRAP_SIG_VALUE,0x5678);
+ WRAP_WR32(PMIC_WRAP_SIG_MODE, 0x1);
+ } else {
+ ret = pwrap_write_nochk(MT6328_DEW_CRC_EN, ENABLE);
+ if (ret) {
+ PWRAPERR("MT6328 enable CRC fail,ret=%x\n", ret);
+ return E_PWR_INIT_ENABLE_CRC;
+ }
+ WRAP_WR32(PMIC_WRAP_SIG_ADR,WRAP_RD32(PMIC_WRAP_SIG_ADR)|MT6328_DEW_CRC_VAL);
+ WRAP_WR32(PMIC_WRAP_STAUPD_GRPEN,WRAP_RD32(PMIC_WRAP_STAUPD_GRPEN)|0x35);
+ }
+
+ return 0;
+}
+
+static int _pwrap_init_reg_clock(uint32_t regck_sel)
+{
+ PWRAPFUC();
+ pwrap_write_nochk(MT6328_DEW_RDDMY_NO, 0x8);
+ WRAP_WR32(PMIC_WRAP_RDDMY, 0x88);
+
+ if ( regck_sel == 1 ) {
+ WRAP_WR32(PMIC_WRAP_CSHEXT_READ, 0x0);
+ WRAP_WR32(PMIC_WRAP_CSHEXT_WRITE, 0x33);
+ WRAP_WR32(PMIC_WRAP_CSLEXT_START, 0x0);
+ WRAP_WR32(PMIC_WRAP_CSLEXT_END, 0x0);
+ } else {
+ WRAP_WR32(PMIC_WRAP_CSHEXT_WRITE, 0xff);
+ WRAP_WR32(PMIC_WRAP_CSHEXT_READ, 0xff);
+ WRAP_WR32(PMIC_WRAP_CSLEXT_START, 0xf);
+ WRAP_WR32(PMIC_WRAP_CSLEXT_END, 0xf);
+ }
+
+ return 0;
+}
+
+static int pwrap_init(void)
+{
+ int sub_return=0;
+ int sub_return1=0;
+ uint32_t rdata=0x0;
+
+ PWRAPFUC();
+ __pwrap_soft_reset();
+ WRAP_WR32(CLK_CFG_4_CLR, CLK_SPI_CK_26M);
+
+ WRAP_WR32(PMIC_WRAP_DCM_EN, 3);
+ WRAP_WR32(PMIC_WRAP_DCM_DBC_PRD, DISABLE);
+
+ sub_return =_pwrap_reset_spislv();
+ if (sub_return) {
+ PWRAPERR("error,_pwrap_reset_spislv fail,sub_return=%x\n", sub_return);
+ return E_PWR_INIT_RESET_SPI;
+ }
+
+ WRAP_WR32(PMIC_WRAP_WRAP_EN, ENABLE);
+ WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, WACS2);
+ WRAP_WR32(PMIC_WRAP_WACS2_EN, ENABLE);
+
+ sub_return = _pwrap_init_sistrobe();
+ if (sub_return) {
+ PWRAPERR("error,DrvPWRAP_InitSiStrobe fail,sub_return=%x\n", sub_return);
+ return E_PWR_INIT_SIDLY;
+ }
+
+ sub_return = _pwrap_init_reg_clock(1);
+ if (sub_return) {
+ PWRAPERR("error,_pwrap_init_reg_clock fail,sub_return=%x\n", sub_return);
+ return E_PWR_INIT_REG_CLOCK;
+ }
+
+ sub_return = _pwrap_init_dio(1);
+ if (sub_return) {
+ PWRAPERR("_pwrap_init_dio test error,error code=%x, sub_return=%x\n", 0x11, sub_return);
+ return E_PWR_INIT_DIO;
+ }
+
+ PWRAPLOG("have cipher\n");
+ sub_return = _pwrap_init_cipher();
+ if (sub_return) {
+ PWRAPERR("Enable Encryption fail, return=%x\n", sub_return);
+ return E_PWR_INIT_CIPHER;
+ }
+
+ sub_return = pwrap_write_nochk(MT6328_DEW_WRITE_TEST, MT6328_WRITE_TEST_VALUE);
+ sub_return1 = pwrap_read_nochk(MT6328_DEW_WRITE_TEST, &rdata);
+ if (rdata != MT6328_WRITE_TEST_VALUE) {
+ PWRAPERR("write test error,rdata=0x%x,exp=0xa55a,sub_return=0x%x,sub_return1=0x%x\n", rdata, sub_return, sub_return1);
+ return E_PWR_INIT_WRITE_TEST;
+ }
+
+ sub_return = _pwrap_init_signature(0);
+ if (sub_return) {
+ PWRAPERR("Enable CRC fail, return=%x\n", sub_return);
+ return E_PWR_INIT_ENABLE_CRC;
+ }
+ PWRAPLOG("mt_pwrap_init PMIC_WRAP_STAUPD_GRPEN(%x)\n", WRAP_RD32(PMIC_WRAP_STAUPD_GRPEN));
+
+ WRAP_WR32(PMIC_WRAP_ADC_CMD_ADDR, MT6328_LDO_RSV_CON1);
+ WRAP_WR32(PMIC_WRAP_PWRAP_ADC_CMD, 0x0100);
+ WRAP_WR32(PMIC_WRAP_ADC_RDATA_ADDR, MT6328_AUXADC_ADC32);
+ PWRAPERR("PMIC_WRAP_ADC_RDATA_ADDR=%x\r\n", WRAP_RD32(PMIC_WRAP_ADC_RDATA_ADDR));
+
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR_LATEST , MT6328_AUXADC_ADC32);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR_WP , MT6328_AUXADC_MDBG_1);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR0 , MT6328_AUXADC_BUF0);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR1 , MT6328_AUXADC_BUF1);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR2 , MT6328_AUXADC_BUF2);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR3 , MT6328_AUXADC_BUF3);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR4 , MT6328_AUXADC_BUF4);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR5 , MT6328_AUXADC_BUF5);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR6 , MT6328_AUXADC_BUF6);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR7 , MT6328_AUXADC_BUF7);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR8 , MT6328_AUXADC_BUF8);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR9 , MT6328_AUXADC_BUF9);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR10 , MT6328_AUXADC_BUF10);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR11 , MT6328_AUXADC_BUF11);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR12 , MT6328_AUXADC_BUF12);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR13 , MT6328_AUXADC_BUF13);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR14 , MT6328_AUXADC_BUF14);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR15 , MT6328_AUXADC_BUF15);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR16 , MT6328_AUXADC_BUF16);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR17 , MT6328_AUXADC_BUF17);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR18 , MT6328_AUXADC_BUF18);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR19 , MT6328_AUXADC_BUF19);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR20 , MT6328_AUXADC_BUF20);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR21 , MT6328_AUXADC_BUF21);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR22 , MT6328_AUXADC_BUF22);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR23 , MT6328_AUXADC_BUF23);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR24 , MT6328_AUXADC_BUF24);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR25 , MT6328_AUXADC_BUF25);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR26 , MT6328_AUXADC_BUF26);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR27 , MT6328_AUXADC_BUF27);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR28 , MT6328_AUXADC_BUF28);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR29 , MT6328_AUXADC_BUF29);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR30 , MT6328_AUXADC_BUF30);
+ WRAP_WR32(PMIC_WRAP_MD_ADC_RDATA_ADDR31 , MT6328_AUXADC_BUF31);
+
+ WRAP_WR32(PMIC_WRAP_HIPRIO_ARB_EN, 0x3ff);
+ PWRAPLOG("mt_pwrap_init-- use D1 or D3 \n");
+ WRAP_WR32(PMIC_WRAP_WACS0_EN, ENABLE);
+ WRAP_WR32(PMIC_WRAP_WACS1_EN, ENABLE);
+ WRAP_WR32(PMIC_WRAP_WACS3_EN, ENABLE);
+
+ WRAP_WR32(PMIC_WRAP_STAUPD_PRD, 0x5);
+ WRAP_WR32(PMIC_WRAP_WDT_UNIT, 0xf);
+ WRAP_WR32(PMIC_WRAP_WDT_SRC_EN, 0xfffffbff);
+ WRAP_WR32(PMIC_WRAP_TIMER_EN, 0x1);
+ WRAP_WR32(PMIC_WRAP_INT_EN, 0xfffffbf9);
+
+ WRAP_WR32(PMIC_WRAP_INIT_DONE0, ENABLE);
+ WRAP_WR32(PMIC_WRAP_INIT_DONE2, ENABLE);
+ WRAP_WR32(PMIC_WRAP_INIT_DONE3, ENABLE);
+ WRAP_WR32(PMIC_WRAP_EINT_STA0_ADR, MT6328_INT_STA);
+
+ PWRAPLOG("mt_pwrap_init---- debug15,%x\n", WRAP_RD32(PMIC_WRAP_INT_EN));
+ return 0;
+}
+
+int pwrap_init_preloader(void)
+{
+ int pwrap_ret, i;
+
+ PWRAPFUC();
+ for (i = 0; i < 3; i++) {
+ pwrap_ret = pwrap_init();
+ if (pwrap_ret)
+ PWRAPLOG("wrap_init fail,the return value=%x.\n",pwrap_ret);
+ else {
+ PWRAPLOG("wrap_init pass,the return value=%x.\n",pwrap_ret);
+ break;
+ }
+ }
+
+ return pwrap_ret;
+}
diff --git a/src/bsp/lk/platform/mt2635/drivers/rules.mk b/src/bsp/lk/platform/mt2635/drivers/rules.mk
new file mode 100644
index 0000000..b3feeaf
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/drivers/rules.mk
@@ -0,0 +1,29 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+MODULE := $(LOCAL_DIR)
+
+
+MODULE_SRCS += \
+ $(LOCAL_DIR)/uart/uart.c \
+ $(LOCAL_DIR)/spm/spm_mtcmos.c \
+ $(LOCAL_DIR)/pll/pll.c \
+ $(LOCAL_DIR)/pll/mempll.c \
+ $(LOCAL_DIR)/mmc/msdc.c \
+ $(LOCAL_DIR)/mmc/mmc_rpmb.c \
+ $(LOCAL_DIR)/mmc/mmc_core.c \
+ $(LOCAL_DIR)/usb/mt_usb.c \
+ $(LOCAL_DIR)/key/mtk_key.c \
+ $(LOCAL_DIR)/wdt/mtk_wdt.c \
+ $(LOCAL_DIR)/pmic/pmic.c \
+ $(LOCAL_DIR)/pmic/pmic_wrap_init.c \
+ $(LOCAL_DIR)/efuse/vefuse.c \
+
+MODULE_DEPS += \
+ lib/bio \
+ lib/partition \
+ lib/fdt \
+ lib/cksum \
+ $(LOCAL_DIR)/../../../../dramk_2635/dram \
+
+MODULE_EXTRA_OBJS += $(LOCAL_DIR)/../../../../lk_ext_mod/platform/mt2635/drivers/efuse/libefuse.o
+
+include make/module.mk
diff --git a/src/bsp/lk/platform/mt2635/drivers/spm/spm_mtcmos.c b/src/bsp/lk/platform/mt2635/drivers/spm/spm_mtcmos.c
new file mode 100644
index 0000000..e1554cd
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/drivers/spm/spm_mtcmos.c
@@ -0,0 +1,1491 @@
+#include <reg.h>
+#include <platform/mt2635.h>
+#include <platform/spm.h>
+#include <platform/spm_mtcmos.h>
+#include <platform/spm_mtcmos_internal.h>
+#include <platform/pll.h>
+
+#define USE_SPIN 0
+
+#define spm_mtcmos_cpu_lock(x) (*x = 0)
+#define spm_mtcmos_cpu_unlock(x) (*x = 0)
+#define spm_mtcmos_noncpu_lock(x) (*(&x) = 0)
+#define spm_mtcmos_noncpu_unlock(x) (*(&x) = 0)
+
+#if USE_SPIN
+
+#define udelay(x) spin(x)
+#define mdelay(x) udelay((x) * 1000)
+
+#else /* !USE_SPIN */
+
+#define my_delay(count) \
+ do { \
+ volatile unsigned int i = count * 26; \
+ for (; i != 0; i--); \
+ } while (0)
+
+#define udelay(x) my_delay(x)
+#define mdelay(x) udelay((x) * 1000)
+
+#endif /* USE_SPIN */
+
+typedef int (*spm_cpu_mtcmos_ctrl_func) (int state, int chkWfiBeforePdn);
+
+static void wait_reg_bits(addr_t reg, u32 mask, u32 value)
+{
+#ifndef CFG_FPGA_PLATFORM
+ while ((spm_read(reg) & mask) != value) ;
+#endif
+}
+
+static void wait_2reg_bits(addr_t reg1, addr_t reg2, u32 mask, u32 value)
+{
+#ifndef CFG_FPGA_PLATFORM
+ while ((spm_read(reg1) & mask) != value ||
+ (spm_read(reg2) & mask) != value) ;
+#endif
+}
+
+static void wait_pwr_status(u32 mask, u32 value)
+{
+ wait_2reg_bits(SPM_PWR_STATUS, SPM_PWR_STATUS_2ND, mask, value);
+}
+
+static spm_cpu_mtcmos_ctrl_func spm_cpu_mtcmos_ctrl_funcs[] = {
+
+ spm_mtcmos_ctrl_cpu0,
+ spm_mtcmos_ctrl_cpu1,
+ spm_mtcmos_ctrl_cpu2,
+ spm_mtcmos_ctrl_cpu3,
+ spm_mtcmos_ctrl_cpu4,
+ spm_mtcmos_ctrl_cpu5,
+ spm_mtcmos_ctrl_cpu6,
+ spm_mtcmos_ctrl_cpu7
+};
+
+int spm_mtcmos_ctrl_cpu(unsigned int cpu, int state, int chkWfiBeforePdn)
+{
+ return (*spm_cpu_mtcmos_ctrl_funcs[cpu]) (state, chkWfiBeforePdn);
+}
+
+int spm_mtcmos_ctrl_cpu0(int state, int chkWfiBeforePdn)
+{
+ unsigned long flags;
+
+ /* enable register control */
+ spm_write(SPM_POWERON_CONFIG_SET, (SPM_PROJECT_CODE << 16) | (1U << 0));
+
+ if (state == STA_POWER_DOWN) {
+ if (chkWfiBeforePdn)
+ while ((spm_read(SPM_SLEEP_TIMER_STA) &
+ CA7_CPU0_STANDBYWFI) == 0) ;
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA7_CPU0_PWR_CON,
+ spm_read(SPM_CA7_CPU0_PWR_CON) | PWR_ISO);
+
+ spm_write(SPM_CA7_CPU0_PWR_CON,
+ spm_read(SPM_CA7_CPU0_PWR_CON) | SRAM_CKISO);
+ spm_write(SPM_CA7_CPU0_PWR_CON,
+ spm_read(SPM_CA7_CPU0_PWR_CON) & ~SRAM_ISOINT_B);
+ spm_write(SPM_CA7_CPU0_L1_PDN,
+ spm_read(SPM_CA7_CPU0_L1_PDN) | L1_PDN);
+
+ wait_reg_bits(SPM_CA7_CPU0_L1_PDN, L1_PDN_ACK, L1_PDN_ACK);
+
+ spm_write(SPM_CA7_CPU0_PWR_CON,
+ spm_read(SPM_CA7_CPU0_PWR_CON) & ~PWR_RST_B);
+ spm_write(SPM_CA7_CPU0_PWR_CON,
+ spm_read(SPM_CA7_CPU0_PWR_CON) | PWR_CLK_DIS);
+
+ spm_write(SPM_CA7_CPU0_PWR_CON,
+ spm_read(SPM_CA7_CPU0_PWR_CON) & ~PWR_ON);
+ spm_write(SPM_CA7_CPU0_PWR_CON,
+ spm_read(SPM_CA7_CPU0_PWR_CON) & ~PWR_ON_2ND);
+
+ wait_pwr_status(CA7_CPU0, 0);
+
+ spm_mtcmos_cpu_unlock(&flags);
+ } else { /* STA_POWER_ON */
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA7_CPU0_PWR_CON,
+ spm_read(SPM_CA7_CPU0_PWR_CON) | PWR_ON);
+ udelay(1);
+ spm_write(SPM_CA7_CPU0_PWR_CON,
+ spm_read(SPM_CA7_CPU0_PWR_CON) | PWR_ON_2ND);
+
+ wait_pwr_status(CA7_CPU0, CA7_CPU0);
+
+ spm_write(SPM_CA7_CPU0_PWR_CON,
+ spm_read(SPM_CA7_CPU0_PWR_CON) & ~PWR_ISO);
+
+ spm_write(SPM_CA7_CPU0_L1_PDN,
+ spm_read(SPM_CA7_CPU0_L1_PDN) & ~L1_PDN);
+
+ wait_reg_bits(SPM_CA7_CPU0_L1_PDN, L1_PDN_ACK, 0);
+
+ udelay(1);
+ spm_write(SPM_CA7_CPU0_PWR_CON,
+ spm_read(SPM_CA7_CPU0_PWR_CON) | SRAM_ISOINT_B);
+ spm_write(SPM_CA7_CPU0_PWR_CON,
+ spm_read(SPM_CA7_CPU0_PWR_CON) & ~SRAM_CKISO);
+
+ spm_write(SPM_CA7_CPU0_PWR_CON,
+ spm_read(SPM_CA7_CPU0_PWR_CON) & ~PWR_CLK_DIS);
+ spm_write(SPM_CA7_CPU0_PWR_CON,
+ spm_read(SPM_CA7_CPU0_PWR_CON) | PWR_RST_B);
+
+ spm_mtcmos_cpu_unlock(&flags);
+ }
+
+ return 0;
+}
+
+int spm_mtcmos_ctrl_cpu1(int state, int chkWfiBeforePdn)
+{
+ unsigned long flags;
+
+ /* enable register control */
+ spm_write(SPM_POWERON_CONFIG_SET, (SPM_PROJECT_CODE << 16) | (1U << 0));
+
+ if (state == STA_POWER_DOWN) {
+ if (chkWfiBeforePdn)
+ while ((spm_read(SPM_SLEEP_TIMER_STA) &
+ CA7_CPU1_STANDBYWFI) == 0) ;
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA7_CPU1_PWR_CON,
+ spm_read(SPM_CA7_CPU1_PWR_CON) | PWR_ISO);
+
+ spm_write(SPM_CA7_CPU1_PWR_CON,
+ spm_read(SPM_CA7_CPU1_PWR_CON) | SRAM_CKISO);
+ spm_write(SPM_CA7_CPU1_PWR_CON,
+ spm_read(SPM_CA7_CPU1_PWR_CON) & ~SRAM_ISOINT_B);
+ spm_write(SPM_CA7_CPU1_L1_PDN,
+ spm_read(SPM_CA7_CPU1_L1_PDN) | L1_PDN);
+
+ wait_reg_bits(SPM_CA7_CPU1_L1_PDN, L1_PDN_ACK, L1_PDN_ACK);
+
+ spm_write(SPM_CA7_CPU1_PWR_CON,
+ spm_read(SPM_CA7_CPU1_PWR_CON) & ~PWR_RST_B);
+ spm_write(SPM_CA7_CPU1_PWR_CON,
+ spm_read(SPM_CA7_CPU1_PWR_CON) | PWR_CLK_DIS);
+
+ spm_write(SPM_CA7_CPU1_PWR_CON,
+ spm_read(SPM_CA7_CPU1_PWR_CON) & ~PWR_ON);
+ spm_write(SPM_CA7_CPU1_PWR_CON,
+ spm_read(SPM_CA7_CPU1_PWR_CON) & ~PWR_ON_2ND);
+
+ wait_pwr_status(CA7_CPU1, 0);
+
+ spm_mtcmos_cpu_unlock(&flags);
+ } else { /* STA_POWER_ON */
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA7_CPU1_PWR_CON,
+ spm_read(SPM_CA7_CPU1_PWR_CON) | PWR_ON);
+ udelay(1);
+ spm_write(SPM_CA7_CPU1_PWR_CON,
+ spm_read(SPM_CA7_CPU1_PWR_CON) | PWR_ON_2ND);
+
+ wait_pwr_status(CA7_CPU1, CA7_CPU1);
+
+ spm_write(SPM_CA7_CPU1_PWR_CON,
+ spm_read(SPM_CA7_CPU1_PWR_CON) & ~PWR_ISO);
+
+ spm_write(SPM_CA7_CPU1_L1_PDN,
+ spm_read(SPM_CA7_CPU1_L1_PDN) & ~L1_PDN);
+
+ wait_reg_bits(SPM_CA7_CPU1_L1_PDN, L1_PDN_ACK, 0);
+
+ udelay(1);
+ spm_write(SPM_CA7_CPU1_PWR_CON,
+ spm_read(SPM_CA7_CPU1_PWR_CON) | SRAM_ISOINT_B);
+ spm_write(SPM_CA7_CPU1_PWR_CON,
+ spm_read(SPM_CA7_CPU1_PWR_CON) & ~SRAM_CKISO);
+
+ spm_write(SPM_CA7_CPU1_PWR_CON,
+ spm_read(SPM_CA7_CPU1_PWR_CON) & ~PWR_CLK_DIS);
+ spm_write(SPM_CA7_CPU1_PWR_CON,
+ spm_read(SPM_CA7_CPU1_PWR_CON) | PWR_RST_B);
+
+ spm_mtcmos_cpu_unlock(&flags);
+ }
+
+ return 0;
+}
+
+int spm_mtcmos_ctrl_cpu2(int state, int chkWfiBeforePdn)
+{
+ unsigned long flags;
+
+ /* enable register control */
+ spm_write(SPM_POWERON_CONFIG_SET, (SPM_PROJECT_CODE << 16) | (1U << 0));
+
+ if (state == STA_POWER_DOWN) {
+ if (chkWfiBeforePdn)
+ while ((spm_read(SPM_SLEEP_TIMER_STA) &
+ CA7_CPU2_STANDBYWFI) == 0) ;
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA7_CPU2_PWR_CON,
+ spm_read(SPM_CA7_CPU2_PWR_CON) | PWR_ISO);
+
+ spm_write(SPM_CA7_CPU2_PWR_CON,
+ spm_read(SPM_CA7_CPU2_PWR_CON) | SRAM_CKISO);
+ spm_write(SPM_CA7_CPU2_PWR_CON,
+ spm_read(SPM_CA7_CPU2_PWR_CON) & ~SRAM_ISOINT_B);
+ spm_write(SPM_CA7_CPU2_L1_PDN,
+ spm_read(SPM_CA7_CPU2_L1_PDN) | L1_PDN);
+
+ wait_reg_bits(SPM_CA7_CPU2_L1_PDN, L1_PDN_ACK, L1_PDN_ACK);
+
+ spm_write(SPM_CA7_CPU2_PWR_CON,
+ spm_read(SPM_CA7_CPU2_PWR_CON) & ~PWR_RST_B);
+ spm_write(SPM_CA7_CPU2_PWR_CON,
+ spm_read(SPM_CA7_CPU2_PWR_CON) | PWR_CLK_DIS);
+
+ spm_write(SPM_CA7_CPU2_PWR_CON,
+ spm_read(SPM_CA7_CPU2_PWR_CON) & ~PWR_ON);
+ spm_write(SPM_CA7_CPU2_PWR_CON,
+ spm_read(SPM_CA7_CPU2_PWR_CON) & ~PWR_ON_2ND);
+
+ wait_pwr_status(CA7_CPU2, 0);
+
+ spm_mtcmos_cpu_unlock(&flags);
+ } else { /* STA_POWER_ON */
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA7_CPU2_PWR_CON,
+ spm_read(SPM_CA7_CPU2_PWR_CON) | PWR_ON);
+ udelay(1);
+ spm_write(SPM_CA7_CPU2_PWR_CON,
+ spm_read(SPM_CA7_CPU2_PWR_CON) | PWR_ON_2ND);
+
+ wait_pwr_status(CA7_CPU2, CA7_CPU2);
+
+ spm_write(SPM_CA7_CPU2_PWR_CON,
+ spm_read(SPM_CA7_CPU2_PWR_CON) & ~PWR_ISO);
+
+ spm_write(SPM_CA7_CPU2_L1_PDN,
+ spm_read(SPM_CA7_CPU2_L1_PDN) & ~L1_PDN);
+
+ wait_reg_bits(SPM_CA7_CPU2_L1_PDN, L1_PDN_ACK, 0);
+
+ udelay(1);
+ spm_write(SPM_CA7_CPU2_PWR_CON,
+ spm_read(SPM_CA7_CPU2_PWR_CON) | SRAM_ISOINT_B);
+ spm_write(SPM_CA7_CPU2_PWR_CON,
+ spm_read(SPM_CA7_CPU2_PWR_CON) & ~SRAM_CKISO);
+
+ spm_write(SPM_CA7_CPU2_PWR_CON,
+ spm_read(SPM_CA7_CPU2_PWR_CON) & ~PWR_CLK_DIS);
+ spm_write(SPM_CA7_CPU2_PWR_CON,
+ spm_read(SPM_CA7_CPU2_PWR_CON) | PWR_RST_B);
+
+ spm_mtcmos_cpu_unlock(&flags);
+ }
+
+ return 0;
+}
+
+int spm_mtcmos_ctrl_cpu3(int state, int chkWfiBeforePdn)
+{
+ unsigned long flags;
+
+ /* enable register control */
+ spm_write(SPM_POWERON_CONFIG_SET, (SPM_PROJECT_CODE << 16) | (1U << 0));
+
+ if (state == STA_POWER_DOWN) {
+ if (chkWfiBeforePdn)
+ while ((spm_read(SPM_SLEEP_TIMER_STA) &
+ CA7_CPU3_STANDBYWFI) == 0) ;
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA7_CPU3_PWR_CON,
+ spm_read(SPM_CA7_CPU3_PWR_CON) | PWR_ISO);
+
+ spm_write(SPM_CA7_CPU3_PWR_CON,
+ spm_read(SPM_CA7_CPU3_PWR_CON) | SRAM_CKISO);
+ spm_write(SPM_CA7_CPU3_PWR_CON,
+ spm_read(SPM_CA7_CPU3_PWR_CON) & ~SRAM_ISOINT_B);
+ spm_write(SPM_CA7_CPU3_L1_PDN,
+ spm_read(SPM_CA7_CPU3_L1_PDN) | L1_PDN);
+
+ wait_reg_bits(SPM_CA7_CPU3_L1_PDN, L1_PDN_ACK, L1_PDN_ACK);
+
+ spm_write(SPM_CA7_CPU3_PWR_CON,
+ spm_read(SPM_CA7_CPU3_PWR_CON) & ~PWR_RST_B);
+ spm_write(SPM_CA7_CPU3_PWR_CON,
+ spm_read(SPM_CA7_CPU3_PWR_CON) | PWR_CLK_DIS);
+
+ spm_write(SPM_CA7_CPU3_PWR_CON,
+ spm_read(SPM_CA7_CPU3_PWR_CON) & ~PWR_ON);
+ spm_write(SPM_CA7_CPU3_PWR_CON,
+ spm_read(SPM_CA7_CPU3_PWR_CON) & ~PWR_ON_2ND);
+
+ wait_pwr_status(CA7_CPU3, 0);
+
+ spm_mtcmos_cpu_unlock(&flags);
+ } else { /* STA_POWER_ON */
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA7_CPU3_PWR_CON,
+ spm_read(SPM_CA7_CPU3_PWR_CON) | PWR_ON);
+ udelay(1);
+ spm_write(SPM_CA7_CPU3_PWR_CON,
+ spm_read(SPM_CA7_CPU3_PWR_CON) | PWR_ON_2ND);
+
+ wait_pwr_status(CA7_CPU3, CA7_CPU3);
+
+ spm_write(SPM_CA7_CPU3_PWR_CON,
+ spm_read(SPM_CA7_CPU3_PWR_CON) & ~PWR_ISO);
+
+ spm_write(SPM_CA7_CPU3_L1_PDN,
+ spm_read(SPM_CA7_CPU3_L1_PDN) & ~L1_PDN);
+
+ wait_reg_bits(SPM_CA7_CPU3_L1_PDN, L1_PDN_ACK, 0);
+
+ udelay(1);
+ spm_write(SPM_CA7_CPU3_PWR_CON,
+ spm_read(SPM_CA7_CPU3_PWR_CON) | SRAM_ISOINT_B);
+ spm_write(SPM_CA7_CPU3_PWR_CON,
+ spm_read(SPM_CA7_CPU3_PWR_CON) & ~SRAM_CKISO);
+
+ spm_write(SPM_CA7_CPU3_PWR_CON,
+ spm_read(SPM_CA7_CPU3_PWR_CON) & ~PWR_CLK_DIS);
+ spm_write(SPM_CA7_CPU3_PWR_CON,
+ spm_read(SPM_CA7_CPU3_PWR_CON) | PWR_RST_B);
+
+ spm_mtcmos_cpu_unlock(&flags);
+ }
+
+ return 0;
+}
+
+int spm_mtcmos_ctrl_cpu4(int state, int chkWfiBeforePdn)
+{
+ unsigned long flags;
+
+ /* enable register control */
+ spm_write(SPM_POWERON_CONFIG_SET, (SPM_PROJECT_CODE << 16) | (1U << 0));
+
+ if (state == STA_POWER_DOWN) {
+ if (chkWfiBeforePdn)
+ mdelay(500);
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA15_CPU0_PWR_CON,
+ spm_read(SPM_CA15_CPU0_PWR_CON) | PWR_ISO);
+
+ spm_write(SPM_CA15_CPU0_PWR_CON,
+ spm_read(SPM_CA15_CPU0_PWR_CON) | SRAM_CKISO);
+ spm_write(SPM_CA15_CPU0_PWR_CON,
+ spm_read(SPM_CA15_CPU0_PWR_CON) & ~SRAM_ISOINT_B);
+ spm_write(SPM_CA15_L1_PWR_CON,
+ spm_read(SPM_CA15_L1_PWR_CON) | CPU0_CA15_L1_PDN);
+
+ wait_reg_bits(SPM_CA15_L1_PWR_CON, CPU0_CA15_L1_PDN_ACK, CPU0_CA15_L1_PDN_ACK);
+
+ spm_write(SPM_CA15_L1_PWR_CON,
+ spm_read(SPM_CA15_L1_PWR_CON) | CPU0_CA15_L1_PDN_ISO);
+
+ spm_write(SPM_CA15_CPU0_PWR_CON,
+ spm_read(SPM_CA15_CPU0_PWR_CON) & ~PWR_RST_B);
+ spm_write(SPM_CA15_CPU0_PWR_CON,
+ spm_read(SPM_CA15_CPU0_PWR_CON) | PWR_CLK_DIS);
+
+ spm_write(SPM_CA15_CPU0_PWR_CON,
+ spm_read(SPM_CA15_CPU0_PWR_CON) & ~PWR_ON);
+ spm_write(SPM_CA15_CPU0_PWR_CON,
+ spm_read(SPM_CA15_CPU0_PWR_CON) & ~PWR_ON_2ND);
+
+ wait_pwr_status(CA15_CPU0, 0);
+
+ spm_mtcmos_cpu_unlock(&flags);
+
+ if (!
+ (spm_read(SPM_PWR_STATUS) &
+ (CA15_CPU1 | CA15_CPU2 | CA15_CPU3))
+ && !(spm_read(SPM_PWR_STATUS_2ND) &
+ (CA15_CPU1 | CA15_CPU2 | CA15_CPU3)))
+ spm_mtcmos_ctrl_cpusys1(state, chkWfiBeforePdn);
+ } else { /* STA_POWER_ON */
+
+ if (!(spm_read(SPM_PWR_STATUS) & CA15_CPUTOP) &&
+ !(spm_read(SPM_PWR_STATUS_2ND) & CA15_CPUTOP))
+ spm_mtcmos_ctrl_cpusys1(state, chkWfiBeforePdn);
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA15_CPU0_PWR_CON,
+ spm_read(SPM_CA15_CPU0_PWR_CON) | PWR_ON);
+ udelay(1);
+ spm_write(SPM_CA15_CPU0_PWR_CON,
+ spm_read(SPM_CA15_CPU0_PWR_CON) | PWR_ON_2ND);
+
+ wait_pwr_status(CA15_CPU0, CA15_CPU0);
+
+ spm_write(SPM_CA15_CPU0_PWR_CON,
+ spm_read(SPM_CA15_CPU0_PWR_CON) & ~PWR_ISO);
+
+ spm_write(SPM_CA15_L1_PWR_CON,
+ spm_read(SPM_CA15_L1_PWR_CON) &
+ ~CPU0_CA15_L1_PDN_ISO);
+ spm_write(SPM_CA15_L1_PWR_CON,
+ spm_read(SPM_CA15_L1_PWR_CON) & ~CPU0_CA15_L1_PDN);
+
+ wait_reg_bits(SPM_CA15_L1_PWR_CON, CPU0_CA15_L1_PDN_ACK, 0);
+
+ udelay(1);
+ spm_write(SPM_CA15_CPU0_PWR_CON,
+ spm_read(SPM_CA15_CPU0_PWR_CON) | SRAM_ISOINT_B);
+ spm_write(SPM_CA15_CPU0_PWR_CON,
+ spm_read(SPM_CA15_CPU0_PWR_CON) & ~SRAM_CKISO);
+
+ spm_write(SPM_CA15_CPU0_PWR_CON,
+ spm_read(SPM_CA15_CPU0_PWR_CON) & ~PWR_CLK_DIS);
+ spm_write(SPM_CA15_CPU0_PWR_CON,
+ spm_read(SPM_CA15_CPU0_PWR_CON) | PWR_RST_B);
+
+ spm_mtcmos_cpu_unlock(&flags);
+ }
+
+ return 0;
+}
+
+int spm_mtcmos_ctrl_cpu5(int state, int chkWfiBeforePdn)
+{
+ unsigned long flags;
+
+ /* enable register control */
+ spm_write(SPM_POWERON_CONFIG_SET, (SPM_PROJECT_CODE << 16) | (1U << 0));
+
+ if (state == STA_POWER_DOWN) {
+ if (chkWfiBeforePdn)
+ while ((spm_read(SPM_SLEEP_TIMER_STA) &
+ CA15_CPU1_STANDBYWFI) == 0) ;
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA15_CPU1_PWR_CON,
+ spm_read(SPM_CA15_CPU1_PWR_CON) | PWR_ISO);
+
+ spm_write(SPM_CA15_CPU1_PWR_CON,
+ spm_read(SPM_CA15_CPU1_PWR_CON) | SRAM_CKISO);
+ spm_write(SPM_CA15_CPU1_PWR_CON,
+ spm_read(SPM_CA15_CPU1_PWR_CON) & ~SRAM_ISOINT_B);
+ spm_write(SPM_CA15_L1_PWR_CON,
+ spm_read(SPM_CA15_L1_PWR_CON) | CPU1_CA15_L1_PDN);
+
+ wait_reg_bits(SPM_CA15_L1_PWR_CON, CPU1_CA15_L1_PDN_ACK, CPU1_CA15_L1_PDN_ACK);
+
+ spm_write(SPM_CA15_L1_PWR_CON,
+ spm_read(SPM_CA15_L1_PWR_CON) | CPU1_CA15_L1_PDN_ISO);
+
+ spm_write(SPM_CA15_CPU1_PWR_CON,
+ spm_read(SPM_CA15_CPU1_PWR_CON) & ~PWR_RST_B);
+ spm_write(SPM_CA15_CPU1_PWR_CON,
+ spm_read(SPM_CA15_CPU1_PWR_CON) | PWR_CLK_DIS);
+
+ spm_write(SPM_CA15_CPU1_PWR_CON,
+ spm_read(SPM_CA15_CPU1_PWR_CON) & ~PWR_ON);
+ spm_write(SPM_CA15_CPU1_PWR_CON,
+ spm_read(SPM_CA15_CPU1_PWR_CON) & ~PWR_ON_2ND);
+
+ wait_pwr_status(CA15_CPU1, 0);
+
+ spm_mtcmos_cpu_unlock(&flags);
+
+ if (!
+ (spm_read(SPM_PWR_STATUS) &
+ (CA15_CPU1 | CA15_CPU2 | CA15_CPU3))
+ && !(spm_read(SPM_PWR_STATUS_2ND) &
+ (CA15_CPU1 | CA15_CPU2 | CA15_CPU3)))
+ spm_mtcmos_ctrl_cpusys1(state, chkWfiBeforePdn);
+ } else { /* STA_POWER_ON */
+
+ if (!(spm_read(SPM_PWR_STATUS) & CA15_CPUTOP) &&
+ !(spm_read(SPM_PWR_STATUS_2ND) & CA15_CPUTOP))
+ spm_mtcmos_ctrl_cpusys1(state, chkWfiBeforePdn);
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA15_CPU1_PWR_CON,
+ spm_read(SPM_CA15_CPU1_PWR_CON) | PWR_ON);
+ udelay(1);
+ spm_write(SPM_CA15_CPU1_PWR_CON,
+ spm_read(SPM_CA15_CPU1_PWR_CON) | PWR_ON_2ND);
+
+ wait_pwr_status(CA15_CPU1, CA15_CPU1);
+
+ spm_write(SPM_CA15_CPU1_PWR_CON,
+ spm_read(SPM_CA15_CPU1_PWR_CON) & ~PWR_ISO);
+
+ spm_write(SPM_CA15_L1_PWR_CON,
+ spm_read(SPM_CA15_L1_PWR_CON) &
+ ~CPU1_CA15_L1_PDN_ISO);
+ spm_write(SPM_CA15_L1_PWR_CON,
+ spm_read(SPM_CA15_L1_PWR_CON) & ~CPU1_CA15_L1_PDN);
+
+ wait_reg_bits(SPM_CA15_L1_PWR_CON, CPU1_CA15_L1_PDN_ACK, 0);
+
+ udelay(1);
+ spm_write(SPM_CA15_CPU1_PWR_CON,
+ spm_read(SPM_CA15_CPU1_PWR_CON) | SRAM_ISOINT_B);
+ spm_write(SPM_CA15_CPU1_PWR_CON,
+ spm_read(SPM_CA15_CPU1_PWR_CON) & ~SRAM_CKISO);
+
+ spm_write(SPM_CA15_CPU1_PWR_CON,
+ spm_read(SPM_CA15_CPU1_PWR_CON) & ~PWR_CLK_DIS);
+ spm_write(SPM_CA15_CPU1_PWR_CON,
+ spm_read(SPM_CA15_CPU1_PWR_CON) | PWR_RST_B);
+
+ spm_mtcmos_cpu_unlock(&flags);
+ }
+
+ return 0;
+}
+
+int spm_mtcmos_ctrl_cpu6(int state, int chkWfiBeforePdn)
+{
+ unsigned long flags;
+
+ /* enable register control */
+ spm_write(SPM_POWERON_CONFIG_SET, (SPM_PROJECT_CODE << 16) | (1U << 0));
+
+ if (state == STA_POWER_DOWN) {
+ if (chkWfiBeforePdn)
+ while ((spm_read(SPM_SLEEP_TIMER_STA) &
+ CA15_CPU2_STANDBYWFI) == 0) ;
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA15_CPU2_PWR_CON,
+ spm_read(SPM_CA15_CPU2_PWR_CON) | PWR_ISO);
+
+ spm_write(SPM_CA15_CPU2_PWR_CON,
+ spm_read(SPM_CA15_CPU2_PWR_CON) | SRAM_CKISO);
+ spm_write(SPM_CA15_CPU2_PWR_CON,
+ spm_read(SPM_CA15_CPU2_PWR_CON) & ~SRAM_ISOINT_B);
+ spm_write(SPM_CA15_L1_PWR_CON,
+ spm_read(SPM_CA15_L1_PWR_CON) | CPU2_CA15_L1_PDN);
+
+ wait_reg_bits(SPM_CA15_L1_PWR_CON, CPU2_CA15_L1_PDN_ACK, CPU2_CA15_L1_PDN_ACK);
+
+ spm_write(SPM_CA15_L1_PWR_CON,
+ spm_read(SPM_CA15_L1_PWR_CON) | CPU2_CA15_L1_PDN_ISO);
+
+ spm_write(SPM_CA15_CPU2_PWR_CON,
+ spm_read(SPM_CA15_CPU2_PWR_CON) & ~PWR_RST_B);
+ spm_write(SPM_CA15_CPU2_PWR_CON,
+ spm_read(SPM_CA15_CPU2_PWR_CON) | PWR_CLK_DIS);
+
+ spm_write(SPM_CA15_CPU2_PWR_CON,
+ spm_read(SPM_CA15_CPU2_PWR_CON) & ~PWR_ON);
+ spm_write(SPM_CA15_CPU2_PWR_CON,
+ spm_read(SPM_CA15_CPU2_PWR_CON) & ~PWR_ON_2ND);
+
+ wait_pwr_status(CA15_CPU2, 0);
+
+ spm_mtcmos_cpu_unlock(&flags);
+
+ if (!
+ (spm_read(SPM_PWR_STATUS) &
+ (CA15_CPU1 | CA15_CPU2 | CA15_CPU3))
+ && !(spm_read(SPM_PWR_STATUS_2ND) &
+ (CA15_CPU1 | CA15_CPU2 | CA15_CPU3)))
+ spm_mtcmos_ctrl_cpusys1(state, chkWfiBeforePdn);
+ } else { /* STA_POWER_ON */
+
+ if (!(spm_read(SPM_PWR_STATUS) & CA15_CPUTOP) &&
+ !(spm_read(SPM_PWR_STATUS_2ND) & CA15_CPUTOP))
+ spm_mtcmos_ctrl_cpusys1(state, chkWfiBeforePdn);
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA15_CPU2_PWR_CON,
+ spm_read(SPM_CA15_CPU2_PWR_CON) | PWR_ON);
+ udelay(1);
+ spm_write(SPM_CA15_CPU2_PWR_CON,
+ spm_read(SPM_CA15_CPU2_PWR_CON) | PWR_ON_2ND);
+
+ wait_pwr_status(CA15_CPU2, CA15_CPU2);
+
+ spm_write(SPM_CA15_CPU2_PWR_CON,
+ spm_read(SPM_CA15_CPU2_PWR_CON) & ~PWR_ISO);
+
+ spm_write(SPM_CA15_L1_PWR_CON,
+ spm_read(SPM_CA15_L1_PWR_CON) &
+ ~CPU2_CA15_L1_PDN_ISO);
+ spm_write(SPM_CA15_L1_PWR_CON,
+ spm_read(SPM_CA15_L1_PWR_CON) & ~CPU2_CA15_L1_PDN);
+
+ wait_reg_bits(SPM_CA15_L1_PWR_CON, CPU2_CA15_L1_PDN_ACK, 0);
+
+ udelay(1);
+ spm_write(SPM_CA15_CPU2_PWR_CON,
+ spm_read(SPM_CA15_CPU2_PWR_CON) | SRAM_ISOINT_B);
+ spm_write(SPM_CA15_CPU2_PWR_CON,
+ spm_read(SPM_CA15_CPU2_PWR_CON) & ~SRAM_CKISO);
+
+ spm_write(SPM_CA15_CPU2_PWR_CON,
+ spm_read(SPM_CA15_CPU2_PWR_CON) & ~PWR_CLK_DIS);
+ spm_write(SPM_CA15_CPU2_PWR_CON,
+ spm_read(SPM_CA15_CPU2_PWR_CON) | PWR_RST_B);
+
+ spm_mtcmos_cpu_unlock(&flags);
+ }
+
+ return 0;
+}
+
+int spm_mtcmos_ctrl_cpu7(int state, int chkWfiBeforePdn)
+{
+ unsigned long flags;
+
+ /* enable register control */
+ spm_write(SPM_POWERON_CONFIG_SET, (SPM_PROJECT_CODE << 16) | (1U << 0));
+
+ if (state == STA_POWER_DOWN) {
+ if (chkWfiBeforePdn)
+ while ((spm_read(SPM_SLEEP_TIMER_STA) &
+ CA15_CPU3_STANDBYWFI) == 0) ;
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA15_CPU3_PWR_CON,
+ spm_read(SPM_CA15_CPU3_PWR_CON) | PWR_ISO);
+
+ spm_write(SPM_CA15_CPU3_PWR_CON,
+ spm_read(SPM_CA15_CPU3_PWR_CON) | SRAM_CKISO);
+ spm_write(SPM_CA15_CPU3_PWR_CON,
+ spm_read(SPM_CA15_CPU3_PWR_CON) & ~SRAM_ISOINT_B);
+ spm_write(SPM_CA15_L1_PWR_CON,
+ spm_read(SPM_CA15_L1_PWR_CON) | CPU3_CA15_L1_PDN);
+
+ wait_reg_bits(SPM_CA15_L1_PWR_CON, CPU3_CA15_L1_PDN_ACK, CPU3_CA15_L1_PDN_ACK);
+
+ spm_write(SPM_CA15_L1_PWR_CON,
+ spm_read(SPM_CA15_L1_PWR_CON) | CPU3_CA15_L1_PDN_ISO);
+
+ spm_write(SPM_CA15_CPU3_PWR_CON,
+ spm_read(SPM_CA15_CPU3_PWR_CON) & ~PWR_RST_B);
+ spm_write(SPM_CA15_CPU3_PWR_CON,
+ spm_read(SPM_CA15_CPU3_PWR_CON) | PWR_CLK_DIS);
+
+ spm_write(SPM_CA15_CPU3_PWR_CON,
+ spm_read(SPM_CA15_CPU3_PWR_CON) & ~PWR_ON);
+ spm_write(SPM_CA15_CPU3_PWR_CON,
+ spm_read(SPM_CA15_CPU3_PWR_CON) & ~PWR_ON_2ND);
+
+ wait_pwr_status(CA15_CPU3, 0);
+
+ spm_mtcmos_cpu_unlock(&flags);
+
+ if (!
+ (spm_read(SPM_PWR_STATUS) &
+ (CA15_CPU1 | CA15_CPU2 | CA15_CPU3))
+ && !(spm_read(SPM_PWR_STATUS_2ND) &
+ (CA15_CPU1 | CA15_CPU2 | CA15_CPU3)))
+ spm_mtcmos_ctrl_cpusys1(state, chkWfiBeforePdn);
+ } else { /* STA_POWER_ON */
+
+ if (!(spm_read(SPM_PWR_STATUS) & CA15_CPUTOP) &&
+ !(spm_read(SPM_PWR_STATUS_2ND) & CA15_CPUTOP))
+ spm_mtcmos_ctrl_cpusys1(state, chkWfiBeforePdn);
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA15_CPU3_PWR_CON,
+ spm_read(SPM_CA15_CPU3_PWR_CON) | PWR_ON);
+ udelay(1);
+ spm_write(SPM_CA15_CPU3_PWR_CON,
+ spm_read(SPM_CA15_CPU3_PWR_CON) | PWR_ON_2ND);
+
+ wait_pwr_status(CA15_CPU3, CA15_CPU3);
+
+ spm_write(SPM_CA15_CPU3_PWR_CON,
+ spm_read(SPM_CA15_CPU3_PWR_CON) & ~PWR_ISO);
+
+ spm_write(SPM_CA15_L1_PWR_CON,
+ spm_read(SPM_CA15_L1_PWR_CON) &
+ ~CPU3_CA15_L1_PDN_ISO);
+ spm_write(SPM_CA15_L1_PWR_CON,
+ spm_read(SPM_CA15_L1_PWR_CON) & ~CPU3_CA15_L1_PDN);
+
+ wait_reg_bits(SPM_CA15_L1_PWR_CON, CPU3_CA15_L1_PDN_ACK, 0);
+
+ udelay(1);
+ spm_write(SPM_CA15_CPU3_PWR_CON,
+ spm_read(SPM_CA15_CPU3_PWR_CON) | SRAM_ISOINT_B);
+ spm_write(SPM_CA15_CPU3_PWR_CON,
+ spm_read(SPM_CA15_CPU3_PWR_CON) & ~SRAM_CKISO);
+
+ spm_write(SPM_CA15_CPU3_PWR_CON,
+ spm_read(SPM_CA15_CPU3_PWR_CON) & ~PWR_CLK_DIS);
+ spm_write(SPM_CA15_CPU3_PWR_CON,
+ spm_read(SPM_CA15_CPU3_PWR_CON) | PWR_RST_B);
+
+ spm_mtcmos_cpu_unlock(&flags);
+ }
+
+ return 0;
+}
+
+int spm_mtcmos_ctrl_cpusys0(int state, int chkWfiBeforePdn)
+{
+ unsigned long flags;
+
+ /* enable register control */
+ spm_write(SPM_POWERON_CONFIG_SET, (SPM_PROJECT_CODE << 16) | (1U << 0));
+
+ if (state == STA_POWER_DOWN) {
+ if (chkWfiBeforePdn)
+ while ((spm_read(SPM_SLEEP_TIMER_STA) &
+ CA7_CPUTOP_STANDBYWFI) == 0) ;
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA7_CPUTOP_PWR_CON,
+ spm_read(SPM_CA7_CPUTOP_PWR_CON) | PWR_ISO);
+
+ spm_write(SPM_CA7_CPUTOP_PWR_CON,
+ spm_read(SPM_CA7_CPUTOP_PWR_CON) | SRAM_CKISO);
+
+ spm_write(SPM_CA7_CPUTOP_PWR_CON,
+ spm_read(SPM_CA7_CPUTOP_PWR_CON) & ~SRAM_ISOINT_B);
+ spm_write(SPM_CA7_CPUTOP_L2_PDN,
+ spm_read(SPM_CA7_CPUTOP_L2_PDN) | L2_SRAM_PDN);
+
+ wait_reg_bits(SPM_CA7_CPUTOP_L2_PDN, L2_SRAM_PDN_ACK, L2_SRAM_PDN_ACK);
+
+ udelay(2);
+
+ spm_write(SPM_CA7_CPUTOP_PWR_CON,
+ spm_read(SPM_CA7_CPUTOP_PWR_CON) & ~PWR_RST_B);
+ spm_write(SPM_CA7_CPUTOP_PWR_CON,
+ spm_read(SPM_CA7_CPUTOP_PWR_CON) | PWR_CLK_DIS);
+
+ spm_write(SPM_CA7_CPUTOP_PWR_CON,
+ spm_read(SPM_CA7_CPUTOP_PWR_CON) & ~PWR_ON);
+ spm_write(SPM_CA7_CPUTOP_PWR_CON,
+ spm_read(SPM_CA7_CPUTOP_PWR_CON) & ~PWR_ON_2ND);
+
+ wait_pwr_status(CA7_CPUTOP, 0);
+
+ spm_mtcmos_cpu_unlock(&flags);
+ } else { /* STA_POWER_ON */
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA7_CPUTOP_PWR_CON,
+ spm_read(SPM_CA7_CPUTOP_PWR_CON) | PWR_ON);
+ udelay(1);
+ spm_write(SPM_CA7_CPUTOP_PWR_CON,
+ spm_read(SPM_CA7_CPUTOP_PWR_CON) | PWR_ON_2ND);
+
+ wait_pwr_status(CA7_CPUTOP, CA7_CPUTOP);
+
+ spm_write(SPM_CA7_CPUTOP_PWR_CON,
+ spm_read(SPM_CA7_CPUTOP_PWR_CON) & ~PWR_ISO);
+
+ spm_write(SPM_CA7_CPUTOP_L2_PDN,
+ spm_read(SPM_CA7_CPUTOP_L2_PDN) & ~L2_SRAM_PDN);
+
+ wait_reg_bits(SPM_CA7_CPUTOP_L2_PDN, L2_SRAM_PDN_ACK, 0);
+
+ udelay(1);
+ spm_write(SPM_CA7_CPUTOP_PWR_CON,
+ spm_read(SPM_CA7_CPUTOP_PWR_CON) | SRAM_ISOINT_B);
+ udelay(1);
+ spm_write(SPM_CA7_CPUTOP_PWR_CON,
+ spm_read(SPM_CA7_CPUTOP_PWR_CON) & ~SRAM_CKISO);
+
+ spm_write(SPM_CA7_CPUTOP_PWR_CON,
+ spm_read(SPM_CA7_CPUTOP_PWR_CON) & ~PWR_CLK_DIS);
+ spm_write(SPM_CA7_CPUTOP_PWR_CON,
+ spm_read(SPM_CA7_CPUTOP_PWR_CON) | PWR_RST_B);
+
+ spm_mtcmos_cpu_unlock(&flags);
+ }
+
+ return 0;
+}
+
+int spm_mtcmos_ctrl_cpusys1(int state, int chkWfiBeforePdn)
+{
+ unsigned long flags;
+
+ /* enable register control */
+ spm_write(SPM_POWERON_CONFIG_SET, (SPM_PROJECT_CODE << 16) | (1U << 0));
+
+ if (state == STA_POWER_DOWN) {
+ if (chkWfiBeforePdn)
+ mdelay(500);
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA15_CPUTOP_PWR_CON,
+ spm_read(SPM_CA15_CPUTOP_PWR_CON) | PWR_ISO);
+
+ spm_write(SPM_CA15_CPUTOP_PWR_CON,
+ spm_read(SPM_CA15_CPUTOP_PWR_CON) | SRAM_CKISO);
+ spm_write(SPM_CA15_CPUTOP_PWR_CON,
+ spm_read(SPM_CA15_CPUTOP_PWR_CON) & ~SRAM_ISOINT_B);
+
+ spm_write(SPM_CA15_L2_PWR_CON,
+ spm_read(SPM_CA15_L2_PWR_CON) | CA15_L2_PDN);
+
+ wait_reg_bits(SPM_CA15_L2_PWR_CON, CA15_L2_PDN_ACK, CA15_L2_PDN_ACK);
+
+ spm_write(SPM_CA15_L2_PWR_CON,
+ spm_read(SPM_CA15_L2_PWR_CON) | CA15_L2_PDN_ISO);
+ udelay(2);
+
+ spm_write(SPM_CA15_CPUTOP_PWR_CON,
+ spm_read(SPM_CA15_CPUTOP_PWR_CON) & ~PWR_RST_B);
+ spm_write(SPM_CA15_CPUTOP_PWR_CON,
+ spm_read(SPM_CA15_CPUTOP_PWR_CON) | PWR_CLK_DIS);
+
+ spm_write(SPM_CA15_CPUTOP_PWR_CON,
+ spm_read(SPM_CA15_CPUTOP_PWR_CON) & ~PWR_ON);
+ spm_write(SPM_CA15_CPUTOP_PWR_CON,
+ spm_read(SPM_CA15_CPUTOP_PWR_CON) & ~PWR_ON_2ND);
+
+ wait_pwr_status(CA15_CPUTOP, 0);
+
+ spm_mtcmos_cpu_unlock(&flags);
+ } else { /* STA_POWER_ON */
+
+ spm_mtcmos_cpu_lock(&flags);
+
+ spm_write(SPM_CA15_CPUTOP_PWR_CON,
+ spm_read(SPM_CA15_CPUTOP_PWR_CON) | PWR_ON);
+ udelay(1);
+ spm_write(SPM_CA15_CPUTOP_PWR_CON,
+ spm_read(SPM_CA15_CPUTOP_PWR_CON) | PWR_ON_2ND);
+
+ wait_pwr_status(CA15_CPUTOP, CA15_CPUTOP);
+
+ spm_write(SPM_CA15_CPUTOP_PWR_CON,
+ spm_read(SPM_CA15_CPUTOP_PWR_CON) & ~PWR_ISO);
+
+ spm_write(SPM_CA15_L2_PWR_CON,
+ spm_read(SPM_CA15_L2_PWR_CON) & ~CA15_L2_PDN_ISO);
+ spm_write(SPM_CA15_L2_PWR_CON,
+ spm_read(SPM_CA15_L2_PWR_CON) & ~CA15_L2_PDN);
+
+ wait_reg_bits(SPM_CA15_L2_PWR_CON, CA15_L2_PDN_ACK, 0);
+
+ udelay(1);
+ spm_write(SPM_CA15_CPUTOP_PWR_CON,
+ spm_read(SPM_CA15_CPUTOP_PWR_CON) | SRAM_ISOINT_B);
+ udelay(1);
+ spm_write(SPM_CA15_CPUTOP_PWR_CON,
+ spm_read(SPM_CA15_CPUTOP_PWR_CON) & ~SRAM_CKISO);
+
+ spm_write(SPM_CA15_CPUTOP_PWR_CON,
+ spm_read(SPM_CA15_CPUTOP_PWR_CON) & ~PWR_CLK_DIS);
+ spm_write(SPM_CA15_CPUTOP_PWR_CON,
+ spm_read(SPM_CA15_CPUTOP_PWR_CON) | PWR_RST_B);
+
+ spm_mtcmos_cpu_unlock(&flags);
+ }
+
+ return 0;
+}
+
+void spm_mtcmos_ctrl_cpusys1_init_1st_bring_up(int state)
+{
+
+ if (state == STA_POWER_DOWN) {
+ spm_mtcmos_ctrl_cpu7(STA_POWER_DOWN, 0);
+ spm_mtcmos_ctrl_cpu6(STA_POWER_DOWN, 0);
+ spm_mtcmos_ctrl_cpu5(STA_POWER_DOWN, 0);
+ spm_mtcmos_ctrl_cpu4(STA_POWER_DOWN, 0);
+ } else { /* STA_POWER_ON */
+
+ spm_mtcmos_ctrl_cpu4(STA_POWER_ON, 1);
+ spm_mtcmos_ctrl_cpu5(STA_POWER_ON, 1);
+ spm_mtcmos_ctrl_cpu6(STA_POWER_ON, 1);
+ spm_mtcmos_ctrl_cpu7(STA_POWER_ON, 1);
+ }
+}
+
+bool spm_cpusys0_can_power_down(void)
+{
+ return !(spm_read(SPM_PWR_STATUS) &
+ (CA15_CPU0 | CA15_CPU1 | CA15_CPU2 | CA15_CPU3 | CA15_CPUTOP |
+ CA7_CPU1 | CA7_CPU2 | CA7_CPU3))
+ && !(spm_read(SPM_PWR_STATUS_2ND) &
+ (CA15_CPU0 | CA15_CPU1 | CA15_CPU2 | CA15_CPU3 | CA15_CPUTOP |
+ CA7_CPU1 | CA7_CPU2 | CA7_CPU3));
+}
+
+bool spm_cpusys1_can_power_down(void)
+{
+ return !(spm_read(SPM_PWR_STATUS) &
+ (CA7_CPU0 | CA7_CPU1 | CA7_CPU2 | CA7_CPU3 | CA7_CPUTOP |
+ CA15_CPU1 | CA15_CPU2 | CA15_CPU3))
+ && !(spm_read(SPM_PWR_STATUS_2ND) &
+ (CA7_CPU0 | CA7_CPU1 | CA7_CPU2 | CA7_CPU3 | CA7_CPUTOP |
+ CA15_CPU1 | CA15_CPU2 | CA15_CPU3));
+}
+
+
+/**************************************
+ * for non-CPU MTCMOS
+ **************************************/
+#define MD2_PWR_STA_MASK (0x1 << 22)
+#define VEN_PWR_STA_MASK (0x1 << 8)
+#define VDE_PWR_STA_MASK (0x1 << 7)
+#define ISP_PWR_STA_MASK (0x1 << 5)
+#define MFG_PWR_STA_MASK (0x1 << 4)
+#define DIS_PWR_STA_MASK (0x1 << 3)
+#define CONN_PWR_STA_MASK (0x1 << 1)
+#define MD1_PWR_STA_MASK (0x1 << 0)
+
+#define SRAM_PDN (0xf << 8) /* VDEC, VENC, ISP, DISP */
+#define MFG_SRAM_PDN (0x3f << 8)
+#define MD_SRAM_PDN (0x1 << 8) /* MD1, C2K */
+#define CONN_SRAM_PDN (0x1 << 8)
+
+#define VDE_SRAM_ACK (0x1 << 12)
+#define VEN_SRAM_ACK (0xf << 12)
+#define ISP_SRAM_ACK (0x3 << 12)
+#define DIS_SRAM_ACK (0x1 << 12)
+#define MFG_SRAM_ACK (0x1 << 16)
+
+#define MD1_PROT_MASK ((0x1U<<24) | (0x1<<25) | (0x1<<26) | (0x1<<27) | (0x1<<28)) /* bit 24,25,26,27,28 */
+#define MD2_PROT_MASK ((0x1U<<29) | (0x1<<30) | (0x1<<31)) /* bit 29, 30, 31 */
+/* bit16 is GCE, Dram dummy read use cqdma, and it is in GCE. */
+#define DISP_PROT_MASK ((0x1 << 1)) /* bit 1, 6, 16; if bit6 set, MMSYS PDN, access reg will hang, */
+#define MFG_PROT_MASK ((0x1 << 14)) /* bit 14 */
+#define CONN_PROT_MASK ((0x1 << 2) | (0x1 << 8)) /* bit 2, 8 */
+
+
+
+int spm_mtcmos_ctrl_vdec(int state)
+{
+ int err = 0;
+ unsigned int val;
+ unsigned long flags;
+
+ spm_mtcmos_noncpu_lock(flags);
+
+ if (state == STA_POWER_DOWN) {
+ spm_write(SPM_VDE_PWR_CON,
+ spm_read(SPM_VDE_PWR_CON) | SRAM_PDN);
+
+ while ((spm_read(SPM_VDE_PWR_CON) & VDE_SRAM_ACK) !=
+ VDE_SRAM_ACK) {
+ }
+
+ spm_write(SPM_VDE_PWR_CON, spm_read(SPM_VDE_PWR_CON) | PWR_ISO);
+
+ val = spm_read(SPM_VDE_PWR_CON);
+ val = (val & ~PWR_RST_B) | PWR_CLK_DIS;
+ spm_write(SPM_VDE_PWR_CON, val);
+
+ spm_write(SPM_VDE_PWR_CON,
+ spm_read(SPM_VDE_PWR_CON) & ~(PWR_ON | PWR_ON_2ND));
+
+ while ((spm_read(SPM_PWR_STATUS) & VDE_PWR_STA_MASK)
+ || (spm_read(SPM_PWR_STATUS_2ND) & VDE_PWR_STA_MASK)) {
+ }
+ } else { /* STA_POWER_ON */
+ spm_write(SPM_VDE_PWR_CON, spm_read(SPM_VDE_PWR_CON) | PWR_ON);
+ spm_write(SPM_VDE_PWR_CON,
+ spm_read(SPM_VDE_PWR_CON) | PWR_ON_2ND);
+
+ while (!(spm_read(SPM_PWR_STATUS) & VDE_PWR_STA_MASK)
+ || !(spm_read(SPM_PWR_STATUS_2ND) & VDE_PWR_STA_MASK)) {
+ }
+
+ spm_write(SPM_VDE_PWR_CON,
+ spm_read(SPM_VDE_PWR_CON) & ~PWR_CLK_DIS);
+ spm_write(SPM_VDE_PWR_CON,
+ spm_read(SPM_VDE_PWR_CON) & ~PWR_ISO);
+ spm_write(SPM_VDE_PWR_CON,
+ spm_read(SPM_VDE_PWR_CON) | PWR_RST_B);
+
+ spm_write(SPM_VDE_PWR_CON,
+ spm_read(SPM_VDE_PWR_CON) & ~SRAM_PDN);
+
+ while ((spm_read(SPM_VDE_PWR_CON) & VDE_SRAM_ACK)) {
+ }
+ }
+
+ spm_mtcmos_noncpu_unlock(flags);
+
+ return err;
+}
+
+int spm_mtcmos_ctrl_venc(int state)
+{
+ int err = 0;
+ unsigned int val;
+ unsigned long flags;
+
+ spm_mtcmos_noncpu_lock(flags);
+
+ if (state == STA_POWER_DOWN) {
+ spm_write(SPM_VEN_PWR_CON,
+ spm_read(SPM_VEN_PWR_CON) | SRAM_PDN);
+
+ while ((spm_read(SPM_VEN_PWR_CON) & VEN_SRAM_ACK) !=
+ VEN_SRAM_ACK) {
+ }
+
+ spm_write(SPM_VEN_PWR_CON, spm_read(SPM_VEN_PWR_CON) | PWR_ISO);
+
+ val = spm_read(SPM_VEN_PWR_CON);
+ val = (val & ~PWR_RST_B) | PWR_CLK_DIS;
+ spm_write(SPM_VEN_PWR_CON, val);
+
+ spm_write(SPM_VEN_PWR_CON,
+ spm_read(SPM_VEN_PWR_CON) & ~(PWR_ON | PWR_ON_2ND));
+
+ while ((spm_read(SPM_PWR_STATUS) & VEN_PWR_STA_MASK)
+ || (spm_read(SPM_PWR_STATUS_2ND) & VEN_PWR_STA_MASK)) {
+ }
+ } else { /* STA_POWER_ON */
+ spm_write(SPM_VEN_PWR_CON, spm_read(SPM_VEN_PWR_CON) | PWR_ON);
+ spm_write(SPM_VEN_PWR_CON,
+ spm_read(SPM_VEN_PWR_CON) | PWR_ON_2ND);
+
+ while (!(spm_read(SPM_PWR_STATUS) & VEN_PWR_STA_MASK)
+ || !(spm_read(SPM_PWR_STATUS_2ND) & VEN_PWR_STA_MASK)) {
+ }
+
+ spm_write(SPM_VEN_PWR_CON,
+ spm_read(SPM_VEN_PWR_CON) & ~PWR_CLK_DIS);
+ spm_write(SPM_VEN_PWR_CON,
+ spm_read(SPM_VEN_PWR_CON) & ~PWR_ISO);
+ spm_write(SPM_VEN_PWR_CON,
+ spm_read(SPM_VEN_PWR_CON) | PWR_RST_B);
+
+ spm_write(SPM_VEN_PWR_CON,
+ spm_read(SPM_VEN_PWR_CON) & ~SRAM_PDN);
+
+ while ((spm_read(SPM_VEN_PWR_CON) & VEN_SRAM_ACK)) {
+ }
+ }
+
+ spm_mtcmos_noncpu_unlock(flags);
+
+ return err;
+}
+
+int spm_mtcmos_ctrl_isp(int state)
+{
+ int err = 0;
+ unsigned int val;
+ unsigned long flags;
+
+ spm_mtcmos_noncpu_lock(flags);
+
+ if (state == STA_POWER_DOWN) {
+ spm_write(SPM_ISP_PWR_CON,
+ spm_read(SPM_ISP_PWR_CON) | SRAM_PDN);
+
+ while ((spm_read(SPM_ISP_PWR_CON) & ISP_SRAM_ACK) !=
+ ISP_SRAM_ACK) {
+ }
+
+ spm_write(SPM_ISP_PWR_CON, spm_read(SPM_ISP_PWR_CON) | PWR_ISO);
+
+ val = spm_read(SPM_ISP_PWR_CON);
+ val = (val & ~PWR_RST_B) | PWR_CLK_DIS;
+ spm_write(SPM_ISP_PWR_CON, val);
+
+ spm_write(SPM_ISP_PWR_CON,
+ spm_read(SPM_ISP_PWR_CON) & ~(PWR_ON | PWR_ON_2ND));
+
+ while ((spm_read(SPM_PWR_STATUS) & ISP_PWR_STA_MASK)
+ || (spm_read(SPM_PWR_STATUS_2ND) & ISP_PWR_STA_MASK)) {
+ }
+ } else { /* STA_POWER_ON */
+ spm_write(SPM_ISP_PWR_CON, spm_read(SPM_ISP_PWR_CON) | PWR_ON);
+ spm_write(SPM_ISP_PWR_CON,
+ spm_read(SPM_ISP_PWR_CON) | PWR_ON_2ND);
+
+ while (!(spm_read(SPM_PWR_STATUS) & ISP_PWR_STA_MASK)
+ || !(spm_read(SPM_PWR_STATUS_2ND) & ISP_PWR_STA_MASK)) {
+ }
+
+ spm_write(SPM_ISP_PWR_CON,
+ spm_read(SPM_ISP_PWR_CON) & ~PWR_CLK_DIS);
+ spm_write(SPM_ISP_PWR_CON,
+ spm_read(SPM_ISP_PWR_CON) & ~PWR_ISO);
+ spm_write(SPM_ISP_PWR_CON,
+ spm_read(SPM_ISP_PWR_CON) | PWR_RST_B);
+
+ spm_write(SPM_ISP_PWR_CON,
+ spm_read(SPM_ISP_PWR_CON) & ~SRAM_PDN);
+
+ while ((spm_read(SPM_ISP_PWR_CON) & ISP_SRAM_ACK)) {
+ }
+ }
+
+ spm_mtcmos_noncpu_unlock(flags);
+
+ return err;
+}
+
+
+int spm_mtcmos_ctrl_disp(int state)
+{
+ int err = 0;
+ unsigned int val;
+ unsigned long flags;
+
+ spm_mtcmos_noncpu_lock(flags);
+
+ if (state == STA_POWER_DOWN) {
+ spm_write(TOPAXI_PROT_EN,
+ spm_read(TOPAXI_PROT_EN) | DISP_PROT_MASK);
+ while ((spm_read(TOPAXI_PROT_STA1) & DISP_PROT_MASK) !=
+ DISP_PROT_MASK) {
+ }
+
+ spm_write(SPM_DIS_PWR_CON,
+ spm_read(SPM_DIS_PWR_CON) | SRAM_PDN);
+
+ while ((spm_read(SPM_DIS_PWR_CON) & DIS_SRAM_ACK) !=
+ DIS_SRAM_ACK) {
+ }
+
+ spm_write(SPM_DIS_PWR_CON, spm_read(SPM_DIS_PWR_CON) | PWR_ISO);
+
+ val = spm_read(SPM_DIS_PWR_CON);
+ val = (val & ~PWR_RST_B) | PWR_CLK_DIS;
+ spm_write(SPM_DIS_PWR_CON, val);
+
+ spm_write(SPM_DIS_PWR_CON,
+ spm_read(SPM_DIS_PWR_CON) & ~(PWR_ON | PWR_ON_2ND));
+
+ while ((spm_read(SPM_PWR_STATUS) & DIS_PWR_STA_MASK)
+ || (spm_read(SPM_PWR_STATUS_2ND) & DIS_PWR_STA_MASK)) {
+ }
+ } else { /* STA_POWER_ON */
+ spm_write(SPM_DIS_PWR_CON, spm_read(SPM_DIS_PWR_CON) | PWR_ON);
+ spm_write(SPM_DIS_PWR_CON,
+ spm_read(SPM_DIS_PWR_CON) | PWR_ON_2ND);
+
+ while (!(spm_read(SPM_PWR_STATUS) & DIS_PWR_STA_MASK)
+ || !(spm_read(SPM_PWR_STATUS_2ND) & DIS_PWR_STA_MASK)) {
+ }
+
+ spm_write(SPM_DIS_PWR_CON,
+ spm_read(SPM_DIS_PWR_CON) & ~PWR_CLK_DIS);
+ spm_write(SPM_DIS_PWR_CON,
+ spm_read(SPM_DIS_PWR_CON) & ~PWR_ISO);
+ spm_write(SPM_DIS_PWR_CON,
+ spm_read(SPM_DIS_PWR_CON) | PWR_RST_B);
+
+ spm_write(SPM_DIS_PWR_CON,
+ spm_read(SPM_DIS_PWR_CON) & ~SRAM_PDN);
+
+ while ((spm_read(SPM_DIS_PWR_CON) & DIS_SRAM_ACK)) {
+ }
+
+ spm_write(TOPAXI_PROT_EN,
+ spm_read(TOPAXI_PROT_EN) & ~DISP_PROT_MASK);
+ while (spm_read(TOPAXI_PROT_STA1) & DISP_PROT_MASK) {
+ }
+ }
+
+ spm_mtcmos_noncpu_unlock(flags);
+
+ return err;
+}
+
+
+int spm_mtcmos_ctrl_mfg(int state)
+{
+ int err = 0;
+ unsigned int val;
+ unsigned long flags;
+
+ spm_mtcmos_noncpu_lock(flags);
+
+ if (state == STA_POWER_DOWN) {
+ spm_write(TOPAXI_PROT_EN,
+ spm_read(TOPAXI_PROT_EN) | MFG_PROT_MASK);
+ while ((spm_read(TOPAXI_PROT_STA1) & MFG_PROT_MASK) !=
+ MFG_PROT_MASK) {
+ }
+
+ spm_write(SPM_MFG_PWR_CON,
+ spm_read(SPM_MFG_PWR_CON) | MFG_SRAM_PDN);
+
+ while ((spm_read(SPM_MFG_PWR_CON) & MFG_SRAM_ACK) !=
+ MFG_SRAM_ACK) {
+ }
+
+ spm_write(SPM_MFG_PWR_CON, spm_read(SPM_MFG_PWR_CON) | PWR_ISO);
+
+ val = spm_read(SPM_MFG_PWR_CON);
+ val = (val & ~PWR_RST_B) | PWR_CLK_DIS;
+ spm_write(SPM_MFG_PWR_CON, val);
+
+ spm_write(SPM_MFG_PWR_CON,
+ spm_read(SPM_MFG_PWR_CON) & ~(PWR_ON | PWR_ON_2ND));
+
+ while ((spm_read(SPM_PWR_STATUS) & MFG_PWR_STA_MASK)
+ || (spm_read(SPM_PWR_STATUS_2ND) & MFG_PWR_STA_MASK)) {
+ }
+ } else { /* STA_POWER_ON */
+ spm_write(SPM_MFG_PWR_CON, spm_read(SPM_MFG_PWR_CON) | PWR_ON);
+ spm_write(SPM_MFG_PWR_CON,
+ spm_read(SPM_MFG_PWR_CON) | PWR_ON_2ND);
+
+ while (!(spm_read(SPM_PWR_STATUS) & MFG_PWR_STA_MASK) ||
+ !(spm_read(SPM_PWR_STATUS_2ND) & MFG_PWR_STA_MASK)) {
+ }
+
+ spm_write(SPM_MFG_PWR_CON,
+ spm_read(SPM_MFG_PWR_CON) & ~PWR_CLK_DIS);
+ spm_write(SPM_MFG_PWR_CON,
+ spm_read(SPM_MFG_PWR_CON) & ~PWR_ISO);
+ spm_write(SPM_MFG_PWR_CON,
+ spm_read(SPM_MFG_PWR_CON) | PWR_RST_B);
+
+ spm_write(SPM_MFG_PWR_CON,
+ spm_read(SPM_MFG_PWR_CON) & ~MFG_SRAM_PDN);
+
+ while ((spm_read(SPM_MFG_PWR_CON) & MFG_SRAM_ACK)) {
+ }
+
+ spm_write(TOPAXI_PROT_EN,
+ spm_read(TOPAXI_PROT_EN) & ~MFG_PROT_MASK);
+ while (spm_read(TOPAXI_PROT_STA1) & MFG_PROT_MASK) {
+ }
+ }
+
+ spm_mtcmos_noncpu_unlock(flags);
+
+ return err;
+}
+
+int spm_mtcmos_ctrl_mdsys1(int state)
+{
+ int err = 0;
+ unsigned int val;
+ unsigned long flags;
+
+ spm_mtcmos_noncpu_lock(flags);
+
+ if (state == STA_POWER_DOWN) {
+ spm_write(TOPAXI_PROT_EN,
+ spm_read(TOPAXI_PROT_EN) | MD1_PROT_MASK);
+ while ((spm_read(TOPAXI_PROT_STA1) & MD1_PROT_MASK) !=
+ MD1_PROT_MASK) {
+ }
+
+ spm_write(SPM_MD_PWR_CON,
+ spm_read(SPM_MD_PWR_CON) | MD_SRAM_PDN);
+
+ spm_write(SPM_MD_PWR_CON, spm_read(SPM_MD_PWR_CON) | PWR_ISO);
+
+ val = spm_read(SPM_MD_PWR_CON);
+ val = (val & ~PWR_RST_B) | PWR_CLK_DIS;
+ spm_write(SPM_MD_PWR_CON, val);
+
+ spm_write(SPM_MD_PWR_CON,
+ spm_read(SPM_MD_PWR_CON) & ~(PWR_ON | PWR_ON_2ND));
+
+ while ((spm_read(SPM_PWR_STATUS) & MD1_PWR_STA_MASK)
+ || (spm_read(SPM_PWR_STATUS_2ND) & MD1_PWR_STA_MASK)) {
+ }
+
+ } else { /* STA_POWER_ON */
+
+ spm_write(SPM_MD_PWR_CON, spm_read(SPM_MD_PWR_CON) | PWR_ON);
+ spm_write(SPM_MD_PWR_CON,
+ spm_read(SPM_MD_PWR_CON) | PWR_ON_2ND);
+
+ while (!(spm_read(SPM_PWR_STATUS) & MD1_PWR_STA_MASK)
+ || !(spm_read(SPM_PWR_STATUS_2ND) & MD1_PWR_STA_MASK)) {
+ }
+
+ spm_write(SPM_MD_PWR_CON,
+ spm_read(SPM_MD_PWR_CON) & ~PWR_CLK_DIS);
+ spm_write(SPM_MD_PWR_CON, spm_read(SPM_MD_PWR_CON) & ~PWR_ISO);
+ spm_write(SPM_MD_PWR_CON, spm_read(SPM_MD_PWR_CON) | PWR_RST_B);
+
+ spm_write(SPM_MD_PWR_CON,
+ spm_read(SPM_MD_PWR_CON) & ~MD_SRAM_PDN);
+
+ spm_write(TOPAXI_PROT_EN,
+ spm_read(TOPAXI_PROT_EN) & ~MD1_PROT_MASK);
+ while (spm_read(TOPAXI_PROT_STA1) & MD1_PROT_MASK) {
+ }
+ }
+
+ spm_mtcmos_noncpu_unlock(flags);
+
+ return err;
+}
+
+int spm_mtcmos_ctrl_mdsys2(int state)
+{
+ int err = 0;
+ unsigned int val;
+ unsigned long flags;
+
+ spm_mtcmos_noncpu_lock(flags);
+
+ if (state == STA_POWER_DOWN) {
+ spm_write(TOPAXI_PROT_EN,
+ spm_read(TOPAXI_PROT_EN) | MD2_PROT_MASK);
+ while ((spm_read(TOPAXI_PROT_STA1) & MD2_PROT_MASK) !=
+ MD2_PROT_MASK) {
+ }
+
+ spm_write(SPM_C2K_PWR_CON,
+ spm_read(SPM_C2K_PWR_CON) | MD_SRAM_PDN);
+
+ spm_write(SPM_C2K_PWR_CON, spm_read(SPM_C2K_PWR_CON) | PWR_ISO);
+
+ val = spm_read(SPM_C2K_PWR_CON);
+ val = (val & ~PWR_RST_B) | PWR_CLK_DIS;
+ spm_write(SPM_C2K_PWR_CON, val);
+
+ spm_write(SPM_C2K_PWR_CON,
+ spm_read(SPM_C2K_PWR_CON) & ~(PWR_ON | PWR_ON_2ND));
+
+ while ((spm_read(SPM_PWR_STATUS) & MD2_PWR_STA_MASK)
+ || (spm_read(SPM_PWR_STATUS_2ND) & MD2_PWR_STA_MASK)) {
+ }
+
+ } else { /* STA_POWER_ON */
+
+ spm_write(SPM_C2K_PWR_CON, spm_read(SPM_C2K_PWR_CON) | PWR_ON);
+ spm_write(SPM_C2K_PWR_CON,
+ spm_read(SPM_C2K_PWR_CON) | PWR_ON_2ND);
+
+ while (!(spm_read(SPM_PWR_STATUS) & MD2_PWR_STA_MASK)
+ || !(spm_read(SPM_PWR_STATUS_2ND) & MD2_PWR_STA_MASK)) {
+ }
+
+ spm_write(SPM_C2K_PWR_CON,
+ spm_read(SPM_C2K_PWR_CON) & ~PWR_CLK_DIS);
+ spm_write(SPM_C2K_PWR_CON,
+ spm_read(SPM_C2K_PWR_CON) & ~PWR_ISO);
+ spm_write(SPM_C2K_PWR_CON,
+ spm_read(SPM_C2K_PWR_CON) | PWR_RST_B);
+
+ spm_write(SPM_C2K_PWR_CON,
+ spm_read(SPM_C2K_PWR_CON) & ~MD_SRAM_PDN);
+
+ spm_write(TOPAXI_PROT_EN,
+ spm_read(TOPAXI_PROT_EN) & ~MD2_PROT_MASK);
+ while (spm_read(TOPAXI_PROT_STA1) & MD2_PROT_MASK) {
+ }
+ }
+
+ spm_mtcmos_noncpu_unlock(flags);
+
+ return err;
+}
+
+int spm_mtcmos_ctrl_connsys(int state)
+{
+ int err = 0;
+ unsigned int val;
+ unsigned long flags;
+
+ spm_mtcmos_noncpu_lock(flags);
+
+ if (state == STA_POWER_DOWN) {
+
+ spm_write(TOPAXI_PROT_EN,
+ spm_read(TOPAXI_PROT_EN) | CONN_PROT_MASK);
+ while ((spm_read(TOPAXI_PROT_STA1) & CONN_PROT_MASK) !=
+ CONN_PROT_MASK) {
+ }
+
+ spm_write(SPM_CONN_PWR_CON,
+ spm_read(SPM_CONN_PWR_CON) | CONN_SRAM_PDN);
+
+ spm_write(SPM_CONN_PWR_CON,
+ spm_read(SPM_CONN_PWR_CON) | PWR_ISO);
+
+ val = spm_read(SPM_CONN_PWR_CON);
+ val = (val & ~PWR_RST_B) | PWR_CLK_DIS;
+ spm_write(SPM_CONN_PWR_CON, val);
+
+ spm_write(SPM_CONN_PWR_CON,
+ spm_read(SPM_CONN_PWR_CON) & ~(PWR_ON | PWR_ON_2ND));
+
+ while ((spm_read(SPM_PWR_STATUS) & CONN_PWR_STA_MASK)
+ || (spm_read(SPM_PWR_STATUS_2ND) & CONN_PWR_STA_MASK)) {
+ }
+ } else {
+ spm_write(SPM_CONN_PWR_CON,
+ spm_read(SPM_CONN_PWR_CON) | PWR_ON);
+ spm_write(SPM_CONN_PWR_CON,
+ spm_read(SPM_CONN_PWR_CON) | PWR_ON_2ND);
+
+ while (!(spm_read(SPM_PWR_STATUS) & CONN_PWR_STA_MASK)
+ || !(spm_read(SPM_PWR_STATUS_2ND) & CONN_PWR_STA_MASK)) {
+ }
+
+ spm_write(SPM_CONN_PWR_CON,
+ spm_read(SPM_CONN_PWR_CON) & ~PWR_CLK_DIS);
+ spm_write(SPM_CONN_PWR_CON,
+ spm_read(SPM_CONN_PWR_CON) & ~PWR_ISO);
+ spm_write(SPM_CONN_PWR_CON,
+ spm_read(SPM_CONN_PWR_CON) | PWR_RST_B);
+
+ spm_write(SPM_CONN_PWR_CON,
+ spm_read(SPM_CONN_PWR_CON) & ~CONN_SRAM_PDN);
+
+ spm_write(TOPAXI_PROT_EN,
+ spm_read(TOPAXI_PROT_EN) & ~CONN_PROT_MASK);
+ while (spm_read(TOPAXI_PROT_STA1) & CONN_PROT_MASK) {
+ }
+ }
+
+ spm_mtcmos_noncpu_unlock(flags);
+
+ return err;
+}
+
+int spm_topaxi_prot(int bit, int en)
+{
+ unsigned long flags;
+
+ spm_mtcmos_noncpu_lock(flags);
+
+ if (en == 1) {
+ spm_write(TOPAXI_PROT_EN,
+ spm_read(TOPAXI_PROT_EN) | (1U << bit));
+ while ((spm_read(TOPAXI_PROT_STA1) & (1U << bit)) !=
+ (1U << bit)) {
+ }
+ } else {
+ spm_write(TOPAXI_PROT_EN,
+ spm_read(TOPAXI_PROT_EN) & ~(1U << bit));
+ while (spm_read(TOPAXI_PROT_STA1) & (1U << bit)) {
+ }
+ }
+
+ spm_mtcmos_noncpu_unlock(flags);
+
+ return 0;
+}
diff --git a/src/bsp/lk/platform/mt2635/drivers/uart/uart.c b/src/bsp/lk/platform/mt2635/drivers/uart/uart.c
new file mode 100644
index 0000000..2395b7e
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/drivers/uart/uart.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <debug.h>
+#include <reg.h>
+#include <dev/uart.h>
+#include <platform/mt_reg_base.h>
+#include <platform/mt_uart.h>
+#include <string.h>
+
+typedef enum {
+ UART1 = UART1_BASE,
+ UART2 = UART2_BASE,
+ UART3 = UART3_BASE,
+ UART4 = UART4_BASE
+} MTK_UART;
+
+/* FCR */
+#define UART_FCR_FIFOE (1 << 0)
+#define UART_FCR_CLRR (1 << 1)
+#define UART_FCR_CLRT (1 << 2)
+#define UART_FCR_DMA1 (1 << 3)
+#define UART_FCR_RXFIFO_1B_TRI (0 << 6)
+#define UART_FCR_RXFIFO_6B_TRI (1 << 6)
+#define UART_FCR_RXFIFO_12B_TRI (2 << 6)
+#define UART_FCR_RXFIFO_RX_TRI (3 << 6)
+#define UART_FCR_TXFIFO_1B_TRI (0 << 4)
+#define UART_FCR_TXFIFO_4B_TRI (1 << 4)
+#define UART_FCR_TXFIFO_8B_TRI (2 << 4)
+#define UART_FCR_TXFIFO_14B_TRI (3 << 4)
+
+#define UART_FCR_FIFO_INIT (UART_FCR_FIFOE|UART_FCR_CLRR|UART_FCR_CLRT)
+#define UART_FCR_NORMAL (UART_FCR_FIFO_INIT | \
+ UART_FCR_TXFIFO_4B_TRI| \
+ UART_FCR_RXFIFO_12B_TRI)
+
+/* LCR */
+#define UART_LCR_BREAK (1 << 6)
+#define UART_LCR_DLAB (1 << 7)
+
+#define UART_WLS_5 (0 << 0)
+#define UART_WLS_6 (1 << 0)
+#define UART_WLS_7 (2 << 0)
+#define UART_WLS_8 (3 << 0)
+#define UART_WLS_MASK (3 << 0)
+
+#define UART_1_STOP (0 << 2)
+#define UART_2_STOP (1 << 2)
+#define UART_1_5_STOP (1 << 2) /* Only when WLS=5 */
+#define UART_STOP_MASK (1 << 2)
+
+#define UART_NONE_PARITY (0 << 3)
+#define UART_ODD_PARITY (0x1 << 3)
+#define UART_EVEN_PARITY (0x3 << 3)
+#define UART_MARK_PARITY (0x5 << 3)
+#define UART_SPACE_PARITY (0x7 << 3)
+#define UART_PARITY_MASK (0x7 << 3)
+
+/* MCR */
+#define UART_MCR_DTR (1 << 0)
+#define UART_MCR_RTS (1 << 1)
+#define UART_MCR_OUT1 (1 << 2)
+#define UART_MCR_OUT2 (1 << 3)
+#define UART_MCR_LOOP (1 << 4)
+#define UART_MCR_XOFF (1 << 7) /* read only */
+#define UART_MCR_NORMAL (UART_MCR_DTR|UART_MCR_RTS)
+
+/* LSR */
+#define UART_LSR_DR (1 << 0)
+#define UART_LSR_OE (1 << 1)
+#define UART_LSR_PE (1 << 2)
+#define UART_LSR_FE (1 << 3)
+#define UART_LSR_BI (1 << 4)
+#define UART_LSR_THRE (1 << 5)
+#define UART_LSR_TEMT (1 << 6)
+#define UART_LSR_FIFOERR (1 << 7)
+
+/* MSR */
+#define UART_MSR_DCTS (1 << 0)
+#define UART_MSR_DDSR (1 << 1)
+#define UART_MSR_TERI (1 << 2)
+#define UART_MSR_DDCD (1 << 3)
+#define UART_MSR_CTS (1 << 4)
+#define UART_MSR_DSR (1 << 5)
+#define UART_MSR_RI (1 << 6)
+#define UART_MSR_DCD (1 << 7)
+
+#define CONFIG_BAUDRATE 921600
+
+#define UART_BASE(uart) (uart)
+
+#define UART_RBR(uart) (UART_BASE(uart)+0x0) /* Read only */
+#define UART_THR(uart) (UART_BASE(uart)+0x0) /* Write only */
+#define UART_IER(uart) (UART_BASE(uart)+0x4)
+#define UART_IIR(uart) (UART_BASE(uart)+0x8) /* Read only */
+#define UART_FCR(uart) (UART_BASE(uart)+0x8) /* Write only */
+#define UART_LCR(uart) (UART_BASE(uart)+0xc)
+#define UART_MCR(uart) (UART_BASE(uart)+0x10)
+#define UART_LSR(uart) (UART_BASE(uart)+0x14)
+#define UART_MSR(uart) (UART_BASE(uart)+0x18)
+#define UART_SCR(uart) (UART_BASE(uart)+0x1c)
+#define UART_DLL(uart) (UART_BASE(uart)+0x0) /* Only when LCR.DLAB = 1 */
+#define UART_DLH(uart) (UART_BASE(uart)+0x4) /* Only when LCR.DLAB = 1 */
+#define UART_EFR(uart) (UART_BASE(uart)+0x8) /* Only when LCR = 0xbf */
+#define UART_XON1(uart) (UART_BASE(uart)+0x10) /* Only when LCR = 0xbf */
+#define UART_XON2(uart) (UART_BASE(uart)+0x14) /* Only when LCR = 0xbf */
+#define UART_XOFF1(uart) (UART_BASE(uart)+0x18) /* Only when LCR = 0xbf */
+#define UART_XOFF2(uart) (UART_BASE(uart)+0x1c) /* Only when LCR = 0xbf */
+#define UART_AUTOBAUD_EN(uart) (UART_BASE(uart)+0x20)
+#define UART_HIGHSPEED(uart) (UART_BASE(uart)+0x24)
+#define UART_SAMPLE_COUNT(uart) (UART_BASE(uart)+0x28)
+#define UART_SAMPLE_POINT(uart) (UART_BASE(uart)+0x2c)
+#define UART_AUTOBAUD_REG(uart) (UART_BASE(uart)+0x30)
+#define UART_RATE_FIX_AD(uart) (UART_BASE(uart)+0x34)
+#define UART_AUTOBAUD_SAMPLE(uart) (UART_BASE(uart)+0x38)
+#define UART_GUARD(uart) (UART_BASE(uart)+0x3c)
+#define UART_ESCAPE_DAT(uart) (UART_BASE(uart)+0x40)
+#define UART_ESCAPE_EN(uart) (UART_BASE(uart)+0x44)
+#define UART_SLEEP_EN(uart) (UART_BASE(uart)+0x48)
+#define UART_VFIFO_EN(uart) (UART_BASE(uart)+0x4c)
+#define UART_RXTRI_AD(uart) (UART_BASE(uart)+0x50)
+
+#define INVAL_UART_BASE 0xFFFFFFFF
+
+// output uart port
+volatile addr_t g_uart = INVAL_UART_BASE;
+
+//extern unsigned int mtk_get_bus_freq(void);
+#define UART_SRC_CLK 26000000
+
+static void uart_setbrg(void)
+{
+ unsigned int byte,speed;
+ unsigned int highspeed;
+ unsigned int quot, divisor, remainder;
+ unsigned int uartclk;
+ unsigned short data, high_speed_div, sample_count, sample_point;
+ unsigned int tmp_div;
+
+ speed = CONFIG_BAUDRATE;
+ uartclk = UART_SRC_CLK;
+ //uartclk = (unsigned int)(mtk_get_bus_freq()*1000/4);
+ if (speed <= 115200 ) {
+ highspeed = 0;
+ quot = 16;
+ } else {
+ highspeed = 3;
+ quot = 1;
+ }
+
+ if (highspeed < 3) { /*0~2*/
+ /* Set divisor DLL and DLH */
+ divisor = uartclk / (quot * speed);
+ remainder = uartclk % (quot * speed);
+
+ if (remainder >= (quot / 2) * speed)
+ divisor += 1;
+
+ writel(highspeed, UART_HIGHSPEED(g_uart));
+ byte = readl(UART_LCR(g_uart)); /* DLAB start */
+ writel((byte | UART_LCR_DLAB), UART_LCR(g_uart));
+ writel((divisor & 0x00ff), UART_DLL(g_uart));
+ writel(((divisor >> 8)&0x00ff), UART_DLH(g_uart));
+ writel(byte, UART_LCR(g_uart)); /* DLAB end */
+ } else {
+ data=(unsigned short)(uartclk/speed);
+ high_speed_div = (data>>8) + 1; // divided by 256
+
+ tmp_div=uartclk/(speed*high_speed_div);
+ divisor = (unsigned short)tmp_div;
+
+ remainder = (uartclk)%(high_speed_div*speed);
+ /*get (sample_count+1)*/
+ if (remainder >= ((speed)*(high_speed_div))>>1)
+ divisor = (unsigned short)(tmp_div+1);
+ else
+ divisor = (unsigned short)tmp_div;
+
+ sample_count=divisor-1;
+
+ /*get the sample point*/
+ sample_point=(sample_count-1)>>1;
+
+ /*configure register*/
+ writel(highspeed, UART_HIGHSPEED(g_uart));
+
+ byte = readl(UART_LCR(g_uart)); /* DLAB start */
+ writel((byte | UART_LCR_DLAB), UART_LCR(g_uart));
+ writel((high_speed_div & 0x00ff), UART_DLL(g_uart));
+ writel(((high_speed_div >> 8)&0x00ff), UART_DLH(g_uart));
+ writel(sample_count, UART_SAMPLE_COUNT(g_uart));
+ writel(sample_point, UART_SAMPLE_POINT(g_uart));
+ writel(byte, UART_LCR(g_uart)); /* DLAB end */
+ }
+}
+
+static void mtk_set_current_uart(MTK_UART uart_base)
+{
+ g_uart = uart_base;
+}
+
+void uart_init_early(void)
+{
+ mtk_set_current_uart(UART1);
+ /* clear fifo */
+ writel(readl(UART_FCR(g_uart)) + UART_FCR_FIFO_INIT, UART_FCR(g_uart));
+ writel(UART_NONE_PARITY | UART_WLS_8 | UART_1_STOP, UART_LCR(g_uart));
+ uart_setbrg();
+}
+
+#define UART_LSR_TX_READY (UART_LSR_THRE | UART_LSR_TEMT)
+int uart_putc(int port, char ch)
+{
+ if (g_uart == INVAL_UART_BASE) {
+ return -1;
+ }
+
+ while(1) {
+ if ((readl(UART_LSR(g_uart)) & UART_LSR_TX_READY) == UART_LSR_TX_READY) {
+ if (ch == '\n')
+ writel((unsigned int)'\r', UART_THR(g_uart));
+
+ writel((unsigned int)ch, UART_THR(g_uart));
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int uart_getc(int port, bool wait)
+{
+ do {
+ if (readl(UART_LSR(g_uart)) & UART_LSR_DR)
+ return (int)(readl(UART_RBR(g_uart)) & 0xFF);
+ } while (wait);
+
+ return -1; /* no data available */
+}
+
+int uart_pputc(int port, char c)
+{
+ return uart_putc(port, c);
+}
+
+int uart_pgetc(int port)
+{
+ return uart_getc(port, 0);
+}
+
+bool check_uart_enter(void)
+{
+ if ((int)readl(UART_RBR(g_uart)) == 13)
+ return true;
+ else
+ return false;
+}
diff --git a/src/bsp/lk/platform/mt2635/drivers/usb/mt_usb.c b/src/bsp/lk/platform/mt2635/drivers/usb/mt_usb.c
new file mode 100644
index 0000000..b744d8a
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/drivers/usb/mt_usb.c
@@ -0,0 +1,2024 @@
+/*
+ * Copyright (c) 2012 MediaTek Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <debug.h>
+#include <dev/udc.h>
+#include <err.h>
+#include <kernel/thread.h>
+#include <kernel/vm.h>
+#include <platform/interrupts.h>
+#include <platform/mt_irq.h>
+#include <platform/mt_reg_base.h>
+#include <platform/mt_usb.h>
+#include <platform/udc-common.h>
+#include <reg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#define writew(v, a) (*REG16(a) = (v))
+#define readw(a) (*REG16(a))
+
+#define USB_DOUBLE_BUF
+
+#define USB_GINTR
+
+/*
+ * to use it during early integarate usb driver just
+ * #define USB_BYPASS_SPIN_AND_THREAD_SLEEP
+ *
+*/
+#ifdef USB_BYPASS_SPIN_AND_THREAD_SLEEP
+#define usb_delay(count) \
+ do { \
+ volatile unsigned int i = count * 26; \
+ for (; i != 0; i--); \
+ } while (0)
+
+#define udelay(x) usb_delay(x)
+#define mdelay(x) usb_delay((x) * 1000)
+
+#define spin(x) usb_delay(x)
+#define thread_sleep(x) usb_delay((x) * 1000)
+#endif
+
+#define USB_DEBUG
+#ifdef USB_DEBUG
+/* DEBUG INFO Sections */
+#define DBG_USB_DUMP_DESC 0
+#define DBG_USB_DUMP_DATA 0
+#define DBG_USB_DUMP_SETUP 1
+#define DBG_USB_FIFO 0
+#define DBG_USB_GENERAL 1
+#define DBG_PHY_CALIBRATION 0
+#endif
+
+#define DBG_C(x...) dprintf(CRITICAL, x)
+#define DBG_I(x...) dprintf(INFO, x)
+#define DBG_S(x...) dprintf(SPEW, x)
+
+#if DBG_USB_GENERAL
+#define DBG_IRQ(x...) dprintf(INFO, x)
+#else
+#define DBG_IRQ(x...) do{} while(0)
+#endif
+
+/* bits used in all the endpoint status registers */
+#define EPT_TX(n) (1 << ((n) + 16))
+#define EPT_RX(n) (1 << (n))
+
+/* udc.h wrapper for usbdcore */
+
+static unsigned char usb_config_value = 0;
+EP0_STATE ep0_state = EP0_IDLE;
+int set_address = 0;
+u32 fifo_addr = FIFO_ADDR_START;
+
+#define EP0 0
+
+/* USB transfer directions */
+#define USB_DIR_IN DEVICE_WRITE /* val: 0x80 */
+#define USB_DIR_OUT DEVICE_READ /* val: 0x00 */
+
+#define EP0_MAX_PACKET_SIZE 64
+
+/* Request types */
+#define USB_TYPE_STANDARD (0x00 << 5)
+#define USB_TYPE_CLASS (0x01 << 5)
+#define USB_TYPE_VENDOR (0x02 << 5)
+#define USB_TYPE_RESERVED (0x03 << 5)
+
+/* values used in GET_STATUS requests */
+#define USB_STAT_SELFPOWERED 0x01
+
+/* USB recipients */
+#define USB_RECIP_DEVICE 0x00
+#define USB_RECIP_INTERFACE 0x01
+#define USB_RECIP_ENDPOINT 0x02
+#define USB_RECIP_OTHER 0x03
+
+/* Endpoints */
+#define USB_EP_NUM_MASK 0x0f /* in bEndpointAddress */
+#define USB_EP_DIR_MASK 0x80
+
+#define USB_TYPE_MASK 0x60
+#define USB_RECIP_MASK 0x1f
+
+#if CFG_FPGA_PLATFORM
+/* for usb phy */
+#include <platform/mt_i2c.h>
+#endif
+
+#define URB_BUF_SIZE 512
+
+struct urb {
+ struct udc_endpoint *endpoint;
+ struct udc_device *device;
+ struct setup_packet device_request;
+
+ u8 *buffer;
+ unsigned int actual_length;
+};
+
+static struct udc_endpoint *ep0in, *ep0out;
+static struct udc_request *ep0req;
+struct urb mt_ep0_urb;
+struct urb mt_tx_urb;
+struct urb mt_rx_urb;
+struct urb *ep0_urb = &mt_ep0_urb;
+struct urb *tx_urb = &mt_tx_urb;
+struct urb *rx_urb = &mt_rx_urb;
+
+/* endpoint data - mt_ep */
+struct udc_endpoint {
+ /* rx side */
+ struct urb *rcv_urb; /* active urb */
+
+ /* tx side */
+ struct urb *tx_urb; /* active urb */
+
+ /* info from hsusb */
+ struct udc_request *req;
+ unsigned int bit; /* EPT_TX/EPT_RX */
+ unsigned char num;
+ unsigned char in;
+ unsigned short maxpkt;
+ int status; /* status for error handling */
+
+ unsigned int sent; /* data already sent */
+ unsigned int last; /* data sent in last packet XXX do we need this */
+ unsigned char mode; /* double buffer */
+};
+
+/* from mt_usbtty.h */
+#define NUM_ENDPOINTS 3
+
+/* origin endpoint_array */
+struct udc_endpoint ep_list[NUM_ENDPOINTS + 1]; /* one extra for control endpoint */
+
+static int usb_online = 0;
+
+static u8 dev_address = 0;
+
+static struct udc_device *the_device;
+static struct udc_gadget *the_gadget;
+/* end from hsusb.c */
+
+/* declare ept_complete handle */
+static void handle_ept_complete(struct udc_endpoint *ept);
+
+/* use mt_typedefs.h */
+#define USBPHY_READ8(offset) readb(USB20_PHY_BASE+offset)
+#define USBPHY_WRITE8(offset, value) writeb(value, USB20_PHY_BASE+offset)
+#define USBPHY_SET8(offset, mask) USBPHY_WRITE8(offset, (USBPHY_READ8(offset)) | (mask))
+#define USBPHY_CLR8(offset, mask) USBPHY_WRITE8(offset, (USBPHY_READ8(offset)) & (~mask))
+
+#define USB11PHY_READ8(offset) readb(USB11_PHY_BASE+offset)
+#define USB11PHY_WRITE8(offset, value) writeb(value, USB11_PHY_BASE+offset)
+#define USB11PHY_SET8(offset, mask) USB11PHY_WRITE8(offset, (USB11PHY_READ8(offset)) | (mask))
+#define USB11PHY_CLR8(offset, mask) USB11PHY_WRITE8(offset, (USB11PHY_READ8(offset)) & (~mask))
+
+static void mt_usb_phy_poweron(void)
+{
+ /*
+ * swtich to USB function.
+ * (system register, force ip into usb mode).
+ */
+ USBPHY_CLR8(0x6b, 0x04);
+ USBPHY_CLR8(0x6e, 0x01);
+ USBPHY_CLR8(0x21, 0x03);
+
+ /* RG_USB20_BC11_SW_EN = 1'b0 */
+ USBPHY_SET8(0x22, 0x04);
+ USBPHY_CLR8(0x1a, 0x80);
+
+ /* RG_USB20_DP_100K_EN = 1'b0 */
+ /* RG_USB20_DP_100K_EN = 1'b0 */
+ USBPHY_CLR8(0x22, 0x03);
+
+ /*OTG enable*/
+ USBPHY_SET8(0x20, 0x10);
+ /* release force suspendm */
+ USBPHY_CLR8(0x6a, 0x04);
+
+ spin(800);
+
+ /* force enter device mode */
+ USBPHY_CLR8(0x6c, 0x10);
+ USBPHY_SET8(0x6c, 0x2E);
+ USBPHY_SET8(0x6d, 0x3E);
+
+ return;
+}
+
+static void mt_usb_phy_savecurrent(void)
+{
+ /*
+ * swtich to USB function.
+ * (system register, force ip into usb mode).
+ */
+ USBPHY_CLR8(0x6b, 0x04);
+ USBPHY_CLR8(0x6e, 0x01);
+ USBPHY_CLR8(0x21, 0x03);
+
+ /* release force suspendm */
+ USBPHY_CLR8(0x6a, 0x04);
+ USBPHY_SET8(0x68, 0x04);
+ /* RG_DPPULLDOWN./RG_DMPULLDOWN. */
+ USBPHY_SET8(0x68, 0xc0);
+ /* RG_XCVRSEL[1:0] = 2'b01 */
+ USBPHY_CLR8(0x68, 0x30);
+ USBPHY_SET8(0x68, 0x10);
+ /* RG_TERMSEL = 1'b1 */
+ USBPHY_SET8(0x68, 0x04);
+ /* RG_DATAIN[3:0] = 4'b0000 */
+ USBPHY_CLR8(0x69, 0x3c);
+
+ /*
+ * force_dp_pulldown, force_dm_pulldown,
+ * force_xcversel, force_termsel.
+ */
+ USBPHY_SET8(0x6a, 0xba);
+
+ /* RG_USB20_BC11_SW_EN = 1'b0 */
+ USBPHY_CLR8(0x1a, 0x80);
+ /* RG_USB20_OTG_VBUSSCMP_EN = 1'b0 */
+ USBPHY_CLR8(0x1a, 0x10);
+
+ spin(800);
+
+ USBPHY_CLR8(0x6a, 0x04);
+ /* rg_usb20_pll_stable = 1 */
+ //USBPHY_SET8(0x63, 0x02);
+
+ spin(1);
+
+ /* force suspendm = 1 */
+ //USBPHY_SET8(0x6a, 0x04);
+
+ //udelay(1);
+
+ return;
+}
+
+static void mt_usb_phy_recover(void)
+{
+
+ /* clean PUPD_BIST_EN */
+ /* PUPD_BIST_EN = 1'b0 */
+ /* PMIC will use it to detect charger type */
+ USBPHY_CLR8(0x1d, 0x10);
+
+ /* force_uart_en = 1'b0 */
+ USBPHY_CLR8(0x6b, 0x04);
+ /* RG_UART_EN = 1'b0 */
+ USBPHY_CLR8(0x6e, 0x01);
+ /* force_uart_en = 1'b0 */
+ USBPHY_CLR8(0x6a, 0x04);
+
+ USBPHY_CLR8(0x21, 0x03);
+ USBPHY_CLR8(0x68, 0xf4);
+
+ /* RG_DATAIN[3:0] = 4'b0000 */
+ USBPHY_CLR8(0x69, 0x3c);
+
+ USBPHY_CLR8(0x6a, 0xba);
+
+ /* RG_USB20_BC11_SW_EN = 1'b0 */
+ USBPHY_CLR8(0x1a, 0x80);
+ /* RG_USB20_OTG_VBUSSCMP_EN = 1'b1 */
+ USBPHY_SET8(0x1a, 0x10);
+
+ //HQA adjustment
+ USBPHY_CLR8(0x18, 0x08);
+ USBPHY_SET8(0x18, 0x06);
+ spin(800);
+
+ /* force enter device mode */
+ //USBPHY_CLR8(0x6c, 0x10);
+ //USBPHY_SET8(0x6c, 0x2E);
+ //USBPHY_SET8(0x6d, 0x3E);
+}
+
+static void Charger_Detect_Init(void)
+{
+ /* RG_USB20_BC11_SW_EN = 1'b1 */
+ USBPHY_SET8(0x1a, 0x80);
+}
+
+static void Charger_Detect_Release(void)
+{
+ /* RG_USB20_BC11_SW_EN = 1'b0 */
+ USBPHY_CLR8(0x1a, 0x80);
+}
+
+static void board_usb_init(void)
+{
+ mt_usb_phy_poweron();
+}
+
+struct udc_descriptor {
+ struct udc_descriptor *next;
+ unsigned short tag; /* ((TYPE << 8) | NUM) */
+ unsigned short len; /* total length */
+ unsigned char data[0];
+};
+
+#if DBG_USB_DUMP_SETUP
+static void dump_setup_packet(const char *str, struct setup_packet *sp)
+{
+ DBG_I("\n");
+ DBG_I(str);
+ DBG_I(" bmRequestType = %x\n", sp->type);
+ DBG_I(" bRequest = %x\n", sp->request);
+ DBG_I(" wValue = %x\n", sp->value);
+ DBG_I(" wIndex = %x\n", sp->index);
+ DBG_I(" wLength = %x\n", sp->length);
+}
+#else
+static void dump_setup_packet(const char *str, struct setup_packet *sp) {}
+#endif
+
+static void copy_desc(struct urb *urb, void *data, int length)
+{
+
+#if DBG_USB_FIFO
+ DBG_I("%s: urb: %x, data %x, length: %d, actual_length: %d\n",
+ __func__, urb->buffer, data, length, urb->actual_length);
+#endif
+
+ //memcpy(urb->buffer + urb->actual_length, data, length);
+ memcpy(urb->buffer, data, length);
+ //urb->actual_length += length;
+ urb->actual_length = length;
+#if DBG_USB_FIFO
+ DBG_I("%s: urb: %x, data %x, length: %d, actual_length: %d\n",
+ __func__, urb, data, length, urb->actual_length);
+#endif
+}
+
+
+static struct udc_descriptor *udc_descriptor_alloc(unsigned type, unsigned num,
+ unsigned len)
+{
+ struct udc_descriptor *desc;
+ if ((len > 255) || (len < 2) || (num > 255) || (type > 255))
+ return 0;
+
+ if (!(desc = malloc(sizeof(struct udc_descriptor) + len)))
+ return 0;
+
+ desc->next = 0;
+ desc->tag = (type << 8) | num;
+ desc->len = len;
+ desc->data[0] = len;
+ desc->data[1] = type;
+
+ return desc;
+}
+
+static struct udc_descriptor *desc_list = 0;
+static unsigned next_string_id = 1;
+
+static void udc_descriptor_register(struct udc_descriptor *desc)
+{
+ desc->next = desc_list;
+ desc_list = desc;
+}
+
+static unsigned udc_string_desc_alloc(const char *str)
+{
+ unsigned len;
+ struct udc_descriptor *desc;
+ unsigned char *data;
+
+ if (next_string_id > 255)
+ return 0;
+
+ if (!str)
+ return 0;
+
+ len = strlen(str);
+ desc = udc_descriptor_alloc(TYPE_STRING, next_string_id, len * 2 + 2);
+ if (!desc)
+ return 0;
+ next_string_id++;
+
+ /* expand ascii string to utf16 */
+ data = desc->data + 2;
+ while (len-- > 0) {
+ *data++ = *str++;
+ *data++ = 0;
+ }
+
+ udc_descriptor_register(desc);
+ return desc->tag & 0xff;
+}
+
+static int mt_read_fifo(struct udc_endpoint *endpoint)
+{
+
+ struct urb *urb = endpoint->rcv_urb;
+ int len = 0, count = 0;
+ int ep_num = endpoint->num;
+ int index;
+ unsigned char *cp;
+ u32 *wp;
+#if !CFG_FPGA_PLATFORM
+ u16 dma_cntl = 0;
+#endif
+
+ if (ep_num == EP0)
+ urb = ep0_urb;
+
+ if (urb) {
+ index = readb(INDEX);
+ writeb(ep_num, INDEX);
+
+ cp = (u8 *) (urb->buffer + urb->actual_length);
+ wp = (u32 *) cp;
+#if DBG_USB_FIFO
+ DBG_I("%s: ep_num: %d, urb: %x, urb->buffer: %x, urb->actual_length = %d\n",
+ __func__, ep_num, urb, urb->buffer, urb->actual_length);
+#endif
+
+ count = len = readw(IECSR + RXCOUNT);
+ if (ep_num != 0) {
+#if DBG_USB_FIFO
+ DBG_I("%s: ep_num: %d count = %d\n",
+ __func__, ep_num, count);
+#endif
+ }
+
+ /* FIX: DMA has problem write now */
+
+#if !CFG_FPGA_PLATFORM
+ arch_clean_invalidate_cache_range((addr_t) cp, count);
+
+ if (ep_num != 0) {
+#if WITH_KERNEL_VM
+ paddr_t wp_dma_addr = kvaddr_to_paddr(wp);
+#else
+ paddr_t wp_dma_addr = (paddr_t)wp;
+#endif
+
+ if (wp_dma_addr >> 32)
+ dprintf(CRITICAL, "[USB] WARN: 64bit physical address!\n");
+ writel((u32)wp_dma_addr, USB_DMA_ADDR (ep_num));
+ writel(count, USB_DMA_COUNT (ep_num));
+ dma_cntl =
+ USB_DMA_BURST_MODE_3 | (ep_num << USB_DMA_ENDPNT_OFFSET) |
+ USB_DMA_EN;
+ writew(dma_cntl, USB_DMA_CNTL (ep_num));
+ while (readw(USB_DMA_CNTL (ep_num)) & USB_DMA_EN);
+ } else
+
+#endif
+ {
+ while (len > 0) {
+ if (len >= 4) {
+ *wp++ = readl(FIFO(ep_num));
+ cp = (unsigned char *) wp;
+ //DBG_I("USB READ FIFO: wp = %lu, cp = %lu\n", wp, cp);
+ len -= 4;
+ } else {
+ *cp++ = readb(FIFO(ep_num));
+ //DBG_I("USB READ FIFO: wp = %lu, cp = %lu\n", wp, cp);
+ len--;
+ }
+ }
+ }
+
+#if DBG_USB_DUMP_DATA
+ if (ep_num != 0) {
+ DBG_I("%s: &urb->buffer: %x\n", __func__, urb->buffer);
+ DBG_I("[USB] dump data:\n");
+ hexdump8(urb->buffer, count);
+ }
+#endif
+
+ urb->actual_length += count;
+
+ writeb(index, INDEX);
+ }
+
+ return count;
+}
+
+static int mt_write_fifo(struct udc_endpoint *endpoint)
+{
+ struct urb *urb = endpoint->tx_urb;
+ int last = 0, count = 0;
+ int ep_num = endpoint->num;
+ int index;
+ unsigned char *cp = NULL;
+#ifdef USB_TX_DMA_MODE_0
+ u32 *wp;
+ u16 dma_cntl = 0;
+#endif
+
+ if (ep_num == EP0)
+ urb = ep0_urb;
+
+ if (urb) {
+ index = readb(INDEX);
+ writeb(ep_num, INDEX);
+
+#if DBG_USB_DUMP_DESC
+ DBG_I("%s: dump desc\n", __func__);
+ hexdump8(urb->buffer, urb->actual_length);
+#endif
+
+
+#if DBG_USB_FIFO
+ DBG_I("%s: ep_num: %d urb: %x, actual_length: %d\n",
+ __func__, ep_num, urb, urb->actual_length);
+ DBG_I("%s: sent: %d, tx_pkt_size: %d\n", __func__, endpoint->sent, endpoint->maxpkt);
+#endif
+
+ count = last = MIN (urb->actual_length - endpoint->sent, endpoint->maxpkt);
+ //count = last = urb->actual_length;
+
+#if DBG_USB_FIFO
+ DBG_I("%s: count: %d\n", __func__, count);
+ DBG_I("%s: urb->actual_length = %d\n", __func__, urb->actual_length);
+ DBG_I("%s: endpoint->sent = %d\n", __func__, endpoint->sent);
+#endif
+
+ if (count < 0) {
+ DBG_C("%s: something is wrong, count < 0", __func__);
+ }
+
+ if (count) {
+ cp = urb->buffer + endpoint->sent;
+#ifdef USB_TX_DMA_MODE_0
+ wp = (u32 *)cp;
+
+ arch_clean_invalidate_cache_range((addr_t) cp, count);
+
+ if (ep_num != 0) {
+ writel(wp, USB_DMA_ADDR(ep_num));
+ writel(count, USB_DMA_COUNT(ep_num));
+ dma_cntl =
+ USB_DMA_BURST_MODE_3 | (ep_num << USB_DMA_ENDPNT_OFFSET) |
+ USB_DMA_EN | USB_DMA_DIR;
+ writew(dma_cntl, USB_DMA_CNTL(ep_num));
+ while (readw(USB_DMA_CNTL (ep_num)) & USB_DMA_EN);
+ } else
+#endif
+ {
+ //DBG("---------write USB fifo---------\n");
+ while (count > 0) {
+ //hexdump8(cp, 1);
+ writeb(*cp, FIFO (ep_num));
+ cp++;
+ count--;
+ }
+ }
+ }
+
+ endpoint->last = last;
+ endpoint->sent += last;
+
+ writeb(index, INDEX);
+ }
+
+ return last;
+}
+
+static struct udc_endpoint *mt_find_ep(int ep_num, u8 dir)
+{
+ int i;
+ u8 in = 0;
+
+ /* convert dir to in */
+ if (dir == USB_DIR_IN) /* dir == USB_DIR_IN */
+ in = 1;
+
+ /* for (i = 0; i < udc_device->max_endpoints; i++) */
+ /* for (i = 0; i < the_gadget->ifc_endpoints; i++) */
+ for (i = 0; i < MT_EP_NUM; i++) {
+ if ((ep_list[i].num == ep_num) && (ep_list[i].in == in)) {
+#if DBG_USB_GENERAL
+ DBG_I("%s: find ep!\n", __func__);
+#endif
+ return &ep_list[i];
+ }
+ }
+ return NULL;
+}
+
+static void mt_udc_flush_fifo(u8 ep_num, u8 dir)
+{
+ u16 tmpReg16;
+ u8 index;
+ struct udc_endpoint *endpoint;
+
+ index = readb(INDEX);
+ writeb(ep_num, INDEX);
+
+ if (ep_num == 0) {
+ tmpReg16 = readw(IECSR + CSR0);
+ tmpReg16 |= EP0_FLUSH_FIFO;
+ writew(tmpReg16, IECSR + CSR0);
+ writew(tmpReg16, IECSR + CSR0);
+ } else {
+ endpoint = mt_find_ep(ep_num, dir);
+ if (endpoint->in == 0) { /* USB_DIR_OUT */
+ tmpReg16 = readw(IECSR + RXCSR);
+ tmpReg16 |= EPX_RX_FLUSHFIFO;
+ writew(tmpReg16, IECSR + RXCSR);
+ writew(tmpReg16, IECSR + RXCSR);
+ } else {
+ tmpReg16 = readw(IECSR + TXCSR);
+ tmpReg16 |= EPX_TX_FLUSHFIFO;
+ writew(tmpReg16, IECSR + TXCSR);
+ writew(tmpReg16, IECSR + TXCSR);
+ }
+ }
+
+ /* recover index register */
+ writeb(index, INDEX);
+}
+
+/* the endpoint does not support the received command, stall it!! */
+static void udc_stall_ep(unsigned int ep_num, u8 dir)
+{
+ struct udc_endpoint *endpoint = mt_find_ep(ep_num, dir);
+ u8 index;
+ u16 csr;
+
+ DBG_C("[USB] %s\n", __func__);
+
+ index = readb(INDEX);
+ writeb(ep_num, INDEX);
+
+ if (ep_num == 0) {
+ csr = readw(IECSR + CSR0);
+ csr |= EP0_SENDSTALL;
+ writew(csr, IECSR + CSR0);
+ mt_udc_flush_fifo(ep_num, USB_DIR_OUT);
+ } else {
+ if (endpoint->in == 0) { /* USB_DIR_OUT */
+ csr = readb(IECSR + RXCSR);
+ csr |= EPX_RX_SENDSTALL;
+ writew(csr, IECSR + RXCSR);
+ mt_udc_flush_fifo(ep_num, USB_DIR_OUT);
+ } else {
+ csr = readb(IECSR + TXCSR);
+ csr |= EPX_TX_SENDSTALL;
+ writew(csr, IECSR + TXCSR);
+ mt_udc_flush_fifo(ep_num, USB_DIR_IN);
+ }
+ }
+ //mt_udc_flush_fifo (ep_num, USB_DIR_OUT);
+ //mt_udc_flush_fifo (ep_num, USB_DIR_IN);
+
+ ep0_state = EP0_IDLE;
+
+ writeb(index, INDEX);
+
+ return;
+}
+
+/*
+ * If abnormal DATA transfer happened, like USB unplugged,
+ * we cannot fix this after mt_udc_reset().
+ * Because sometimes there will come reset twice.
+ */
+static void mt_udc_suspend(void)
+{
+ /* handle abnormal DATA transfer if we had any */
+ struct udc_endpoint *endpoint;
+ int i;
+
+ /* deal with flags */
+ usb_online = 0;
+ usb_config_value = 0;
+ the_gadget->notify(the_gadget, UDC_EVENT_OFFLINE);
+
+ /* error out any pending reqs */
+ for (i = 1; i < MT_EP_NUM; i++) {
+ /* ensure that ept_complete considers
+ * this to be an error state
+ */
+#if DBG_USB_GENERAL
+ DBG_I("%s: ep: %i, in: %s, req: %p\n",
+ __func__, ep_list[i].num, ep_list[i].in ? "IN" : "OUT", ep_list[i].req);
+#endif
+ if ((ep_list[i].req && (ep_list[i].in == 0)) || /* USB_DIR_OUT */
+ (ep_list[i].req && (ep_list[i].in == 1))) { /* USB_DIR_IN */
+ ep_list[i].status = -1; /* HALT */
+ endpoint = &ep_list[i];
+ handle_ept_complete(endpoint);
+ }
+ }
+}
+
+static void mt_udc_rxtxmap_recover(void)
+{
+ int i;
+
+ for (i = 1; i < MT_EP_NUM; i++) {
+ if (ep_list[i].num != 0) { /* allocated */
+
+ writeb(ep_list[i].num, INDEX);
+
+ if (ep_list[i].in == 0) /* USB_DIR_OUT */
+ writel(ep_list[i].maxpkt, (IECSR + RXMAP));
+ else
+ writel(ep_list[i].maxpkt, (IECSR + TXMAP));
+ }
+ }
+}
+
+static void mt_udc_reset(void)
+{
+
+ /* MUSBHDRC automatically does the following when reset signal is detected */
+ /* 1. Sets FAddr to 0
+ * 2. Sets Index to 0
+ * 3. Flush all endpoint FIFOs
+ * 4. Clears all control/status registers
+ * 5. Enables all endpoint interrupts
+ * 6. Generates a Rest interrupt
+ */
+
+ DBG_I("[USB] %s\n", __func__);
+
+ /* disable all endpoint interrupts */
+ writeb(0, INTRTXE);
+ writeb(0, INTRRXE);
+ writeb(0, INTRUSBE);
+
+ writew(SWRST_SWRST | SWRST_DISUSBRESET, SWRST);
+
+ dev_address = 0;
+
+ /* flush FIFO */
+ mt_udc_flush_fifo(0, USB_DIR_OUT);
+ mt_udc_flush_fifo(1, USB_DIR_OUT);
+ mt_udc_flush_fifo(1, USB_DIR_IN);
+ //mt_udc_flush_fifo (2, USB_DIR_IN);
+
+ /* detect USB speed */
+ if (readb(POWER) & PWR_HS_MODE) {
+ DBG_I("[USB] USB High Speed\n");
+// enable_highspeed();
+ } else {
+ DBG_I("[USB] USB Full Speed\n");
+ }
+
+ /* restore RXMAP and TXMAP if the endpoint has been configured */
+ mt_udc_rxtxmap_recover();
+
+ /* enable suspend */
+ writeb((INTRUSB_SUSPEND | INTRUSB_RESUME | INTRUSB_RESET |INTRUSB_DISCON), INTRUSBE);
+
+}
+
+static void mt_udc_ep0_write(void)
+{
+
+ struct udc_endpoint *endpoint = &ep_list[EP0];
+ int count = 0;
+ u16 csr0 = 0;
+ u8 index = 0;
+
+ index = readb(INDEX);
+ writeb(0, INDEX);
+
+ csr0 = readw(IECSR + CSR0);
+ if (csr0 & EP0_TXPKTRDY) {
+ DBG_I("mt_udc_ep0_write: ep0 is not ready to be written\n");
+ return;
+ }
+
+ count = mt_write_fifo(endpoint);
+
+#if DBG_USB_GENERAL
+ DBG_I("%s: count = %d\n", __func__, count);
+#endif
+
+ if (count < EP0_MAX_PACKET_SIZE) {
+ /* last packet */
+ csr0 |= (EP0_TXPKTRDY | EP0_DATAEND);
+ ep0_urb->actual_length = 0;
+ endpoint->sent = 0;
+ ep0_state = EP0_IDLE;
+ } else {
+ /* more packets are waiting to be transferred */
+ csr0 |= EP0_TXPKTRDY;
+ }
+
+ writew(csr0, IECSR + CSR0);
+ writeb(index, INDEX);
+
+ return;
+}
+
+static void mt_udc_ep0_read(void)
+{
+
+ struct udc_endpoint *endpoint = &ep_list[EP0];
+ int count = 0;
+ u16 csr0 = 0;
+ u8 index = 0;
+
+ index = readb(INDEX);
+ writeb(EP0, INDEX);
+
+ csr0 = readw(IECSR + CSR0);
+
+ /* erroneous ep0 interrupt */
+ if (!(csr0 & EP0_RXPKTRDY)) {
+ return;
+ }
+
+ count = mt_read_fifo(endpoint);
+
+ if (count <= EP0_MAX_PACKET_SIZE) {
+ /* last packet */
+ csr0 |= (EP0_SERVICED_RXPKTRDY | EP0_DATAEND);
+ ep0_state = EP0_IDLE;
+ } else {
+ /* more packets are waiting to be transferred */
+ csr0 |= EP0_SERVICED_RXPKTRDY;
+ }
+
+ writew(csr0, IECSR + CSR0);
+
+ writeb(index, INDEX);
+
+ return;
+}
+
+static int ep0_standard_setup(struct urb *urb)
+{
+ struct setup_packet *request;
+ struct udc_descriptor *desc;
+ //struct udc_device *device;
+ u8 *cp = urb->buffer;
+#if 0
+ if (!urb || !urb->device) {
+ DBG ("\n!urb || !urb->device\n");
+ return false;
+ }
+#endif
+
+ request = &urb->device_request;
+ //device = urb->device;
+
+ dump_setup_packet("[USB] Device Request\n", request);
+
+ if ((request->type & USB_TYPE_MASK) != 0) {
+ return false; /* Class-specific requests are handled elsewhere */
+ }
+
+ /* handle all requests that return data (direction bit set on bm RequestType) */
+ if ((request->type & USB_EP_DIR_MASK)) {
+ /* send the descriptor */
+ ep0_state = EP0_TX;
+
+ switch (request->request) {
+ /* data stage: from device to host */
+ case GET_STATUS:
+#if DBG_USB_GENERAL
+ DBG_I("GET_STATUS\n");
+#endif
+ urb->actual_length = 2;
+ cp[0] = cp[1] = 0;
+ switch (request->type & USB_RECIP_MASK) {
+ case USB_RECIP_DEVICE:
+ cp[0] = USB_STAT_SELFPOWERED;
+ break;
+ case USB_RECIP_OTHER:
+ urb->actual_length = 0;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+
+ case GET_DESCRIPTOR:
+#if DBG_USB_GENERAL
+ DBG_I("GET_DESCRIPTOR\n");
+#endif
+ /* usb_highspeed? */
+
+ for (desc = desc_list; desc; desc = desc->next) {
+#if DBG_USB_DUMP_DESC
+ DBG_I("desc->tag: %x: request->value: %x\n", desc->tag, request->value);
+#endif
+ if (desc->tag == request->value) {
+
+#if DBG_USB_DUMP_DESC
+ DBG_I("Find packet!\n");
+#endif
+ unsigned len = desc->len;
+ if (len > request->length)
+ len = request->length;
+
+#if DBG_USB_GENERAL
+ DBG_I("%s: urb: %p, cp: %p\n", __func__, urb, cp);
+#endif
+ copy_desc(urb, desc->data, len);
+ return 0;
+ }
+ }
+ /* descriptor lookup failed */
+ return false;
+
+ case GET_CONFIGURATION:
+#if DBG_USB_GENERAL
+ DBG_I("GET_CONFIGURATION\n");
+ DBG_I("USB_EP_DIR_MASK\n");
+#endif
+#if 0
+ urb->actual_length = 1;
+ ((char *) urb->buffer)[0] = device->configuration;
+#endif
+// return 0;
+ break;
+
+ case GET_INTERFACE:
+#if DBG_USB_GENERAL
+ DBG_I("GET_INTERFACE\n");
+#endif
+
+#if 0
+ urb->actual_length = 1;
+ ((char *) urb->buffer)[0] = device->alternate;
+ return 0;
+#endif
+ break;
+ default:
+ DBG_C("Unsupported command with TX data stage\n");
+ break;
+ }
+ } else {
+
+ switch (request->request) {
+
+ case SET_ADDRESS:
+#if DBG_USB_GENERAL
+ DBG_I("SET_ADDRESS\n");
+#endif
+
+ dev_address = (request->value);
+ set_address = 1;
+ return 0;
+
+ case SET_CONFIGURATION:
+#if DBG_USB_GENERAL
+ DBG_I("SET_CONFIGURATION\n");
+#endif
+#if 0
+ device->configuration = (request->value) & 0x7f;
+ device->interface = device->alternate = 0;
+#endif
+ if (request->value == 1) {
+ usb_config_value = 1;
+ the_gadget->notify(the_gadget, UDC_EVENT_ONLINE);
+ } else {
+ usb_config_value = 0;
+ the_gadget->notify(the_gadget, UDC_EVENT_OFFLINE);
+ }
+
+ usb_online = request->value ? 1 : 0;
+ //usb_status(request->value ? 1 : 0, usb_highspeed);
+
+ return 0;
+
+ default:
+ DBG_C("Unsupported command with RX data stage\n");
+ break;
+
+ }
+ }
+ return false;
+}
+
+static void mt_udc_ep0_setup(void)
+{
+ struct udc_endpoint *endpoint = &ep_list[0];
+ u8 index;
+ u8 stall = 0;
+ u16 csr0;
+ struct setup_packet *request;
+
+#if DBG_USB_FIFO
+ u16 count;
+#endif
+
+ index = readb(INDEX);
+ writeb(0, INDEX);
+ /* Read control status register for endpiont 0 */
+ csr0 = readw(IECSR + CSR0);
+
+ /* check whether RxPktRdy is set? */
+ if (!(csr0 & EP0_RXPKTRDY))
+ return;
+
+ /* unload fifo */
+ ep0_urb->actual_length = 0;
+
+#ifndef USB_DEBUG
+ mt_read_fifo(endpoint);
+#else
+#if DBG_USB_FIFO
+ count = mt_read_fifo(endpoint);
+ DBG_I("%s: mt_read_fifo count = %d\n", __func__, count);
+#else
+ mt_read_fifo(endpoint);
+#endif
+#endif
+ /* decode command */
+ request = &ep0_urb->device_request;
+ memcpy(request, ep0_urb->buffer, sizeof(struct setup_packet));
+
+ if (((request->type) & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+#if DBG_USB_GENERAL
+ DBG_I("[USB] Standard Request\n");
+#endif
+ stall = ep0_standard_setup(ep0_urb);
+ if (stall) {
+ dump_setup_packet("[USB] STANDARD REQUEST NOT SUPPORTED\n", request);
+ }
+ } else if (((request->type) & USB_TYPE_MASK) == USB_TYPE_CLASS) {
+#if DBG_USB_GENERAL
+ DBG_I("[USB] Class-Specific Request\n");
+#endif
+// stall = ep0_class_setup(ep0_urb);
+ /* Mark dead code, reported by Coverity. */
+ //if (stall) {
+ // dump_setup_packet("[USB] CLASS REQUEST NOT SUPPORTED\n", request);
+ //}
+ } else if (((request->type) & USB_TYPE_MASK) == USB_TYPE_VENDOR) {
+#if DBG_USB_GENERAL
+ DBG_I("[USB] Vendor-Specific Request\n");
+ /* do nothing now */
+ DBG_I("[USB] ALL VENDOR-SPECIFIC REQUESTS ARE NOT SUPPORTED!!\n");
+#endif
+ }
+
+ if (stall) {
+ /* the received command is not supported */
+ udc_stall_ep(0, USB_DIR_OUT);
+ return;
+ }
+
+ switch (ep0_state) {
+ case EP0_TX:
+ /* data stage: from device to host */
+#if DBG_USB_GENERAL
+ DBG_I("%s: EP0_TX\n", __func__);
+#endif
+ csr0 = readw(IECSR + CSR0);
+ csr0 |= (EP0_SERVICED_RXPKTRDY);
+ writew(csr0, IECSR + CSR0);
+
+ mt_udc_ep0_write();
+
+ break;
+ case EP0_RX:
+ /* data stage: from host to device */
+#if DBG_USB_GENERAL
+ DBG_I("%s: EP0_RX\n", __func__);
+#endif
+ csr0 = readw(IECSR + CSR0);
+ csr0 |= (EP0_SERVICED_RXPKTRDY);
+ writew(csr0, IECSR + CSR0);
+
+ break;
+ case EP0_IDLE:
+ /* no data stage */
+#if DBG_USB_GENERAL
+ DBG_I("%s: EP0_IDLE\n", __func__);
+#endif
+ csr0 = readw(IECSR + CSR0);
+ csr0 |= (EP0_SERVICED_RXPKTRDY | EP0_DATAEND);
+
+ writew(csr0, IECSR + CSR0);
+ writew(csr0, IECSR + CSR0);
+
+ break;
+ default:
+ break;
+ }
+
+ writeb(index, INDEX);
+ return;
+
+}
+
+static void mt_udc_ep0_handler(void)
+{
+
+ u16 csr0;
+ u8 index = 0;
+
+ index = readb(INDEX);
+ writeb(0, INDEX);
+
+ csr0 = readw(IECSR + CSR0);
+
+ if (csr0 & EP0_SENTSTALL) {
+#if DBG_USB_GENERAL
+ DBG_I("USB: [EP0] SENTSTALL\n");
+#endif
+ /* needs implementation for exception handling here */
+ ep0_state = EP0_IDLE;
+ }
+
+ if (csr0 & EP0_SETUPEND) {
+#if DBG_USB_GENERAL
+ DBG_I("USB: [EP0] SETUPEND\n");
+#endif
+ csr0 |= EP0_SERVICE_SETUP_END;
+ writew(csr0, IECSR + CSR0);
+
+ ep0_state = EP0_IDLE;
+ }
+
+ switch (ep0_state) {
+ case EP0_IDLE:
+#if DBG_USB_GENERAL
+ DBG_I("%s: EP0_IDLE\n", __func__);
+#endif
+ if (set_address) {
+ writeb(dev_address, FADDR);
+ set_address = 0;
+ }
+ mt_udc_ep0_setup();
+ break;
+ case EP0_TX:
+#if DBG_USB_GENERAL
+ DBG_I("%s: EP0_TX\n", __func__);
+#endif
+ mt_udc_ep0_write();
+ break;
+ case EP0_RX:
+#if DBG_USB_GENERAL
+ DBG_I("%s: EP0_RX\n", __func__);
+#endif
+ mt_udc_ep0_read();
+ break;
+ default:
+ break;
+ }
+
+ writeb(index, INDEX);
+
+ return;
+}
+
+
+/*
+ * udc_setup_ep - setup endpoint
+ *
+ * Associate a physical endpoint with endpoint_instance and initialize FIFO
+ */
+static void mt_setup_ep(unsigned int ep, struct udc_endpoint *endpoint)
+{
+ u8 index;
+ u16 csr;
+ u16 csr0;
+ u16 max_packet_size;
+ u8 fifosz = 0;
+
+ /* EP table records in bits hence bit 1 is ep0 */
+ index = readb(INDEX);
+ writeb(ep, INDEX);
+
+ if (ep == EP0) {
+ /* Read control status register for endpiont 0 */
+ csr0 = readw(IECSR + CSR0);
+
+ /* check whether RxPktRdy is set? */
+ if (!(csr0 & EP0_RXPKTRDY))
+ return;
+ }
+
+ /* Configure endpoint fifo */
+ /* Set fifo address, fifo size, and fifo max packet size */
+#if DBG_USB_GENERAL
+ DBG_I("%s: endpoint->in: %d, maxpkt: %d\n",
+ __func__, endpoint->in, endpoint->maxpkt);
+#endif
+ if (endpoint->in == 0) { /* USB_DIR_OUT */
+ /* Clear data toggle to 0 */
+ csr = readw(IECSR + RXCSR);
+ /* pangyen 20090911 */
+ csr |= EPX_RX_CLRDATATOG | EPX_RX_FLUSHFIFO;
+ writew(csr, IECSR + RXCSR);
+ /* Set fifo address */
+ writew(fifo_addr >> 3, RXFIFOADD);
+ /* Set fifo max packet size */
+ max_packet_size = endpoint->maxpkt;
+ writew(max_packet_size, IECSR + RXMAP);
+ /* Set fifo size (double buffering is currently not enabled) */
+ switch (max_packet_size) {
+ case 8:
+ case 16:
+ case 32:
+ case 64:
+ case 128:
+ case 256:
+ case 512:
+ case 1024:
+ case 2048:
+ if (endpoint->mode == DOUBLE_BUF)
+ fifosz |= FIFOSZ_DPB;
+ fifosz |= __builtin_ffs(max_packet_size >> 4);
+ writeb(fifosz, RXFIFOSZ);
+ break;
+ case 4096:
+ fifosz |= __builtin_ffs(max_packet_size >> 4);
+ writeb(fifosz, RXFIFOSZ);
+ break;
+ case 3072:
+ fifosz = __builtin_ffs(4096 >> 4);
+ writeb(fifosz, RXFIFOSZ);
+ break;
+
+ default:
+ DBG_C("The max_packet_size for ep %d is not supported\n", ep);
+ }
+ } else {
+ /* Clear data toggle to 0 */
+ csr = readw(IECSR + TXCSR);
+ /* pangyen 20090911 */
+ csr |= EPX_TX_CLRDATATOG | EPX_TX_FLUSHFIFO;
+ writew(csr, IECSR + TXCSR);
+ /* Set fifo address */
+ writew(fifo_addr >> 3, TXFIFOADD);
+ /* Set fifo max packet size */
+ max_packet_size = endpoint->maxpkt;
+ writew(max_packet_size, IECSR + TXMAP);
+ /* Set fifo size(double buffering is currently not enabled) */
+ switch (max_packet_size) {
+ case 8:
+ case 16:
+ case 32:
+ case 64:
+ case 128:
+ case 256:
+ case 512:
+ case 1024:
+ case 2048:
+ if (endpoint->mode == DOUBLE_BUF)
+ fifosz |= FIFOSZ_DPB;
+ /* Add for resolve issue reported by Coverity */
+ fifosz |= __builtin_ffs(max_packet_size >> 4);
+ writeb(fifosz, TXFIFOSZ);
+ break;
+ case 4096:
+ fifosz |= __builtin_ffs(max_packet_size >> 4);
+ writeb(fifosz, TXFIFOSZ);
+ break;
+ case 3072:
+ fifosz = __builtin_ffs(4096 >> 4);
+ writeb(fifosz, TXFIFOSZ);
+ break;
+
+ default:
+ DBG_C("The max_packet_size for ep %d is not supported\n", ep);
+ }
+ }
+
+ if (endpoint->mode == DOUBLE_BUF)
+ fifo_addr += (max_packet_size << 1);
+ else
+ fifo_addr += max_packet_size;
+
+ /* recover INDEX register */
+ writeb(index, INDEX);
+}
+
+struct udc_endpoint *_udc_endpoint_alloc(unsigned char num, unsigned char in,
+ unsigned short max_pkt)
+{
+ int i;
+
+ /*
+ * find an unused slot in ep_list from EP1 to MAX_EP
+ * for example, EP1 will use 2 slot one for IN and the other for OUT
+ */
+ if (num != EP0) {
+ for (i = 1; i < MT_EP_NUM; i++) {
+ if (ep_list[i].num == 0) /* usable */
+ break;
+ }
+
+ if (i == MT_EP_NUM) /* ep has been exhausted. */
+ return NULL;
+
+ if (in) { /* usb EP1 tx */
+ ep_list[i].tx_urb = tx_urb;
+#ifdef USB_DOUBLE_BUF
+ ep_list[i].mode = DOUBLE_BUF;
+#endif
+ } else { /* usb EP1 rx */
+ ep_list[i].rcv_urb = rx_urb;
+#ifdef USB_DOUBLE_BUF
+ ep_list[i].mode = DOUBLE_BUF;
+#endif
+ }
+ } else {
+ i = EP0; /* EP0 */
+ }
+
+ ep_list[i].maxpkt = max_pkt;
+ ep_list[i].num = num;
+ ep_list[i].in = in;
+ ep_list[i].req = NULL;
+
+ /* store EPT_TX/RX info */
+ if (ep_list[i].in) {
+ ep_list[i].bit = EPT_TX(num);
+ } else {
+ ep_list[i].bit = EPT_RX(num);
+ }
+
+ /* write parameters to this ep (write to hardware) */
+ mt_setup_ep(num, &ep_list[i]);
+
+ DBG_I("[USB] ept%d %s @%p/%p max=%d bit=%x\n",
+ num, in ? "in" : "out", &ep_list[i], &ep_list, max_pkt, ep_list[i].bit);
+
+ return &ep_list[i];
+}
+
+#define SETUP(type,request) (((type) << 8) | (request))
+
+static unsigned long ept_alloc_table = EPT_TX(0) | EPT_RX(0);
+
+struct udc_endpoint *udc_endpoint_alloc(unsigned type, unsigned maxpkt)
+{
+ struct udc_endpoint *ept;
+ unsigned n;
+ unsigned in;
+
+ if (type == UDC_BULK_IN) {
+ in = 1;
+ } else if (type == UDC_BULK_OUT) {
+ in = 0;
+ } else {
+ return 0;
+ }
+
+ /* udc_endpoint_alloc is used for EPx except EP0 */
+ for (n = 1; n < 16; n++) {
+ unsigned long bit = in ? EPT_TX(n) : EPT_RX(n);
+ if (ept_alloc_table & bit)
+ continue;
+ ept = _udc_endpoint_alloc(n, in, maxpkt);
+ if (ept)
+ ept_alloc_table |= bit;
+ return ept;
+ }
+
+ return 0;
+}
+
+static void handle_ept_complete(struct udc_endpoint *ept)
+{
+ unsigned int actual;
+ int status;
+ struct udc_request *req;
+
+ req = ept->req;
+ if (req) {
+#if DBG_USB_GENERAL
+ DBG_I("%s: req: %p: req->length: %d: status: %d\n", __func__, req, req->length, ept->status);
+#endif
+ /* release this request for processing next */
+ ept->req = NULL;
+
+ if (ept->status == -1) {
+ actual = 0;
+ status = -1;
+ DBG_C("%s: EP%d/%s FAIL status: %x\n",
+ __func__, ept->num, ept->in ? "in" : "out", status);
+ } else {
+ actual = req->length;
+ status = 0;
+ }
+ if (req->complete)
+ req->complete(req, actual, status);
+ }
+
+}
+
+static void mt_udc_epx_handler(u8 ep_num, u8 dir)
+{
+ u8 index;
+ u16 csr;
+ u32 count;
+ struct udc_endpoint *endpoint;
+ struct urb *urb;
+ struct udc_request *req; /* for event signaling */
+ u8 intrrxe;
+
+ endpoint = mt_find_ep(ep_num, dir);
+
+ index = readb(INDEX);
+ writeb(ep_num, INDEX);
+
+#if DBG_USB_GENERAL
+ DBG_I("EP%d Interrupt\n", ep_num);
+ DBG_I("dir: %x\n", dir);
+#endif
+
+ switch (dir) {
+ case USB_DIR_OUT:
+ /* transfer direction is from host to device */
+ /* from the view of usb device, it's RX */
+ csr = readw(IECSR + RXCSR);
+
+ if (csr & EPX_RX_SENTSTALL) {
+ DBG_C("EP %d(RX): STALL\n", ep_num);
+ /* exception handling: implement this!! */
+ return;
+ }
+
+ if (!(csr & EPX_RX_RXPKTRDY)) {
+#if DBG_USB_GENERAL
+ DBG_I("EP %d: ERRONEOUS INTERRUPT\n", ep_num); // normal
+#endif
+ return;
+ }
+
+ //DBG_C("mt_read_fifo, start\n");
+ count = mt_read_fifo(endpoint);
+ //DBG_C("mt_read_fifo, end\n");
+
+#if DBG_USB_GENERAL
+ DBG_I("EP%d(RX), count = %d\n", ep_num, count);
+#endif
+
+ csr &= ~EPX_RX_RXPKTRDY;
+ writew(csr, IECSR + RXCSR);
+ if (readw(IECSR + RXCSR) & EPX_RX_RXPKTRDY) {
+#if DBG_USB_GENERAL
+ DBG_I("%s: rxpktrdy clear failed\n", __func__);
+#endif
+ }
+
+ /* do signaling */
+ req = endpoint->req;
+ /* workaround: if req->lenth == 64 bytes (not huge data transmission)
+ * do normal return */
+#if DBG_USB_GENERAL
+ DBG_I("%s: req->length: %x, endpoint->rcv_urb->actual_length: %x\n",
+ __func__, req->length, endpoint->rcv_urb->actual_length);
+#endif
+
+ /* Deal with FASTBOOT command */
+ if ((req->length >= endpoint->rcv_urb->actual_length) && req->length == 64) {
+ req->length = count;
+
+ /* mask EPx INTRRXE */
+ /* The buffer is passed from the AP caller.
+ * It happens that AP is dealing with the buffer filled data by driver,
+ * but the driver is still receiving the next data packets onto the buffer.
+ * Data corrupted happens if the every request use the same buffer.
+ * Mask the EPx to ensure that AP and driver are not accessing the buffer parallely.
+ */
+ intrrxe = readb(INTRRXE);
+ writeb((intrrxe &= ~(1 << ep_num)), INTRRXE);
+ }
+
+ /* Deal with DATA transfer */
+ if ((req->length == endpoint->rcv_urb->actual_length) ||
+ ((req->length >= endpoint->rcv_urb->actual_length) && req->length == 64)) {
+ handle_ept_complete(endpoint);
+
+ /* mask EPx INTRRXE */
+ /* The buffer is passed from the AP caller.
+ * It happens that AP is dealing with the buffer filled data by driver,
+ * but the driver is still receiving the next data packets onto the buffer.
+ * Data corrupted happens if the every request use the same buffer.
+ * Mask the EPx to ensure that AP and driver are not accessing the buffer parallely.
+ */
+ intrrxe = readb(INTRRXE);
+ writeb((intrrxe &= ~(1 << ep_num)), INTRRXE);
+ }
+ break;
+ case USB_DIR_IN:
+ /* transfer direction is from device to host */
+ /* from the view of usb device, it's tx */
+ csr = readw(IECSR + TXCSR);
+
+ if (csr & EPX_TX_SENTSTALL) {
+ DBG_C("EP %d(TX): STALL\n", ep_num);
+ endpoint->status = -1;
+ handle_ept_complete(endpoint);
+ /* exception handling: implement this!! */
+ return;
+ }
+
+ if (csr & EPX_TX_TXPKTRDY) {
+ DBG_C
+ ("mt_udc_epx_handler: ep%d is not ready to be written\n",
+ ep_num);
+ return;
+ }
+
+ urb = endpoint->tx_urb;
+ if (endpoint->sent == urb->actual_length) {
+ /* do signaling */
+ handle_ept_complete(endpoint);
+ break;
+ }
+
+ /* send next packet of the same urb */
+ count = mt_write_fifo(endpoint);
+#if DBG_USB_GENERAL
+ DBG_I("EP%d(TX), count = %d\n", ep_num, endpoint->sent);
+#endif
+
+ if (count != 0) {
+ /* not the interrupt generated by the last tx packet of the transfer */
+ csr |= EPX_TX_TXPKTRDY;
+ writew(csr, IECSR + TXCSR);
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ writeb(index, INDEX);
+
+ return;
+}
+
+static void mt_udc_irq(u8 intrtx, u8 intrrx, u8 intrusb)
+{
+
+ int i;
+
+ DBG_IRQ("[USB] INTERRUPT\n");
+
+ if (intrusb) {
+ if (intrusb & INTRUSB_RESUME) {
+ DBG_IRQ("[USB] INTRUSB: RESUME\n");
+ }
+
+ if (intrusb & INTRUSB_SESS_REQ) {
+ DBG_IRQ("[USB] INTRUSB: SESSION REQUEST\n");
+ }
+
+ if (intrusb & INTRUSB_VBUS_ERROR) {
+ DBG_IRQ("[USB] INTRUSB: VBUS ERROR\n");
+ }
+
+ if (intrusb & INTRUSB_SUSPEND) {
+ DBG_IRQ("[USB] INTRUSB: SUSPEND\n");
+ mt_udc_suspend();
+ }
+
+ if (intrusb & INTRUSB_CONN) {
+ DBG_IRQ("[USB] INTRUSB: CONNECT\n");
+ }
+
+ if (intrusb & INTRUSB_DISCON) {
+ DBG_IRQ("[USB] INTRUSB: DISCONNECT\n");
+ }
+
+ if (intrusb & INTRUSB_RESET) {
+ DBG_IRQ("[USB] INTRUSB: RESET\n");
+ mt_udc_reset();
+ }
+
+ if (intrusb & INTRUSB_SOF) {
+ DBG_IRQ("[USB] INTRUSB: SOF\n");
+ }
+ }
+
+ /* endpoint 0 interrupt? */
+ if (intrtx & EPMASK (0)) {
+ mt_udc_ep0_handler();
+ intrtx &= ~0x1;
+ }
+
+ if (intrtx) {
+ for (i = 1; i < MT_EP_NUM; i++) {
+ if (intrtx & EPMASK (i)) {
+ mt_udc_epx_handler(i, USB_DIR_IN);
+ }
+ }
+ }
+
+ if (intrrx) {
+ for (i = 1; i < MT_EP_NUM; i++) {
+ if (intrrx & EPMASK (i)) {
+ mt_udc_epx_handler(i, USB_DIR_OUT);
+ }
+ }
+ }
+
+}
+
+static enum handler_return service_interrupts(void *arg)
+{
+
+ volatile u8 intrtx, intrrx, intrusb;
+ /* polling interrupt status for incoming interrupts and service it */
+ intrtx = readb(INTRTX) & readb(INTRTXE);
+ intrrx = readb(INTRRX) & readb(INTRRXE);
+ intrusb = readb(INTRUSB) & readb(INTRUSBE);
+
+ writeb(intrtx, INTRTX);
+ writeb(intrrx, INTRRX);
+ writeb(intrusb, INTRUSB);
+
+ intrusb &= ~INTRUSB_SOF;
+
+ if (intrtx | intrrx | intrusb) {
+ mt_udc_irq(intrtx, intrrx, intrusb);
+ }
+
+ return INT_RESCHEDULE;
+}
+
+static int mt_usb_irq_init(void)
+{
+ /* disable all endpoint interrupts */
+ writeb(0, INTRTXE);
+ writeb(0, INTRRXE);
+ writeb(0, INTRUSBE);
+
+ /* 2. Ack all gpt irq if needed */
+ //writel(0x3F, GPT_IRQ_ACK);
+
+ /* 3. Register usb irq */
+ mt_irq_set_sens(MT_USB0_IRQ_ID, LEVEL_SENSITIVE);
+ mt_irq_set_polarity(MT_USB0_IRQ_ID, MT65xx_POLARITY_LOW);
+
+ return 0;
+}
+
+/* Turn on the USB connection by enabling the pullup resistor */
+static void mt_usb_connect_internal(void)
+{
+ u8 tmpReg8;
+
+ /* connect */
+ tmpReg8 = readb(POWER);
+ tmpReg8 |= PWR_SOFT_CONN;
+ tmpReg8 |= PWR_ENABLE_SUSPENDM;
+
+#ifdef USB_FORCE_FULL_SPEED
+ tmpReg8 &= ~PWR_HS_ENAB;
+#else
+ tmpReg8 |= PWR_HS_ENAB;
+#endif
+ writeb(tmpReg8, POWER);
+}
+
+/* Turn off the USB connection by disabling the pullup resistor */
+static void mt_usb_disconnect_internal(void)
+{
+ u8 tmpReg8;
+
+ /* connect */
+ tmpReg8 = readb(POWER);
+ tmpReg8 &= ~PWR_SOFT_CONN;
+ writeb(tmpReg8, POWER);
+}
+
+int udc_init(struct udc_device *dev)
+{
+ struct udc_descriptor *desc = NULL;
+#ifdef USB_GINTR
+#ifdef USB_HSDMA_ISR
+ u32 usb_dmaintr;
+#endif
+ u32 usb_l1intm;
+#endif
+
+ DBG_I("[USB] %s:\n", __func__);
+
+ DBG_I("[USB] ep0_urb: %p\n", ep0_urb);
+ /* RESET */
+ mt_usb_disconnect_internal();
+ thread_sleep(20);
+ mt_usb_connect_internal();
+ thread_sleep(20);
+
+ /* usb phy init */
+ board_usb_init();
+ mt_usb_phy_recover();
+ thread_sleep(20);
+ /* allocate ep0 */
+ ep0out = _udc_endpoint_alloc(EP0, 0, EP0_MAX_PACKET_SIZE);
+ ep0in = _udc_endpoint_alloc(EP0, 1, EP0_MAX_PACKET_SIZE);
+ ep0req = udc_request_alloc();
+ ep0req->buffer = malloc(4096);
+ ep0_urb->buffer = (u8 *)malloc(4096);
+ if (!ep0req->buffer || !ep0req->buffer) {
+ dprintf(CRITICAL, "[USB] allocate buffer failed\n");
+ return ERR_NO_MEMORY;
+ }
+
+ {
+ /* create and register a language table descriptor */
+ /* language 0x0409 is US English */
+ desc = udc_descriptor_alloc(TYPE_STRING, EP0, 4);
+ desc->data[2] = 0x09;
+ desc->data[3] = 0x04;
+ udc_descriptor_register(desc);
+ }
+#ifdef USB_HSDMA_ISR
+ /* setting HSDMA interrupt register */
+ usb_dmaintr = (0xff | 0xff << USB_DMA_INTR_UNMASK_SET_OFFSET);
+ writel(usb_dmaintr, USB_DMA_INTR);
+#endif
+
+#ifdef USB_GINTR
+ usb_l1intm = (TX_INT_STATUS | RX_INT_STATUS | USBCOM_INT_STATUS | DMA_INT_STATUS);
+ writel(usb_l1intm, USB_L1INTM);
+#endif
+ the_device = dev;
+ return 0;
+}
+
+void udc_endpoint_free(struct udc_endpoint *ept)
+{
+ /* todo */
+}
+
+struct udc_request *udc_request_alloc(void)
+{
+ struct udc_request *req;
+ req = malloc(sizeof(*req));
+ req->buffer = NULL;
+ req->length = 0;
+ return req;
+}
+
+
+void udc_request_free(struct udc_request *req)
+{
+ free(req);
+}
+
+/* Called to start packet transmission. */
+/* It must be applied in udc_request_queue when polling mode is used.
+ * (When USB_GINTR is undefined).
+ * If interrupt mode is used, you can use
+ * mt_udc_epx_handler(ept->num, USB_DIR_IN); to replace mt_ep_write make ISR
+ * do it for you.
+ */
+static int mt_ep_write(struct udc_endpoint *endpoint)
+{
+ int ep_num = endpoint->num;
+ int count;
+ u8 index;
+ u16 csr;
+
+ index = readb(INDEX);
+ writeb(ep_num, INDEX);
+
+ /* udc_endpoint_write: cannot write ep0 */
+ if (ep_num == 0)
+ return false;
+
+ /* udc_endpoint_write: cannot write USB_DIR_OUT */
+ if (endpoint->in == 0)
+ return false;
+
+ csr = readw(IECSR + TXCSR);
+ if (csr & EPX_TX_TXPKTRDY) {
+#if DBG_USB_GENERAL
+ DBG_I("[USB]: udc_endpoint_write: ep%d is not ready to be written\n",
+ ep_num);
+
+#endif
+ return false;
+ }
+ count = mt_write_fifo(endpoint);
+
+ csr |= EPX_TX_TXPKTRDY;
+ writew(csr, IECSR + TXCSR);
+
+ writeb(index, INDEX);
+
+ return count;
+}
+
+int udc_request_queue(struct udc_endpoint *ept, struct udc_request *req)
+{
+ u8 intrrxe;
+
+#if DBG_USB_GENERAL
+ DBG_I("[USB] %s: ept%d %s queue req=%p, req->length=%x\n",
+ __func__, ept->num, ept->in ? "in" : "out", req, req->length);
+ DBG_I("[USB] %s: ept%d: %p, ept->in: %s, ept->rcv_urb->buffer: %p, req->buffer: %p\n",
+ __func__, ept->num, ept, ept->in ? "IN" : "OUT" , ept->rcv_urb->buffer, req->buffer);
+#endif
+
+ THREAD_LOCK(state); /* enter_critical_section */
+ ept->req = req;
+ ept->status = 0; /* ACTIVE */
+
+ ept->sent = 0;
+ ept->last = 0;
+
+ /* read */
+ if (!ept->in) {
+ ept->rcv_urb->buffer = req->buffer;
+ ept->rcv_urb->actual_length = 0;
+
+ /* unmask EPx INTRRXE */
+ /*
+ * To avoid the parallely access the buffer,
+ * it is umasked here and umask at complete.
+ */
+ intrrxe = readb(INTRRXE);
+ intrrxe |= (1 << ept->num);
+ writeb(intrrxe, INTRRXE);
+ }
+
+ /* write */
+ if (ept->in) {
+ ept->tx_urb->buffer = req->buffer;
+ ept->tx_urb->actual_length = req->length;
+
+ mt_ep_write(ept);
+ }
+ THREAD_UNLOCK(state); /* exit_critical_section */
+ return 0;
+}
+
+int udc_register_gadget(struct udc_gadget *gadget)
+{
+ if (the_gadget) {
+ DBG_C("only one gadget supported\n");
+ return false;
+ }
+ the_gadget = gadget;
+ return 0;
+}
+
+static void udc_ept_desc_fill(struct udc_endpoint *ept, unsigned char *data)
+{
+ data[0] = 7;
+ data[1] = TYPE_ENDPOINT;
+ data[2] = ept->num | (ept->in ? USB_DIR_IN : USB_DIR_OUT);
+ data[3] = 0x02; /* bulk -- the only kind we support */
+ data[4] = ept->maxpkt;
+ data[5] = ept->maxpkt >> 8;
+ data[6] = ept->in ? 0x00 : 0x01;
+}
+
+static unsigned udc_ifc_desc_size(struct udc_gadget *g)
+{
+ return 9 + g->ifc_endpoints * 7;
+}
+
+static void udc_ifc_desc_fill(struct udc_gadget *g, unsigned char *data)
+{
+ unsigned n;
+
+ data[0] = 0x09;
+ data[1] = TYPE_INTERFACE;
+ data[2] = 0x00; /* ifc number */
+ data[3] = 0x00; /* alt number */
+ data[4] = g->ifc_endpoints;
+ data[5] = g->ifc_class;
+ data[6] = g->ifc_subclass;
+ data[7] = g->ifc_protocol;
+ data[8] = udc_string_desc_alloc(g->ifc_string);
+
+ data += 9;
+ for (n = 0; n < g->ifc_endpoints; n++) {
+ udc_ept_desc_fill(g->ept[n], data);
+ data += 7;
+ }
+}
+
+static int udc_start_cond(void)
+{
+ struct udc_descriptor *desc;
+ unsigned char *data;
+ unsigned size;
+
+ DBG_C("[USB] %s\n", __func__);
+
+ if (!the_device) {
+ DBG_C("udc cannot start before init\n");
+ return false;
+ }
+ if (!the_gadget) {
+ DBG_C("udc has no gadget registered\n");
+ return false;
+ }
+
+ /* create our device descriptor */
+ desc = udc_descriptor_alloc(TYPE_DEVICE, EP0, 18);
+ data = desc->data;
+ data[2] = 0x00; /* usb spec minor rev */
+ data[3] = 0x02; /* usb spec major rev */
+ data[4] = 0x00; /* class */
+ data[5] = 0x00; /* subclass */
+ data[6] = 0x00; /* protocol */
+ data[7] = 0x40; /* max packet size on ept 0 */
+ memcpy(data + 8, &the_device->vendor_id, sizeof(short));
+ memcpy(data + 10, &the_device->product_id, sizeof(short));
+ memcpy(data + 12, &the_device->version_id, sizeof(short));
+ data[14] = udc_string_desc_alloc(the_device->manufacturer);
+ data[15] = udc_string_desc_alloc(the_device->product);
+ data[16] = udc_string_desc_alloc(the_device->serialno);
+ data[17] = 1; /* number of configurations */
+ udc_descriptor_register(desc);
+
+ /* create our configuration descriptor */
+ size = 9 + udc_ifc_desc_size(the_gadget);
+ desc = udc_descriptor_alloc(TYPE_CONFIGURATION, EP0, size);
+ data = desc->data;
+ data[0] = 0x09;
+ data[2] = size;
+ data[3] = size >> 8;
+ data[4] = 0x01; /* number of interfaces */
+ data[5] = 0x01; /* configuration value */
+ data[6] = 0x00; /* configuration string */
+ data[7] = 0x80; /* attributes */
+ data[8] = 0x80; /* max power (250ma) -- todo fix this */
+
+ udc_ifc_desc_fill(the_gadget, data + 9);
+ udc_descriptor_register(desc);
+
+#if DBG_USB_DUMP_DESC
+ DBG_I("%s: dump desc_list\n", __func__);
+ for (desc = desc_list; desc; desc = desc->next) {
+ DBG_I("tag: %04x\n", desc->tag);
+ DBG_I("len: %d\n", desc->len);
+ DBG_I("data:");
+ hexdump8(desc->data, desc->len);
+ }
+#endif
+
+ /* register interrupt handler */
+ dprintf(CRITICAL, "MT_USB0_IRQ_ID: %u\n", MT_USB0_IRQ_ID);
+ mt_usb_irq_init();
+ register_int_handler(MT_USB0_IRQ_ID, service_interrupts, NULL);
+
+ /* go to RUN mode */
+ mt_usb_phy_recover();
+
+ /* clear INTRTX, INTRRX and INTRUSB */
+ writew(0xffff, INTRTX); /* writew */
+ writew(0xffff, INTRRX); /* writew */
+ writeb(0xff, INTRUSB); /* writeb */
+
+ /* unmask usb irq */
+#ifdef USB_GINTR
+ unmask_interrupt(MT_USB0_IRQ_ID);
+#endif
+ writeb((INTRUSB_SUSPEND | INTRUSB_RESUME | INTRUSB_RESET |INTRUSB_DISCON), INTRUSBE);
+
+ return 0;
+}
+
+int udc_start(void)
+{
+ return udc_start_cond();
+}
+
+int udc_stop(void)
+{
+ thread_sleep(10);
+ mt_usb_disconnect_internal();
+ mt_usb_phy_savecurrent();
+ free(ep0_urb->buffer);
+ return 0;
+}
diff --git a/src/bsp/lk/platform/mt2635/drivers/wdt/mtk_wdt.c b/src/bsp/lk/platform/mt2635/drivers/wdt/mtk_wdt.c
new file mode 100644
index 0000000..06bc74d
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/drivers/wdt/mtk_wdt.c
@@ -0,0 +1,350 @@
+#include <debug.h>
+#include <platform/mtk_wdt.h>
+#include <platform/mtk_timer.h>
+
+#if ENABLE_WDT_MODULE
+
+static bool mtk_wd_CheckNonResetReg2(unsigned int offset)
+{
+ u32 tmp;
+ tmp = readl(MTK_WDT_NONRST_REG2);
+ if (tmp & (1U << offset))
+ return true;
+ else
+ return false;
+}
+
+static void mtk_wd_SetNonResetReg2(unsigned int offset, bool value)
+{
+ u32 reg;
+
+ reg = readl(MTK_WDT_NONRST_REG2);
+ if (value)
+ reg |= (1U << offset);
+ else
+ reg &= ~(1U << offset);
+
+ writel(reg, MTK_WDT_NONRST_REG2);
+}
+
+void set_clr_fastboot_mode(bool flag)
+{
+ if (flag==true)
+ mtk_wd_SetNonResetReg2(0x2, 1);
+ else if (flag==false)
+ mtk_wd_SetNonResetReg2(0x2, 0);
+
+ dprintf(INFO, "set_clr_fastboot_mode\n");
+}
+
+void set_clr_recovery_mode(bool flag)
+{
+ if (flag==true)
+ mtk_wd_SetNonResetReg2(0x1, 1);
+ else if (flag==false)
+ mtk_wd_SetNonResetReg2(0x1, 0);
+
+ dprintf(INFO, "set_clr_recovery_mode\n");
+}
+
+bool check_fastboot_mode(void)
+{
+ return mtk_wd_CheckNonResetReg2(0x2);
+}
+
+bool check_recovery_mode(void)
+{
+ return mtk_wd_CheckNonResetReg2(0x1);
+}
+
+void mtk_wdt_disable(void)
+{
+ u32 tmp;
+
+ tmp = readl(MTK_WDT_MODE);
+ tmp &= ~MTK_WDT_MODE_ENABLE; /* disable watchdog */
+ tmp |= (MTK_WDT_MODE_KEY); /* need key then write is allowed */
+ writel(tmp, MTK_WDT_MODE);
+}
+
+static void mtk_wdt_reset(char mode)
+{
+ /* Watchdog Rest */
+ unsigned int wdt_mode_val;
+ writel(MTK_WDT_RESTART_KEY, MTK_WDT_RESTART);
+
+ wdt_mode_val = readl(MTK_WDT_MODE);
+ /* clear autorestart bit: autoretart: 1, bypass power key, 0: not bypass power key */
+ wdt_mode_val &=(~MTK_WDT_MODE_AUTO_RESTART);
+ /* make sure WDT mode is hw reboot mode, can not config isr mode */
+ wdt_mode_val &=(~(MTK_WDT_MODE_IRQ|MTK_WDT_MODE_ENABLE | MTK_WDT_MODE_DUAL_MODE));
+
+ if (mode) { /* mode != 0 means by pass power key reboot, We using auto_restart bit as by pass power key flag */
+ wdt_mode_val = wdt_mode_val | (MTK_WDT_MODE_KEY|MTK_WDT_MODE_EXTEN|MTK_WDT_MODE_AUTO_RESTART);
+ writel(wdt_mode_val, MTK_WDT_MODE);
+
+ } else {
+ wdt_mode_val = wdt_mode_val | (MTK_WDT_MODE_KEY|MTK_WDT_MODE_EXTEN);
+ writel(wdt_mode_val,MTK_WDT_MODE);
+
+ }
+
+ spin(100);
+ writel(MTK_WDT_SWRST_KEY, MTK_WDT_SWRST);
+}
+
+static unsigned int mtk_wdt_check_status(void)
+{
+ static unsigned int status = 0;
+
+ /*
+ * Because WDT_STA register will be cleared after writing WDT_MODE,
+ * we use a static variable to store WDT_STA.
+ * After reset, static varialbe will always be clear to 0,
+ * so only read WDT_STA when static variable is 0 is OK
+ */
+ if (0 == status)
+ status = readl(MTK_WDT_STATUS);
+
+ return status;
+}
+
+static void mtk_wdt_mode_config(bool dual_mode_en,
+ bool irq,
+ bool ext_en,
+ bool ext_pol,
+ bool wdt_en)
+{
+ unsigned int tmp;
+
+ tmp = readl(MTK_WDT_MODE);
+ tmp |= MTK_WDT_MODE_KEY;
+
+ // Bit 0 : Whether enable watchdog or not
+ if (wdt_en == true)
+ tmp |= MTK_WDT_MODE_ENABLE;
+ else
+ tmp &= ~MTK_WDT_MODE_ENABLE;
+
+ // Bit 1 : Configure extern reset signal polarity.
+ if (ext_pol == true)
+ tmp |= MTK_WDT_MODE_EXT_POL;
+ else
+ tmp &= ~MTK_WDT_MODE_EXT_POL;
+
+ // Bit 2 : Whether enable external reset signal
+ if (ext_en == true)
+ tmp |= MTK_WDT_MODE_EXTEN;
+ else
+ tmp &= ~MTK_WDT_MODE_EXTEN;
+
+ // Bit 3 : Whether generating interrupt instead of reset signal
+ if (irq == true)
+ tmp |= MTK_WDT_MODE_IRQ;
+ else
+ tmp &= ~MTK_WDT_MODE_IRQ;
+
+ // Bit 6 : Whether enable debug module reset
+ if (dual_mode_en == true)
+ tmp |= MTK_WDT_MODE_DUAL_MODE;
+ else
+ tmp &= ~MTK_WDT_MODE_DUAL_MODE;
+
+ // Bit 4: WDT_Auto_restart, this is a reserved bit, we use it as bypass powerkey flag.
+ // Because HW reboot always need reboot to kernel, we set it always.
+ tmp |= MTK_WDT_MODE_AUTO_RESTART;
+
+ writel(tmp, MTK_WDT_MODE);
+ //dual_mode(1); //always dual mode
+ //mdelay(100);
+ dprintf(INFO,"mtk_wdt_mode_config LK mode value=%x", readl(MTK_WDT_MODE));
+}
+
+static void mtk_wdt_set_time_out_value(uint32_t value)
+{
+ static unsigned int timeout;
+
+ /*
+ * TimeOut = BitField 15:5
+ * Key = BitField 4:0 = 0x08
+ */
+
+ // sec * 32768 / 512 = sec * 64 = sec * 1 << 6
+ timeout = (unsigned int)(value * ( 1 << 6) );
+ timeout = timeout << 5;
+ writel((timeout | MTK_WDT_LENGTH_KEY), MTK_WDT_LENGTH);
+}
+
+static void mtk_wdt_restart(void)
+{
+ // Reset WatchDogTimer's counting value to time out value
+ // ie., keepalive()
+ writel(MTK_WDT_RESTART_KEY, MTK_WDT_RESTART);
+}
+
+static void mtk_wdt_sw_reset(void)
+{
+ printf ("UB WDT SW RESET\n");
+ //DRV_WriteReg32 (0x70025000, 0x2201);
+ //DRV_WriteReg32 (0x70025008, 0x1971);
+ //DRV_WriteReg32 (0x7002501C, 0x1209);
+ mtk_wdt_reset(1);/* NOTE here, this reset will cause by pass power key */
+
+ // system will reset
+
+ while (1) {
+ printf ("UB SW reset fail ... \n");
+ };
+}
+
+static void mtk_wdt_hw_reset(void)
+{
+ dprintf(INFO,"UB WDT_HW_Reset\n");
+
+ // 1. set WDT timeout 1 secs, 1*64*512/32768 = 1sec
+ mtk_wdt_set_time_out_value(1);
+
+ // 2. enable WDT debug reset enable, generating irq disable, ext reset disable
+ // ext reset signal low, wdt enalbe
+ mtk_wdt_mode_config(true, false, false, false, true);
+
+ // 3. reset the watch dog timer to the value set in WDT_LENGTH register
+ mtk_wdt_restart();
+
+ // 4. system will reset
+ while (1);
+}
+
+
+static const char *parsing_reset_reason(unsigned int wdt_status)
+{
+ const char *rst_reason="normal";
+ switch (wdt_status) {
+ case MTK_WDT_STATUS_HWWDT_RST:
+ rst_reason="hw_rst";
+ break;
+
+ case MTK_WDT_STATUS_SWWDT_RST:
+ rst_reason="sw_rst";
+ break;
+
+ case MTK_WDT_STATUS_IRQWDT_RST:
+ rst_reason="irq_rst";
+ break;
+
+ case MTK_WDT_STATUS_SECURITY_RST:
+ rst_reason="security_rst";
+ break;
+
+ case MTK_WDT_STATUS_DEBUGWDT_RST:
+ rst_reason="debug_rst";
+ break;
+
+ case MTK_WDT_STATUS_THERMAL_DIRECT_RST:
+ rst_reason="thermal_ctl_rst";
+ break;
+
+ case MTK_WDT_STATUS_SPMWDT_RST:
+ rst_reason="spm_rst";
+ break;
+
+ case MTK_WDT_STATUS_SPM_THERMAL_RST:
+ rst_reason="spm_thermal_rst";
+ break;
+
+ default:
+ break;
+ }
+
+ return rst_reason;
+}
+void mtk_wdt_init(void)
+{
+ /* This function will store the reset reason: Time out/ SW trigger */
+ dprintf(ALWAYS, "Watchdog Status: %x , boot from %s\n", mtk_wdt_check_status(),parsing_reset_reason(mtk_wdt_check_status()));
+
+ mtk_wdt_mode_config(false, false, false, false, false);
+
+#if (!LK_WDT_DISABLE)
+ mtk_wdt_set_time_out_value(10);
+ mtk_wdt_mode_config(true, true, true, false, true);
+ mtk_wdt_restart();
+#endif
+}
+
+static bool mtk_is_rgu_trigger_reset(void)
+{
+ if (mtk_wdt_check_status())
+ return true;
+ return false;
+}
+
+void mtk_arch_reset(char mode)
+{
+ dprintf(INFO,"UB mtk_arch_reset\n");
+
+ mtk_wdt_reset(mode);
+
+ while (1);
+}
+
+static void rgu_swsys_reset(WD_SYS_RST_TYPE reset_type)
+{
+ if (WD_MD_RST == reset_type) {
+ unsigned int wdt_dbg_ctrl;
+ wdt_dbg_ctrl = readl(MTK_WDT_SWSYSRST);
+ wdt_dbg_ctrl |= MTK_WDT_SWSYS_RST_KEY;
+ wdt_dbg_ctrl |= 0x80;// 1<<7
+ writel(wdt_dbg_ctrl, MTK_WDT_SWSYSRST);
+ spin(1000);
+ wdt_dbg_ctrl = readl(MTK_WDT_SWSYSRST);
+ wdt_dbg_ctrl |= MTK_WDT_SWSYS_RST_KEY;
+ wdt_dbg_ctrl &= (~0x80);// ~(1<<7)
+ writel(wdt_dbg_ctrl, MTK_WDT_SWSYSRST);
+ dprintf(INFO,"rgu pl md reset\n");
+ }
+}
+#else
+void mtk_wdt_init(void)
+{
+ dprintf(INFO,"UB WDT Dummy init called\n");
+}
+static bool mtk_is_rgu_trigger_reset()
+{
+ dprintf(INFO,"UB Dummy mtk_is_rgu_trigger_reset called\n");
+ return FALSE;
+}
+void mtk_arch_reset(char mode)
+{
+ dprintf(INFO,"UB WDT Dummy arch reset called\n");
+}
+
+int mtk_wdt_boot_check(void)
+{
+ dprintf(INFO,"UB WDT Dummy mtk_wdt_boot_check called\n");
+ return WDT_NOT_WDT_REBOOT;
+}
+
+void mtk_wdt_disable(void)
+{
+ dprintf(INFO,"UB WDT Dummy mtk_wdt_disable called\n");
+}
+
+static void mtk_wdt_restart(void)
+{
+ dprintf(INFO,"UB WDT Dummy mtk_wdt_restart called\n");
+}
+static void mtk_wdt_sw_reset(void)
+{
+ dprintf(INFO,"UB WDT Dummy mtk_wdt_sw_reset called\n");
+}
+
+static void mtk_wdt_hw_reset(void)
+{
+ dprintf(INFO,"UB WDT Dummy mtk_wdt_hw_reset called\n");
+}
+static void rgu_swsys_reset(WD_SYS_RST_TYPE reset_type)
+{
+ dprintf(INFO,"UB WDT Dummy rgu_swsys_reset called\n");
+}
+#endif
diff --git a/src/bsp/lk/platform/mt2635/include/platform/generic_ioctl.h b/src/bsp/lk/platform/mt2635/include/platform/generic_ioctl.h
new file mode 100644
index 0000000..84c2ec8
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/generic_ioctl.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_ASM_GENERIC_IOCTL_H
+#define _UAPI_ASM_GENERIC_IOCTL_H
+#define _IOC_NRBITS 8
+#define _IOC_TYPEBITS 8
+#ifndef _IOC_SIZEBITS
+#define _IOC_SIZEBITS 14
+#endif
+#ifndef _IOC_DIRBITS
+#define _IOC_DIRBITS 2
+#endif
+#define _IOC_NRMASK ((1 << _IOC_NRBITS) - 1)
+#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS) - 1)
+#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS) - 1)
+#define _IOC_DIRMASK ((1 << _IOC_DIRBITS) - 1)
+#define _IOC_NRSHIFT 0
+#define _IOC_TYPESHIFT (_IOC_NRSHIFT + _IOC_NRBITS)
+#define _IOC_SIZESHIFT (_IOC_TYPESHIFT + _IOC_TYPEBITS)
+#define _IOC_DIRSHIFT (_IOC_SIZESHIFT + _IOC_SIZEBITS)
+#ifndef _IOC_NONE
+#define _IOC_NONE 0U
+#endif
+#ifndef _IOC_WRITE
+#define _IOC_WRITE 1U
+#endif
+#ifndef _IOC_READ
+#define _IOC_READ 2U
+#endif
+#define _IOC(dir,type,nr,size) (((dir) << _IOC_DIRSHIFT) | ((type) << _IOC_TYPESHIFT) | ((nr) << _IOC_NRSHIFT) | ((size) << _IOC_SIZESHIFT))
+#define _IOC_TYPECHECK(t) (sizeof(t))
+#define _IO(type,nr) _IOC(_IOC_NONE, (type), (nr), 0)
+#define _IOR(type,nr,size) _IOC(_IOC_READ, (type), (nr), (_IOC_TYPECHECK(size)))
+#define _IOW(type,nr,size) _IOC(_IOC_WRITE, (type), (nr), (_IOC_TYPECHECK(size)))
+#define _IOWR(type,nr,size) _IOC(_IOC_READ | _IOC_WRITE, (type), (nr), (_IOC_TYPECHECK(size)))
+#define _IOR_BAD(type,nr,size) _IOC(_IOC_READ, (type), (nr), sizeof(size))
+#define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE, (type), (nr), sizeof(size))
+#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ | _IOC_WRITE, (type), (nr), sizeof(size))
+#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
+#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
+#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
+#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
+#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT)
+#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT)
+#define IOC_INOUT ((_IOC_WRITE | _IOC_READ) << _IOC_DIRSHIFT)
+#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT)
+#define IOCSIZE_SHIFT (_IOC_SIZESHIFT)
+#endif
diff --git a/src/bsp/lk/platform/mt2635/include/platform/gic.h b/src/bsp/lk/platform/mt2635/include/platform/gic.h
new file mode 100644
index 0000000..125e350
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/gic.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+#include <platform/mt2635.h>
+
+#define GICBASE(n) (PERIPHERAL_BASE_VIRT + 0x220000)
+#define GICD_OFFSET (0x1000)
+#define GICC_OFFSET (0x2000)
+
diff --git a/src/bsp/lk/platform/mt2635/include/platform/mmc_core.h b/src/bsp/lk/platform/mt2635/include/platform/mmc_core.h
new file mode 100644
index 0000000..a34c8d7
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/mmc_core.h
@@ -0,0 +1,642 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+
+#include <stdbool.h>
+#include <sys/types.h>
+#include <kernel/mutex.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MMC_BLOCK_BITS_SHFT (9)
+#define MMC_BLOCK_SIZE (1 << MMC_BLOCK_BITS_SHFT)
+#define MMC_MAX_BLOCK_SIZE (1 << MMC_BLOCK_BITS_SHFT)
+
+#define SDIO_MAX_FUNCS (7)
+
+#define SD_CMD_BIT (1 << 7)
+#define SD_CMD_APP_BIT (1 << 8)
+#define SD_CMD_AUTO_BIT (1 << 9)
+
+/* MMC command numbers */
+#define MMC_CMD_GO_IDLE_STATE (0) /* bc. no response */
+#define MMC_CMD_SEND_OP_COND (1) /* bcr. R3 */
+#define MMC_CMD_ALL_SEND_CID (2) /* bcr. R2 */
+#define MMC_CMD_SET_RELATIVE_ADDR (3) /* ac. R1 */
+#define MMC_CMD_SET_DSR (4) /* bc. no response */
+#define MMC_CMD_SLEEP_AWAKE (5) /* ac. R1b */
+#define MMC_CMD_SWITCH (6) /* ac. R1b */
+#define MMC_CMD_SELECT_CARD (7) /* ac. R1/R1b */
+#define MMC_CMD_SEND_EXT_CSD (8) /* adtc. R1 */
+#define MMC_CMD_SEND_CSD (9) /* ac. R2 */
+#define MMC_CMD_SEND_CID (10) /* ac. R2 */
+#define MMC_CMD_READ_DAT_UNTIL_STOP (11) /* adtc. R1 */
+#define MMC_CMD_STOP_TRANSMISSION (12) /* ac. R1/R1b */
+#define MMC_CMD_SEND_STATUS (13) /* ac. R1 */
+#define MMC_CMD_BUSTEST_R (14) /* adtc. R1 */
+#define MMC_CMD_GO_INACTIVE_STATE (15) /* ac. no response */
+#define MMC_CMD_SET_BLOCKLEN (16) /* ac. R1 */
+#define MMC_CMD_READ_SINGLE_BLOCK (17) /* adtc. R1 */
+#define MMC_CMD_READ_MULTIPLE_BLOCK (18) /* adtc. R1 */
+#define MMC_CMD_BUSTEST_W (19) /* adtc. R1 */
+#define MMC_CMD_WRITE_DAT_UNTIL_STOP (20) /* adtc. R1 */
+#define MMC_CMD21 (21) /* adtc. R1 Sandisk */
+#define MMC_CMD_SET_BLOCK_COUNT (23) /* ac. R1 */
+#define MMC_CMD_WRITE_BLOCK (24) /* adtc. R1 */
+#define MMC_CMD_WRITE_MULTIPLE_BLOCK (25) /* adtc. R1 */
+#define MMC_CMD_PROGRAM_CID (26) /* adtc. R1 */
+#define MMC_CMD_PROGRAM_CSD (27) /* adtc. R1 */
+
+#define MMC_CMD_SET_WRITE_PROT (28) /* ac. R1b */
+#define MMC_CMD_CLR_WRITE_PROT (29) /* ac. R1b */
+#define MMC_CMD_SEND_WRITE_PROT (30) /* adtc. R1 */
+#define MMC_CMD_SEND_WRITE_PROT_TYPE (31) /* adtc. R1 */
+#define MMC_CMD_ERASE_WR_BLK_START (32)
+#define MMC_CMD_ERASE_WR_BLK_END (33)
+#define MMC_CMD_ERASE_GROUP_START (35) /* ac. R1 */
+#define MMC_CMD_ERASE_GROUP_END (36) /* ac. R1 */
+#define MMC_CMD_ERASE (38) /* ac. R1b */
+#define MMC_CMD_FAST_IO (39) /* ac. R4 */
+#define MMC_CMD_GO_IRQ_STATE (40) /* bcr. R5 */
+#define MMC_CMD_LOCK_UNLOCK (42) /* adtc. R1 */
+#define MMC_CMD50 (50) /* adtc. R1 Sandisk */
+#define MMC_CMD_APP_CMD (55) /* ac. R1 */
+#define MMC_CMD_GEN_CMD (56) /* adtc. R1 */
+
+/* SD Card command numbers */
+#define SD_CMD_SEND_RELATIVE_ADDR (3 | SD_CMD_BIT)
+#define SD_CMD_SWITCH (6 | SD_CMD_BIT)
+#define SD_CMD_SEND_IF_COND (8 | SD_CMD_BIT)
+#define SD_CMD_VOL_SWITCH (11 | SD_CMD_BIT)
+#define SD_CMD_SEND_TUNING_BLOCK (19 | SD_CMD_BIT)
+#define SD_CMD_SPEED_CLASS_CTRL (20 | SD_CMD_BIT)
+
+#define SD_ACMD_SET_BUSWIDTH (6 | SD_CMD_APP_BIT)
+#define SD_ACMD_SD_STATUS (13 | SD_CMD_APP_BIT)
+#define SD_ACMD_SEND_NR_WR_BLOCKS (22 | SD_CMD_APP_BIT)
+#define SD_ACMD_SET_WR_ERASE_CNT (23 | SD_CMD_APP_BIT)
+#define SD_ACMD_SEND_OP_COND (41 | SD_CMD_APP_BIT)
+#define SD_ACMD_SET_CLR_CD (42 | SD_CMD_APP_BIT)
+#define SD_ACMD_SEND_SCR (51 | SD_CMD_APP_BIT)
+
+/* SDIO Card command numbers */
+#define SD_IO_SEND_OP_COND (5 | SD_CMD_BIT) /* bcr. R4 */
+#define SD_IO_RW_DIRECT (52 | SD_CMD_BIT)/* ac. R5 */
+#define SD_IO_RW_EXTENDED (53 | SD_CMD_BIT)/* adtc. R5 */
+
+/* platform dependent command */
+#define SD_ATOCMD_STOP_TRANSMISSION (12 | SD_CMD_AUTO_BIT)
+#define SD_ATOCMD_SET_BLOCK_COUNT (23 | SD_CMD_AUTO_BIT)
+
+#define MMC_VDD_145_150 0x00000001 /* VDD voltage 1.45 - 1.50 */
+#define MMC_VDD_150_155 0x00000002 /* VDD voltage 1.50 - 1.55 */
+#define MMC_VDD_155_160 0x00000004 /* VDD voltage 1.55 - 1.60 */
+#define MMC_VDD_160_165 0x00000008 /* VDD voltage 1.60 - 1.65 */
+#define MMC_VDD_165_170 0x00000010 /* VDD voltage 1.65 - 1.70 */
+#define MMC_VDD_17_18 0x00000020 /* VDD voltage 1.7 - 1.8 */
+#define MMC_VDD_18_19 0x00000040 /* VDD voltage 1.8 - 1.9 */
+#define MMC_VDD_19_20 0x00000080 /* VDD voltage 1.9 - 2.0 */
+#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */
+#define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */
+#define MMC_VDD_22_23 0x00000400 /* VDD voltage 2.2 ~ 2.3 */
+#define MMC_VDD_23_24 0x00000800 /* VDD voltage 2.3 ~ 2.4 */
+#define MMC_VDD_24_25 0x00001000 /* VDD voltage 2.4 ~ 2.5 */
+#define MMC_VDD_25_26 0x00002000 /* VDD voltage 2.5 ~ 2.6 */
+#define MMC_VDD_26_27 0x00004000 /* VDD voltage 2.6 ~ 2.7 */
+#define MMC_VDD_27_28 0x00008000 /* VDD voltage 2.7 ~ 2.8 */
+#define MMC_VDD_28_29 0x00010000 /* VDD voltage 2.8 ~ 2.9 */
+#define MMC_VDD_29_30 0x00020000 /* VDD voltage 2.9 ~ 3.0 */
+#define MMC_VDD_30_31 0x00040000 /* VDD voltage 3.0 ~ 3.1 */
+#define MMC_VDD_31_32 0x00080000 /* VDD voltage 3.1 ~ 3.2 */
+#define MMC_VDD_32_33 0x00100000 /* VDD voltage 3.2 ~ 3.3 */
+#define MMC_VDD_33_34 0x00200000 /* VDD voltage 3.3 ~ 3.4 */
+#define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */
+#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */
+#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */
+#define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */ //Add this line by reference to include/linux/mmc/host.h in linux kernel
+#define MMC_VDD_27_36 0x00FF8000
+
+#define EMMC_VER_50 (50)
+#define EMMC_VER_45 (45)
+#define EMMC_VER_44 (44)
+#define EMMC_VER_43 (43)
+#define EMMC_VER_42 (42)
+#define SD_VER_10 (10)
+#define SD_VER_20 (20)
+#define SD_VER_30 (30)
+
+#define MMC_ERR_NONE 0
+#define MMC_ERR_TIMEOUT 1
+#define MMC_ERR_BADCRC 2
+#define MMC_ERR_FIFO 3
+#define MMC_ERR_FAILED 4
+#define MMC_ERR_INVALID 5
+#define MMC_ERR_CMDTUNEFAIL 6
+#define MMC_ERR_READTUNEFAIL 7
+#define MMC_ERR_WRITETUNEFAIL 8
+#define MMC_ERR_CMD_TIMEOUT 9
+#define MMC_ERR_CMD_RSPCRC 10
+#define MMC_ERR_ACMD_TIMEOUT 11
+#define MMC_ERR_ACMD_RSPCRC 12
+#define MMC_ERR_AXI_RSPCRC 13
+#define MMC_ERR_UNEXPECT 14
+
+#define MMC_POWER_OFF 0
+#define MMC_POWER_UP 1
+#define MMC_POWER_ON 2
+
+#define MMC_BUS_WIDTH_1 0
+#define MMC_BUS_WIDTH_4 2
+
+#define SD_BUS_WIDTH_1 0
+#define SD_BUS_WIDTH_4 2
+
+#define MMC_STATE_PRESENT (1<<0) /* present in sysfs */
+#define MMC_STATE_READONLY (1<<1) /* card is read-only */
+#define MMC_STATE_HIGHSPEED (1<<2) /* card is in high speed mode */
+#define MMC_STATE_BLOCKADDR (1<<3) /* card uses block-addressing */
+#define MMC_STATE_HIGHCAPS (1<<4)
+#define MMC_STATE_UHS1 (1<<5) /* card is in ultra high speed mode */
+#define MMC_STATE_DDR (1<<6) /* card is in ddr mode */
+#define MMC_STATE_HS200 (1<<7)
+#define MMC_STATE_HS400 (1<<8)
+#define MMC_STATE_BACKYARD (1<<9)
+
+#define R1_OUT_OF_RANGE (1UL << 31) /* er, c */
+#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */
+#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */
+#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */
+#define R1_ERASE_PARAM (1 << 27) /* ex, c */
+#define R1_WP_VIOLATION (1 << 26) /* erx, c */
+#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */
+#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */
+#define R1_COM_CRC_ERROR (1 << 23) /* er, b */
+#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */
+#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */
+#define R1_CC_ERROR (1 << 20) /* erx, c */
+#define R1_ERROR (1 << 19) /* erx, c */
+#define R1_UNDERRUN (1 << 18) /* ex, c */
+#define R1_OVERRUN (1 << 17) /* ex, c */
+#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */
+#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */
+#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */
+#define R1_ERASE_RESET (1 << 13) /* sr, c */
+#define R1_STATUS(x) (x & 0xFFFFE000)
+#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */
+#define R1_READY_FOR_DATA (1 << 8) /* sx, a */
+#define R1_SWITCH_ERROR (1 << 7) /* ex, b */
+#define R1_URGENT_BKOPS (1 << 6) /* sr, a */
+#define R1_APP_CMD (1 << 5) /* sr, c */
+
+/*
+ * Card Command Classes (CCC)
+ */
+#define CCC_BASIC (1<<0) /* (0) Basic protocol functions */
+/* (CMD0,1,2,3,4,7,9,10,12,13,15) */
+#define CCC_STREAM_READ (1<<1) /* (1) Stream read commands */
+/* (CMD11) */
+#define CCC_BLOCK_READ (1<<2) /* (2) Block read commands */
+/* (CMD16,17,18) */
+#define CCC_STREAM_WRITE (1<<3) /* (3) Stream write commands */
+/* (CMD20) */
+#define CCC_BLOCK_WRITE (1<<4) /* (4) Block write commands */
+/* (CMD16,24,25,26,27) */
+#define CCC_ERASE (1<<5) /* (5) Ability to erase blocks */
+/* (CMD32,33,34,35,36,37,38,39) */
+#define CCC_WRITE_PROT (1<<6) /* (6) Able to write protect blocks */
+/* (CMD28,29,30) */
+#define CCC_LOCK_CARD (1<<7) /* (7) Able to lock down card */
+/* (CMD16,CMD42) */
+#define CCC_APP_SPEC (1<<8) /* (8) Application specific */
+/* (CMD55,56,57,ACMD*) */
+#define CCC_IO_MODE (1<<9) /* (9) I/O mode */
+/* (CMD5,39,40,52,53) */
+#define CCC_SWITCH (1<<10) /* (10) High speed switch */
+/* (CMD6,34,35,36,37,50) */
+/* (11) Reserved */
+/* (CMD?) */
+
+/*
+ * CSD field definitions
+ */
+
+#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */
+#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */
+#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */
+#define CSD_STRUCT_EXT_CSD 3 /* Version is coded in CSD_STRUCTURE in EXT_CSD */
+
+#define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */
+#define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */
+#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */
+#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 - 3.2 - 3.31 */
+#define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 - 4.1 */
+
+/*
+ * EXT_CSD fields
+ */
+
+#define EXT_CSD_BADBLK_MGMT 134 /* R/W */
+#define EXT_CSD_ENH_START_ADDR 136 /* R/W 4 bytes */
+#define EXT_CSD_ENH_SIZE_MULT 140 /* R/W 3 bytes */
+#define EXT_CSD_GP1_SIZE_MULT 143 /* R/W 3 bytes */
+#define EXT_CSD_GP2_SIZE_MULT 146 /* R/W 3 bytes */
+#define EXT_CSD_GP3_SIZE_MULT 149 /* R/W 3 bytes */
+#define EXT_CSD_GP4_SIZE_MULT 152 /* R/W 3 bytes */
+#define EXT_CSD_PART_SET_COMPL 155 /* R/W */
+#define EXT_CSD_PART_ATTR 156 /* R/W 3 bytes */
+#define EXT_CSD_MAX_ENH_SIZE_MULT 157 /* R/W 3 bytes */
+#define EXT_CSD_PART_SUPPORT 160 /* R */
+#define EXT_CSD_HPI_MGMT 161 /* R/W/E_P (4.41) */
+#define EXT_CSD_RST_N_FUNC 162 /* R/W */
+#define EXT_CSD_BKOPS_EN 163 /* R/W (4.41) */
+#define EXT_CSD_BKOPS_START 164 /* W/E_P (4.41) */
+#define EXT_CSD_WR_REL_PARAM 166 /* R (4.41) */
+#define EXT_CSD_WR_REL_SET 167 /* R/W (4.41) */
+#define EXT_CSD_RPMB_SIZE_MULT 168 /* R */
+#define EXT_CSD_FW_CONFIG 169 /* R/W */
+#define EXT_CSD_USR_WP 171 /* R/W, R/W/C_P & R/W/E_P */
+#define EXT_CSD_BOOT_WP 173 /* R/W, R/W/C_P */
+#define EXT_CSD_ERASE_GRP_DEF 175 /* R/W/E */
+#define EXT_CSD_BOOT_BUS_WIDTH 177 /* R/W/E */
+#define EXT_CSD_BOOT_CONFIG_PROT 178 /* R/W & R/W/C_P */
+#define EXT_CSD_PART_CFG 179 /* R/W/E & R/W/E_P */
+#define EXT_CSD_ERASED_MEM_CONT 181 /* R */
+#define EXT_CSD_BUS_WIDTH 183 /* R/W */
+#define EXT_CSD_HS_TIMING 185 /* R/W */
+#define EXT_CSD_PWR_CLASS 187 /* R/W/E_P */
+#define EXT_CSD_CMD_SET_REV 189 /* R */
+#define EXT_CSD_CMD_SET 191 /* R/W/E_P */
+#define EXT_CSD_REV 192 /* R */
+#define EXT_CSD_STRUCT 194 /* R */
+#define EXT_CSD_CARD_TYPE 196 /* RO */
+#define EXT_CSD_OUT_OF_INTR_TIME 198 /* R (4.41) */
+#define EXT_CSD_PART_SWITCH_TIME 199 /* R (4.41) */
+#define EXT_CSD_PWR_CL_52_195 200 /* R */
+#define EXT_CSD_PWR_CL_26_195 201 /* R */
+#define EXT_CSD_PWR_CL_52_360 202 /* R */
+#define EXT_CSD_PWR_CL_26_360 203 /* R */
+#define EXT_CSD_MIN_PERF_R_4_26 205 /* R */
+#define EXT_CSD_MIN_PERF_W_4_26 206 /* R */
+#define EXT_CSD_MIN_PERF_R_8_26_4_25 207 /* R */
+#define EXT_CSD_MIN_PERF_W_8_26_4_25 208 /* R */
+#define EXT_CSD_MIN_PERF_R_8_52 209 /* R */
+#define EXT_CSD_MIN_PERF_W_8_52 210 /* R */
+#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
+#define EXT_CSD_S_A_TIMEOUT 217 /* R */
+#define EXT_CSD_S_C_VCCQ 219 /* R */
+#define EXT_CSD_S_C_VCC 220 /* R */
+#define EXT_CSD_HC_WP_GPR_SIZE 221 /* R */
+#define EXT_CSD_REL_WR_SEC_C 222 /* R */
+#define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* R */
+#define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* R */
+#define EXT_CSD_ACC_SIZE 225 /* R */
+#define EXT_CSD_BOOT_SIZE_MULT 226 /* R */
+#define EXT_CSD_BOOT_INFO 228 /* R */
+#define EXT_CSD_SEC_TRIM_MULT 229 /* R */
+#define EXT_CSD_SEC_ERASE_MULT 230 /* R */
+#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* R */
+#define EXT_CSD_TRIM_MULT 232 /* R */
+#define EXT_CSD_MIN_PERF_DDR_R_8_52 234 /* R */
+#define EXT_CSD_MIN_PERF_DDR_W_8_52 235 /* R */
+#define EXT_CSD_PWR_CL_DDR_52_195 238 /* R */
+#define EXT_CSD_PWR_CL_DDR_52_360 239 /* R */
+#define EXT_CSD_INI_TIMEOUT_AP 241 /* R */
+#define EXT_CSD_CORRECT_PRG_SECTS_NUM 242 /* R, 4 bytes (4.41) */
+#define EXT_CSD_BKOPS_STATUS 246 /* R (4.41) */
+#define EXT_CSD_BKOPS_SUPP 502 /* R (4.41) */
+#define EXT_CSD_HPI_FEATURE 503 /* R (4.41) */
+#define EXT_CSD_S_CMD_SET 504 /* R */
+
+/*
+ * EXT_CSD field definitions
+ */
+
+/* SEC_FEATURE_SUPPORT[231] */
+#define EXT_CSD_SEC_FEATURE_ER_EN (1<<0)
+#define EXT_CSD_SEC_FEATURE_BD_BLK_EN (1<<2)
+#define EXT_CSD_SEC_FEATURE_GB_CL_EN (1<<4)
+
+/* BOOT_INFO[228] */
+#define EXT_CSD_BOOT_INFO_ALT_BOOT (1<<0)
+#define EXT_CSD_BOOT_INFO_DDR_BOOT (1<<1)
+#define EXT_CSD_BOOT_INFO_HS_BOOT (1<<2)
+
+#define EXT_CSD_CMD_SET_NORMAL (1<<0)
+#define EXT_CSD_CMD_SET_SECURE (1<<1)
+#define EXT_CSD_CMD_SET_CPSECURE (1<<2)
+
+#define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_DDR_52 (1<<2) /* Card can run at DDR 52MHz@1.8V or 3V */
+#define EXT_CSD_CARD_TYPE_DDR_52_1_2V (1<<3) /* Card can run at DDR 52MHz@1.2V */
+#define EXT_CSD_CARD_TYPE_HS200_1_8V (1<<4) /* Card can run at 200MHz@ 1.8V*/
+#define EXT_CSD_CARD_TYPE_HS200_1_2V (1<<5) /* Card can run at 200MHz@ 1.2V*/
+#define EXT_CSD_CARD_TYPE_HS400_1_8V (1<<6) /* Card can run at 200MHz@ 1.8V*/
+#define EXT_CSD_CARD_TYPE_HS400_1_2V (1<<7) /* Card can run at 200MHz@ 1.2V*/
+
+/* BUS_WIDTH[183] */
+#define EXT_CSD_BUS_WIDTH_1 (0) /* Card is in 1 bit mode */
+#define EXT_CSD_BUS_WIDTH_4 (1) /* Card is in 4 bit mode */
+#define EXT_CSD_BUS_WIDTH_8 (2) /* Card is in 8 bit mode */
+#define EXT_CSD_BUS_WIDTH_4_DDR (5) /* Card is in 4 bit mode + DDR */
+#define EXT_CSD_BUS_WIDTH_8_DDR (6) /* Card is in 8 bit mode + DDR */
+
+/* high speed timing */
+#define EXT_CSD_HS_TIMEING_BACKWARDS (0) /* selecting backwards compatibility interface timing */
+#define EXT_CSD_HS_TIMEING_HS (1) /* selecting high speed interface timing */
+#define EXT_CSD_HS_TIMEING_HS200 (2) /* selecting hs200 interface timing */
+#define EXT_CSD_HS_TIMEING_HS400 (3) /* selecting hs400 interface timing */
+
+/* ERASED_MEM_CONT[181] */
+#define EXT_CSD_ERASED_MEM_CONT_0 (0)
+#define EXT_CSD_ERASED_MEM_CONT_1 (1)
+
+/* PARTITION CONFIG[179] */
+#define EXT_CSD_PART_CFG_DEFT_PART (0)
+#define EXT_CSD_PART_CFG_BOOT_PART_1 (1)
+#define EXT_CSD_PART_CFG_BOOT_PART_2 (2)
+#define EXT_CSD_PART_CFG_RPMB_PART (3)
+#define EXT_CSD_PART_CFG_GP_PART_1 (4)
+#define EXT_CSD_PART_CFG_GP_PART_2 (5)
+#define EXT_CSD_PART_CFG_GP_PART_3 (6)
+#define EXT_CSD_PART_CFG_GP_PART_4 (7)
+#define EXT_CSD_PART_CFG_EN_NO_BOOT (0 << 3)
+#define EXT_CSD_PART_CFG_EN_BOOT_PART_1 (1 << 3)
+#define EXT_CSD_PART_CFG_EN_BOOT_PART_2 (2 << 3)
+#define EXT_CSD_PART_CFG_EN_USER_AREA (7 << 3)
+#define EXT_CSD_PART_CFG_EN_NO_ACK (0 << 6)
+#define EXT_CSD_PART_CFG_EN_ACK (1 << 6)
+
+/* BOOT_CONFIG_PROT[178] */
+#define EXT_CSD_EN_PWR_BOOT_CFG_PROT (1)
+#define EXT_CSD_EN_PERM_BOOT_CFG_PROT (1<<4) /* Carefully */
+
+/* BOOT_BUS_WIDTH[177] */
+#define EXT_CSD_BOOT_BUS_WIDTH_1 (0)
+#define EXT_CSD_BOOT_BUS_WIDTH_4 (1)
+#define EXT_CSD_BOOT_BUS_WIDTH_8 (2)
+#define EXT_CSD_BOOT_BUS_RESET (1 << 2)
+
+#define EXT_CSD_BOOT_BUS_MODE_DEFT (0 << 3)
+#define EXT_CSD_BOOT_BUS_MODE_HS (1 << 3)
+#define EXT_CSD_BOOT_BUS_MODE_DDR (2 << 3)
+
+/* ERASE_GROUP_DEF[175] */
+#define EXT_CSD_ERASE_GRP_DEF_EN (1)
+
+/* BOOT_WP[173] */
+#define EXT_CSD_BOOT_WP_EN_PWR_WP (1)
+#define EXT_CSD_BOOT_WP_EN_PERM_WP (1 << 2)
+#define EXT_CSD_BOOT_WP_DIS_PERM_WP (1 << 4)
+#define EXT_CSD_BOOT_WP_DIS_PWR_WP (1 << 6)
+
+/* USER_WP[171] */
+#define EXT_CSD_USR_WP_EN_PWR_WP (1)
+#define EXT_CSD_USR_WP_EN_PERM_WP (1<<2)
+#define EXT_CSD_USR_WP_DIS_PWR_WP (1<<3)
+#define EXT_CSD_USR_WP_DIS_PERM_WP (1<<4)
+#define EXT_CSD_USR_WP_DIS_CD_PERM_WP (1<<6)
+#define EXT_CSD_USR_WP_DIS_PERM_PWD (1<<7)
+
+/* RST_n_FUNCTION[162] */
+#define EXT_CSD_RST_N_TEMP_DIS (0)
+#define EXT_CSD_RST_N_PERM_EN (1) /* carefully */
+#define EXT_CSD_RST_N_PERM_DIS (2) /* carefully */
+
+/* PARTITIONING_SUPPORT[160] */
+#define EXT_CSD_PART_SUPPORT_PART_EN (1)
+#define EXT_CSD_PART_SUPPORT_ENH_ATTR_EN (1<<1)
+
+/* PARTITIONS_ATTRIBUTE[156] */
+#define EXT_CSD_PART_ATTR_ENH_USR (1<<0)
+#define EXT_CSD_PART_ATTR_ENH_1 (1<<1)
+#define EXT_CSD_PART_ATTR_ENH_2 (1<<2)
+#define EXT_CSD_PART_ATTR_ENH_3 (1<<3)
+#define EXT_CSD_PART_ATTR_ENH_4 (1<<4)
+
+/* PARTITION_SETTING_COMPLETED[156] */
+#define EXT_CSD_PART_SET_COMPL_BIT (1<<0)
+
+/*
+ * MMC_SWITCH access modes
+ */
+
+#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */
+#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits which are 1 in value */
+#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */
+#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */
+
+#define MMC_SWITCH_MODE_SDR12 0
+#define MMC_SWITCH_MODE_SDR25 1
+#define MMC_SWITCH_MODE_SDR50 2
+#define MMC_SWITCH_MODE_SDR104 3
+#define MMC_SWITCH_MODE_DDR50 4
+
+#define MMC_SWITCH_MODE_DRV_TYPE_B 0
+#define MMC_SWITCH_MODE_DRV_TYPE_A 1
+#define MMC_SWITCH_MODE_DRV_TYPE_C 2
+#define MMC_SWITCH_MODE_DRV_TYPE_D 3
+
+#define MMC_SWITCH_MODE_CL_200MA 0
+#define MMC_SWITCH_MODE_CL_400MA 1
+#define MMC_SWITCH_MODE_CL_600MA 2
+#define MMC_SWITCH_MODE_CL_800MA 3
+
+/*
+ * MMC_ERASE arguments
+ */
+#define MMC_ERASE_SECURE_REQ (1 << 31)
+#define MMC_ERASE_GC_REQ (1 << 15)
+#define MMC_ERASE_DISCARD (3 << 0)
+#define MMC_ERASE_TRIM (1 << 0)
+#define MMC_ERASE_NORMAL (0)
+
+#define HOST_BUS_WIDTH_1 (1)
+#define HOST_BUS_WIDTH_4 (4)
+#define HOST_BUS_WIDTH_8 (8)
+
+#define EMMC_BOOT_PULL_CMD_MODE (0)
+#define EMMC_BOOT_RST_CMD_MODE (1)
+
+enum {
+ EMMC_BOOT_PWR_RESET = 0,
+ EMMC_BOOT_RST_N_SIG,
+ EMMC_BOOT_PRE_IDLE_CMD
+};
+
+enum {
+ RESP_NONE = 0,
+ RESP_R1,
+ RESP_R2,
+ RESP_R3,
+ RESP_R4,
+ RESP_R5,
+ RESP_R6,
+ RESP_R7,
+ RESP_R1B
+};
+
+struct mmc_csd {
+ unsigned char mmca_vsn;
+ unsigned int max_dtr; /* max. data transfer rate */
+ unsigned int read_blkbits; /* max. read data block length */
+ unsigned int capacity; /* card capacity */
+};
+
+struct mmc_ext_csd {
+ unsigned int sectors;
+ unsigned int hs_max_dtr;
+ unsigned char rev;
+ unsigned char boot_info;
+ unsigned int boot_part_sz;
+ unsigned int rpmb_sz;
+ unsigned char ddr_support;
+ unsigned char part_cfg;
+ unsigned char sec_support;
+ unsigned char reset_en;
+};
+
+#define MMC_CAP_4_BIT_DATA (1 << 0) /* Can the host do 4 bit transfers */
+#define MMC_CAP_MULTIWRITE (1 << 1) /* Can accurately report bytes sent to card on error */
+#define MMC_CAP_BYTEBLOCK (1 << 2) /* Can do non-log2 block sizes */
+#define MMC_CAP_MMC_HIGHSPEED (1 << 3) /* Can do MMC high-speed timing */
+#define MMC_CAP_SD_HIGHSPEED (1 << 4) /* Can do SD high-speed timing */
+#define MMC_CAP_8_BIT_DATA (1 << 5) /* Can the host do 8 bit transfers */
+#define MMC_CAP_SD_UHS1 (1 << 6) /* Can do SD ultra-high-speed timing */
+#define MMC_CAP_DDR (1 << 7) /* The host support dual data rate */
+#define MMC_CAP_EMMC_HS200 (1 << 8) /* The host support dual data rate */
+#define MMC_CAP_EMMC_HS400 (1 << 9) /* The host support dual data rate */
+
+struct mmc_host {
+ struct mmc_card *card;
+ u32 max_phys_segs;
+ addr_t base; /* host base address */
+ u32 caps; /* Host capabilities */
+ u32 f_min; /* host min. frequency */
+ u32 f_max; /* host max. frequency */
+ u32 clk; /* host clock speed */
+ u32 sclk; /* SD/MS clock speed */
+ u32 blklen; /* block len */
+ u32 ocr; /* current ocr */
+ u32 ocr_avail; /* available ocr */
+ u32 timeout_ns; /* data timeout ns */
+ u32 timeout_clks; /* data timeout clks */
+ u8 clksrc; /* clock source */
+ u8 hclksrc; /* clock source */
+ u8 curr_part; /* host current working partition */
+ u32 intr_mask; /* Interrupt mask */
+ u32 time_read;
+ void *priv; /* private data */
+ mutex_t lock; /* mutex lock for multi-thread */
+ int (*blk_read)(struct mmc_host *host, u8 *dst, u32 src, u32 nblks);
+ int (*blk_write)(struct mmc_host *host, u32 dst, u8 *src, u32 nblks);
+};
+
+#define MMC_TYPE_UNKNOWN (0) /* Unknown card */
+#define MMC_TYPE_MMC (0x00000001) /* MMC card */
+#define MMC_TYPE_SD (0x00000002) /* SD card */
+#define MMC_TYPE_SDIO (0x00000004) /* SDIO card */
+
+/* MMC device */
+struct mmc_card {
+ struct mmc_host *host; /* the host this device belongs to */
+ unsigned int nblks;
+ unsigned int blklen;
+ unsigned int ocr;
+ unsigned int maxhz;
+ unsigned int uhs_mode;
+ unsigned int rca; /* relative card address of device */
+ unsigned int type; /* card type */
+ unsigned int sdio_funcs; /* number of SDIO functions */
+ unsigned short state; /* (our) card state */
+ unsigned short ready; /* card is ready or not */
+ struct mmc_csd csd; /* card specific */
+ struct mmc_ext_csd ext_csd; /* mmc v4 extended card specific */
+ u8 version; /* the SD card version, 1.0, 2.0, or 3.0*/
+};
+
+struct mmc_command {
+ u32 opcode;
+ u32 arg;
+ u32 rsptyp;
+ u32 resp[4];
+ u32 timeout;
+ u32 retries; /* max number of retries */
+ u32 error; /* command error */
+};
+
+struct mmc_data {
+ u8 *buf;
+ struct mmc_command *cmd;
+ u32 blks;
+ u32 timeout; /* ms */
+};
+
+#define mmc_card_set_host(c,h) ((c)->host = (h))
+#define mmc_card_set_unknown(c) ((c)->type = MMC_TYPE_UNKNOWN)
+
+#define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT)
+#define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY)
+#define mmc_card_backyard(c) ((c)->state & MMC_STATE_BACKYARD)
+#define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED)
+#define mmc_card_uhs1(c) ((c)->state & MMC_STATE_UHS1)
+#define mmc_card_hs200(c) ((c)->state & MMC_STATE_HS200)
+#define mmc_card_hs400(c) ((c)->state & MMC_STATE_HS400)
+#define mmc_card_ddr(c) ((c)->state & MMC_STATE_DDR)
+#define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR)
+#define mmc_card_highcaps(c) ((c)->state & MMC_STATE_HIGHCAPS)
+
+#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
+#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
+#define mmc_card_set_backyard(c) ((c)->state |= MMC_STATE_BACKYARD)
+#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
+#define mmc_card_set_uhs1(c) ((c)->state |= MMC_STATE_UHS1)
+#define mmc_card_set_hs200(c) ((c)->state |= MMC_STATE_HS200)
+#define mmc_card_set_hs400(c) ((c)->state |= MMC_STATE_HS400)
+#define mmc_card_set_ddr(c) ((c)->state |= MMC_STATE_DDR)
+#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
+
+#define mmc_card_clear_present(c) ((c)->state &= ~MMC_STATE_PRESENT)
+#define mmc_card_clear_readonly(c) ((c)->state &= ~MMC_STATE_READONLY)
+#define mmc_card_clear_highspeed(c) ((c)->state &= ~MMC_STATE_HIGHSPEED)
+#define mmc_card_clear_uhs1(c) ((c)->state &= ~MMC_STATE_UHS1)
+#define mmc_card_clear_hs200(c) ((c)->state &= ~MMC_STATE_HS200)
+#define mmc_card_clear_hs400(c) ((c)->state &= ~MMC_STATE_HS400)
+#define mmc_card_clear_ddr(c) ((c)->state &= ~MMC_STATE_DDR)
+#define mmc_card_clear_blockaddr(c) ((c)->state &= ~MMC_STATE_BLOCKADDR)
+
+#define mmc_card_clr_ddr(c) ((c)->state &= ~MMC_STATE_DDR)
+#define mmc_card_clr_speed_mode(c) ((c)->state &= ~(MMC_STATE_HS400 | MMC_STATE_HS200 | MMC_STATE_UHS1 | MMC_STATE_HIGHSPEED | MMC_STATE_BACKYARD))
+
+#define mmc_card_name(c) ((c)->cid.prod_name)
+
+#define mmc_op_multi(op) (((op) == MMC_CMD_READ_MULTIPLE_BLOCK) || \
+ ((op) == MMC_CMD_WRITE_MULTIPLE_BLOCK))
+
+int emmc_init(void);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/bsp/lk/platform/mt2635/include/platform/mmc_ioctl.h b/src/bsp/lk/platform/mt2635/include/platform/mmc_ioctl.h
new file mode 100644
index 0000000..6afd29b
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/mmc_ioctl.h
@@ -0,0 +1,76 @@
+#ifndef LINUX_MMC_IOCTL_H
+#define LINUX_MMC_IOCTL_H
+
+#include <sys/types.h>
+#include "generic_ioctl.h"
+
+struct mmc_ioc_cmd {
+ /* Implies direction of data. true = write, false = read */
+ int write_flag;
+
+ /* Application-specific command. true = precede with CMD55 */
+ int is_acmd;
+
+ u32 opcode;
+ u32 arg;
+ u32 response[4]; /* CMD response */
+ unsigned int flags;
+ unsigned int blksz;
+ unsigned int blocks;
+
+ /*
+ * Sleep at least postsleep_min_us useconds, and at most
+ * postsleep_max_us useconds *after* issuing command. Needed for
+ * some read commands for which cards have no other way of indicating
+ * they're ready for the next command (i.e. there is no equivalent of
+ * a "busy" indicator for read operations).
+ */
+ unsigned int postsleep_min_us;
+ unsigned int postsleep_max_us;
+
+ /*
+ * Override driver-computed timeouts. Note the difference in units!
+ */
+ unsigned int data_timeout_ns;
+ unsigned int cmd_timeout_ms;
+
+ /*
+ * For 64-bit machines, the next member, ``u64 data_ptr``, wants to
+ * be 8-byte aligned. Make sure this struct is the same size when
+ * built for 32-bit.
+ */
+ u32 __pad;
+
+ /* DAT buffer */
+ u64 data_ptr;
+};
+#define mmc_ioc_cmd_set_data(ic, ptr) ic.data_ptr = (u64)(unsigned long) ptr
+
+/**
+ * struct mmc_ioc_multi_cmd - multi command information
+ * @num_of_cmds: Number of commands to send. Must be equal to or less than
+ * MMC_IOC_MAX_CMDS.
+ * @cmds: Array of commands with length equal to 'num_of_cmds'
+ */
+struct mmc_ioc_multi_cmd {
+ u64 num_of_cmds;
+ struct mmc_ioc_cmd cmds[0];
+};
+
+#define MMC_BLOCK_MAJOR 179
+#define MMC_IOC_CMD _IOWR(MMC_BLOCK_MAJOR, 0, struct mmc_ioc_cmd)
+/*
+ * MMC_IOC_MULTI_CMD: Used to send an array of MMC commands described by
+ * the structure mmc_ioc_multi_cmd. The MMC driver will issue all
+ * commands in array in sequence to card.
+ */
+#define MMC_IOC_MULTI_CMD _IOWR(MMC_BLOCK_MAJOR, 1, struct mmc_ioc_multi_cmd)
+/*
+ * Since this ioctl is only meant to enhance (and not replace) normal access
+ * to the mmc bus device, an upper data transfer limit of MMC_IOC_MAX_BYTES
+ * is enforced per ioctl call. For larger data transfers, use the normal
+ * block device operations.
+ */
+#define MMC_IOC_MAX_BYTES (512L * 1024)
+#define MMC_IOC_MAX_CMDS 255
+#endif /* LINUX_MMC_IOCTL_H */
diff --git a/src/bsp/lk/platform/mt2635/include/platform/mmc_rpmb.h b/src/bsp/lk/platform/mt2635/include/platform/mmc_rpmb.h
new file mode 100755
index 0000000..74e46d1
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/mmc_rpmb.h
@@ -0,0 +1,57 @@
+
+
+#ifndef _MMC_RPMB_H
+#define _MMC_RPMB_H
+
+#include "mmc_core.h"
+
+/* ==================================================================================
+
+ RPMB definition
+
+====================================================================================*/
+#define RPMB_SZ_STUFF 196
+#define RPMB_SZ_MAC 32
+#define RPMB_SZ_DATA 256
+#define RPMB_SZ_NONCE 16
+
+#define RPMB_PROGRAM_KEY 1 /* Program RPMB Authentication Key */
+#define RPMB_GET_WRITE_COUNTER 2 /* Read RPMB write counter */
+#define RPMB_WRITE_DATA 3 /* Write data to RPMB partition */
+#define RPMB_READ_DATA 4 /* Read data from RPMB partition */
+#define RPMB_RESULT_READ 5 /* Read result request */
+#define RPMB_REQ 1 /* RPMB request mark */
+#define RPMB_RESP (1 << 1)/* RPMB response mark */
+#define RPMB_AVALIABLE_SECTORS 8 /* 4K page size */
+
+#define RPMB_TYPE_BEG 510
+#define RPMB_RES_BEG 508
+#define RPMB_BLKS_BEG 506
+#define RPMB_ADDR_BEG 504
+#define RPMB_WCOUNTER_BEG 500
+
+#define RPMB_NONCE_BEG 484
+#define RPMB_DATA_BEG 228
+#define RPMB_MAC_BEG 196
+
+struct mmc_rpmb_cfg {
+ u16 type; /* RPMB request type */
+ u16 result; /* response or request result */
+ u16 blk_cnt; /* Number of blocks(half sector 256B) */
+ u16 addr; /* data address */
+ u32 *wc; /* write counter */
+ u8 *nonce; /* Ramdom number */
+ u8 *data; /* Buffer of the user data */
+ u8 *mac; /* Message Authentication Code */
+};
+
+struct mmc_rpmb_req {
+ struct mmc_rpmb_cfg *rpmb_cfg;
+ u8 *data_frame;
+};
+
+extern int mmc_rpmb_set_key(u8 *key);
+extern u32 mmc_rpmb_get_size(void);
+extern u32 mmc_rpmb_get_rel_wr_sec_c(void);
+
+#endif
diff --git a/src/bsp/lk/platform/mt2635/include/platform/msdc.h b/src/bsp/lk/platform/mt2635/include/platform/msdc.h
new file mode 100644
index 0000000..43e6ee2
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/msdc.h
@@ -0,0 +1,1050 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+
+#include <reg.h>
+#include <platform/msdc_cfg.h>
+#include <platform/mt_reg_base.h>
+#include <platform/mmc_core.h>
+
+/*--------------------------------------------------------------------------*/
+/* Common Macro */
+/*--------------------------------------------------------------------------*/
+#define REG_ADDR(x) ((volatile uint32_t *)(base + OFFSET_##x))
+
+/*--------------------------------------------------------------------------*/
+/* Common Definition */
+/*--------------------------------------------------------------------------*/
+#define MSDC_FIFO_SZ (128)
+#define MSDC_FIFO_THD (128)
+//#define MSDC_MAX_NUM (2)
+
+#define MSDC_MS (0)
+#define MSDC_SDMMC (1)
+
+#define MSDC_MODE_UNKNOWN (0)
+#define MSDC_MODE_PIO (1)
+#define MSDC_MODE_DMA_BASIC (2)
+#define MSDC_MODE_DMA_DESC (3)
+#define MSDC_MODE_DMA_ENHANCED (4)
+#define MSDC_MODE_MMC_STREAM (5)
+
+#define MSDC_BUS_1BITS (0)
+#define MSDC_BUS_4BITS (1)
+#define MSDC_BUS_8BITS (2)
+
+#define MSDC_BURST_8B (3)
+#define MSDC_BURST_16B (4)
+#define MSDC_BURST_32B (5)
+#define MSDC_BURST_64B (6)
+
+#define MSDC_PIN_PULL_NONE (0)
+#define MSDC_PIN_PULL_DOWN (1)
+#define MSDC_PIN_PULL_UP (2)
+#define MSDC_PIN_KEEP (3)
+
+#ifdef FPGA_PLATFORM
+#define MSDC_OP_SCLK (12000000)
+#define MSDC_MAX_SCLK MSDC_OP_SCLK
+#else
+#define MSDC_OP_SCLK (200000000)
+#define MSDC_MAX_SCLK (400000000)
+#endif
+
+#define MSDC_MIN_SCLK (260000)
+
+#define MSDC_350K_SCLK (350000)
+#define MSDC_400K_SCLK (400000)
+#define MSDC_25M_SCLK (25000000)
+#define MSDC_26M_SCLK (26000000)
+#define MSDC_50M_SCLK (50000000)
+#define MSDC_52M_SCLK (52000000)
+#define MSDC_100M_SCLK (100000000)
+#define MSDC_179M_SCLK (179000000)
+#define MSDC_200M_SCLK (200000000)
+#define MSDC_208M_SCLK (208000000)
+#define MSDC_400M_SCLK (400000000)
+#define MSDC_800M_SCLK (800000000)
+
+#define MSDC_AUTOCMD12 (0x0001)
+#define MSDC_AUTOCMD23 (0x0002)
+#define MSDC_AUTOCMD19 (0x0003)
+
+#define TYPE_CMD_RESP_EDGE (0)
+#define TYPE_WRITE_CRC_EDGE (1)
+#define TYPE_READ_DATA_EDGE (2)
+#define TYPE_WRITE_DATA_EDGE (3)
+
+#define START_AT_RISING (0x0)
+#define START_AT_FALLING (0x1)
+#define START_AT_RISING_AND_FALLING (0x2)
+#define START_AT_RISING_OR_FALLING (0x3)
+
+#define MSDC_DMA_BURST_8B (3)
+#define MSDC_DMA_BURST_16B (4)
+#define MSDC_DMA_BURST_32B (5)
+#define MSDC_DMA_BURST_64B (6)
+
+/*--------------------------------------------------------------------------*/
+/* Register Offset */
+/*--------------------------------------------------------------------------*/
+#define OFFSET_MSDC_CFG (0x00)
+#define OFFSET_MSDC_IOCON (0x04)
+#define OFFSET_MSDC_PS (0x08)
+#define OFFSET_MSDC_INT (0x0c)
+#define OFFSET_MSDC_INTEN (0x10)
+#define OFFSET_MSDC_FIFOCS (0x14)
+#define OFFSET_MSDC_TXDATA (0x18)
+#define OFFSET_MSDC_RXDATA (0x1c)
+#define OFFSET_SDC_CFG (0x30)
+#define OFFSET_SDC_CMD (0x34)
+#define OFFSET_SDC_ARG (0x38)
+#define OFFSET_SDC_STS (0x3c)
+#define OFFSET_SDC_RESP0 (0x40)
+#define OFFSET_SDC_RESP1 (0x44)
+#define OFFSET_SDC_RESP2 (0x48)
+#define OFFSET_SDC_RESP3 (0x4c)
+#define OFFSET_SDC_BLK_NUM (0x50)
+#define OFFSET_SDC_VOL_CHG (0x54)
+#define OFFSET_SDC_CSTS (0x58)
+#define OFFSET_SDC_CSTS_EN (0x5c)
+#define OFFSET_SDC_DCRC_STS (0x60)
+
+/* Only for EMMC Controller 4 registers below */
+#define OFFSET_EMMC_CFG0 (0x70)
+#define OFFSET_EMMC_CFG1 (0x74)
+#define OFFSET_EMMC_STS (0x78)
+#define OFFSET_EMMC_IOCON (0x7c)
+
+#define OFFSET_SDC_ACMD_RESP (0x80)
+#define OFFSET_SDC_ACMD19_TRG (0x84)
+#define OFFSET_SDC_ACMD19_STS (0x88)
+#define OFFSET_MSDC_DMA_HIGH4BIT (0x8C)
+#define OFFSET_MSDC_DMA_SA (0x90)
+#define OFFSET_MSDC_DMA_CA (0x94)
+#define OFFSET_MSDC_DMA_CTRL (0x98)
+#define OFFSET_MSDC_DMA_CFG (0x9c)
+#define OFFSET_MSDC_DBG_SEL (0xa0)
+#define OFFSET_MSDC_DBG_OUT (0xa4)
+#define OFFSET_MSDC_DMA_LEN (0xa8)
+#define OFFSET_MSDC_PATCH_BIT0 (0xb0)
+#define OFFSET_MSDC_PATCH_BIT1 (0xb4)
+#define OFFSET_MSDC_PATCH_BIT2 (0xb8)
+
+/* Only for SD/SDIO Controller 6 registers below */
+#define OFFSET_DAT0_TUNE_CRC (0xc0)
+#define OFFSET_DAT1_TUNE_CRC (0xc4)
+#define OFFSET_DAT2_TUNE_CRC (0xc8)
+#define OFFSET_DAT3_TUNE_CRC (0xcc)
+#define OFFSET_CMD_TUNE_CRC (0xd0)
+#define OFFSET_SDIO_TUNE_WIND (0xd4)
+
+#define OFFSET_MSDC_PAD_TUNE (0xF0)
+#define OFFSET_MSDC_PAD_TUNE0 (0xF0)
+#define OFFSET_MSDC_PAD_TUNE1 (0xF4)
+#define OFFSET_MSDC_DAT_RDDLY0 (0xF8)
+#define OFFSET_MSDC_DAT_RDDLY1 (0xFC)
+
+#define OFFSET_MSDC_DAT_RDDLY2 (0x100)
+#define OFFSET_MSDC_DAT_RDDLY3 (0x104)
+
+#define OFFSET_MSDC_HW_DBG (0x110)
+#define OFFSET_MSDC_VERSION (0x114)
+#define OFFSET_MSDC_ECO_VER (0x118)
+
+/* Only for EMMC 5.0 Controller 4 registers below */
+#define OFFSET_EMMC50_PAD_CTL0 (0x180)
+#define OFFSET_EMMC50_PAD_DS_CTL0 (0x184)
+#define OFFSET_EMMC50_PAD_DS_TUNE (0x188)
+#define OFFSET_EMMC50_PAD_CMD_TUNE (0x18c)
+#define OFFSET_EMMC50_PAD_DAT01_TUNE (0x190)
+#define OFFSET_EMMC50_PAD_DAT23_TUNE (0x194)
+#define OFFSET_EMMC50_PAD_DAT45_TUNE (0x198)
+#define OFFSET_EMMC50_PAD_DAT67_TUNE (0x19c)
+#define OFFSET_EMMC51_CFG0 (0x204)
+#define OFFSET_EMMC50_CFG0 (0x208)
+#define OFFSET_EMMC50_CFG1 (0x20c)
+#define OFFSET_EMMC50_CFG2 (0x21c)
+#define OFFSET_EMMC50_CFG3 (0x220)
+#define OFFSET_EMMC50_CFG4 (0x224)
+#define OFFSET_EMMC50_BLOCK_LENGTH (0x228)
+/*--------------------------------------------------------------------------*/
+/* Register Address */
+/*--------------------------------------------------------------------------*/
+/* common register */
+#define MSDC_CFG REG_ADDR(MSDC_CFG)
+#define MSDC_IOCON REG_ADDR(MSDC_IOCON)
+#define MSDC_PS REG_ADDR(MSDC_PS)
+#define MSDC_INT REG_ADDR(MSDC_INT)
+#define MSDC_INTEN REG_ADDR(MSDC_INTEN)
+#define MSDC_FIFOCS REG_ADDR(MSDC_FIFOCS)
+#define MSDC_TXDATA REG_ADDR(MSDC_TXDATA)
+#define MSDC_RXDATA REG_ADDR(MSDC_RXDATA)
+
+/* sdmmc register */
+#define SDC_CFG REG_ADDR(SDC_CFG)
+#define SDC_CMD REG_ADDR(SDC_CMD)
+#define SDC_ARG REG_ADDR(SDC_ARG)
+#define SDC_STS REG_ADDR(SDC_STS)
+#define SDC_RESP0 REG_ADDR(SDC_RESP0)
+#define SDC_RESP1 REG_ADDR(SDC_RESP1)
+#define SDC_RESP2 REG_ADDR(SDC_RESP2)
+#define SDC_RESP3 REG_ADDR(SDC_RESP3)
+#define SDC_BLK_NUM REG_ADDR(SDC_BLK_NUM)
+#define SDC_VOL_CHG REG_ADDR(SDC_VOL_CHG)
+#define SDC_CSTS REG_ADDR(SDC_CSTS)
+#define SDC_CSTS_EN REG_ADDR(SDC_CSTS_EN)
+#define SDC_DCRC_STS REG_ADDR(SDC_DCRC_STS)
+
+/* emmc register*/
+#define EMMC_CFG0 REG_ADDR(EMMC_CFG0)
+#define EMMC_CFG1 REG_ADDR(EMMC_CFG1)
+#define EMMC_STS REG_ADDR(EMMC_STS)
+#define EMMC_IOCON REG_ADDR(EMMC_IOCON)
+
+/* auto command register */
+#define SDC_ACMD_RESP REG_ADDR(SDC_ACMD_RESP)
+#define SDC_ACMD19_TRG REG_ADDR(SDC_ACMD19_TRG)
+#define SDC_ACMD19_STS REG_ADDR(SDC_ACMD19_STS)
+
+/* dma register */
+#define MSDC_DMA_HIGH4BIT REG_ADDR(MSDC_DMA_HIGH4BIT)
+#define MSDC_DMA_SA REG_ADDR(MSDC_DMA_SA)
+#define MSDC_DMA_CA REG_ADDR(MSDC_DMA_CA)
+#define MSDC_DMA_CTRL REG_ADDR(MSDC_DMA_CTRL)
+#define MSDC_DMA_CFG REG_ADDR(MSDC_DMA_CFG)
+
+/* debug register */
+#define MSDC_DBG_SEL REG_ADDR(MSDC_DBG_SEL)
+#define MSDC_DBG_OUT REG_ADDR(MSDC_DBG_OUT)
+#define MSDC_DMA_LEN REG_ADDR(MSDC_DMA_LEN)
+
+/* misc register */
+#define MSDC_PATCH_BIT0 REG_ADDR(MSDC_PATCH_BIT0)
+#define MSDC_PATCH_BIT1 REG_ADDR(MSDC_PATCH_BIT1)
+#define MSDC_PATCH_BIT2 REG_ADDR(MSDC_PATCH_BIT2)
+#define DAT0_TUNE_CRC REG_ADDR(DAT0_TUNE_CRC)
+#define DAT1_TUNE_CRC REG_ADDR(DAT1_TUNE_CRC)
+#define DAT2_TUNE_CRC REG_ADDR(DAT2_TUNE_CRC)
+#define DAT3_TUNE_CRC REG_ADDR(DAT3_TUNE_CRC)
+#define CMD_TUNE_CRC REG_ADDR(CMD_TUNE_CRC)
+#define SDIO_TUNE_WIND REG_ADDR(SDIO_TUNE_WIND)
+#define MSDC_PAD_TUNE REG_ADDR(MSDC_PAD_TUNE)
+#define MSDC_PAD_TUNE0 REG_ADDR(MSDC_PAD_TUNE0)
+#define MSDC_PAD_TUNE1 REG_ADDR(MSDC_PAD_TUNE1)
+
+/* data read delay */
+#define MSDC_DAT_RDDLY0 REG_ADDR(MSDC_DAT_RDDLY0)
+#define MSDC_DAT_RDDLY1 REG_ADDR(MSDC_DAT_RDDLY1)
+#define MSDC_DAT_RDDLY2 REG_ADDR(MSDC_DAT_RDDLY2)
+#define MSDC_DAT_RDDLY3 REG_ADDR(MSDC_DAT_RDDLY3)
+
+#define MSDC_HW_DBG REG_ADDR(MSDC_HW_DBG)
+#define MSDC_VERSION REG_ADDR(MSDC_VERSION)
+#define MSDC_ECO_VER REG_ADDR(MSDC_ECO_VER)
+/* eMMC 5.0 register */
+#define EMMC50_PAD_CTL0 REG_ADDR(EMMC50_PAD_CTL0)
+#define EMMC50_PAD_DS_CTL0 REG_ADDR(EMMC50_PAD_DS_CTL0)
+#define EMMC50_PAD_DS_TUNE REG_ADDR(EMMC50_PAD_DS_TUNE)
+#define EMMC50_PAD_CMD_TUNE REG_ADDR(EMMC50_PAD_CMD_TUNE)
+#define EMMC50_PAD_DAT01_TUNE REG_ADDR(EMMC50_PAD_DAT01_TUNE)
+#define EMMC50_PAD_DAT23_TUNE REG_ADDR(EMMC50_PAD_DAT23_TUNE)
+#define EMMC50_PAD_DAT45_TUNE REG_ADDR(EMMC50_PAD_DAT45_TUNE)
+#define EMMC50_PAD_DAT67_TUNE REG_ADDR(EMMC50_PAD_DAT67_TUNE)
+#define EMMC51_CFG0 REG_ADDR(EMMC51_CFG0)
+#define EMMC50_CFG0 REG_ADDR(EMMC50_CFG0)
+#define EMMC50_CFG1 REG_ADDR(EMMC50_CFG1)
+#define EMMC50_CFG2 REG_ADDR(EMMC50_CFG2)
+#define EMMC50_CFG3 REG_ADDR(EMMC50_CFG3)
+#define EMMC50_CFG4 REG_ADDR(EMMC50_CFG4)
+#define EMMC50_BLOCK_LENGTH REG_ADDR(EMMC50_BLOCK_LENGTH)
+
+/*--------------------------------------------------------------------------*/
+/* Register Mask */
+/*--------------------------------------------------------------------------*/
+
+/* MSDC_CFG mask */
+#define MSDC_CFG_MODE (0x1 << 0) /* RW */
+#define MSDC_CFG_CKPDN (0x1 << 1) /* RW */
+#define MSDC_CFG_RST (0x1 << 2) /* A0 */
+#define MSDC_CFG_PIO (0x1 << 3) /* RW */
+#define MSDC_CFG_CKDRVEN (0x1 << 4) /* RW */
+#define MSDC_CFG_BV18SDT (0x1 << 5) /* RW */
+#define MSDC_CFG_BV18PSS (0x1 << 6) /* R */
+#define MSDC_CFG_CKSTB (0x1 << 7) /* R */
+#define MSDC_CFG_CKDIV (0xFFF << 8) /* RW !!! MT2701 change 0xFF ->0xFFF*/
+#define MSDC_CFG_CKMOD (0x3 << 20) /* W1C !!! MT2701 change 16 ->21 only for eMCC 5.0*/
+#define MSDC_CFG_CKMOD_HS400 (0x1 << 22) /* RW !!! MT2701 change 18 ->22 only for eMCC 5.0*/
+#define MSDC_CFG_START_BIT (0x3 << 23) /* RW !!! MT2701 change 19 ->23 only for eMCC 5.0*/
+#define MSDC_CFG_SCLK_STOP_DDR (0x1 << 25) /* RW !!! MT2701 change 21 ->25 */
+
+/* MSDC_IOCON mask */
+#define MSDC_IOCON_SDR104CKS (0x1 << 0) /* RW */
+#define MSDC_IOCON_RSPL (0x1 << 1) /* RW */
+#define MSDC_IOCON_R_D_SMPL (0x1 << 2) /* RW */
+#define MSDC_IOCON_DSPL MSDC_IOCON_R_D_SMPL /* alias */
+
+#define MSDC_IOCON_DDLSEL (0x1 << 3) /* RW */
+#define MSDC_IOCON_DDR50CKD (0x1 << 4) /* RW */
+#define MSDC_IOCON_R_D_SMPL_SEL (0x1 << 5) /* RW */
+#define MSDC_IOCON_W_D_SMPL (0x1 << 8) /* RW */
+#define MSDC_IOCON_W_D_SMPL_SEL (0x1 << 9) /* RW */
+#define MSDC_IOCON_W_D0SPL (0x1 << 10) /* RW */
+#define MSDC_IOCON_W_D1SPL (0x1 << 11) /* RW */
+#define MSDC_IOCON_W_D2SPL (0x1 << 12) /* RW */
+#define MSDC_IOCON_W_D3SPL (0x1 << 13) /* RW */
+
+#define MSDC_IOCON_R_D0SPL (0x1 << 16) /* RW */
+#define MSDC_IOCON_R_D1SPL (0x1 << 17) /* RW */
+#define MSDC_IOCON_R_D2SPL (0x1 << 18) /* RW */
+#define MSDC_IOCON_R_D3SPL (0x1 << 19) /* RW */
+#define MSDC_IOCON_R_D4SPL (0x1 << 20) /* RW */
+#define MSDC_IOCON_R_D5SPL (0x1 << 21) /* RW */
+#define MSDC_IOCON_R_D6SPL (0x1 << 22) /* RW */
+#define MSDC_IOCON_R_D7SPL (0x1 << 23) /* RW */
+//#define MSDC_IOCON_RISCSZ (0x3 << 24) /* RW !!! MT2701 remove*/
+
+/* MSDC_PS mask */
+#define MSDC_PS_CDEN (0x1 << 0) /* RW */
+#define MSDC_PS_CDSTS (0x1 << 1) /* RU */
+
+#define MSDC_PS_CDDEBOUNCE (0xF << 12) /* RW */
+#define MSDC_PS_DAT (0xFF << 16) /* RU */
+#define MSDC_PS_DAT8PIN (0xFF << 16) /* RU */
+#define MSDC_PS_DAT4PIN (0xF << 16) /* RU */
+#define MSDC_PS_DAT0 (0x1 << 16) /* RU */
+
+#define MSDC_PS_CMD (0x1 << 24) /* RU */
+
+#define MSDC_PS_WP (0x1 << 31) /* RU */
+
+/* MSDC_INT mask */
+#define MSDC_INT_MMCIRQ (0x1 << 0) /* W1C */
+#define MSDC_INT_CDSC (0x1 << 1) /* W1C */
+
+#define MSDC_INT_ACMDRDY (0x1 << 3) /* W1C */
+#define MSDC_INT_ACMDTMO (0x1 << 4) /* W1C */
+#define MSDC_INT_ACMDCRCERR (0x1 << 5) /* W1C */
+#define MSDC_INT_DMAQ_EMPTY (0x1 << 6) /* W1C */
+#define MSDC_INT_SDIOIRQ (0x1 << 7) /* W1C Only for SD/SDIO */
+#define MSDC_INT_CMDRDY (0x1 << 8) /* W1C */
+#define MSDC_INT_CMDTMO (0x1 << 9) /* W1C */
+#define MSDC_INT_RSPCRCERR (0x1 << 10) /* W1C */
+#define MSDC_INT_CSTA (0x1 << 11) /* R */
+#define MSDC_INT_XFER_COMPL (0x1 << 12) /* W1C */
+#define MSDC_INT_DXFER_DONE (0x1 << 13) /* W1C */
+#define MSDC_INT_DATTMO (0x1 << 14) /* W1C */
+#define MSDC_INT_DATCRCERR (0x1 << 15) /* W1C */
+#define MSDC_INT_ACMD19_DONE (0x1 << 16) /* W1C */
+#define MSDC_INT_BDCSERR (0x1 << 17) /* W1C */
+#define MSDC_INT_GPDCSERR (0x1 << 18) /* W1C */
+#define MSDC_INT_DMAPRO (0x1 << 19) /* W1C */
+#define MSDC_INT_GOBOUND (0x1 << 20) /* W1C Only for SD/SDIO ACMD 53*/
+#define MSDC_INT_ACMD53_DONE (0x1 << 21) /* W1C Only for SD/SDIO ACMD 53*/
+#define MSDC_INT_ACMD53_FAIL (0x1 << 22) /* W1C Only for SD/SDIO ACMD 53*/
+#define MSDC_INT_AXI_RESP_ERR (0x1 << 23) /* W1C Only for eMMC 5.0*/
+
+/* MSDC_INTEN mask */
+#define MSDC_INTEN_MMCIRQ (0x1 << 0) /* RW */
+#define MSDC_INTEN_CDSC (0x1 << 1) /* RW */
+
+#define MSDC_INTEN_ACMDRDY (0x1 << 3) /* RW */
+#define MSDC_INTEN_ACMDTMO (0x1 << 4) /* RW */
+#define MSDC_INTEN_ACMDCRCERR (0x1 << 5) /* RW */
+#define MSDC_INTEN_DMAQ_EMPTY (0x1 << 6) /* RW */
+#define MSDC_INTEN_SDIOIRQ (0x1 << 7) /* RW Only for SDIO*/
+#define MSDC_INTEN_CMDRDY (0x1 << 8) /* RW */
+#define MSDC_INTEN_CMDTMO (0x1 << 9) /* RW */
+#define MSDC_INTEN_RSPCRCERR (0x1 << 10) /* RW */
+#define MSDC_INTEN_CSTA (0x1 << 11) /* RW */
+#define MSDC_INTEN_XFER_COMPL (0x1 << 12) /* RW */
+#define MSDC_INTEN_DXFER_DONE (0x1 << 13) /* RW */
+#define MSDC_INTEN_DATTMO (0x1 << 14) /* RW */
+#define MSDC_INTEN_DATCRCERR (0x1 << 15) /* RW */
+#define MSDC_INTEN_ACMD19_DONE (0x1 << 16) /* RW */
+#define MSDC_INTEN_BDCSERR (0x1 << 17) /* RW */
+#define MSDC_INTEN_GPDCSERR (0x1 << 18) /* RW */
+#define MSDC_INTEN_DMAPRO (0x1 << 19) /* RW */
+#define MSDC_INTEN_GOBOUND (0x1 << 20) /* RW Only for SD/SDIO ACMD 53*/
+#define MSDC_INTEN_ACMD53_DONE (0x1 << 21) /* RW Only for SD/SDIO ACMD 53*/
+#define MSDC_INTEN_ACMD53_FAIL (0x1 << 22) /* RW Only for SD/SDIO ACMD 53*/
+#define MSDC_INTEN_AXI_RESP_ERR (0x1 << 23) /* RW Only for eMMC 5.0*/
+
+#define MSDC_INTEN_DFT ( MSDC_INTEN_MMCIRQ |MSDC_INTEN_CDSC | MSDC_INTEN_ACMDRDY\
+ |MSDC_INTEN_ACMDTMO |MSDC_INTEN_ACMDCRCERR | MSDC_INTEN_DMAQ_EMPTY /*|MSDC_INTEN_SDIOIRQ*/\
+ |MSDC_INTEN_CMDRDY |MSDC_INTEN_CMDTMO | MSDC_INTEN_RSPCRCERR |MSDC_INTEN_CSTA\
+ |MSDC_INTEN_XFER_COMPL |MSDC_INTEN_DXFER_DONE | MSDC_INTEN_DATTMO |MSDC_INTEN_DATCRCERR\
+ |MSDC_INTEN_BDCSERR |MSDC_INTEN_ACMD19_DONE | MSDC_INTEN_GPDCSERR /*|MSDC_INTEN_DMAPRO*/\
+ /*|MSDC_INTEN_GOBOUND |MSDC_INTEN_ACMD53_DONE |MSDC_INTEN_ACMD53_FAIL |MSDC_INTEN_AXI_RESP_ERR*/)
+
+
+/* MSDC_FIFOCS mask */
+#define MSDC_FIFOCS_RXCNT (0xFF << 0) /* R */
+#define MSDC_FIFOCS_TXCNT (0xFF << 16) /* R */
+#define MSDC_FIFOCS_CLR (0x1 << 31) /* RW */
+
+/* SDC_CFG mask */
+#define SDC_CFG_SDIOINTWKUP (0x1 << 0) /* RW */
+#define SDC_CFG_INSWKUP (0x1 << 1) /* RW */
+#define SDC_CFG_BUSWIDTH (0x3 << 16) /* RW */
+#define SDC_CFG_SDIO (0x1 << 19) /* RW */
+#define SDC_CFG_SDIOIDE (0x1 << 20) /* RW */
+#define SDC_CFG_INTATGAP (0x1 << 21) /* RW */
+#define SDC_CFG_DTOC (0xFF << 24) /* RW */
+
+/* SDC_CMD mask */
+#define SDC_CMD_OPC (0x3F << 0) /* RW */
+#define SDC_CMD_BRK (0x1 << 6) /* RW */
+#define SDC_CMD_RSPTYP (0x7 << 7) /* RW */
+#define SDC_CMD_DTYP (0x3 << 11) /* RW */
+#define SDC_CMD_RW (0x1 << 13) /* RW */
+#define SDC_CMD_STOP (0x1 << 14) /* RW */
+#define SDC_CMD_GOIRQ (0x1 << 15) /* RW */
+#define SDC_CMD_BLKLEN (0xFFF << 16) /* RW */
+#define SDC_CMD_AUTOCMD (0x3 << 28) /* RW */
+#define SDC_CMD_VOLSWTH (0x1 << 30) /* RW */
+#define SDC_CMD_ACMD53 (0x1 << 31) /* RW Only for SD/SDIO ACMD 53*/
+
+/* SDC_STS mask */
+#define SDC_STS_SDCBUSY (0x1 << 0) /* RW */
+#define SDC_STS_CMDBUSY (0x1 << 1) /* RW */
+#define SDC_STS_CMD_WR_BUSY (0x1 << 16) /* RW !!! MT2701 Add*/
+#define SDC_STS_SWR_COMPL (0x1 << 31) /* RW */
+
+/* SDC_VOL_CHG mask */
+#define SDC_VOL_CHG_VCHGCNT (0xFFFF<< 0) /* RW !!! MT2701 Add*/
+/* SDC_DCRC_STS mask */
+#define SDC_DCRC_STS_POS (0xFF << 0) /* RO */
+#define SDC_DCRC_STS_NEG (0xFF << 8) /* RO */
+
+/* EMMC_CFG0 mask */
+#define EMMC_CFG0_BOOTSTART (0x1 << 0) /* WO Only for eMMC */
+#define EMMC_CFG0_BOOTSTOP (0x1 << 1) /* WO Only for eMMC */
+#define EMMC_CFG0_BOOTMODE (0x1 << 2) /* RW Only for eMMC */
+#define EMMC_CFG0_BOOTACKDIS (0x1 << 3) /* RW Only for eMMC */
+
+#define EMMC_CFG0_BOOTWDLY (0x7 << 12) /* RW Only for eMMC */
+#define EMMC_CFG0_BOOTSUPP (0x1 << 15) /* RW Only for eMMC */
+
+/* EMMC_CFG1 mask */
+#define EMMC_CFG1_BOOTDATTMC (0xFFFFF<< 0) /* RW Only for eMMC */
+#define EMMC_CFG1_BOOTACKTMC (0xFFF << 20) /* RW Only for eMMC */
+
+/* EMMC_STS mask */
+#define EMMC_STS_BOOTCRCERR (0x1 << 0) /* W1C Only for eMMC */
+#define EMMC_STS_BOOTACKERR (0x1 << 1) /* W1C Only for eMMC */
+#define EMMC_STS_BOOTDATTMO (0x1 << 2) /* W1C Only for eMMC */
+#define EMMC_STS_BOOTACKTMO (0x1 << 3) /* W1C Only for eMMC */
+#define EMMC_STS_BOOTUPSTATE (0x1 << 4) /* RU Only for eMMC */
+#define EMMC_STS_BOOTACKRCV (0x1 << 5) /* W1C Only for eMMC */
+#define EMMC_STS_BOOTDATRCV (0x1 << 6) /* RU Only for eMMC */
+
+/* EMMC_IOCON mask */
+#define EMMC_IOCON_BOOTRST (0x1 << 0) /* RW Only for eMMC */
+
+/* SDC_ACMD19_TRG mask */
+#define SDC_ACMD19_TRG_TUNESEL (0xF << 0) /* RW */
+
+/* DMA_SA_HIGH4BIT mask */
+#define DMA_SA_HIGH4BIT_L4BITS (0xF << 0) /* RW !!! MT2701 Add*/
+/* MSDC_DMA_CTRL mask */
+#define MSDC_DMA_CTRL_START (0x1 << 0) /* WO */
+#define MSDC_DMA_CTRL_STOP (0x1 << 1) /* AO */
+#define MSDC_DMA_CTRL_RESUME (0x1 << 2) /* WO */
+#define MSDC_DMA_CTRL_READYM (0x1 << 3) /* RO !!! MT2701 Add*/
+
+#define MSDC_DMA_CTRL_MODE (0x1 << 8) /* RW */
+#define MSDC_DMA_CTRL_ALIGN (0x1 << 9) /* RW !!! MT2701 Add*/
+#define MSDC_DMA_CTRL_LASTBUF (0x1 << 10) /* RW */
+#define MSDC_DMA_CTRL_SPLIT1K (0x1 << 11) /* RW !!! MT2701 Add*/
+#define MSDC_DMA_CTRL_BURSTSZ (0x7 << 12) /* RW */
+// #define MSDC_DMA_CTRL_XFERSZ (0xffffUL << 16)/* RW */
+
+/* MSDC_DMA_CFG mask */
+#define MSDC_DMA_CFG_STS (0x1 << 0) /* R */
+#define MSDC_DMA_CFG_DECSEN (0x1 << 1) /* RW */
+#define MSDC_DMA_CFG_LOCKDISABLE (0x1 << 2) /* RW !!! MT2701 Add*/
+//#define MSDC_DMA_CFG_BDCSERR (0x1 << 4) /* R */
+//#define MSDC_DMA_CFG_GPDCSERR (0x1 << 5) /* R */
+#define MSDC_DMA_CFG_AHBEN (0x3 << 8) /* RW */
+#define MSDC_DMA_CFG_ACTEN (0x3 << 12) /* RW */
+
+#define MSDC_DMA_CFG_CS12B (0x1 << 16) /* RW */
+#define MSDC_DMA_CFG_OUTB_STOP (0x1 << 17) /* RW */
+
+/* MSDC_PATCH_BIT0 mask */
+//#define MSDC_PB0_RESV1 (0x1 << 0)
+#define MSDC_PB0_EN_8BITSUP (0x1 << 1) /* RW */
+#define MSDC_PB0_DIS_RECMDWR (0x1 << 2) /* RW */
+//#define MSDC_PB0_RESV2 (0x1 << 3)
+#define MSDC_PB0_RDDATSEL (0x1 << 3) /* RW !!! MT2701 Add for SD/SDIO/eMMC 4.5*/
+#define MSDC_PB0_ACMD53_CRCINTR (0x1 << 4) /* RW !!! MT2701 Add only for SD/SDIO */
+#define MSDC_PB0_ACMD53_ONESHOT (0x1 << 5) /* RW !!! MT2701 Add ony for SD/SDIO */
+//#define MSDC_PB0_RESV3 (0x1 << 6)
+#define MSDC_PB0_DESC_UP_SEL (0x1 << 6) /* RW !!! MT2701 Add*/
+#define MSDC_PB0_INT_DAT_LATCH_CK_SEL (0x7 << 7) /* RW */
+#define MSDC_INT_DAT_LATCH_CK_SEL MSDC_PB0_INT_DAT_LATCH_CK_SEL /* alias */
+
+#define MSDC_PB0_CKGEN_MSDC_DLY_SEL (0x1F << 10) /* RW */
+#define MSDC_CKGEN_MSDC_DLY_SEL MSDC_PB0_CKGEN_MSDC_DLY_SEL /* alias */
+
+
+#define MSDC_PB0_FIFORD_DIS (0x1 << 15) /* RW */
+//#define MSDC_PB0_SDIO_DBSSEL (0x1 << 16) /* RW !!! MT2701 change*/
+#define MSDC_PB0_MSDC_BLKNUMSEL (0x1 << 16) /* RW !!! MT2701 change ACMD23*/
+#define MSDC_PB0_BLKNUM_SEL MSDC_PB0_MSDC_BLKNUMSEL /* alias */
+
+#define MSDC_PB0_SDIO_INTCSEL (0x1 << 17) /* RW */
+#define MSDC_PB0_SDIO_BSYDLY (0xF << 18) /* RW */
+#define MSDC_PB0_SDC_WDOD (0xF << 22) /* RW */
+#define MSDC_PB0_CMDIDRTSEL (0x1 << 26) /* RW */
+#define MSDC_PB0_CMDFAILSEL (0x1 << 27) /* RW */
+#define MSDC_PB0_SDIO_INTDLYSEL (0x1 << 28) /* RW */
+#define MSDC_PB0_SPCPUSH (0x1 << 29) /* RW */
+#define MSDC_PB0_DETWR_CRCTMO (0x1 << 30) /* RW */
+#define MSDC_PB0_EN_DRVRSP (0x1 << 31) /* RW */
+
+/* MSDC_PATCH_BIT1 mask */
+#define MSDC_PB1_WRDAT_CRCS_TA_CNTR (0x7 << 0) /* RW */
+#define MSDC_PATCH_BIT1_WRDAT_CRCS MSDC_PB1_WRDAT_CRCS_TA_CNTR /* alias */
+
+
+#define MSDC_PB1_CMD_RSP_TA_CNTR (0x7 << 3) /* RW */
+#define MSDC_PATCH_BIT1_CMD_RSP MSDC_PB1_CMD_RSP_TA_CNTR /* alias */
+
+//#define MSDC_PB1_RESV3 (0x3 << 6)
+#define MSDC_PB1_GET_BUSY_MARGIN (0x1 << 6) /* RW !!! MT2701 Add */
+#define MSDC_PB1_GET_CRC_MARGIN (0x1 << 7) /* RW !!! MT2701 Add */
+#define MSDC_PB1_BIAS_TUNE_28NM (0xF << 8) /* RW */
+#define MSDC_PB1_BIAS_EN18IO_28NM (0x1 << 12) /* RW */
+#define MSDC_PB1_BIAS_EXT_28NM (0x1 << 13) /* RW */
+
+//#define MSDC_PB1_RESV2 (0x3 << 14)
+#define MSDC_PB1_RESET_GDMA (0x1 << 15) /* RW !!! MT2701 Add */
+//#define MSDC_PB1_RESV1 (0x7F << 16)
+#define MSDC_PB1_EN_SINGLE_BURST (0x1 << 16) /* RW !!! MT2701 Add */
+#define MSDC_PB1_EN_FORCE_STOP_GDMA (0x1 << 17) /* RW !!! MT2701 Add for eMMC 5.0 only*/
+#define MSDC_PB1_DCM_DIV_SEL2 (0x3 << 18) /* RW !!! MT2701 Add for eMMC 5.0 only*/
+#define MSDC_PB1_DCM_DIV_SEL1 (0x1 << 20) /* RW !!! MT2701 Add */
+#define MSDC_PB1_DCM_EN (0x1 << 21) /* RW !!! MT2701 Add */
+#define MSDC_PB1_AXI_WRAP_CKEN (0x1 << 22) /* RW !!! MT2701 Add for eMMC 5.0 only*/
+#define MSDC_PB1_AHBCKEN (0x1 << 23) /* RW */
+#define MSDC_PB1_CKSPCEN (0x1 << 24) /* RW */
+#define MSDC_PB1_CKPSCEN (0x1 << 25) /* RW */
+#define MSDC_PB1_CKVOLDETEN (0x1 << 26) /* RW */
+#define MSDC_PB1_CKACMDEN (0x1 << 27) /* RW */
+#define MSDC_PB1_CKSDEN (0x1 << 28) /* RW */
+#define MSDC_PB1_CKWCTLEN (0x1 << 29) /* RW */
+#define MSDC_PB1_CKRCTLEN (0x1 << 30) /* RW */
+#define MSDC_PB1_CKSHBFFEN (0x1 << 31) /* RW */
+
+/* MSDC_PATCH_BIT2 mask */
+#define MSDC_PB2_ENHANCEGPD (0x1 << 0) /* RW !!! MT2701 Add */
+#define MSDC_PB2_SUPPORT64G (0x1 << 1) /* RW !!! MT2701 Add */
+#define MSDC_PB2_RESPWAIT (0x3 << 2) /* RW !!! MT2701 Add */
+#define MSDC_PB2_CFGRDATCNT (0x1F << 4) /* RW !!! MT2701 Add */
+#define MSDC_PB2_CFGRDAT (0x1 << 9) /* RW !!! MT2701 Add */
+
+#define MSDC_PB2_INTCRESPSEL (0x1 << 11) /* RW !!! MT2701 Add */
+#define MSDC_PB2_CFGRESPCNT (0x7 << 12) /* RW !!! MT2701 Add */
+#define MSDC_PB2_CFGRESP (0x1 << 15) /* RW !!! MT2701 Add */
+#define MSDC_PB2_RESPSTSENSEL (0x7 << 16) /* RW !!! MT2701 Add */
+
+#define MSDC_PB2_POPENCNT (0xF << 20) /* RW !!! MT2701 Add */
+#define MSDC_PB2_CFGCRCSTSSEL (0x1 << 24) /* RW !!! MT2701 Add */
+#define MSDC_PB2_CFGCRCSTSEDGE (0x1 << 25) /* RW !!! MT2701 Add */
+#define MSDC_PB2_CFGCRCSTSCNT (0x3 << 26) /* RW !!! MT2701 Add */
+#define MSDC_PB2_CFGCRCSTS (0x1 << 28) /* RW !!! MT2701 Add */
+#define MSDC_PB2_CRCSTSENSEL (0x7 << 29) /* RW !!! MT2701 Add */
+
+
+/* SDIO_TUNE_WIND mask */
+#define SDIO_TUNE_WIND_TUNEWINDOW (0x1F << 0) /* RW !!! MT2701 Add for SD/SDIO only*/
+
+/* MSDC_PAD_TUNE/MSDC_PAD_TUNE0 mask */
+#define MSDC_PAD_TUNE_DATWRDLY (0x1F << 0) /* RW */
+
+#define MSDC_PAD_TUNE_DELAYEN (0x1 << 7) /* RW !!! MT2701 Add*/
+#define MSDC_PAD_TUNE_DATRRDLY (0x1F << 8) /* RW */
+#define MSDC_PAD_TUNE_DATRRDLYSEL (0x1 << 13) /* RW !!! MT2701 Add*/
+
+#define MSDC_PAD_TUNE_RXDLYSEL (0x1 << 15) /* RW !!! MT2701 Add*/
+#define MSDC_PAD_TUNE_CMDRDLY (0x1F << 16) /* RW */
+#define MSDC_PAD_TUNE_CMDRDLYSEL (0x1 << 21) /* RW !!! MT2701 Add*/
+#define MSDC_PAD_TUNE_CMDRRDLY (0x1F << 22) /* RW */
+#define MSDC_PAD_TUNE_CLKTXDLY (0x1F << 27) /* RW */
+
+/* MSDC_PAD_TUNE1 mask */
+
+#define MSDC_PAD_TUNE1_DATRRDLY2 (0x1F << 8) /* RW !!! MT2701 Add*/
+#define MSDC_PAD_TUNE1_DATRDLY2SEL (0x1 << 13) /* RW !!! MT2701 Add*/
+
+#define MSDC_PAD_TUNE1_CMDRDLY2 (0x1F << 16) /* RW !!! MT2701 Add*/
+#define MSDC_PAD_TUNE1_CMDRDLY2SEL (0x1 << 21) /* RW !!! MT2701 Add*/
+
+
+/* MSDC_DAT_RDDLY0 mask */
+#define MSDC_DAT_RDDLY0_D3 (0x1F << 0) /* RW */
+#define MSDC_DAT_RDDLY0_D2 (0x1F << 8) /* RW */
+#define MSDC_DAT_RDDLY0_D1 (0x1F << 16) /* RW */
+#define MSDC_DAT_RDDLY0_D0 (0x1F << 24) /* RW */
+
+/* MSDC_DAT_RDDLY1 mask */
+#define MSDC_DAT_RDDLY1_D7 (0x1F << 0) /* RW */
+
+#define MSDC_DAT_RDDLY1_D6 (0x1F << 8) /* RW */
+
+#define MSDC_DAT_RDDLY1_D5 (0x1F << 16) /* RW */
+
+#define MSDC_DAT_RDDLY1_D4 (0x1F << 24) /* RW */
+
+/* MSDC_DAT_RDDLY2 mask */
+#define MSDC_DAT_RDDLY2_D3 (0x1F << 0) /* RW !!! MT2701 Add*/
+
+#define MSDC_DAT_RDDLY2_D2 (0x1F << 8) /* RW !!! MT2701 Add*/
+
+#define MSDC_DAT_RDDLY2_D1 (0x1F << 16) /* RW !!! MT2701 Add*/
+
+#define MSDC_DAT_RDDLY2_D0 (0x1F << 24) /* RW !!! MT2701 Add*/
+
+/* MSDC_DAT_RDDLY3 mask */
+#define MSDC_DAT_RDDLY3_D7 (0x1F << 0) /* RW !!! MT2701 Add*/
+
+#define MSDC_DAT_RDDLY3_D6 (0x1F << 8) /* RW !!! MT2701 Add*/
+
+#define MSDC_DAT_RDDLY3_D5 (0x1F << 16) /* RW !!! MT2701 Add*/
+
+#define MSDC_DAT_RDDLY3_D4 (0x1F << 24) /* RW !!! MT2701 Add*/
+
+/* MSDC_HW_DBG_SEL mask */
+#define MSDC_HW_DBG0_SEL (0xFF << 0) /* RW DBG3->DBG0 !!! MT2701 Change*/
+#define MSDC_HW_DBG1_SEL (0x3F << 8) /* RW DBG2->DBG1 !!! MT2701 Add*/
+
+#define MSDC_HW_DBG2_SEL (0xFF << 16) /* RW DBG1->DBG2 !!! MT2701 Add*/
+//#define MSDC_HW_DBG_WRAPTYPE_SEL (0x3 << 22) /* RW !!! MT2701 Removed*/
+#define MSDC_HW_DBG3_SEL (0x3F << 24) /* RW DBG0->DBG3 !!! MT2701 Add*/
+#define MSDC_HW_DBG_WRAP_SEL (0x1 << 30) /* RW */
+
+
+/* MSDC_EMMC50_PAD_CTL0 mask*/
+#define MSDC_EMMC50_PAD_CTL0_DCCSEL (0x1 << 0) /* RW */
+#define MSDC_EMMC50_PAD_CTL0_HLSEL (0x1 << 1) /* RW */
+#define MSDC_EMMC50_PAD_CTL0_DLP0 (0x3 << 2) /* RW */
+#define MSDC_EMMC50_PAD_CTL0_DLN0 (0x3 << 4) /* RW */
+#define MSDC_EMMC50_PAD_CTL0_DLP1 (0x3 << 6) /* RW */
+#define MSDC_EMMC50_PAD_CTL0_DLN1 (0x3 << 8) /* RW */
+
+/* MSDC_EMMC50_PAD_DS_CTL0 mask */
+#define MSDC_EMMC50_PAD_DS_CTL0_SR (0x1 << 0) /* RW */
+#define MSDC_EMMC50_PAD_DS_CTL0_R0 (0x1 << 1) /* RW */
+#define MSDC_EMMC50_PAD_DS_CTL0_R1 (0x1 << 2) /* RW */
+#define MSDC_EMMC50_PAD_DS_CTL0_PUPD (0x1 << 3) /* RW */
+#define MSDC_EMMC50_PAD_DS_CTL0_IES (0x1 << 4) /* RW */
+#define MSDC_EMMC50_PAD_DS_CTL0_SMT (0x1 << 5) /* RW */
+#define MSDC_EMMC50_PAD_DS_CTL0_RDSEL (0x3F << 6) /* RW */
+#define MSDC_EMMC50_PAD_DS_CTL0_TDSEL (0xF << 12) /* RW */
+#define MSDC_EMMC50_PAD_DS_CTL0_DRV (0x7 << 16) /* RW */
+
+
+/* EMMC50_PAD_DS_TUNE mask */
+#define MSDC_EMMC50_PAD_DS_TUNE_DLYSEL (0x1 << 0) /* RW */
+#define MSDC_EMMC50_PAD_DS_TUNE_DLY2SEL (0x1 << 1) /* RW */
+#define MSDC_EMMC50_PAD_DS_TUNE_DLY1 (0x1F << 2) /* RW */
+#define MSDC_EMMC50_PAD_DS_TUNE_DLY2 (0x1F << 7) /* RW */
+#define MSDC_EMMC50_PAD_DS_TUNE_DLY3 (0x1F << 12) /* RW */
+
+/* EMMC50_PAD_CMD_TUNE mask */
+#define MSDC_EMMC50_PAD_CMD_TUNE_DLY3SEL (0x1 << 0) /* RW */
+#define MSDC_EMMC50_PAD_CMD_TUNE_RXDLY3 (0x1F << 1) /* RW */
+#define MSDC_EMMC50_PAD_CMD_TUNE_TXDLY (0x1F << 6) /* RW */
+
+/* EMMC50_PAD_DAT01_TUNE mask */
+#define MSDC_EMMC50_PAD_DAT0_RXDLY3SEL (0x1 << 0) /* RW */
+#define MSDC_EMMC50_PAD_DAT0_RXDLY3 (0x1F << 1) /* RW */
+#define MSDC_EMMC50_PAD_DAT0_TXDLY (0x1F << 6) /* RW */
+#define MSDC_EMMC50_PAD_DAT1_RXDLY3SEL (0x1 << 16) /* RW */
+#define MSDC_EMMC50_PAD_DAT1_RXDLY3 (0x1F << 17) /* RW */
+#define MSDC_EMMC50_PAD_DAT1_TXDLY (0x1F << 22) /* RW */
+
+/* EMMC50_PAD_DAT23_TUNE mask */
+#define MSDC_EMMC50_PAD_DAT2_RXDLY3SEL (0x1 << 0) /* RW */
+#define MSDC_EMMC50_PAD_DAT2_RXDLY3 (0x1F << 1) /* RW */
+#define MSDC_EMMC50_PAD_DAT2_TXDLY (0x1F << 6) /* RW */
+#define MSDC_EMMC50_PAD_DAT3_RXDLY3SEL (0x1 << 16) /* RW */
+#define MSDC_EMMC50_PAD_DAT3_RXDLY3 (0x1F << 17) /* RW */
+#define MSDC_EMMC50_PAD_DAT3_TXDLY (0x1F << 22) /* RW */
+
+/* EMMC50_PAD_DAT45_TUNE mask */
+#define MSDC_EMMC50_PAD_DAT4_RXDLY3SEL (0x1 << 0) /* RW */
+#define MSDC_EMMC50_PAD_DAT4_RXDLY3 (0x1F << 1) /* RW */
+#define MSDC_EMMC50_PAD_DAT4_TXDLY (0x1F << 6) /* RW */
+#define MSDC_EMMC50_PAD_DAT5_RXDLY3SEL (0x1 << 16) /* RW */
+#define MSDC_EMMC50_PAD_DAT5_RXDLY3 (0x1F << 17) /* RW */
+#define MSDC_EMMC50_PAD_DAT5_TXDLY (0x1F << 22) /* RW */
+
+/* EMMC50_PAD_DAT67_TUNE mask */
+#define MSDC_EMMC50_PAD_DAT6_RXDLY3SEL (0x1 << 0) /* RW */
+#define MSDC_EMMC50_PAD_DAT6_RXDLY3 (0x1F << 1) /* RW */
+#define MSDC_EMMC50_PAD_DAT6_TXDLY (0x1F << 6) /* RW */
+#define MSDC_EMMC50_PAD_DAT7_RXDLY3SEL (0x1 << 16) /* RW */
+#define MSDC_EMMC50_PAD_DAT7_RXDLY3 (0x1F << 17) /* RW */
+#define MSDC_EMMC50_PAD_DAT7_TXDLY (0x1F << 22) /* RW */
+
+/* EMMC51_CFG0 mask */
+#define MSDC_EMMC51_CFG_CMDQ_EN (0x1 << 0) /* RW !!! MT2701 Add*/
+#define MSDC_EMMC51_CFG_WDAT_CNT (0x3FF << 1) /* RW !!! MT2701 Add*/
+#define MSDC_EMMC51_CFG_RDAT_CNT (0x3FF << 11) /* RW !!! MT2701 Add*/
+#define MSDC_EMMC51_CFG_CMDQ_CMD_EN (0x1 << 21) /* RW !!! MT2701 Add*/
+
+
+/* EMMC50_CFG0 mask */
+#define MSDC_EMMC50_CFG_PADCMD_LATCHCK (0x1 << 0) /* RW*/
+#define MSDC_EMMC50_CFG_CRCSTS_CNT (0x3 << 1) /* RW*/
+#define MSDC_EMMC50_CFG_CRCSTS_EDGE (0x1 << 3) /* RW*/
+#define MSDC_EMMC50_CFG_CRC_STS_EDGE MSDC_EMMC50_CFG_CRCSTS_EDGE /*alias */
+
+#define MSDC_EMMC50_CFG_CRCSTS_SEL (0x1 << 4) /* RW*/
+#define MSDC_EMMC50_CFG_CRC_STS_SEL MSDC_EMMC50_CFG_CRCSTS_SEL /*alias */
+
+#define MSDC_EMMC50_CFG_ENDBIT_CHKCNT (0xF << 5) /* RW*/
+#define MSDC_EMMC50_CFG_CMDRSP_SEL (0x1 << 9) /* RW*/
+#define MSDC_EMMC50_CFG_CMD_RESP_SEL MSDC_EMMC50_CFG_CMDRSP_SEL /*alias */
+
+#define MSDC_EMMC50_CFG_CMDEDGE_SEL (0x1 << 10) /* RW*/
+#define MSDC_EMMC50_CFG_ENDBIT_CNT (0x3FF<< 11) /* RW*/
+#define MSDC_EMMC50_CFG_READDAT_CNT (0x7 << 21) /* RW*/
+#define MSDC_EMMC50_CFG_EMMC50_MONSEL (0x1 << 24) /* RW*/
+#define MSDC_EMMC50_CFG_MSDC_WRVALID (0x1 << 25) /* RW*/
+#define MSDC_EMMC50_CFG_MSDC_RDVALID (0x1 << 26) /* RW*/
+#define MSDC_EMMC50_CFG_MSDC_WRVALID_SEL (0x1 << 27) /* RW*/
+#define MSDC_EMMC50_CFG_MSDC_RDVALID_SEL (0x1 << 28) /* RW*/
+#define MSDC_EMMC50_CFG_MSDC_TXSKEW_SEL (0x1 << 29) /* RW*/
+//#define MSDC_EMMC50_CFG_MSDC_GDMA_RESET (0x1 << 31) /* RW !!! MT2701 Removed*/
+
+/* EMMC50_CFG1 mask */
+#define MSDC_EMMC50_CFG1_WRPTR_MARGIN (0xFF << 0) /* RW*/
+#define MSDC_EMMC50_CFG1_CKSWITCH_CNT (0x7 << 8) /* RW*/
+#define MSDC_EMMC50_CFG1_RDDAT_STOP (0x1 << 11) /* RW*/
+#define MSDC_EMMC50_CFG1_WAIT8CLK_CNT (0xF << 12) /* RW*/
+#define MSDC_EMMC50_CFG1_EMMC50_DBG_SEL (0xFF << 16) /* RW*/
+#define MSDC_EMMC50_CFG1_PSH_CNT (0x7 << 24) /* RW !!! MT2701 Add*/
+#define MSDC_EMMC50_CFG1_PSH_PS_SEL (0x1 << 27) /* RW !!! MT2701 Add*/
+#define MSDC_EMMC50_CFG1_DS_CFG (0x1 << 28) /* RW !!! MT2701 Add*/
+
+/* EMMC50_CFG2 mask */
+//#define MSDC_EMMC50_CFG2_AXI_GPD_UP (0x1 << 0) /* RW !!! MT2701 Removed*/
+#define MSDC_EMMC50_CFG2_AXI_IOMMU_WR_EMI (0x1 << 1) /* RW*/
+#define MSDC_EMMC50_CFG2_AXI_SHARE_EN_WR_EMI (0x1 << 2) /* RW*/
+
+#define MSDC_EMMC50_CFG2_AXI_IOMMU_RD_EMI (0x1 << 7) /* RW*/
+#define MSDC_EMMC50_CFG2_AXI_SHARE_EN_RD_EMI (0x1 << 8) /* RW*/
+
+#define MSDC_EMMC50_CFG2_AXI_BOUND_128B (0x1 << 13) /* RW*/
+#define MSDC_EMMC50_CFG2_AXI_BOUND_256B (0x1 << 14) /* RW*/
+#define MSDC_EMMC50_CFG2_AXI_BOUND_512B (0x1 << 15) /* RW*/
+#define MSDC_EMMC50_CFG2_AXI_BOUND_1K (0x1 << 16) /* RW*/
+#define MSDC_EMMC50_CFG2_AXI_BOUND_2K (0x1 << 17) /* RW*/
+#define MSDC_EMMC50_CFG2_AXI_BOUND_4K (0x1 << 18) /* RW*/
+#define MSDC_EMMC50_CFG2_AXI_RD_OUTSTANDING_NUM (0x1F << 19) /* RW*/
+#define MSDC_EMMC50_CFG2_AXI_RD_OUTS_NUM MSDC_EMMC50_CFG2_AXI_RD_OUTSTANDING_NUM /*alias */
+
+#define MSDC_EMMC50_CFG2_AXI_SET_LET (0xF << 24) /* RW*/
+#define MSDC_EMMC50_CFG2_AXI_SET_LEN MSDC_EMMC50_CFG2_AXI_SET_LET /*alias */
+
+#define MSDC_EMMC50_CFG2_AXI_RESP_ERR_TYPE (0x3 << 28) /* RW*/
+#define MSDC_EMMC50_CFG2_AXI_BUSY (0x1 << 30) /* RW*/
+
+
+/* EMMC50_CFG3 mask */
+#define MSDC_EMMC50_CFG3_OUTSTANDING_WR (0x1F << 0) /* RW*/
+#define MSDC_EMMC50_CFG3_OUTS_WR MSDC_EMMC50_CFG3_OUTSTANDING_WR /*alias */
+
+#define MSDC_EMMC50_CFG3_ULTRA_SET_WR (0x3F << 5) /* RW*/
+#define MSDC_EMMC50_CFG3_PREULTRA_SET_WR (0x3F << 11) /* RW*/
+#define MSDC_EMMC50_CFG3_ULTRA_SET_RD (0x3F << 17) /* RW*/
+#define MSDC_EMMC50_CFG3_PREULTRA_SET_RD (0x3F << 23) /* RW*/
+
+/* EMMC50_CFG4 mask */
+#define MSDC_EMMC50_CFG4_IMPR_ULTRA_SET_WR (0xFF << 0) /* RW*/
+#define MSDC_EMMC50_CFG4_IMPR_ULTRA_SET_RD (0xFF << 8) /* RW*/
+#define MSDC_EMMC50_CFG4_ULTRA_EN (0x3 << 16) /* RW*/
+#define MSDC_EMMC50_CFG4_WRAP_SEL (0x1F << 18) /* RW !!! MT2701 Add*/
+
+/* EMMC50_BLOCK_LENGTH mask */
+#define EMMC50_BLOCK_LENGTH_BLKLENGTH (0xFF << 0) /* RW !!! MT2701 Add*/
+
+
+#if 1
+/* Chaotian Add GPIO top layer */
+#define MSDC0_CMD_PUPD (GPIO_BASE + 0xd80)
+#define MSDC0_CMD_PUPD_MASK (0x7 << 0)
+
+#define MSDC0_DSL_PUPD (GPIO_BASE + 0xd80)
+#define MSDC0_DSL_PUPD_MASK (0x7 << 8)
+
+#define MSDC0_CLK_PUPD (GPIO_BASE + 0xd80)
+#define MSDC0_CLK_PUPD_MASK (0x7 << 4)
+
+#define MSDC0_DAT0_PUPD (GPIO_BASE + 0xd80)
+#define MSDC0_DAT0_PUPD_MASK (0x7 << 12)
+
+#define MSDC0_DAT1_PUPD (GPIO_BASE + 0xd80)
+#define MSDC0_DAT1_PUPD_MASK (0x7 << 16)
+
+#define MSDC0_DAT2_PUPD (GPIO_BASE + 0xd80)
+#define MSDC0_DAT2_PUPD_MASK (0x7 << 20)
+
+#define MSDC0_DAT3_PUPD (GPIO_BASE + 0xd80)
+#define MSDC0_DAT3_PUPD_MASK (0x7 << 24)
+
+#define MSDC0_DAT4_PUPD (GPIO_BASE + 0xd80)
+#define MSDC0_DAT4_PUPD_MASK (0x7 << 28)
+
+#define MSDC0_DAT5_PUPD (GPIO_BASE + 0xd90)
+#define MSDC0_DAT5_PUPD_MASK (0x7 << 0)
+
+#define MSDC0_DAT6_PUPD (GPIO_BASE + 0xd90)
+#define MSDC0_DAT6_PUPD_MASK (0x7 << 4)
+
+#define MSDC0_DAT7_PUPD (GPIO_BASE + 0xd90)
+#define MSDC0_DAT7_PUPD_MASK (0x7 << 8)
+
+#define MSDC0_RSTB_PUPD (GPIO_BASE + 0xd90)
+#define MSDC0_RSTB_PUPD_MASK (0x7 << 12)
+
+#define MSDC0_SMT (GPIO_BASE + 0xd10)
+#define MSDC0_SMT_CMD_MASK (0x1 << 0)
+#define MSDC0_SMT_DSL_MASK (0x1 << 1)
+#define MSDC0_SMT_CLK_MASK (0x1 << 2)
+#define MSDC0_SMT_DAT_MASK (0x1 << 3)
+#define MSDC0_SMT_RSTB_MASK (0x1 << 4)
+
+#define MSDC0_DRV (GPIO_BASE + 0xd70)
+#define MSDC0_DRV_CMD_MASK (0xf << 0)
+#define MSDC0_DRV_DSL_MASK (0xf << 4)
+#define MSDC0_DRV_CLK_MASK (0xf << 8)
+#define MSDC0_DRV_DAT_MASK (0xf << 12)
+
+#define MSDC_DRVN_GEAR0 0
+#define MSDC_DRVN_GEAR1 1
+#define MSDC_DRVN_GEAR2 2
+#define MSDC_DRVN_GEAR3 3
+#define MSDC_DRVN_GEAR4 4
+#define MSDC_DRVN_GEAR5 5
+#define MSDC_DRVN_GEAR6 6
+#define MSDC_DRVN_GEAR7 7
+#define MSDC_DRVN_DONT_CARE MSDC_DRVN_GEAR0
+
+
+#endif
+
+typedef enum __MSDC_PIN_STATE {
+ MSDC_PST_PU_10KOHM = 0,
+ MSDC_PST_PU_50KOHM,
+ MSDC_PST_PD_10KOHM,
+ MSDC_PST_PD_50KOHM,
+ MSDC_PST_MAX
+} MSDC_PIN_STATE;
+
+
+/* each PLL have different gears for select
+ * software can used mux interface from clock management module to select */
+enum {
+ MSDC50_CLKSRC4HCLK_26MHZ = 0,
+ MSDC50_CLKSRC4HCLK_273MHZ,
+ MSDC50_CLKSRC4HCLK_182MHZ,
+ MSDC50_CLKSRC4HCLK_78MHZ,
+ MSDC_DONOTCARE_HCLK,
+ MSDC50_CLKSRC4HCLK_MAX
+};
+
+enum {
+ MSDC50_CLKSRC_26MHZ = 0,
+ MSDC50_CLKSRC_400MHZ, /* MSDCPLL_CK */
+ MSDC50_CLKSRC_182MHZ, /*MSDCPLL_D2 */
+ MSDC50_CLKSRC_136MHZ,
+ MSDC50_CLKSRC_156MHZ,
+ MSDC50_CLKSRC_200MHZ, /*MSDCPLL_D4 */
+ MSDC50_CLKSRC_100MHZ,
+ MSDC50_CLKSRC_50MHZ,
+ MSDC50_CLKSRC_MAX
+};
+
+/* MSDC0/1/2
+ PLL MUX SEL List */
+enum {
+ MSDC30_CLKSRC_26MHZ = 0,
+ MSDC30_CLKSRC_200MHZ,
+ MSDC30_CLKSRC_182MHZ,
+ MSDC30_CLKSRC_91MHZ,
+ MSDC30_CLKSRC_156MHZ,
+ MSDC30_CLKSRC_104MHZ,
+ MSDC30_CLKSRC_MAX
+};
+
+#define MSDC50_CLKSRC_DEFAULT MSDC50_CLKSRC_200MHZ
+#define MSDC30_CLKSRC_DEFAULT MSDC30_CLKSRC_200MHZ
+
+typedef enum MT65XX_POWER_VOL_TAG {
+ VOL_DEFAULT,
+ VOL_0900 = 900,
+ VOL_1000 = 1000,
+ VOL_1100 = 1100,
+ VOL_1200 = 1200,
+ VOL_1300 = 1300,
+ VOL_1350 = 1350,
+ VOL_1500 = 1500,
+ VOL_1800 = 1800,
+ VOL_2000 = 2000,
+ VOL_2100 = 2100,
+ VOL_2500 = 2500,
+ VOL_2800 = 2800,
+ VOL_3000 = 3000,
+ VOL_3300 = 3300,
+ VOL_3400 = 3400,
+ VOL_3500 = 3500,
+ VOL_3600 = 3600
+} MT65XX_POWER_VOLTAGE;
+
+/*--------------------------------------------------------------------------*/
+/* Descriptor Structure */
+/*--------------------------------------------------------------------------*/
+#define DMA_FLAG_NONE (0x00000000)
+#define DMA_FLAG_EN_CHKSUM (0x00000001)
+#define DMA_FLAG_PAD_BLOCK (0x00000002)
+#define DMA_FLAG_PAD_DWORD (0x00000004)
+
+#define MSDC_WRITE32(addr, data) writel(data, addr)
+#define MSDC_READ32(addr) readl(addr)
+#define MSDC_WRITE8(addr, data) writeb(data, addr)
+#define MSDC_READ8(addr) readb(addr)
+
+#define MSDC_SET_BIT32(addr,mask) \
+ do { \
+ unsigned int tv = MSDC_READ32(addr); \
+ tv |=((u32)(mask)); \
+ MSDC_WRITE32(addr,tv); \
+ } while (0)
+#define MSDC_CLR_BIT32(addr,mask) \
+ do { \
+ unsigned int tv = MSDC_READ32(addr); \
+ tv &= ~((u32)(mask)); \
+ MSDC_WRITE32(addr,tv); \
+ } while (0)
+
+#define MSDC_SET_FIELD(reg,field,val) \
+ do { \
+ u32 tv = MSDC_READ32(reg); \
+ tv &= ~((u32)(field)); \
+ tv |= ((val) << (__builtin_ffs((u32)(field)) - 1)); \
+ MSDC_WRITE32(reg, tv); \
+ } while (0)
+
+#define MSDC_GET_FIELD(reg,field,val) \
+ do { \
+ u32 tv = MSDC_READ32(reg); \
+ val = ((tv & (field)) >> (__builtin_ffs((u32)(field)) - 1)); \
+ } while (0)
+
+#define MSDC_RETRY(expr,retry,cnt) \
+ do { \
+ uint32_t t = cnt; \
+ uint32_t r = retry; \
+ uint32_t c = cnt; \
+ while (r) { \
+ if (!(expr)) break; \
+ if (c-- == 0) { \
+ r--; spin(200); c = t; \
+ } \
+ } \
+ if (r == 0) \
+ dprintf(CRITICAL, "%s->%d: retry %d times failed!\n", __func__, \
+ __LINE__, retry); \
+ } while (0)
+
+#define MSDC_RESET() \
+ do { \
+ MSDC_SET_BIT32(MSDC_CFG, MSDC_CFG_RST); \
+ MSDC_RETRY(MSDC_READ32(MSDC_CFG) & MSDC_CFG_RST, 5, 1000); \
+ } while (0)
+
+#define MSDC_CLR_INT() \
+ do { \
+ volatile uint32_t val = MSDC_READ32(MSDC_INT); \
+ MSDC_WRITE32(MSDC_INT, val); \
+ } while (0)
+
+#define MSDC_CLR_FIFO() \
+ do { \
+ MSDC_SET_BIT32(MSDC_FIFOCS, MSDC_FIFOCS_CLR); \
+ MSDC_RETRY(MSDC_READ32(MSDC_FIFOCS) & MSDC_FIFOCS_CLR, 5, 1000); \
+ } while (0)
+
+#define MSDC_FIFO_WRITE32(val) MSDC_WRITE32(MSDC_TXDATA, val)
+#define MSDC_FIFO_READ32() MSDC_READ32(MSDC_RXDATA)
+#define MSDC_FIFO_WRITE8(val) MSDC_WRITE8(MSDC_TXDATA, val)
+#define MSDC_FIFO_READ8() MSDC_READ8(MSDC_RXDATA)
+
+#define MSDC_TXFIFOCNT() \
+ ((MSDC_READ32(MSDC_FIFOCS) & MSDC_FIFOCS_TXCNT) >> 16)
+#define MSDC_RXFIFOCNT() \
+ ((MSDC_READ32(MSDC_FIFOCS) & MSDC_FIFOCS_RXCNT) >> 0)
+
+#define SDC_IS_BUSY() (MSDC_READ32(SDC_STS) & SDC_STS_SDCBUSY)
+#define SDC_IS_CMD_BUSY() (MSDC_READ32(SDC_STS) & SDC_STS_CMDBUSY)
+
+#define SDC_SEND_CMD(cmd,arg) \
+ do { \
+ MSDC_WRITE32(SDC_ARG, (arg)); \
+ MSDC_WRITE32(SDC_CMD, (cmd)); \
+ } while (0)
+
+#define MSDC_DMA_ON MSDC_CLR_BIT32(MSDC_CFG, MSDC_CFG_PIO);
+#define MSDC_DMA_OFF MSDC_SET_BIT32(MSDC_CFG, MSDC_CFG_PIO);
+
+#define MSDC_RELIABLE_WRITE (0x1 << 0)
+#define MSDC_PACKED (0x1 << 1)
+#define MSDC_TAG_REQUEST (0x1 << 2)
+#define MSDC_CONTEXT_ID (0x1 << 3)
+#define MSDC_FORCED_PROG (0x1 << 4)
+
+#ifdef FPGA_PLATFORM
+#define msdc_pin_set(...)
+#define msdc_set_smt(...)
+#define msdc_set_driving(...)
+#endif
+
+int msdc_init(struct mmc_host *host);
+void msdc_config_bus(struct mmc_host *host, u32 width);
+int msdc_dma_transfer(struct mmc_host *host, struct mmc_data *data);
+int msdc_tune_bwrite(struct mmc_host *host, u32 dst, u8 *src, u32 nblks);
+int msdc_tune_bread(struct mmc_host *host, u8 *dst, u32 src, u32 nblks);
+void msdc_reset_tune_counter(struct mmc_host *host);
+int msdc_abort_handler(struct mmc_host *host, int abort_card);
+int msdc_tune_read(struct mmc_host *host);
+void msdc_config_clock(struct mmc_host *host, int state, u32 hz);
+int msdc_cmd(struct mmc_host *host, struct mmc_command *cmd);
+void msdc_set_timeout(struct mmc_host *host, u32 ns, u32 clks);
+void msdc_set_autocmd(struct mmc_host *host, int cmd);
+int msdc_get_autocmd(struct mmc_host *host);
+
diff --git a/src/bsp/lk/platform/mt2635/include/platform/msdc_cfg.h b/src/bsp/lk/platform/mt2635/include/platform/msdc_cfg.h
new file mode 100644
index 0000000..0afd634
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/msdc_cfg.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+
+/*--------------------------------------------------------------------------*/
+/* Common Definition */
+/*--------------------------------------------------------------------------*/
+#ifdef MACH_FPGA
+#define FPGA_PLATFORM
+#endif
+
+/* HW deal with the 2K DMA boundary limitation, SW do nothing with it */
+/* Most of eMMC request in lk are sequential access, so it's no need to
+ * use descript DMA mode, I just remove relevant codes. JieWu@20160607 */
+#define MSDC_USE_DMA_MODE
+
+#define FEATURE_MMC_WR_TUNING
+#define FEATURE_MMC_RD_TUNING
+#define FEATURE_MMC_CM_TUNING
+
+/* Maybe we discard these macro definition */
+//#define MSDC_USE_PATCH_BIT2_TURNING_WITH_ASYNC
+
+/*--------------------------------------------------------------------------*/
+/* Debug Definition */
+/*--------------------------------------------------------------------------*/
+//#define KEEP_SLIENT_BUILD
+//#define ___MSDC_DEBUG___
diff --git a/src/bsp/lk/platform/mt2635/include/platform/mt2635.h b/src/bsp/lk/platform/mt2635/include/platform/mt2635.h
new file mode 100644
index 0000000..dd0f5c3
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/mt2635.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+#include <debug.h>
+
+/* L2C */
+#define MEMORY_BASE_PHYS (0x200000)
+#define MEMORY_BASE_VIRT (KERNEL_BASE)
+#define MEMORY_APERTURE_SIZE (0x40000UL)
+
+/* Internal SRAM */
+#define SRAM_BASE_PHYS (0x100000)
+#define SRAM_BASE_SIZE (0x10000L)
+#define SRAM_BASE_VIRT (MEMORY_BASE_VIRT + 0x100000UL)
+
+
+
+/* map all of 0-1GB into kernel space in one shot */
+#define PERIPHERAL_BASE_PHYS (0x10000000)
+#define PERIPHERAL_BASE_SIZE (0x0d000000UL)
+#if WITH_KERNEL_VM
+#define PERIPHERAL_BASE_VIRT (SRAM_BASE_VIRT + 0x300000UL)
+#else
+#define PERIPHERAL_BASE_VIRT PERIPHERAL_BASE_PHYS
+#endif
+
+#define DRAM_BASE_PHY (0x40000000U)
+#if WITH_KERNEL_VM
+#define DRAM_BASE_VIRT (PERIPHERAL_BASE_VIRT + PERIPHERAL_BASE_SIZE)
+#else
+#define DRAM_BASE_VIRT DRAM_BASE_PHY
+#endif
+
+/* individual peripherals in this mapping */
+#define CPUPRIV_BASE_VIRT (PERIPHERAL_BASE_VIRT + 0x08000000)
+#define CPUPRIV_BASE_PHYS (PERIPHERAL_BASE_PHYS + 0x08000000)
+#define CPUPRIV_SIZE (0x00020000)
+
+/* interrupts */
+#define ARM_GENERIC_TIMER_VIRTUAL_INT 27
+#define ARM_GENERIC_TIMER_PHYSICAL_INT 30
+
+#define MAX_INT 221
+
+/* mt_mempll_init and dram calibration */
+#define DRAMC0_BASE (PERIPHERAL_BASE_VIRT + 0x214000)
+#define DRAMC_NAO_BASE (PERIPHERAL_BASE_VIRT + 0x20E000)
+#define DDRPHY_BASE (PERIPHERAL_BASE_VIRT + 0x213000)
+#define SPM_BASE (PERIPHERAL_BASE_VIRT + 0x6000)
+#define RGU_BASE (PERIPHERAL_BASE_VIRT + 0x00212000)
+#define SRAMROM_BASE (PERIPHERAL_BASE_VIRT + 0x202000)
diff --git a/src/bsp/lk/platform/mt2635/include/platform/mt_irq.h b/src/bsp/lk/platform/mt2635/include/platform/mt_irq.h
new file mode 100644
index 0000000..51a249f
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/mt_irq.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __MT_IRQ_H__
+#define __MT_IRQ_H__
+
+#define GIC_CPU_CTRL 0x00
+#define GIC_CPU_PRIMASK 0x04
+#define GIC_CPU_BINPOINT 0x08
+#define GIC_CPU_INTACK 0x0c
+#define GIC_CPU_EOI 0x10
+#define GIC_CPU_RUNNINGPRI 0x14
+#define GIC_CPU_HIGHPRI 0x18
+
+#define GIC_DIST_CTRL 0x000
+#define GIC_DIST_CTR 0x004
+#define GIC_DIST_ENABLE_SET 0x100
+#define GIC_DIST_ENABLE_CLEAR 0x180
+#define GIC_DIST_PENDING_SET 0x200
+#define GIC_DIST_PENDING_CLEAR 0x280
+#define GIC_DIST_ACTIVE_BIT 0x300
+#define GIC_DIST_PRI 0x400
+#define GIC_DIST_TARGET 0x800
+#define GIC_DIST_CONFIG 0xc00
+#define GIC_DIST_SOFTINT 0xf00
+#define GIC_DIST_ICDISR 0x80
+enum {IRQ_MASK_HEADER = 0xF1F1F1F1, IRQ_MASK_FOOTER = 0xF2F2F2F2};
+
+struct mtk_irq_mask {
+ unsigned int header; /* for error checking */
+ unsigned int mask0;
+ unsigned int mask1;
+ unsigned int mask2;
+ unsigned int mask3;
+ unsigned int mask4;
+ unsigned int mask5;
+ unsigned int mask6;
+ unsigned int mask7;
+ unsigned int footer; /* for error checking */
+};
+
+
+/*
+ * Define hadware registers.
+ */
+
+/*
+ * Define IRQ code.
+ */
+
+#define GIC_PRIVATE_SIGNALS (32)
+
+#define GIC_PPI_OFFSET (27)
+#define GIC_PPI_GLOBAL_TIMER (GIC_PPI_OFFSET + 0)
+#define GIC_PPI_LEGACY_FIQ (GIC_PPI_OFFSET + 1)
+#define GIC_PPI_PRIVATE_TIMER (GIC_PPI_OFFSET + 2)
+#define GIC_PPI_WATCHDOG_TIMER (GIC_PPI_OFFSET + 3)
+#define GIC_PPI_LEGACY_IRQ (GIC_PPI_OFFSET + 4)
+
+
+#define ARM_GENERIC_TIMER_NONSECURE_PHYSICAL_INT 30
+
+#define MT_GPT_IRQ_ID 184
+#define MT_USB0_IRQ_ID 104
+#define MT_MSDC0_IRQ_ID 111
+#define MT_MSDC1_IRQ_ID 112
+
+#define MT_NR_PPI (5)
+#define MT_NR_SPI (221)
+#define NR_IRQ_LINE (GIC_PPI_OFFSET + MT_NR_PPI + MT_NR_SPI) // 5 PPIs and 224 SPIs
+
+#define EDGE_SENSITIVE 0
+#define LEVEL_SENSITIVE 1
+
+#define MT65xx_POLARITY_LOW 0
+#define MT65xx_POLARITY_HIGH 1
+
+
+int mt_irq_mask_all(struct mtk_irq_mask *mask); //(This is ONLY used for the sleep driver)
+int mt_irq_mask_restore(struct mtk_irq_mask *mask); //(This is ONLY used for the sleep driver)
+void mt_irq_set_sens(unsigned int irq, unsigned int sens);
+void mt_irq_set_polarity(unsigned int irq, unsigned int polarity);
+int mt_irq_mask_restore(struct mtk_irq_mask *mask);
+void mt_irq_unmask(unsigned int irq);
+void mt_irq_ack(unsigned int irq);
+
+void platform_init_interrupts(void);
+
+#endif /* !__MT_IRQ_H__ */
diff --git a/src/bsp/lk/platform/mt2635/include/platform/mt_reg_base.h b/src/bsp/lk/platform/mt2635/include/platform/mt_reg_base.h
new file mode 100644
index 0000000..1e0ad44
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/mt_reg_base.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#pragma once
+
+#include <platform/mt2635.h>
+
+/* I/O mapping */
+#define IO_PHYS PERIPHERAL_BASE_VIRT
+#define IO_SIZE PERIPHERAL_BASE_SIZE
+
+/* IO register definitions */
+#define EMI_BASE (IO_PHYS + 0x00203000)
+#define GPIO_BASE (IO_PHYS + 0x00211000)
+#define GIC_CPU_BASE (IO_PHYS + 0x00222000)
+#define GIC_DIST_BASE (IO_PHYS + 0x00221000)
+#define MCUSYS_CFGREG_BASE (IO_PHYS + 0x00200000)
+#define INT_POL_CTL0 (MCUSYS_CFGREG_BASE + 0x620)
+
+#define UART1_BASE (IO_PHYS + 0x01002000)
+#define UART2_BASE (IO_PHYS + 0x01003000)
+#define UART3_BASE (IO_PHYS + 0x01004000)
+#define UART4_BASE (IO_PHYS + 0x01005000)
+
+#define MSDC0_BASE (IO_PHYS + 0x01230000)
+
+#define USB0_BASE (IO_PHYS + 0x01200000)
+#define USBSIF_BASE (IO_PHYS + 0x01210000)
+#define USB_BASE (USB0_BASE)
diff --git a/src/bsp/lk/platform/mt2635/include/platform/mt_uart.h b/src/bsp/lk/platform/mt2635/include/platform/mt_uart.h
new file mode 100644
index 0000000..f151098
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/mt_uart.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#pragma once
+
+bool check_uart_enter(void);
diff --git a/src/bsp/lk/platform/mt2635/include/platform/mt_usb.h b/src/bsp/lk/platform/mt2635/include/platform/mt_usb.h
new file mode 100644
index 0000000..1742f05
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/mt_usb.h
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2012 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+
+/* USB PHY registers */
+#define USB20_PHY_BASE (USBSIF_BASE + 0x0800)
+#define USB11_PHY_BASE (USBSIF_BASE + 0x0900)
+
+/* hardware spec */
+#define MT_EP_NUM 4
+#define MT_CHAN_NUM 4
+#define MT_EP0_FIFOSIZE 64
+
+#define FIFO_ADDR_START 512
+
+#define MT_BULK_MAXP 512
+#define MT_INT_MAXP 1024
+
+/* USB common registers */
+#define FADDR (USB_BASE + 0x0000) /* Function Address Register */
+#define POWER (USB_BASE + 0x0001) /* Power Management Register */
+#define INTRTX (USB_BASE + 0x0002) /* TX Interrupt Status Register */
+#define INTRRX (USB_BASE + 0x0004) /* RX Interrupt Status Register */
+#define INTRTXE (USB_BASE + 0x0006) /* TX Interrupt Status Enable Register */
+#define INTRRXE (USB_BASE + 0x0008) /* RX Interrupt Status Enable Register */
+#define INTRUSB (USB_BASE + 0x000a) /* Common USB Interrupt Register */
+#define INTRUSBE (USB_BASE + 0x000b) /* Common USB Interrupt Enable Register */
+#define FRAME (USB_BASE + 0x000c) /* Frame Number Register */
+#define INDEX (USB_BASE + 0x000e) /* Endpoint Selecting Index Register */
+#define TESTMODE (USB_BASE + 0x000f) /* Test Mode Enable Register */
+
+/* POWER fields */
+#define PWR_ISO_UPDATE (1<<7)
+#define PWR_SOFT_CONN (1<<6)
+#define PWR_HS_ENAB (1<<5)
+#define PWR_HS_MODE (1<<4)
+#define PWR_RESET (1<<3)
+#define PWR_RESUME (1<<2)
+#define PWR_SUSPEND_MODE (1<<1)
+#define PWR_ENABLE_SUSPENDM (1<<0)
+
+/* INTRUSB fields */
+#define INTRUSB_VBUS_ERROR (1<<7)
+#define INTRUSB_SESS_REQ (1<<6)
+#define INTRUSB_DISCON (1<<5)
+#define INTRUSB_CONN (1<<4)
+#define INTRUSB_SOF (1<<3)
+#define INTRUSB_RESET (1<<2)
+#define INTRUSB_RESUME (1<<1)
+#define INTRUSB_SUSPEND (1<<0)
+
+/* DMA control registers */
+#define USB_DMA_INTR (USB_BASE + 0x0200)
+#define USB_DMA_INTR_UNMASK_SET_OFFSET (24)
+
+#define USB_DMA_CNTL(chan) (USB_BASE + 0x0204 + 0x10*(chan-1))
+#define USB_DMA_ADDR(chan) (USB_BASE + 0x0208 + 0x10*(chan-1))
+#define USB_DMA_COUNT(chan) (USB_BASE + 0x020c + 0x10*(chan-1))
+
+/* Endpoint Control/Status Registers */
+#define IECSR (USB_BASE + 0x0010)
+/* for EP0 */
+#define CSR0 0x2 /* EP0 Control Status Register */
+/* For Host Mode, it would be 0x2 */
+#define COUNT0 0x8 /* EP0 Received Bytes Register */
+#define NAKLIMIT0 0xB /* NAK Limit Register */
+#define CONFIGDATA 0xF /* Core Configuration Register */
+/* for other endpoints */
+#define TXMAP 0x0 /* TXMAP Register: Max Packet Size for TX */
+#define TXCSR 0x2 /* TXCSR Register: TX Control Status Register */
+#define RXMAP 0x4 /* RXMAP Register: Max Packet Size for RX */
+#define RXCSR 0x6 /* RXCSR Register: RX Control Status Register */
+#define RXCOUNT 0x8 /* RXCOUNT Register */
+#define TXTYPE 0xa /* TX Type Register */
+#define TXINTERVAL 0xb /* TX Interval Register */
+#define RXTYPE 0xc /* RX Type Register */
+#define RXINTERVAL 0xd /* RX Interval Register */
+#define FIFOSIZE 0xf /* configured FIFO size register */
+
+/* control status register fields */
+/* CSR0_DEV */
+#define EP0_FLUSH_FIFO (1<<8)
+#define EP0_SERVICE_SETUP_END (1<<7)
+#define EP0_SERVICED_RXPKTRDY (1<<6)
+#define EP0_SENDSTALL (1<<5)
+#define EP0_SETUPEND (1<<4)
+#define EP0_DATAEND (1<<3)
+#define EP0_SENTSTALL (1<<2)
+#define EP0_TXPKTRDY (1<<1)
+#define EP0_RXPKTRDY (1<<0)
+
+/* TXCSR_DEV */
+#define EPX_TX_AUTOSET (1<<15)
+#define EPX_TX_ISO (1<<14)
+#define EPX_TX_MODE (1<<13)
+#define EPX_TX_DMAREQEN (1<<12)
+#define EPX_TX_FRCDATATOG (1<<11)
+#define EPX_TX_DMAREQMODE (1<<10)
+#define EPX_TX_AUTOSETEN_SPKT (1<<9)
+#define EPX_TX_INCOMPTX (1<<7)
+#define EPX_TX_CLRDATATOG (1<<6)
+#define EPX_TX_SENTSTALL (1<<5)
+#define EPX_TX_SENDSTALL (1<<4)
+#define EPX_TX_FLUSHFIFO (1<<3)
+#define EPX_TX_UNDERRUN (1<<2)
+#define EPX_TX_FIFONOTEMPTY (1<<1)
+#define EPX_TX_TXPKTRDY (1<<0)
+
+/* RXCSR_DEV */
+#define EPX_RX_AUTOCLEAR (1<<15)
+#define EPX_RX_ISO (1<<14)
+#define EPX_RX_DMAREQEN (1<<13)
+#define EPX_RX_DISNYET (1<<12)
+#define EPX_RX_PIDERR (1<<12)
+#define EPX_RX_DMAREQMODE (1<<11)
+#define EPX_RX_AUTOCLRENSPKT (1<<10)
+#define EPX_RX_INCOMPRXINTREN (1<<9)
+#define EPX_RX_INCOMPRX (1<<8)
+#define EPX_RX_CLRDATATOG (1<<7)
+#define EPX_RX_SENTSTALL (1<<6)
+#define EPX_RX_SENDSTALL (1<<5)
+#define EPX_RX_FLUSHFIFO (1<<4)
+#define EPX_RX_DATAERR (1<<3)
+#define EPX_RX_OVERRUN (1<<2)
+#define EPX_RX_FIFOFULL (1<<1)
+#define EPX_RX_RXPKTRDY (1<<0)
+
+/* CONFIGDATA fields */
+#define MP_RXE (1<<7)
+#define MP_TXE (1<<6)
+#define BIGENDIAN (1<<5)
+#define HBRXE (1<<4)
+#define HBTXE (1<<3)
+#define DYNFIFOSIZING (1<<2)
+#define SOFTCONE (1<<1)
+#define UTMIDATAWIDTH (1<<0)
+
+/* FIFO register */
+/*
+ * for endpint 1 ~ 4, writing to these addresses = writing to the
+ * corresponding TX FIFO, reading from these addresses = reading from
+ * corresponding RX FIFO
+ */
+
+#define FIFO(ep_num) (USB_BASE + 0x0020 + ep_num*0x0004)
+
+/* ============================ */
+/* additional control registers */
+/* ============================ */
+
+#define DEVCTL (USB_BASE + 0x0060) /* OTG Device Control Register */
+#define PWRUPCNT (USB_BASE + 0x0061) /* Power Up Counter Register */
+#define TXFIFOSZ (USB_BASE + 0x0062) /* TX FIFO Size Register */
+#define RXFIFOSZ (USB_BASE + 0x0063) /* RX FIFO Size Register */
+#define TXFIFOADD (USB_BASE + 0x0064) /* TX FIFO Address Register */
+#define RXFIFOADD (USB_BASE + 0x0066) /* RX FIFO Address Register */
+#define HWVERS (USB_BASE + 0x006c) /* H/W Version Register */
+#define SWRST (USB_BASE + 0x0074) /* Software Reset Register */
+#define EPINFO (USB_BASE + 0x0078) /* TX and RX Information Register */
+#define RAM_DMAINFO (USB_BASE + 0x0079) /* RAM and DMA Information Register */
+#define LINKINFO (USB_BASE + 0x007a) /* Delay Time Information Register */
+#define VPLEN (USB_BASE + 0x007b) /* VBUS Pulse Charge Time Register */
+#define HSEOF1 (USB_BASE + 0x007c) /* High Speed EOF1 Register */
+#define FSEOF1 (USB_BASE + 0x007d) /* Full Speed EOF1 Register */
+#define LSEOF1 (USB_BASE + 0x007e) /* Low Speed EOF1 Register */
+#define RSTINFO (USB_BASE + 0x007f) /* Reset Information Register */
+
+/* FIFO size register fields and available packet size values */
+#define DOUBLE_BUF 1
+#define FIFOSZ_DPB (1 << 4)
+#define PKTSZ 0x0f
+
+#define PKTSZ_8 (1<<3)
+#define PKTSZ_16 (1<<4)
+#define PKTSZ_32 (1<<5)
+#define PKTSZ_64 (1<<6)
+#define PKTSZ_128 (1<<7)
+#define PKTSZ_256 (1<<8)
+#define PKTSZ_512 (1<<9)
+#define PKTSZ_1024 (1<<10)
+
+#define FIFOSZ_8 (0x0)
+#define FIFOSZ_16 (0x1)
+#define FIFOSZ_32 (0x2)
+#define FIFOSZ_64 (0x3)
+#define FIFOSZ_128 (0x4)
+#define FIFOSZ_256 (0x5)
+#define FIFOSZ_512 (0x6)
+#define FIFOSZ_1024 (0x7)
+#define FIFOSZ_2048 (0x8)
+#define FIFOSZ_4096 (0x9)
+#define FIFOSZ_3072 (0xF)
+
+/* SWRST fields */
+#define SWRST_PHY_RST (1<<7)
+#define SWRST_PHYSIG_GATE_HS (1<<6)
+#define SWRST_PHYSIG_GATE_EN (1<<5)
+#define SWRST_REDUCE_DLY (1<<4)
+#define SWRST_UNDO_SRPFIX (1<<3)
+#define SWRST_FRC_VBUSVALID (1<<2)
+#define SWRST_SWRST (1<<1)
+#define SWRST_DISUSBRESET (1<<0)
+
+/* DMA_CNTL */
+#define USB_DMA_CNTL_ENDMAMODE2 (1 << 13)
+#define USB_DMA_CNTL_PP_RST (1 << 12)
+#define USB_DMA_CNTL_PP_EN (1 << 11)
+#define USB_DMA_BURST_MODE_MASK (3 << 9)
+#define USB_DMA_BURST_MODE_0 (0 << 9)
+#define USB_DMA_BURST_MODE_1 (0x1 << 9)
+#define USB_DMA_BURST_MODE_2 (0x2 << 9)
+#define USB_DMA_BURST_MODE_3 (0x3 << 9)
+#define USB_DMA_BUS_ERROR (0x1 << 8)
+#define USB_DMA_ENDPNT_MASK (0xf << 4)
+#define USB_DMA_ENDPNT_OFFSET (4)
+#define USB_DMA_INTEN (1 << 3)
+#define USB_DMA_DMAMODE (1 << 2)
+#define USB_DMA_DIR (1 << 1)
+#define USB_DMA_EN (1 << 0)
+
+/* USB level 1 interrupt registers */
+
+#define USB_L1INTS (USB_BASE + 0xa0) /* USB level 1 interrupt status register */
+#define USB_L1INTM (USB_BASE + 0xa4) /* USB level 1 interrupt mask register */
+#define USB_L1INTP (USB_BASE + 0xa8) /* USB level 1 interrupt polarity register */
+
+#define TX_INT_STATUS (1 << 0)
+#define RX_INT_STATUS (1 << 1)
+#define USBCOM_INT_STATUS (1 << 2)
+#define DMA_INT_STATUS (1 << 3)
+#define PSR_INT_STATUS (1 << 4)
+#define QINT_STATUS (1 << 5)
+#define QHIF_INT_STATUS (1 << 6)
+#define DPDM_INT_STATUS (1 << 7)
+#define VBUSVALID_INT_STATUS (1 << 8)
+#define IDDIG_INT_STATUS (1 << 9)
+#define DRVVBUS_INT_STATUS (1 << 10)
+#define POWERDWN_INT_STATUS (1 << 11)
+
+#define VBUSVALID_INT_POL (1 << 8)
+#define IDDIG_INT_POL (1 << 9)
+#define DRVVBUS_INT_POL (1 << 10)
+
+/* mt_usb defines */
+typedef enum {
+ EP0_IDLE = 0,
+ EP0_RX,
+ EP0_TX,
+} EP0_STATE;
+
+/* some macros */
+#define EPMASK(X) (1 << X)
+#define CHANMASK(X) (1 << X)
diff --git a/src/bsp/lk/platform/mt2635/include/platform/mtk_key.h b/src/bsp/lk/platform/mt2635/include/platform/mtk_key.h
new file mode 100644
index 0000000..d89f5a1
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/mtk_key.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#pragma once
+
+bool check_download_key(void);
diff --git a/src/bsp/lk/platform/mt2635/include/platform/mtk_serial_key.h b/src/bsp/lk/platform/mt2635/include/platform/mtk_serial_key.h
new file mode 100644
index 0000000..65185e4
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/mtk_serial_key.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+
+/* serial key */
+#if WITH_KERNEL_VM
+#define SERIAL_KEY_HI (18446462598741254464UL)
+#define SERIAL_KEY_LO (18446462598741254468UL)
+#else
+#define SERIAL_KEY_HI (270557508U)
+#define SERIAL_KEY_LO (270557504U)
+#endif
diff --git a/src/bsp/lk/platform/mt2635/include/platform/mtk_timer.h b/src/bsp/lk/platform/mt2635/include/platform/mtk_timer.h
new file mode 100644
index 0000000..d8a9d3f
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/mtk_timer.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+
+#include <sys/types.h>
+#include <stdbool.h>
+#include <reg.h>
+
+void gpt_busy_wait_us(u32 timeout_us);
+void gpt_busy_wait_ms(u32 timeout_ms);
+
+void mdelay(unsigned long msec);
+void udelay(unsigned long usec);
+void mtk_timer_init(void);
diff --git a/src/bsp/lk/platform/mt2635/include/platform/mtk_wdt.h b/src/bsp/lk/platform/mt2635/include/platform/mtk_wdt.h
new file mode 100644
index 0000000..03505a9
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/mtk_wdt.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+
+#include <platform/mt_reg_base.h>
+#include <stdbool.h>
+#include <platform/mt2635.h>
+
+#define ENABLE_WDT_MODULE (1) /* Module switch */
+#define LK_WDT_DISABLE (1)
+
+#define MTK_WDT_BASE RGU_BASE
+
+#define MTK_WDT_MODE (MTK_WDT_BASE+0x0000)
+#define MTK_WDT_LENGTH (MTK_WDT_BASE+0x0004)
+#define MTK_WDT_RESTART (MTK_WDT_BASE+0x0008)
+#define MTK_WDT_STATUS (MTK_WDT_BASE+0x000C)
+#define MTK_WDT_INTERVAL (MTK_WDT_BASE+0x0010)
+#define MTK_WDT_SWRST (MTK_WDT_BASE+0x0014)
+#define MTK_WDT_SWSYSRST (MTK_WDT_BASE+0x0018)
+#define MTK_WDT_NONRST_REG (MTK_WDT_BASE+0x0020)
+#define MTK_WDT_NONRST_REG2 (MTK_WDT_BASE+0x0024)
+#define MTK_WDT_REQ_MODE (MTK_WDT_BASE+0x0030)
+#define MTK_WDT_REQ_IRQ_EN (MTK_WDT_BASE+0x0034)
+#define MTK_WDT_DRAMC_CTL (MTK_WDT_BASE+0x0040)
+
+/*WDT_MODE*/
+#define MTK_WDT_MODE_KEYMASK (0xff00)
+#define MTK_WDT_MODE_KEY (0x22000000)
+
+#define MTK_WDT_MODE_DUAL_MODE (0x0040)
+#define MTK_WDT_MODE_IN_DIS (0x0020) /* Reserved */
+#define MTK_WDT_MODE_AUTO_RESTART (0x0010) /* Reserved */
+#define MTK_WDT_MODE_IRQ (0x0008)
+#define MTK_WDT_MODE_EXTEN (0x0004)
+#define MTK_WDT_MODE_EXT_POL (0x0002)
+#define MTK_WDT_MODE_ENABLE (0x0001)
+
+/*WDT_LENGTH*/
+#define MTK_WDT_LENGTH_TIME_OUT (0xffe0)
+#define MTK_WDT_LENGTH_KEYMASK (0x001f)
+#define MTK_WDT_LENGTH_KEY (0x0008)
+
+/*WDT_RESTART*/
+#define MTK_WDT_RESTART_KEY (0x1971)
+
+/*WDT_STATUS*/
+#define MTK_WDT_STATUS_HWWDT_RST (0x80000000)
+#define MTK_WDT_STATUS_SWWDT_RST (0x40000000)
+#define MTK_WDT_STATUS_IRQWDT_RST (0x20000000)
+#define MTK_WDT_STATUS_SECURITY_RST (1<<28)
+#define MTK_WDT_STATUS_DEBUGWDT_RST (0x00080000)
+#define MTK_WDT_STATUS_THERMAL_DIRECT_RST (1<<18)
+#define MTK_WDT_STATUS_SPMWDT_RST (0x0002)
+#define MTK_WDT_STATUS_SPM_THERMAL_RST (0x0001)
+
+/*WDT_INTERVAL*/
+#define MTK_WDT_INTERVAL_MASK (0x0fff)
+
+/*WDT_SWRST*/
+#define MTK_WDT_SWRST_KEY (0x1209)
+
+/*WDT_SWSYSRST*/
+#define MTK_WDT_SWSYS_RST_PWRAP_SPI_CTL_RST (0x0800)
+#define MTK_WDT_SWSYS_RST_APMIXED_RST (0x0400)
+#define MTK_WDT_SWSYS_RST_MD_LITE_RST (0x0200)
+#define MTK_WDT_SWSYS_RST_INFRA_AO_RST (0x0100)
+#define MTK_WDT_SWSYS_RST_MD_RST (0x0080)
+#define MTK_WDT_SWSYS_RST_DDRPHY_RST (0x0040)
+#define MTK_WDT_SWSYS_RST_IMG_RST (0x0020)
+#define MTK_WDT_SWSYS_RST_VDEC_RST (0x0010)
+#define MTK_WDT_SWSYS_RST_VENC_RST (0x0008)
+#define MTK_WDT_SWSYS_RST_MFG_RST (0x0004)
+#define MTK_WDT_SWSYS_RST_DISP_RST (0x0002)
+#define MTK_WDT_SWSYS_RST_INFRA_RST (0x0001)
+
+#define MTK_WDT_SWSYS_RST_KEY (0x88000000)
+
+typedef enum wd_swsys_reset_type {
+ WD_MD_RST,
+} WD_SYS_RST_TYPE;
+
+void set_clr_fastboot_mode(bool flag);
+void set_clr_recovery_mode(bool flag);
+bool check_fastboot_mode(void);
+bool check_recovery_mode(void);
+void mtk_wdt_init(void);
+void mtk_wdt_disable(void);
+void mtk_arch_reset(char mode);
diff --git a/src/bsp/lk/platform/mt2635/include/platform/pll.h b/src/bsp/lk/platform/mt2635/include/platform/pll.h
new file mode 100644
index 0000000..5774ac1
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/pll.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PLL1_H
+#define PLL1_H
+
+#include <platform/mt2635.h>
+#include <platform/mt_reg_base.h>
+
+#define APMIXED_BASE (IO_PHYS + 0x00209000)
+#define CKSYS_BASE (IO_PHYS + 0x00210000)
+#define INFRACFG_AO_BASE (IO_PHYS + 0x00000000)
+#define PERICFG_BASE (IO_PHYS + 0x00002000)
+#define MFGCFG_BASE (IO_PHYS + 0x03000000)
+#define MMSYS_CONFIG_BASE (IO_PHYS + 0x04000000)
+#define IMGSYS_BASE (IO_PHYS + 0x05000000)
+#define VDEC_GCON_BASE (IO_PHYS + 0x06000000)
+#define VENC_GCON_BASE (IO_PHYS + 0x07000000)
+
+/* MCUSS Register */
+#define ACLKEN_DIV (IO_PHYS + 0x00200640)
+
+/* APMIXEDSYS Register */
+#define AP_PLL_CON0 (APMIXED_BASE + 0x00)
+#define AP_PLL_CON1 (APMIXED_BASE + 0x04)
+#define AP_PLL_CON2 (APMIXED_BASE + 0x08)
+#define AP_PLL_CON3 (APMIXED_BASE + 0x0C)
+#define AP_PLL_CON4 (APMIXED_BASE + 0x10)
+#define AP_PLL_CON5 (APMIXED_BASE + 0x14)
+#define AP_PLL_CON6 (APMIXED_BASE + 0x18)
+#define AP_PLL_CON7 (APMIXED_BASE + 0x1C)
+#define CLKSQ_STB_CON0 (APMIXED_BASE + 0x20)
+#define PLL_PWR_CON0 (APMIXED_BASE + 0x24)
+#define PLL_PWR_CON1 (APMIXED_BASE + 0x28)
+#define PLL_ISO_CON0 (APMIXED_BASE + 0x2C)
+#define PLL_ISO_CON1 (APMIXED_BASE + 0x30)
+#define PLL_STB_CON0 (APMIXED_BASE + 0x34)
+#define DIV_STB_CON0 (APMIXED_BASE + 0x38)
+#define PLL_CHG_CON0 (APMIXED_BASE + 0x3C)
+#define PLL_TEST_CON0 (APMIXED_BASE + 0x40)
+
+#define ARMPLL_CON0 (APMIXED_BASE + 0x200)
+#define ARMPLL_CON1 (APMIXED_BASE + 0x204)
+#define ARMPLL_CON2 (APMIXED_BASE + 0x208)
+#define ARMPLL_PWR_CON0 (APMIXED_BASE + 0x20C)
+
+#define MAINPLL_CON0 (APMIXED_BASE + 0x210)
+#define MAINPLL_CON1 (APMIXED_BASE + 0x214)
+#define MAINPLL_PWR_CON0 (APMIXED_BASE + 0x21C)
+
+#define UNIVPLL_CON0 (APMIXED_BASE + 0x220)
+#define UNIVPLL_CON1 (APMIXED_BASE + 0x224)
+#define UNIVPLL_PWR_CON0 (APMIXED_BASE + 0x22C)
+
+#define MMPLL_CON0 (APMIXED_BASE + 0x230)
+#define MMPLL_CON1 (APMIXED_BASE + 0x234)
+#define MMPLL_CON2 (APMIXED_BASE + 0x238)
+#define MMPLL_PWR_CON0 (APMIXED_BASE + 0x23C)
+
+#define MSDCPLL_CON0 (APMIXED_BASE + 0x240)
+#define MSDCPLL_CON1 (APMIXED_BASE + 0x244)
+#define MSDCPLL_PWR_CON0 (APMIXED_BASE + 0x24C)
+
+#define VENCPLL_CON0 (APMIXED_BASE + 0x250)
+#define VENCPLL_CON1 (APMIXED_BASE + 0x254)
+#define VENCPLL_PWR_CON0 (APMIXED_BASE + 0x25C)
+
+#define TVDPLL_CON0 (APMIXED_BASE + 0x260)
+#define TVDPLL_CON1 (APMIXED_BASE + 0x264)
+#define TVDPLL_PWR_CON0 (APMIXED_BASE + 0x26C)
+
+#define APLL1_CON0 (APMIXED_BASE + 0x270)
+#define APLL1_CON1 (APMIXED_BASE + 0x274)
+#define APLL1_CON2 (APMIXED_BASE + 0x278)
+#define APLL1_CON3 (APMIXED_BASE + 0x27C)
+#define APLL1_PWR_CON0 (APMIXED_BASE + 0x280)
+
+#define APLL2_CON0 (APMIXED_BASE + 0x284)
+#define APLL2_CON1 (APMIXED_BASE + 0x288)
+#define APLL2_CON2 (APMIXED_BASE + 0x28C)
+#define APLL2_CON3 (APMIXED_BASE + 0x290)
+#define APLL2_PWR_CON0 (APMIXED_BASE + 0x294)
+
+/* TOPCKGEN Register */
+#define CLK_MODE (CKSYS_BASE + 0x000)
+#define TST_SEL_0 (CKSYS_BASE + 0x020)
+#define TST_SEL_1 (CKSYS_BASE + 0x024)
+#define CLK_CFG_0 (CKSYS_BASE + 0x040)
+#define CLK_CFG_1 (CKSYS_BASE + 0x050)
+#define CLK_CFG_2 (CKSYS_BASE + 0x060)
+#define CLK_CFG_3 (CKSYS_BASE + 0x070)
+#define CLK_CFG_4 (CKSYS_BASE + 0x080)
+#define CLK_CFG_5 (CKSYS_BASE + 0x090)
+#define CLK_CFG_6 (CKSYS_BASE + 0x0A0)
+#define CLK_CFG_7 (CKSYS_BASE + 0x0B0)
+#define CLK_CFG_8 (CKSYS_BASE + 0x100)
+#define CLK_CFG_9 (CKSYS_BASE + 0x104)
+#define CLK_CFG_10 (CKSYS_BASE + 0x108)
+#define CLK_CFG_11 (CKSYS_BASE + 0x10C)
+#define CLK_SCP_CFG_0 (CKSYS_BASE + 0x200)
+#define CLK_SCP_CFG_1 (CKSYS_BASE + 0x204)
+#define CLK_MISC_CFG_0 (CKSYS_BASE + 0x210)
+#define CLK_MISC_CFG_1 (CKSYS_BASE + 0x214)
+#define CLK_MISC_CFG_2 (CKSYS_BASE + 0x218)
+#define CLK26CALI_0 (CKSYS_BASE + 0x220)
+#define CLK26CALI_1 (CKSYS_BASE + 0x224)
+#define CLK26CALI_2 (CKSYS_BASE + 0x228)
+#define CKSTA_REG (CKSYS_BASE + 0x22C)
+#define MBIST_CFG_0 (CKSYS_BASE + 0x308)
+#define MBIST_CFG_1 (CKSYS_BASE + 0x30C)
+
+/* INFRASYS Register */
+#define TOP_CKMUXSEL (INFRACFG_AO_BASE + 0x00)
+#define TOP_CKDIV1 (INFRACFG_AO_BASE + 0x08)
+#define TOP_DCMCTL (INFRACFG_AO_BASE + 0x10)
+
+#define INFRA_GLOBALCON_DCMCTL (INFRACFG_AO_BASE + 0x050) //0x10000050
+/** 0x10000050 INFRA_GLOBALCON_DCMCTL
+ * 0 0 faxi_dcm_enable
+ * 1 1 fmem_dcm_enable
+ * 8 8 axi_clock_gated_en
+ * 9 9 l2c_sram_infra_dcm_en
+ **/
+#define INFRA_GLOBALCON_DCMCTL_MASK (0x00000303)
+#define INFRA_GLOBALCON_DCMCTL_ON (0x00000303)
+#define INFRA_GLOBALCON_DCMDBC (INFRACFG_AO_BASE + 0x054) //0x10000054
+/** 0x10000054 INFRA_GLOBALCON_DCMDBC
+ * 6 0 dcm_dbc_cnt (default 7'h7F)
+ * 8 8 faxi_dcm_dbc_enable
+ * 22 16 dcm_dbc_cnt_fmem (default 7'h7F)
+ * 24 24 dcm_dbc_enable_fmem
+ **/
+#define INFRA_GLOBALCON_DCMDBC_MASK ((0x7f<<0) | (1<<8) | (0x7f<<16) | (1<<24))
+#define INFRA_GLOBALCON_DCMDBC_ON ((0<<0) | (1<<8) | (0<<16) | (1<<24))
+#define INFRA_GLOBALCON_DCMFSEL (INFRACFG_AO_BASE + 0x058) //0x10000058
+/** 0x10000058 INFRA_GLOBALCON_DCMFSEL
+ * 2 0 dcm_qtr_fsel ("1xx: 1/4, 01x: 1/8, 001: 1/16, 000: 1/32")
+ * 11 8 dcm_half_fsel ("1xxx:1/2, 01xx: 1/4, 001x: 1/8, 0001: 1/16, 0000: 1/32")
+ * 20 16 dcm_full_fsel ("1xxxx:1/1, 01xxx:1/2, 001xx: 1/4, 0001x: 1/8, 00001: 1/16, 00000: 1/32")
+ * 28 24 dcm_full_fsel_fmem ("1xxxx:1/1, 01xxx:1/2, 001xx: 1/4, 0001x: 1/8, 00001: 1/16, 00000: 1/32")
+ **/
+#define INFRA_GLOBALCON_DCMFSEL_MASK ((0x7<<0) | (0xf<<8) | (0x1f<<16) | (0x1f<<24))
+#define INFRA_GLOBALCON_DCMFSEL_ON ((0<<0) | (0<<8) | (0x10<<16) | (0x10<<24))
+
+#define INFRA_PDN_SET0 (INFRACFG_AO_BASE + 0x0040)
+#define INFRA_PDN_CLR0 (INFRACFG_AO_BASE + 0x0044)
+#define INFRA_PDN_STA0 (INFRACFG_AO_BASE + 0x0048)
+
+#define TOPAXI_PROT_EN (INFRACFG_AO_BASE + 0x0220)
+#define TOPAXI_PROT_STA1 (INFRACFG_AO_BASE + 0x0228)
+
+#define PERI_PDN_SET0 (PERICFG_BASE + 0x0008)
+#define PERI_PDN_CLR0 (PERICFG_BASE + 0x0010)
+#define PERI_PDN_STA0 (PERICFG_BASE + 0x0018)
+
+/* MFGCFG Register*/
+#define MFG_CG_CON (MFGCFG_BASE + 0)
+#define MFG_CG_SET (MFGCFG_BASE + 4)
+#define MFG_CG_CLR (MFGCFG_BASE + 8)
+
+/* MMSYS Register*/
+#define DISP_CG_CON0 (MMSYS_CONFIG_BASE + 0x100)
+#define DISP_CG_SET0 (MMSYS_CONFIG_BASE + 0x104)
+#define DISP_CG_CLR0 (MMSYS_CONFIG_BASE + 0x108)
+#define DISP_CG_CON1 (MMSYS_CONFIG_BASE + 0x110)
+#define DISP_CG_SET1 (MMSYS_CONFIG_BASE + 0x114)
+#define DISP_CG_CLR1 (MMSYS_CONFIG_BASE + 0x118)
+
+#define MMSYS_DUMMY (MMSYS_CONFIG_BASE + 0x890)
+
+/* IMGSYS Register */
+#define IMG_CG_CON (IMGSYS_BASE + 0x0000)
+#define IMG_CG_SET (IMGSYS_BASE + 0x0004)
+#define IMG_CG_CLR (IMGSYS_BASE + 0x0008)
+
+/* VDEC Register */
+#define VDEC_CKEN_SET (VDEC_GCON_BASE + 0x0000)
+#define VDEC_CKEN_CLR (VDEC_GCON_BASE + 0x0004)
+#define LARB_CKEN_SET (VDEC_GCON_BASE + 0x0008)
+#define LARB_CKEN_CLR (VDEC_GCON_BASE + 0x000C)
+
+/* VENC Register*/
+#define VENC_CG_CON (VENC_GCON_BASE + 0x0)
+#define VENC_CG_SET (VENC_GCON_BASE + 0x4)
+#define VENC_CG_CLR (VENC_GCON_BASE + 0x8)
+
+enum {
+ PLL_MODE_1 = 1,
+ PLL_MODE_2 = 2,
+ PLL_MODE_3 = 3,
+};
+enum {
+ DDR533 = 533,
+ DDR800 = 800,
+ DDR938 = 938,
+ DDR1066 = 1066,
+ DDR1333 = 1333,
+ DDR1466 = 1466,
+};
+
+#ifdef DDRPHY_3PLL_MODE
+#define PHYSYNC_MODE
+#if 1
+#define DDRPHY_2PLL
+#endif
+#endif
+
+#define DDR_1333
+
+void mt_pll_init(void);
+void mt_pll_post_init(void);
+void mt_init_mempll(void);
+
+#endif
diff --git a/src/bsp/lk/platform/mt2635/include/platform/pmic.h b/src/bsp/lk/platform/mt2635/include/platform/pmic.h
new file mode 100644
index 0000000..a9c4f96
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/pmic.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+
+#define PMIC6325_E1_CID_CODE 0x2510
+#define PMIC6325_E2_CID_CODE 0x2520
+#define PMIC6325_E3_CID_CODE 0x2530
+
+#define VCORE_ADDR 0x0616
+#define VCORE_MASK 0x7F
+#define VCORE_SHIFT 0
+
+#define EFUSE_ADDR 0x0A30
+#define EFUSE_MASK 0x1
+#define EFUSE_SHIFT 1
+
+/* ==================================================
+ * PMIC Exported Function
+ * ==================================================
+ */
+extern void mt_pmic_init (void);
+extern void pmic_set_vcore(unsigned int voltage_mv);
+extern unsigned int pmic_get_vcore(void);
+extern void pmic_set_efuse(unsigned int voltage_mv);
+extern unsigned int pmic_enable_efuse(bool on);
\ No newline at end of file
diff --git a/src/bsp/lk/platform/mt2635/include/platform/pmic_wrap_init.h b/src/bsp/lk/platform/mt2635/include/platform/pmic_wrap_init.h
new file mode 100644
index 0000000..6ec02a4
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/pmic_wrap_init.h
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+#include <debug.h>
+#include <platform/pll.h>
+#include <reg.h>
+#include <stdint.h>
+
+typedef unsigned int *UINT32P;
+
+#define PWRAPTAG "[PWRAP] "
+#define PWRAPFUC(fmt, arg...) dprintf(SPEW, PWRAPTAG "%s\n", __FUNCTION__)
+#define PWRAPLOG(fmt, arg...) dprintf(INFO, PWRAPTAG fmt,##arg)
+#define PWRAPERR(fmt, arg...) dprintf(ALWAYS, PWRAPTAG "ERROR,line=%d\r\n" fmt, __LINE__, ##arg)
+
+/* global variable and sys interface */
+#define TIMEOUT_READ 0xFF
+#define TIMEOUT_WAIT_IDLE 0xFF
+
+#define CLK_CFG_4_CLR (CKSYS_BASE+0x088) //6582
+#define CLK_SPI_CK_26M 0x70000
+
+#define INFRACFG_AO_REG_BASE INFRACFG_AO_BASE
+#define INFRA_GLOBALCON_RST0 (INFRACFG_AO_REG_BASE+0x030)
+#define INFRA_GLOBALCON_RST1 (INFRACFG_AO_REG_BASE+0x034)
+
+#define PWRAP_BASE (IO_PHYS + 0x1000)
+#define PMIC_WRAP_BASE (PWRAP_BASE) /* 0x1000D000 */
+#define PMIC_WRAP_MUX_SEL ((UINT32P)(PMIC_WRAP_BASE+0x0))
+#define PMIC_WRAP_WRAP_EN ((UINT32P)(PMIC_WRAP_BASE+0x4))
+#define PMIC_WRAP_DIO_EN ((UINT32P)(PMIC_WRAP_BASE+0x8))
+#define PMIC_WRAP_SIDLY ((UINT32P)(PMIC_WRAP_BASE+0xC))
+#define PMIC_WRAP_RDDMY ((UINT32P)(PMIC_WRAP_BASE+0x10))
+#define PMIC_WRAP_SI_CK_CON ((UINT32P)(PMIC_WRAP_BASE+0x14))
+#define PMIC_WRAP_CSHEXT_WRITE ((UINT32P)(PMIC_WRAP_BASE+0x18))
+#define PMIC_WRAP_CSHEXT_READ ((UINT32P)(PMIC_WRAP_BASE+0x1C))
+#define PMIC_WRAP_CSLEXT_START ((UINT32P)(PMIC_WRAP_BASE+0x20))
+#define PMIC_WRAP_CSLEXT_END ((UINT32P)(PMIC_WRAP_BASE+0x24))
+#define PMIC_WRAP_STAUPD_PRD ((UINT32P)(PMIC_WRAP_BASE+0x28))
+#define PMIC_WRAP_STAUPD_GRPEN ((UINT32P)(PMIC_WRAP_BASE+0x2C))
+#define PMIC_WRAP_EINT_STA0_ADR ((UINT32P)(PMIC_WRAP_BASE+0x30))
+#define PMIC_WRAP_HIPRIO_ARB_EN ((UINT32P)(PMIC_WRAP_BASE+0x54))
+#define PMIC_WRAP_MAN_EN ((UINT32P)(PMIC_WRAP_BASE+0x60))
+#define PMIC_WRAP_MAN_CMD ((UINT32P)(PMIC_WRAP_BASE+0x64))
+#define PMIC_WRAP_WACS0_EN ((UINT32P)(PMIC_WRAP_BASE+0x70))
+#define PMIC_WRAP_INIT_DONE0 ((UINT32P)(PMIC_WRAP_BASE+0x74))
+#define PMIC_WRAP_WACS1_EN ((UINT32P)(PMIC_WRAP_BASE+0x84))
+#define PMIC_WRAP_INIT_DONE1 ((UINT32P)(PMIC_WRAP_BASE+0x88))
+#define PMIC_WRAP_WACS2_EN ((UINT32P)(PMIC_WRAP_BASE+0x98))
+#define PMIC_WRAP_INIT_DONE2 ((UINT32P)(PMIC_WRAP_BASE+0x9C))
+#define PMIC_WRAP_WACS2_CMD ((UINT32P)(PMIC_WRAP_BASE+0xA0))
+#define PMIC_WRAP_WACS2_RDATA ((UINT32P)(PMIC_WRAP_BASE+0xA4))
+#define PMIC_WRAP_WACS2_VLDCLR ((UINT32P)(PMIC_WRAP_BASE+0xA8))
+#define PMIC_WRAP_WACS3_EN ((UINT32P)(PMIC_WRAP_BASE+0xAC))
+#define PMIC_WRAP_INIT_DONE3 ((UINT32P)(PMIC_WRAP_BASE+0xB0))
+#define PMIC_WRAP_INT_EN ((UINT32P)(PMIC_WRAP_BASE+0xC0))
+#define PMIC_WRAP_SIG_ADR ((UINT32P)(PMIC_WRAP_BASE+0xD0))
+#define PMIC_WRAP_SIG_MODE ((UINT32P)(PMIC_WRAP_BASE+0xD4))
+#define PMIC_WRAP_SIG_VALUE ((UINT32P)(PMIC_WRAP_BASE+0xD8))
+#define PMIC_WRAP_TIMER_EN ((UINT32P)(PMIC_WRAP_BASE+0xE4))
+#define PMIC_WRAP_WDT_UNIT ((UINT32P)(PMIC_WRAP_BASE+0xEC))
+#define PMIC_WRAP_WDT_SRC_EN ((UINT32P)(PMIC_WRAP_BASE+0xF0))
+#define PMIC_WRAP_CIPHER_KEY_SEL ((UINT32P)(PMIC_WRAP_BASE+0x180))
+#define PMIC_WRAP_CIPHER_IV_SEL ((UINT32P)(PMIC_WRAP_BASE+0x184))
+#define PMIC_WRAP_CIPHER_EN ((UINT32P)(PMIC_WRAP_BASE+0x188))
+#define PMIC_WRAP_CIPHER_RDY ((UINT32P)(PMIC_WRAP_BASE+0x18C))
+#define PMIC_WRAP_CIPHER_MODE ((UINT32P)(PMIC_WRAP_BASE+0x190))
+#define PMIC_WRAP_CIPHER_SWRST ((UINT32P)(PMIC_WRAP_BASE+0x194))
+#define PMIC_WRAP_DCM_EN ((UINT32P)(PMIC_WRAP_BASE+0x198))
+#define PMIC_WRAP_DCM_DBC_PRD ((UINT32P)(PMIC_WRAP_BASE+0x19C))
+#define PMIC_WRAP_ADC_CMD_ADDR ((UINT32P)(PMIC_WRAP_BASE+0x1A4))
+#define PMIC_WRAP_PWRAP_ADC_CMD ((UINT32P)(PMIC_WRAP_BASE+0x1A8))
+#define PMIC_WRAP_ADC_RDATA_ADDR ((UINT32P)(PMIC_WRAP_BASE+0x1AC))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR_LATEST ((UINT32P)(PMIC_WRAP_BASE+0x1B8))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR_WP ((UINT32P)(PMIC_WRAP_BASE+0x1BC))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR0 ((UINT32P)(PMIC_WRAP_BASE+0x1C0))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR1 ((UINT32P)(PMIC_WRAP_BASE+0x1C4))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR2 ((UINT32P)(PMIC_WRAP_BASE+0x1C8))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR3 ((UINT32P)(PMIC_WRAP_BASE+0x1CC))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR4 ((UINT32P)(PMIC_WRAP_BASE+0x1D0))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR5 ((UINT32P)(PMIC_WRAP_BASE+0x1D4))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR6 ((UINT32P)(PMIC_WRAP_BASE+0x1D8))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR7 ((UINT32P)(PMIC_WRAP_BASE+0x1DC))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR8 ((UINT32P)(PMIC_WRAP_BASE+0x1E0))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR9 ((UINT32P)(PMIC_WRAP_BASE+0x1E4))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR10 ((UINT32P)(PMIC_WRAP_BASE+0x1E8))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR11 ((UINT32P)(PMIC_WRAP_BASE+0x1EC))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR12 ((UINT32P)(PMIC_WRAP_BASE+0x1F0))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR13 ((UINT32P)(PMIC_WRAP_BASE+0x1F4))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR14 ((UINT32P)(PMIC_WRAP_BASE+0x1F8))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR15 ((UINT32P)(PMIC_WRAP_BASE+0x1FC))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR16 ((UINT32P)(PMIC_WRAP_BASE+0x200))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR17 ((UINT32P)(PMIC_WRAP_BASE+0x204))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR18 ((UINT32P)(PMIC_WRAP_BASE+0x208))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR19 ((UINT32P)(PMIC_WRAP_BASE+0x20C))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR20 ((UINT32P)(PMIC_WRAP_BASE+0x210))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR21 ((UINT32P)(PMIC_WRAP_BASE+0x214))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR22 ((UINT32P)(PMIC_WRAP_BASE+0x218))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR23 ((UINT32P)(PMIC_WRAP_BASE+0x21C))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR24 ((UINT32P)(PMIC_WRAP_BASE+0x220))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR25 ((UINT32P)(PMIC_WRAP_BASE+0x224))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR26 ((UINT32P)(PMIC_WRAP_BASE+0x228))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR27 ((UINT32P)(PMIC_WRAP_BASE+0x22C))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR28 ((UINT32P)(PMIC_WRAP_BASE+0x230))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR29 ((UINT32P)(PMIC_WRAP_BASE+0x234))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR30 ((UINT32P)(PMIC_WRAP_BASE+0x238))
+#define PMIC_WRAP_MD_ADC_RDATA_ADDR31 ((UINT32P)(PMIC_WRAP_BASE+0x23C))
+
+/* macro for wrapper regsister */
+#define GET_WACS0_FSM(x) ((x>>16) & 0x00000007)
+#define GET_WACS2_FSM(x) ((x>>16) & 0x00000007)
+#define GET_WACS0_RDATA(x) ((x>>0) & 0x0000ffff)
+#define GET_SYNC_IDLE0(x) ((x>>20) & 0x00000001)
+#define GET_SYNC_IDLE2(x) ((x>>20) & 0x00000001)
+#define GET_INIT_DONE0(x) ((x>>21) & 0x00000001)
+
+#define ENABLE 1
+#define DISABLE 0
+#define DISABLE_ALL 0
+
+#define WACS2 (1 << 5)
+
+#define WRAPPER_MODE 0
+#define MANUAL_MODE 1
+
+#define WACS_FSM_IDLE (0x00)
+#define WACS_FSM_REQ (0x02)
+#define WACS_FSM_WFDLE (0x04)
+#define WACS_FSM_WFVLDCLR (0x06)
+#define WACS_INIT_DONE (0x01)
+#define WACS_SYNC_IDLE (0x01)
+#define WACS_SYNC_BUSY (0x00)
+
+#define MT6328_PMIC_REG_BASE (0x0000)
+#define MT6328_HWCID ((uint32_t)(MT6328_PMIC_REG_BASE+0x0200))
+#define MT6328_SWCID ((uint32_t)(MT6328_PMIC_REG_BASE+0x0202))
+#define MT6328_DEW_DIO_EN ((uint32_t)(MT6328_PMIC_REG_BASE+0x02D4))
+#define MT6328_DEW_READ_TEST ((uint32_t)(MT6328_PMIC_REG_BASE+0x02D6))
+#define MT6328_DEW_WRITE_TEST ((uint32_t)(MT6328_PMIC_REG_BASE+0x02D8))
+#define MT6328_DEW_CRC_EN ((uint32_t)(MT6328_PMIC_REG_BASE+0x02DC))
+#define MT6328_DEW_CRC_VAL ((uint32_t)(MT6328_PMIC_REG_BASE+0x02DE))
+#define MT6328_DEW_CIPHER_KEY_SEL ((uint32_t)(MT6328_PMIC_REG_BASE+0x02E2))
+#define MT6328_DEW_CIPHER_IV_SEL ((uint32_t)(MT6328_PMIC_REG_BASE+0x02E4))
+#define MT6328_DEW_CIPHER_EN ((uint32_t)(MT6328_PMIC_REG_BASE+0x02E6))
+#define MT6328_DEW_CIPHER_RDY ((uint32_t)(MT6328_PMIC_REG_BASE+0x02E8))
+#define MT6328_DEW_CIPHER_MODE ((uint32_t)(MT6328_PMIC_REG_BASE+0x02EA))
+#define MT6328_DEW_CIPHER_SWRST ((uint32_t)(MT6328_PMIC_REG_BASE+0x02EC))
+#define MT6328_DEW_RDDMY_NO ((uint32_t)(MT6328_PMIC_REG_BASE+0x02EE))
+#define MT6328_INT_STA ((uint32_t)(MT6328_PMIC_REG_BASE+0x0302))
+#define MT6328_LDO_RSV_CON1 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0A8E))
+#define MT6328_AUXADC_ADC32 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E40))
+#define MT6328_AUXADC_BUF0 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E44))
+#define MT6328_AUXADC_BUF1 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E46))
+#define MT6328_AUXADC_BUF2 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E48))
+#define MT6328_AUXADC_BUF3 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E4A))
+#define MT6328_AUXADC_BUF4 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E4C))
+#define MT6328_AUXADC_BUF5 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E4E))
+#define MT6328_AUXADC_BUF6 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E50))
+#define MT6328_AUXADC_BUF7 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E52))
+#define MT6328_AUXADC_BUF8 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E54))
+#define MT6328_AUXADC_BUF9 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E56))
+#define MT6328_AUXADC_BUF10 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E58))
+#define MT6328_AUXADC_BUF11 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E5A))
+#define MT6328_AUXADC_BUF12 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E5C))
+#define MT6328_AUXADC_BUF13 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E5E))
+#define MT6328_AUXADC_BUF14 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E60))
+#define MT6328_AUXADC_BUF15 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E62))
+#define MT6328_AUXADC_BUF16 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E64))
+#define MT6328_AUXADC_BUF17 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E66))
+#define MT6328_AUXADC_BUF18 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E68))
+#define MT6328_AUXADC_BUF19 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E6A))
+#define MT6328_AUXADC_BUF20 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E6C))
+#define MT6328_AUXADC_BUF21 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E6E))
+#define MT6328_AUXADC_BUF22 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E70))
+#define MT6328_AUXADC_BUF23 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E72))
+#define MT6328_AUXADC_BUF24 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E74))
+#define MT6328_AUXADC_BUF25 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E76))
+#define MT6328_AUXADC_BUF26 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E78))
+#define MT6328_AUXADC_BUF27 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E7A))
+#define MT6328_AUXADC_BUF28 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E7C))
+#define MT6328_AUXADC_BUF29 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E7E))
+#define MT6328_AUXADC_BUF30 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E80))
+#define MT6328_AUXADC_BUF31 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0E82))
+#define MT6328_AUXADC_MDBG_1 ((uint32_t)(MT6328_PMIC_REG_BASE+0x0F0A))
+
+#define MT6328_DEFAULT_VALUE_READ_TEST 0x5aa5
+#define MT6328_WRITE_TEST_VALUE 0x1234
+
+/* manual commnd */
+#define OP_RD (0x0)
+#define OP_WR (0x1)
+
+#define OP_CSH (0x0)
+#define OP_CSL (0x1)
+#define OP_OUTS (0x8)
+
+/* error code */
+#define E_PWR_INVALID_ARG 1
+#define E_PWR_INVALID_RW 2
+#define E_PWR_INVALID_ADDR 3
+#define E_PWR_INVALID_WDAT 4
+#define E_PWR_INVALID_OP_MANUAL 5
+#define E_PWR_NOT_IDLE_STATE 6
+#define E_PWR_NOT_INIT_DONE 7
+#define E_PWR_NOT_INIT_DONE_READ 8
+#define E_PWR_WAIT_IDLE_TIMEOUT 9
+#define E_PWR_WAIT_IDLE_TIMEOUT_READ 10
+#define E_PWR_INIT_SIDLY_FAIL 11
+#define E_PWR_RESET_TIMEOUT 12
+#define E_PWR_TIMEOUT 13
+
+#define E_PWR_INIT_RESET_SPI 20
+#define E_PWR_INIT_SIDLY 21
+#define E_PWR_INIT_REG_CLOCK 22
+#define E_PWR_INIT_ENABLE_PMIC 23
+#define E_PWR_INIT_DIO 24
+#define E_PWR_INIT_CIPHER 25
+#define E_PWR_INIT_WRITE_TEST 26
+#define E_PWR_INIT_ENABLE_CRC 27
+#define E_PWR_INIT_ENABLE_DEWRAP 28
+
+#define E_PWR_READ_TEST_FAIL 30
+#define E_PWR_WRITE_TEST_FAIL 31
+#define E_PWR_SWITCH_DIO 32
+
+#define WRAP_RD32(addr) readl(addr)
+#define WRAP_WR32(addr,val) writel(val, addr)
+
+extern int pwrap_wacs2(uint32_t write, uint32_t adr, uint32_t wdata, uint32_t *rdata);
+extern int pwrap_init_preloader(void);
diff --git a/src/bsp/lk/platform/mt2635/include/platform/spm.h b/src/bsp/lk/platform/mt2635/include/platform/spm.h
new file mode 100644
index 0000000..737f31b
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/spm.h
@@ -0,0 +1,360 @@
+#ifndef _SPM_
+#define _SPM_
+
+/*
+//XXX: only in kernel
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include <mach/mt_reg_base.h>
+#include <mach/mt_irq.h>
+#include <mach/sync_write.h>
+*/
+#include <platform.h>
+// #include <typedefs.h>
+// #include <sync_write.h>
+
+/**************************************
+ * Config and Parameter
+ **************************************/
+//#define SPM_BASE SLEEP_BASE
+#define SPM_IRQ0_ID SLEEP_IRQ_BIT0_ID
+#define SPM_IRQ1_ID SLEEP_IRQ_BIT1_ID
+#define SPM_IRQ2_ID SLEEP_IRQ_BIT2_ID
+#define SPM_IRQ3_ID SLEEP_IRQ_BIT3_ID
+#define SPM_IRQ4_ID SLEEP_IRQ_BIT4_ID
+#define SPM_IRQ5_ID SLEEP_IRQ_BIT5_ID
+#define SPM_IRQ6_ID SLEEP_IRQ_BIT6_ID
+#define SPM_IRQ7_ID SLEEP_IRQ_BIT7_ID
+
+
+/**************************************
+ * Define and Declare
+ **************************************/
+#define SPM_POWERON_CONFIG_SET (SPM_BASE + 0x000)
+#define SPM_POWER_ON_VAL0 (SPM_BASE + 0x010)
+#define SPM_POWER_ON_VAL1 (SPM_BASE + 0x014)
+#define SPM_CLK_SETTLE (SPM_BASE + 0x100)
+#define SPM_CA7_CPU0_PWR_CON (SPM_BASE + 0x200)
+#define SPM_CA7_DBG_PWR_CON (SPM_BASE + 0x204)
+#define SPM_CA7_CPUTOP_PWR_CON (SPM_BASE + 0x208)
+#define SPM_VDE_PWR_CON (SPM_BASE + 0x210)
+#define SPM_MFG_PWR_CON (SPM_BASE + 0x214)
+#define SPM_CA7_CPU1_PWR_CON (SPM_BASE + 0x218)
+#define SPM_CA7_CPU2_PWR_CON (SPM_BASE + 0x21c)
+#define SPM_CA7_CPU3_PWR_CON (SPM_BASE + 0x220)
+#define SPM_VEN_PWR_CON (SPM_BASE + 0x230)
+#define SPM_IFR_PWR_CON (SPM_BASE + 0x234)
+#define SPM_ISP_PWR_CON (SPM_BASE + 0x238)
+#define SPM_DIS_PWR_CON (SPM_BASE + 0x23c)
+#define SPM_DPY_PWR_CON (SPM_BASE + 0x240)
+#define SPM_CA7_CPUTOP_L2_PDN (SPM_BASE + 0x244)
+#define SPM_CA7_CPUTOP_L2_SLEEP (SPM_BASE + 0x248)
+#define SPM_CA7_CPU0_L1_PDN (SPM_BASE + 0x25c)
+#define SPM_CA7_CPU1_L1_PDN (SPM_BASE + 0x264)
+#define SPM_CA7_CPU2_L1_PDN (SPM_BASE + 0x26c)
+#define SPM_CA7_CPU3_L1_PDN (SPM_BASE + 0x274)
+#define SPM_GCPU_SRAM_CON (SPM_BASE + 0x27c)
+#define SPM_CONN_PWR_CON (SPM_BASE + 0x280)
+#define SPM_MD_PWR_CON (SPM_BASE + 0x284)
+#define SPM_MCU_PWR_CON (SPM_BASE + 0x290)
+#define SPM_IFR_SRAMROM_CON (SPM_BASE + 0x294)
+#define SPM_MJC_PWR_CON (SPM_BASE + 0x298)
+#define SPM_AUDIO_PWR_CON (SPM_BASE + 0x29c)
+#define SPM_CA15_CPU0_PWR_CON (SPM_BASE + 0x2a0)
+#define SPM_CA15_CPU1_PWR_CON (SPM_BASE + 0x2a4)
+#define SPM_CA15_CPU2_PWR_CON (SPM_BASE + 0x2a8)
+#define SPM_CA15_CPU3_PWR_CON (SPM_BASE + 0x2ac)
+#define SPM_CA15_CPUTOP_PWR_CON (SPM_BASE + 0x2b0)
+#define SPM_CA15_L1_PWR_CON (SPM_BASE + 0x2b4)
+#define SPM_CA15_L2_PWR_CON (SPM_BASE + 0x2b8)
+#define SPM_MFG_2D_PWR_CON (SPM_BASE + 0x2c0)
+#define SPM_MFG_ASYNC_PWR_CON (SPM_BASE + 0x2c4)
+#define SPM_MD32_SRAM_CON (SPM_BASE + 0x2c8)
+#define SPM_ARMPLL_DIV_PWR_CON (SPM_BASE + 0x2cc)
+#define SPM_MD2_PWR_CON (SPM_BASE + 0x2d0)
+#define SPM_C2K_PWR_CON (SPM_BASE + 0x2d4)//mt6735
+#define SPM_INFRA_MD_PWR_CON (SPM_BASE + 0x2d8)//mt6735
+#define SPM_CPU_EXT_ISO (SPM_BASE + 0x2dc)//mt6735
+#define SPM_PCM_CON0 (SPM_BASE + 0x310)
+#define SPM_PCM_CON1 (SPM_BASE + 0x314)
+#define SPM_PCM_IM_PTR (SPM_BASE + 0x318)
+#define SPM_PCM_IM_LEN (SPM_BASE + 0x31c)
+#define SPM_PCM_REG_DATA_INI (SPM_BASE + 0x320)
+#define SPM_PCM_EVENT_VECTOR0 (SPM_BASE + 0x340)
+#define SPM_PCM_EVENT_VECTOR1 (SPM_BASE + 0x344)
+#define SPM_PCM_EVENT_VECTOR2 (SPM_BASE + 0x348)
+#define SPM_PCM_EVENT_VECTOR3 (SPM_BASE + 0x34c)
+#define SPM_PCM_MAS_PAUSE_MASK (SPM_BASE + 0x354)
+#define SPM_PCM_PWR_IO_EN (SPM_BASE + 0x358)
+#define SPM_PCM_TIMER_VAL (SPM_BASE + 0x35c)
+#define SPM_PCM_TIMER_OUT (SPM_BASE + 0x360)
+#define SPM_PCM_REG0_DATA (SPM_BASE + 0x380)
+#define SPM_PCM_REG1_DATA (SPM_BASE + 0x384)
+#define SPM_PCM_REG2_DATA (SPM_BASE + 0x388)
+#define SPM_PCM_REG3_DATA (SPM_BASE + 0x38c)
+#define SPM_PCM_REG4_DATA (SPM_BASE + 0x390)
+#define SPM_PCM_REG5_DATA (SPM_BASE + 0x394)
+#define SPM_PCM_REG6_DATA (SPM_BASE + 0x398)
+#define SPM_PCM_REG7_DATA (SPM_BASE + 0x39c)
+#define SPM_PCM_REG8_DATA (SPM_BASE + 0x3a0)
+#define SPM_PCM_REG9_DATA (SPM_BASE + 0x3a4)
+#define SPM_PCM_REG10_DATA (SPM_BASE + 0x3a8)
+#define SPM_PCM_REG11_DATA (SPM_BASE + 0x3ac)
+#define SPM_PCM_REG12_DATA (SPM_BASE + 0x3b0)
+#define SPM_PCM_REG13_DATA (SPM_BASE + 0x3b4)
+#define SPM_PCM_REG14_DATA (SPM_BASE + 0x3b8)
+#define SPM_PCM_REG15_DATA (SPM_BASE + 0x3bc)
+#define SPM_PCM_EVENT_REG_STA (SPM_BASE + 0x3c0)
+#define SPM_PCM_FSM_STA (SPM_BASE + 0x3c4)
+#define SPM_PCM_IM_HOST_RW_PTR (SPM_BASE + 0x3c8)
+#define SPM_PCM_IM_HOST_RW_DAT (SPM_BASE + 0x3cc)
+#define SPM_PCM_EVENT_VECTOR4 (SPM_BASE + 0x3d0)
+#define SPM_PCM_EVENT_VECTOR5 (SPM_BASE + 0x3d4)
+#define SPM_PCM_EVENT_VECTOR6 (SPM_BASE + 0x3d8)
+#define SPM_PCM_EVENT_VECTOR7 (SPM_BASE + 0x3dc)
+#define SPM_PCM_SW_INT_SET (SPM_BASE + 0x3e0)
+#define SPM_PCM_SW_INT_CLEAR (SPM_BASE + 0x3e4)
+#define SPM_CLK_CON (SPM_BASE + 0x400)
+#define SPM_SLEEP_DUAL_VCORE_PWR_CON (SPM_BASE + 0x404)
+#define SPM_SLEEP_PTPOD2_CON (SPM_BASE + 0x408)
+#define SPM_APMCU_PWRCTL (SPM_BASE + 0x600)
+#define SPM_AP_DVFS_CON_SET (SPM_BASE + 0x604)
+#define SPM_AP_STANBY_CON (SPM_BASE + 0x608)
+#define SPM_PWR_STATUS (SPM_BASE + 0x60c)
+#define SPM_PWR_STATUS_2ND (SPM_BASE + 0x610)
+//#define SPM_AP_BSI_REQ (SPM_BASE + 0x614)
+#define SPM_SLEEP_MDBSI_CON (SPM_BASE + 0x614)//mt6735
+#define SPM_BSI_GEN (SPM_BASE + 0x620)//mt6735
+#define SPM_BSI_EN_SR (SPM_BASE + 0x624)//mt6735
+#define SPM_BSI_CLK_SR (SPM_BASE + 0x628)//mt6735
+#define SPM_BSI_DO_SR (SPM_BASE + 0x62c)//mt6735
+#define SPM_BSI_D1_SR (SPM_BASE + 0x630)//mt6735
+#define SPM_BSI_D2_SR (SPM_BASE + 0x634)//mt6735
+#define SPM_AP_SEMA (SPM_BASE + 0x638)//mt6735
+#define SPM_SPM_SEMA (SPM_BASE + 0x63c)//mt6735
+#define SPM_SLEEP_TIMER_STA (SPM_BASE + 0x720)
+#define SPM_SLEEP_TWAM_CON (SPM_BASE + 0x760)
+#define SPM_SLEEP_TWAM_STATUS0 (SPM_BASE + 0x764)
+#define SPM_SLEEP_TWAM_STATUS1 (SPM_BASE + 0x768)
+#define SPM_SLEEP_TWAM_STATUS2 (SPM_BASE + 0x76c)
+#define SPM_SLEEP_TWAM_STATUS3 (SPM_BASE + 0x770)
+#define SPM_SLEEP_TWAM_CURR_STATUS0 (SPM_BASE + 0x774)
+#define SPM_SLEEP_TWAM_CURR_STATUS1 (SPM_BASE + 0x778)
+#define SPM_SLEEP_TWAM_CURR_STATUS2 (SPM_BASE + 0x77C)
+#define SPM_SLEEP_TWAM_CURR_STATUS3 (SPM_BASE + 0x780)
+#define SPM_SLEEP_TWAM_TIMER_OUT (SPM_BASE + 0x784)
+#define SPM_SLEEP_TWAM_WINDOW_LEN (SPM_BASE + 0x788)
+#define SPM_SLEEP_IDLE_SEL (SPM_BASE + 0x78C)
+#define SPM_SLEEP_WAKEUP_EVENT_MASK (SPM_BASE + 0x810)
+#define SPM_SLEEP_CPU_WAKEUP_EVENT (SPM_BASE + 0x814)
+#define SPM_SLEEP_MD32_WAKEUP_EVENT_MASK (SPM_BASE + 0x818)
+#define SPM_PCM_WDT_TIMER_VAL (SPM_BASE + 0x824)
+#define SPM_PCM_WDT_TIMER_OUT (SPM_BASE + 0x828)
+#define SPM_PCM_MD32_MAILBOX (SPM_BASE + 0x830)
+#define SPM_PCM_MD32_IRQ (SPM_BASE + 0x834)
+#define SPM_SLEEP_ISR_MASK (SPM_BASE + 0x900)
+#define SPM_SLEEP_ISR_STATUS (SPM_BASE + 0x904)
+#define SPM_SLEEP_ISR_RAW_STA (SPM_BASE + 0x910)
+#define SPM_SLEEP_MD32_ISR_RAW_STA (SPM_BASE + 0x914)
+#define SPM_SLEEP_WAKEUP_MISC (SPM_BASE + 0x918)
+#define SPM_SLEEP_BUS_PROTECT_RDY (SPM_BASE + 0x91c)
+#define SPM_SLEEP_SUBSYS_IDLE_STA (SPM_BASE + 0x920)
+#define SPM_PCM_RESERVE (SPM_BASE + 0xb00)
+#define SPM_PCM_RESERVE2 (SPM_BASE + 0xb04)
+#define SPM_PCM_FLAGS (SPM_BASE + 0xb08)
+#define SPM_PCM_SRC_REQ (SPM_BASE + 0xb0c)
+#define SPM_PCM_DEBUG_CON (SPM_BASE + 0xb20)
+#define SPM_CA7_CPU0_IRQ_MASK (SPM_BASE + 0xb30)
+#define SPM_CA7_CPU1_IRQ_MASK (SPM_BASE + 0xb34)
+#define SPM_CA7_CPU2_IRQ_MASK (SPM_BASE + 0xb38)
+#define SPM_CA7_CPU3_IRQ_MASK (SPM_BASE + 0xb3c)
+#define SPM_CA15_CPU0_IRQ_MASK (SPM_BASE + 0xb40)
+#define SPM_CA15_CPU1_IRQ_MASK (SPM_BASE + 0xb44)
+#define SPM_CA15_CPU2_IRQ_MASK (SPM_BASE + 0xb48)
+#define SPM_CA15_CPU3_IRQ_MASK (SPM_BASE + 0xb4c)
+#define SPM_PCM_PASR_DPD_0 (SPM_BASE + 0xb60)
+#define SPM_PCM_PASR_DPD_1 (SPM_BASE + 0xb64)
+#define SPM_PCM_PASR_DPD_2 (SPM_BASE + 0xb68)
+#define SPM_PCM_PASR_DPD_3 (SPM_BASE + 0xb6c)
+#define SPM_SLEEP_CA7_WFI0_EN (SPM_BASE + 0xf00)
+#define SPM_SLEEP_CA7_WFI1_EN (SPM_BASE + 0xf04)
+#define SPM_SLEEP_CA7_WFI2_EN (SPM_BASE + 0xf08)
+#define SPM_SLEEP_CA7_WFI3_EN (SPM_BASE + 0xf0c)
+#define SPM_SLEEP_CA15_WFI0_EN (SPM_BASE + 0xf10)
+#define SPM_SLEEP_CA15_WFI1_EN (SPM_BASE + 0xf14)
+#define SPM_SLEEP_CA15_WFI2_EN (SPM_BASE + 0xf18)
+#define SPM_SLEEP_CA15_WFI3_EN (SPM_BASE + 0xf1c)
+
+#define SPM_PROJECT_CODE 0xb16
+
+#define SPM_REGWR_EN (1U << 0)
+#define SPM_REGWR_CFG_KEY (SPM_PROJECT_CODE << 16)
+
+#if 1
+/* PCM Flags store in PCM_RESERVE4(0xB18)*/
+#define SPM_CPU_PDN_DIS (1U << 0)
+#define SPM_INFRA_PDN_DIS (1U << 1)
+#define SPM_DDRPHY_PDN_DIS (1U << 2)
+#define SPM_VCORE_DVS_DIS (1U << 3)//mt6735 no use
+#define SPM_PASR_DIS (1U << 4)
+#define SPM_MD_VRF18_DIS (1U << 5)//mt6735
+#define SPM_CMD_LCM_EN (1U << 6)//mt6735
+#define SPM_MEMPLL_RESET (1U << 7)
+#define SPM_VCORE_DVFS_EN (1U << 8)//mt6735
+#define SPM_CPU_DVS_DIS (1U << 9)
+#define SPM_IFRA_MD_PDN_DIS (1U << 10)//mt6735
+#define SPM_EXT_VSEL_GPIO103 (1U << 11)//mt6735 no use
+#define SPM_DDR_HIGH_SPEED (1U << 12)//mt6735 no use
+#define SPM_SCREEN_OFF (1U << 13)//mt6735 no use
+#define SPM_MEMPLL_1PLL_3PLL_SEL (1U << 16)//mt6735 no use
+#define SPM_VCORE_DVS_POSITION (1U << 17)//mt6735 no use
+#define SPM_BUCK_SEL (1U << 18)//mt6735 no use
+#define SPM_DRAM_RANK1_ADDR_SEL0 (1U << 19)//0x60000000
+#define SPM_DRAM_RANK1_ADDR_SEL1 (1U << 20)//0x80000000
+#define SPM_DRAM_RANK1_ADDR_SEL2 (1U << 21)//0xc0000000
+#else
+#define SPM_CPU_PDN_DIS (1U << 0)
+#define SPM_INFRA_PDN_DIS (1U << 1)
+#define SPM_DDRPHY_PDN_DIS (1U << 2)
+#define SPM_VCORE_DVS_DIS (1U << 3)
+#define SPM_PASR_DIS (1U << 4)
+#define SPM_DPD_DIS (1U << 5)
+#define SPM_SODI_DIS (1U << 6)
+#define SPM_MEMPLL_RESET (1U << 7)
+#define SPM_MAINPLL_PDN_DIS (1U << 8)
+#define SPM_CPU_DVS_DIS (1U << 9)
+#define SPM_CPU_DORMANT (1U << 10)
+#define SPM_EXT_VSEL_GPIO103 (1U << 11)
+#define SPM_DDR_HIGH_SPEED (1U << 12)
+#define SPM_SCREEN_OFF (1U << 13)
+#endif
+
+/* Wakeup Source*/
+#if 1
+#define SPM_WAKE_SRC_LIST { \
+ SPM_WAKE_SRC(0, SPM_MERGE), /* PCM timer, TWAM or CPU */ \
+ SPM_WAKE_SRC(1, LTE_PTP), \
+ SPM_WAKE_SRC(2, KP), \
+ SPM_WAKE_SRC(3, WDT), \
+ SPM_WAKE_SRC(4, GPT), \
+ SPM_WAKE_SRC(5, EINT), \
+ SPM_WAKE_SRC(6, CONN_WDT), \
+ SPM_WAKE_SRC(7, CCIF0_MD), \
+ SPM_WAKE_SRC(8, CCIF1_MD), \
+ SPM_WAKE_SRC(9, LOW_BAT), \
+ SPM_WAKE_SRC(10, CONN2AP), \
+ SPM_WAKE_SRC(11, F26M_WAKE), \
+ SPM_WAKE_SRC(12, F26M_SLEEP), \
+ SPM_WAKE_SRC(13, PCM_WDT), \
+ SPM_WAKE_SRC(14, USB_CD), \
+ SPM_WAKE_SRC(15, USB_PDN), \
+ SPM_WAKE_SRC(16, LTE_WAKE), \
+ SPM_WAKE_SRC(17, LTE_SLEEP), \
+ SPM_WAKE_SRC(18, SEJ), \
+ SPM_WAKE_SRC(19, UART0), \
+ SPM_WAKE_SRC(20, AFE), \
+ SPM_WAKE_SRC(21, THERM), \
+ SPM_WAKE_SRC(22, CIRQ), \
+ SPM_WAKE_SRC(23, MD1_VRF18_WAKE), \
+ SPM_WAKE_SRC(24, SYSPWREQ), \
+ SPM_WAKE_SRC(25, MD_WDT), \
+ SPM_WAKE_SRC(26, C2K_WDT), \
+ SPM_WAKE_SRC(27, CLDMA_MD), \
+ SPM_WAKE_SRC(28, MD1_VRF18_SLEEP), \
+ SPM_WAKE_SRC(29, CPU_IRQ), \
+ SPM_WAKE_SRC(30, APSRC_WAKE), \
+ SPM_WAKE_SRC(31, APSRC_SLEEP) \
+}
+#else
+#define SPM_WAKE_SRC_LIST { \
+ SPM_WAKE_SRC(0, SPM_MERGE), /* PCM timer, TWAM or CPU */ \
+ SPM_WAKE_SRC(1, MD32_WDT), \
+ SPM_WAKE_SRC(2, KP), \
+ SPM_WAKE_SRC(3, WDT), \
+ SPM_WAKE_SRC(4, GPT), \
+ SPM_WAKE_SRC(5, CONN2AP), \
+ SPM_WAKE_SRC(6, EINT), \
+ SPM_WAKE_SRC(7, CONN_WDT), \
+ SPM_WAKE_SRC(8, CCIF0_MD), \
+ SPM_WAKE_SRC(9, LOW_BAT), \
+ SPM_WAKE_SRC(10, MD32_SPM), \
+ SPM_WAKE_SRC(11, F26M_WAKE), \
+ SPM_WAKE_SRC(12, F26M_SLEEP), \
+ SPM_WAKE_SRC(13, PCM_WDT), \
+ SPM_WAKE_SRC(14, USB_CD), \
+ SPM_WAKE_SRC(15, USB_PDN), \
+ SPM_WAKE_SRC(16, LTE_WAKE), \
+ SPM_WAKE_SRC(17, LTE_SLEEP), \
+ SPM_WAKE_SRC(18, CCIF1_MD), \
+ SPM_WAKE_SRC(19, UART0), \
+ SPM_WAKE_SRC(20, AFE), \
+ SPM_WAKE_SRC(21, THERM), \
+ SPM_WAKE_SRC(22, CIRQ), \
+ SPM_WAKE_SRC(23, MD2_WDT), \
+ SPM_WAKE_SRC(24, SYSPWREQ), \
+ SPM_WAKE_SRC(25, MD_WDT), \
+ SPM_WAKE_SRC(26, CLDMA_MD), \
+ SPM_WAKE_SRC(27, SEJ), \
+ SPM_WAKE_SRC(28, ALL_MD32), \
+ SPM_WAKE_SRC(29, CPU_IRQ), \
+ SPM_WAKE_SRC(30, APSRC_WAKE), \
+ SPM_WAKE_SRC(31, APSRC_SLEEP) \
+}
+#endif
+/* define WAKE_SRC_XXX */
+#undef SPM_WAKE_SRC
+#define SPM_WAKE_SRC(id, name) \
+ WAKE_SRC_##name = (1U << (id))
+enum SPM_WAKE_SRC_LIST;
+
+typedef enum {
+ WR_NONE = 0,
+ WR_UART_BUSY = 1,
+ WR_PCM_ASSERT = 2,
+ WR_PCM_TIMER = 3,
+ WR_WAKE_SRC = 4,
+ WR_UNKNOWN = 5,
+} wake_reason_t;
+
+struct twam_sig {
+ u32 sig0; /* signal 0: config or status */
+ u32 sig1; /* signal 1: config or status */
+ u32 sig2; /* signal 2: config or status */
+ u32 sig3; /* signal 3: config or status */
+};
+
+typedef void (*twam_handler_t)(struct twam_sig *twamsig);
+
+/* for power management init */
+extern int spm_module_init(void);
+
+/* for ANC in talking */
+extern void spm_mainpll_on_request(const char *drv_name);
+extern void spm_mainpll_on_unrequest(const char *drv_name);
+
+/* for TWAM in MET tool */
+extern void spm_twam_register_handler(twam_handler_t handler);
+extern void spm_twam_enable_monitor(struct twam_sig *twamsig, bool speed_mode);
+extern void spm_twam_disable_monitor(void);
+
+
+/**************************************
+ * Macro and Inline
+ **************************************/
+/*
+//XXX: only in kernel
+#define spm_read(addr) readl(IOMEM(addr))
+*/
+#define spm_read(addr) readl(addr)
+#define spm_write(addr, val) writel(val, addr)
+
+#define is_cpu_pdn(flags) (!((flags) & SPM_CPU_PDN_DIS))
+#define is_infra_pdn(flags) (!((flags) & SPM_INFRA_PDN_DIS))
+#define is_ddrphy_pdn(flags) (!((flags) & SPM_DDRPHY_PDN_DIS))
+#define is_dualvcore_pdn(flags) (!((flags) & SPM_DUALVCORE_PDN_DIS))
+
+#define get_high_cnt(sigsta) ((sigsta) & 0x3ff)
+#define get_high_percent(sigsta) (get_high_cnt(sigsta) * 100 / 1023)
+
+#endif
diff --git a/src/bsp/lk/platform/mt2635/include/platform/spm_mtcmos.h b/src/bsp/lk/platform/mt2635/include/platform/spm_mtcmos.h
new file mode 100644
index 0000000..a18cb0c
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/spm_mtcmos.h
@@ -0,0 +1,53 @@
+#ifndef _SPM_MTCMOS_
+#define _SPM_MTCMOS_
+
+#define STA_POWER_DOWN 0
+#define STA_POWER_ON 1
+
+/*
+ * 1. for CPU MTCMOS: CPU0, CPU1, CPU2, CPU3, DBG0, CPU4, CPU5, CPU6, CPU7, DBG1, CPUSYS1
+ * 2. call spm_mtcmos_cpu_lock/unlock() before/after any operations
+ */
+extern void spm_mtcmos_cpu_lock(unsigned long *flags);
+extern void spm_mtcmos_cpu_unlock(unsigned long *flags);
+
+extern int spm_mtcmos_ctrl_cpu(unsigned int cpu, int state, int chkWfiBeforePdn);
+extern int spm_mtcmos_ctrl_cpu0(int state, int chkWfiBeforePdn);
+extern int spm_mtcmos_ctrl_cpu1(int state, int chkWfiBeforePdn);
+extern int spm_mtcmos_ctrl_cpu2(int state, int chkWfiBeforePdn);
+extern int spm_mtcmos_ctrl_cpu3(int state, int chkWfiBeforePdn);
+extern int spm_mtcmos_ctrl_cpu4(int state, int chkWfiBeforePdn);
+extern int spm_mtcmos_ctrl_cpu5(int state, int chkWfiBeforePdn);
+extern int spm_mtcmos_ctrl_cpu6(int state, int chkWfiBeforePdn);
+extern int spm_mtcmos_ctrl_cpu7(int state, int chkWfiBeforePdn);
+
+extern int spm_mtcmos_ctrl_dbg0(int state);
+
+extern int spm_mtcmos_ctrl_cpusys0(int state, int chkWfiBeforePdn);
+extern int spm_mtcmos_ctrl_cpusys1(int state, int chkWfiBeforePdn);
+
+extern bool spm_cpusys0_can_power_down(void);
+extern bool spm_cpusys1_can_power_down(void);
+
+extern void spm_mtcmos_ctrl_cpusys1_init_1st_bring_up(int state);
+
+/*
+ * 1. for non-CPU MTCMOS: VDEC, VENC, ISP, DISP, MFG, INFRA, DDRPHY, MDSYS1, MDSYS2
+ * 2. call spm_mtcmos_noncpu_lock/unlock() before/after any operations
+ */
+extern int spm_mtcmos_ctrl_vdec(int state);
+extern int spm_mtcmos_ctrl_venc(int state);
+extern int spm_mtcmos_ctrl_isp(int state);
+extern int spm_mtcmos_ctrl_disp(int state);
+extern int spm_mtcmos_ctrl_mfg(int state);
+extern int spm_mtcmos_ctrl_mfg_ASYNC(int state);
+extern int spm_mtcmos_ctrl_mjc(int state);
+extern int spm_mtcmos_ctrl_aud(int state);
+
+extern int spm_mtcmos_ctrl_mdsys1(int state);
+extern int spm_mtcmos_ctrl_mdsys2(int state);
+extern int spm_mtcmos_ctrl_connsys(int state);
+
+extern int spm_topaxi_prot(int bit, int en);
+
+#endif
diff --git a/src/bsp/lk/platform/mt2635/include/platform/spm_mtcmos_internal.h b/src/bsp/lk/platform/mt2635/include/platform/spm_mtcmos_internal.h
new file mode 100644
index 0000000..6b9498b
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/spm_mtcmos_internal.h
@@ -0,0 +1,99 @@
+#ifndef _SPM_MTCMOS_INTERNAL_
+#define _SPM_MTCMOS_INTERNAL_
+
+
+/**************************************
+ * for CPU MTCMOS
+ **************************************/
+/*
+ * regiser bit difinition
+ */
+/* SPM_CA7_CPU0_PWR_CON */
+/* SPM_CA7_CPU1_PWR_CON */
+/* SPM_CA7_CPU2_PWR_CON */
+/* SPM_CA7_CPU3_PWR_CON */
+/* SPM_CA7_DBG_PWR_CON */
+/* SPM_CA7_CPUTOP_PWR_CON */
+/* SPM_CA15_CPU0_PWR_CON */
+/* SPM_CA15_CPU1_PWR_CON */
+/* SPM_CA15_CPU2_PWR_CON */
+/* SPM_CA15_CPU3_PWR_CON */
+/* SPM_CA15_CPUTOP_PWR_CON */
+#define SRAM_ISOINT_B (1U << 6)
+#define SRAM_CKISO (1U << 5)
+#define PWR_CLK_DIS (1U << 4)
+#define PWR_ON_2ND (1U << 3)
+#define PWR_ON (1U << 2)
+#define PWR_ISO (1U << 1)
+#define PWR_RST_B (1U << 0)
+
+/* SPM_CA7_CPU0_L1_PDN */
+/* SPM_CA7_CPU1_L1_PDN */
+/* SPM_CA7_CPU2_L1_PDN */
+/* SPM_CA7_CPU3_L1_PDN */
+#define L1_PDN_ACK (1U << 8)
+#define L1_PDN (1U << 0)
+/* SPM_CA7_CPUTOP_L2_PDN */
+#define L2_SRAM_PDN_ACK (1U << 8)
+#define L2_SRAM_PDN (1U << 0)
+/* SPM_CA7_CPUTOP_L2_SLEEP */
+#define L2_SRAM_SLEEP_B_ACK (1U << 8)
+#define L2_SRAM_SLEEP_B (1U << 0)
+
+/* SPM_CA15_L1_PWR_CON */
+#define CPU3_CA15_L1_PDN_ACK (1U << 19)
+#define CPU2_CA15_L1_PDN_ACK (1U << 18)
+#define CPU1_CA15_L1_PDN_ACK (1U << 17)
+#define CPU0_CA15_L1_PDN_ACK (1U << 16)
+#define CPU3_CA15_L1_PDN_ISO (1U << 7)
+#define CPU2_CA15_L1_PDN_ISO (1U << 6)
+#define CPU1_CA15_L1_PDN_ISO (1U << 5)
+#define CPU0_CA15_L1_PDN_ISO (1U << 4)
+#define CPU3_CA15_L1_PDN (1U << 3)
+#define CPU2_CA15_L1_PDN (1U << 2)
+#define CPU1_CA15_L1_PDN (1U << 1)
+#define CPU0_CA15_L1_PDN (1U << 0)
+/* SPM_CA15_L2_PWR_CON */
+#define CA15_L2_SLEEPB_ACK (1U << 4)
+#define CA15_L2_PDN_ACK (1U << 0)
+#define CA15_L2_SLEEPB_ISO (1U << 6)
+#define CA15_L2_SLEEPB (1U << 4)
+#define CA15_L2_PDN_ISO (1U << 2)
+#define CA15_L2_PDN (1U << 0)
+
+/* SPM_PWR_STATUS */
+/* SPM_PWR_STATUS_2ND */
+#define CA15_CPU3 (1U << 17)
+#define CA15_CPU2 (1U << 18)
+#define CA15_CPU1 (1U << 19)
+#define CA15_CPU0 (1U << 20)
+#define CA15_CPUTOP (1U << 16)
+//#define CA7_DBG (1U << 13)
+#define CA7_CPU3 (1U << 10)
+#define CA7_CPU2 (1U << 11)
+#define CA7_CPU1 (1U << 12)
+#define CA7_CPU0 (1U << 13)
+#define CA7_CPUTOP (1U << 9)
+
+/* SPM_SLEEP_TIMER_STA */
+#define CA15_CPUTOP_STANDBYWFI (1U << 25)
+#define CA7_CPUTOP_STANDBYWFI (1U << 24)
+#define CA15_CPU3_STANDBYWFI (1U << 23)
+#define CA15_CPU2_STANDBYWFI (1U << 22)
+#define CA15_CPU1_STANDBYWFI (1U << 21)
+#define CA15_CPU0_STANDBYWFI (1U << 20)
+#define CA7_CPU3_STANDBYWFI (1U << 19)
+#define CA7_CPU2_STANDBYWFI (1U << 18)
+#define CA7_CPU1_STANDBYWFI (1U << 17)
+#define CA7_CPU0_STANDBYWFI (1U << 16)
+
+/* SPM_SLEEP_DUAL_VCORE_PWR_CON */
+#define VCA15_PWR_ISO (1U << 13)
+#define VCA7_PWR_ISO (1U << 12)
+
+/* INFRA_TOPAXI_PROTECTEN */
+#define CA15_PDN_REQ (30)
+#define CA7_PDN_REQ (29)
+
+#endif /*_SPM_MTCMOS_INTERNAL_ */
+
diff --git a/src/bsp/lk/platform/mt2635/include/platform/sync_write.h b/src/bsp/lk/platform/mt2635/include/platform/sync_write.h
new file mode 100644
index 0000000..892d070
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/sync_write.h
@@ -0,0 +1,41 @@
+#ifndef _SYNC_WRITE_H
+#define _SYNC_WRITE_H
+
+#include <arch/arm64.h>
+
+#if 0
+#define reg_dummy_read(b) \
+ do { \
+ int c = *b; \
+ int c ++; \
+ } while (0)
+
+
+#define dsb() \
+ do { \
+ __asm__ __volatile__ ("dsb" : : : "memory"); \
+ } while (0)
+
+#define mt65xx_reg_sync_writel(v, a) \
+ do { \
+ *(volatile unsigned int *)(a) = (v); \
+ dsb(); \
+ } while (0)
+
+#define mt65xx_reg_sync_writew(v, a) \
+ do { \
+ *(volatile unsigned short *)(a) = (v); \
+ dsb(); \
+ } while (0)
+
+#define mt65xx_reg_sync_writeb(v, a) \
+ do { \
+ *(volatile unsigned char *)(a) = (v); \
+ dsb(); \
+ } while (0)
+#endif
+void mt_reg_sync_writel();
+void mt_reg_sync_writew();
+void mt_reg_sync_writeb();
+
+#endif
diff --git a/src/bsp/lk/platform/mt2635/include/platform/udc-common.h b/src/bsp/lk/platform/mt2635/include/platform/udc-common.h
new file mode 100644
index 0000000..be6fc62
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/udc-common.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+
+#define GET_STATUS 0
+#define CLEAR_FEATURE 1
+#define SET_FEATURE 3
+#define SET_ADDRESS 5
+#define GET_DESCRIPTOR 6
+#define SET_DESCRIPTOR 7
+#define GET_CONFIGURATION 8
+#define SET_CONFIGURATION 9
+#define GET_INTERFACE 10
+#define SET_INTERFACE 11
+#define SYNCH_FRAME 12
+#define SET_SEL 48
+
+#define TYPE_DEVICE 1
+#define TYPE_CONFIGURATION 2
+#define TYPE_STRING 3
+#define TYPE_INTERFACE 4
+#define TYPE_ENDPOINT 5
+#define TYPE_DEV_QUALIFIER 6
+#define TYPE_OTHER_SPEEDCONF 7
+#define TYPE_IFACE_POWER 8
+#define TYPE_OTG 9
+#define TYPE_DEBUG 10
+#define TYPE_IFACE_ASSOC 11
+#define TYPE_BOS 15
+#define TYPE_DEVICE_CAP 16
+#define TYPE_SS_EP_COMP 48
+
+#define DEVICE_READ 0x80
+#define DEVICE_WRITE 0x00
+#define INTERFACE_READ 0x81
+#define INTERFACE_WRITE 0x01
+#define ENDPOINT_READ 0x82
+#define ENDPOINT_WRITE 0x02
+
+#define TEST_SE0_NAK 0x0300
+#define TEST_PACKET 0x0400
+#define PORTSC_PTC (0xF << 16)
+#define PORTSC_PTC_SE0_NAK (0x03 << 16)
+#define PORTSC_PTC_TST_PKT (0x4 << 16)
+
+#define USB3_U1_ENABLE 48
+#define USB3_U2_ENABLE 49
+
+#define UDC_TYPE_BULK_IN 1
+#define UDC_TYPE_BULK_OUT 2
+
+struct setup_packet {
+ unsigned char type;
+ unsigned char request;
+ unsigned short value;
+ unsigned short index;
+ unsigned short length;
+} __attribute__ ((packed));
diff --git a/src/bsp/lk/platform/mt2635/include/platform/wdt.h b/src/bsp/lk/platform/mt2635/include/platform/wdt.h
new file mode 100644
index 0000000..e81f960
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/include/platform/wdt.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __MTK_WDT_H__
+#define __MTK_WDT_H__
+
+#define MTK_WDT_BASE RGU_BASE
+
+#define MTK_WDT_MODE (MTK_WDT_BASE+0x0000)
+#define MTK_WDT_LENGTH (MTK_WDT_BASE+0x0004)
+#define MTK_WDT_RESTART (MTK_WDT_BASE+0x0008)
+#define MTK_WDT_STATUS (MTK_WDT_BASE+0x000C)
+#define MTK_WDT_INTERVAL (MTK_WDT_BASE+0x0010)
+#define MTK_WDT_SWRST (MTK_WDT_BASE+0x0014)
+#define MTK_WDT_SWSYSRST (MTK_WDT_BASE+0x0018)
+#define MTK_WDT_NONRST_REG (MTK_WDT_BASE+0x0020)
+#define MTK_WDT_NONRST_REG2 (MTK_WDT_BASE+0x0024)
+#define MTK_WDT_REQ_MODE (MTK_WDT_BASE+0x0030)
+#define MTK_WDT_REQ_IRQ_EN (MTK_WDT_BASE+0x0034)
+#define MTK_WDT_DEBUG_CTL (MTK_WDT_BASE+0x0040)
+#define MTK_WDT_DEBUG_2_REG (MTK_WDT_BASE+0x0508)
+
+
+
+/*WDT_MODE*/
+#define MTK_WDT_MODE_KEYMASK (0xff00)
+#define MTK_WDT_MODE_KEY (0x22000000)
+
+#define MTK_WDT_MODE_DDR_RESERVE (0x0080)
+#define MTK_WDT_MODE_DUAL_MODE (0x0040)
+#define MTK_WDT_MODE_IN_DIS (0x0020) /* Reserved */
+#define MTK_WDT_MODE_AUTO_RESTART (0x0010) /* Reserved */
+#define MTK_WDT_MODE_IRQ (0x0008)
+#define MTK_WDT_MODE_EXTEN (0x0004)
+#define MTK_WDT_MODE_EXT_POL (0x0002)
+#define MTK_WDT_MODE_ENABLE (0x0001)
+
+
+/*WDT_LENGTH*/
+#define MTK_WDT_LENGTH_TIME_OUT (0xffe0)
+#define MTK_WDT_LENGTH_KEYMASK (0x001f)
+#define MTK_WDT_LENGTH_KEY (0x0008)
+
+/*WDT_RESTART*/
+#define MTK_WDT_RESTART_KEY (0x1971)
+
+/*WDT_STATUS*/
+#define MTK_WDT_STATUS_HWWDT_RST (0x80000000)
+#define MTK_WDT_STATUS_SWWDT_RST (0x40000000)
+#define MTK_WDT_STATUS_IRQWDT_RST (0x20000000)
+#define MTK_WDT_STATUS_DEBUGWDT_RST (0x00080000)
+#define MTK_WDT_STATUS_SPMWDT_RST (0x0002)
+#define MTK_WDT_STATUS_SPM_THERMAL_RST (0x0001)
+#define MTK_WDT_STATUS_THERMAL_DIRECT_RST (1<<18)
+#define MTK_WDT_STATUS_SECURITY_RST (1<<28)
+
+
+
+
+/*WDT_INTERVAL*/
+#define MTK_WDT_INTERVAL_MASK (0x0fff)
+
+/*WDT_SWRST*/
+#define MTK_WDT_SWRST_KEY (0x1209)
+
+/*WDT_SWSYSRST*/
+#define MTK_WDT_SWSYS_RST_PWRAP_SPI_CTL_RST (0x0800)
+#define MTK_WDT_SWSYS_RST_APMIXED_RST (0x0400)
+#define MTK_WDT_SWSYS_RST_MD_LITE_RST (0x0200)
+#define MTK_WDT_SWSYS_RST_INFRA_AO_RST (0x0100)
+#define MTK_WDT_SWSYS_RST_MD_RST (0x0080)
+#define MTK_WDT_SWSYS_RST_DDRPHY_RST (0x0040)
+#define MTK_WDT_SWSYS_RST_IMG_RST (0x0020)
+#define MTK_WDT_SWSYS_RST_VDEC_RST (0x0010)
+#define MTK_WDT_SWSYS_RST_VENC_RST (0x0008)
+#define MTK_WDT_SWSYS_RST_MFG_RST (0x0004)
+#define MTK_WDT_SWSYS_RST_DISP_RST (0x0002)
+#define MTK_WDT_SWSYS_RST_INFRA_RST (0x0001)
+
+
+//#define MTK_WDT_SWSYS_RST_KEY (0x1500)
+#define MTK_WDT_SWSYS_RST_KEY (0x88000000)
+#define MTK_WDT_REQ_IRQ_KEY (0x44000000)
+
+/* WDT_NONRST_REG */
+#define MTK_WDT_NONRST_DL (0x00008000)
+
+//MTK_WDT_DEBUG_CTL
+#define MTK_DEBUG_CTL_KEY (0x59000000)
+#define MTK_RG_DDR_PROTECT_EN (0x00001)
+#define MTK_RG_MCU_LATH_EN (0x00002)
+#define MTK_RG_DRAMC_SREF (0x00100)
+#define MTK_RG_DRAMC_ISO (0x00200)
+#define MTK_RG_CONF_ISO (0x00400)
+#define MTK_DDR_RESERVE_RTA (0x10000) //sta
+#define MTK_DDR_SREF_STA (0x20000) //sta
+
+
+/* Reboot reason */
+#define RE_BOOT_REASON_UNKNOW (0x00)
+#define RE_BOOT_BY_WDT_HW (0x01)
+#define RE_BOOT_BY_WDT_SW (0x02)
+#define RE_BOOT_WITH_INTTERUPT (0x04)
+#define RE_BOOT_BY_SPM_THERMAL (0x08)
+#define RE_BOOT_BY_SPM (0x10)
+#define RE_BOOT_BY_THERMAL_DIRECT (0x20)
+#define RE_BOOT_BY_DEBUG (0x40)
+#define RE_BOOT_BY_SECURITY (0x80)
+
+
+
+#define RE_BOOT_ABNORMAL (0xF0)
+
+/* Reboot from which stage */
+#define RE_BOOT_FROM_UNKNOW (0x00)
+#define RE_BOOT_FROM_PRE_LOADER (0x01)
+#define RE_BOOT_FROM_U_BOOT (0x02)
+#define RE_BOOT_FROM_KERNEL (0x03)
+#define RE_BOOT_FROM_POWER_ON (0x04)
+
+#define WDT_NORMAL_REBOOT (0x01)
+#define WDT_BY_PASS_PWK_REBOOT (0x02)
+#define WDT_NOT_WDT_REBOOT (0x00)
+
+typedef enum wd_swsys_reset_type {
+ WD_MD_RST,
+} WD_SYS_RST_TYPE;
+
+extern void mtk_wdt_init(void);
+//extern void mtk_wdt_reset(void);
+//extern unsigned int mtk_wdt_check_status(void);
+//extern unsigned int mtk_wdt_get_trig_reboot_stage(void);
+extern BOOL mtk_is_rgu_trigger_reset(void);
+extern void mtk_arch_reset(char mode);
+extern int mtk_wdt_boot_check(void);
+int rgu_dram_reserved(int enable);
+int rgu_is_reserve_ddr_enabled(void);
+
+int rgu_is_dram_slf(void);
+
+void rgu_release_rg_dramc_conf_iso(void);
+
+void rgu_release_rg_dramc_iso(void);
+
+void rgu_release_rg_dramc_sref(void);
+int rgu_is_reserve_ddr_mode_success(void);
+void rgu_swsys_reset(WD_SYS_RST_TYPE reset_type);
+
+
+extern unsigned g_rgu_status;
+
+#endif /*__MTK_WDT_H__*/
diff --git a/src/bsp/lk/platform/mt2635/interrupts.c b/src/bsp/lk/platform/mt2635/interrupts.c
new file mode 100644
index 0000000..a9aeacf
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/interrupts.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#if ARCH_ARM
+#include <arch/arm.h>
+#endif
+#if ARCH_ARM64
+#include <arch/arm64.h>
+#endif
+#include <reg.h>
+#include <debug.h>
+#include <kernel/thread.h>
+#include <platform/mt_irq.h>
+#include <platform/interrupts.h>
+#include <platform/mt_reg_base.h>
+
+#define write_r(a, v) writel(v, a) /* need to fix it */
+
+/* set for mt_gic */
+void mt_irq_set_polarity(unsigned int irq, unsigned int polarity)
+{
+ unsigned int offset;
+ unsigned int reg_index;
+ unsigned int value;
+
+ /* peripheral device's IRQ line is using GIC's SPI, and line ID >= GIC_PRIVATE_SIGNALS */
+ if (irq < GIC_PRIVATE_SIGNALS) {
+ dprintf(SPEW, "The Interrupt ID < 32, please check!\n");
+ return;
+ }
+
+ offset = (irq - GIC_PRIVATE_SIGNALS) & 0x1F;
+ reg_index = (irq - GIC_PRIVATE_SIGNALS) >> 5;
+ if (polarity == 0) {
+ value = readl(INT_POL_CTL0 + (reg_index * 4));
+ value |= (1 << offset); /* always invert the incoming IRQ's polarity */
+ write_r((INT_POL_CTL0 + (reg_index * 4)), value);
+ } else {
+ value = readl(INT_POL_CTL0 + (reg_index * 4));
+ value &= ~(0x1 << offset);
+ write_r(INT_POL_CTL0 + (reg_index * 4), value);
+
+ }
+}
+
+/* set for arm gic */
+void mt_irq_set_sens(unsigned int irq, unsigned int sens)
+{
+ unsigned int config;
+
+ if (sens == EDGE_SENSITIVE) {
+ config = readl(GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4);
+ config |= (0x2 << (irq % 16) * 2);
+ write_r(GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4, config);
+ } else {
+ config = readl(GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4);
+ config &= ~(0x2 << (irq % 16) * 2);
+ write_r( GIC_DIST_BASE + GIC_DIST_CONFIG + (irq / 16) * 4, config);
+ }
+ DSB;
+}
diff --git a/src/bsp/lk/platform/mt2635/platform.c b/src/bsp/lk/platform/mt2635/platform.c
new file mode 100644
index 0000000..265625e
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/platform.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <arch.h>
+#include <arch/arm64/mmu.h>
+#include <arch/ops.h>
+#include <assert.h>
+#include <debug.h>
+#include <dev/interrupt/arm_gic.h>
+#include <dev/timer/arm_generic.h>
+#include <dev/uart.h>
+#include <err.h>
+#include <kernel/vm.h>
+#include <platform.h>
+#include <platform/emi.h>
+#include <platform/memory.h>
+#include <platform/mmc_core.h>
+#include <platform/mt2635.h>
+#include <platform/mtk_timer.h>
+#include <platform/mtk_wdt.h>
+#include <platform/pll.h>
+#include <platform/pmic.h>
+#include <lib/bio.h>
+#include <lib/mempool.h>
+
+#if WITH_KERNEL_VM
+#define L2C_MAPPING_IDX 0
+#define PERIPHERAL_MAPPING_IDX 1
+#define SRAM_MAPPING_IDX 2
+#define DRAM_MAPPING_IDX 3
+
+/* initial memory mappings. parsed by start.S */
+struct mmu_initial_mapping mmu_initial_mappings[] = {
+ {
+ .phys = MEMORY_BASE_PHYS,
+ .virt = MEMORY_BASE_VIRT,
+ .size = MEMORY_APERTURE_SIZE,
+ .flags = 0,
+ .name = "l2c"
+ },
+ {
+ .phys = PERIPHERAL_BASE_PHYS,
+ .virt = PERIPHERAL_BASE_VIRT,
+ .size = PERIPHERAL_BASE_SIZE,
+ .flags = MMU_INITIAL_MAPPING_FLAG_DEVICE,
+ .name = "peripherals"
+ },
+ /* reserved for internal sram */
+ { 0 },
+ /* reserved for dram */
+ { 0 },
+ /* null entry to terminate the list */
+ { 0 }
+};
+
+static pmm_arena_t arena = {
+ .name = "sdram",
+ .base = SRAM_BASE_PHYS,
+ .size = SRAM_BASE_SIZE,
+ .flags = PMM_ARENA_FLAG_KMAP,
+};
+
+/* only enable el1 dcache */
+static void dcache_enable(void)
+{
+ uint32_t sctlr;
+
+ asm volatile("mrs %0, sctlr_el1" : "=r" (sctlr) : : "cc");
+ asm volatile("msr sctlr_el1, %0" : : "r" (sctlr | (1 << 2)) : "cc");
+ asm volatile("isb");
+}
+
+#endif /* WITH_KERNEL_VM */
+
+void platform_early_init(void)
+{
+ uart_init_early();
+
+ /* initialize the interrupt controller */
+ arm_gic_init();
+
+ /* initialize the timer block */
+ mtk_timer_init();
+
+ mtk_wdt_init();
+ arm_generic_timer_init(ARM_GENERIC_TIMER_PHYSICAL_INT, 13000000);
+
+#if WITH_KERNEL_VM
+ arch_disable_cache(DCACHE);
+#endif
+ mt_pll_init();
+
+ mt_pmic_init();
+
+ /*
+ * mt_init_mempll() and mt_pll_post_init() should be invoked
+ * after pmic_ini
+ */
+ mt_init_mempll();
+ mt_pll_post_init();
+ /* dram calibration, mapping and test */
+ mt_mem_init();
+
+#if WITH_KERNEL_VM
+ dcache_enable();
+
+ /* add DRAM to mmu_initial_mappings for physical-to-virtual translation */
+ mmu_initial_mappings[DRAM_MAPPING_IDX].phys = DRAM_BASE_PHY;
+ mmu_initial_mappings[DRAM_MAPPING_IDX].virt = DRAM_BASE_VIRT;
+ mmu_initial_mappings[DRAM_MAPPING_IDX].size = get_dram_size();
+ mmu_initial_mappings[DRAM_MAPPING_IDX].flags = 0;
+ mmu_initial_mappings[DRAM_MAPPING_IDX].name = "dram";
+
+ /* mapping internel sram to cacheable memory */
+ arch_mmu_map(SRAM_BASE_VIRT, SRAM_BASE_PHYS, SRAM_BASE_SIZE >> PAGE_SIZE_SHIFT, 0);
+ /* add intrenal sram to mmu_initial_mappings for heap */
+ mmu_initial_mappings[SRAM_MAPPING_IDX].phys = SRAM_BASE_PHYS;
+ mmu_initial_mappings[SRAM_MAPPING_IDX].virt = SRAM_BASE_VIRT;
+ mmu_initial_mappings[SRAM_MAPPING_IDX].size = SRAM_BASE_SIZE;
+ mmu_initial_mappings[SRAM_MAPPING_IDX].flags = 0;
+ mmu_initial_mappings[SRAM_MAPPING_IDX].name = "sram";
+
+ pmm_add_arena(&arena);
+#endif
+}
+
+void platform_init(void)
+{
+ int ret;
+ bdev_t *rpdev;
+ unsigned int *rpmb_size;
+
+ ret = mempool_init((void *)CACHED_MEMPOOL_ADDR, CACHED_MEMPOOL_SIZE,
+ MEMPOOL_CACHE);
+ if (ret != NO_ERROR)
+ platform_halt(HALT_ACTION_REBOOT, HALT_REASON_SW_PANIC);
+
+ emmc_init();
+
+ rpdev = bio_open("mmc0rpmb");
+ if (rpdev != NULL) {
+ rpmb_size = (unsigned int *)(readl(SRAMROM_BASE + 0x3c) + 0x8fc + KERNEL_ASPACE_BASE);
+ *rpmb_size = rpdev->total_size;
+ bio_close(rpdev);
+ }
+}
diff --git a/src/bsp/lk/platform/mt2635/rules.mk b/src/bsp/lk/platform/mt2635/rules.mk
new file mode 100644
index 0000000..78e91bc
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/rules.mk
@@ -0,0 +1,55 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+COMMON_PLAT := $(LOCAL_DIR)/../mediatek/common
+
+ARCH ?= arm64
+ARM_CPU ?= cortex-a53
+WITH_SMP ?= 0
+WITH_KERNEL_VM ?= 1
+
+LK_HEAP_IMPLEMENTATION ?= miniheap
+
+GLOBAL_INCLUDES += -I$(LK_TOP_DIR)/include \
+
+MODULE_SRCS += \
+ $(COMMON_PLAT)/boot_mode.c \
+ $(LOCAL_DIR)/platform.c \
+ $(LOCAL_DIR)/debug.c \
+ $(LOCAL_DIR)/interrupts.c \
+ $(LOCAL_DIR)/timer.c \
+
+ifeq ($(WITH_KERNEL_VM),1)
+KERNEL_ASPACE_BASE ?= 0xffff000000200000
+KERNEL_ASPACE_SIZE ?= 0x00000000f0000000
+MMU_IDENT_SIZE_SHIFT ?= 32
+endif
+MEMBASE ?= 0x200000
+KERNEL_LOAD_OFFSET ?= 0x1000
+MEMSIZE ?= 0x00040000 # 256K
+MACH_TYPE := 2635
+
+MODULE_DEPS += \
+ dev/interrupt/arm_gic \
+ dev/timer/arm_generic \
+ lib/bio \
+ lib/partition \
+ lib/fdt \
+ lib/mempool \
+
+ifeq ($(WITH_KERNEL_VM),1)
+GLOBAL_DEFINES += MMU_IDENT_SIZE_SHIFT=$(MMU_IDENT_SIZE_SHIFT)
+endif
+
+GLOBAL_DEFINES += \
+ MEMBASE=$(MEMBASE) \
+ MEMSIZE=$(MEMSIZE) \
+ RAMBASE=$(RAMBASE) \
+ MACH_TYPE=$(MACH_TYPE) \
+ PLATFORM_SUPPORTS_PANIC_SHELL=1 \
+ WITH_NO_FP=1 \
+
+LINKER_SCRIPT += \
+ $(BUILDDIR)/system-onesegment.ld
+
+include make/module.mk $(LOCAL_DIR)/drivers/rules.mk
diff --git a/src/bsp/lk/platform/mt2635/timer.c b/src/bsp/lk/platform/mt2635/timer.c
new file mode 100644
index 0000000..8e1bcd1
--- /dev/null
+++ b/src/bsp/lk/platform/mt2635/timer.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <platform/mt2635.h>
+#include <platform/mtk_timer.h>
+#include <platform/mt_reg_base.h>
+
+#define CPUXGPT_BASE IO_PHYS + 0x200000
+#define INDEX_BASE ((volatile unsigned int *)(CPUXGPT_BASE+0x0674))
+#define CTL_BASE ((volatile unsigned int *)(CPUXGPT_BASE+0x0670))
+
+void set_cntfrq(unsigned long freq)
+{
+#if ARCH_ARM64
+
+#else
+ __asm__ volatile("mcr p15, 0, %0, c14, c0, 0\n" :: "r"(freq));
+#endif
+}
+
+
+void cpuxgpt_enable(void)
+{
+ *CTL_BASE = (0x201);
+ *INDEX_BASE = (0);
+}
+
+
+/* delay msec mseconds */
+extern lk_time_t current_time(void);
+void mdelay(unsigned long msec)
+{
+ lk_time_t start = current_time();
+
+ while (start + msec > current_time());
+}
+
+/* delay usec useconds */
+extern lk_bigtime_t current_time_hires(void);
+void udelay(unsigned long usec)
+{
+ lk_bigtime_t start = current_time_hires();
+
+ while (start + usec > current_time_hires());
+}
+
+/*
+ * busy wait
+ */
+void gpt_busy_wait_us(u32 timeout_us)
+{
+ udelay(timeout_us);
+}
+
+void gpt_busy_wait_ms(u32 timeout_ms)
+{
+ mdelay(timeout_ms);
+}
+
+void mtk_timer_init (void)
+{
+ cpuxgpt_enable();
+}