diff options
Diffstat (limited to 'plat/hikey/drivers')
-rw-r--r-- | plat/hikey/drivers/dw_mmc.c | 754 | ||||
-rw-r--r-- | plat/hikey/drivers/hi6553.c | 46 | ||||
-rw-r--r-- | plat/hikey/drivers/hisi_dvfs.c | 808 | ||||
-rw-r--r-- | plat/hikey/drivers/hisi_ipc.c | 241 | ||||
-rw-r--r-- | plat/hikey/drivers/hisi_mcu.c | 247 | ||||
-rw-r--r-- | plat/hikey/drivers/hisi_pwrc.c | 111 | ||||
-rw-r--r-- | plat/hikey/drivers/hisi_pwrc_sram.S | 87 | ||||
-rw-r--r-- | plat/hikey/drivers/sp804_timer.c | 120 |
8 files changed, 0 insertions, 2414 deletions
diff --git a/plat/hikey/drivers/dw_mmc.c b/plat/hikey/drivers/dw_mmc.c deleted file mode 100644 index 5eecd0c5..00000000 --- a/plat/hikey/drivers/dw_mmc.c +++ /dev/null @@ -1,754 +0,0 @@ -/* - * Copyright (c) 2014-2015, Linaro Ltd. All rights reserved. - * Copyright (c) 2014-2015, Hisilicon Ltd. All rights reserved. - * - * 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. - * - * Neither the name of ARM nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific - * prior written permission. - * - * 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 HOLDER 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 <console.h> -#include <debug.h> -#include <errno.h> -#include <mmio.h> -#include <string.h> -#include <sp804_timer.h> -#include <dw_mmc.h> -#include <partitions.h> -#include <platform_def.h> -#include <hi6220.h> -#include <hi6553.h> - -#define MMC_PLL 100000000 - -#define IDMAC_DES0_DIC (1 << 1) -#define IDMAC_DES0_LD (1 << 2) -#define IDMAC_DES0_FS (1 << 3) -#define IDMAC_DES0_CH (1 << 4) -#define IDMAC_DES0_ER (1 << 5) -#define IDMAC_DES0_CES (1 << 30) -#define IDMAC_DES0_OWN (1 << 31) - -#define IDMAC_DES1_BS1(x) ((x) & 0x1fff) -#define IDMAC_DES2_BS2(x) (((x) & 0x1fff) << 13) - -struct idmac_desc { - unsigned int des0; - unsigned int des1; - unsigned int des2; - unsigned int des3; -}; - -static inline int mmc_state(unsigned int data) -{ - return ((data & MMC_STATUS_CURRENT_STATE_MASK) >> - MMC_STATUS_CURRENT_STATE_SHIFT); -} - -static inline int wait_data_ready(void) -{ - unsigned int data; - - while (1) { - data = mmio_read_32(MMC0_RINTSTS); - if (data & (MMC_INT_DCRC | MMC_INT_DRT | MMC_INT_SBE | - MMC_INT_EBE)) { - NOTICE("unwanted interrupts:0x%x\n", data); - return -EINVAL; - } - if (data & MMC_INT_DTO) - break; - } - /* clear interrupts */ - mmio_write_32(MMC0_RINTSTS, ~0); - return 0; -} - -static int update_mmc0_clock(void) -{ - unsigned int data; - - /* CMD_UPDATE_CLK */ - data = BIT_CMD_WAIT_PRVDATA_COMPLETE | BIT_CMD_UPDATE_CLOCK_ONLY | - BIT_CMD_START; - mmio_write_32(MMC0_CMD, data); - while (1) { - data = mmio_read_32(MMC0_CMD); - if (!(data & CMD_START_BIT)) - break; - data = mmio_read_32(MMC0_RINTSTS); - if (data & MMC_INT_HLE) { - NOTICE("fail to update mmc clock frequency\n"); - return -EINVAL; - } - } - return 0; -} - -static int set_mmc0_clock(int rate) -{ - int ret, divider, found = 0; - unsigned int data; - - for (divider = 1; divider < 256; divider++) { - if ((MMC_PLL / (2 * divider)) <= rate) { - found = 1; - break; - } - } - if (!found) - return -EINVAL; - - /* wait until mmc is idle */ - do { - data = mmio_read_32(MMC0_STATUS); - } while (data & MMC_STS_DATA_BUSY); - - /* Disable mmc clock first */ - mmio_write_32(MMC0_CLKENA, 0); - do { - ret = update_mmc0_clock(); - } while (ret); - - /* enable mmc clock */ - do { - mmio_write_32(MMC0_CLKENA, 1); - mmio_write_32(MMC0_CLKSRC, 0); - mmio_write_32(MMC0_CLKDIV, divider); - ret = update_mmc0_clock(); - } while (ret); - return 0; -} - -static void set_mmc0_io(void) -{ - mmio_write_32(MMC0_CTYPE, MMC_8BIT_MODE); - mmio_write_32(MMC0_TMOUT, ~0); /* maxium timeout value */ - mmio_write_32(MMC0_DEBNCE, 0x00ffffff); - mmio_write_32(MMC0_BLKSIZ, MMC_BLOCK_SIZE); - mmio_write_32(MMC0_BYTCNT, 256 * 1024); -} - -static int mmc0_send_cmd(unsigned int cmd, unsigned int arg, unsigned int *buf) -{ - unsigned int data, err_mask; - - if (!buf) { - NOTICE("buf is invalid\n"); - return -EFAULT; - } - - mmio_write_32(MMC0_CMDARG, arg); - - /* clear interrupts */ - mmio_write_32(MMC0_RINTSTS, ~0); - - switch (cmd) { - case 0: - data = BIT_CMD_SEND_INIT; - break; - case 1: - data = BIT_CMD_RESPONSE_EXPECT; - break; - case 2: - data = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_LONG_RESPONSE | - BIT_CMD_CHECK_RESPONSE_CRC | BIT_CMD_SEND_INIT; - break; - case 3: - data = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | - BIT_CMD_SEND_INIT; - break; - case 8: - data = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | - BIT_CMD_DATA_EXPECTED | BIT_CMD_READ | - BIT_CMD_WAIT_PRVDATA_COMPLETE; - break; - case 9: - data = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | - BIT_CMD_LONG_RESPONSE; - break; - case 12: - data = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | - BIT_CMD_STOP_ABORT_CMD; - break; - case 17: - case 18: - data = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | - BIT_CMD_DATA_EXPECTED | BIT_CMD_READ | - BIT_CMD_WAIT_PRVDATA_COMPLETE; - break; - case 24: - case 25: - data = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | - BIT_CMD_DATA_EXPECTED | BIT_CMD_WRITE | - BIT_CMD_WAIT_PRVDATA_COMPLETE; - break; - case 30: - data = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | - BIT_CMD_DATA_EXPECTED; - break; - case 7: - if (arg) - data = BIT_CMD_RESPONSE_EXPECT | - BIT_CMD_CHECK_RESPONSE_CRC; - else - data = 0; - break; - default: - data = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC; - break; - } - data |= (cmd & 0x3f) | BIT_CMD_USE_HOLD_REG | BIT_CMD_START; - mmio_write_32(MMC0_CMD, data); - err_mask = MMC_INT_EBE | MMC_INT_HLE | MMC_INT_RTO | MMC_INT_RCRC | - MMC_INT_RE; - do { - data = mmio_read_32(MMC0_RINTSTS); - if (data & err_mask) { - NOTICE("mmc: error status 0x%x\n", data); - return -EIO; - } - } while (!(data & MMC_INT_CMD_DONE)); - - buf[0] = mmio_read_32(MMC0_RESP0); - if ((cmd == 2) || (cmd == 9)) { - buf[1] = mmio_read_32(MMC0_RESP1); - buf[2] = mmio_read_32(MMC0_RESP2); - buf[3] = mmio_read_32(MMC0_RESP3); - } - return 0; -} - -/* Only print error message if it meets failure? */ -static void mmc0_check_tran_mode(void) -{ - unsigned int buf[4]; - int ret; - - mmio_write_32(MMC0_RINTSTS, ~0); - - while (1) { - ret = mmc0_send_cmd(13, EMMC_FIX_RCA << 16, buf); - if (ret) { - NOTICE("failed on command 13\n"); - return; - } - if (((buf[0] >> 9) & 0xf) == 4) - return; - } -} - -static int mmc0_update_ext_csd(int index, int value) -{ - unsigned int arg, data, buf[4]; - int ret; - - arg = 3 << 24; - arg |= (index & 0xff) << 16; - arg |= (value & 0xff) << 8; - arg |= 1; - memset(buf, 0, 4 * sizeof(buf[0])); - - ret = mmc0_send_cmd(6, arg, buf); - if (ret) { - NOTICE("failed to send command 6\n"); - return ret; - } - - /* wait busy de-assert */ - while (1) { - data = mmio_read_32(MMC0_STATUS); - if (!(data & MMC_STS_DATA_BUSY)) - break; - } - - do { - ret = mmc0_send_cmd(13, EMMC_FIX_RCA << 16, buf); - if (ret) { - NOTICE("failed to send command 13\n"); - return ret; - } - - if (buf[0] & MMC_STATUS_SWITCH_ERROR) { - NOTICE("maybe switch mmc mode error\n"); - return -1; - } - } while (mmc_state(buf[0]) == MMC_STATE_PRG); - - return 0; -} - -#define EXTCSD_BUS_WIDTH 183 - -static int mmc0_set_clock_and_width(int rate, int width) -{ - int ret; - - switch (width) { - case 0: - mmio_write_32(MMC0_CTYPE, 0); - ret = mmc0_update_ext_csd(EXTCSD_BUS_WIDTH, 0); - break; - case 8: - mmio_write_32(MMC0_CTYPE, 1 << 16); - ret = mmc0_update_ext_csd(EXTCSD_BUS_WIDTH, 2 + 4); - mmio_write_32(MMC0_UHSREG, 1 << 16); - break; - default: - NOTICE("wrong bus width:%d\n", width); - return -EINVAL; - } - if (ret) { - NOTICE("return failure on %s, %d\n", __func__, __LINE__); - return ret; - } - - set_mmc0_clock(rate); - return 0; -} - -static int manu_id; - -#define EXTCSD_HS_TIMING 185 - -#ifdef EMMC_READ_EXT_CSD -static int mmc0_read_ext_csd(unsigned int dst_start); -#endif -static int enum_mmc0_card(void) -{ - unsigned int buf[4], cid[4]; - int ret = 0, i, version; - - /* CMD0: reset to IDLE */ - ret = mmc0_send_cmd(0, 0, buf); - if (ret) { - NOTICE("failed to send IDLE command\n"); - return ret; - } - - while (1) { - udelay(100); - /* CMD1: READY */ - ret = mmc0_send_cmd(1, 0x40ff8000, buf); - if (ret) { - NOTICE("failed to send READY command\n"); - return ret; - } - if (buf[0] & 0x80000000) - break; - } - - /* CMD2: IDENT */ - ret = mmc0_send_cmd(2, 0, buf); - if (ret) { - NOTICE("failed to send IDENT command\n"); - return ret; - } - VERBOSE("manuid:"); - for (i = 0; i < 4; i++) { - cid[i] = buf[i]; - VERBOSE(" 0x%x", cid[i]); - } - VERBOSE("\n"); - - /* CMD3: STBY */ - ret = mmc0_send_cmd(3, EMMC_FIX_RCA << 16, buf); - if (ret) { - NOTICE("failed to send STBY command\n"); - return ret; - } - - /* CMD9: get CSD */ - ret = mmc0_send_cmd(9, EMMC_FIX_RCA << 16, buf); - if (ret) { - NOTICE("failed to get CSD\n"); - return ret; - } - VERBOSE("CSD: %x-%x-%x-%x\n", buf[0], buf[1], buf[2], buf[3]); - version = (buf[3] >> 26) & 0xf; - switch (version) { - case 0: /* MMC v1.0-v1.2 */ - case 1: /* MMC v1.4 */ - manu_id = (cid[3] >> 8) & 0xffffff; - break; - case 2: /* MMC v2.0-v2.2 */ - case 3: /* MMC v3.1-v3.3 */ - case 4: /* MMC v4 */ - manu_id = (cid[3] >> 24) & 0xff; - break; - default: - WARN("wrong mmc version (%d) is specified.\n", version); - break; - } - - VERBOSE("mmc version:%d\n", version); - /* CMD7: TRAN */ - ret = mmc0_send_cmd(7, EMMC_FIX_RCA << 16, buf); - if (ret) { - NOTICE("failed to send TRAN command\n"); - return ret; - } - mmc0_check_tran_mode(); - - mmc0_set_clock_and_width(400000, 0); -#ifdef EMMC_READ_EXT_CSD - mmc0_read_ext_csd(0x50000); -#endif - ret = mmc0_update_ext_csd(EXTCSD_HS_TIMING, 1); - if (ret) { - NOTICE("alter HS mode fail\n"); - } - - ret = mmc0_set_clock_and_width(50000000, 8); - return ret; -} - -static int enable_mmc0(void) -{ - unsigned int data; - - /* reset mmc0 */ - data = MMC_CTRL_RESET | MMC_FIFO_RESET | MMC_DMA_RESET; - mmio_write_32(MMC0_CTRL, data); - /* wait until reset operation finished */ - do { - data = mmio_read_32(MMC0_CTRL); - } while (data); - - data = MMC_INT_EN | MMC_DMA_EN; - mmio_write_32(MMC0_CTRL, data); - - mmio_write_32(MMC0_INTMASK, 0x0); - mmio_write_32(MMC0_RINTSTS, ~0); - mmio_write_32(MMC0_IDINTEN, ~0); - mmio_write_32(MMC0_IDSTS, ~0); - - mmio_write_32(MMC0_BLKSIZ, MMC_BLOCK_SIZE); - mmio_write_32(MMC0_BMOD, MMC_IDMAC_SWRESET); - do { - data = mmio_read_32(MMC0_BMOD); - } while (data & MMC_IDMAC_SWRESET); - - data |= MMC_IDMAC_ENABLE | MMC_IDMAC_FB; - mmio_write_32(MMC0_BMOD, data); - - data = MMC_DMA_BURST_SIZE(2) | MMC_FIFO_TWMARK(8) | MMC_FIFO_RWMARK(7); - mmio_write_32(MMC0_FIFOTH, data); - data = MMC_CARD_RD_THR(512) | MMC_CARD_RD_THR_EN; - mmio_write_32(MMC0_CARDTHRCTL, data); - - udelay(100); - set_mmc0_clock(378000); - udelay(100); - - set_mmc0_io(); - return 0; -} - -#define MMC_BLOCK_SIZE 512 -#define MMC_DMA_MAX_BUFFER_SIZE (512 * 8) - -#ifdef EMMC_READ_EXT_CSD -static int mmc0_read_ext_csd(unsigned int dst_start) -{ - unsigned int blk_cnt, bytes, desc_num, buf[4], data; - struct idmac_desc *desc = NULL; - int i, ret, last_idx; - uintptr_t src_addr, dst_addr = dst_start; - - blk_cnt = 1; - bytes = blk_cnt * MMC_BLOCK_SIZE; - memset((void *)MMC_DATA_BASE, 0, bytes); - - mmio_write_32(MMC0_BYTCNT, bytes); - - mmio_write_32(MMC0_RINTSTS, ~0); - - desc_num = (bytes + MMC_DMA_MAX_BUFFER_SIZE - 1) / - MMC_DMA_MAX_BUFFER_SIZE; - - desc = (struct idmac_desc *)MMC_DESC_BASE; - - for (i = 0; i < desc_num; i++) { - (desc + i)->des0 = IDMAC_DES0_OWN | IDMAC_DES0_CH | - IDMAC_DES0_DIC; - (desc + i)->des1 = IDMAC_DES1_BS1(MMC_DMA_MAX_BUFFER_SIZE); - /* buffer address */ - (desc + i)->des2 = MMC_DATA_BASE + MMC_DMA_MAX_BUFFER_SIZE * i; - /* next descriptor address */ - (desc + i)->des3 = MMC_DESC_BASE + - (sizeof(struct idmac_desc) * (i + 1)); - } - /* first descriptor */ - desc->des0 |= IDMAC_DES0_FS; - /* last descriptor */ - last_idx = desc_num - 1; - (desc + last_idx)->des0 |= IDMAC_DES0_LD; - (desc + last_idx)->des0 &= ~(IDMAC_DES0_DIC | IDMAC_DES0_CH); - (desc + last_idx)->des1 = IDMAC_DES1_BS1(bytes - (last_idx * - MMC_DMA_MAX_BUFFER_SIZE)); - /* set next descriptor address as 0 */ - (desc + last_idx)->des3 = 0; - - mmio_write_32(MMC0_DBADDR, MMC_DESC_BASE); - - /* read extended CSD */ - ret = mmc0_send_cmd(8, EMMC_FIX_RCA << 16, buf); - if (ret) { - NOTICE("failed to send CMD8\n"); - mmio_write_32(MMC0_RINTSTS, ~0); - return -EFAULT; - } - - ret = wait_data_ready(); - if (ret) - return ret; - - if (blk_cnt > 1) { - ret = mmc0_send_cmd(12, EMMC_FIX_RCA << 16, buf); - if (ret) { - NOTICE("failed to send Stop Transmission command\n"); - return ret; - } - mmio_write_32(MMC0_RINTSTS, ~0); - } - src_addr = MMC_DATA_BASE; - memcpy((void *)dst_addr, (void *)src_addr, MMC_BLOCK_SIZE); - - return 0; -} -#endif - -int mmc0_read(unsigned long src_start, size_t src_size, - unsigned long dst_start, uint32_t boot_partition) -{ - unsigned int src_blk_start = src_start / MMC_BLOCK_SIZE; - unsigned int src_blk_cnt, offset, bytes, desc_num, buf[4]; - struct idmac_desc *desc = NULL; - int i, ret, last_idx; - uintptr_t src_addr, dst_addr = dst_start; - - if (boot_partition) { - /* switch to boot partition 1 */ - ret = mmc0_update_ext_csd(EXT_CSD_PARTITION_CONFIG, - PART_CFG_BOOT_PARTITION1_ENABLE | - PART_CFG_PARTITION1_ACCESS); - if (ret) { - NOTICE("fail to switch eMMC boot partition\n"); - return ret; - } - } - offset = src_start % MMC_BLOCK_SIZE; - src_blk_cnt = (src_size + offset + MMC_BLOCK_SIZE - 1) / MMC_BLOCK_SIZE; - bytes = src_blk_cnt * MMC_BLOCK_SIZE; - - mmio_write_32(MMC0_BYTCNT, bytes); - - mmio_write_32(MMC0_RINTSTS, ~0); - - desc_num = (bytes + MMC_DMA_MAX_BUFFER_SIZE - 1) / - MMC_DMA_MAX_BUFFER_SIZE; - - desc = (struct idmac_desc *)MMC_DESC_BASE; - - for (i = 0; i < desc_num; i++) { - (desc + i)->des0 = IDMAC_DES0_OWN | IDMAC_DES0_CH | - IDMAC_DES0_DIC; - (desc + i)->des1 = IDMAC_DES1_BS1(MMC_DMA_MAX_BUFFER_SIZE); - /* buffer address */ - (desc + i)->des2 = MMC_DATA_BASE + MMC_DMA_MAX_BUFFER_SIZE * i; - /* next descriptor address */ - (desc + i)->des3 = MMC_DESC_BASE + - (sizeof(struct idmac_desc) * (i + 1)); - } - /* first descriptor */ - desc->des0 |= IDMAC_DES0_FS; - /* last descriptor */ - last_idx = desc_num - 1; - (desc + last_idx)->des0 |= IDMAC_DES0_LD; - (desc + last_idx)->des0 &= ~(IDMAC_DES0_DIC | IDMAC_DES0_CH); - (desc + last_idx)->des1 = IDMAC_DES1_BS1(bytes - (last_idx * - MMC_DMA_MAX_BUFFER_SIZE)); - /* set next descriptor address as 0 */ - (desc + last_idx)->des3 = 0; - - mmio_write_32(MMC0_DBADDR, MMC_DESC_BASE); - - ret = mmc0_send_cmd(23, src_blk_cnt & 0xffff, buf); - if (ret) { - NOTICE("failed to send CMD23\n"); - mmio_write_32(MMC0_RINTSTS, ~0); - return -EFAULT; - } - /* multiple read */ - ret = mmc0_send_cmd(18, src_blk_start, buf); - if (ret) { - NOTICE("failed to send CMD18\n"); - mmio_write_32(MMC0_RINTSTS, ~0); - return -EFAULT; - } - - ret = wait_data_ready(); - if (ret) - return ret; - - src_addr = MMC_DATA_BASE + offset; - memcpy((void *)dst_addr, (void *)src_addr, src_size); - - if (boot_partition) { - /* switch back to normal partition */ - ret = mmc0_update_ext_csd(EXT_CSD_PARTITION_CONFIG, - PART_CFG_BOOT_PARTITION1_ENABLE); - if (ret) - NOTICE("fail to switch eMMC normal partition\n"); - } - return ret; -} - -static int write_multi_blocks(unsigned int lba, unsigned int count, - unsigned int buffer, unsigned int boot_partition) -{ - unsigned int bytes, resp_buf[4], desc_num; - struct idmac_desc *desc = NULL; - int ret, last_idx, i; - - if (buffer % 4) { - NOTICE("invalid buffer address:0x%x\n", buffer); - return -EINVAL; - } - if (boot_partition) { - /* switch to boot partition 1 */ - ret = mmc0_update_ext_csd(EXT_CSD_PARTITION_CONFIG, - PART_CFG_BOOT_PARTITION1_ENABLE | - PART_CFG_PARTITION1_ACCESS); - if (ret) { - NOTICE("fail to switch eMMC boot partition\n"); - return ret; - } - } - bytes = MMC_BLOCK_SIZE * count; - - mmio_write_32(MMC0_BYTCNT, bytes); - mmio_write_32(MMC0_RINTSTS, ~0); - - desc_num = (bytes + MMC_DMA_MAX_BUFFER_SIZE - 1) / - MMC_DMA_MAX_BUFFER_SIZE; - - desc = (struct idmac_desc *)MMC_DESC_BASE; - - for (i = 0; i < desc_num; i++) { - (desc + i)->des0 = IDMAC_DES0_OWN | IDMAC_DES0_CH | - IDMAC_DES0_DIC; - (desc + i)->des1 = IDMAC_DES1_BS1(MMC_DMA_MAX_BUFFER_SIZE); - /* buffer address */ - (desc + i)->des2 = buffer + MMC_DMA_MAX_BUFFER_SIZE * i; - /* next descriptor address */ - (desc + i)->des3 = MMC_DESC_BASE + - (sizeof(struct idmac_desc) * (i + 1)); - } - /* first descriptor */ - desc->des0 |= IDMAC_DES0_FS; - /* last descriptor */ - last_idx = desc_num - 1; - (desc + last_idx)->des0 |= IDMAC_DES0_LD; - (desc + last_idx)->des0 &= ~(IDMAC_DES0_DIC | IDMAC_DES0_CH); - (desc + last_idx)->des1 = IDMAC_DES1_BS1(bytes - (last_idx * - MMC_DMA_MAX_BUFFER_SIZE)); - /* set next descriptor address as 0 */ - (desc + last_idx)->des3 = 0; - - mmio_write_32(MMC0_DBADDR, MMC_DESC_BASE); - - ret = mmc0_send_cmd(25, lba, resp_buf); - if (ret) { - NOTICE("failed to send CMD25\n"); - mmio_write_32(MMC0_RINTSTS, ~0); - return -EFAULT; - } - ret = wait_data_ready(); - if (ret) - return ret; - - ret = mmc0_send_cmd(12, EMMC_FIX_RCA << 16, resp_buf); - if (ret) { - NOTICE("failed to send CMD12\n"); - mmio_write_32(MMC0_RINTSTS, ~0); - return -EFAULT; - } - - do { - ret = mmc0_send_cmd(13, EMMC_FIX_RCA << 16, resp_buf); - if (ret) { - NOTICE("failed to send command 13\n"); - return ret; - } - } while (!(resp_buf[0] & MMC_STATUS_READY_FOR_DATA) || - (mmc_state(resp_buf[0] != MMC_STATE_TRAN))); - - if (boot_partition) { - /* switch back to normal partition */ - ret = mmc0_update_ext_csd(EXT_CSD_PARTITION_CONFIG, - PART_CFG_BOOT_PARTITION1_ENABLE); - if (ret) - NOTICE("fail to switch eMMC normal partition\n"); - } - return ret; -} - -int mmc0_write(unsigned long mmc_start, size_t size, - unsigned long buffer, uint32_t boot_partition) -{ - unsigned int mmc_blk_start = mmc_start / MMC_BLOCK_SIZE; - unsigned int mmc_blk_cnt, offset; - - offset = mmc_start % MMC_BLOCK_SIZE; - mmc_blk_cnt = (size + offset + MMC_BLOCK_SIZE - 1) / MMC_BLOCK_SIZE; - - return write_multi_blocks(mmc_blk_start, mmc_blk_cnt, buffer, - boot_partition); -} - -int init_mmc(void) -{ - int ret; - - enable_mmc0(); - - ret = enum_mmc0_card(); - if (ret) - return ret; - - /* set boot mode to 8-bit */ - mmc0_update_ext_csd(177, 2); - /* response to RESET signal */ - mmc0_update_ext_csd(162, 1); - /* set access userdata area */ - mmc0_update_ext_csd(EXT_CSD_PARTITION_CONFIG, - PART_CFG_BOOT_PARTITION1_ENABLE); - - mmio_write_32(MMC0_RINTSTS, ~0); - - return 0; -} diff --git a/plat/hikey/drivers/hi6553.c b/plat/hikey/drivers/hi6553.c deleted file mode 100644 index 521c59a6..00000000 --- a/plat/hikey/drivers/hi6553.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved. - * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved. - * - * 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. - * - * Neither the name of ARM nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific - * prior written permission. - * - * 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 HOLDER 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 <arch.h> -#include <assert.h> -#include <mmio.h> -#include <hi6553.h> -#include <hi6220.h> - -unsigned char hi6553_read_8(unsigned int offset) -{ - return mmio_read_8(PMUSSI_BASE + (offset << 2)); -} - -void hi6553_write_8(unsigned int offset, unsigned int value) -{ - mmio_write_8(PMUSSI_BASE + (offset << 2), value); -} diff --git a/plat/hikey/drivers/hisi_dvfs.c b/plat/hikey/drivers/hisi_dvfs.c deleted file mode 100644 index 3fb4a8e2..00000000 --- a/plat/hikey/drivers/hisi_dvfs.c +++ /dev/null @@ -1,808 +0,0 @@ -/* - * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved. - * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved. - * - * 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. - * - * Neither the name of ARM nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific - * prior written permission. - * - * 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 HOLDER 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 <arch_helpers.h> -#include <assert.h> -#include <bl_common.h> -#include <console.h> -#include <debug.h> -#include <partitions.h> -#include <platform.h> -#include <platform_def.h> -#include <string.h> -#include <mmio.h> -#include <hi6220.h> -#include <hi6553.h> - -#define ACPU_FREQ_MAX_NUM 5 -#define ACPU_OPP_NUM 7 - -#define ACPU_VALID_VOLTAGE_MAGIC (0x5A5AC5C5) - -#define ACPU_WAIT_TIMEOUT (200) -#define ACPU_WAIT_FOR_WFI_TIMOUT (2000) -#define ACPU_DFS_STATE_CNT (0x10000) - -struct acpu_dvfs_sram_stru { - unsigned int magic; - unsigned int support_freq_num; - unsigned int support_freq_max; - unsigned int start_prof; - unsigned int vol[ACPU_OPP_NUM]; -}; - -struct acpu_volt_cal_para { - unsigned int freq; - unsigned int ul_vol; - unsigned int dl_vol; - unsigned int core_ref_hpm; -}; - -struct ddr_volt_cal_para { - unsigned int freq; - unsigned int ul_vol; - unsigned int dl_vol; - unsigned int ddr_ref_hpm; -}; - -struct acpu_dvfs_opp_para { - unsigned int freq; - unsigned int acpu_clk_profile0; - unsigned int acpu_clk_profile1; - unsigned int acpu_vol_profile; - unsigned int acpu_pll_freq; - unsigned int acpu_pll_frac; -}; - -unsigned int efuse_acpu_freq[]= { - 1200000, 1250000, 1300000, 1350000, - 1400000, 1450000, 1500000, 1550000, - 1600000, 1650000, 1700000, 1750000, - 1800000, 1850000, 1900000, 1950000, -}; - -struct acpu_dvfs_opp_para hi6220_acpu_profile[] = { - { 208000, 0x61E5, 0x022, 0x3A, 0x5220102B, 0x05555555 }, - { 432000, 0x10A6, 0x121, 0x3A, 0x5120102D, 0x10000005 }, - { 729000, 0x2283, 0x100, 0x4A, 0x51101026, 0x10000005 }, - { 960000, 0x1211, 0x100, 0x5B, 0x51101032, 0x10000005 }, - { 1200000, 0x1211, 0x100, 0x6B, 0x5110207D, 0x10000005 }, - { 1400000, 0x1211, 0x100, 0x6B, 0x51101049, 0x10000005 }, - { 1500000, 0x1211, 0x100, 0x6B, 0x51101049, 0x10000005 }, -}; - -struct acpu_dvfs_opp_para *acpu_dvfs_profile = hi6220_acpu_profile; -struct acpu_dvfs_sram_stru *acpu_dvfs_sram_buf = - (struct acpu_dvfs_sram_stru *)MEMORY_AXI_ACPU_FREQ_VOL_ADDR; - -static inline void write_reg_mask(uintptr_t addr, - uint32_t val, uint32_t mask) -{ - uint32_t reg; - - reg = mmio_read_32(addr); - reg = (reg & ~(mask)) | val; - mmio_write_32(addr, reg); -} - -static inline uint32_t read_reg_mask(uintptr_t addr, - uint32_t mask, uint32_t offset) -{ - uint32_t reg; - - reg = mmio_read_32(addr); - reg &= (mask << offset); - return (reg >> offset); -} - -static int acpu_dvfs_syspll_cfg(unsigned int prof_id) -{ - uint32_t reg0 = 0; - uint32_t count = 0; - uint32_t clk_div_status = 0; - - /* - * step 1: - * - ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x3; - * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x1; - */ - write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x3 << 12, 0x3 << 12); - write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x1 << 4, 0x1 << 4); - - /* - * step 2: - * - ACPUSYSPLLCFG.acpu_syspll_div_cfg: - * 208MHz, set to 0x5; - * 500MHz, set to 0x2; - * other opps set to 0x1 - */ - if (prof_id == 0) - write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x5 << 0, 0x7 << 0); - else if (prof_id == 1) - write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x2 << 0, 0x7 << 0); - else - write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x1 << 0, 0x7 << 0); - - /* - * step 3: - * - Polling ACPU_SC_CPU_STAT.clk_div_status_vd == 0x3; - * - ACPU_SC_VD_CTRL.tune_en_dif = 0 - * - ACPU_SC_VD_CTRL.tune_en_int = 0 - * - PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg = 0x1 - * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x1 - */ - clk_div_status = 0x3; - do { - reg0 = read_reg_mask(ACPU_SC_CPU_STAT, 0x3, 20); - if ((count++) > ACPU_DFS_STATE_CNT) { - ERROR("%s: clk div status timeout!\n", __func__); - return -1; - } - } while(clk_div_status != reg0); - - write_reg_mask(ACPU_SC_VD_CTRL, 0x0, (0x1 << 0) | (0x1 << 11)); - write_reg_mask(PMCTRL_ACPUCLKDIV, 0x1 << 8, 0x3 << 8); - write_reg_mask(PMCTRL_ACPUPLLSEL, 0x1 << 0, 0x1 << 0); - - return 0; -} - -static void acpu_dvfs_clk_div_cfg(unsigned int prof_id, - unsigned int *cpuext_cfg, - unsigned int *acpu_ddr_cfg) -{ - if (0 == prof_id) { - write_reg_mask(PMCTRL_ACPUCLKDIV, - (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | - (0x1 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START), - (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | - (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START)); - *cpuext_cfg = 0x1; - *acpu_ddr_cfg = 0x1; - } else if (1 == prof_id) { - write_reg_mask(PMCTRL_ACPUCLKDIV, - (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | - (0x1 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START), - (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | - (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START)); - *cpuext_cfg = 0x1; - *acpu_ddr_cfg = 0x1; - } else { - /* ddr has not been inited */ - write_reg_mask(PMCTRL_ACPUCLKDIV, - (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | - (0x0 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START), - (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | - (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START)); - *cpuext_cfg = 0x1; - *acpu_ddr_cfg = 0x0; - } - - return; -} - -static int acpu_dvfs_freq_ascend(unsigned int cur_prof, unsigned int tar_prof) -{ - unsigned int reg0 = 0; - unsigned int reg1 = 0; - unsigned int reg2 = 0; - unsigned int count = 0; - unsigned int cpuext_cfg_val = 0; - unsigned int acpu_ddr_cfg_val = 0; - int ret = 0; - - /* - * step 1: - * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x3; - * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x1; - * - * step 2: - * - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x5 (208MHz) - * - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x2 (500MHz) - * - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x1 (Other OPPs) - * - * step 3: - * - ACPU_SC_CPU_STAT.clk_div_status_vd = 0x3; - * - ACPU_SC_VD_CTRL.tune_en_dif = 0x0; - * - ACPU_SC_VD_CTRL.tune_en_int = 0x0; - * - PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg = 0x1; - * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x1 - */ - ret = acpu_dvfs_syspll_cfg(cur_prof); - if (ret) - return -1; - - /* - * step 4: - * - Polling PMCTRL_ACPUPLLSEL.syspll_sw_stat == 0x1 - */ - count = 0; - do { - reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, - SOC_PMCTRL_ACPUPLLSEL_syspll_sw_stat_START); - if ((count++) > ACPU_DFS_STATE_CNT) { - ERROR("%s: syspll sw status timeout\n", __func__); - return -1; - } - } while(0x1 != reg0); - - /* Enable VD functionality if > 800MHz */ - if (acpu_dvfs_profile[tar_prof].freq > 800000) { - - write_reg_mask(ACPU_SC_VD_HPM_CTRL, - HPM_OSC_DIV_VAL, HPM_OSC_DIV_MASK); - - /* - * step 5: - * - ACPU_SC_VD_HPM_CTRL.hpm_dly_exp = 0xC7A; - * - ACPU_SC_VD_MASK_PATTERN_CTRL[12:0] = 0xCCB; - */ - write_reg_mask(ACPU_SC_VD_HPM_CTRL, - HPM_DLY_EXP_VAL, HPM_DLY_EXP_MASK); - write_reg_mask(ACPU_SC_VD_MASK_PATTERN_CTRL, - ACPU_SC_VD_MASK_PATTERN_VAL, - ACPU_SC_VD_MASK_PATTERN_MASK); - - /* - * step 6: - * - ACPU_SC_VD_DLY_TABLE0_CTRL = 0x1FFF; - * - ACPU_SC_VD_DLY_TABLE1_CTRL = 0x1FFFFFF; - * - ACPU_SC_VD_DLY_TABLE2_CTRL = 0x7FFFFFFF; - * - ACPU_SC_VD_DLY_FIXED_CTRL = 0x1; - */ - mmio_write_32(ACPU_SC_VD_DLY_TABLE0_CTRL, 0x1FFF); - mmio_write_32(ACPU_SC_VD_DLY_TABLE1_CTRL, 0x1FFFFFF); - mmio_write_32(ACPU_SC_VD_DLY_TABLE2_CTRL, 0x7FFFFFFF); - mmio_write_32(ACPU_SC_VD_DLY_FIXED_CTRL, 0x1); - - /* - * step 7: - * - ACPU_SC_VD_CTRL.shift_table0 = 0x1; - * - ACPU_SC_VD_CTRL.shift_table1 = 0x3; - * - ACPU_SC_VD_CTRL.shift_table2 = 0x5; - * - ACPU_SC_VD_CTRL.shift_table3 = 0x6; - * - * step 8: - * - ACPU_SC_VD_CTRL.tune = 0x7; - */ - write_reg_mask(ACPU_SC_VD_CTRL, - ACPU_SC_VD_SHIFT_TABLE_TUNE_VAL, - ACPU_SC_VD_SHIFT_TABLE_TUNE_MASK); - } - - /* step 9: ACPUPLLCTRL.acpupll_en_cfg = 0x0 */ - write_reg_mask(PMCTRL_ACPUPLLCTRL, 0x0, - 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START); - - /* step 10: set PMCTRL_ACPUPLLFREQ and PMCTRL_ACPUPLLFRAC */ - mmio_write_32(PMCTRL_ACPUPLLFREQ, - acpu_dvfs_profile[tar_prof].acpu_pll_freq); - mmio_write_32(PMCTRL_ACPUPLLFRAC, - acpu_dvfs_profile[tar_prof].acpu_pll_frac); - - /* - * step 11: - * - wait for 1us; - * - PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x1 - */ - count = 0 ; - while (count < ACPU_WAIT_TIMEOUT) { - count++; - } - write_reg_mask(PMCTRL_ACPUPLLCTRL, - 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START, - 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START); - - /* step 12: PMCTRL_ACPUVOLPMUADDR = 0x100da */ - mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0x100da); - - /* - * step 13: - * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x13 (208MHz); - * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x13 (500MHz); - * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x20 (798MHz); - * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x3A (1300MHz); - * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x3A (1500MHz); - */ - write_reg_mask(PMCTRL_ACPUDESTVOL, - acpu_dvfs_profile[tar_prof].acpu_vol_profile, - ((0x1 << (SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_END + 1)) - 1)); - - /* - * step 14: - * - Polling PMCTRL_ACPUDESTVOL.acpu_vol_using == ACPUDESTVOL.acpu_dest_vol - * - Polling ACPUVOLTIMEOUT.acpu_vol_timeout == 0x1 - * - Config PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg - * - Config ACPUCLKDIV.cpuext_clk_div_cfg; - */ - count = 0; - do { - reg0 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, - SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_START); - reg1 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, - SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_START); - reg2 = read_reg_mask(PMCTRL_ACPUVOLTTIMEOUT, 0x1, - SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_START); - if ((count++) > ACPU_DFS_STATE_CNT) { - ERROR("%s: acpu destvol cfg timeout.\n", __func__); - return -1; - } - } while((reg0 != reg1) || (0x1 != reg2)); - - acpu_dvfs_clk_div_cfg(tar_prof, &cpuext_cfg_val, &acpu_ddr_cfg_val); - - /* - * step 15: - * - Polling PMCTRL_ACPUCLKDIV.cpuext_clk_div_stat; - * - Polling ACPUCLKDIV.acpu_ddr_clk_div_stat; - * - ACPUPLLCTRL.acpupll_timeout = 0x1; - * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x0; - */ - count = 0; - do { - reg0 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, - SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_START); - reg1 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, - SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_START); - reg2 = read_reg_mask(PMCTRL_ACPUPLLCTRL, 0x1, - SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_START); - if ((count++) > ACPU_DFS_STATE_CNT) { - ERROR("%s: acpu clk div cfg timeout.\n", __func__); - return -1; - } - } while((cpuext_cfg_val != reg1) || - (acpu_ddr_cfg_val != reg0) || - (0x1 != reg2)); - - write_reg_mask(PMCTRL_ACPUPLLSEL, 0x0, - 0x1 << SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_START); - - /* - * step 16: - * - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1; - * - ACPU_SC_VD_CTRL.force_clk_en = 0x0; - * - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0; - * - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0; - * - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0; - * - ACPU_SC_VD_CTRL.div_en_dif = 0x1; - * - ACPU_SC_VD_CTRL.tune_en_int = 0x1; - * - ACPU_SC_VD_CTRL.tune_en_dif = 0x1; - * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0; - * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0; - */ - count = 0; - do { - reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, - SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_START); - if ((count++) > ACPU_DFS_STATE_CNT) { - ERROR("%s: acpu pll sw status timeout.\n", __func__); - return -1; - } - } while(0x1 != reg0); - - if (acpu_dvfs_profile[tar_prof].freq > 800000) - write_reg_mask(ACPU_SC_VD_CTRL, - ACPU_SC_VD_EN_ASIC_VAL, ACPU_SC_VD_EN_MASK); - - write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x0, - (0x3 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_sw_START) | - (0x1 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_START)); - - return 0; -} - -static int acpu_dvfs_freq_descend(unsigned int cur_prof, unsigned int tar_prof) -{ - unsigned int reg0 = 0; - unsigned int reg1 = 0; - unsigned int reg2 = 0; - unsigned int count = 0; - unsigned int cpuext_cfg_val = 0; - unsigned int acpu_ddr_cfg_val = 0; - int ret = 0; - - ret = acpu_dvfs_syspll_cfg(tar_prof); - if (ret) - return -1; - - /* - * step 4: - * - Polling PMCTRL_ACPUPLLSEL.syspll_sw_stat == 0x1 - */ - count = 0; - do { - reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, 2); - if ((count++) > ACPU_DFS_STATE_CNT) { - ERROR("%s: syspll sw status timeout.\n", __func__); - return -1; - } - } while(0x1 != reg0); - - /* - * Step 5: - * - PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x0 - */ - write_reg_mask(PMCTRL_ACPUPLLCTRL, 0x0, 0x1 << 0); - - /* - * step 6 - * - Config PMCTRL_ACPUPLLFREQ and ACPUPLLFRAC - */ - mmio_write_32(PMCTRL_ACPUPLLFREQ, acpu_dvfs_profile[tar_prof].acpu_pll_freq); - mmio_write_32(PMCTRL_ACPUPLLFRAC, acpu_dvfs_profile[tar_prof].acpu_pll_frac); - - /* - * step 7: - * - Wait 1us; - * - Config PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x1 - */ - count = 0 ; - while (count < ACPU_WAIT_TIMEOUT) { - count++; - } - - write_reg_mask(PMCTRL_ACPUPLLCTRL, - 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START, - 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START); - - /* Enable VD functionality if > 800MHz */ - if (acpu_dvfs_profile[tar_prof].freq > 800000) { - - write_reg_mask(ACPU_SC_VD_HPM_CTRL, - HPM_OSC_DIV_VAL, HPM_OSC_DIV_MASK); - - /* - * step 9: - * - ACPU_SC_VD_HPM_CTRL.hpm_dly_exp = 0xC7A; - * - ACPU_SC_VD_MASK_PATTERN_CTRL[12:0] = 0xCCB; - */ - write_reg_mask(ACPU_SC_VD_HPM_CTRL, - HPM_DLY_EXP_VAL, HPM_DLY_EXP_MASK); - write_reg_mask(ACPU_SC_VD_MASK_PATTERN_CTRL, - ACPU_SC_VD_MASK_PATTERN_VAL, - ACPU_SC_VD_MASK_PATTERN_MASK); - - /* - * step 10: - * - ACPU_SC_VD_DLY_TABLE0_CTRL = 0x1FFF; - * - ACPU_SC_VD_DLY_TABLE1_CTRL = 0x1FFFFFF; - * - ACPU_SC_VD_DLY_TABLE2_CTRL = 0x7FFFFFFF; - * - ACPU_SC_VD_DLY_FIXED_CTRL = 0x1; - */ - mmio_write_32(ACPU_SC_VD_DLY_TABLE0_CTRL, 0x1FFF); - mmio_write_32(ACPU_SC_VD_DLY_TABLE1_CTRL, 0x1FFFFFF); - mmio_write_32(ACPU_SC_VD_DLY_TABLE2_CTRL, 0x7FFFFFFF); - mmio_write_32(ACPU_SC_VD_DLY_FIXED_CTRL, 0x1); - - /* - * step 11: - * - ACPU_SC_VD_CTRL.shift_table0 = 0x1; - * - ACPU_SC_VD_CTRL.shift_table1 = 0x3; - * - ACPU_SC_VD_CTRL.shift_table2 = 0x5; - * - ACPU_SC_VD_CTRL.shift_table3 = 0x6; - * - * step 12: - * - ACPU_SC_VD_CTRL.tune = 0x7; - */ - write_reg_mask(ACPU_SC_VD_CTRL, - ACPU_SC_VD_SHIFT_TABLE_TUNE_VAL, - ACPU_SC_VD_SHIFT_TABLE_TUNE_MASK); - } - - /* - * step 13: - * - Pollig PMCTRL_ACPUPLLCTRL.acpupll_timeout == 0x1; - * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x0; - */ - count = 0; - do { - reg0 = read_reg_mask(PMCTRL_ACPUPLLCTRL, 0x1, - SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_START); - if ((count++) > ACPU_DFS_STATE_CNT) { - ERROR("%s: acpupll timeout.\n", __func__); - return -1; - } - } while(0x1 != reg0); - - write_reg_mask(PMCTRL_ACPUPLLSEL, 0x0, - 0x1 << SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_START); - - /* - * step 14: - * - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1; - * - ACPU_SC_VD_CTRL.force_clk_en = 0x0; - * - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0; - * - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0; - * - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0; - * - ACPU_SC_VD_CTRL.div_en_dif = 0x1; - * - ACPU_SC_VD_CTRL.tune_en_int = 0x1; - * - ACPU_SC_VD_CTRL.tune_en_dif = 0x1; - */ - count = 0; - do { - reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, - SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_START); - if ((count++) > ACPU_DFS_STATE_CNT) { - ERROR("%s: acpupll sw status timeout.\n", __func__); - return -1; - } - } while(0x1 != reg0); - - if (acpu_dvfs_profile[tar_prof].freq > 800000) - write_reg_mask(ACPU_SC_VD_CTRL, - ACPU_SC_VD_EN_ASIC_VAL, ACPU_SC_VD_EN_MASK); - - /* - * step 15: - * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0; - * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0; - */ - write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x0, - (0x3 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_sw_START) | - (0x1 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_START)); - - /* - * step 16: - * - Polling ACPU_SC_CPU_STAT.clk_div_status_vd == 0x0; - */ - count = 0; - do { - reg0 = read_reg_mask(ACPU_SC_CPU_STAT, 0x3, - ACPU_SC_CPU_STAT_CLK_DIV_STATUS_VD_SHIFT); - if ((count++) > ACPU_DFS_STATE_CNT) { - ERROR("%s: clk div status timeout.\n", __func__); - return -1; - } - } while(0x0 != reg0); - - acpu_dvfs_clk_div_cfg(tar_prof, &cpuext_cfg_val, &acpu_ddr_cfg_val); - - /* - * step 17: - * - Polling PMCTRL_ACPUCLKDIV.cpuext_clk_div_stat; - * - Polling ACPUCLKDIV.acpu_ddr_clk_div_stat; - * - PMCTRL_ACPUVOLPMUADDR = 0x1006C; - */ - count = 0; - do { - reg0 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, - SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_START); - reg1 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, - SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_START); - if ((count++) > ACPU_DFS_STATE_CNT) { - ERROR("%s: acpu clk div cfg timeout.\n", __func__); - return -1; - } - } while((cpuext_cfg_val != reg0) || (acpu_ddr_cfg_val != reg1)); - - mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0x100da); - - /* - * step 16: - * - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1; - * - ACPU_SC_VD_CTRL.force_clk_en = 0x0; - * - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0; - * - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0; - * - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0; - * - ACPU_SC_VD_CTRL.div_en_dif = 0x1; - * - ACPU_SC_VD_CTRL.tune_en_int = 0x1; - * - ACPU_SC_VD_CTRL.tune_en_dif = 0x1; - * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0; - * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0; - */ - write_reg_mask(PMCTRL_ACPUDESTVOL, - acpu_dvfs_profile[tar_prof].acpu_vol_profile, - ((0x1 << (SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_END + 1)) - 1)); - - /* - * step 19: - * - Polling PMCTRL_ACPUDESTVOL.acpu_vol_using == ACPUDESTVOL.acpu_dest_vol - * - ACPUVOLTIMEOUT.acpu_vol_timeout = 0x1; - */ - count = 0; - do { - reg0 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, - SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_START); - reg1 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, - SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_START); - reg2 = read_reg_mask(PMCTRL_ACPUVOLTTIMEOUT, 0x1, - SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_START); - if ((count++) > ACPU_DFS_STATE_CNT) { - ERROR("%s: acpu destvol cfg timeout.\n", __func__); - return -1; - } - } while((reg0 != reg1) || (0x1 != reg2)); - - return 0; -} - -int acpu_dvfs_target(unsigned int curr_prof, unsigned int target_prof) -{ - int ret = 0; - - if (curr_prof == target_prof) { - INFO("%s: target_prof is equal curr_prof: is %d!\n", - __func__, curr_prof); - return 0; - } - - if ((curr_prof >= ACPU_FREQ_MAX_NUM) || - (target_prof >= ACPU_FREQ_MAX_NUM)) { - INFO("%s: invalid parameter %d %d\n", - __func__, curr_prof, target_prof); - return -1; - } - - if (target_prof > acpu_dvfs_sram_buf->support_freq_num) - target_prof = acpu_dvfs_sram_buf->support_freq_num; - - if (target_prof < curr_prof) - ret = acpu_dvfs_freq_descend(curr_prof, target_prof); - else if (target_prof > curr_prof) - ret = acpu_dvfs_freq_ascend(curr_prof, target_prof); - - if (ret) { - ERROR("%s: acpu_dvfs_target failed!\n"); - return -1; - } - - /* Complete acpu dvfs setting and set magic number */ - acpu_dvfs_sram_buf->start_prof = target_prof; - acpu_dvfs_sram_buf->magic = ACPU_VALID_VOLTAGE_MAGIC; - - mmio_write_32(DDR_DFS_FREQ_ADDR, 800000); - return 0; -} - -static int acpu_dvfs_set_freq(void) -{ - unsigned int i; - unsigned int curr_prof; - unsigned int target_prof; - unsigned int max_freq = 0; - - max_freq = acpu_dvfs_sram_buf->support_freq_max; - - for (i = 0; i < acpu_dvfs_sram_buf->support_freq_num; i++) { - - if (max_freq == hi6220_acpu_profile[i].freq) { - target_prof = i; - break; - } - } - - if (i == acpu_dvfs_sram_buf->support_freq_num) { - ERROR("%s: cannot found max freq profile\n", __func__); - return -1; - } - - curr_prof = 0; - target_prof = i; - - /* if max freq is 208MHz, do nothing */ - if (curr_prof == target_prof) - return 0; - - if (acpu_dvfs_target(curr_prof, target_prof)) { - ERROR("%s: set acpu freq failed!", __func__); - return -1; - } - - INFO("%s: support freq num is %d\n", - __func__, acpu_dvfs_sram_buf->support_freq_num); - INFO("%s: start prof is 0x%x\n", - __func__, acpu_dvfs_sram_buf->start_prof); - INFO("%s: magic is 0x%x\n", - __func__, acpu_dvfs_sram_buf->magic); - INFO("%s: voltage:\n", __func__); - for (i = 0; i < acpu_dvfs_sram_buf->support_freq_num; i++) - INFO(" - %d: 0x%x\n", i, acpu_dvfs_sram_buf->vol[i]); - - NOTICE("%s: set acpu freq success!", __func__); - return 0; -} - -struct acpu_dvfs_volt_setting -{ - unsigned int magic; - unsigned int support_freq_num; - unsigned int support_freq_max; - unsigned int start_prof; - unsigned int vol[7]; - unsigned int hmp_dly_threshold[7]; -}; - -static void acpu_dvfs_volt_init(void) -{ - struct acpu_dvfs_volt_setting *volt; - - /* - * - set default voltage; - * - set pmu address; - * - set voltage up and down step; - * - set voltage stable time; - */ - mmio_write_32(PMCTRL_ACPUDFTVOL, 0x4a); - mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0xda); - mmio_write_32(PMCTRL_ACPUVOLUPSTEP, 0x1); - mmio_write_32(PMCTRL_ACPUVOLDNSTEP, 0x1); - mmio_write_32(PMCTRL_ACPUPMUVOLUPTIME, 0x60); - mmio_write_32(PMCTRL_ACPUPMUVOLDNTIME, 0x60); - mmio_write_32(PMCTRL_ACPUCLKOFFCFG, 0x1000); - - volt= (void *)MEMORY_AXI_ACPU_FREQ_VOL_ADDR; - volt->magic = 0x5a5ac5c5; - volt->support_freq_num = 5; - volt->support_freq_max = 1200000; - volt->start_prof = 4; - volt->vol[0] = 0x49; - volt->vol[1] = 0x49; - volt->vol[2] = 0x50; - volt->vol[3] = 0x60; - volt->vol[4] = 0x78; - volt->vol[5] = 0x78; - volt->vol[6] = 0x78; - - volt->hmp_dly_threshold[0] = 0x0; - volt->hmp_dly_threshold[1] = 0x0; - volt->hmp_dly_threshold[2] = 0x0; - volt->hmp_dly_threshold[3] = 0x0e8b0e45; - volt->hmp_dly_threshold[4] = 0x10691023; - volt->hmp_dly_threshold[5] = 0x10691023; - volt->hmp_dly_threshold[6] = 0x10691023; - - INFO("%s: success!\n", __func__); -} - -void init_acpu_dvfs(void) -{ - unsigned int i = 0; - - INFO("%s: pmic version %d\n", __func__, hi6553_read_8(VERSION_REG)); - - /* init parameters */ - mmio_write_32(ACPU_CHIP_MAX_FREQ, efuse_acpu_freq[8]); - INFO("%s: ACPU_CHIP_MAX_FREQ=0x%x.\n", - __func__, mmio_read_32(ACPU_CHIP_MAX_FREQ)); - - /* set maximum support frequency to 1.2GHz */ - for(i = 0; i < ACPU_FREQ_MAX_NUM; i++) - acpu_dvfs_sram_buf->vol[i] = hi6220_acpu_profile[i].acpu_vol_profile; - - acpu_dvfs_sram_buf->support_freq_num = ACPU_FREQ_MAX_NUM; - acpu_dvfs_sram_buf->support_freq_max = 1200000; - - /* init acpu dvfs */ - acpu_dvfs_volt_init(); - acpu_dvfs_set_freq(); - - return; -} diff --git a/plat/hikey/drivers/hisi_ipc.c b/plat/hikey/drivers/hisi_ipc.c deleted file mode 100644 index 393982c1..00000000 --- a/plat/hikey/drivers/hisi_ipc.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved. - * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved. - * - * 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. - * - * Neither the name of ARM nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific - * prior written permission. - * - * 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 HOLDER 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 <hisi_ipc.h> -#include <hisi_sram_map.h> -#include <mmio.h> -#include <platform_def.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> - -#include <hi6220_regs_acpu.h> - -#define BIT(x) (0x1 << (x)) - -static int _ipc_init = 0; - -static unsigned int cpu_ipc_num[PLATFORM_CLUSTER_COUNT][PLATFORM_CORE_COUNT_PER_CLUSTER] = { - { - HISI_IPC_MCU_INT_SRC_ACPU0_PD, - HISI_IPC_MCU_INT_SRC_ACPU1_PD, - HISI_IPC_MCU_INT_SRC_ACPU2_PD, - HISI_IPC_MCU_INT_SRC_ACPU3_PD, - }, - { - HISI_IPC_MCU_INT_SRC_ACPU4_PD, - HISI_IPC_MCU_INT_SRC_ACPU5_PD, - HISI_IPC_MCU_INT_SRC_ACPU6_PD, - HISI_IPC_MCU_INT_SRC_ACPU7_PD, - } -}; - -int hisi_cpus_pd_in_cluster_besides_curr(unsigned int cpu, - unsigned int cluster) -{ - unsigned int val = 0, cpu_val = 0; - int i; - - val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR); - val = val >> (cluster * 16); - - for (i = 0; i < PLATFORM_CORE_COUNT_PER_CLUSTER; i++) { - - if (cpu == i) - continue; - - cpu_val = (val >> (i * 4)) & 0xF; - if (cpu_val == 0x8) - return 0; - } - - return 1; -} - -int hisi_cpus_powered_off_besides_curr(unsigned int cpu) -{ - unsigned int val; - - val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR); - return (val == (0x8 << (cpu * 4))); -} - -static void hisi_ipc_send(unsigned int ipc_num) -{ - if (!_ipc_init) { - printf("error ipc base is null!!!\n"); - return; - } - - mmio_write_32(HISI_IPC_CPU_RAW_INT_ADDR, 1 << ipc_num); -} - -void hisi_ipc_spin_lock(unsigned int signal) -{ - unsigned int hs_ctrl; - - if (signal >= HISI_IPC_INT_SRC_NUM) - return; - - do { - hs_ctrl = mmio_read_32(HISI_IPC_ACPU_CTRL(signal)); - } while (hs_ctrl); -} - -void hisi_ipc_spin_unlock(unsigned int signal) -{ - if (signal >= HISI_IPC_INT_SRC_NUM) - return; - - mmio_write_32(HISI_IPC_ACPU_CTRL(signal), 0); -} - -void hisi_ipc_cpu_on_off(unsigned int cpu, unsigned int cluster, - unsigned int mode) -{ - unsigned int val = 0; - unsigned int offset; - - if (mode == HISI_IPC_PM_ON) - offset = cluster * 16 + cpu * 4; - else - offset = cluster * 16 + cpu * 4 + 1; - - hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE); - val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR); - val |= (0x01 << offset); - mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, val); - hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE); - - hisi_ipc_send(cpu_ipc_num[cluster][cpu]); -} - -void hisi_ipc_cpu_on(unsigned int cpu, unsigned int cluster) -{ - unsigned int data, expected; - - hisi_ipc_cpu_on_off(cpu, cluster, HISI_IPC_PM_ON); - - /* Enable debug module */ - data = mmio_read_32(ACPU_SC_PDBGUP_MBIST); - if (cluster) - expected = 1 << (cpu + PDBGUP_CLUSTER1_SHIFT); - else - expected = 1 << cpu; - mmio_write_32(ACPU_SC_PDBGUP_MBIST, data | expected); - do { - /* RAW barrier */ - data = mmio_read_32(ACPU_SC_PDBGUP_MBIST); - } while (!(data & expected)); -} - -void hisi_ipc_cpu_off(unsigned int cpu, unsigned int cluster) -{ - hisi_ipc_cpu_on_off(cpu, cluster, HISI_IPC_PM_OFF); -} - -void hisi_ipc_cluster_on_off(unsigned int cpu, unsigned int cluster, - unsigned int mode) -{ - unsigned int val = 0; - unsigned int offset; - - if (mode == HISI_IPC_PM_ON) - offset = cluster * 4; - else - offset = cluster * 4 + 1; - - hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE); - val = mmio_read_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR); - val |= (0x01 << offset); - mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, val); - hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE); - - hisi_ipc_send(cpu_ipc_num[cluster][cpu]); -} - -void hisi_ipc_cluster_on(unsigned int cpu, unsigned int cluster) -{ - hisi_ipc_cluster_on_off(cpu, cluster, HISI_IPC_PM_ON); -} - -void hisi_ipc_cluster_off(unsigned int cpu, unsigned int cluster) -{ - hisi_ipc_cluster_on_off(cpu, cluster, HISI_IPC_PM_OFF); -} - -void hisi_ipc_cpu_suspend(unsigned int cpu, unsigned int cluster) -{ - unsigned int val = 0; - unsigned int offset; - - offset = cluster * 16 + cpu * 4 + 2; - - hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE); - val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR); - val |= (0x01 << offset); - mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, val); - hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE); - - hisi_ipc_send(cpu_ipc_num[cluster][cpu]); -} - -void hisi_ipc_cluster_suspend(unsigned int cpu, unsigned int cluster) -{ - unsigned int val; - unsigned int offset; - - offset = cluster * 4 + 1; - - hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE); - if (hisi_cpus_pd_in_cluster_besides_curr(cpu, cluster)) { - val = mmio_read_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR); - val |= (0x01 << offset); - mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, val); - } - hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE); - - hisi_ipc_send(cpu_ipc_num[cluster][cpu]); -} - -void hisi_ipc_psci_system_off(void) -{ - hisi_ipc_send(HISI_IPC_MCU_INT_SRC_ACPU_PD); -} - -int hisi_ipc_init(void) -{ - _ipc_init = 1; - - mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, 0x8); - mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, 0x8); - return 0; -} diff --git a/plat/hikey/drivers/hisi_mcu.c b/plat/hikey/drivers/hisi_mcu.c deleted file mode 100644 index 50d5f543..00000000 --- a/plat/hikey/drivers/hisi_mcu.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved. - * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved. - * - * 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. - * - * Neither the name of ARM nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific - * prior written permission. - * - * 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 HOLDER 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 <arch_helpers.h> -#include <assert.h> -#include <bl_common.h> -#include <console.h> -#include <debug.h> -#include <partitions.h> -#include <platform.h> -#include <platform_def.h> -#include <string.h> -#include <mmio.h> -#include <hi6220.h> - -#define MCU_SECTION_MAX 30 - -enum MCU_IMAGE_SEC_TYPE_ENUM { - MCU_IMAGE_SEC_TYPE_TEXT = 0, /* text section */ - MCU_IMAGE_SEC_TYPE_DATA, /* data section */ - MCU_IMAGE_SEC_TYPE_BUTT -}; - -enum MCU_IMAGE_SEC_LOAD_ENUM { - MCU_IMAGE_SEC_LOAD_STATIC = 0, - MCU_IMAGE_SEC_LOAD_DYNAMIC, - MCU_IMAGE_SEC_LOAD_BUFFER, - MCU_IMAGE_SEC_LOAD_MODEM_ENTRY, - MCU_IMAGE_SEC_LOAD_BUTT -}; - -struct mcu_image_sec { - unsigned short serial; - char type; - char load_attr; - uint32_t src_offset; /* offset in image */ - uint32_t dst_offset; /* offset in memory */ - uint32_t size; -}; - -struct mcu_image_head { - char time_stamp[24]; - uint32_t image_size; - uint32_t secs_num; - struct mcu_image_sec secs[MCU_SECTION_MAX]; -}; - -#define SOC_SRAM_M3_BASE_ADDR (0xF6000000) - -#define MCU_SRAM_SIZE (0x0000C000) -#define MCU_CACHE_SIZE (0x00004000) -#define MCU_CODE_SIZE (MCU_SRAM_SIZE - MCU_CACHE_SIZE) - -#define MCU_SYS_MEM_ADDR (0x05E00000) -#define MCU_SYS_MEM_SIZE (0x00100000) - -#if 0 -static uint32_t ap2mcu_addr(uint32_t ap_addr) -{ - if (ap_addr >= SOC_SRAM_M3_BASE_ADDR && - ap_addr < SOC_SRAM_M3_BASE_ADDR + MCU_SRAM_SIZE) - return ap_addr - SOC_SRAM_M3_BASE_ADDR; - else if (ap_addr >= MCU_SYS_MEM_ADDR && - ap_addr < MCU_SYS_MEM_ADDR + MCU_SYS_MEM_SIZE ) - return ap_addr - MCU_SYS_MEM_ADDR + MCU_SRAM_SIZE; - else - return ap_addr; -} -#endif - -static uint32_t mcu2ap_addr(uint32_t mcu_addr) -{ - if (mcu_addr < MCU_CODE_SIZE) - return (mcu_addr + SOC_SRAM_M3_BASE_ADDR); - else if ((mcu_addr >= MCU_SRAM_SIZE) && - (mcu_addr < MCU_SRAM_SIZE + MCU_SYS_MEM_SIZE)) - return mcu_addr - MCU_SRAM_SIZE + MCU_SYS_MEM_ADDR; - else - return mcu_addr; -} - -static int is_binary_header_invalid(struct mcu_image_head *head, - unsigned length) -{ - /* invalid cases */ - if ((head->image_size == 0) || - (head->image_size > length) || - (head->secs_num > MCU_SECTION_MAX) || - (head->secs_num == 0)) - return 1; - - return 0; -} - -static int is_binary_section_invalid(struct mcu_image_sec *sec, - struct mcu_image_head *head) -{ - unsigned long ap_dst_offset = 0; - - if ((sec->serial >= head->secs_num) || - (sec->src_offset + sec->size > head->image_size)) - return 1; - - if ((sec->type >= MCU_IMAGE_SEC_TYPE_BUTT) || - (sec->load_attr >= MCU_IMAGE_SEC_LOAD_BUTT)) - return 1; - - ap_dst_offset = mcu2ap_addr(sec->dst_offset); - if ((ap_dst_offset >= SOC_SRAM_M3_BASE_ADDR) && - (ap_dst_offset < SOC_SRAM_M3_BASE_ADDR + 0x20000 - sec->size)) - return 0; - else if ((ap_dst_offset >= MCU_SYS_MEM_ADDR) && - (ap_dst_offset < MCU_SYS_MEM_ADDR + MCU_SYS_MEM_SIZE - sec->size)) - return 0; - else if ((ap_dst_offset >= 0xfff8e000) && - (ap_dst_offset < 0xfff91c00 - sec->size)) - return 0; - - ERROR("%s: mcu destination address invalid.\n", __func__); - ERROR("%s: number=%d, dst offset=%d size=%d\n", - __func__, sec->serial, sec->dst_offset, sec->size); - return 1; -} - -void hisi_mcu_enable_sram(void) -{ - mmio_write_32(AO_SC_PERIPH_CLKEN4, - AO_SC_PERIPH_CLKEN4_HCLK_IPC_S | - AO_SC_PERIPH_CLKEN4_HCLK_IPC_NS); - - /* set register to enable dvfs which is used by mcu */ - mmio_write_32(PERI_SC_RESERVED8_ADDR, 0x0A001022); - - /* mcu mem is powered on, need de-assert reset */ - mmio_write_32(AO_SC_PERIPH_RSTDIS4, - AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N); - - /* enable mcu hclk */ - mmio_write_32(AO_SC_PERIPH_CLKEN4, - AO_SC_PERIPH_CLKEN4_HCLK_MCU | - AO_SC_PERIPH_CLKEN4_CLK_MCU_DAP); -} - -void hisi_mcu_start_run(void) -{ - unsigned int val; - -#if 0 - /* set mcu's self loop instruction 0xE7FE at entry point */ - val = mmio_read_32((SOC_SRAM_M3_BASE_ADDR + 0x200)); - val &= 0xFFFF0000; - val |= 0xE7FE; - mmio_write_32((SOC_SRAM_M3_BASE_ADDR + 0x200), val); -#endif - - /* set mcu ddr remap configuration */ - mmio_write_32(AO_SC_MCU_SUBSYS_CTRL2, MCU_SYS_MEM_ADDR); - - /* de-assert reset for mcu and to run */ - mmio_write_32(AO_SC_PERIPH_RSTDIS4, - AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N | - AO_SC_PERIPH_RSTDIS4_RESET_MCU_SYS_N | - AO_SC_PERIPH_RSTDIS4_RESET_MCU_POR_N | - AO_SC_PERIPH_RSTDIS4_RESET_MCU_DAP_N); - - val = mmio_read_32(AO_SC_SYS_CTRL2); - mmio_write_32(AO_SC_SYS_CTRL2, - val | AO_SC_SYS_CTRL2_GLB_SRST_STAT_CLEAR); - - INFO("%s: AO_SC_SYS_CTRL2=%x\n", __func__, - mmio_read_32(AO_SC_SYS_CTRL2)); -} - -int hisi_mcu_load_image(uintptr_t image_base, uint32_t image_size) -{ - unsigned int i; - struct mcu_image_head *head; - char *buf; - - head = (struct mcu_image_head *)image_base; - if (is_binary_header_invalid(head, image_size)) { - ERROR("Invalid %s image header.\n", head->time_stamp); - return -1; - } - - buf = (char *)head; - for (i = 0; i < head->secs_num; i++) { - - int *src, *dst; - - /* check the sections */ - if (is_binary_section_invalid(&head->secs[i], head)) { - ERROR("Invalid mcu section.\n"); - return -1; - } - - /* check if the section is static-loaded */ - if (head->secs[i].load_attr != MCU_IMAGE_SEC_LOAD_STATIC) - continue; - - /* copy the sections */ - src = (int *)(intptr_t)(buf + head->secs[i].src_offset); - dst = (int *)(intptr_t)mcu2ap_addr(head->secs[i].dst_offset); - - memcpy((void *)dst, (void *)src, head->secs[i].size); - - INFO("%s: mcu sections %d:\n", __func__, i); - INFO("%s: src = 0x%x\n", __func__, src); - INFO("%s: dst = 0x%x\n", __func__, dst); - INFO("%s: size = %d\n", __func__, head->secs[i].size); - - INFO("%s: [SRC 0x%x] 0x%x 0x%x 0x%x 0x%x\n", __func__, - src, src[0], src[1], src[2], src[3]); - INFO("%s: [DST 0x%x] 0x%x 0x%x 0x%x 0x%x\n", __func__, - dst, dst[0], dst[1], dst[2], dst[3]); - } - - return 0; -} diff --git a/plat/hikey/drivers/hisi_pwrc.c b/plat/hikey/drivers/hisi_pwrc.c deleted file mode 100644 index c1d9e471..00000000 --- a/plat/hikey/drivers/hisi_pwrc.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved. - * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved. - * - * 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. - * - * Neither the name of ARM nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific - * prior written permission. - * - * 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 HOLDER 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 <bakery_lock.h> -#include <mmio.h> -#include <hisi_ipc.h> -#include <hisi_pwrc.h> -#include <hisi_sram_map.h> -#include <hi6220_regs_acpu.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#include <platform_def.h> - -#define CLUSTER_CORE_COUNT (4) -#define CLUSTER_CORE_MASK ((1 << CLUSTER_CORE_COUNT) - 1) - -#define BIT(x) (0x1 << (x)) - -void hisi_pwrc_set_core_bx_addr(unsigned int core, unsigned int cluster, - uintptr_t entry_point) -{ - uintptr_t *core_entry = (uintptr_t *)PWRCTRL_ACPU_ASM_D_ARM_PARA_AD; - unsigned int i; - - if (!core_entry) { - printf("%s: core entry point is null!\n", __func__); - return; - } - - i = cluster * CLUSTER_CORE_COUNT + core; - mmio_write_64((uintptr_t)(core_entry + i), entry_point); -} - -void hisi_pwrc_set_cluster_wfi(unsigned int cluster) -{ - unsigned int reg = 0; - - if (cluster == 0) { - reg = mmio_read_32(ACPU_CTRL_BASE + 0x0E4); - reg |= BIT(0); - mmio_write_32(ACPU_CTRL_BASE + 0x0E4, reg); - } else if (cluster == 1) { - reg = mmio_read_32(ACPU_CTRL_BASE + 0x0E4); - reg |= BIT(16); - mmio_write_32(ACPU_CTRL_BASE + 0x0E4, reg); - } -} - -int hisi_pwrc_setup(void) -{ - unsigned int reg; - extern char pm_asm_code[], pm_asm_code_end[]; - extern char v7_asm[], v7_asm_end[]; - - mmio_write_32(ACPU_SC_CPUx_RVBARADDR(0), PWRCTRL_ACPU_ASM_CODE_BASE >> 2); - mmio_write_32(ACPU_SC_CPUx_RVBARADDR(1), PWRCTRL_ACPU_ASM_CODE_BASE >> 2); - mmio_write_32(ACPU_SC_CPUx_RVBARADDR(2), PWRCTRL_ACPU_ASM_CODE_BASE >> 2); - mmio_write_32(ACPU_SC_CPUx_RVBARADDR(3), PWRCTRL_ACPU_ASM_CODE_BASE >> 2); - mmio_write_32(ACPU_SC_CPUx_RVBARADDR(4), PWRCTRL_ACPU_ASM_CODE_BASE >> 2); - mmio_write_32(ACPU_SC_CPUx_RVBARADDR(5), PWRCTRL_ACPU_ASM_CODE_BASE >> 2); - mmio_write_32(ACPU_SC_CPUx_RVBARADDR(6), PWRCTRL_ACPU_ASM_CODE_BASE >> 2); - mmio_write_32(ACPU_SC_CPUx_RVBARADDR(7), PWRCTRL_ACPU_ASM_CODE_BASE >> 2); - - memset((void *)PWRCTRL_ACPU_ASM_SPACE_ADDR, 0, 0x400); - memcpy((void *)PWRCTRL_ACPU_ASM_SPACE_ADDR, (void *)v7_asm, - v7_asm_end - v7_asm); - - memcpy((void *)PWRCTRL_ACPU_ASM_CODE_BASE, (void *)pm_asm_code, - pm_asm_code_end - pm_asm_code); - - reg = mmio_read_32(0xF7800000 + 0x004); - - /* Remap SRAM address */ - reg |= BIT(0x1) | BIT(17); - - /* Enable reset signal for watchdog */ - reg |= BIT(0x0) | BIT(16); - - mmio_write_32(0xF7800000 + 0x004, reg); - - return 0; -} diff --git a/plat/hikey/drivers/hisi_pwrc_sram.S b/plat/hikey/drivers/hisi_pwrc_sram.S deleted file mode 100644 index ae8eec40..00000000 --- a/plat/hikey/drivers/hisi_pwrc_sram.S +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved. - * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved. - * - * 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. - * - * Neither the name of ARM nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific - * prior written permission. - * - * 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 HOLDER 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 <arch.h> -#include <asm_macros.S> -#include <hisi_sram_map.h> - - .global pm_asm_code - .global pm_asm_code_end - .global v7_asm - .global v7_asm_end - - .align 3 -func pm_asm_code - mov x0, 0 - msr oslar_el1, x0 - - mrs x0, s3_1_c15_c2_0 - bic x0, x0, #0x1E000000 - orr x0, x0, #0x180000 - orr x0, x0, #0xe000 - msr s3_1_c15_c2_0, x0 - - mrs x3, actlr_el3 - orr x3, x3, #(0x1<<5) - msr actlr_el3, x3 - - mrs x3, actlr_el2 - orr x3, x3, #(0x1<<5) - msr actlr_el2, x3 - - ldr x3, =PWRCTRL_ACPU_ASM_D_ARM_PARA_AD - mrs x0, mpidr_el1 - and x1, x0, #MPIDR_CPU_MASK - and x0, x0, #MPIDR_CLUSTER_MASK - add x0, x1, x0, LSR #6 -pen: ldr x4, [x3, x0, LSL #3] - cbz x4, pen - - mov x0, #0x0 - mov x1, #0x0 - mov x2, #0x0 - mov x3, #0x0 - br x4 - - .ltorg - -pm_asm_code_end: - - .align 3 - .section .rodata.v7_asm, "aS" -v7_asm: - .word 0xE1A00000 // nop - .word 0xE3A02003 // mov r2, #3 - .word 0xEE0C2F50 // mcr 15, 0, r2, cr12, cr0, {2} - .word 0xE320F003 // wfi - - .ltorg -v7_asm_end: diff --git a/plat/hikey/drivers/sp804_timer.c b/plat/hikey/drivers/sp804_timer.c deleted file mode 100644 index 269bf1c6..00000000 --- a/plat/hikey/drivers/sp804_timer.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved. - * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved. - * - * 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. - * - * Neither the name of ARM nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific - * prior written permission. - * - * 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 HOLDER 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 <console.h> -#include <debug.h> -#include <errno.h> -#include <hi6220.h> -#include <mmio.h> -#include <sp804_timer.h> - -/* Init dual timer0 (TIMER00 & TIMER01) */ -void hi6220_timer_init(void) -{ - unsigned int data; - - /* select 32KHz as the clock of dual timer0 */ - /* FIXME: But I find that it's 19.2MHz, not 32KHz. */ - data = mmio_read_32(AO_SC_TIMER_EN0); - while (data & 3) { - data &= ~3; - data |= 3 << 16; - mmio_write_32(AO_SC_TIMER_EN0, data); - data = mmio_read_32(AO_SC_TIMER_EN0); - } - /* enable the pclk of dual timer0 */ - data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4); - while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0)) { - mmio_write_32(AO_SC_PERIPH_CLKEN4, PCLK_TIMER1 | PCLK_TIMER0); - data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4); - } - /* reset dual timer0 */ - data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4); - mmio_write_32(AO_SC_PERIPH_RSTEN4, PCLK_TIMER1 | PCLK_TIMER0); - do { - data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4); - } while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0)); - /* unreset dual timer0 */ - mmio_write_32(AO_SC_PERIPH_RSTDIS4, PCLK_TIMER1 | PCLK_TIMER0); - do { - data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4); - } while ((data & PCLK_TIMER1) || (data & PCLK_TIMER0)); - - /* disable timer00 */ - mmio_write_32(TIMER00_CONTROL, 0); - mmio_write_32(TIMER00_LOAD, 0xffffffff); - /* free running */ - mmio_write_32(TIMER00_CONTROL, 0x82); -} - -static unsigned int get_timer_value(void) -{ - return mmio_read_32(TIMER00_VALUE); -} - -void udelay(int us) -{ - unsigned int start, cnt, delta, delta_us; - - if (us <= 0) - us = 1; - /* counter is decreasing */ - start = get_timer_value(); - do { - cnt = get_timer_value(); - if (cnt > start) { - delta = 0xffffffff - cnt; - delta += start; - } else - delta = start - cnt; - delta_us = (delta * 10) / 192; - } while (delta_us < us); -} - -void mdelay(int ms) -{ - unsigned int start, cnt, delta, delta_ms; - - if (ms <= 0) - ms = 1; - - /* counter is decreasing */ - start = get_timer_value(); - do { - cnt = get_timer_value(); - if (cnt > start) { - delta = 0xffffffff - cnt; - delta += start; - } else - delta = start - cnt; - delta_ms = delta / 19200; - } while (delta_ms < ms); -} |