1784 lines
70 KiB
C
1784 lines
70 KiB
C
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
|
/*
|
|
* PSRAM test command for C5 U-Boot.
|
|
* psram_reg.h + psram.h + bl2 driver inlined.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <linux/types.h>
|
|
#include <linux/delay.h>
|
|
#include <command.h>
|
|
#include <vsprintf.h>
|
|
|
|
static void wr_reg(uint32_t base_add, uint32_t dat)
|
|
{
|
|
*(volatile uint32_t *)(((uintptr_t)(0) << 2) + base_add) = (dat);
|
|
}
|
|
|
|
static uint32_t rd_reg(uint32_t base_add)
|
|
{
|
|
return *(volatile uint32_t *)(((uintptr_t)(0) << 2) + base_add);
|
|
}
|
|
|
|
static void psram_uboot_udelay(unsigned int us)
|
|
{
|
|
udelay(us);
|
|
}
|
|
|
|
static void psram_uboot_watchdog_disable(void)
|
|
{
|
|
}
|
|
|
|
#define _udelay(us) psram_uboot_udelay(us)
|
|
#define watchdog_disable() psram_uboot_watchdog_disable()
|
|
|
|
static void psram_serial_puts(const char *s) { printf("%s", s); }
|
|
static void psram_serial_put_dec(unsigned int v) { printf("%u", v); }
|
|
static void psram_serial_put_hex(unsigned int v, int bits) { (void)bits; printf("0x%x", v); }
|
|
static void psram_bl2_print(const char *prefix, unsigned int val, int unused, const char *suffix)
|
|
{
|
|
(void)unused;
|
|
printf("%s%u%s", prefix, val, suffix);
|
|
}
|
|
#define serial_puts(s) psram_serial_puts(s)
|
|
#define serial_put_dec(v) psram_serial_put_dec(v)
|
|
#define serial_put_hex(v,b) psram_serial_put_hex(v,b)
|
|
#define bl2_print(p,v,u,s) psram_bl2_print(p,v,u,s)
|
|
|
|
/* ---------- psram_reg.h ---------- */
|
|
/*
|
|
* Copyright (c) 2025 Amlogic, Inc. All rights reserved.
|
|
*
|
|
* This source code is subject to the terms and conditions defined in the
|
|
* file 'LICENSE' which is part of this source code package.
|
|
*/
|
|
// Reading file: ../psram/rtl/psram_reg.vh
|
|
|
|
//
|
|
// -----------------------------------------------
|
|
// APB_BASE: APB0_BASE_ADDR = 0xfe007400
|
|
// -----------------------------------------------
|
|
//64MB addr: 0xf400_0000 ~ 0xf7ff_ffff
|
|
|
|
#define PADCTRL_GPIOP_I ((0x0020 << 2) + 0xffa04000)
|
|
#define PADCTRL_GPIOP_O ((0x0021 << 2) + 0xffa04000)
|
|
#define PADCTRL_GPIOP_OEN ((0x0022 << 2) + 0xffa04000)
|
|
|
|
#define PADCTRL_PIN_MUX_REGAO_5 ((0x0005 << 2) + 0xffa04000)
|
|
#define PADCTRL_PIN_MUX_REGAO_6 ((0x0006 << 2) + 0xffa04000)
|
|
|
|
#define PADCTRL_GPIOP_DS ((0x0027 << 2) + 0xffa04000)
|
|
#define AO_CLKCTRL_PSRAM_CLK_CTRL ((0x0016 << 2) + 0xffa00000)
|
|
|
|
#define AO_RESETCTRL_RESET0 ((0x0000 << 2) + 0xffa02000)
|
|
#define AO_PWRCTRL_FOCRST0 ((0x0003 << 2) + 0xffa0c000)
|
|
#define PWRCTRL_FOCRST0 ((0x000c << 2) + 0xfe00c000)
|
|
#define PWRCTRL_FOCRST1 ((0x000d << 2) + 0xfe00c000)
|
|
|
|
#define P_PWRCTRL_FOCRST0 (volatile uint32_t *)0xfe00c030
|
|
#define P_PWRCTRL_FOCRST1 (volatile uint32_t *)0xfe00c034
|
|
#define P_PWRCTRL_MEM_PD0 (volatile uint32_t *)0xfe00c040
|
|
#define P_PWRCTRL_MEM_PD1 (volatile uint32_t *)0xfe00c044
|
|
#define P_PWRCTRL_MEM_PD2 (volatile uint32_t *)0xfe00c048
|
|
#define P_PWRCTRL_MEM_PD3 (volatile uint32_t *)0xfe00c04c
|
|
#define P_PWRCTRL_MEM_PD4 (volatile uint32_t *)0xfe00c050
|
|
#define P_PWRCTRL_MEM_PD5 (volatile uint32_t *)0xfe00c054
|
|
#define P_PWRCTRL_MEM_PD6 (volatile uint32_t *)0xfe00c058
|
|
#define P_PWRCTRL_MEM_PD7 (volatile uint32_t *)0xfe00c05c
|
|
#define P_PWRCTRL_MEM_PD8 (volatile uint32_t *)0xfe00c060
|
|
#define P_PWRCTRL_MEM_PD9 (volatile uint32_t *)0xfe00c064
|
|
#define P_PWRCTRL_MEM_PD10 (volatile uint32_t *)0xfe00c068
|
|
#define P_PWRCTRL_MEM_PD11 (volatile uint32_t *)0xfe00c06c
|
|
#define P_PWRCTRL_MEM_PD12 (volatile uint32_t *)0xfe00c070
|
|
#define P_PWRCTRL_MEM_PD13 (volatile uint32_t *)0xfe00c074
|
|
#define P_PWRCTRL_MEM_PD14 (volatile uint32_t *)0xfe00c078
|
|
#define P_PWRCTRL_MEM_PD15 (volatile uint32_t *)0xfe00c07c
|
|
#define P_PWRCTRL_MEM_PD16 (volatile uint32_t *)0xfe00c080
|
|
#define P_PWRCTRL_MEM_PD17 (volatile uint32_t *)0xfe00c084
|
|
#define P_PWRCTRL_MEM_PD18 (volatile uint32_t *)0xfe00c088
|
|
#define P_PWRCTRL_MEM_PD19 (volatile uint32_t *)0xfe00c08c
|
|
#define P_PWRCTRL_MEM_PD20 (volatile uint32_t *)0xfe00c090
|
|
#define P_PWRCTRL_MEM_PD21 (volatile uint32_t *)0xfe00c094
|
|
#define P_PWRCTRL_MEM_PD22 (volatile uint32_t *)0xfe00c098
|
|
#define P_PWRCTRL_MEM_PD23 (volatile uint32_t *)0xfe00c09c
|
|
#define P_PWRCTRL_MEM_PD24 (volatile uint32_t *)0xfe00c0a0
|
|
#define P_PWRCTRL_MEM_PD25 (volatile uint32_t *)0xfe00c0a4
|
|
#define P_PWRCTRL_MEM_PD26 (volatile uint32_t *)0xfe00c0a8
|
|
|
|
#define P_AO_PWRCTRL_FOCRST0 (volatile uint32_t *)0xffa0c00c
|
|
#define P_AO_PWRCTRL_MEM_PD0 (volatile uint32_t *)0xffa0c034
|
|
|
|
|
|
#define PSRAM_AXI_INTF_CTRL ((0x0000 << 2) + 0xffa18000)
|
|
//bit 4 axi interface psram clock domain soft reset. 1 = reset AXI interface. 0 = normal.
|
|
//bit 3 axi interface axi clock domain soft reset. 1 = reset AXI interface. 0 = normal.
|
|
//bit 2 disable axi interface clock. 1 = disable; 0 = enable.
|
|
//bit 1 axi interface auto clock gating enable. 1 = enable; 0 = disable.
|
|
//bit 0 axi interface AXI request enable. 1 = enable. 0 = disable.
|
|
#define PSRAM_DBUF_CTRL ((0x0001 << 2) + 0xffa18000)
|
|
//bit 19. DBUF clock disable. 1: disable dbuf clock. 0: normal working mode.
|
|
//bit 18. DBUF auto clock gating disable. 1: disable auto clock gating feature. 0: use hardware auto clock gating to save power.
|
|
//bit 17. DBUF soft reset. 1: reset DBUF. 0: normal working mode.
|
|
//bit 16. MWRITE_EN. 1 : enable mask write(with DM pin). 0 not enable.
|
|
//bit 15:0 DBUF AGE to write back to PSRAM if DBUF is dirty. but whole DBUF data is not READ to write.(with MWRITE enabled).
|
|
#define PSRAM_DBUF_CTRL1 ((0x0002 << 2) + 0xffa18000)
|
|
//bit 15:0 DBUF AGE to write back to psram if DBUF is dirty and whole DBUF data is ready to write.
|
|
#define PSRAM_APB_CTRL ((0x0003 << 2) + 0xffa18000)
|
|
//7:4 PSRAM PHY register APB secure contrl.
|
|
//bit 7, 1: no secure control. 0 : use bit 4 to match PPROT[0] bit.
|
|
//bit 4. when bit 7 == 0, bit 4 must match PPROT[0] to access.
|
|
//3:0 PCTL_CTRL APB bus control registers secure control.
|
|
//bit 3, 1: no secure control. 0 : use bit 0 to match PPROT[0] bit.
|
|
//bit 0. when bit 3 == 0, bit 0 must match PPROT[0] to access.
|
|
#define PSRAM_SEC_CTRL ((0x0004 << 2) + 0xffa18000)
|
|
//bit 31. ADDRESS security range enable. 1 = enable; 0: disable.
|
|
//if scruity range disabled, but AXI data describe enabled key0 is selected.
|
|
//bit 23 range 7 des key selection 0 : key0; 1: key1;
|
|
//bit 22 range 6 des key selection 0 : key0; 1: key1;
|
|
//bit 21 range 5 des key selection 0 : key0; 1: key1;
|
|
//bit 20 range 4 des key selection 0 : key0; 1: key1;
|
|
//bit 19 range 3 des key selection 0 : key0; 1: key1;
|
|
//bit 18 range 2 des key selection 0 : key0; 1: key1;
|
|
//bit 17 range 1 des key selection 0 : key0; 1: key1;
|
|
//bit 16 range0 des key selection 0 : key0; 1: key1;
|
|
//bit 6. range6 enable: 1: enable; 0 : disable.
|
|
//bit 5. range5 enable: 1: enable; 0 : disable.
|
|
//bit 4. range4 enable: 1: enable; 0 : disable.
|
|
//bit 3. range3 enable: 1: enable; 0 : disable.
|
|
//bit 2. range2 enable: 1: enable; 0 : disable.
|
|
//bit 1. range1 enable: 1: enable; 0 : disable.
|
|
//bit 0. range0 enable: 1: enable; 0 : disable.
|
|
#define PSRAM_DES_PADDING ((0x0005 << 2) + 0xffa18000)
|
|
//bit 31 :0 Padding, with address together to generate describe 64 bits input.
|
|
#define PSRAM_RANGE0_STA ((0x0010 << 2) + 0xffa18000)
|
|
//bit 22 :0.
|
|
//AXI security range 0 start address in unit of 64Byte. related to HADDR bit 28:6.
|
|
#define PSRAM_RANGE0_EDA ((0x0011 << 2) + 0xffa18000)
|
|
//bit 22 :0.
|
|
//AXI security range 0 end address in unit of 64Byte. related to HADDR bit 28:6.
|
|
#define PSRAM_RANGE0_CTRL0 ((0x0012 << 2) + 0xffa18000)
|
|
// AXI security range 0 control.
|
|
#define PSRAM_RANGE0_CTRL1 ((0x0013 << 2) + 0xffa18000)
|
|
// AXI security range 0 control.
|
|
#define PSRAM_RANGE1_STA ((0x0014 << 2) + 0xffa18000)
|
|
//bit 22 :0.
|
|
//AXI security range 1 start address in unit of 64Byte. related to HADDR bit 28:6.
|
|
#define PSRAM_RANGE1_EDA ((0x0015 << 2) + 0xffa18000)
|
|
//bit 22 :0.
|
|
//AXI security range 1 end address in unit of 64Byte. related to HADDR bit 28:6.
|
|
#define PSRAM_RANGE1_CTRL0 ((0x0016 << 2) + 0xffa18000)
|
|
// AXI security range 1 control.
|
|
#define PSRAM_RANGE1_CTRL1 ((0x0017 << 2) + 0xffa18000)
|
|
// AXI security range 1 control.
|
|
#define PSRAM_RANGE2_STA ((0x0018 << 2) + 0xffa18000)
|
|
//bit 31 : 6.
|
|
//AXI security range 2 start address in unit of 64Byte. related to HADDR bit 28:6.
|
|
#define PSRAM_RANGE2_EDA ((0x0019 << 2) + 0xffa18000)
|
|
//bit 31 :6.
|
|
//AXI security range 2 end address in unit of 64Byte. related to HADDR bit 28:6.
|
|
#define PSRAM_RANGE2_CTRL0 ((0x001a << 2) + 0xffa18000)
|
|
#define PSRAM_RANGE2_CTRL1 ((0x001b << 2) + 0xffa18000)
|
|
#define PSRAM_RANGE3_STA ((0x001c << 2) + 0xffa18000)
|
|
//bit 31 : 6.
|
|
//AXI security range 3 start address in unit of 64Byte. related to HADDR bit 28:6.
|
|
#define PSRAM_RANGE3_EDA ((0x001d << 2) + 0xffa18000)
|
|
//bit 31 :6.
|
|
//AXI security range 3 end address in unit of 64Byte. related to HADDR bit 28:6.
|
|
#define PSRAM_RANGE3_CTRL0 ((0x001e << 2) + 0xffa18000)
|
|
// AXI security range 3 control.
|
|
#define PSRAM_RANGE3_CTRL1 ((0x001f << 2) + 0xffa18000)
|
|
// AXI security range 3 control.
|
|
#define PSRAM_RANGE4_STA ((0x0020 << 2) + 0xffa18000)
|
|
//bit 31 :6.
|
|
//AXI security range 4 start address in unit of 64Byte. related to HADDR bit 28:6.
|
|
#define PSRAM_RANGE4_EDA ((0x0021 << 2) + 0xffa18000)
|
|
//bit 31 :6.
|
|
//AXI security range 4 end address in unit of 64Byte. related to HADDR bit 28:6.
|
|
#define PSRAM_RANGE4_CTRL0 ((0x0022 << 2) + 0xffa18000)
|
|
// AXI security range 4 control.
|
|
#define PSRAM_RANGE4_CTRL1 ((0x0023 << 2) + 0xffa18000)
|
|
#define PSRAM_RANGE5_STA ((0x0024 << 2) + 0xffa18000)
|
|
//bit 22 :0.
|
|
//AXI security range 5 start address in unit of 64Byte. related to HADDR bit 28:6.
|
|
#define PSRAM_RANGE5_EDA ((0x0025 << 2) + 0xffa18000)
|
|
//bit 22 :0.
|
|
//AXI security range 5 end address in unit of 64Byte. related to HADDR bit 28:6.
|
|
#define PSRAM_RANGE5_CTRL0 ((0x0026 << 2) + 0xffa18000)
|
|
// AXI security range 5 control.
|
|
#define PSRAM_RANGE5_CTRL1 ((0x0027 << 2) + 0xffa18000)
|
|
// AXI security range 5 control.
|
|
#define PSRAM_RANGE6_STA ((0x0028 << 2) + 0xffa18000)
|
|
//bit 22 :0.
|
|
//AXI security range 6 start address in unit of 64Byte. related to HADDR bit 28:6.
|
|
#define PSRAM_RANGE6_EDA ((0x0029 << 2) + 0xffa18000)
|
|
//bit 22 :0.
|
|
//AXI security range 6 end address in unit of 64Byte. related to HADDR bit 28:6.
|
|
#define PSRAM_RANGE6_CTRL0 ((0x002a << 2) + 0xffa18000)
|
|
// AXI security range 6 control.
|
|
#define PSRAM_RANGE6_CTRL1 ((0x002b << 2) + 0xffa18000)
|
|
// AXI security range 6 control.
|
|
#define PSRAM_RANGE7_CTRL0 ((0x002c << 2) + 0xffa18000)
|
|
#define PSRAM_RANGE7_CTRL1 ((0x002d << 2) + 0xffa18000)
|
|
#define PSRAM_VIO_STATUS ((0x002e << 2) + 0xffa18000)
|
|
//bit 31: security violation. write 1 to clean security violation status.
|
|
//bit 30. 1 : AXI write violation. 0 : axi read violation.
|
|
//bit 18:16. AXI ARPROT/AWPROT>
|
|
//bit 11:0. AXI violation ID.
|
|
#define PSRAM_VIO_ADDR ((0x002f << 2) + 0xffa18000)
|
|
//read only
|
|
//31:0 AXI violation address.
|
|
#define PSRAM_USER_CTRL0 ((0x0080 << 2) + 0xffa18000)
|
|
//bit 31. user request enable. write 1 to enable. read 0, means user command accepted by the SPI_CTRL.
|
|
//bit 30. usr request done. after user command done. this bit set to 1.
|
|
//bit 29. USR COMMAND enable.
|
|
//bit 28. command type0. 1 READ command. 0 write command.
|
|
//bit 27. command type1. 1 for register. 0 : for memory.
|
|
//bit 21~16. USR command clock cycles
|
|
//bit 15~0. USR COMMAND CODE.
|
|
#define PSRAM_USER_CTRL1 ((0x0081 << 2) + 0xffa18000)
|
|
//bit 31. USR_ADDR_EN
|
|
//bit 30:29. USR_ADDR_DW
|
|
//bit 28~20. USR address clock cycle number.
|
|
//bit 19:16 USR data output/input switch position
|
|
//bit 15. USR DUMMY ENABLE
|
|
//bit 13~8. USR DUMMY clock cycles.
|
|
//bit 5:0 USR data DQS read enable position.
|
|
#define PSRAM_USER_CTRL2 ((0x0082 << 2) + 0xffa18000)
|
|
//bit 31 usr des key selection. 1 : key 1; 0 : key 0.
|
|
//bit 30. usr check latency. for Winbond PSRAM data read/write, DQS input identify the latency is doubled or not.
|
|
//bit 29. usr data des enable.
|
|
//bit 28 usr datain enable.
|
|
//bit 27. usr datain destination. 1 : write to CFG_STS register. 0 : write to DATA REGISTERs.
|
|
//bit 26~16 usr data in clock cycle number.
|
|
//bit 15. usr datout enable.
|
|
//bit 14. usr data out source 1 : from CFG_STS register. 0 from DATA register.
|
|
//bit 13~11. not used.
|
|
//bit 10~0. usr dataout clock cycles.
|
|
#define PSRAM_USER_CTRL3 ((0x0083 << 2) + 0xffa18000)
|
|
//bit 17:16. which cycle to ask phy to check read/write latency at PSRAM SEND COMMAND stage.
|
|
//since PSRAM send command stage only 3 clock cycle. So this number only can chose 0, 1, 2.
|
|
//bit 15:0. user dummy data when output in dummy cycle.
|
|
#define PSRAM_USER_ADDR ((0x0084 << 2) + 0xffa18000)
|
|
//bit 31:0. 32bits user address.
|
|
#define PSRAM_AXI_REQ_CTRL0 ((0x0085 << 2) + 0xffa18000)
|
|
//bit 31. AXI request enable.
|
|
//bit 30 AXI cmd_en. command cycle enable.
|
|
//bit 29:24. AXI request command cycle clock numbers.
|
|
//bit 22. AXI request address cycle enable.
|
|
//bit 21:16. AXI request address cycle clock number.
|
|
//bit 15:14. AXI address cycle data width.
|
|
//bit 13:12. at which clock cycle to send signal to phy to check latency flag for WINBOND PSRAM flexible latency.
|
|
//since PSRAM send command stage only 3 clock cycle. So this number only can chose 0, 1, 2.
|
|
//bit 6 // AXI Write dummy enable.
|
|
//bit 5:0 // axi write dummy clock cycle number.
|
|
#define PSRAM_AXI_REQ_CTRL1 ((0x0086 << 2) + 0xffa18000)
|
|
//bit 31:16. AXI request psram READ command code.
|
|
//bit 15:0. AXI request psram write command code.
|
|
#define PSRAM_AXI_REQ_CTRL2 ((0x0087 << 2) + 0xffa18000)
|
|
//bit 31. AXI read request Dummy enable.
|
|
//bit 30. Check latency enable for WINBOND PSRAM flexible latency.
|
|
//bit 27:22. clock cycles in dummy stage to enable PSRAM PHY reading logic.
|
|
//bit 21:16. axi_read dummy clock cycles number.
|
|
//bit 15:0. dummy data if output in dummy cycles.
|
|
#define PSRAM_AXI_REQ_CTRL3 ((0x0088 << 2) + 0xffa18000)
|
|
//bit 31 des enable.
|
|
//bit 26:16. DATA input clock cycles.
|
|
//bit 10:0. DATA output clock cycles.
|
|
#define PSRAM_ACTIMING0 ((0x0089 << 2) + 0xffa18000)
|
|
//bit 31:30. tSLCH
|
|
//bit 29:28 tCLSH
|
|
//bit 20:16 tSHWL
|
|
//bit 15:12 tSHSL2
|
|
//bit 11:8 tSHSL1
|
|
//bit 7:0 tWHSL
|
|
#define PSRAM_ACTIMING1 ((0x008a << 2) + 0xffa18000)
|
|
//bit 7:0 tRWR for winbond PSRAM, = tRWR -3. Winbond PSRAM include one CS cycle and 2 command cycle.
|
|
//for APMEMORY should be same value of tCPH
|
|
#define PSRAM_ACTIMING2 ((0x008b << 2) + 0xffa18000)
|
|
#define PSRAM_WDG_CTRL ((0x008c << 2) + 0xffa18000)
|
|
//bit [31] 1: force to reset PSRAM PCTL and PHY logic. 0: normal.
|
|
//bit [30] 1: automatic reset PSRAM PCTL and PHY logic if watch dog triggered.
|
|
//bit 12:0. watch dog timer. for Winbond PSRAM should be 1us for tRC. for APMEMORY should be 1us for tCEM.
|
|
//SPI DATA BUFFER. There's a total 512KByte + 64byte(organized as 36x128bits) SRAM .
|
|
// since each APB access is 32bits. So we use word address as APB read/write address.
|
|
// But for SPI side we have to use 128bit boundary. That's the first Program/read SPI with data buffer must start at data buffer 128bit boundary. that means the PSRAM_USE_DBUF_ADDR last 2 bits must be 0.
|
|
#define PSRAM_DBUF_0 ((0x0090 << 2) + 0xffa18000)
|
|
#define PSRAM_DBUF_1 ((0x0091 << 2) + 0xffa18000)
|
|
#define PSRAM_DBUF_2 ((0x0092 << 2) + 0xffa18000)
|
|
#define PSRAM_DBUF_3 ((0x0093 << 2) + 0xffa18000)
|
|
#define PSRAM_DBUF_4 ((0x0094 << 2) + 0xffa18000)
|
|
#define PSRAM_DBUF_5 ((0x0095 << 2) + 0xffa18000)
|
|
#define PSRAM_DBUF_6 ((0x0096 << 2) + 0xffa18000)
|
|
#define PSRAM_DBUF_7 ((0x0097 << 2) + 0xffa18000)
|
|
#define PSRAM_DBUF_8 ((0x0098 << 2) + 0xffa18000)
|
|
#define PSRAM_DBUF_9 ((0x0099 << 2) + 0xffa18000)
|
|
#define PSRAM_DBUF_A ((0x009a << 2) + 0xffa18000)
|
|
#define PSRAM_DBUF_B ((0x009b << 2) + 0xffa18000)
|
|
#define PSRAM_DBUF_C ((0x009c << 2) + 0xffa18000)
|
|
#define PSRAM_DBUF_D ((0x009d << 2) + 0xffa18000)
|
|
#define PSRAM_DBUF_E ((0x009e << 2) + 0xffa18000)
|
|
#define PSRAM_DBUF_F ((0x009f << 2) + 0xffa18000)
|
|
#define PSRAM_CFG_STS ((0x00a0 << 2) + 0xffa18000)
|
|
//32bits register to save the USR read command read back values.
|
|
#define PSRAM_STATUS ((0x00a1 << 2) + 0xffa18000)
|
|
//bit 31. usr_req_done flag. 1 : user request done . write 1 to clean.
|
|
//bit 30~11.
|
|
//bit 10:8
|
|
//bit 7:3.
|
|
//bit 2. axi_data buffer idle bit. 1 : idle. 0 : working.
|
|
//bit 1. axi interface idle bit. 1 : idle. 0 : working.
|
|
//bit 0. psram ctrl idle bit. 1 : idle. 0 : working.
|
|
#define PSRAM_CTRL ((0x00a2 << 2) + 0xffa18000)
|
|
//bit 31. PSRAM in DTR mode.
|
|
//bit 30. psram input data latch clock select. 1: from clock input pin. 0: from DQS
|
|
//if use clock input pin as data input latch clock, bit 13:12 should select 01.
|
|
//bit 29:27. PSRAM mode.
|
|
//'b000 : STR SPI mode.
|
|
//'b001 : STR QPI mode.
|
|
//'b010 : DTR QPI mode.
|
|
//'b011 : DTR OPI FLASH.
|
|
//'b100 : APmemory PSRAM mode.
|
|
//'b101 : Winbond PSRAM mode.
|
|
//bit 26. enable to generation interruption after usr request done. 1: enable. 0: disable.
|
|
//bit 25. to enable APMEMORY 2 command cycle mode. 1 : enable : 0: 3 command cycles.
|
|
//bit 24. to enable the psram clock output always enable. 1 : enable. 0: disable.
|
|
//bit 23. to enable the psram clock output extend mode to cover APMEMORY tCPI.
|
|
//bit 22. to disable the CKN output. 1: disable PSRAM CK_N pin output. 0: CK_N working normal.
|
|
//bit 21. PSRAM DATA IN/OUT high 8bit and low 8 bit endian. 1 : rising edge is low byte. falling edge data is high byte. 0 : rising edge is high byte. falling edge data is low byte.
|
|
//bit 20. PSRAM ADDRESS unit. 1: Byte. 0 : word.
|
|
// APMEMORY used byte address. Winbond use word address.
|
|
//bit 19. DQSEN generation. if use dqs to latch input data, this bit should be set to 1 to ask DMC generate ENABLE signal in dummy stage. 0: not generate DQS_EN.
|
|
//bit 18. PSRAM RESET I/O oe_n value. if need RESET pin.
|
|
//bit 17. PSRAM RESET I/O output vale. if need reset pin.
|
|
//bit 16. force CS output low. for APMEMORY exit DPPD mode. 1: to force cs output low : 0 output normal working mode.
|
|
//bit 13:12. psram data in clock enable selection. 00: use DQSEN. 01: use clkin cnt.
|
|
//bit 11. DM Disable. 1: disable DM output. 0: with dmoutput.
|
|
//bit 9. psram pctl auto clock gating enable. 1: enable. 0 : disable.
|
|
//bit 8. psram pctl clock disable. 1: disable. 0 : enable.
|
|
//bit 2 PSRAM SPI mode, DQ2 works as WP(write protection mode).
|
|
//bit 1. DQ2 WP mode value.
|
|
//bit 0. PSRAM SPI mode, DQ3 works as HOLD function.
|
|
#define PSRAM_PIN_CTRL ((0x00a3 << 2) + 0xffa18000)
|
|
//bit 30:28 DATA 6 DQ pin selection.
|
|
//bit 27:24 DATA 6 DQ pin selection.
|
|
//bit 22:20 DATA 5 DQ pin selection.
|
|
//bit 18:16 DATA 4 DQ pin selection.
|
|
//bit 14:12 DATA 3 DQ pin selection.
|
|
//bit 10:8 DATA 2 DQ pin selection.
|
|
//bit 6:4 DATA 1 DQ pin selection.
|
|
//bit 2:0 DATA 0 DQ pin selection.
|
|
//0 : from DQ[0]
|
|
//1 : from DQ[1]
|
|
//2 : from DQ[2]
|
|
//3 : from DQ[3]
|
|
//4 : from DQ[4]
|
|
//5 : from DQ[5]
|
|
//6 : from DQ[6]
|
|
//7 : from DQ[7]
|
|
//psram_dly_16 is used for all DQ[0~] in/out/oen delay adjustment.
|
|
//psram_dly_16 consists of 15 delay cells, one delay cell is 50ps delay( typical corner).
|
|
//psram_dly_16 is control by delay_sel[3:0]. 0 = no delay. 1~15 controls how many delay cells used.
|
|
//psram_dly_16 can be controlled by each control register either with real delay mode or VT updated with 4xclock period.
|
|
//psram_lcdl is used for DQS/DQSN input and CK/CKN output delay 90degree delay generation and/or delay fine tune.
|
|
//psram_lcdl consits of 96 delay cells, same delay cell used in psram_dly_16.
|
|
//psram_lcdl should be calibrated with the psram_4xclock. and tracked with psram_4xclock with VT updated.
|
|
#define PSRAM_DQ0_DIN_DLY ((0x00c0 << 2) + 0xffa18000)
|
|
//bit 31:28. DQ7 DIN delay control. in DLY16 real mode, only [3:0] is valid.
|
|
//bit 27:24. DQ6 DIN delay control. in DLY16 real mode, only [3:0] is valid.
|
|
//bit 23:20. DQ5 DIN delay control. in DLY16 real mode, only [3:0] is valid.
|
|
//bit 19:16. DQ4 DIN delay control. in DLY16 real mode, only [3:0] is valid.
|
|
//bit 15:12. DQ3 DIN delay control. in DLY16 real mode, only [3:0] is valid.
|
|
//bit 11:8. DQ2 DIN delay control. in DLY16 real mode, only [3:0] is valid.
|
|
//bit 7:4. DQ1 DIN delay control. in DLY16 real mode, only [3:0] is valid.
|
|
//bit 3:0. DQ0 DIN delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ1_DIN_DLY ((0x00c1 << 2) + 0xffa18000)
|
|
//bit 6:0. DQ1 input delay control. in DLY16 read mode, only [3:0] is valid.
|
|
#define PSRAM_DQ2_DIN_DLY ((0x00c2 << 2) + 0xffa18000)
|
|
//bit 6:0. DQ2 input delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ3_DIN_DLY ((0x00c3 << 2) + 0xffa18000)
|
|
//bit 6:0. DQ3 input delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ4_DIN_DLY ((0x00c4 << 2) + 0xffa18000)
|
|
//bit 6:0. DQ4 input delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ5_DIN_DLY ((0x00c5 << 2) + 0xffa18000)
|
|
//bit 6:0. DQ5 input delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ6_DIN_DLY ((0x00c6 << 2) + 0xffa18000)
|
|
//bit 6:0. DQ6 input delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ7_DIN_DLY ((0x00c7 << 2) + 0xffa18000)
|
|
//bit 6:0. DQ7 input delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ0_DOUT_DLY ((0x00c8 << 2) + 0xffa18000)
|
|
//bit 6:0. DQ0 DOUT delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ1_DOUT_DLY ((0x00c9 << 2) + 0xffa18000)
|
|
//bit 6:0. DQ1 output delay control. in DLY16 read mode, only [3:0] is valid.
|
|
#define PSRAM_DQ2_DOUT_DLY ((0x00ca << 2) + 0xffa18000)
|
|
//bit 6:0. DQ2 output delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ3_DOUT_DLY ((0x00cb << 2) + 0xffa18000)
|
|
//bit 6:0. DQ3 output delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ4_DOUT_DLY ((0x00cc << 2) + 0xffa18000)
|
|
//bit 6:0. DQ4 output delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ5_DOUT_DLY ((0x00cd << 2) + 0xffa18000)
|
|
//bit 6:0. DQ5 output delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ6_DOUT_DLY ((0x00ce << 2) + 0xffa18000)
|
|
//bit 6:0. DQ6 output delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ7_DOUT_DLY ((0x00cf << 2) + 0xffa18000)
|
|
//bit 6:0. DQ7 output delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ0_OEN_DLY ((0x00d0 << 2) + 0xffa18000)
|
|
//bit 6:0. DQ0 OEN delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ1_OEN_DLY ((0x00d1 << 2) + 0xffa18000)
|
|
//bit 6:0. DQ1 output enable delay control. in DLY16 read mode, only [3:0] is valid.
|
|
#define PSRAM_DQ2_OEN_DLY ((0x00d2 << 2) + 0xffa18000)
|
|
//bit 6:0. DQ2 output enable delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ3_OEN_DLY ((0x00d3 << 2) + 0xffa18000)
|
|
//bit 6:0. DQ3 output enable delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ4_OEN_DLY ((0x00d4 << 2) + 0xffa18000)
|
|
//bit 6:0. DQ4 output enable delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ5_OEN_DLY ((0x00d5 << 2) + 0xffa18000)
|
|
//bit 6:0. DQ5 output enable delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ6_OEN_DLY ((0x00d6 << 2) + 0xffa18000)
|
|
//bit 6:0. DQ6 output enable delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQ7_OEN_DLY ((0x00d7 << 2) + 0xffa18000)
|
|
//bit 6:0. DQ7 output enable delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DM_DOUT_DLY ((0x00d8 << 2) + 0xffa18000)
|
|
//bit 6:0. DM output delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DM_OEN_DLY ((0x00d9 << 2) + 0xffa18000)
|
|
//bit 6:0. DM output enable delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_CS_DOUT_DLY ((0x00da << 2) + 0xffa18000)
|
|
//bit 6:0. CS output delay control. in DLY16 real mode, only [3:0] is valid.
|
|
#define PSRAM_DQS_DIN_DLY ((0x00db << 2) + 0xffa18000)
|
|
//bit 6:0. DQS input delay control. unit = 1/64 UI with PSRAM_LCDL_CTRL bit 28 = 0;
|
|
// unit = 1 delay cell, with PSRAM_LCDL_CTRL bit 28 = 1;
|
|
#define PSRAM_DQSN_DIN_DLY ((0x00dc << 2) + 0xffa18000)
|
|
//bit 6:0. DQSN input delay control. unit = 1/64 UI with PSRAM_LCDL_CTRL bit 28 = 0;
|
|
// unit = 1 delay cell, with PSRAM_LCDL_CTRL bit 28 = 1;
|
|
#define PSRAM_CKN_DOUT_DLY ((0x00dd << 2) + 0xffa18000)
|
|
//bit 6:0. CKN output delay control. unit = 1/64 UI with PSRAM_LCDL_CTRL bit 28 = 0;
|
|
// unit = 1 delay cell, with PSRAM_LCDL_CTRL bit 28 = 1;
|
|
#define PSRAM_CK_DOUT_DLY ((0x00de << 2) + 0xffa18000)
|
|
//bit 6:0. CK output delay control. unit = 1/64 UI with PSRAM_LCDL_CTRL bit 28 = 0;
|
|
// unit = 1 delay cell, with PSRAM_LCDL_CTRL bit 28 = 1;
|
|
#define PSRAM_RDEN_DLY ((0x00df << 2) + 0xffa18000)
|
|
//bit 10:7. READ enable phase delay. unit = 1UI. for AP QPI PSRAM. PSRAM only send one cycle DQS preamble.
|
|
// We have to used this UI delay to compensate the whole clock output delay and the DQS input delay.
|
|
// if run high frequency, this delay need to be trained. the valid value from 0 ~ 12. Since one UI is 1/4 of PSRAM clock,
|
|
// the total delay of the clock output delay + input delay should be less than 3 PSRAM clock.
|
|
//bit 6:0. READ enable fine tune delay control. unit = 1/64 UI with PSRAM_LCDL_CTRL bit 28 = 0;
|
|
// unit = 1 delay cell, with PSRAM_LCDL_CTRL bit 28 = 1;
|
|
#define PSRAM_LCDL_CTRL ((0x00f0 << 2) + 0xffa18000)
|
|
//bit 31. write 1 to update all delay cell delays control.
|
|
//bit 30. write 1 to calibration LCDL.
|
|
//bit 29. LCDL track enable. 1: enable LCDL auto track VT changes.
|
|
//bit 28. LCDL delay control mode.
|
|
//1 : real delay mode. For DQS/DQSN/CKN/CK/RDEN delay control register, one number means one delay cells.
|
|
//0 : UI MODE. For DQS/DQSN/CKN/CK/RDEN delay control register, one number means 1/64 psram_4xclk period.
|
|
//bit 27. DLY16 ( psram_dly_16 cell) delay control mode.
|
|
//1 : real delay mode. For all data delay control register, one number means one delay cells.
|
|
//0 : UI MODE. For all data delay control register, one number means 1/64 psram_4xclk period.
|
|
//bit 27:6. not used.
|
|
//bit 26. to generate clock phase same as data phase.
|
|
//bit 25. enable to extend I/O pin OE one cycle later.
|
|
//bit 24. enable to extend I/O pin OE one cycle earlier.
|
|
//bit 23:0. timer do trigger LCDL track the VT once. each track will compensate the UI with 1/16 delay cell delay.
|
|
//LCDL calibration ctroller.
|
|
#define PSRAM_LCDL_CAL_CTRL1 ((0x00f1 << 2) + 0xffa18000)
|
|
//27:24. which LCDL delay line used to run calibration.
|
|
//19:16. LCDL calibration loop end position.
|
|
//15:12. LCDL calibration loop initial position.
|
|
//10:0. LCDL calibration initial phase counter.
|
|
#define PSRAM_LCDL_CAL_CTRL2 ((0x00f2 << 2) + 0xffa18000)
|
|
//31 cfg_cal_hp
|
|
//26:16 LCDL phase lock limit. if the lcdl phase counter difference between 2 calibration loops is less than this number, The LCDL would be locked and stop the calibration.
|
|
//10:0. deta_init. the first loop phase changing number.
|
|
#define PSRAM_LCDL_CAL_CTRL3 ((0x00f3 << 2) + 0xffa18000)
|
|
//29:25 to configure LCDL calibration step 5 position.
|
|
//24:20 to configure LCDL calibration step 4 position.
|
|
//19:15 to configure LCDL calibration step 3 position.
|
|
//14:10 to configure LCDL calibration step 2 position.
|
|
//9:5 to configure LCDL calibration step 1 position.
|
|
//4:0 to configure LCDL calibration step 0 position.
|
|
#define PSRAM_LCDL_CAL_CTRL4 ((0x00f4 << 2) + 0xffa18000)
|
|
//19:15 to configure LCDL calibration step 9 position.
|
|
//14:10 to configure LCDL calibration step 8 position.
|
|
//9:5 to configure LCDL calibration step 7 position.
|
|
//4:0 to configure LCDL calibration step 6 position.
|
|
#define PSRAM_CLK_UI ((0x00f5 << 2) + 0xffa18000)
|
|
//bit 6:0. 4xCLOCK period delay measured from LCDL calibration.
|
|
#define PSRAM_LCDL_PH ((0x00f6 << 2) + 0xffa18000)
|
|
//10:0 LCDL phase counter after calibration.
|
|
#define PSRAM_LCDL_STATUS ((0x00f7 << 2) + 0xffa18000)
|
|
//bit 31. LCDL lock status. 1: LCDL locked to 4x clock.
|
|
//`endif
|
|
//
|
|
// Closing file: ../psram/rtl/psram_reg.vh
|
|
//
|
|
//
|
|
|
|
|
|
/* ---------- psram.h ---------- */
|
|
|
|
/*
|
|
* Copyright (C) 2019 Amlogic, Inc. All rights reserved.
|
|
*/
|
|
|
|
//#include "../include/timing.h"
|
|
//#include "../include/ddr_define.h"
|
|
//#include <acs.h>
|
|
//#include <fip-v3.h>
|
|
//#include <usb/usb_pcd.h>
|
|
|
|
|
|
#define PSRAM_D2PLL_FUNCTION_MASK_BIT 0
|
|
|
|
#define PSRAM_WINDOW_TEST
|
|
|
|
#define AXI_INTERFACE_SELECT_DDR 1
|
|
#define AXI_INTERFACE_SELECT_PSRAM 2
|
|
|
|
//#define DRIVER_STRENGTH_INEX_SOC_DRIVER 1
|
|
//#define DRIVER_STRENGTH_INEX_PSRAM_WINBOND_DRIVER 2
|
|
//#define DRIVER_STRENGTH_INEX_PSRAM_AP_MEMORY_DRIVER 3
|
|
|
|
#define PSRAM_CHIP_LOGIC_INDEX_SOC 1
|
|
|
|
#define PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W955D8MKY 0x20
|
|
#define PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W956D8MKY 0x21
|
|
#define PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W966D8MKY 0x22
|
|
|
|
#define PSRAM_CHIP_LOGIC_INDEX_AP_MEMORY_3_CMD 0x30
|
|
|
|
#define PSRAM_WRITE_MODE_REGISTER 1 //do not modify sequence
|
|
#define PSRAM_READ_MODE_REGISTER 3 //do not modify sequence
|
|
#define PSRAM_WRITE_MEMORY_DATA 0 //do not modify sequence
|
|
#define PSRAM_READ_MEMORY_DATA 2 //do not modify sequence
|
|
|
|
#define PSRAM_CHIP_LOGIC_INDEX_AP_MEMORY_3_CMD_MR1 0x8d
|
|
#define PSRAM_CHIP_LOGIC_INDEX_AP_MEMORY_3_CMD_MR2 0x93
|
|
|
|
#define PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W955D8MKY_MR0 0x5f
|
|
#define PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W956D8MKY_MR0 0x86
|
|
#define PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W966D8MKY_MR0 0x96
|
|
|
|
typedef struct psram_set {
|
|
unsigned int magic;
|
|
unsigned int board_id;
|
|
/* align8 */
|
|
unsigned int version;
|
|
unsigned char psram_mr[12];
|
|
/* align8 */
|
|
unsigned char psram_board_mask;
|
|
unsigned char psram_amlogic_protocol_id;
|
|
unsigned char psram_test_function[2];
|
|
unsigned char psram_vendor_id;
|
|
unsigned char psram_device_id;
|
|
unsigned char psram_soc_drv;
|
|
unsigned char psram_dram_drv;
|
|
/* align8 */
|
|
unsigned int psram_ac_timing0;
|
|
unsigned int psram_ac_timing1;
|
|
unsigned int psram_ac_timing2;
|
|
unsigned int psram_mode_crtl;
|
|
/* align8 */
|
|
unsigned short psram_frequency;
|
|
unsigned short psram_size;
|
|
unsigned int psram_mode_crtl_bl33;
|
|
unsigned int psram_pin_crtl;
|
|
unsigned int psram_lcd_ctrl;
|
|
/* align8 */
|
|
unsigned char psram_pin_dq_in_delay[8];
|
|
unsigned char psram_pin_dq_out_delay[8];
|
|
unsigned char psram_pin_dq_out_oe_delay[8];
|
|
/* align8 */
|
|
unsigned char psram_pin_dm_out_delay;
|
|
unsigned char psram_pin_dm_out_oe_delay;
|
|
unsigned char psram_pin_cs_out_delay;
|
|
unsigned char psram_pin_dqsp_in_delay;
|
|
unsigned char psram_pin_dqsn_in_delay;
|
|
unsigned char psram_pin_ckp_out_delay;
|
|
unsigned char psram_pin_ckn_out_delay;
|
|
/* align8 */
|
|
unsigned char psram_pin_rden_delay;
|
|
unsigned char psram_bdlr_delay;
|
|
unsigned char psram_reserve[6];
|
|
|
|
/* pls check alignment of each variable */
|
|
}__attribute__ ((packed)) psram_set_t;
|
|
|
|
typedef struct psram_bl2_set{
|
|
uint16_t psram_mr[12];
|
|
uint32_t psram_ac_timing0;
|
|
uint32_t psram_ac_timing1;
|
|
uint32_t psram_ac_timing2;
|
|
uint32_t psram_mode_crtl;
|
|
uint32_t psram_cur_clk_frequency;
|
|
char psram_cur_amlogic_protocol_id;
|
|
char psram_use_hifi_pll;
|
|
char psram_fixed_latency_enable;
|
|
char psram_initial_latency;
|
|
char psram_cmd_cycle;
|
|
char psram_enable_data_mask;
|
|
char psram_user_cmd_code_read_register;
|
|
char psram_user_cmd_code_write_register;
|
|
char psram_user_cmd_code_read_memory;
|
|
char psram_user_cmd_code_write_memory;
|
|
uint32_t axi_req_ctrl0;
|
|
uint32_t axi_req_ctrl1;
|
|
uint32_t axi_req_ctrl2;
|
|
uint32_t user_ctrl0;
|
|
uint32_t user_ctrl1;
|
|
uint32_t user_ctrl2;
|
|
uint32_t user_ctrl3;
|
|
uint32_t psram_ctrl;
|
|
}psram_bl2_set_t;
|
|
|
|
typedef struct psram_bl33_set{
|
|
char psram_board_mask;
|
|
char psram_amlogic_protocol_id;
|
|
char psram_test_function[2];
|
|
char psram_vendor_id;
|
|
char psram_device_id;
|
|
uint16_t psram_frequency;
|
|
uint16_t psram_dram_size;
|
|
char psram_soc_drv;
|
|
char psram_dram_drv;
|
|
uint32_t psram_mode_crtl_bl33;
|
|
uint32_t psram_pin_crtl;
|
|
uint32_t psram_lcd_ctrl;
|
|
char psram_pin_dq_in_delay[8];
|
|
char psram_pin_dq_out_delay[8];
|
|
char psram_pin_dq_out_oe_delay[8];
|
|
char psram_pin_dm_out_delay;
|
|
char psram_pin_dm_out_oe_delay;
|
|
char psram_pin_cs_out_delay;
|
|
char psram_pin_dqsp_in_delay;
|
|
char psram_pin_dqsn_in_delay;
|
|
char psram_pin_ckp_out_delay;
|
|
char psram_pin_ckn_out_delay;
|
|
char psram_pin_rden_delay;
|
|
char psram_bdlr_delay;
|
|
char psram_reserver[7];
|
|
}psram_psram_dev_t;
|
|
|
|
|
|
|
|
/* ---------- psram driver ---------- */
|
|
psram_bl2_set_t *psram_bl2_set_p = {0};
|
|
//psram_psram_dev_t p_dev;
|
|
psram_set_t *psram_p_dev_p = {0};
|
|
psram_bl2_set_t psram_bl2_set_p_t = {.psram_ac_timing0 = 0,};
|
|
psram_set_t psram_p_dev_p_t = {.psram_board_mask = 0,};
|
|
uint32_t sram_test_base = 0xf4000000;//64MB
|
|
|
|
#define P_AO_RESETCTRL_RESET0_LEVEL (volatile uint32_t *)0xffa02004
|
|
#define PSRAM_FREQUENCY_TEST_INDEX (1 << 0)
|
|
#define PSRAM_WINDOW_TEST_INDEX (1 << 1)
|
|
|
|
void psram_init_pin(psram_set_t *psram_p_dev);
|
|
char psram_init_winbond(psram_set_t *psram_p_dev);
|
|
char psram_init_ap(psram_set_t *psram_p_dev);
|
|
void psram_re_init(psram_set_t *psram_p_dev);
|
|
void psram_frequency_test(psram_set_t *psram_p_dev);
|
|
void psram_window_test(psram_set_t *psram_p_dev);
|
|
char psram_uboot_drv_init(void);
|
|
psram_set_t *psram_uboot_get_dev(void);
|
|
|
|
static void psram_config_axi_interface(uint32_t ctrl3, uint32_t ctrl2, uint32_t ctrl1, uint32_t ctrl0) {
|
|
wr_reg(PSRAM_AXI_REQ_CTRL3, ctrl3);
|
|
wr_reg(PSRAM_AXI_REQ_CTRL2, ctrl2);
|
|
wr_reg(PSRAM_AXI_REQ_CTRL1, ctrl1);
|
|
wr_reg(PSRAM_AXI_REQ_CTRL0, ctrl0);
|
|
wr_reg(PSRAM_DBUF_CTRL, (1 << 16) | 0x100);
|
|
wr_reg(PSRAM_DBUF_CTRL1, 0x100);
|
|
wr_reg(PSRAM_AXI_INTF_CTRL, 0x3);
|
|
}
|
|
|
|
static int psram_find_ap_freq_index(uint32_t frequency) {
|
|
static const uint16_t ap_freqs[] = {250, 225, 200, 166, 133, 109, 66};
|
|
int i = 0;
|
|
for (; i < 7; i++) {
|
|
if (frequency >= ap_freqs[i]) break;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
static void psram_send_user_cmd(uint32_t addr, uint32_t data, uint32_t ctrl3, uint32_t ctrl2, uint32_t ctrl1, uint32_t ctrl0) {
|
|
wr_reg(PSRAM_CFG_STS, data);
|
|
wr_reg(PSRAM_USER_ADDR, addr);
|
|
wr_reg(PSRAM_USER_CTRL3, ctrl3);
|
|
wr_reg(PSRAM_USER_CTRL2, ctrl2);
|
|
wr_reg(PSRAM_USER_CTRL1, ctrl1);
|
|
wr_reg(PSRAM_USER_CTRL0, ctrl0);
|
|
}
|
|
|
|
static void psram_ap_write_mr(uint32_t addr, uint32_t val) {
|
|
psram_send_user_cmd(addr, val, 0, 0xc001, 0, 0xa003c0c0);
|
|
}
|
|
|
|
static void psram_ap_read_mr(uint32_t addr, uint32_t latency) {
|
|
psram_send_user_cmd(addr, 0, 0, 0x18010000, 0x8000 | (latency << 8) | (latency - 2), 0xf0034040);
|
|
}
|
|
|
|
static void psram_wb_write_reg(uint32_t addr, uint32_t data) {
|
|
psram_send_user_cmd(addr, data, 0x20000, 0xc001, 0, 0xa8030000);
|
|
}
|
|
|
|
static void psram_wait_user_cmd(void) {
|
|
while (((rd_reg(PSRAM_USER_CTRL0) >> 30) & 1) == 0);
|
|
}
|
|
|
|
static void psram_wait_status_ready(void) {
|
|
while ((rd_reg(PSRAM_STATUS) & 0x80000000) != 0x80000000);
|
|
}
|
|
|
|
static void psram_setup_pads(psram_set_t *psram_p_dev) {
|
|
psram_init_pin(psram_p_dev);
|
|
if (psram_p_dev->psram_amlogic_protocol_id == PSRAM_CHIP_LOGIC_INDEX_AP_MEMORY_3_CMD) {
|
|
wr_reg(PADCTRL_PIN_MUX_REGAO_5, 0x11111110);
|
|
wr_reg(PADCTRL_GPIOP_OEN, rd_reg(PADCTRL_GPIOP_OEN) & 0xfffffffe);
|
|
wr_reg(PADCTRL_GPIOP_O, rd_reg(PADCTRL_GPIOP_O) & 0xfffffffe); //set clk n to level 0
|
|
}
|
|
}
|
|
|
|
static char psram_detect_ap_size(psram_set_t *psram_p_dev) {
|
|
if ((psram_p_dev->psram_mr[1] & 0x1f) == (PSRAM_CHIP_LOGIC_INDEX_AP_MEMORY_3_CMD_MR1 & 0x1f)) {
|
|
switch (psram_p_dev->psram_mr[2]) {
|
|
case 0x91: psram_p_dev->psram_size = 4; break;
|
|
case 0x93: psram_p_dev->psram_size = 8; break;
|
|
case 0x95: psram_p_dev->psram_size = 16; break;
|
|
case 0x97: psram_p_dev->psram_size = 32; break;
|
|
case 0xc7: psram_p_dev->psram_size = 64; break;
|
|
default: break;
|
|
}
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#define ENABLE_WINBOND_PSRAM_PXP_DEBUG 1
|
|
|
|
//#define ENABLE_PSRAM_GET_AP_EID
|
|
#define ENABLE_PSRAM_EXTRA_TEST
|
|
char psram_calculate_drv(char chip_logic_index, unsigned char driver_strength_value) {
|
|
if (chip_logic_index == PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W956D8MKY) {
|
|
return (driver_strength_value > 114) ? 1 :
|
|
(driver_strength_value > 0) ? (134 / driver_strength_value) : 0;
|
|
}
|
|
if (chip_logic_index == PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W966D8MKY) {
|
|
return (driver_strength_value > 114) ? 1 :
|
|
(driver_strength_value > 0) ? (134 / driver_strength_value) : 0;
|
|
}
|
|
if (chip_logic_index == PSRAM_CHIP_LOGIC_INDEX_SOC) {
|
|
if (driver_strength_value > 240) return 0;
|
|
if (driver_strength_value > 60) return 1;
|
|
return (driver_strength_value > 50) ? 2 : 3;
|
|
}
|
|
if (driver_strength_value > 150) return 3;
|
|
if (driver_strength_value > 75) return 2;
|
|
char limit = (chip_logic_index == PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W955D8MKY) ? 42 : 38;
|
|
if (chip_logic_index == PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W955D8MKY) {
|
|
return (driver_strength_value > limit) ? 0 : 1;
|
|
}
|
|
return (driver_strength_value > limit) ? 1 : 0;
|
|
}
|
|
|
|
char psram_calculate_latency(char chip_logic_index, uint32_t psram_frequency) {
|
|
if (chip_logic_index == PSRAM_CHIP_LOGIC_INDEX_AP_MEMORY_3_CMD) {
|
|
return 10 - psram_find_ap_freq_index(psram_frequency);
|
|
}
|
|
if (chip_logic_index == PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W966D8MKY)
|
|
chip_logic_index = PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W956D8MKY;
|
|
char limit = (chip_logic_index == PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W956D8MKY) ? 85 : 66;
|
|
if (psram_frequency > 166)
|
|
return (chip_logic_index == PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W956D8MKY) ? 7 : 6;
|
|
if (psram_frequency > 133) return 6;
|
|
if (psram_frequency > 104) return 5;
|
|
if (psram_frequency > limit) return 4;
|
|
return 3;
|
|
}
|
|
|
|
char psram_calculate_wl_latency(char chip_logic_index, uint32_t psram_frequency) {
|
|
if (chip_logic_index == PSRAM_CHIP_LOGIC_INDEX_AP_MEMORY_3_CMD) {
|
|
return psram_calculate_latency(chip_logic_index, psram_frequency) + 4;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void psram_init_pin(psram_set_t *psram_p_dev) {
|
|
uint32_t gpio_drv = 0;
|
|
|
|
// Set GPIO PAD0/PAD3 low before enabling mux to avoid IO model warning
|
|
wr_reg(PADCTRL_GPIOP_OEN, 0);
|
|
wr_reg(PADCTRL_GPIOP_O, 0);
|
|
|
|
_udelay(1);
|
|
wr_reg(PADCTRL_PIN_MUX_REGAO_5, 0x11111111);
|
|
wr_reg(PADCTRL_PIN_MUX_REGAO_6, 0x11111);
|
|
if (psram_p_dev->psram_pin_crtl == 0)
|
|
psram_p_dev->psram_pin_crtl = 0x76543210;
|
|
wr_reg(PSRAM_PIN_CTRL, psram_p_dev->psram_pin_crtl);
|
|
gpio_drv = psram_calculate_drv(PSRAM_CHIP_LOGIC_INDEX_SOC,
|
|
psram_p_dev->psram_soc_drv);
|
|
gpio_drv = (gpio_drv * 0x01555555);
|
|
wr_reg(PADCTRL_GPIOP_DS, gpio_drv);
|
|
}
|
|
|
|
void psram_reset_psram(char chip_logic_index) {
|
|
//if((PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD==chip_logic_index)
|
|
//||(PSRAM_CHIP_LOGIC_INDEX_AP_MEMORY_3_CMD==chip_logic_index))
|
|
// enable PSRAM RESET_N pin
|
|
uint32_t data32 = 0;
|
|
wr_reg(PSRAM_CTRL,(data32) | ((1 << 17)));
|
|
_udelay(1);
|
|
wr_reg(PSRAM_CTRL, (data32) & (~ (1 << 17)));
|
|
//wr_reg(PSRAM_CTRL,(data32)|(( 1 << 17)) );
|
|
//wait 150us for PSRAM stable.
|
|
_udelay(150);
|
|
wr_reg(PSRAM_CTRL,(data32) | ((1 << 17)));
|
|
//wr_reg(PSRAM_CTRL, (data32)&(~ ( 1 << 17)) );
|
|
}
|
|
|
|
char psram_lcdl_calibration(void) {
|
|
//LCDL calibration
|
|
uint32_t data32;
|
|
//uint32_t loop_count = 100;
|
|
|
|
//serial_puts("psram debug-4-1-1");
|
|
wr_reg(PSRAM_LCDL_CTRL, 0);
|
|
wr_reg(PSRAM_LCDL_CAL_CTRL2, (2 << 16) | 40);
|
|
wr_reg(PSRAM_LCDL_CAL_CTRL1, 0 | (0 << 12) | (4 << 16) | (0 << 24));
|
|
wr_reg(PSRAM_LCDL_CTRL, 1 << 30);
|
|
//serial_puts("\npxp turn off dll calibration");
|
|
|
|
while (rd_reg(PSRAM_LCDL_STATUS) != 0x80000000);
|
|
data32 = rd_reg(PSRAM_CLK_UI);
|
|
serial_puts("CAL RESULT: 1 4xclock period = delay cells ");
|
|
serial_put_hex(data32, 32);
|
|
data32 = rd_reg(PSRAM_CTRL);
|
|
serial_puts("\nPSRAM_CTRL reg = ");
|
|
serial_put_hex(data32, 32);
|
|
|
|
|
|
//config DQS din phase.
|
|
// wr_reg(PSRAM_DQS_DIN_DLY, 64); //1 4xclock period.
|
|
// wr_reg(PSRAM_DQSN_DIN_DLY, 64); //1 4xclock period.
|
|
//wr_reg(PSRAM_DQS_DIN_DLY, 32); //1 2xclock period.
|
|
//wr_reg(PSRAM_DQSN_DIN_DLY, 32); //1 2xclock period.
|
|
wr_reg(PSRAM_LCDL_CTRL, 1 << 31); //update LCDL setting.
|
|
wr_reg(PSRAM_LCDL_CTRL, 0x20001000 | (3 << 24)); //enable LCDL tracking.
|
|
|
|
//#if ENABLE_WINBOND_PSRAM_PXP_DEBUG
|
|
// loop_count = 10;
|
|
//#else
|
|
// loop_count = 100;
|
|
//#endif
|
|
// do {
|
|
// if (Rd(PSRAM_LCDL_STATUS) & 0x80000000)
|
|
// break;
|
|
// } while(loop_count--);
|
|
// data32 = Rd(PSRAM_CLK_UI);
|
|
// serial_puts("CAL RESULT: 1 4xclock period = delay cells\n");
|
|
// serial_put_hex(data32, 32);
|
|
return data32;
|
|
}
|
|
|
|
static uint32_t pack_delay_value(const uint8_t *delay_arr) {
|
|
uint32_t val = 0;
|
|
for (int i = 0; i < 8; i++) {
|
|
val |= ((uint32_t)delay_arr[i] & 0xf) << (i * 4);
|
|
}
|
|
return val;
|
|
}
|
|
|
|
void psram_config_phy_delay(psram_set_t *psram_p_dev) {
|
|
if (psram_p_dev->psram_pin_dqsp_in_delay == 0)
|
|
psram_p_dev->psram_pin_dqsp_in_delay = 32;
|
|
|
|
wr_reg(PSRAM_DQ0_DIN_DLY, pack_delay_value(psram_p_dev->psram_pin_dq_in_delay));
|
|
wr_reg(PSRAM_DQ0_DOUT_DLY, pack_delay_value(psram_p_dev->psram_pin_dq_out_delay));
|
|
wr_reg(PSRAM_DQ0_OEN_DLY, pack_delay_value(psram_p_dev->psram_pin_dq_out_oe_delay));
|
|
|
|
wr_reg((PSRAM_DM_DOUT_DLY), (psram_p_dev->psram_pin_dm_out_delay));
|
|
wr_reg((PSRAM_DM_OEN_DLY), (psram_p_dev->psram_pin_dm_out_oe_delay));
|
|
wr_reg((PSRAM_CS_DOUT_DLY), (psram_p_dev->psram_pin_cs_out_delay));
|
|
wr_reg((PSRAM_DQS_DIN_DLY), (psram_p_dev->psram_pin_dqsp_in_delay));
|
|
wr_reg((PSRAM_DQSN_DIN_DLY), (psram_p_dev->psram_pin_dqsp_in_delay));
|
|
wr_reg((PSRAM_CK_DOUT_DLY), (psram_p_dev->psram_pin_ckp_out_delay));
|
|
wr_reg((PSRAM_CKN_DOUT_DLY), (psram_p_dev->psram_pin_ckp_out_delay));
|
|
wr_reg((PSRAM_RDEN_DLY), (psram_p_dev->psram_pin_rden_delay));
|
|
}
|
|
|
|
#if 0
|
|
unsigned int ddr_test_single_addr(unsigned int addr, unsigned int value)
|
|
{
|
|
addr = ((addr >> 2) << 2);
|
|
serial_puts("ddr test:\n");
|
|
serial_puts("write test: write[0x");
|
|
serial_put_hex(addr, 32);
|
|
serial_puts("]=0x");
|
|
serial_put_hex(value, 32);
|
|
serial_puts("...");
|
|
serial_puts("\n");
|
|
wr_reg(addr, value);
|
|
|
|
|
|
unsigned int count = 0;
|
|
|
|
//for(unsigned int count=0;count<0x10;){
|
|
|
|
serial_puts("read[0x");
|
|
serial_put_hex(addr + count, 32);
|
|
serial_puts("]=0x");
|
|
serial_put_hex(rd_reg(addr + count), 32);
|
|
serial_puts("\n");
|
|
//count=count+4;}
|
|
if (value != rd_reg(addr))
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
char psram_test(uint32_t test_size) {
|
|
////test psram add and data size
|
|
sram_test_base = 0xf4000000;//64MB
|
|
//ddr_test_single_addr(sram_test_base + 0x00000000, 0x12345678);
|
|
//ddr_test_single_addr(sram_test_base + 0x00000004, 0x11223344);
|
|
//ddr_test_single_addr(sram_test_base + 0x00000008, 0x55667788);
|
|
//ddr_test_single_addr(sram_test_base + 0x0000000c, 0x33ccddee);
|
|
//ddr_test_single_addr(sram_test_base + 0x00000010, 0x7788aabb);
|
|
#if 1
|
|
uint32_t test_fail = 0;
|
|
unsigned long i = 0;
|
|
unsigned long repeat = 0;
|
|
unsigned long repeat_max = 1;
|
|
|
|
watchdog_disable();
|
|
//serial_puts("\nwrite test");
|
|
for (repeat = 0; repeat < repeat_max; repeat++) {
|
|
for (i = sram_test_base; i < (sram_test_base + test_size);) {
|
|
wr_reg(i, (i >> 2));
|
|
if (i % 0x10000 == 0) {
|
|
serial_puts("\r");
|
|
serial_put_hex(i, 32);
|
|
}
|
|
i = i + 4;
|
|
}
|
|
}
|
|
//serial_puts("\nread test");
|
|
for (repeat = 0; repeat < repeat_max; repeat++) {
|
|
for (i = sram_test_base; i < (sram_test_base + test_size);) {
|
|
//wr_reg(i, (i>>2));
|
|
if (i % 0x10000 == 0) {
|
|
serial_puts("\r");
|
|
serial_put_hex(i, 32);
|
|
serial_puts(" ");
|
|
serial_put_hex(rd_reg(i), 32);
|
|
}
|
|
if ((rd_reg(i)) != (i >> 2)) {
|
|
#if 0
|
|
serial_puts("\nadd 0x");
|
|
serial_put_hex(i, 32);
|
|
serial_puts(" data ");
|
|
serial_put_hex(rd_reg(i), 32);
|
|
serial_puts(" ");
|
|
#endif
|
|
test_fail++;
|
|
//return test_fail;
|
|
}
|
|
i = i + 4;
|
|
}
|
|
}
|
|
serial_puts("\npsram test error ==");
|
|
serial_put_dec(test_fail);
|
|
return test_fail;
|
|
#endif
|
|
}
|
|
|
|
uint32_t psram_pll_init(psram_set_t *psram_p_dev) {
|
|
uint32_t freq = (psram_p_dev->psram_frequency);
|
|
serial_puts("\npsram freq==");
|
|
serial_put_dec(freq);
|
|
serial_puts("\n");
|
|
//if ( (freq != 192) && (freq != 128) && (freq != 32)) {
|
|
/* todo, hifi pll init here */
|
|
// hifi_pll_init(freq << 3);
|
|
//CONFIG PSRAM CLOCK.
|
|
if (freq <= 12) //12MHz psram clk
|
|
wr_reg(AO_CLKCTRL_PSRAM_CLK_CTRL, (1 << 8) | (0 << 9) | 0); //rtc_oscin_clk 24Mhz
|
|
else if (freq <= 100)
|
|
wr_reg(AO_CLKCTRL_PSRAM_CLK_CTRL, (1 << 8) | (1 << 9) | 1); //fix_div5/2 = 200MHz
|
|
else if (freq <= 166)
|
|
wr_reg(AO_CLKCTRL_PSRAM_CLK_CTRL, (1 << 8) | (3 << 9) | 1); //fix_div3/2 = 333MHz
|
|
else if (freq <= 200)
|
|
wr_reg(AO_CLKCTRL_PSRAM_CLK_CTRL, (1 << 8) | (1 << 9) | 0); //fix_div5 = 400MHz
|
|
else if (freq <= 250)
|
|
wr_reg(AO_CLKCTRL_PSRAM_CLK_CTRL, (1 << 8) | (2 << 9) | 0); //fix_div4 = 500MHz
|
|
else //166Mhz
|
|
wr_reg(AO_CLKCTRL_PSRAM_CLK_CTRL, (1 << 8) | (3 << 9) | 1); //fix_div3/2 = 333MHz
|
|
//wr_reg(AO_CLKCTRL_PSRAM_CLK_CTRL, 1 | (3 << 9) | (1 << 8));
|
|
//fix_div3/2 = 333MHz //for 2x_clk
|
|
//}
|
|
//else {
|
|
// /* config clk ctrl */
|
|
// wr_reg(AO_CLKCTRL_PSRAM_CLK_CTRL, get_ram_clk_ctrl(freq << 2));
|
|
// /* enable clk */
|
|
// wr_reg(AO_CLKCTRL_PSRAM_CLK_CTRL, rd_reg(AO_CLKCTRL_PSRAM_CLK_CTRL) | (1 << 8));
|
|
//}
|
|
return 0;
|
|
}
|
|
|
|
/* AO reset pulse before PHY bring-up (AP path) */
|
|
static void psram_ao_reset_pulse(void)
|
|
{
|
|
*P_AO_RESETCTRL_RESET0_LEVEL &= ~(1 << 30);
|
|
_udelay(1);
|
|
*P_AO_RESETCTRL_RESET0_LEVEL |= (1 << 30);
|
|
_udelay(1);
|
|
_udelay(1);
|
|
_udelay(1);
|
|
}
|
|
|
|
#define PSRAM_BRINGUP_PRE_UDELAY (1u << 0)
|
|
#define PSRAM_BRINGUP_AO_RESET (1u << 1)
|
|
#define PSRAM_BRINGUP_PHY_DELAY (1u << 2)
|
|
#define PSRAM_BRINGUP_POST_UDELAY10 (1u << 3)
|
|
|
|
/* LCDL cal + pad mux + device reset */
|
|
static void psram_init_cal_pads_reset(psram_set_t *psram_p_dev)
|
|
{
|
|
psram_lcdl_calibration();
|
|
psram_setup_pads(psram_p_dev);
|
|
psram_reset_psram(psram_p_dev->psram_amlogic_protocol_id);
|
|
}
|
|
|
|
/* PLL/APB/LCDL bring-up; flags select AP vs Winbond differences */
|
|
static void psram_init_hw_bringup(psram_set_t *psram_p_dev, unsigned char flags)
|
|
{
|
|
//if (flags & PSRAM_BRINGUP_PRE_UDELAY) {
|
|
// _udelay(1);
|
|
// _udelay(1);
|
|
//}
|
|
//if (flags & PSRAM_BRINGUP_AO_RESET)
|
|
psram_ao_reset_pulse();
|
|
_udelay(1);
|
|
psram_pll_init(psram_p_dev);
|
|
_udelay(1);
|
|
//if (flags & PSRAM_BRINGUP_PHY_DELAY)
|
|
psram_config_phy_delay(psram_p_dev);
|
|
_udelay(1);
|
|
wr_reg(PSRAM_APB_CTRL, 0x99);
|
|
//if (flags & PSRAM_BRINGUP_POST_UDELAY10)
|
|
_udelay(10);
|
|
psram_init_cal_pads_reset(psram_p_dev);
|
|
_udelay(1);
|
|
}
|
|
|
|
/* PSRAM_CTRL / ACTIMING / LCDL after device reset */
|
|
static void psram_init_phy_regs(unsigned char chip_id)
|
|
{
|
|
wr_reg(PSRAM_ACTIMING0, (1 << 28));
|
|
if (chip_id == PSRAM_CHIP_LOGIC_INDEX_AP_MEMORY_3_CMD) {
|
|
wr_reg(PSRAM_CTRL, (0 << 24) | (1 << 17) | (1 << 31) | (0 << 30) |
|
|
(1 << 20) | (1 << 21) | (1 << 22) | (4 << 27) | (0 << 9));
|
|
wr_reg(PSRAM_ACTIMING1, 4);
|
|
//wr_reg(PSRAM_DQS_DIN_DLY, 32);
|
|
//wr_reg(PSRAM_DQSN_DIN_DLY, 32);
|
|
//wr_reg(PSRAM_LCDL_CTRL, (1 << 31) | (3 << 24));
|
|
//wr_reg(PSRAM_LCDL_CTRL, (1 << 29) | 0x1000 | (3 << 24));
|
|
} else {
|
|
wr_reg(PSRAM_CTRL, (1 << 31) | (5 << 27) | (1 << 9) | (1 << 17) | (1 << 22));
|
|
wr_reg(PSRAM_CTRL, (1 << 31) | (5 << 27) | (1 << 9) | (1 << 17) | (0 << 22));
|
|
wr_reg(PSRAM_ACTIMING1, 5);
|
|
}
|
|
wr_reg(PSRAM_LCDL_CTRL, 1 << 31);
|
|
wr_reg(PSRAM_LCDL_CTRL, 0x20001000 | (3 << 24));
|
|
}
|
|
|
|
void psram_re_init(psram_set_t *psram_p_dev) {
|
|
switch (psram_p_dev->psram_amlogic_protocol_id) {
|
|
case PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W955D8MKY:
|
|
case PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W956D8MKY:
|
|
case PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W966D8MKY:
|
|
psram_init_winbond(psram_p_dev);
|
|
break;
|
|
case PSRAM_CHIP_LOGIC_INDEX_AP_MEMORY_3_CMD:
|
|
psram_init_ap(psram_p_dev);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
#ifdef PSRAM_WINDOW_TEST
|
|
#if 1
|
|
void psram_window_test(psram_set_t *psram_p_dev) {
|
|
uint32_t write_read_dqs[2][3] = {{0,0,0,}, {0,0,0,}};
|
|
unsigned count_i = 0;
|
|
unsigned count = 0;
|
|
char count_far_fail = 0;
|
|
char count_near_ok = 0;
|
|
char test_fail = 0;
|
|
unsigned clk_org = 0;
|
|
unsigned test_size_min = (1 << 15);
|
|
unsigned test_size = (4 << 19);
|
|
unsigned long reg_add = 0;
|
|
clk_org = rd_reg(PSRAM_CK_DOUT_DLY);
|
|
unsigned count_j = 0;
|
|
for (count_i = 0; count_i < 2; count_i++) {
|
|
uint32_t *dqs = write_read_dqs[count_i];
|
|
if (count_i == 0)
|
|
reg_add = PSRAM_DQS_DIN_DLY;
|
|
else
|
|
reg_add = PSRAM_CKN_DOUT_DLY;
|
|
|
|
count = rd_reg(reg_add);
|
|
dqs[0] = count;
|
|
dqs[1] = 0;
|
|
dqs[2] = 96;
|
|
for (count_j = 0; count_j < 2; count_j++) {
|
|
count_near_ok = dqs[0];
|
|
if (count_j == 0) {
|
|
count_far_fail = dqs[1];
|
|
if (count_i == 1) {
|
|
wr_reg(PSRAM_CKN_DOUT_DLY, 64 + clk_org);
|
|
wr_reg(PSRAM_CK_DOUT_DLY, 64 + clk_org);
|
|
wr_reg(PSRAM_LCDL_CTRL, 0x20001000 | (3 << 24) | (1 << 26));
|
|
wr_reg(PSRAM_LCDL_CTRL, 0x20001000 | (3 << 24) | (1 << 26) | (1 << 31));
|
|
count = rd_reg(reg_add);
|
|
dqs[0] = count;
|
|
count_near_ok = dqs[0];
|
|
}
|
|
}
|
|
else {
|
|
count_far_fail = dqs[2];
|
|
if (count_i == 1) {
|
|
count = rd_reg(reg_add);
|
|
dqs[0] = count;
|
|
count_near_ok = dqs[0];
|
|
}
|
|
}
|
|
while (1) {
|
|
count = ((count_far_fail + count_near_ok) >> 1);
|
|
wr_reg(reg_add, count);
|
|
wr_reg(reg_add + 4, count);
|
|
if ((count_i == 1) && (count_j == 0)) {
|
|
wr_reg(PSRAM_LCDL_CTRL, 0x20001000 | (3 << 24) | (1 << 26));
|
|
}
|
|
wr_reg(PSRAM_LCDL_CTRL, (rd_reg(PSRAM_LCDL_CTRL)) | (1 << 31));
|
|
test_fail = psram_test(test_size_min);
|
|
if (test_fail == 0) {
|
|
test_fail = test_fail + psram_test(test_size);
|
|
}
|
|
if (test_fail) {
|
|
count_far_fail = count;
|
|
test_fail = 0;
|
|
psram_re_init(psram_p_dev);
|
|
}
|
|
else {
|
|
count_near_ok = count;
|
|
}
|
|
if ((((count_far_fail + 1) >= count_near_ok) && (count_j == 0)) || \
|
|
(((count_near_ok + 1) >= count_far_fail) && (count_j == 1))) {
|
|
dqs[count_j == 0 ? 1 : 2] = count_near_ok;
|
|
test_fail = 0;
|
|
psram_re_init(psram_p_dev);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
uint32_t *dqs_w = write_read_dqs[1];
|
|
uint32_t *dqs_r = write_read_dqs[0];
|
|
dqs_w[2] = 64 + dqs_w[2];
|
|
dqs_w[0] = 64 + clk_org;
|
|
for (count_i = 0; count_i < 2; count_i++) {
|
|
uint32_t *dqs = write_read_dqs[count_i];
|
|
serial_puts(count_i == 0 ? "\npsram window read " : "\npsram window write ");
|
|
serial_put_dec(dqs[0]);
|
|
serial_puts(" ");
|
|
serial_put_dec(dqs[1]);
|
|
serial_puts(" ");
|
|
serial_put_dec(dqs[2]);
|
|
serial_puts(" 1/64UI==");
|
|
serial_put_dec((1000000 / (psram_p_dev->psram_frequency << 2)) / 64);
|
|
serial_puts("ps\n");
|
|
}
|
|
wr_reg(PSRAM_DQS_DIN_DLY, (dqs_r[1] + dqs_r[2]) >> 1);
|
|
wr_reg(PSRAM_DQSN_DIN_DLY, (dqs_r[1] + dqs_r[2]) >> 1);
|
|
count_i = ((dqs_w[1] + dqs_w[2]) >> 1);
|
|
if (count_i > 64) {
|
|
wr_reg(PSRAM_CKN_DOUT_DLY, count_i - 64);
|
|
wr_reg(PSRAM_CK_DOUT_DLY, count_i - 64);
|
|
}
|
|
else {
|
|
for (count_j = PSRAM_DQ0_DOUT_DLY; count_j <= PSRAM_DQ7_DOUT_DLY - PSRAM_DQ0_DOUT_DLY;) {
|
|
wr_reg(count_j, 64 - count_i);
|
|
count_j = count_j + 4;
|
|
}
|
|
}
|
|
wr_reg(PSRAM_LCDL_CTRL, 0x20001000 | (3 << 24) | (0 << 26));
|
|
wr_reg(PSRAM_LCDL_CTRL, 0x20001000 | (3 << 24) | (0 << 26) | (1 << 31));
|
|
}
|
|
#endif
|
|
|
|
void psram_frequency_test(psram_set_t *psram_p_dev) {
|
|
//window test
|
|
//psram_amlogic_sw_training_test();
|
|
uint32_t count = 0;
|
|
serial_puts("\n ddr frequency test end");
|
|
for (count = 96;count < 300;) {
|
|
psram_p_dev->psram_frequency = count;
|
|
//serial_puts("\n test psram clk==");
|
|
//serial_put_dec(count );
|
|
//serial_puts("MHz");
|
|
bl2_print("\nDDR_SWEEP_clk== ",count,1," M");
|
|
psram_re_init(psram_p_dev);
|
|
//serial_puts(" 1232");
|
|
//psram_window_test(psram_p_dev);
|
|
//serial_puts(" result==");
|
|
//serial_put_dec(psram_test(psram_p_dev->psram_size<<20));
|
|
uint32_t pass_flag = (psram_test(psram_p_dev->psram_size << 20));
|
|
|
|
serial_puts(" psram test frequency ");
|
|
serial_put_dec(psram_p_dev->psram_frequency);
|
|
if (pass_flag > 1) {
|
|
serial_puts(" 0 skip");
|
|
}
|
|
if (pass_flag == 0) {
|
|
serial_puts(" 1 pass");
|
|
}
|
|
if (pass_flag == 1) {
|
|
serial_puts(" 2 fail");
|
|
}
|
|
serial_puts(" dll ");
|
|
serial_put_dec(rd_reg(PSRAM_CLK_UI));
|
|
count = count + 12;
|
|
}
|
|
}
|
|
|
|
#if 1
|
|
#define A1_PWM 0xfe002400
|
|
|
|
uint32_t tack[35][2] =
|
|
{{ 1044,0x00000022},
|
|
{ 1034,0x00010021},
|
|
{ 1024,0x00020020},
|
|
{ 1014,0x0003001f},
|
|
{ 1004,0x0004001e},
|
|
{ 994,0x0005001d},
|
|
{ 983,0x0006001c},
|
|
{ 973,0x0007001b},
|
|
{ 963,0x0008001a},
|
|
{ 953,0x00090019},
|
|
{ 943,0x000a0018},
|
|
{ 932,0x000b0017},
|
|
{ 922,0x000c0016},
|
|
{ 912,0x000d0015},
|
|
{ 902,0x000e0014},
|
|
{ 892,0x000f0013},
|
|
{ 881,0x00100012},
|
|
{ 871,0x00110011},
|
|
{ 861,0x00120010},
|
|
{ 851,0x0013000f},
|
|
{ 841,0x0014000e},
|
|
{ 831,0x0015000d},
|
|
{ 820,0x0016000c},
|
|
{ 810,0x0017000b},
|
|
{ 800,0x0018000a},
|
|
{ 790,0x00190009},
|
|
{ 780,0x001a0008},
|
|
{ 769,0x001b0007},
|
|
{ 759,0x001c0006},
|
|
{ 749,0x001d0005},
|
|
{ 739,0x001e0004},
|
|
{ 729,0x001f0003},
|
|
{ 719,0x00200002},
|
|
{ 708,0x00210001},
|
|
{ 698,0x00220000},};
|
|
|
|
void psram_sweep_vddee_test(psram_set_t *psram_p_dev) {
|
|
//uint32_t org_test_value = 0x00220000;
|
|
//uint32_t c_step=0x0000ffff;
|
|
uint8_t serch = 0;
|
|
while (serch < 35)
|
|
{
|
|
wr_reg(A1_PWM, tack[serch][1]);
|
|
//if (p_dev->ddr_global_message.stick_dmc_ddr_window_test_enable)
|
|
{
|
|
//serial_put_dec(tack[serch][0]);
|
|
//serial_puts("mv\n");
|
|
//bl2_print("\nread org_EE_voltage "tack[serch][0],1," mv \n");
|
|
bl2_print("\nDDR_SWEEP_begin_EE_voltage psram ",tack[serch][0],1," mv bdlr ");
|
|
serial_puts(" \n");
|
|
//psram_frequency_test(psram_p_dev);
|
|
psram_window_test(psram_p_dev);
|
|
bl2_print("\nDDR_SWEEP_end_EE_voltage psram ",tack[serch][0],1," mv \n");
|
|
}
|
|
// if (serch == 34)
|
|
// {//org_test_value = 0x00220000;
|
|
// serch = 0;
|
|
// }
|
|
//else
|
|
{
|
|
serch++;
|
|
//org_test_value = org_test_value-c_step;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
uint32_t global_stick_g12_d2pll_cmd_enable;
|
|
void psram_extra_test(psram_set_t *psram_p_dev) {
|
|
//window test
|
|
//psram_amlogic_sw_training_test();
|
|
if (global_stick_g12_d2pll_cmd_enable)
|
|
psram_p_dev->psram_test_function[0] =
|
|
PSRAM_WINDOW_TEST_INDEX | PSRAM_FREQUENCY_TEST_INDEX;
|
|
#ifdef ENABLE_PSRAM_EXTRA_TEST
|
|
//if (psram_p_dev->psram_test_function[0] == G12_D2PLL_CMD_SWEEP_EE_VOLTAGE_FREQUENCY_TABLE_TEST)
|
|
//psram_sweep_vddee_test(psram_p_dev);
|
|
if (psram_p_dev->psram_test_function[0] & PSRAM_WINDOW_TEST_INDEX)
|
|
psram_window_test(psram_p_dev);
|
|
if (psram_p_dev->psram_test_function[0] & PSRAM_FREQUENCY_TEST_INDEX)
|
|
psram_frequency_test(psram_p_dev);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
void psram_config_winbond(char chip_logic_index, uint32_t psram_frequency)
|
|
{
|
|
//CONFIG WINBOND PSRAM CONFIG0 register.
|
|
uint32_t latency = 0;
|
|
uint32_t data32 = 0;
|
|
|
|
latency = psram_calculate_latency(chip_logic_index, psram_frequency);
|
|
data32 = 1 | (1 << 2) | ((0) << 3) | \
|
|
(((latency > 4) ? (latency - 5) : (latency + 11)) << 4) | \
|
|
(0xf << 8) | (0 << 3) | (1 << 15);
|
|
psram_wb_write_reg(0x1000, data32);
|
|
psram_wait_status_ready();
|
|
}
|
|
|
|
void psram_config_winbond_sleep(void)
|
|
{
|
|
uint32_t data32;
|
|
data32 = rd_reg(PSRAM_STATUS);
|
|
|
|
//check psram idle
|
|
if ((data32 & 0x7) == 0x7)
|
|
serial_puts("Psram : psram idle\n");
|
|
else
|
|
serial_puts("Warning : Psram busy, can't entry hybirf sleep mode !\n");
|
|
|
|
//disable axi req before resend user-cmd ,or user cmd can not send out
|
|
data32 = rd_reg(PSRAM_AXI_REQ_CTRL0);
|
|
wr_reg(PSRAM_AXI_REQ_CTRL0, data32 & ~(1 << 31));
|
|
psram_wb_write_reg(0x1002, 0xffa0);
|
|
psram_wait_status_ready();
|
|
}
|
|
|
|
void psram_exit_winbond_sleep(void)
|
|
{
|
|
psram_send_user_cmd(0x1002, 0xffa0, 2 << 16, (1 << 15) | (1 << 14) | 1, 0, 0xb8030000);
|
|
psram_wait_status_ready();
|
|
wr_reg(PSRAM_AXI_REQ_CTRL0, rd_reg(PSRAM_AXI_REQ_CTRL0) | (1 << 31));
|
|
}
|
|
|
|
|
|
char psram_init_winbond(psram_set_t *psram_p_dev) {
|
|
//#if 1 //winbond
|
|
char init_pass = 0;
|
|
#if ENABLE_WINBOND_PSRAM_PXP_DEBUG
|
|
#else
|
|
char time_out_count = 0;
|
|
#endif
|
|
//uint32_t data32=0;
|
|
uint32_t latency = 0;
|
|
//uint32_t init_freq=0;
|
|
/* enable on real chip */
|
|
//dmc_reset(psram_p_dev);
|
|
serial_puts("\ninit winbond\n");
|
|
#if ENABLE_WINBOND_PSRAM_PXP_DEBUG
|
|
//psram_p_dev->psram_frequency = 166;
|
|
psram_p_dev->psram_amlogic_protocol_id = PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W955D8MKY;
|
|
#else
|
|
char auto_frequency = 0;
|
|
|
|
if (psram_p_dev->psram_frequency == 0xffff) {
|
|
auto_frequency = 1;
|
|
psram_p_dev->psram_frequency = 166;//166;128
|
|
}
|
|
psram_p_dev->psram_frequency = 166;
|
|
psram_p_dev->psram_amlogic_protocol_id = PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W955D8MKY;
|
|
|
|
//wr_reg (AO_RESETCTRL_RESET0, (1<<4)|rd_reg(AO_RESETCTRL_RESET0));
|
|
WINBOND_REINT:
|
|
_udelay(1);
|
|
#endif
|
|
psram_init_hw_bringup(psram_p_dev,
|
|
PSRAM_BRINGUP_PRE_UDELAY | PSRAM_BRINGUP_PHY_DELAY | PSRAM_BRINGUP_POST_UDELAY10);
|
|
latency = psram_calculate_latency(psram_p_dev->psram_amlogic_protocol_id,
|
|
psram_p_dev->psram_frequency);
|
|
psram_init_phy_regs(psram_p_dev->psram_amlogic_protocol_id);
|
|
|
|
psram_config_winbond(psram_p_dev->psram_amlogic_protocol_id, psram_p_dev->psram_frequency);
|
|
//read identification reg0
|
|
psram_send_user_cmd(0x0000, 0x0, 2 << 16, (1 << 28) | (1 << 27) | (1 << 16), 0x00008000 | ((latency) << 8) | (latency - 2), (1 << 31) | (1 << 29) | (1 << 28) | (1 << 27) | (3 << 16) | 0);
|
|
#if ENABLE_WINBOND_PSRAM_PXP_DEBUG
|
|
#else
|
|
while ((((rd_reg(PSRAM_USER_CTRL0)) >> 30) & 1) == 0)
|
|
{//add time out for use winbond protocol to probe ap memory then no dqs may result bus hang
|
|
_udelay(10);
|
|
time_out_count++;
|
|
if (time_out_count > 10)
|
|
{
|
|
if (auto_frequency) {
|
|
psram_p_dev->psram_frequency = 0xffff;
|
|
auto_frequency = 0;
|
|
}
|
|
return init_pass;
|
|
}
|
|
};
|
|
#endif
|
|
//serial_puts("\ninit winbond 5\n");
|
|
psram_p_dev->psram_mr[1] = (rd_reg(PSRAM_CFG_STS)) & 0xff;
|
|
//serial_puts("\ninit winbond 6\n");
|
|
psram_p_dev->psram_mr[0] = (rd_reg(PSRAM_CFG_STS)) & 0xff;
|
|
psram_p_dev->psram_mr[1] = ((rd_reg(PSRAM_CFG_STS)) >> 8) & 0xff;
|
|
serial_puts("\npsram_mr[0]== ");
|
|
serial_put_hex(psram_p_dev->psram_mr[0], 32);//0x8d
|
|
serial_puts("\npsram_mr[1]== ");
|
|
serial_put_hex(psram_p_dev->psram_mr[1], 32);
|
|
serial_puts("\n");
|
|
|
|
if ((psram_p_dev->psram_mr[0]) == (PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W955D8MKY_MR0)) {
|
|
init_pass = 1;
|
|
psram_p_dev->psram_size = 4;
|
|
psram_p_dev->psram_amlogic_protocol_id = PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W955D8MKY;
|
|
}
|
|
if ((psram_p_dev->psram_mr[0]) == (PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W956D8MKY_MR0)) {
|
|
init_pass = 1;
|
|
psram_p_dev->psram_size = 8;
|
|
psram_p_dev->psram_amlogic_protocol_id = PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W956D8MKY;
|
|
}
|
|
if ((psram_p_dev->psram_mr[0]) == (PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W966D8MKY_MR0)) {
|
|
init_pass = 1;
|
|
psram_p_dev->psram_size = 32;
|
|
psram_p_dev->psram_amlogic_protocol_id = PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W966D8MKY;
|
|
}
|
|
#if ENABLE_WINBOND_PSRAM_PXP_DEBUG
|
|
#else
|
|
if (!init_pass) {
|
|
if (auto_frequency) {
|
|
psram_p_dev->psram_frequency = 0xffff;
|
|
auto_frequency = 0;
|
|
}
|
|
return init_pass;
|
|
}
|
|
#endif
|
|
#if ENABLE_WINBOND_PSRAM_PXP_DEBUG
|
|
#else
|
|
if ((auto_frequency) && (psram_p_dev->psram_amlogic_protocol_id == PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W956D8MKY
|
|
|| psram_p_dev->psram_amlogic_protocol_id == PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W966D8MKY)) {
|
|
psram_p_dev->psram_frequency = 192;
|
|
auto_frequency = 0;
|
|
goto WINBOND_REINT;
|
|
}
|
|
#endif
|
|
|
|
psram_config_axi_interface(
|
|
32 | (32 << 16) | (1 << 31),
|
|
(latency << 16) | ((latency - 2) << 22) | (1 << 30) | (1 << 31),
|
|
(0 << 16) | 0,
|
|
latency | (1 << 6) | (2 << 12)| (3 << 24) | (1 << 30) | (1 << 31)
|
|
);
|
|
//psram_test(psram_p_dev); //test psram add and data size
|
|
|
|
return init_pass;
|
|
}
|
|
|
|
#ifdef ENABLE_PSRAM_GET_AP_EID
|
|
static uint32_t psram_get_eid_half(uint32_t latency, uint32_t len, uint32_t ctrl0) {
|
|
uint32_t eid = 0;
|
|
for (char count = 0; count < 16; count++) {
|
|
wr_reg(PSRAM_DBUF_0 + (count << 2), 0);
|
|
}
|
|
psram_send_user_cmd(0x00000006, 0, 0, (1 << 28) | (0 << 27) | (len << 16),
|
|
(1 << 15) | (latency << 8) | (latency - 2), ctrl0);
|
|
psram_wait_user_cmd();
|
|
for (char count = 0; count < 16; count++) {
|
|
uint32_t r = rd_reg(PSRAM_DBUF_0 + (count << 2));
|
|
eid |= ((r & 1) << (31 - (count << 1))) |
|
|
(((r >> 16) & 1) << (31 - (count << 1) - 1));
|
|
}
|
|
return eid;
|
|
}
|
|
#endif
|
|
|
|
char psram_init_ap(psram_set_t *psram_p_dev) {
|
|
#if 1
|
|
serial_puts("\ninit ap\n");
|
|
char init_pass = 0;
|
|
psram_p_dev->psram_amlogic_protocol_id = PSRAM_CHIP_LOGIC_INDEX_AP_MEMORY_3_CMD;
|
|
if (psram_p_dev->psram_frequency == 0xffff) {
|
|
psram_p_dev->psram_frequency = 192;
|
|
}
|
|
//uint32_t data32=0;
|
|
uint32_t latency = 0;
|
|
uint32_t wr_latency=0;
|
|
|
|
latency = psram_calculate_latency(psram_p_dev->psram_amlogic_protocol_id, psram_p_dev->psram_frequency);
|
|
wr_latency = psram_calculate_wl_latency(psram_p_dev->psram_amlogic_protocol_id, psram_p_dev->psram_frequency);
|
|
|
|
psram_init_hw_bringup(psram_p_dev, PSRAM_BRINGUP_AO_RESET);
|
|
psram_init_phy_regs(PSRAM_CHIP_LOGIC_INDEX_AP_MEMORY_3_CMD);
|
|
#if 0
|
|
extern void watchdog_disable(void);
|
|
extern void debug_rom(char * file, int line);
|
|
serial_puts("---------- AMLOGIC INTERNAL USED ONLY ----------\n\n");
|
|
serial_puts("---------- BL2 WITH DEBUGROM SUPPORT ----------\n\n");
|
|
watchdog_disable();
|
|
debug_rom(__FILE__,__LINE__);
|
|
#endif
|
|
|
|
psram_ap_write_mr(0x00000000, ((latency - 3) << 2) | psram_calculate_drv((psram_p_dev->psram_amlogic_protocol_id), psram_p_dev->psram_dram_drv));
|
|
|
|
//configure MR4.
|
|
static const uint8_t ap_mr4s[] = {6, 2, 4, 0, 7, 3, 5, 1};
|
|
char mr4 = ap_mr4s[psram_find_ap_freq_index(psram_p_dev->psram_frequency)];
|
|
|
|
psram_ap_write_mr(0x00000004, (mr4 << 5));
|
|
|
|
//configure MR8.
|
|
psram_ap_write_mr(0x00000008, 2);
|
|
|
|
//read MR8
|
|
psram_ap_read_mr(0x00000008, latency);
|
|
psram_wait_user_cmd();
|
|
//read MR1
|
|
psram_ap_read_mr(0x00000001, latency);
|
|
psram_wait_user_cmd();
|
|
psram_p_dev->psram_mr[1] = (rd_reg(PSRAM_CFG_STS))&0xff;
|
|
psram_p_dev->psram_mr[2] = ((rd_reg(PSRAM_CFG_STS)) >> 8)&0xff;
|
|
serial_puts("\npsram_mr[1]== ");
|
|
serial_put_hex(psram_p_dev->psram_mr[1], 32);//0x8d
|
|
serial_puts("\npsram_mr[2]== ");
|
|
serial_put_hex(psram_p_dev->psram_mr[2], 32);
|
|
serial_puts("\n");
|
|
//ddr_debug_serial_puts("DDR_debug", __FILE__, __LINE__);
|
|
//ddr_debug_rom(__FILE__, __LINE__);
|
|
if (psram_detect_ap_size(psram_p_dev)) {
|
|
init_pass = 1;
|
|
}
|
|
else {
|
|
return init_pass;
|
|
}
|
|
|
|
#ifdef ENABLE_PSRAM_GET_AP_EID
|
|
uint32_t EID[2];
|
|
EID[0] = psram_get_eid_half(latency, 32, (1 << 31) | (1 << 29) | (1 << 28) | (1 << 27) | (3 << 16) | 0x4040);
|
|
EID[1] = psram_get_eid_half(latency, 64, (1 << 31) | (1 << 29) | (1 << 28) | (1 << 27) | (3 << 16) | 0x4000);
|
|
serial_puts("\nEID ");
|
|
serial_put_hex(EID[0], 32);
|
|
serial_puts(" ");
|
|
serial_put_hex(EID[1], 32);
|
|
#endif
|
|
|
|
psram_config_axi_interface(
|
|
32 | (32 << 16) | (0 << 31),
|
|
((latency + 1) << 16) | ((latency + 1 - 2) << 22) | (1 << 28) | (1 << 31),
|
|
(0 << 16) | 0x8080,
|
|
wr_latency | (1 << 6) | (3 << 24) | (1 << 30) | (1 << 31)
|
|
);
|
|
//serial_puts("PSRAM_ACTIMING1==");
|
|
//serial_put_hex(rd_reg(PSRAM_ACTIMING1), 32);//0x8d
|
|
|
|
#endif
|
|
serial_puts("\nend init ap\n");
|
|
return init_pass;
|
|
}
|
|
|
|
static psram_set_t psram_uboot_dev_storage;
|
|
static char psram_uboot_dev_ready;
|
|
|
|
char psram_uboot_drv_init(void)
|
|
{
|
|
psram_set_t *psram_p_dev = &psram_uboot_dev_storage;
|
|
char init_pass = 0;
|
|
uint32_t data32;
|
|
|
|
memset(psram_p_dev, 0, sizeof(*psram_p_dev));
|
|
psram_uboot_dev_ready = 0;
|
|
|
|
data32 = rd_reg(AO_PWRCTRL_FOCRST0);
|
|
wr_reg(AO_PWRCTRL_FOCRST0, (data32 | (1 << 12)));
|
|
wr_reg(AO_PWRCTRL_FOCRST0, (data32 & ~(1 << 12)));
|
|
*P_AO_PWRCTRL_MEM_PD0 = 0x0;
|
|
|
|
psram_p_dev->psram_soc_drv = psram_p_dev->psram_soc_drv ? psram_p_dev->psram_soc_drv : 48;
|
|
psram_p_dev->psram_dram_drv = psram_p_dev->psram_dram_drv ? psram_p_dev->psram_dram_drv : 48;
|
|
|
|
{
|
|
static const unsigned char init_delays[32] = {
|
|
1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 32, 32, 16, 16, 1
|
|
};
|
|
memcpy(psram_p_dev->psram_pin_dq_in_delay,
|
|
&init_delays[0],
|
|
sizeof(psram_p_dev->psram_pin_dq_in_delay));
|
|
|
|
memcpy(psram_p_dev->psram_pin_dq_out_delay,
|
|
&init_delays[8],
|
|
sizeof(psram_p_dev->psram_pin_dq_out_delay));
|
|
|
|
memcpy(psram_p_dev->psram_pin_dq_out_oe_delay,
|
|
&init_delays[16],
|
|
sizeof(psram_p_dev->psram_pin_dq_out_oe_delay));
|
|
|
|
psram_p_dev->psram_pin_dm_out_delay = init_delays[24];
|
|
psram_p_dev->psram_pin_dm_out_oe_delay = init_delays[25];
|
|
psram_p_dev->psram_pin_cs_out_delay = init_delays[26];
|
|
psram_p_dev->psram_pin_dqsp_in_delay = init_delays[27];
|
|
psram_p_dev->psram_pin_dqsn_in_delay = init_delays[28];
|
|
psram_p_dev->psram_pin_ckp_out_delay = init_delays[29];
|
|
psram_p_dev->psram_pin_ckn_out_delay = init_delays[30];
|
|
psram_p_dev->psram_pin_rden_delay = init_delays[31];
|
|
}
|
|
|
|
*P_AO_RESETCTRL_RESET0_LEVEL &= ~(1 << 30);
|
|
_udelay(1);
|
|
*P_AO_RESETCTRL_RESET0_LEVEL |= (1 << 30);
|
|
psram_p_dev->psram_frequency = 166;
|
|
init_pass = psram_init_winbond(psram_p_dev);
|
|
if (!init_pass)
|
|
init_pass = psram_init_ap(psram_p_dev);
|
|
|
|
if (init_pass) {
|
|
psram_uboot_dev_ready = 1;
|
|
printf("psram init ok, freq=%uMHz size=%uMB\n",
|
|
psram_p_dev->psram_frequency, psram_p_dev->psram_size);
|
|
} else {
|
|
printf("psram init failed\n");
|
|
}
|
|
return init_pass;
|
|
}
|
|
|
|
psram_set_t *psram_uboot_get_dev(void)
|
|
{
|
|
return psram_uboot_dev_ready ? &psram_uboot_dev_storage : NULL;
|
|
}
|
|
|
|
static int psram_uboot_set_freq(psram_set_t *pdev, unsigned int freq_mhz)
|
|
{
|
|
char init_pass;
|
|
|
|
if (freq_mhz == 0 || freq_mhz > 300) {
|
|
printf("freq %u MHz invalid (use 1-300)\n", freq_mhz);
|
|
return 1;
|
|
}
|
|
|
|
printf("psram freq %u -> %u MHz, re-init...\n",
|
|
pdev->psram_frequency, freq_mhz);
|
|
pdev->psram_frequency = freq_mhz;
|
|
init_pass = 0;
|
|
switch (pdev->psram_amlogic_protocol_id) {
|
|
case PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W955D8MKY:
|
|
case PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W956D8MKY:
|
|
case PSRAM_CHIP_LOGIC_INDEX_WINBOND_3_CMD_W966D8MKY:
|
|
init_pass = psram_init_winbond(pdev);
|
|
break;
|
|
case PSRAM_CHIP_LOGIC_INDEX_AP_MEMORY_3_CMD:
|
|
init_pass = psram_init_ap(pdev);
|
|
break;
|
|
default:
|
|
printf("unknown protocol id 0x%x, run psram_test 0x1 first\n",
|
|
pdev->psram_amlogic_protocol_id);
|
|
return 1;
|
|
}
|
|
|
|
if (!init_pass) {
|
|
printf("psram re-init at %u MHz failed\n", freq_mhz);
|
|
return 1;
|
|
}
|
|
printf("psram freq %u MHz ok, size=%uMB\n", pdev->psram_frequency, pdev->psram_size);
|
|
return 0;
|
|
}
|
|
|
|
/* ---------- psram_test U-Boot command ---------- */
|
|
#define PSRAM_TEST_CMD_INIT 0x1
|
|
#define PSRAM_TEST_CMD_FREQ_SWEEP 0x2
|
|
#define PSRAM_TEST_CMD_WINDOW 0x3
|
|
#define PSRAM_TEST_CMD_SET_FREQ 0x4
|
|
|
|
static int do_psram_test_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
|
|
{
|
|
unsigned long subcmd;
|
|
unsigned long freq_mhz;
|
|
psram_set_t *pdev;
|
|
char *endp;
|
|
|
|
if (argc < 2) {
|
|
printf("psram_test subcmd [arg]\n");
|
|
printf(" 0x1 - init PSRAM\n");
|
|
printf(" 0x2 - frequency sweep\n");
|
|
printf(" 0x3 - delay window test\n");
|
|
printf(" 0x4 <mhz> - switch PSRAM frequency and re-init\n");
|
|
printf(" psram_test_base - test psram base address %x\n", sram_test_base);
|
|
return 1;
|
|
}
|
|
|
|
subcmd = simple_strtoul(argv[1], &endp, 0);
|
|
if (argv[1][0] == 0 || *endp != 0) {
|
|
printf("invalid subcmd\n");
|
|
return 1;
|
|
}
|
|
|
|
switch (subcmd) {
|
|
case PSRAM_TEST_CMD_INIT:
|
|
return psram_uboot_drv_init() ? 0 : 1;
|
|
case PSRAM_TEST_CMD_FREQ_SWEEP:
|
|
pdev = psram_uboot_get_dev();
|
|
if (!pdev) {
|
|
printf("run psram_test 0x1 first\n");
|
|
return 1;
|
|
}
|
|
psram_frequency_test(pdev);
|
|
return 0;
|
|
case PSRAM_TEST_CMD_WINDOW:
|
|
pdev = psram_uboot_get_dev();
|
|
if (!pdev) {
|
|
printf("run psram_test 0x1 first\n");
|
|
return 1;
|
|
}
|
|
psram_re_init(pdev);
|
|
psram_window_test(pdev);
|
|
return 0;
|
|
case PSRAM_TEST_CMD_SET_FREQ:
|
|
pdev = psram_uboot_get_dev();
|
|
if (!pdev) {
|
|
printf("run psram_test 0x1 first\n");
|
|
return 1;
|
|
}
|
|
if (argc < 3) {
|
|
printf("usage: psram_test 0x4 <freq_mhz>\n");
|
|
printf("current freq=%u MHz\n", pdev->psram_frequency);
|
|
return 1;
|
|
}
|
|
freq_mhz = simple_strtoul(argv[2], &endp, 0);
|
|
if (argv[2][0] == 0 || *endp != 0) {
|
|
printf("invalid freq\n");
|
|
return 1;
|
|
}
|
|
return psram_uboot_set_freq(pdev, freq_mhz) ? 1 : 0;
|
|
default:
|
|
printf("unknown subcmd 0x%lx\n", subcmd);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
U_BOOT_CMD(psram_test, 6, 1, do_psram_test_cmd,
|
|
"psram_test subcmd [arg]",
|
|
"psram_test 0x1 - init PSRAM\n"
|
|
"psram_test 0x2 - frequency sweep\n"
|
|
"psram_test 0x3 - window test\n"
|
|
"psram_test 0x4 <freq_mhz> - switch frequency\n");
|