Add Broadcom's code for bcm63xx support
[project/bcm63xx/atf.git] / plat / bcm / drivers / pmc_drv.c
1 /* SPDX-License-Identifier: GPL-2.0+
2 *
3 * Copyright 2019 Broadcom Ltd.
4 */
5 /*
6 <:copyright-BRCM:2013:DUAL/GPL:standard
7
8 Copyright (c) 2013 Broadcom
9 All Rights Reserved
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License, version 2, as published by
13 the Free Software Foundation (the "GPL").
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20
21 A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php, or by
22 writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA.
24
25 :>
26 */
27
28 #include <debug.h>
29 #include <platform_def.h>
30 #include <delay_timer.h>
31 #include "pmc_drv.h"
32 #include "BPCM.h"
33 #include "command.h"
34
35 #if IS_BCMCHIP(6858) || defined(PMC_IMPL_3_X)
36 #include "clk_rst.h"
37 #endif
38
39 int pmc_mode = PMC_MODE_DQM;
40
41 static int SendAndWait(TCommand * cmd, TCommand * rsp)
42 {
43 #if defined(PMC_ON_HOSTCPU)
44 rsp->u.cmdGenericParams.params[0] = 0;
45 rsp->u.cmdGenericParams.params[1] = 0;
46 return 0;
47 #else
48 #if IS_BCMCHIP(63138)
49 /* translate new cmdID into old cmdID that the pmc will understand NB:
50 * requires cmdIDs below to be the new versions
51 */
52
53 static const unsigned char newToOldcmdIDMap[] = {
54 [cmdSetRunState] = 64, // cmdSetRunState,
55 [cmdSetPowerState] = 65, // cmdSetPowerState,
56 [cmdShutdownAllowed] = 66, // cmdShutdownAllowed,
57 [cmdGetSelect0] = 67, // cmdGetSelect0,
58 [cmdGetSelect3] = 68, // cmdGetSelect3,
59 [cmdGetAvsDisableState] = 69, // cmdGetAvsDisableState,
60 [cmdGetPVT] = 70, // cmdGetPVT,
61 [cmdPowerDevOnOff] = 129, // cmdPowerDevOnOff,
62 [cmdPowerZoneOnOff] = 130, // cmdPowerZoneOnOff,
63 [cmdResetDevice] = 131, // cmdResetDevice,
64 [cmdResetZone] = 132, // cmdResetZone,
65 [cmdAllocateG2UDQM] = 133, // cmdAllocateG2UDQM,
66 [cmdQSMAvailable] = 134, // cmdQSMAvailable,
67 [cmdRevision] = 135, // cmdRevision,
68 };
69
70 static int pmc_remap = 0;
71 #endif
72 static uint32_t reqdID = 1;
73 int status = kPMC_COMMAND_TIMEOUT;
74 TCommand dummy;
75
76 #if defined(BOOT_MEMC_SRAM)
77 reqdID = 1;
78 #endif
79 pmc_spin_lock();
80
81 /* clear previous rsp data if any */
82 while (PMC->dqm.notEmptySts & PMC_DQM_RPL_STS) {
83 if (!rsp)
84 rsp = &dummy;
85
86 rsp->word0.Reg32 = PMC->dqmQData[PMC_DQM_RPL_NUM].word[0];
87 rsp->word1.Reg32 = PMC->dqmQData[PMC_DQM_RPL_NUM].word[1];
88 rsp->u.cmdGenericParams.params[0] =
89 PMC->dqmQData[PMC_DQM_RPL_NUM].word[2];
90 rsp->u.cmdGenericParams.params[1] =
91 PMC->dqmQData[PMC_DQM_RPL_NUM].word[3];
92
93 printk
94 ("PMC reqdID=%d previous rsp.word[0-3]=0x[%08x %08x %08x %08x] status=%d\n",
95 reqdID, rsp->word0.Reg32, rsp->word1.Reg32,
96 rsp->u.cmdGenericParams.params[0],
97 rsp->u.cmdGenericParams.params[1], rsp->word0.Bits.error);
98 }
99
100 #if IS_BCMCHIP(63138)
101 if (pmc_remap && cmd->word0.Bits.cmdID < sizeof newToOldcmdIDMap &&
102 newToOldcmdIDMap[cmd->word0.Bits.cmdID])
103 cmd->word0.Bits.cmdID = newToOldcmdIDMap[cmd->word0.Bits.cmdID];
104 #endif
105
106 #ifdef PMC_LOG_IN_DTCM
107 if (cmd->word0.Bits.cmdID == cmdCloseAVS)
108 PMC->ctrl.hostMboxOut = 1; // request sync dtcm log
109 #endif
110
111 cmd->word0.Bits.msgID = reqdID;
112
113 /* send the command */
114 PMC->dqmQData[PMC_DQM_REQ_NUM].word[0] = cmd->word0.Reg32;
115 PMC->dqmQData[PMC_DQM_REQ_NUM].word[1] = cmd->word1.Reg32;
116 PMC->dqmQData[PMC_DQM_REQ_NUM].word[2] =
117 cmd->u.cmdGenericParams.params[0];
118 PMC->dqmQData[PMC_DQM_REQ_NUM].word[3] =
119 cmd->u.cmdGenericParams.params[1];
120
121 #ifdef CONFIG_BRCM_IKOS
122 /* We do not enable PMC TIMER here for IKOS, or it will wait forever */
123 while (!(PMC->dqm.notEmptySts & PMC_DQM_RPL_STS)) ;
124 #elif defined(PMC_IMPL_3_X)
125 #ifdef PMC_LOG_IN_DTCM
126 if (cmd->word0.Bits.cmdID == cmdCloseAVS) {
127 while (!(PMC->dqm.notEmptySts & PMC_DQM_RPL_STS))
128 pmc_show_log_item();
129
130 PMC->ctrl.hostMboxOut = 0; // ignore dtcm log
131 }
132 else
133 #endif // #ifdef PMC_LOG_IN_DTCM
134 {
135 PMC->ctrl.gpTmr0Ctl = ((1 << 31) | (1 << 29) |
136 ((400000 << 1) & 0x1fffffff)); // 400ms
137
138 while (!(PMC->dqm.notEmptySts & PMC_DQM_RPL_STS) &&
139 (PMC->ctrl.gpTmr0Ctl & (1 << 31))) ;
140 }
141 #else
142 PMC->ctrl.gpTmr2Ctl = ((1 << 31) | (1 << 29) | 400000); // 400ms
143
144 while (!(PMC->dqm.notEmptySts & PMC_DQM_RPL_STS) &&
145 (PMC->ctrl.gpTmr2Ctl & (1 << 31))) {
146 #if !defined(_CFE_) && (IS_BCMCHIP(63148) || IS_BCMCHIP(4908))
147 /* Do not tight poll the PMC registers for longer command */
148 if (cmd->word0.Bits.cmdID == cmdCloseAVS)
149 udelay(1000);
150 #endif
151 }
152 #endif /* CONFIG_BRCM_IKOS */
153
154 if (PMC->dqm.notEmptySts & PMC_DQM_RPL_STS) {
155 if (!rsp)
156 rsp = &dummy;
157
158 /* command didn't timeout, fill in the response */
159 rsp->word0.Reg32 = PMC->dqmQData[PMC_DQM_RPL_NUM].word[0];
160 rsp->word1.Reg32 = PMC->dqmQData[PMC_DQM_RPL_NUM].word[1];
161 rsp->u.cmdGenericParams.params[0] =
162 PMC->dqmQData[PMC_DQM_RPL_NUM].word[2];
163 rsp->u.cmdGenericParams.params[1] =
164 PMC->dqmQData[PMC_DQM_RPL_NUM].word[3];
165
166 if (rsp->word0.Bits.msgID == reqdID)
167 status = rsp->word0.Bits.error;
168 else
169 status = kPMC_MESSAGE_ID_MISMATCH;
170
171 if (status != kPMC_NO_ERROR)
172 printk
173 ("PMC reqdID=%d error=%d rsp.word[0-3]=0x[%08x %08x %08x %08x]\n",
174 reqdID, status, rsp->word0.Reg32, rsp->word1.Reg32,
175 rsp->u.cmdGenericParams.params[0],
176 rsp->u.cmdGenericParams.params[1]);
177 }
178
179 reqdID = (reqdID + 1) & 0xff;
180
181 pmc_spin_unlock();
182
183 return status;
184 #endif
185 }
186
187 static int SendCmd(TCommand * cmd, int cmdID, int devAddr, int zone, int island,
188 TCommand * rsp)
189 {
190 cmd->word0.Reg32 = 0;
191 cmd->word0.Bits.cmdID = cmdID;
192 cmd->word1.Reg32 = 0;
193 cmd->word1.Bits.devAddr = devAddr;
194 cmd->word1.Bits.zoneIdx = zone;
195 cmd->word1.Bits.island = island;
196
197 return SendAndWait(cmd, rsp);
198 }
199
200 int SendCommand(int cmdID, int devAddr, int zone, int island, uint32_t word2,
201 uint32_t word3, TCommand * rsp)
202 {
203 TCommand cmd;
204
205 cmd.u.cmdGenericParams.params[0] = word2;
206 cmd.u.cmdGenericParams.params[1] = word3;
207
208 return SendCmd(&cmd, cmdID, devAddr, zone, island, rsp);
209 }
210
211
212 #if defined(PMC_IMPL_3_X) || defined(PMC_ON_HOSTCPU)
213 #ifdef PMC_ON_HOSTCPU
214 #define KEYHOLE_IDX 1
215 #else
216 #define KEYHOLE_IDX 0
217 #endif
218 int read_bpcm_reg_direct(int devAddr, int wordOffset, uint32_t * value)
219 {
220 int status = kPMC_NO_ERROR;
221 int bus = (devAddr >> PMB_BUS_ID_SHIFT) & 0x3;
222 uint32_t address, ctlSts;
223 volatile PMB_keyhole_reg *keyhole = &PMB->keyhole[KEYHOLE_IDX];
224
225
226 address =
227 ((devAddr & 0xff) *
228 ((PMB->
229 config >> PMB_NUM_REGS_SHIFT) & PMB_NUM_REGS_MASK)) |
230 (wordOffset);
231
232 keyhole->control =
233 PMC_PMBM_START | (bus << PMC_PMBM_BUS_SHIFT) | (PMC_PMBM_Read) |
234 address;
235 ctlSts = keyhole->control;
236 while (ctlSts & PMC_PMBM_BUSY)
237 ctlSts = keyhole->control; /*wait for completion */
238
239 if (ctlSts & PMC_PMBM_TIMEOUT)
240 status = kPMC_COMMAND_TIMEOUT;
241 else
242 *value = keyhole->rd_data;
243
244 return status;
245 }
246
247 int write_bpcm_reg_direct(int devAddr, int wordOffset, uint32_t value)
248 {
249 int status = kPMC_NO_ERROR;
250 int bus = (devAddr >> PMB_BUS_ID_SHIFT) & 0x3;
251 uint32_t address, ctlSts;
252 volatile PMB_keyhole_reg *keyhole = &PMB->keyhole[KEYHOLE_IDX];
253
254 address =
255 ((devAddr & 0xff) *
256 ((PMB->
257 config >> PMB_NUM_REGS_SHIFT) & PMB_NUM_REGS_MASK)) |
258 (wordOffset);
259 keyhole->wr_data = value;
260 keyhole->control =
261 PMC_PMBM_START | (bus << PMC_PMBM_BUS_SHIFT) | (PMC_PMBM_Write) |
262 address;
263
264 ctlSts = keyhole->control;
265 while (ctlSts & PMC_PMBM_BUSY)
266 ctlSts = keyhole->control; /*wait for completion */
267
268 if (ctlSts & PMC_PMBM_TIMEOUT)
269 status = kPMC_COMMAND_TIMEOUT;
270
271 return status;
272 }
273
274
275 #else // #if defined(PMC_IMPL_3_X) || defined(PMC_ON_HOSTCPU)
276 int read_bpcm_reg_direct(int devAddr, int wordOffset, uint32_t * value)
277 {
278 int status = kPMC_NO_ERROR;
279 int bus = (devAddr >> PMB_BUS_ID_SHIFT) & 0x3;
280 volatile PMBMaster *pmbm_ptr;
281
282 if (bus >= PMB_BUS_MAX)
283 return kPMC_INVALID_BUS;
284
285 pmbm_ptr = &(PROCMON->PMBM[bus]);
286
287 /* Make sure PMBM is not busy */
288
289 pmbm_ptr->ctrl = PMC_PMBM_START | PMC_PMBM_Read |
290 ((devAddr & 0xff) << 12) | wordOffset;
291
292 while (pmbm_ptr->ctrl & PMC_PMBM_START) ;
293
294 if (pmbm_ptr->ctrl & PMC_PMBM_TIMEOUT)
295 status = kPMC_COMMAND_TIMEOUT;
296 else
297 *value = pmbm_ptr->rd_data;
298
299 return status;
300 }
301
302 int write_bpcm_reg_direct(int devAddr, int wordOffset, uint32_t value)
303 {
304 int bus = (devAddr >> PMB_BUS_ID_SHIFT) & 0x3;
305 int status = kPMC_NO_ERROR;
306 volatile PMBMaster *pmbm_ptr;
307 if (bus >= PMB_BUS_MAX)
308 return kPMC_INVALID_BUS;
309
310 pmbm_ptr = &(PROCMON->PMBM[bus]);
311
312 pmbm_ptr->wr_data = value;
313 pmbm_ptr->ctrl = PMC_PMBM_START | PMC_PMBM_Write |
314 ((devAddr & 0xff) << 12) | wordOffset;
315
316 while (pmbm_ptr->ctrl & PMC_PMBM_START) ;
317
318 if (pmbm_ptr->ctrl & PMC_PMBM_TIMEOUT)
319 status = kPMC_COMMAND_TIMEOUT;
320
321 return status;
322 }
323 #endif // #if defined(PMC_IMPL_3_X) || defined(PMC_ON_HOSTCPU)
324
325 /* note: all the [Read|Write][BPCM|Zone]Register functions are different from
326 * how they are defined in firmware code. In the driver code, it takes in
327 * wordOffset as the argument, but in the firmware code, it uses byteOffset */
328 int ReadBPCMRegister(int devAddr, int wordOffset, uint32_t * value)
329 {
330 int status = kPMC_INVALID_STATE;
331
332 if (PMC_ACCESS_BPCM_DIRECT || pmc_mode == PMC_MODE_PMB_DIRECT) {
333 pmc_spin_lock();
334 status = read_bpcm_reg_direct(devAddr, wordOffset, value);
335 pmc_spin_unlock();
336 } else if (pmc_mode == PMC_MODE_DQM) {
337 TCommand rsp;
338 status =
339 SendCommand(cmdReadBpcmReg, devAddr, 0, 0, wordOffset, 0,
340 &rsp);
341
342 if (status == kPMC_NO_ERROR)
343 *value = rsp.u.cmdResponse.word2;
344 }
345
346 return status;
347 }
348
349 int WriteBPCMRegister(int devAddr, int wordOffset, uint32_t value)
350 {
351 int status = kPMC_INVALID_STATE;
352
353 if (PMC_ACCESS_BPCM_DIRECT || pmc_mode == PMC_MODE_PMB_DIRECT) {
354 pmc_spin_lock();
355 status = write_bpcm_reg_direct(devAddr, wordOffset, value);
356 pmc_spin_unlock();
357 } else if (pmc_mode == PMC_MODE_DQM) {
358 status =
359 SendCommand(cmdWriteBpcmReg, devAddr, 0, 0, wordOffset,
360 value, 0);
361 }
362
363 return status;
364 }
365
366
367 int PowerOnZone(int devAddr, int zone)
368 {
369 BPCM_PWR_ZONE_N_CONTROL reg;
370 int status;
371
372 #if IS_BCMCHIP(6858)
373 /* Do not use DQM command cmdPowerZoneOnOff for non 6858 because this command is only available if a
374 PMC application has been uploaded to expand the PMC boot rom functionality */
375 if (pmc_mode == PMC_MODE_DQM) {
376 TCommand cmd = {0};
377 cmd.u.cmdStateOnlyParam.state = 1;
378 return SendCmd(&cmd, cmdPowerZoneOnOff, devAddr, zone, 0, 0);
379 }
380 #endif
381
382 status =
383 ReadBPCMRegister(devAddr, BPCMRegOffset(zones[zone].control),
384 &reg.Reg32);
385 if (status == kPMC_NO_ERROR && reg.Bits.pwr_on_state == 0) {
386 reg.Bits.pwr_dn_req = 0;
387 reg.Bits.dpg_ctl_en = 1;
388 reg.Bits.pwr_up_req = 1;
389 reg.Bits.mem_pwr_ctl_en = 1;
390 reg.Bits.blk_reset_assert = 1;
391 status =
392 WriteBPCMRegister(devAddr,
393 BPCMRegOffset(zones[zone].control),
394 reg.Reg32);
395 }
396 return status;
397 }
398
399 int PowerOnDevice(int devAddr)
400 {
401 if (PMC_ACCESS_BPCM_DIRECT || pmc_mode == PMC_MODE_PMB_DIRECT) {
402 int ix, status;
403 BPCM_CAPABILITES_REG capabilities;
404
405 status =
406 ReadBPCMRegister(devAddr, BPCMRegOffset(capabilities),
407 &capabilities.Reg32);
408 for (ix = 0;
409 (ix < capabilities.Bits.num_zones)
410 && (status == kPMC_NO_ERROR); ix++) {
411 status = PowerOnZone(devAddr, ix);
412 }
413
414 return status;
415 }
416
417 if (pmc_mode == PMC_MODE_DQM) {
418 TCommand cmd = {0};
419 cmd.u.cmdPowerDevice.state = 1;
420 return SendCmd(&cmd, cmdPowerDevOnOff, devAddr, 0, 0, 0);
421 }
422
423 return kPMC_INVALID_STATE;
424 }
425
426 int PowerOffDevice(int devAddr, int repower)
427 {
428 if (PMC_ACCESS_BPCM_DIRECT || pmc_mode == PMC_MODE_PMB_DIRECT) {
429 /* we can power off the entire device by powering off the 0th zone. */
430 BPCM_PWR_ZONE_N_CONTROL reg;
431 int status;
432
433 status =
434 ReadBPCMRegister(devAddr, BPCMRegOffset(zones[0].control),
435 &reg.Reg32);
436
437 if (status == kPMC_NO_ERROR && reg.Bits.pwr_off_state == 0) {
438 reg.Bits.pwr_dn_req = 1;
439 WriteBPCMRegister(devAddr,
440 BPCMRegOffset(zones[0].control),
441 reg.Reg32);
442 }
443
444 return status;
445 }
446
447 if (pmc_mode == PMC_MODE_DQM) {
448 TCommand cmd = {0};
449 cmd.u.cmdPowerDevice.state = 0;
450 cmd.u.cmdPowerDevice.restore = repower;
451 return SendCmd(&cmd, cmdPowerDevOnOff, devAddr, 0, 0, 0);
452 }
453
454 return kPMC_INVALID_STATE;
455 }
456
457 int ResetDevice(int devAddr)
458 {
459 /* all zones had their blk_reset_assert bits set at initial config time */
460 BPCM_PWR_ZONE_N_CONTROL reg;
461 int status;
462
463 #if IS_BCMCHIP(6858)
464 /* Do not use DQM command cmdResetDevice for non 6858 because this command is only available if a
465 PMC application has been uploaded to expand the PMC boot rom functionality */
466 if (pmc_mode == PMC_MODE_DQM)
467 return SendCommand(cmdResetDevice, devAddr, 0, 0, 0, 0, 0);
468 #endif
469
470 status = PowerOffDevice(devAddr, 0);
471 do {
472 status =
473 ReadBPCMRegister(devAddr, BPCMRegOffset(zones[0].control),
474 &reg.Reg32);
475 } while ((reg.Bits.pwr_off_state != 1) && (status == kPMC_NO_ERROR));
476 if (status == kPMC_NO_ERROR)
477 status = PowerOnDevice(devAddr);
478 return status;
479 }
480
481 // initalize pmc_mode (possibly) before printk available
482 void pmc_initmode(void)
483 {
484 #if defined MISC_STRAP_BUS_PMC_ROM_BOOT
485 /* read the strap pin and based on the strap pin, choose the mode */
486 if ((MISC->miscStrapBus & MISC_STRAP_BUS_PMC_ROM_BOOT) == 0)
487 pmc_mode = PMC_MODE_PMB_DIRECT;
488 #else // #if defined MISC_STRAP_BUS_PMC_ROM_BOOT
489 #if IS_BCMCHIP(6858)
490 pmc_mode = PMC_MODE_DQM;
491 #else
492 pmc_mode = PMC_MODE_PMB_DIRECT;
493 #ifdef CFG_RAMAPP
494 #if IS_BCMCHIP(63158)
495 /* MIPS based PMC */
496 if (PMC->ctrl.softResets == 0)
497 pmc_mode = PMC_MODE_DQM;
498 #elif defined(PMC_IMPL_3_X)
499 /* Maestro based PMC) */
500 if (PROCMON->maestroReg.coreCtrl.coreEnable == 1)
501 pmc_mode = PMC_MODE_DQM;
502 #endif // #if IS_BCMCHIP(63158)
503 #endif // #ifdef CFG_RAMAPP
504 #endif // #if IS_BCMCHIP(6858)
505 #endif // #if defined MISC_STRAP_BUS_PMC_ROM_BOOT
506 }
507
508
509
510