summaryrefslogtreecommitdiff
path: root/bsp/nxp/lpc/lpc408x/drivers/drv_sdram.c
blob: a0473bae0110415de1662b50bcc3b5550dfe9036 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2013-05-19     Bernard      The first version for LPC40xx
 */

#include <rtthread.h>

#ifdef BSP_USING_SDRAM
#include "drv_sdram.h"

#include <lpc_emc.h>
#include <lpc_timer.h>

static void  sdram_gpio_config(void)
{
    LPC_IOCON->P3_0 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* D0 @ P3.0 */
    LPC_IOCON->P3_1 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* D1 @ P3.1 */
    LPC_IOCON->P3_2 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* D2 @ P3.2 */
    LPC_IOCON->P3_3 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* D3 @ P3.3 */

    LPC_IOCON->P3_4 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* D4 @ P3.4 */
    LPC_IOCON->P3_5 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* D5 @ P3.5 */
    LPC_IOCON->P3_6 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* D6 @ P3.6 */
    LPC_IOCON->P3_7 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* D7 @ P3.7 */

    LPC_IOCON->P3_8 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* D8 @ P3.8 */
    LPC_IOCON->P3_9 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* D9 @ P3.9 */
    LPC_IOCON->P3_10 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* D10 @ P3.10 */
    LPC_IOCON->P3_11 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* D11 @ P3.11 */

    LPC_IOCON->P3_12 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* D12 @ P3.12 */
    LPC_IOCON->P3_13 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* D13 @ P3.13 */
    LPC_IOCON->P3_14 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* D14 @ P3.14 */
    LPC_IOCON->P3_15 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* D15 @ P3.15 */


    LPC_IOCON->P4_0 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* A0 @ P4.0 */
    LPC_IOCON->P4_1 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* A1 @ P4.1 */
    LPC_IOCON->P4_2 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* A2 @ P4.2 */
    LPC_IOCON->P4_3 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* A3 @ P4.3 */

    LPC_IOCON->P4_4 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* A4 @ P4.4 */
    LPC_IOCON->P4_5 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* A5 @ P4.5 */
    LPC_IOCON->P4_6 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* A6 @ P4.6 */
    LPC_IOCON->P4_7 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* A7 @ P4.7 */

    LPC_IOCON->P4_8 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* A8 @ P4.8 */
    LPC_IOCON->P4_9 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* A9 @ P4.9 */
    LPC_IOCON->P4_10 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* A10 @ P4.10 */
    LPC_IOCON->P4_11 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* A11 @ P4.11 */

    LPC_IOCON->P4_12 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* A12 @ P4.12 */
    LPC_IOCON->P4_13 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* A13 @ P4.13 */
    LPC_IOCON->P4_14 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* A14 @ P4.14 */

    LPC_IOCON->P4_25 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* WEN @ P4.25 */

    LPC_IOCON->P2_16 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* CASN @ P2.16 */
    LPC_IOCON->P2_17 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* RASN @ P2.17 */
    LPC_IOCON->P2_18 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* CLK[0] @ P2.18 */
    LPC_IOCON->P2_19 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* CLK[1] @ P2.19 */

    LPC_IOCON->P2_20 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* DYCSN[0] @ P2.20 */
    LPC_IOCON->P2_24 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* CKE[0] @ P2.24 */

    LPC_IOCON->P2_28 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* DQM[0] @ P2.28 */
    LPC_IOCON->P2_29 = (1 << 0 | 0 << 3 | 0 << 5 | 1 << 9); /* DQM[1] @ P2.29 */
}

void rt_hw_sdram_init(void)
{
    volatile uint32_t i;
    volatile uint32_t dwtemp;
    uint16_t wtemp = wtemp;
    TIM_TIMERCFG_Type TIM_ConfigStruct;

    TIM_ConfigStruct.PrescaleOption = TIM_PRESCALE_USVAL;
    TIM_ConfigStruct.PrescaleValue  = 1;

    /* Set configuration for Tim_config and Tim_MatchConfig */
    TIM_Init(LPC_TIM0, TIM_TIMER_MODE, &TIM_ConfigStruct);

    LPC_SC->PCONP      |= 0x00000800;
    LPC_SC->EMCDLYCTL   = 0x00001010;
    LPC_EMC->Control = 0x00000001;
    LPC_EMC->Config  = 0x00000000;

    sdram_gpio_config();

    LPC_EMC->DynamicRP         = EMC_NS2CLK(20);        /* 20ns  */
    LPC_EMC->DynamicRAS        =  15;                   /* EMC_NS2CLK(42, nsPerClk),42ns to 100K ns  */
    LPC_EMC->DynamicSREX       = 1 - 1;                 /* tSRE, 1clk */
    LPC_EMC->DynamicAPR        = 2 - 1;                 /* Not found!!! Estimated as 2clk */
    LPC_EMC->DynamicDAL        = EMC_NS2CLK(20) + 2;    /* tDAL = tRP + tDPL = 20ns + 2clk  */
    LPC_EMC->DynamicWR         = 2 - 1;                 /* 2CLK */
    LPC_EMC->DynamicRC         = EMC_NS2CLK(63);        /* H57V2562GTR-75C tRC=63ns(min)*/
    LPC_EMC->DynamicRFC        = EMC_NS2CLK(63);        /* H57V2562GTR-75C tRFC=tRC */
    LPC_EMC->DynamicXSR        = 0x0000000F;            /* exit self-refresh to active */
    LPC_EMC->DynamicRRD        = EMC_NS2CLK(63);        /* 3clk, tRRD=15ns(min) */
    LPC_EMC->DynamicMRD        = 2 - 1;                 /* 2clk, tMRD=2clk(min) */

    LPC_EMC->DynamicReadConfig = 0x00000001;            /* Command delayed strategy, using EMCCLKDELAY */
    /* H57V2562GTR-75C: tCL=3CLK, tRCD=20ns(min), 3 CLK=24ns */
    LPC_EMC->DynamicRasCas0    = 0x303;

    /* For Manley lpc1778 SDRAM: H57V2562GTR-75C, 256Mb, 16Mx16, 4 banks, row=13, column=9 */
#ifdef SDRAM_CONFIG_16BIT
    LPC_EMC->DynamicConfig0    = 0x680;                 /* 256Mb, 16Mx16, 4 banks, row=13, column=9, RBC */
#elif defined SDRAM_CONFIG_32BIT
    LPC_EMC->DynamicConfig0 = 0x4680;                   /* 256Mb, 16Mx16, 4 banks, row=13, column=9, RBC */
#endif
    TIM_Waitms(100);

    LPC_EMC->DynamicControl    = 0x00000183;            /* Issue NOP command */
    TIM_Waitms(200);                                    /* wait 200ms */

    LPC_EMC->DynamicControl    = 0x00000103;            /* Issue PALL command */

    LPC_EMC->DynamicRefresh    = 0x00000002;            /* ( n * 16 ) -> 32 clock cycles */
    for (i = 0; i < 0x80; i++);                         /* wait 128 AHB clock cycles */

    LPC_EMC->DynamicRefresh    = EMC_SDRAM_REFRESH(64);

    LPC_EMC->DynamicControl    = 0x00000083;            /* Issue MODE command */

#ifdef SDRAM_CONFIG_16BIT
    wtemp = *((volatile uint16_t *)(EXT_SDRAM_BEGIN | (0x33 << 12)));   /* 8 burst, 3 CAS latency */
#elif defined SDRAM_CONFIG_32BIT
    dwtemp = *((volatile uint32_t *)(SDRAM_BASE | (0x32 << 13)));       /* 4 burst, 3 CAS latency */
#endif

    LPC_EMC->DynamicControl    = 0x00000000;                            /* Issue NORMAL command */

    LPC_EMC->DynamicConfig0 |= 0x80000;                                 /* enable buffer */
    TIM_Waitms(1);

    TIM_DeInit(LPC_TIM0);
}

#endif /* BSP_USING_SDRAM */