Commit 90b74af2 authored by Alexander Potashev's avatar Alexander Potashev

RT73025. ea-lpc1788: configure EMC for DRAM

The DRAM configuration is the same as in the existing port from LPCware.
parent 4b579f2c
......@@ -28,7 +28,227 @@
#include <asm/arch/lpc178x_gpio.h>
/*
* GPIO pin configuration table for EA-LPC1788
* SDRAM-specific configuration
*/
/*
* Programmable delay value for EMC outputs in command delayed mode
*/
#define LPC178X_EMC_CMDDLY 0x10
/*
* Programmable delay value for the feedback clock that controls input data
* sampling
*/
#define LPC178X_EMC_FBCLKDLY 0x10
/*
* IS42S32800B SDRAM: 32-bit, 4 banks, 12 rows, 9 cols.
* See Table 133 "Address mapping" in the LPC178x/7x User Manual.
*/
#define LPC178X_EMC_AM 0x89
/*
* Timing for 54MHz bus
*/
#define LPC178X_EMC_RAS 2
#define LPC178X_EMC_CAS 2
/* Command delayed strategy, using EMCCLKDELAY */
#define LPC178X_EMC_RDCFG_RD 1
/* Precharge command period (tRP) = 1 EMC clock cycle */
#define LPC178X_EMC_T_RP 1
/* Active to precharge command perion (tRAS) = 3 clocks */
#define LPC178X_EMC_T_RAS 3
/* Self-refresh exit time (tSREX) = 4 clocks */
#define LPC178X_EMC_T_SREX 4
/* Last-data-out to active command time (tAPR) = 2 clocks */
#define LPC178X_EMC_T_APR 2
/* Data-in to active command (tDAL) = 2 clocks */
#define LPC178X_EMC_T_DAL 2
/* Write recovery time (tWR) = 2 clocks */
#define LPC178X_EMC_T_WR 2
/* Active to active command perion (tRC) = 4 clocks */
#define LPC178X_EMC_T_RC 4
/*
* Auto-refresh period and auto-refresh to active command period
* (tRFC) = 4 clocks
*/
#define LPC178X_EMC_T_RFC 4
/* Exit self-refresh to active command time (tXSR) = 4 clocks */
#define LPC178X_EMC_T_XSR 4
/* Active bank A to active bank B latency (tRRD) = 1 clock */
#define LPC178X_EMC_T_RRD 1
/* Load mode register to active command time (tMRD) = 1 clock */
#define LPC178X_EMC_T_MRD 1
/*
* Refresh timer.
* Indicates the multiple of 16 CCLKs between SDRAM refresh cycles.
*/
#define LPC178X_EMC_REFRESH 0x2E
#define LPC178X_EMC_REFRESH_FAST 2 /* Only for initialization */
/*
* See IS42S32800B mode register (IS42S32800B datasheet, page 16).
* CAS2, Burst Length = 4.
*/
#define LPC178X_EMC_MODEREG_BL 2 /* Burst Length code */
#define LPC178X_EMC_MODEREG_CAS 2 /* CAS Latency */
/*
* SCC registers
*/
/*
* EMC Delay Control register
*/
/* Programmable delay value for EMC outputs in command delayed mode */
#define LPC178X_SCC_EMCDLYCTL_CMDDLY_BITS 0
/*
* Programmable delay value for the feedback clock that controls input data
* sampling
*/
#define LPC178X_SCC_EMCDLYCTL_FBCLKDLY_BITS 8
/*
* EMC registers
*/
/*
* EMC Control register
*/
#define LPC178X_EMC_CTRL_EN_MSK (1 << 0)
/* EMC data pins (DQ0..DQ31) */
#define LPC178X_EMC_DATA_PINS 31
/* EMC row/column address pins (A0..A11) */
#define LPC178X_EMC_ADDR_PINS 12
/*
* Dynamic Memory Control register
*/
/* Dynamic memory clock enable (CE) */
#define LPC178X_EMC_DYCTRL_CE_MSK (1 << 0)
/* Dynamic memory clock control (CS) */
#define LPC178X_EMC_DYCTRL_CS_MSK (1 << 1)
/* SDRAM initialization (I) */
#define LPC178X_EMC_DYCTRL_I_BITS 7
#define LPC178X_EMC_DYCTRL_I_NORMAL 0
#define LPC178X_EMC_DYCTRL_I_MODE 1
#define LPC178X_EMC_DYCTRL_I_PALL 2 /* precharge all */
#define LPC178X_EMC_DYCTRL_I_NOP 3 /* no operation */
/*
* Dynamic Memory Read Configuration register:
* Read data strategy (RD)
*/
#define LPC178X_EMC_DYRDCFG_RD_BITS 0
/*
* The SDRAM chip (IS42S32800B) mode register.
* See IS42S32800B datasheet, page 16.
*/
#define LPC178X_EMC_MODEREG_BL_BITS 0 /* Burst Length */
#define LPC178X_EMC_MODEREG_CAS_BITS 4 /* CAS Latency */
#define LPC178X_EMC_MODEREG_VALUE \
((LPC178X_EMC_MODEREG_BL << LPC178X_EMC_MODEREG_BL_BITS) | \
(LPC178X_EMC_MODEREG_CAS << LPC178X_EMC_MODEREG_CAS_BITS))
/*
* Offset of the 12 least-significant bits of mode register (A0..A11)
* in addresses on the AHB bus.
*
* In the high-performance mode the shift should be the following:
* 13 = 9 (column bits) + 2 (bank select bits) + 2 (32 bits)
* 1. IS42S32800B SDRAM has 512 columns, therefore 9 bits are used for the column number.
* 2. Bank select field has 2 bits.
* 3. `2` is log2(32/8), because the SDRAM chip is 32-bit, and its
* internal addresses do not have 2 least-significant bits of
* the AHB bus addresses.
*
* In the low-power mode this shift will be different.
*/
#define LPC178X_EMC_MODEREG_ADDR_SHIFT 13
/*
* Dynamic Memory registers (per chip)
*/
/*
* Dynamic Memory Configuration register
*/
/* Address mapping */
#define LPC178X_EMC_DYCFG_AM_BITS 7
/* Buffer enable */
#define LPC178X_EMC_DYCFG_B_MSK (1 << 19)
/*
* Dynamic Memory RAS & CAS Delay register
*/
/* RAS latency */
#define LPC178X_EMC_DYRASCAS_RAS_BITS 0
/* CAS latency */
#define LPC178X_EMC_DYRASCAS_CAS_BITS 8
/*
* EMC per-chip registers for DRAM.
*
* This structure must be 0x20 bytes in size
* (for `struct lpc178x_emc_regs` to be correct.)
*/
struct lpc178x_emc_dy_regs {
u32 cfg; /* Dynamic Memory Configuration register */
u32 rascas; /* Dynamic Memory RAS & CAS Delay registers */
u32 rsv0[6];
};
/*
* EMC (External Memory Controller) register map
* Should be mapped at 0x2009C000.
*/
struct lpc178x_emc_regs {
/* 0x2009C000 */
u32 emcctrl; /* EMC Control register */
u32 emcsts; /* EMC Status register */
u32 emccfg; /* EMC Configuration register */
u32 rsv0[5];
/* 0x2009C020 */
u32 dy_ctrl; /* Dynamic Memory Control register */
u32 dy_rfsh; /* Dynamic Memory Refresh Timer register */
u32 dy_rdcfg; /* Dynamic Memory Read Configuration register */
u32 rsv1;
/* 0x2009C030 */
u32 dy_trp; /* Dynamic Memory Precharge Command Period register */
u32 dy_tras; /* Dynamic Memory Active to Precharge Command
Period register */
u32 dy_srex; /* Dynamic Memory Self-refresh Exit Time register */
u32 dy_apr; /* Dynamic Memory Last Data Out to Active
Time register */
u32 dy_dal; /* Dynamic Memory Data-in to Active Command
Time register */
u32 dy_wr; /* Dynamic Memory Write Recovery Time register */
u32 dy_rc; /* Dynamic Memory Active to Active Command
Period register */
u32 dy_rfc; /* Dynamic Memory Auto-refresh Period register */
u32 dy_xsr; /* Dynamic Memory Exit Self-refresh register */
u32 dy_rrd; /* Dynamic Memory Active Bank A to
Active Bank B Time register */
u32 dy_mrd; /* Dynamic Memory Load Mode register to
Active Command Time */
/* 0x2009C05C */
u32 rsv2[41];
/* 0x2009C100 */
struct lpc178x_emc_dy_regs dy[4]; /* 4 DRAM chips are possible */
};
#define LPC178X_EMC_BASE (LPC178X_AHB_PERIPH_BASE + 0x0001C000)
#define LPC178X_EMC ((volatile struct lpc178x_emc_regs *) \
LPC178X_EMC_BASE)
DECLARE_GLOBAL_DATA_PTR;
/*
* GPIO pin configuration table for EA-LPC1788-32
*
* This table does not list all GPIO pins that will be configured. See also
* the code in `gpio_init()`.
*/
static const struct lpc178x_gpio_pin_config ea_lpc1788_gpio[] = {
#if CONFIG_LPC178X_UART_PORT == 0
......@@ -44,6 +264,37 @@ static const struct lpc178x_gpio_pin_config ea_lpc1788_gpio[] = {
#else /* Neither UART0 nor UART2 */
#error This configuration of GPIO pins supports only UART0 or UART2
#endif
#ifdef CONFIG_NR_DRAM_BANKS
#define LPC178X_GPIO_EMC_REGVAL \
(LPC178X_GPIO_CONFIG_D(1, LPC178X_NO_PULLUP, 0, 0, 1, 0))
/* Configure EMC bank address select 0 and 1 (BA0, BA1) */
{{4, 13}, LPC178X_GPIO_EMC_REGVAL},
{{4, 14}, LPC178X_GPIO_EMC_REGVAL},
/* Configure EMC column address strobe (CAS) */
{{2, 16}, LPC178X_GPIO_EMC_REGVAL},
/* Configure EMC row address strobe (RAS) */
{{2, 17}, LPC178X_GPIO_EMC_REGVAL},
/* Configure EMC write enable (WE) */
{{4, 25}, LPC178X_GPIO_EMC_REGVAL},
/* Configure EMC clock input (CLK) */
{{2, 18}, LPC178X_GPIO_EMC_REGVAL},
/* Configure EMC clock enable (CKE) */
{{2, 24}, LPC178X_GPIO_EMC_REGVAL},
/* Configure EMC chip select (DYCS0) */
{{2, 20}, LPC178X_GPIO_EMC_REGVAL},
/* Configure EMC I/O mask (DQM0..DQM3) */
{{2, 28}, LPC178X_GPIO_EMC_REGVAL},
{{2, 29}, LPC178X_GPIO_EMC_REGVAL},
{{2, 30}, LPC178X_GPIO_EMC_REGVAL},
{{2, 31}, LPC178X_GPIO_EMC_REGVAL},
#endif
};
/*
......@@ -58,9 +309,26 @@ static void gpio_init(void)
lpc178x_periph_enable(LPC178X_SCC_PCONP_PCGPIO_MSK, 1);
/*
* Configure GPIO pins
* Configure GPIO pins using the `ea_lpc1788_gpio[]` table
*/
lpc178x_gpio_config_table(ea_lpc1788_gpio, ARRAY_SIZE(ea_lpc1788_gpio));
#ifdef CONFIG_NR_DRAM_BANKS
/*
* Configure GPIO pins used for the External Memory Controller (EMC)
*/
struct lpc178x_gpio_dsc dsc;
/* Configure EMC data pins (DQ0..DQ31) */
dsc.port = 3;
for (dsc.pin = 0; dsc.pin <= LPC178X_EMC_DATA_PINS; dsc.pin++)
lpc178x_gpio_config(&dsc, LPC178X_GPIO_EMC_REGVAL);
/* Configure EMC row/column address pins (A0..A11) */
dsc.port = 4;
for (dsc.pin = 0; dsc.pin <= LPC178X_EMC_ADDR_PINS; dsc.pin++)
lpc178x_gpio_config(&dsc, LPC178X_GPIO_EMC_REGVAL);
#endif
}
/*
......@@ -100,7 +368,107 @@ int misc_init_r(void)
*/
int dram_init(void)
{
/* TBD */
volatile struct lpc178x_emc_dy_regs *dy;
u32 tmp32;
dy = &LPC178X_EMC->dy[CONFIG_SYS_RAM_CS];
/*
* Enable power on EMC
*/
lpc178x_periph_enable(LPC178X_SCC_PCONP_PCEMC_MSK, 1);
/*
* Clock delay
*/
LPC178X_SCC->emcdlyctl =
(LPC178X_EMC_CMDDLY << LPC178X_SCC_EMCDLYCTL_CMDDLY_BITS) |
(LPC178X_EMC_FBCLKDLY << LPC178X_SCC_EMCDLYCTL_FBCLKDLY_BITS);
/*
* Enable EMC
*/
LPC178X_EMC->emcctrl = LPC178X_EMC_CTRL_EN_MSK;
/*
* Little-endian mode
*/
LPC178X_EMC->emccfg = 0;
/*
* Address mapping (see Table 133 from the LPC178x/7x User Manual)
*/
dy->cfg = (LPC178X_EMC_AM << LPC178X_EMC_DYCFG_AM_BITS);
/*
* Configure DRAM timing
*/
dy->rascas =
(LPC178X_EMC_RAS << LPC178X_EMC_DYRASCAS_RAS_BITS) |
(LPC178X_EMC_CAS << LPC178X_EMC_DYRASCAS_CAS_BITS);
LPC178X_EMC->dy_rdcfg =
(LPC178X_EMC_RDCFG_RD << LPC178X_EMC_DYRDCFG_RD_BITS);
LPC178X_EMC->dy_trp = LPC178X_EMC_T_RP - 1;
LPC178X_EMC->dy_tras = LPC178X_EMC_T_RAS - 1;
LPC178X_EMC->dy_srex = LPC178X_EMC_T_SREX - 1;
LPC178X_EMC->dy_apr = LPC178X_EMC_T_APR - 1;
LPC178X_EMC->dy_dal = LPC178X_EMC_T_DAL;
LPC178X_EMC->dy_wr = LPC178X_EMC_T_WR - 1;
LPC178X_EMC->dy_rc = LPC178X_EMC_T_RC - 1;
LPC178X_EMC->dy_rfc = LPC178X_EMC_T_RFC - 1;
LPC178X_EMC->dy_xsr = LPC178X_EMC_T_XSR - 1;
LPC178X_EMC->dy_rrd = LPC178X_EMC_T_RRD - 1;
LPC178X_EMC->dy_mrd = LPC178X_EMC_T_MRD - 1;
udelay(100000);
/*
* Issue SDRAM NOP (no operation) command
*/
LPC178X_EMC->dy_ctrl =
LPC178X_EMC_DYCTRL_CE_MSK | LPC178X_EMC_DYCTRL_CS_MSK |
(LPC178X_EMC_DYCTRL_I_NOP << LPC178X_EMC_DYCTRL_I_BITS);
udelay(200000);
/*
* Pre-charge all with fast refresh
*/
LPC178X_EMC->dy_ctrl =
LPC178X_EMC_DYCTRL_CE_MSK | LPC178X_EMC_DYCTRL_CS_MSK |
(LPC178X_EMC_DYCTRL_I_PALL << LPC178X_EMC_DYCTRL_I_BITS);
LPC178X_EMC->dy_rfsh = LPC178X_EMC_REFRESH_FAST;
udelay(1000);
/*
* Set refresh period
*/
LPC178X_EMC->dy_rfsh = LPC178X_EMC_REFRESH;
/*
* Load mode word, CAS2, burst of 4
*/
LPC178X_EMC->dy_ctrl =
LPC178X_EMC_DYCTRL_CE_MSK | LPC178X_EMC_DYCTRL_CS_MSK |
(LPC178X_EMC_DYCTRL_I_MODE << LPC178X_EMC_DYCTRL_I_BITS);
tmp32 = *(volatile u32 *)(CONFIG_SYS_RAM_BASE |
(LPC178X_EMC_MODEREG_VALUE << LPC178X_EMC_MODEREG_ADDR_SHIFT));
/*
* Normal mode
*/
LPC178X_EMC->dy_ctrl =
(LPC178X_EMC_DYCTRL_I_NORMAL << LPC178X_EMC_DYCTRL_I_BITS);
/*
* Enable DRAM buffer
*/
dy->cfg = (LPC178X_EMC_AM << LPC178X_EMC_DYCFG_AM_BITS) |
LPC178X_EMC_DYCFG_B_MSK;
/*
* Fill in global info with description of DRAM configuration
*/
gd->bd->bi_dram[0].start = CONFIG_SYS_RAM_BASE;
gd->bd->bi_dram[0].size = CONFIG_SYS_RAM_SIZE;
return 0;
}
......@@ -90,6 +90,11 @@ static u32 clock_val[CLOCK_END];
#define LPC178X_SCC_CCLKSEL_CCLKDIV_BITS 0
#define LPC178X_SCC_CCLKSEL_CCLKSEL_BIT 8
/*
* EMC Clock Selection register
*/
#define LPC178X_SCC_EMCCLKSEL_HALFCPU_MSK (1 << 0)
/*
* Calculate clock rates
*/
......@@ -143,6 +148,15 @@ static u32 clock_val[CLOCK_END];
*/
#define LPC178X_PCLK_RATE (LPC178X_CPU_CLK_SEL_OUT / CONFIG_LPC178X_PCLK_DIV)
/*
* Set LPC178X_EMC_RATE to the EMC clock
*/
#ifdef CONFIG_LPC178X_EMC_HALFCPU
#define LPC178X_EMC_RATE (LPC178X_CPU_CLK_SEL_OUT / 2)
#else
#define LPC178X_EMC_RATE (LPC178X_CPU_CLK_SEL_OUT)
#endif
/*
* Compile time sanity checks for defined board clock setup
*/
......@@ -270,6 +284,17 @@ static void clock_setup(void)
* Only PCLKDIV bit group used in PCLKSEL, therefore not using |=
*/
LPC178X_SCC->pclksel = CONFIG_LPC178X_PCLK_DIV;
#ifdef CONFIG_NR_DRAM_BANKS
/*
* EMC clock
*/
#ifdef CONFIG_LPC178X_EMC_HALFCPU
LPC178X_SCC->emcclksel = LPC178X_SCC_EMCCLKSEL_HALFCPU_MSK;
#else /* CONFIG_LPC178X_EMC_HALFCPU */
LPC178X_SCC->emcclksel = 0;
#endif /* CONFIG_LPC178X_EMC_HALFCPU */
#endif /* CONFIG_NR_DRAM_BANKS */
}
/*
......@@ -291,6 +316,11 @@ void clock_init(void)
* Set peripheral clock rate
*/
clock_val[CLOCK_PCLK] = LPC178X_PCLK_RATE;
/*
* Set EMC clock rate
*/
clock_val[CLOCK_EMCCLK] = LPC178X_EMC_RATE;
}
/*
......
......@@ -29,14 +29,15 @@
*/
int print_cpuinfo(void)
{
char buf[2][32];
char buf[3][32];
printf("CPU : %s\n", "LPC178x/7x series (Cortex-M3)");
strmhz(buf[0], clock_get(CLOCK_SYSTICK));
strmhz(buf[1], clock_get(CLOCK_PCLK));
printf("Freqs: SYSTICK=%sMHz,PCLK=%sMHz,\n",
buf[0], buf[1]);
strmhz(buf[1], clock_get(CLOCK_EMCCLK));
strmhz(buf[2], clock_get(CLOCK_PCLK));
printf("Freqs: SYSTICK=%sMHz,EMCCLK=%sMHz,PCLK=%sMHz\n",
buf[0], buf[1], buf[2]);
return 0;
}
......@@ -105,7 +105,7 @@ static inline int lpc178x_validate_gpio(const struct lpc178x_gpio_dsc *dsc)
* Configure the specified GPIO pin.
* Returns 0 on success, -EINVAL otherwise.
*/
static int lpc178x_gpio_config(const struct lpc178x_gpio_dsc *dsc, u32 regval)
int lpc178x_gpio_config(const struct lpc178x_gpio_dsc *dsc, u32 regval)
{
int rv;
......
......@@ -56,6 +56,7 @@
#define LPC178X_SCC_PCONP_PCUART0_MSK (1 << 3)
#define LPC178X_SCC_PCONP_PCUART1_MSK (1 << 4)
#define LPC178X_SCC_PCONP_PCUART4_MSK (1 << 8)
#define LPC178X_SCC_PCONP_PCEMC_MSK (1 << 11)
#define LPC178X_SCC_PCONP_PCGPIO_MSK (1 << 15)
#define LPC178X_SCC_PCONP_PCUART2_MSK (1 << 24)
#define LPC178X_SCC_PCONP_PCUART3_MSK (1 << 25)
......@@ -126,6 +127,19 @@ struct lpc178x_scc_regs {
u32 scs; /* System Controls and Status register */
u32 rsv0;
u32 pclksel; /* Peripheral Clock Selection register */
/* 0x400FC1AC */
u32 rsv1[7];
/* 0x400FC1C8 */
u32 clkoutcfg;
u32 rstcon0;
u32 rstcon1;
/* 0x400FC1D4 */
u32 rsv2[2];
/* 0x400FC1DC */
u32 emcdlyctl;
u32 emccal;
};
/*
......@@ -145,6 +159,7 @@ extern void lpc178x_periph_enable(u32 pconp_mask, int enable);
*/
enum clock {
CLOCK_SYSTICK, /* Systimer clock frequency expressed in Hz */
CLOCK_EMCCLK, /* EMC clock frequency expressed in Hz */
CLOCK_PCLK, /* Peripheral clock frequency expressed in Hz */
CLOCK_END /* for internal usage */
};
......
......@@ -89,7 +89,14 @@ struct lpc178x_gpio_pin_config {
};
/*
* Configure a set of GPIO pins using the given configuration table
* Configure the specified GPIO pin.
* Returns 0 on success, -EINVAL otherwise.
*/
int lpc178x_gpio_config(const struct lpc178x_gpio_dsc *dsc, u32 regval);
/*
* Configure a set of GPIO pins using the given configuration table.
* Returns 0 on success.
*/
extern int lpc178x_gpio_config_table(
const struct lpc178x_gpio_pin_config *table, unsigned int len);
......
......@@ -165,6 +165,10 @@
#define CONFIG_SYS_RAM_BASE (0xA0000000 + \
(CONFIG_SYS_RAM_CS * 0x10000000))
#define CONFIG_SYS_RAM_SIZE (32 * 1024 * 1024)
/*
* Use the CPU_CLOCK/2 for EMC
*/
#define CONFIG_LPC178X_EMC_HALFCPU
/*
* Configuration of the external Flash memory
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment