blob: 099b2ed78d39ca5a1a41035b1c311ed6aecea291 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <ddk/io-buffer.h>
#include <string.h>
#pragma once
//From EMMC Design documentation provided by AMLOGIC
#define AML_SD_EMMC_IRQ_ALL_CLEAR 0x3fff
#define AML_SD_EMMC_CTS_OSCIN_CLK_FREQ 24000000 //24MHz
#define AML_SD_EMMC_CTS_OSCIN_CLK_SRC 0
#define AML_SD_EMMC_FCLK_DIV2_FREQ 1000000000 //1GHz
#define AML_SD_EMMC_FCLK_DIV2_SRC 1
//~Min freq attainable with DIV2 Src
#define AML_SD_EMMC_FCLK_DIV2_MIN_FREQ 20000000 //20MHz
#define AML_SD_EMMC_MAX_BLK_SIZE 512
//Default values after reset.EMMC Design Docs by AMLOGIC: PG 56
#define AML_SD_EMMC_DEFAULT_BL_LEN 9 //512 bytes
#define AML_SD_EMMC_DEFAULT_RESP_TIMEOUT 8 //256 core clock cycles
#define AML_SD_EMMC_DEFAULT_RC_CC 4 //16 core clock cycles
#define AML_SD_EMMC_DEFAULT_CLK_SRC 0 //24MHz
#define AML_SD_EMMC_DEFAULT_CLK_DIV 60 //Defaults to 400KHz
#define AML_SD_EMMC_DEFAULT_CLK_CORE_PHASE 2
#define AML_SD_EMMC_MAX_TUNING_TRIES 7
#define AML_SD_EMMC_ADJ_DELAY_TEST_ATTEMPTS 10
#define AML_SD_EMMC_DEFAULT_CMD_TIMEOUT 0xc //2^12 ms.
#define AML_SD_EMMC_SRAM_MEMORY_BASE 0x200
#define AML_SD_EMMC_SRAM_MEMORY_SIZE 512
#define AML_SD_EMMC_PING_BUFFER_BASE 0x400
#define AML_SD_EMMC_PING_BUFFER_SIZE 512
#define AML_SD_EMMC_PONG_BUFER_BASE 0x600
#define AML_SD_EMMC_PONG_BUFFER_SIZE 512
#define AML_SD_EMMC_MAX_PIO_DESCS 32 // 16 * 32 = 512
#define AML_SD_EMMC_MAX_PIO_DATA_SIZE AML_SD_EMMC_PING_BUFFER_SIZE + \
AML_SD_EMMC_PONG_BUFFER_SIZE
#define AML_SDIO_PORTB_GPIO_REG_5_VAL 0x00020000
#define AML_SDIO_PORTB_PERIPHS_PINMUX2_VAL 0x01000000
#define AML_SDIO_PORTB_PERIPHS_GPIO2_EN 0xffffffef
#define AML_SDIO_PORTB_HHI_GCLK_MPEG0_VAL 0x02000000
#define AML_SDIO_PORTB_SD_EMMC_CLK_VAL 0xf181ffff
static inline void update_bits(uint32_t *x, uint32_t mask, uint32_t loc, uint32_t val) {
*x &= ~mask;
*x |= ((val << loc) & mask);
}
static inline uint32_t get_bits(uint32_t x, uint32_t mask, uint32_t loc) {
return (x & mask) >> loc;
}
static inline bool get_bit(uint32_t x, uint32_t mask) {
return (x & mask) ? 1 : 0;
}
typedef struct {
volatile uint32_t sd_emmc_clock; // 0x00
#define AML_SD_EMMC_CLOCK_CFG_DIV_LOC 0
#define AML_SD_EMMC_CLOCK_CFG_DIV_MASK 0x0000003f
#define AML_SD_EMMC_CLOCK_CFG_SRC_LOC 6
#define AML_SD_EMMC_CLOCK_CFG_SRC_MASK 0x000000c0
#define AML_SD_EMMC_CLOCK_CFG_CO_PHASE_LOC 8
#define AML_SD_EMMC_CLOCK_CFG_CO_PHASE_MASK 0x00000300
#define AML_SD_EMMC_CLOCK_CFG_TX_PHASE_LOC 10
#define AML_SD_EMMC_CLOCK_CFG_TX_PHASE_MASK 0x00000c00
#define AML_SD_EMMC_CLOCK_CFG_RX_PHASE_LOC 12
#define AML_SD_EMMC_CLOCK_CFG_RX_PHASE_MASK 0x00003000
#define AML_SD_EMMC_CLOCK_CFG_SRAM_PD_LOC 14
#define AML_SD_EMMC_CLOCK_CFG_SRAM_PD_MASK 0x0000c000
#define AML_SD_EMMC_CLOCK_CFG_TX_DELAY_LOC 16
#define AML_SD_EMMC_CLOCK_CFG_TX_DELAY_MASK 0x003f0000
#define AML_SD_EMMC_CLOCK_CFG_RX_DELAY_LOC 22
#define AML_SD_EMMC_CLOCK_CFG_RX_DELAY_MASK 0x0fc00000
#define AML_SD_EMMC_CLOCK_CFG_ALWAYS_ON 0x10000000
#define AML_SD_EMMC_CLOCK_CFG_IRQ_SDIO_SLEEP 0x20000000
#define AML_SD_EMMC_CLOCK_CFG_IRQ_SDIO_SLEEP_DS 0x40000000
#define AML_SD_EMMC_CLOCK_CFG_NAND 0x80000000
volatile uint32_t sd_emmc_delay1; // 0x04
#define AML_SD_EMMC_DELAY_DATA0_LOC 0
#define AML_SD_EMMC_DELAY_DATA0_MASK 0x0000003f
#define AML_SD_EMMC_DELAY_DATA1_LOC 6
#define AML_SD_EMMC_DELAY_DATA1_MASK 0x00000fc0
#define AML_SD_EMMC_DELAY_DATA2_LOC 12
#define AML_SD_EMMC_DELAY_DATA2_MASK 0x0003f000
#define AML_SD_EMMC_DELAY_DATA3_LOC 18
#define AML_SD_EMMC_DELAY_DATA3_MASK 0x00fc0000
#define AML_SD_EMMC_DELAY_DATA4_LOC 24
#define AML_SD_EMMC_DELAY_DATA4_MASK 0x3f000000
#define AML_SD_EMMC_DELAY_SPARE_LOC 30
#define AML_SD_EMMC_DELAY_SPARE_MASK 0xc0000000
volatile uint32_t sd_emmc_delay2; //0x08
volatile uint32_t sd_emmc_adjust; // 0x0c
#define AML_SD_EMMC_ADJUST_CALI_SEL_LOC 8
#define AML_SD_EMMC_ADJUST_CALI_SEL_MASK 0x00000f00
#define AML_SD_EMMC_ADJUST_CALI_ENABLE 0x00001000
#define AML_SD_EMMC_ADJUST_ADJ_FIXED 0x00002000
#define AML_SD_EMMC_ADJUST_CALI_RISE 0x00004000
#define AML_SD_EMMC_ADJUST_DS_ENABLE 0x00008000
#define AML_SD_EMMC_ADJUST_ADJ_DELAY_LOC 16
#define AML_SD_EMMC_ADJUST_ADJ_DELAY_MASK 0x003f0000
#define AML_SD_EMMC_ADJUST_ADJ_AUTO 0x00400000
volatile uint32_t sd_emmc_calout; // 0x10
#define AML_SD_EMMC_CALOUT_CALI_IDX_LOC 0
#define AML_SD_EMMC_CALOUT_CALI_IDX_MASK 0x0000003f
#define AML_SD_EMMC_CALOUT_CALI_VLD 0x00000040
#define AML_SD_EMMC_CALOUT_CALI_SETUP_LOC 8
#define AML_SD_EMMC_CALOUT_CALI_SETUP_MASK 0x0000ff00
volatile uint32_t sd_emmc_calout_v2[3]; // 0x14~0x1c
volatile uint32_t resvd_test[6]; // 0x20~0x34
volatile uint32_t sd_emmc_intf3[2]; // 0x38, 0x39
volatile uint32_t sd_emmc_start; // 0x40
#define AML_SD_EMMC_START_DESC_INT 0x00000001
#define AML_SD_EMMC_START_DESC_BUSY 0x00000002
#define AML_SD_EMMC_START_DESC_ADDR_LOC 2
#define AML_SD_EMMC_START_DESC_ADDR_MASK 0xfffffffc
volatile uint32_t sd_emmc_cfg; // 0x44
#define AML_SD_EMMC_CFG_BUS_WIDTH_LOC 0
#define AML_SD_EMMC_CFG_BUS_WIDTH_MASK 0x00000003
#define AML_SD_EMMC_CFG_BUS_WIDTH_1BIT 0x00000000
#define AML_SD_EMMC_CFG_BUS_WIDTH_4BIT 0x00000001
#define AML_SD_EMMC_CFG_BUS_WIDTH_8BIT 0x00000002
#define AML_SD_EMMC_CFG_DDR 0x00000004
#define AML_SD_EMMC_CFG_DC_UGT 0x00000008
#define AML_SD_EMMC_CFG_BL_LEN_LOC 4
#define AML_SD_EMMC_CFG_BL_LEN_MASK 0x000000f0
#define AML_SD_EMMC_CFG_RESP_TIMEOUT_LOC 8
#define AML_SD_EMMC_CFG_RESP_TIMEOUT_MASK 0x00000f00
#define AML_SD_EMMC_CFG_RC_CC_LOC 12
#define AML_SD_EMMC_CFG_RC_CC_MASK 0x0000f000
#define AML_SD_EMMC_CFG_OUT_FALL 0x00010000
#define AML_SD_EMMC_CFG_BLK_GAP_IP 0x00020000
#define AML_SD_EMMC_CFG_SDCLK_ALWAYS_ON 0x00040000
#define AML_SD_EMMC_CFG_IGNORE_OWNER 0x00080000
#define AML_SD_EMMC_CFG_CHK_DS 0x00100000
#define AML_SD_EMMC_CFG_CMD_LOW 0x00200000
#define AML_SD_EMMC_CFG_STOP_CLK 0x00400000
#define AML_SD_EMMC_CFG_AUTO_CLK 0x00800000
#define AML_SD_EMMC_CFG_TXD_ADD_ERR 0x01000000
#define AML_SD_EMMC_CFG_TXD_RETRY 0x02000000
#define AML_SD_EMMC_CFG_IRQ_DS 0x04000000
#define AML_SD_EMMC_CFG_ERR_ABORT 0x08000000
#define AML_SD_EMMC_CFG_IP_TXD_ADJ_LOC 28
#define AML_SD_EMMC_CFG_IP_TXD_ADJ_MASK 0xf0000000
volatile uint32_t sd_emmc_status; // 0x48
#define AML_SD_EMMC_STATUS_RXD_ERR_LOC 0
#define AML_SD_EMMC_STATUS_RXD_ERR_MASK 0x000000ff
#define AML_SD_EMMC_STATUS_TXD_ERR 0x00000100
#define AML_SD_EMMC_STATUS_DESC_ERR 0x00000200
#define AML_SD_EMMC_STATUS_RESP_ERR 0x00000400
#define AML_SD_EMMC_STATUS_RESP_TIMEOUT 0x00000800
#define AML_SD_EMMC_STATUS_DESC_TIMEOUT 0x00001000
#define AML_SD_EMMC_STATUS_END_OF_CHAIN 0x00002000
#define AML_SD_EMMC_STATUS_RESP_STATUS 0x00004000
#define AML_SD_EMMC_STATUS_IRQ_SDIO 0x00008000
#define AML_SD_EMMC_STATUS_DAT_I_LOC 16
#define AML_SD_EMMC_STATUS_DAT_I_MASK 0x00ff0000
#define AML_SD_EMMC_STATUS_CMD_I 0x01000000
#define AML_SD_EMMC_STATUS_DS 0x02000000
#define AML_SD_EMMC_STATUS_BUS_FSM_LOC 26
#define AML_SD_EMMC_STATUS_BUS_FSM_MASK 0x3c000000
#define AML_SD_EMMC_STATUS_BUS_DESC_BUSY 0x40000000
#define AML_SD_EMMC_STATUS_BUS_CORE_BUSY 0x80000000
volatile uint32_t sd_emmc_irq_en; // 0x4c
volatile uint32_t sd_emmc_cmd_cfg; // 0x50
#define AML_SD_EMMC_CMD_INFO_LEN_LOC 0
#define AML_SD_EMMC_CMD_INFO_LEN_MASK 0x000001ff
#define AML_SD_EMMC_CMD_INFO_BLOCK_MODE 0x00000200
#define AML_SD_EMMC_CMD_INFO_R1B 0x00000400
#define AML_SD_EMMC_CMD_INFO_END_OF_CHAIN 0x00000800
#define AML_SD_EMMC_CMD_INFO_TIMEOUT_LOC 12
#define AML_SD_EMMC_CMD_INFO_TIMEOUT_MASK 0x0000f000
#define AML_SD_EMMC_CMD_INFO_NO_RESP 0x00010000
#define AML_SD_EMMC_CMD_INFO_NO_CMD 0x00020000
#define AML_SD_EMMC_CMD_INFO_DATA_IO 0x00040000
#define AML_SD_EMMC_CMD_INFO_DATA_WR 0x00080000
#define AML_SD_EMMC_CMD_INFO_RESP_NO_CRC 0x00100000
#define AML_SD_EMMC_CMD_INFO_RESP_128 0x00200000
#define AML_SD_EMMC_CMD_INFO_RESP_NUM 0x00400000
#define AML_SD_EMMC_CMD_INFO_DATA_NUM 0x00800000
#define AML_SD_EMMC_CMD_INFO_CMD_IDX_LOC 24
#define AML_SD_EMMC_CMD_INFO_CMD_IDX_MASK 0x3f000000
#define AML_SD_EMMC_CMD_INFO_ERROR 0x40000000
#define AML_SD_EMMC_CMD_INFO_OWNER 0x80000000
volatile uint32_t sd_emmc_cmd_arg; // 0x54
volatile uint32_t sd_emmc_cmd_dat; // 0x58
volatile uint32_t sd_emmc_cmd_rsp; // 0x5c
volatile uint32_t sd_emmc_cmd_rsp1; // 0x60
volatile uint32_t sd_emmc_cmd_rsp2; // 0x64
volatile uint32_t sd_emmc_cmd_rsp3; // 0x68
volatile uint32_t bus_err; // 0x6c
volatile uint32_t sd_emmc_curr_cfg; // 0x70
volatile uint32_t sd_emmc_curr_arg; // 0x74
volatile uint32_t sd_emmc_curr_dat; // 0x78
volatile uint32_t sd_emmc_curr_rsp; // 0x7c
volatile uint32_t sd_emmc_next_cfg; // 0x80
volatile uint32_t sd_emmc_next_arg; // 0x84
volatile uint32_t sd_emmc_next_dat; // 0x88
volatile uint32_t sd_emmc_next_rsp; // 0x8c
volatile uint32_t sd_emmc_rxd; // 0x90
volatile uint32_t sd_emmc_txd; // 0x94
volatile uint32_t resvd[90]; // 0x98~0x1fc
volatile uint32_t sramDesc[128]; // 0x200
volatile uint32_t ping[128]; // 0x400
volatile uint32_t pong[128]; // 0x800
} aml_sd_emmc_regs_t;
typedef struct {
uint32_t cmd_info;
uint32_t cmd_arg;
uint32_t data_addr;
uint32_t resp_addr;
} aml_sd_emmc_desc_t;
typedef struct {
bool supports_dma;
uint32_t min_freq;
uint32_t max_freq;
} aml_sd_emmc_config_t;
static const uint8_t aml_sd_emmc_tuning_blk_pattern_4bit[64] = {
0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,
};
static const uint8_t aml_sd_emmc_tuning_blk_pattern_8bit[128] = {
0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
};