分支自 DSP/ADSP21569/DSP-21569

graydon
2023-09-20 d40b58b3ecbfb79e015f55755127849335e289b7
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
/*
 * dmc.c
 *
 *  Created on: 2021Äê10ÔÂ30ÈÕ
 *      Author: graydon
 */
 
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include <sys/platform.h>
#include <sys/adi_core.h>
#include "DMCInit.h"
 
 
/* delay function */
#pragma inline
static void dmcdelay(uint32_t delay)
{
  uint32_t i;
  for(i=delay; i>0ul; i--){
      NOP();
  }
}
 
 
 
/* DMC phy ZQ calibration routine
 * The first step in DMC initialization
 */
void adi_dmc_phy_calibration(ADI_DMC_CONFIG *pConfig,uint32_t csel_dsel)
{
     /* Program the ODT and drive strength values */
 
  *pREG_DMC0_DDR_ZQ_CTL0 = pConfig->ulDDR_ZQCTL0;
  *pREG_DMC0_DDR_ZQ_CTL1 = pConfig->ulDDR_ZQCTL1;
  *pREG_DMC0_DDR_ZQ_CTL2 = pConfig->ulDDR_ZQCTL2;
 
    /* Generate the trigger */
  *pREG_DMC0_DDR_CA_CTL = 0x00000000ul ;
  *pREG_DMC0_DDR_ROOT_CTL = 0x00000000ul;
  *pREG_DMC0_DDR_ROOT_CTL = 0x00010000ul;
  dmcdelay(csel_dsel*8000ul);
 
     /* The [31:26] bits may change if pad ring changes */
  *pREG_DMC0_DDR_CA_CTL  = 0x0C000001ul|TrigCalib;
  dmcdelay(csel_dsel*8000ul);
  *pREG_DMC0_DDR_CA_CTL  = 0x00000000ul ;
  *pREG_DMC0_DDR_ROOT_CTL = 0x00000000ul ;
 
 
  /* DQS delay trim*/
  if (DelayTrim)
  {
    *pREG_DMC0_DDR_LANE0_CTL1|= (((Bypasscode)<<BITP_DMC_DDR_LANE0_CTL1_BYPCODE) & BITM_DMC_DDR_LANE0_CTL1_BYPCODE)|BITM_DMC_DDR_LANE0_CTL1_BYPDELCHAINEN;
    *pREG_DMC0_DDR_LANE1_CTL1|=(((Bypasscode)<<BITP_DMC_DDR_LANE1_CTL1_BYPCODE) & BITM_DMC_DDR_LANE1_CTL1_BYPCODE)|BITM_DMC_DDR_LANE1_CTL1_BYPDELCHAINEN;
  }
 
  /* DQS duty trim */
   if(DqsTrim)
   {
    *pREG_DMC0_DDR_LANE0_CTL0|= ((Dqscode)<<BITP_DMC_DDR_LANE0_CTL0_BYPENB) & (BITM_DMC_DDR_LANE1_CTL0_BYPENB|BITM_DMC_DDR_LANE0_CTL0_BYPSELP|BITM_DMC_DDR_LANE0_CTL0_BYPCODE);
    *pREG_DMC0_DDR_LANE1_CTL0|=((Dqscode)<<BITP_DMC_DDR_LANE1_CTL0_BYPENB) & (BITM_DMC_DDR_LANE1_CTL1_BYPCODE|BITM_DMC_DDR_LANE1_CTL0_BYPSELP|BITM_DMC_DDR_LANE1_CTL0_BYPCODE);
   }
 
   /* Clock duty trim */
   if(ClkTrim)
   {
     *pREG_DMC0_DDR_CA_CTL|=(((Clkcode <<BITP_DMC_DDR_CA_CTL_BYPCODE1)&BITM_DMC_DDR_CA_CTL_BYPCODE1)|BITM_DMC_DDR_CA_CTL_BYPENB|((CLKDIR<<BITP_DMC_DDR_CA_CTL_BYPSELP)&BITM_DMC_DDR_CA_CTL_BYPSELP));
   }
 
}
 
/*  DMC lane reset routine
 *  DMC lane reset should be performed when DMC clock is changed
 *  Sequence: Before changing the DDR clock frequency reset the lane , call cgu routine to change the DMC clock frequency
 *        Then take DMC lanes out of reset
 */
