507 lines
10 KiB
C
Raw Normal View History

2025-10-10 16:07:00 +08:00
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <common/bk_include.h>
#include <driver/psram_types.h>
#include "psram_hal.h"
#include "psram_ll_macro_def.h"
#include "bk_pm_internal_api.h"
#include "sys_driver.h"
#include "aon_pmu_ll.h"
#include <driver/psram.h>
#include <modules/chip_support.h>
extern void delay_us(uint32_t us);
static void psram_delay(volatile uint32_t times)
{
while(times--);
}
void psram_hal_set_sf_reset(uint32_t value)
{
psram_ll_set_sf_reset_value(value);
}
void psram_hal_set_cmd_reset(void)
{
psram_ll_set_reg8_value(0x4);
}
void psram_hal_cmd_write(uint32_t addr, uint32_t value)
{
psram_ll_set_write_address(addr);
psram_ll_set_write_data(value);
psram_ll_set_reg8_value(0x1);
while(psram_ll_get_reg8_value() & 0x1);
}
uint32_t psram_hal_cmd_read(uint32_t addr)
{
uint8_t m = 10, i = 5;
for (i = 5; i > 0; i--)
{
psram_ll_set_write_address(addr);
psram_ll_set_reg8_value(0x2);
m = 10;
while(psram_ll_get_reg8_value() & 0x2)
{
for (int j = 0; j < 5000; j++) {}
m--;
if (m == 0)
break;
};
if (m != 0)
{
return psram_ll_get_regb_value();
}
psram_hal_set_sf_reset(0);
psram_hal_set_sf_reset(1);
psram_hal_set_cmd_reset();
}
return 0;
}
void psram_hal_set_clk(psram_clk_t clk)
{
switch (clk)
{
case PSRAM_240M:
sys_drv_psram_clk_sel(1); // clk sel: 0-320 1-480
sys_drv_psram_set_clkdiv(0); //frq: F/(2 + (1+div))
break;
case PSRAM_160M:
sys_drv_psram_clk_sel(0); // clk sel: 0-320 1-480
sys_drv_psram_set_clkdiv(0); //frq: F/(2 + (1+div))
break;
case PSRAM_120M:
sys_drv_psram_clk_sel(1); // clk sel: 0-320 1-480
sys_drv_psram_set_clkdiv(1); //frq: F/(2 + (1+div))
break;
case PSRAM_80M:
sys_drv_psram_clk_sel(0); // clk sel: 0-320 1-480
sys_drv_psram_set_clkdiv(1); //frq: F/(2 + (1+div))
break;
default:
break;
}
}
void psram_hal_set_voltage(psram_voltage_t voltage)
{
#if (COINFG_SOC_BK7256XX)
switch (voltage)
{
case PSRAM_OUT_3_20V:
sys_drv_psram_psldo_vset(0, 1);
break;
case PSRAM_OUT_3_0V:
sys_drv_psram_psldo_vset(0, 0);
break;
case PSRAM_OUT_2_0V:
sys_drv_psram_psldo_vset(1, 1);
break;
case PSRAM_OUT_1_80V:
sys_drv_psram_psldo_vset(1, 0);
break;
default:
break;
}
#else
switch (voltage)
{
case PSRAM_OUT_3_0V:
sys_drv_psram_psldo_vset(0, 0);
break;
case PSRAM_OUT_1_95V:
sys_drv_psram_psldo_vset(1, 0);
break;
case PSRAM_OUT_1_90V:
sys_drv_psram_psldo_vset(1, 1);
break;
case PSRAM_OUT_1_85V:
sys_drv_psram_psldo_vset(1, 2);
break;
case PSRAM_OUT_1_80V:
sys_drv_psram_psldo_vset(1, 3);
break;
default:
break;
}
#endif
}
static inline bool is_psram_addr_out_of_range(uint32_t addr)
{
#if (CONFIG_PSRAM_WRITE_THROUGH)
return ((addr < SOC_PSRAM_DATA_BASE) || (addr > (SOC_PSRAM_DATA_BASE + SOC_PSRAM_DATA_SIZE)));
#else
return false;
#endif
}
static inline bool is_32bytes_aligned(uint32_t addr)
{
return ((addr & 0x1f) == 0);
}
int psram_hal_set_write_through(psram_write_through_area_t area, uint32_t enable, uint32_t start, uint32_t end)
{
#if (CONFIG_PSRAM_WRITE_THROUGH)
if (area > PSRAM_WRITE_THROUGH_AREA_COUNT) {
return BK_ERR_PSRAM_AREA;
}
if (enable) {
if (start >= end) {
return BK_ERR_PSRAM_ADDR_RELATION;
}
if (is_psram_addr_out_of_range(start) || is_psram_addr_out_of_range(end)) {
return BK_ERR_PSRAM_ADDR_OUT_OF_RANGE;
}
if ((!is_32bytes_aligned(start)) || (!is_32bytes_aligned(end))) {
return BK_ERR_PSRAM_ADDR_ALIGN;
}
psram_ll_set_cover_start(area, start >> 5);
psram_ll_set_cover_stop_enable(area, BIT(31) | (end >> 5));
} else {
psram_ll_set_cover_stop_enable(area, 0);
}
return BK_OK;
#else
return BK_FAIL;
#endif
}
void psram_hal_set_transfer_mode(uint32_t value)
{
psram_ll_set_reg4_wrap_config(value);
}
static int psram_hal_APS6408L_init(uint32_t *id)
{
uint32_t val = 0;
#if (CONFIG_SOC_BK7256XX)
uint32_t chip_id = bk_get_hardware_chip_id_version();
if (chip_id == CHIP_VERSION_C)
psram_hal_set_mode_value(PSRAM_MODE1);
else
psram_hal_set_mode_value(PSRAM_MODE3);
#else
psram_hal_set_mode_value(PSRAM_MODE6);//PSRAM_MODE2
//psram_hal_set_reg5_value(0x282);
psram_hal_set_reg5_value(0x380);
#endif
psram_hal_set_cmd_reset();
psram_delay(500);
val = psram_hal_cmd_read(0x00000000);//1 0001 10001101
#if (CONFIG_SOC_BK7256XX)
// 8 line
val = ((val >> 8) & 0xFF) | ((val & 0xFF) << 8);
#endif
if (val == 0 || val != *id)
{
return -1;
}
else
{
*id = val;
}
val = psram_hal_get_regb_value();
#if (CONFIG_SOC_BK7256XX)
val = (val & ~(0x1F << 8)) | (0x4 << 10) | (0x3 << 8);
#else
val = (val & ~(0x1F)) | (0x4 << 2) | 0x3;
#endif
psram_hal_cmd_write(0x00000000, val);
psram_hal_cmd_read(0x00000000);//1 0001 10001101
psram_hal_cmd_read(0x00000004);
val = psram_hal_get_regb_value();
#if (CONFIG_SOC_BK7256XX)
val = (val & ~(0x7 << 13)) | (0x6 << 13);//write latency 110 166Mhz
#else
val = (val & ~(0x7 << 5)) | (0x6 << 5);
#endif
psram_hal_cmd_write(0x00000004, val);
return 0;
}
static int psram_hal_W955D8MKY_5J_init(uint32_t *id)
{
uint32_t val = 0;
uint32_t io_drv = 0; /*range [0, 3]*/
#if (CONFIG_SOC_BK7256XX)
psram_hal_set_mode_value(PSRAM_MODE4);// mode 4
#elif (CONFIG_SOC_BK7236XX)
psram_hal_set_mode_value(PSRAM_MODE8);// mode 8
#endif
#if (!CONFIG_SOC_BK7256XX)
psram_hal_set_reg5_value(0x292);
//psram_hal_set_reg5_value(0x380); //NOTES:APS PSRAM drive stength needs changed.This type PSRAM needs to be verified.
#endif
psram_hal_set_cmd_reset();
psram_delay(500);
val = psram_hal_cmd_read(0x01000000);
(VOID *)val;
#if (CONFIG_SOC_BK7256XX)
// 8 line
val = ((val >> 8) & 0xFF) | ((val & 0xFF) << 8);
#endif
#if (CONFIG_SOC_BK7256XX)
val = 0x8F1C | (io_drv << 12);
#else
val = 0x1C8F | (io_drv << 4);
#endif
#if (CONFIG_SOC_BK7256XX)
psram_hal_cmd_write(0x01000000, val);
#elif (CONFIG_SOC_BK7236XX)
psram_hal_cmd_write(0x01000000, 0x1c8f);
#endif
psram_hal_cmd_read(0x01000000);
return 0;
}
static int psram_hal_APS128XXO_OB9_init(uint32_t *id)
{
uint32_t val = 0;
psram_hal_set_mode_value(PSRAM_MODE7);
#if (!CONFIG_SOC_BK7256XX)
//psram_hal_set_reg5_value(0x292);
psram_hal_set_reg5_value(0x380);
#endif
psram_hal_set_cmd_reset();
psram_delay(500);
val = psram_hal_cmd_read(0x00000000);//1 0001 10001101
#if (CONFIG_SOC_BK7256XX)
// 8 line
val = ((val >> 8) & 0xFF) | ((val & 0xFF) << 8);
#endif
if (val == 0 || val != *id)
{
return -1;
}
else
{
*id = val;
}
val = psram_hal_get_regb_value();
#if (CONFIG_SOC_BK7256XX)
val = (val & ~(0x7 << 10)) | (0x4 << 10);
#else
val = (val & ~(0x7 << 2)) | (0x4 << 2);
#endif
psram_hal_cmd_write(0x00000000, val);
psram_hal_cmd_read(0x00000004);
val = psram_hal_get_regb_value();
#if (CONFIG_SOC_BK7256XX)
val = (val & ~(0x7 << 13)) | (0x6 << 13);
#else
val = (val & ~(0x7 << 5)) | (0x6 << 5);
#endif
psram_hal_cmd_write(0x00000004, val);
psram_hal_cmd_read(0x00000008);//1 0001 10001101
val = psram_hal_get_regb_value();
val |= 0x40;
psram_hal_cmd_write(0x00000008,val);
return 0;
}
uint32_t psram_hal_config_init(uint32_t id)
{
int ret = 0;
uint32_t val = 0;
uint32_t type = id;
psram_hal_set_sf_reset(1);
/* set psram bypass */
val = psram_hal_get_reg2_value();
val |= (0x1 << 1);
psram_hal_set_reg2_value(val);
if (id != 0)
{
if (id == PSRAM_APS6408L_ID)
{
psram_hal_APS6408L_init(&type);
return type;
}
else if (id == PSRAM_APS128XXO_OB9_ID)
{
psram_hal_APS128XXO_OB9_init(&type);
return type;
}
else //id == PSRAM_W955D8MKY_5J_ID
{
psram_hal_W955D8MKY_5J_init(&type);
return type;
}
}
else
{
type = PSRAM_APS6408L_ID;
ret = psram_hal_APS6408L_init(&type);
if (ret == 0)
{
return type;
}
type = PSRAM_APS128XXO_OB9_ID;
ret = psram_hal_APS128XXO_OB9_init(&type);
if (ret == 0)
{
return type;
}
type = PSRAM_W955D8MKY_5J_ID;
ret = psram_hal_W955D8MKY_5J_init(&type);
return type;
}
}
// config 1: psram power and clk config, need wait clk stable
void psram_hal_power_clk_enable(uint8_t enable)
{
if (enable)
{
psram_delay(500);
sys_drv_psram_ldo_enable(1);
delay_us(1000);
bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_AHBP_PSRAM, PM_POWER_MODULE_STATE_ON);
// psram bus clk always open
sys_drv_psram_psram_disckg(1);
//psram 80M
psram_hal_set_clk(PSRAM_80M);
sys_drv_dev_clk_pwr_up(CLK_PWR_ID_PSRAM, CLK_PWR_CTRL_PWR_UP);//psram_clk_enable bit19=1
}
else
{
bk_psram_heap_init_flag_set(false);
bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_AHBP_PSRAM, PM_POWER_MODULE_STATE_OFF);
psram_hal_set_sf_reset(0);
sys_drv_dev_clk_pwr_up(CLK_PWR_ID_PSRAM, CLK_PWR_CTRL_PWR_DOWN);//psram_clk_disable
// power down
sys_drv_psram_ldo_enable(0);
}
psram_delay(3000);
}
// config 2: reset psram and wait psram ready
void psram_hal_reset(void)
{
#if (CONFIG_SOC_BK7256XX)
psram_hal_set_sf_reset(1);
#if (CONFIG_PSRAM_APS6408L_O)
int chip_id = bk_get_hardware_chip_id_version();
if (chip_id == CHIP_VERSION_C)
psram_hal_set_mode_value(PSRAM_MODE1);
else
psram_hal_set_mode_value(PSRAM_MODE3);
#else
//psram_hal_set_mode_value(PSRAM_MODE5);// mode 5
psram_hal_set_mode_value(PSRAM_MODE4);// mode 4
#endif
psram_hal_set_cmd_reset();
#endif //CONFIG_SOC_BK7256XX
}
// config 3: psram config
void psram_hal_config(void)
{
#if (CONFIG_SOC_BK7256XX)
uint32_t val = 0;
#if (CONFIG_PSRAM_APS6408L_O)
psram_hal_cmd_read(0x00000000);//1 0001 10001101
val = psram_hal_get_regb_value();
val = (val & ~(0x1F << 8)) | (0x4 << 10) | (0x3 << 8);
psram_hal_cmd_write(0x00000000, val);
psram_hal_cmd_read(0x00000000);//1 0001 10001101
psram_hal_cmd_read(0x00000004);
val = psram_hal_get_regb_value();
val = (val & ~(0x7 << 13)) | (0x6 << 13);//write latency 110 166Mhz
psram_hal_cmd_write(0x00000004, val);
#else
uint32_t io_drv = 0; /*range [0, 3]*/
val = psram_hal_cmd_read(0x01000000);
//val = 0x8F1F | (io_drv << 12);// mode 5
val = 0x8F1C | (io_drv << 12);// mode 4
psram_hal_cmd_write(0x01000000, val);
psram_hal_cmd_read(0x01000000);
#endif
#endif //CONFIG_SOC_BK7256XX
}