Files
luban-lite/bsp/artinchip/drv_bare/psram/xspi_psram.c
刘可亮 564e22b32f v0.7.5
2023-08-28 09:48:01 +08:00

245 lines
6.1 KiB
C

/*
* Copyright (c) 2023, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: Mingfeng.Li <mingfeng.li@artinchip.com>
*/
#include <rtconfig.h>
#include <stdio.h>
#include <stdlib.h>
#include <aic_common.h>
#include <string.h>
#include <aic_core.h>
#include <aic_hal.h>
#include <driver.h>
#include <xspi_psram.h>
#include <hal_xspi.h>
#include "aic_core.h"
#define XSPI_DDR_MODE 1
#define XSPI_SDR_MODE 0
#define XSPI_MODE_XCCELA 0
#define XSPI_MODE_HYPERBUS 1
#define XSPI_MODE_OPI 2
#define XSPI_MODE_SPI 3
#define XSPI_IO_1 0x0
#define XSPI_IO_2 0x1
#define XSPI_IO_4 0x2
#define XSPI_IO_8 0x3
#define XSPI_PARALLEL_MODE 1
#define XSPI_SINGLE_MODE 0
#define BASE_PSRAM 0x40000000
// usually config by menuconfig
#ifndef AIC_XSPI_PSRAM_CLK
#define AIC_XSPI_PSRAM_CLK 99000000
#endif
#ifndef AIC_XSPI_PSRAM_CS0_PINS
#define AIC_XSPI_PSRAM_CS0_PINS 0
#endif
#ifndef AIC_XSPI_PSRAM_CS1_PINS
#define AIC_XSPI_PSRAM_CS1_PINS 0
#endif
static struct aic_xspi aic_xspi_controller[] = {
{
.name = "xspi",
.idx = 0,
.clk_id = CLK_XSPI,
/* XSPI IP hw Frequency division=2 */
.clk_in_hz = AIC_XSPI_PSRAM_CLK * 2,
},
};
static struct aic_xspi *aic_get_xspi_by_index(u32 idx)
{
struct aic_xspi *xspi;
u32 i;
xspi = NULL;
for (i = 0; i < ARRAY_SIZE(aic_xspi_controller); i++) {
if (i == idx) {
xspi = &aic_xspi_controller[i];
break;
}
}
return xspi;
}
static int aic_xspi_psram_dev_reset(hal_xspi_handle *handle)
{
pr_info("aic_xspi_psram_dev_reset %s:%d\n\n\n", __FUNCTION__, __LINE__);
hal_xspi_set_cmd_width(handle, XSPI_DDR_MODE, XSPI_IO_8);
hal_xspi_set_cmd(handle, XSPI_DDR_MODE, 0xff);
hal_xspi_set_addr_width(handle, XSPI_DDR_MODE, XSPI_IO_8, 3);
hal_xspi_set_addr(handle, 0x0);
hal_xspi_set_dummy(handle, XSPI_IO_8, 0x0);
hal_xspi_set_write_cnt(handle, XSPI_DDR_MODE, XSPI_IO_8, 1);
u8 buf = 0;
struct hal_xspi_transfer t;
t.rx_data = NULL;
t.tx_data = &buf;
t.data_len = 1;
hal_xspi_transfer_cpu_sync(handle, &t);
pr_info("aic_xspi_psram_dev_reset %s:%d\n\n\n", __FUNCTION__, __LINE__);
return 0;
}
static int aic_xspi_psram_dev_init(hal_xspi_handle *handle)
{
hal_xspi_set_cmd_width(handle, XSPI_DDR_MODE, XSPI_IO_8);
hal_xspi_set_cmd(handle, XSPI_DDR_MODE, 0xc0);
hal_xspi_set_addr_width(handle, XSPI_DDR_MODE, XSPI_IO_8, 3);
hal_xspi_set_addr(handle, 0x0);
hal_xspi_set_dummy(handle, XSPI_IO_8, 0x0);
hal_xspi_set_write_cnt(handle, XSPI_DDR_MODE, XSPI_IO_8, 2);
u8 buf1[2] = {0x19, 0x00};
struct hal_xspi_transfer t2;
t2.rx_data = NULL;
t2.tx_data = (u8 *)buf1;
t2.data_len = 2;
hal_xspi_transfer_cpu_sync(handle, &t2);
hal_xspi_set_addr(handle, 0x4);
u8 buf11[2] = {0x80, 0x00};
struct hal_xspi_transfer t22;
t22.rx_data = NULL;
t22.tx_data = (u8 *)buf11;
t22.data_len = 2;
hal_xspi_transfer_cpu_sync(handle, &t22);
return 0;
}
static int aic_xspi_psram_read_id(hal_xspi_handle *handle)
{
u32 data = 0;
pr_info("aic_xspi_psram_read_id %s:%d\n", __FUNCTION__, __LINE__);
hal_xspi_set_cmd_width(handle, XSPI_DDR_MODE, XSPI_IO_8);
hal_xspi_set_cmd(handle, XSPI_DDR_MODE, 0x40);
hal_xspi_set_addr_width(handle, XSPI_DDR_MODE, XSPI_IO_8, 3);
hal_xspi_set_addr(handle, 0x02);
hal_xspi_set_dummy(handle, XSPI_IO_8, 3);
hal_xspi_set_read_cnt(handle, XSPI_DDR_MODE, XSPI_IO_8, 4);
struct hal_xspi_transfer t3;
t3.rx_data = (u8 *)&data;
t3.tx_data = NULL;
t3.data_len = 4;
hal_xspi_transfer_cpu_sync(handle, &t3);
pr_info("APS3208K_ID= 0x%x\n", data);
return 0;
}
static int aic_xspi_psram_xip(hal_xspi_handle *handle, hal_xspi_proto_cfg_t proto)
{
hal_xspi_xip_cfg(handle, proto);
hal_xspi_xip_enable(handle);
return 0;
}
int aic_xspi_psram_init(void)
{
u32 ret = 0;
struct aic_xspi *xspi;
struct hal_xspi_config cfg;
xspi = aic_get_xspi_by_index(0);
if (!xspi)
return -1;
if (xspi->inited)
return 0;
memset(&cfg, 0, sizeof(cfg));
cfg.idx = xspi->idx;
cfg.clk_in_hz = xspi->clk_in_hz;
cfg.clk_id = xspi->clk_id;
cfg.cs0_port = AIC_XSPI_PSRAM_CS0_PINS;
cfg.cs1_port = AIC_XSPI_PSRAM_CS1_PINS;
ret = hal_xspi_init(&xspi->handle, &cfg);
if (ret) {
pr_err("xspi init failed.\n");
return ret;
}
hal_xspi_set_cs(&xspi->handle, 0);
aic_xspi_psram_dev_reset(&xspi->handle);
aic_udelay(500);
aic_xspi_psram_dev_init(&xspi->handle);
aic_xspi_psram_read_id(&xspi->handle);
hal_xspi_set_cs(&xspi->handle, 1);
aic_xspi_psram_dev_reset(&xspi->handle);
aic_udelay(500);
aic_xspi_psram_dev_init(&xspi->handle);
aic_xspi_psram_read_id(&xspi->handle);
// set Boundary_Control = 2k.
hal_xspi_set_boudary(&xspi->handle, BOUNDARY_2K);
hal_xspi_proto_cfg_t psram_proto_cfg = {0};
psram_proto_cfg.mode = XSPI_MODE_OPI;
psram_proto_cfg.clk_mode = XSPI_DDR_MODE;
psram_proto_cfg.parallel_mode = XSPI_SINGLE_MODE;
psram_proto_cfg.wr_cmd_lines = XSPI_IO_8;
psram_proto_cfg.wr_cmd_val = 0x80;
psram_proto_cfg.addr_lines = XSPI_IO_8;
psram_proto_cfg.addr_width = 3;
//psram_proto_cfg.wr_dummy = 0;
psram_proto_cfg.wr_dummy = 2; // >166M
psram_proto_cfg.rd_dummy = 0x06;
psram_proto_cfg.wr_cnt_lines = XSPI_IO_8;
psram_proto_cfg.wr_cnt = 2;
psram_proto_cfg.rd_cnt_lines = XSPI_IO_8;
psram_proto_cfg.rd_cnt = 3;
psram_proto_cfg.rd_cmd_lines = XSPI_IO_8;
psram_proto_cfg.rd_cmd_val = 0x00;
aic_xspi_psram_xip(&xspi->handle, psram_proto_cfg);
void *psram_training_buf = (u32*)(BASE_PSRAM);
int len = 1024 * 256;
ret = hal_xspi_dll_training(&xspi->handle, 0, 2, psram_training_buf, len);
if (ret) {
pr_err("xspi cs0 trainning failed.\n");
while(1);
}
ret = hal_xspi_dll_training(&xspi->handle, 1, 2, psram_training_buf, len);
if (ret) {
pr_err("xspi cs0 trainning failed.\n");
while(1);
}
hal_xspi_set_parallel_mode(&xspi->handle, XSPI_PARALLEL_MODE);
return 0;
}