void adi_dmc_lane_reset(bool reset)
{
 
  if (reset) {
    *pREG_DMC0_DDR_LANE0_CTL0 |= BITM_DMC_DDR_LANE0_CTL0_CB_RSTDLL;
    *pREG_DMC0_DDR_LANE1_CTL0 |= BITM_DMC_DDR_LANE1_CTL0_CB_RSTDLL;
 
 
  } else {
    *pREG_DMC0_DDR_LANE0_CTL0 &= ~BITM_DMC_DDR_LANE0_CTL0_CB_RSTDLL;
    *pREG_DMC0_DDR_LANE1_CTL0 &= ~BITM_DMC_DDR_LANE1_CTL0_CB_RSTDLL;
 
  }
}
 
 
/* dmc_ctrl_init() configures DMC controller
 * It returns ADI_DMC_SUCCESS on success and ADI_DMC_FAILURE on failure
 */
 
ADI_DMC_RESULT adi_dmc_ctrl_init(ADI_DMC_CONFIG *pConfig,uint32_t csel_dsel)
{
 
  uint32_t phyphase,rd_cnt,t_EMR1,t_EMR3, t_CTL,data_cyc;
 
  /* program timing registers*/
  *pREG_DMC0_CFG = (pConfig->ulDDR_DLLCTLCFG) & 0xFFFFul;
  *pREG_DMC0_TR0 = pConfig->ulDDR_TR0;
  *pREG_DMC0_TR1 = pConfig->ulDDR_TR1;
  *pREG_DMC0_TR2 = pConfig->ulDDR_TR2;
 
  /* program shadow registers */
  *pREG_DMC0_MR =  ((pConfig->ulDDR_MREMR1) >> 16ul) & 0xFFFFul;
  *pREG_DMC0_MR1 = (pConfig->ulDDR_MREMR1) & 0xFFFFul;
  *pREG_DMC0_MR2 = (pConfig->ulDDR_EMR2EMR3)>>16ul & 0xFFFFul;
  *pREG_DMC0_EMR3 =(pConfig->ulDDR_EMR2EMR3) & 0xFFFFul;
 
  /* program Dll timing register */
  *pREG_DMC0_DLLCTL = ((pConfig->ulDDR_DLLCTLCFG) >> 16ul) & 0xFFFFul;
 
  dmcdelay(csel_dsel*2000ul);
 
  *pREG_DMC0_DDR_CA_CTL |=BITM_DMC_DDR_CA_CTL_SW_REFRESH;
 
  dmcdelay(csel_dsel_r*5ul);
 
  *pREG_DMC0_DDR_ROOT_CTL |= BITM_DMC_DDR_ROOT_CTL_SW_REFRESH | (OfstdCycle << BITP_DMC_DDR_ROOT_CTL_PIPE_OFSTDCYCLE);
 
  /* Start DMC initialization */
  *pREG_DMC0_CTL       = pConfig->ulDDR_CTL;
 
  dmcdelay(csel_dsel*12500ul);
 
  /* Add necessary delay depending on the configuration */
  t_EMR1=(pConfig->ulDDR_MREMR1 & BITM_DMC_MR1_WL)>>BITP_DMC_MR1_WL;
  if(t_EMR1)
  {
     dmcdelay(csel_dsel_r*600ul);
     while(((*pREG_DMC0_MR1 & BITM_DMC_MR1_WL)>>BITP_DMC_MR1_WL) != 0ul)
     {
 
     }
  }
 
 
  t_EMR3=(pConfig->ulDDR_EMR2EMR3 & BITM_DMC_EMR3_MPR)>>BITP_DMC_EMR3_MPR;
  if(t_EMR3)
  {
     dmcdelay(csel_dsel*2000ul);
     while(((*pREG_DMC0_EMR3 & BITM_DMC_EMR3_MPR)>>BITP_DMC_EMR3_MPR) != 0ul)
     {
     }
  }
 
 
  t_CTL=(pConfig->ulDDR_CTL & BITM_DMC_CTL_RL_DQS)>>BITP_DMC_CTL_RL_DQS;
  if(t_CTL)
  {
     dmcdelay(csel_dsel*600ul);
     while(((*pREG_DMC0_CTL & BITM_DMC_CTL_RL_DQS)>>BITP_DMC_CTL_RL_DQS) != 0ul)
     {
 
     }
  }
 
  /* check if DMC initialization finished, if not return error */
  while((*pREG_DMC0_STAT & BITM_DMC_STAT_INITDONE) !=BITM_DMC_STAT_INITDONE);
 
 
  /* End of DMC controller configuration, Start of Phy control registers */
 
  /* toggle DCYCLE */
 
  *pREG_DMC0_DDR_LANE0_CTL1 |= BITM_DMC_DDR_LANE0_CTL1_COMP_DCYCLE;
  *pREG_DMC0_DDR_LANE1_CTL1 |= BITM_DMC_DDR_LANE1_CTL1_COMP_DCYCLE;
 
  dmcdelay(csel_dsel_r*10ul);
 
  *pREG_DMC0_DDR_LANE0_CTL1 &= (~BITM_DMC_DDR_LANE0_CTL1_COMP_DCYCLE);
  *pREG_DMC0_DDR_LANE1_CTL1 &= (~BITM_DMC_DDR_LANE1_CTL1_COMP_DCYCLE);
 
  /* toggle RSTDAT */
  *pREG_DMC0_DDR_LANE0_CTL0 |= BITM_DMC_DDR_LANE0_CTL0_CB_RSTDAT;
  *pREG_DMC0_DDR_LANE0_CTL0 &= (~BITM_DMC_DDR_LANE0_CTL0_CB_RSTDAT);
 
  *pREG_DMC0_DDR_LANE1_CTL0 |= BITM_DMC_DDR_LANE1_CTL0_CB_RSTDAT;
  *pREG_DMC0_DDR_LANE1_CTL0 &= (~BITM_DMC_DDR_LANE1_CTL0_CB_RSTDAT);
 
  dmcdelay(csel_dsel*2500ul);
 
  /* Program phyphase*/
 
  phyphase = (*pREG_DMC0_STAT & BITM_DMC_STAT_PHYRDPHASE)>>BITP_DMC_STAT_PHYRDPHASE;
  data_cyc= (phyphase << BITP_DMC_DLLCTL_DATACYC) & BITM_DMC_DLLCTL_DATACYC;
  rd_cnt = ((pConfig->ulDDR_DLLCTLCFG) >> 16);
  rd_cnt <<= BITP_DMC_DLLCTL_DLLCALRDCNT;
  rd_cnt &= BITM_DMC_DLLCTL_DLLCALRDCNT;
 
  *pREG_DMC0_DLLCTL =rd_cnt|data_cyc;
 
  *pREG_DMC0_CTL = (pConfig->ulDDR_CTL & (~BITM_DMC_CTL_INIT) & (~BITM_DMC_CTL_RL_DQS));
 
  return ADI_DMC_SUCCESS;
 
}
 
