1 /* SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2019 Broadcom Ltd.
6 <:copyright-BRCM:2013:DUAL/GPL:standard
8 Copyright (c) 2013 Broadcom
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").
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.
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.
29 #include <platform_def.h>
30 #include <delay_timer.h>
35 #if IS_BCMCHIP(6858) || defined(PMC_IMPL_3_X)
39 int pmc_mode
= PMC_MODE_DQM
;
41 static int SendAndWait(TCommand
* cmd
, TCommand
* rsp
)
43 #if defined(PMC_ON_HOSTCPU)
44 rsp
->u
.cmdGenericParams
.params
[0] = 0;
45 rsp
->u
.cmdGenericParams
.params
[1] = 0;
49 /* translate new cmdID into old cmdID that the pmc will understand NB:
50 * requires cmdIDs below to be the new versions
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,
70 static int pmc_remap
= 0;
72 static uint32_t reqdID
= 1;
73 int status
= kPMC_COMMAND_TIMEOUT
;
76 #if defined(BOOT_MEMC_SRAM)
81 /* clear previous rsp data if any */
82 while (PMC
->dqm
.notEmptySts
& PMC_DQM_RPL_STS
) {
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];
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
);
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
];
106 #ifdef PMC_LOG_IN_DTCM
107 if (cmd
->word0
.Bits
.cmdID
== cmdCloseAVS
)
108 PMC
->ctrl
.hostMboxOut
= 1; // request sync dtcm log
111 cmd
->word0
.Bits
.msgID
= reqdID
;
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];
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
))
130 PMC
->ctrl
.hostMboxOut
= 0; // ignore dtcm log
133 #endif // #ifdef PMC_LOG_IN_DTCM
135 PMC
->ctrl
.gpTmr0Ctl
= ((1 << 31) | (1 << 29) |
136 ((400000 << 1) & 0x1fffffff)); // 400ms
138 while (!(PMC
->dqm
.notEmptySts
& PMC_DQM_RPL_STS
) &&
139 (PMC
->ctrl
.gpTmr0Ctl
& (1 << 31))) ;
142 PMC
->ctrl
.gpTmr2Ctl
= ((1 << 31) | (1 << 29) | 400000); // 400ms
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
)
152 #endif /* CONFIG_BRCM_IKOS */
154 if (PMC
->dqm
.notEmptySts
& PMC_DQM_RPL_STS
) {
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];
166 if (rsp
->word0
.Bits
.msgID
== reqdID
)
167 status
= rsp
->word0
.Bits
.error
;
169 status
= kPMC_MESSAGE_ID_MISMATCH
;
171 if (status
!= kPMC_NO_ERROR
)
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]);
179 reqdID
= (reqdID
+ 1) & 0xff;
187 static int SendCmd(TCommand
* cmd
, int cmdID
, int devAddr
, int zone
, int island
,
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
;
197 return SendAndWait(cmd
, rsp
);
200 int SendCommand(int cmdID
, int devAddr
, int zone
, int island
, uint32_t word2
,
201 uint32_t word3
, TCommand
* rsp
)
205 cmd
.u
.cmdGenericParams
.params
[0] = word2
;
206 cmd
.u
.cmdGenericParams
.params
[1] = word3
;
208 return SendCmd(&cmd
, cmdID
, devAddr
, zone
, island
, rsp
);
212 #if defined(PMC_IMPL_3_X) || defined(PMC_ON_HOSTCPU)
213 #ifdef PMC_ON_HOSTCPU
214 #define KEYHOLE_IDX 1
216 #define KEYHOLE_IDX 0
218 int read_bpcm_reg_direct(int devAddr
, int wordOffset
, uint32_t * value
)
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
];
229 config
>> PMB_NUM_REGS_SHIFT
) & PMB_NUM_REGS_MASK
)) |
233 PMC_PMBM_START
| (bus
<< PMC_PMBM_BUS_SHIFT
) | (PMC_PMBM_Read
) |
235 ctlSts
= keyhole
->control
;
236 while (ctlSts
& PMC_PMBM_BUSY
)
237 ctlSts
= keyhole
->control
; /*wait for completion */
239 if (ctlSts
& PMC_PMBM_TIMEOUT
)
240 status
= kPMC_COMMAND_TIMEOUT
;
242 *value
= keyhole
->rd_data
;
247 int write_bpcm_reg_direct(int devAddr
, int wordOffset
, uint32_t value
)
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
];
257 config
>> PMB_NUM_REGS_SHIFT
) & PMB_NUM_REGS_MASK
)) |
259 keyhole
->wr_data
= value
;
261 PMC_PMBM_START
| (bus
<< PMC_PMBM_BUS_SHIFT
) | (PMC_PMBM_Write
) |
264 ctlSts
= keyhole
->control
;
265 while (ctlSts
& PMC_PMBM_BUSY
)
266 ctlSts
= keyhole
->control
; /*wait for completion */
268 if (ctlSts
& PMC_PMBM_TIMEOUT
)
269 status
= kPMC_COMMAND_TIMEOUT
;
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
)
278 int status
= kPMC_NO_ERROR
;
279 int bus
= (devAddr
>> PMB_BUS_ID_SHIFT
) & 0x3;
280 volatile PMBMaster
*pmbm_ptr
;
282 if (bus
>= PMB_BUS_MAX
)
283 return kPMC_INVALID_BUS
;
285 pmbm_ptr
= &(PROCMON
->PMBM
[bus
]);
287 /* Make sure PMBM is not busy */
289 pmbm_ptr
->ctrl
= PMC_PMBM_START
| PMC_PMBM_Read
|
290 ((devAddr
& 0xff) << 12) | wordOffset
;
292 while (pmbm_ptr
->ctrl
& PMC_PMBM_START
) ;
294 if (pmbm_ptr
->ctrl
& PMC_PMBM_TIMEOUT
)
295 status
= kPMC_COMMAND_TIMEOUT
;
297 *value
= pmbm_ptr
->rd_data
;
302 int write_bpcm_reg_direct(int devAddr
, int wordOffset
, uint32_t value
)
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
;
310 pmbm_ptr
= &(PROCMON
->PMBM
[bus
]);
312 pmbm_ptr
->wr_data
= value
;
313 pmbm_ptr
->ctrl
= PMC_PMBM_START
| PMC_PMBM_Write
|
314 ((devAddr
& 0xff) << 12) | wordOffset
;
316 while (pmbm_ptr
->ctrl
& PMC_PMBM_START
) ;
318 if (pmbm_ptr
->ctrl
& PMC_PMBM_TIMEOUT
)
319 status
= kPMC_COMMAND_TIMEOUT
;
323 #endif // #if defined(PMC_IMPL_3_X) || defined(PMC_ON_HOSTCPU)
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
)
330 int status
= kPMC_INVALID_STATE
;
332 if (PMC_ACCESS_BPCM_DIRECT
|| pmc_mode
== PMC_MODE_PMB_DIRECT
) {
334 status
= read_bpcm_reg_direct(devAddr
, wordOffset
, value
);
336 } else if (pmc_mode
== PMC_MODE_DQM
) {
339 SendCommand(cmdReadBpcmReg
, devAddr
, 0, 0, wordOffset
, 0,
342 if (status
== kPMC_NO_ERROR
)
343 *value
= rsp
.u
.cmdResponse
.word2
;
349 int WriteBPCMRegister(int devAddr
, int wordOffset
, uint32_t value
)
351 int status
= kPMC_INVALID_STATE
;
353 if (PMC_ACCESS_BPCM_DIRECT
|| pmc_mode
== PMC_MODE_PMB_DIRECT
) {
355 status
= write_bpcm_reg_direct(devAddr
, wordOffset
, value
);
357 } else if (pmc_mode
== PMC_MODE_DQM
) {
359 SendCommand(cmdWriteBpcmReg
, devAddr
, 0, 0, wordOffset
,
367 int PowerOnZone(int devAddr
, int zone
)
369 BPCM_PWR_ZONE_N_CONTROL reg
;
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
) {
377 cmd
.u
.cmdStateOnlyParam
.state
= 1;
378 return SendCmd(&cmd
, cmdPowerZoneOnOff
, devAddr
, zone
, 0, 0);
383 ReadBPCMRegister(devAddr
, BPCMRegOffset(zones
[zone
].control
),
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;
392 WriteBPCMRegister(devAddr
,
393 BPCMRegOffset(zones
[zone
].control
),
399 int PowerOnDevice(int devAddr
)
401 if (PMC_ACCESS_BPCM_DIRECT
|| pmc_mode
== PMC_MODE_PMB_DIRECT
) {
403 BPCM_CAPABILITES_REG capabilities
;
406 ReadBPCMRegister(devAddr
, BPCMRegOffset(capabilities
),
407 &capabilities
.Reg32
);
409 (ix
< capabilities
.Bits
.num_zones
)
410 && (status
== kPMC_NO_ERROR
); ix
++) {
411 status
= PowerOnZone(devAddr
, ix
);
417 if (pmc_mode
== PMC_MODE_DQM
) {
419 cmd
.u
.cmdPowerDevice
.state
= 1;
420 return SendCmd(&cmd
, cmdPowerDevOnOff
, devAddr
, 0, 0, 0);
423 return kPMC_INVALID_STATE
;
426 int PowerOffDevice(int devAddr
, int repower
)
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
;
434 ReadBPCMRegister(devAddr
, BPCMRegOffset(zones
[0].control
),
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
),
447 if (pmc_mode
== PMC_MODE_DQM
) {
449 cmd
.u
.cmdPowerDevice
.state
= 0;
450 cmd
.u
.cmdPowerDevice
.restore
= repower
;
451 return SendCmd(&cmd
, cmdPowerDevOnOff
, devAddr
, 0, 0, 0);
454 return kPMC_INVALID_STATE
;
457 int ResetDevice(int devAddr
)
459 /* all zones had their blk_reset_assert bits set at initial config time */
460 BPCM_PWR_ZONE_N_CONTROL reg
;
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);
470 status
= PowerOffDevice(devAddr
, 0);
473 ReadBPCMRegister(devAddr
, BPCMRegOffset(zones
[0].control
),
475 } while ((reg
.Bits
.pwr_off_state
!= 1) && (status
== kPMC_NO_ERROR
));
476 if (status
== kPMC_NO_ERROR
)
477 status
= PowerOnDevice(devAddr
);
481 // initalize pmc_mode (possibly) before printk available
482 void pmc_initmode(void)
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
490 pmc_mode
= PMC_MODE_DQM
;
492 pmc_mode
= PMC_MODE_PMB_DIRECT
;
494 #if IS_BCMCHIP(63158)
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