/* In order to preserve ddr content while changing DMC clock, put memory in self refresh mode
 *
 * sequence: program DMC controller to enter self refresh mode. No further access should be issued to ddr memory
 *       call cgu routines to change DMC clock
 *       exit self-refresh mode
 *
 */
void adi_dmc_self_refresh(bool enter)
{
  if (enter){
    /*Set the SRREQ bit to enter self refresh mode*/
      while((*pREG_DMC0_STAT & BITM_DMC_STAT_IDLE)==0ul)
      {
 
      }
    *pREG_DMC0_CTL|= BITM_DMC_CTL_SRREQ;
 
    /*Wait for self refresh acknowledge from the controller*/
    while((*pREG_DMC0_STAT & BITM_DMC_STAT_SRACK)==0ul)
    {
 
    }
 
  }else{
    /*clear the SRREQ bit to exit self refresh mode*/
    *pREG_DMC0_CTL &= ~BITM_DMC_CTL_SRREQ;
 
    /*Wait for self refresh acknowledge from the controller*/
    while((*pREG_DMC0_STAT & BITM_DMC_STAT_SRACK)==1ul)
    {
 
    }
    /*Wait for the DMC to be in IDLE state*/
    while((*pREG_DMC0_STAT & BITM_DMC_STAT_IDLE)==0ul)
    {
 
    }
 
    *pREG_DMC0_CTL |=BITM_DMC_CTL_DLLCAL;
    /*Wait for DLL calib*/
    while((*pREG_DMC0_STAT & BITM_DMC_STAT_DLLCALDONE)==0ul)
    {
 
    }
 
  }
}
 
/**
 * @brief    Initializes DMC controller.
 *
 * @return   Status
 *           - 0: Successful in initializing DMC controller.
 *           - 1: Error.
 
 */
int dmc_cfg0_init(void)
{
 
    static ADI_DMC_CONFIG  CONFIG533 =
    {
            CFG0_REG_DDR_DLLCTLCFG,
            CFG0_REG_DMC_MR2MR3,
            CFG0_REG_DMC_CTL_VALUE,
            CFG0_REG_DMC_MRMR1,
            CFG0_REG_DMC_TR0_VALUE,
            CFG0_REG_DMC_TR1_VALUE,
            CFG0_REG_DMC_TR2_VALUE,
            0x00782828ul,
            0ul,
            0x70000000ul
    };
 
    /* Initialize DMC PHY registers*/
    adi_dmc_phy_calibration((&CONFIG533),csel_dsel_r);
 
    /* Initialize DMC Controller*/
    if(adi_dmc_ctrl_init((&CONFIG533),csel_dsel_r) != ADI_DMC_SUCCESS)
    {
       /* Return non-zero */
       return 1u;
    }
 
 
    return 0u;
}