1*76fdad1fSMario Six // SPDX-License-Identifier: GPL-2.0+
2*76fdad1fSMario Six /*
3*76fdad1fSMario Six * (C) Copyright 2018
4*76fdad1fSMario Six * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
5*76fdad1fSMario Six */
6*76fdad1fSMario Six
7*76fdad1fSMario Six #include <common.h>
8*76fdad1fSMario Six #include <dm.h>
9*76fdad1fSMario Six #include <sysreset.h>
10*76fdad1fSMario Six #include <wait_bit.h>
11*76fdad1fSMario Six
12*76fdad1fSMario Six #include "sysreset_mpc83xx.h"
13*76fdad1fSMario Six
14*76fdad1fSMario Six /* Magic 4-byte word to enable reset ('RSTE' in ASCII) */
15*76fdad1fSMario Six static const u32 RPR_MAGIC = 0x52535445;
16*76fdad1fSMario Six /* Wait at most 2000ms for reset control enable bit */
17*76fdad1fSMario Six static const uint RESET_WAIT_TIMEOUT = 2000;
18*76fdad1fSMario Six
19*76fdad1fSMario Six /**
20*76fdad1fSMario Six * __do_reset() - Execute the system reset
21*76fdad1fSMario Six *
22*76fdad1fSMario Six * Return: The functions resets the system, and never returns.
23*76fdad1fSMario Six */
__do_reset(void)24*76fdad1fSMario Six static int __do_reset(void)
25*76fdad1fSMario Six {
26*76fdad1fSMario Six ulong msr;
27*76fdad1fSMario Six int res;
28*76fdad1fSMario Six
29*76fdad1fSMario Six immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
30*76fdad1fSMario Six
31*76fdad1fSMario Six puts("Resetting the board.\n");
32*76fdad1fSMario Six
33*76fdad1fSMario Six /* Interrupts and MMU off */
34*76fdad1fSMario Six msr = mfmsr();
35*76fdad1fSMario Six msr &= ~(MSR_EE | MSR_IR | MSR_DR);
36*76fdad1fSMario Six mtmsr(msr);
37*76fdad1fSMario Six
38*76fdad1fSMario Six /* Enable Reset Control Reg */
39*76fdad1fSMario Six out_be32(&immap->reset.rpr, RPR_MAGIC);
40*76fdad1fSMario Six sync();
41*76fdad1fSMario Six isync();
42*76fdad1fSMario Six
43*76fdad1fSMario Six /* Confirm Reset Control Reg is enabled */
44*76fdad1fSMario Six res = wait_for_bit_be32(&immap->reset.rcer, RCER_CRE, true,
45*76fdad1fSMario Six RESET_WAIT_TIMEOUT, false);
46*76fdad1fSMario Six if (res) {
47*76fdad1fSMario Six debug("%s: Timed out waiting for reset control to be set\n",
48*76fdad1fSMario Six __func__);
49*76fdad1fSMario Six return res;
50*76fdad1fSMario Six }
51*76fdad1fSMario Six
52*76fdad1fSMario Six udelay(200);
53*76fdad1fSMario Six
54*76fdad1fSMario Six /* Perform reset, only one bit */
55*76fdad1fSMario Six out_be32(&immap->reset.rcr, RCR_SWHR);
56*76fdad1fSMario Six
57*76fdad1fSMario Six /* Never executes */
58*76fdad1fSMario Six return 0;
59*76fdad1fSMario Six }
60*76fdad1fSMario Six
mpc83xx_sysreset_request(struct udevice * dev,enum sysreset_t type)61*76fdad1fSMario Six static int mpc83xx_sysreset_request(struct udevice *dev, enum sysreset_t type)
62*76fdad1fSMario Six {
63*76fdad1fSMario Six switch (type) {
64*76fdad1fSMario Six case SYSRESET_WARM:
65*76fdad1fSMario Six case SYSRESET_COLD:
66*76fdad1fSMario Six return __do_reset();
67*76fdad1fSMario Six default:
68*76fdad1fSMario Six return -EPROTONOSUPPORT;
69*76fdad1fSMario Six }
70*76fdad1fSMario Six
71*76fdad1fSMario Six return -EINPROGRESS;
72*76fdad1fSMario Six }
73*76fdad1fSMario Six
74*76fdad1fSMario Six /**
75*76fdad1fSMario Six * print_83xx_arb_event() - Print arbiter events to buffer
76*76fdad1fSMario Six * @force: Print arbiter events, even if none are indicated by the system
77*76fdad1fSMario Six * @buf: The buffer to receive the printed arbiter event information
78*76fdad1fSMario Six * @size: The size of the buffer to receive the printed arbiter event
79*76fdad1fSMario Six * information in bytes
80*76fdad1fSMario Six *
81*76fdad1fSMario Six * Return: Number of bytes printed to buffer, -ve on error
82*76fdad1fSMario Six */
print_83xx_arb_event(bool force,char * buf,int size)83*76fdad1fSMario Six static int print_83xx_arb_event(bool force, char *buf, int size)
84*76fdad1fSMario Six {
85*76fdad1fSMario Six int etype = (gd->arch.arbiter_event_attributes & AEATR_EVENT)
86*76fdad1fSMario Six >> AEATR_EVENT_SHIFT;
87*76fdad1fSMario Six int mstr_id = (gd->arch.arbiter_event_attributes & AEATR_MSTR_ID)
88*76fdad1fSMario Six >> AEATR_MSTR_ID_SHIFT;
89*76fdad1fSMario Six int tbst = (gd->arch.arbiter_event_attributes & AEATR_TBST)
90*76fdad1fSMario Six >> AEATR_TBST_SHIFT;
91*76fdad1fSMario Six int tsize = (gd->arch.arbiter_event_attributes & AEATR_TSIZE)
92*76fdad1fSMario Six >> AEATR_TSIZE_SHIFT;
93*76fdad1fSMario Six int ttype = (gd->arch.arbiter_event_attributes & AEATR_TTYPE)
94*76fdad1fSMario Six >> AEATR_TTYPE_SHIFT;
95*76fdad1fSMario Six int tsize_val = (tbst << 3) | tsize;
96*76fdad1fSMario Six int tsize_bytes = tbst ? (tsize ? tsize : 8) : 16 + 8 * tsize;
97*76fdad1fSMario Six int res = 0;
98*76fdad1fSMario Six
99*76fdad1fSMario Six /*
100*76fdad1fSMario Six * If we don't force output, and there is no event (event address ==
101*76fdad1fSMario Six * 0), then don't print anything
102*76fdad1fSMario Six */
103*76fdad1fSMario Six if (!force && !gd->arch.arbiter_event_address)
104*76fdad1fSMario Six return 0;
105*76fdad1fSMario Six
106*76fdad1fSMario Six if (CONFIG_IS_ENABLED(CONFIG_DISPLAY_AER_FULL)) {
107*76fdad1fSMario Six res = snprintf(buf, size,
108*76fdad1fSMario Six "Arbiter Event Status:\n"
109*76fdad1fSMario Six " %s: 0x%08lX\n"
110*76fdad1fSMario Six " %s: 0x%1x = %s\n"
111*76fdad1fSMario Six " %s: 0x%02x = %s\n"
112*76fdad1fSMario Six " %s: 0x%1x = %d bytes\n"
113*76fdad1fSMario Six " %s: 0x%02x = %s\n",
114*76fdad1fSMario Six "Event Address", gd->arch.arbiter_event_address,
115*76fdad1fSMario Six "Event Type", etype, event[etype],
116*76fdad1fSMario Six "Master ID", mstr_id, master[mstr_id],
117*76fdad1fSMario Six "Transfer Size", tsize_val, tsize_bytes,
118*76fdad1fSMario Six "Transfer Type", ttype, transfer[ttype]);
119*76fdad1fSMario Six } else if (CONFIG_IS_ENABLED(CONFIG_DISPLAY_AER_BRIEF)) {
120*76fdad1fSMario Six res = snprintf(buf, size,
121*76fdad1fSMario Six "Arbiter Event Status: AEATR=0x%08lX, AEADR=0x%08lX\n",
122*76fdad1fSMario Six gd->arch.arbiter_event_attributes,
123*76fdad1fSMario Six gd->arch.arbiter_event_address);
124*76fdad1fSMario Six }
125*76fdad1fSMario Six
126*76fdad1fSMario Six return res;
127*76fdad1fSMario Six }
128*76fdad1fSMario Six
mpc83xx_sysreset_get_status(struct udevice * dev,char * buf,int size)129*76fdad1fSMario Six static int mpc83xx_sysreset_get_status(struct udevice *dev, char *buf, int size)
130*76fdad1fSMario Six {
131*76fdad1fSMario Six /* Ad-hoc data structure to map RSR bit values to their descriptions */
132*76fdad1fSMario Six static const struct {
133*76fdad1fSMario Six /* Bit mask for the bit in question */
134*76fdad1fSMario Six ulong mask;
135*76fdad1fSMario Six /* Description of the bitmask in question */
136*76fdad1fSMario Six char *desc;
137*76fdad1fSMario Six } bits[] = {
138*76fdad1fSMario Six {
139*76fdad1fSMario Six RSR_SWSR, "Software Soft"}, {
140*76fdad1fSMario Six RSR_SWHR, "Software Hard"}, {
141*76fdad1fSMario Six RSR_JSRS, "JTAG Soft"}, {
142*76fdad1fSMario Six RSR_CSHR, "Check Stop"}, {
143*76fdad1fSMario Six RSR_SWRS, "Software Watchdog"}, {
144*76fdad1fSMario Six RSR_BMRS, "Bus Monitor"}, {
145*76fdad1fSMario Six RSR_SRS, "External/Internal Soft"}, {
146*76fdad1fSMario Six RSR_HRS, "External/Internal Hard"}
147*76fdad1fSMario Six };
148*76fdad1fSMario Six int res;
149*76fdad1fSMario Six ulong rsr = gd->arch.reset_status;
150*76fdad1fSMario Six int i;
151*76fdad1fSMario Six char *sep;
152*76fdad1fSMario Six
153*76fdad1fSMario Six res = snprintf(buf, size, "Reset Status:");
154*76fdad1fSMario Six if (res < 0) {
155*76fdad1fSMario Six debug("%s: Could not write reset status message (err = %d)\n",
156*76fdad1fSMario Six dev->name, res);
157*76fdad1fSMario Six return -EIO;
158*76fdad1fSMario Six }
159*76fdad1fSMario Six
160*76fdad1fSMario Six buf += res;
161*76fdad1fSMario Six size -= res;
162*76fdad1fSMario Six
163*76fdad1fSMario Six sep = " ";
164*76fdad1fSMario Six for (i = 0; i < ARRAY_SIZE(bits); i++)
165*76fdad1fSMario Six /* Print description of set bits */
166*76fdad1fSMario Six if (rsr & bits[i].mask) {
167*76fdad1fSMario Six res = snprintf(buf, size, "%s%s%s", sep, bits[i].desc,
168*76fdad1fSMario Six (i == ARRAY_SIZE(bits) - 1) ? "\n" : "");
169*76fdad1fSMario Six if (res < 0) {
170*76fdad1fSMario Six debug("%s: Could not write reset status message (err = %d)\n",
171*76fdad1fSMario Six dev->name, res);
172*76fdad1fSMario Six return -EIO;
173*76fdad1fSMario Six }
174*76fdad1fSMario Six buf += res;
175*76fdad1fSMario Six size -= res;
176*76fdad1fSMario Six sep = ", ";
177*76fdad1fSMario Six }
178*76fdad1fSMario Six
179*76fdad1fSMario Six /*
180*76fdad1fSMario Six * TODO(mario.six@gdsys.cc): Move this into a dedicated
181*76fdad1fSMario Six * arbiter driver
182*76fdad1fSMario Six */
183*76fdad1fSMario Six if (CONFIG_IS_ENABLED(CONFIG_DISPLAY_AER_FULL) ||
184*76fdad1fSMario Six CONFIG_IS_ENABLED(CONFIG_DISPLAY_AER_BRIEF)) {
185*76fdad1fSMario Six /*
186*76fdad1fSMario Six * If there was a bus monitor reset event, we force the arbiter
187*76fdad1fSMario Six * event to be printed
188*76fdad1fSMario Six */
189*76fdad1fSMario Six res = print_83xx_arb_event(rsr & RSR_BMRS, buf, size);
190*76fdad1fSMario Six if (res < 0) {
191*76fdad1fSMario Six debug("%s: Could not write arbiter event message (err = %d)\n",
192*76fdad1fSMario Six dev->name, res);
193*76fdad1fSMario Six return -EIO;
194*76fdad1fSMario Six }
195*76fdad1fSMario Six buf += res;
196*76fdad1fSMario Six size -= res;
197*76fdad1fSMario Six }
198*76fdad1fSMario Six snprintf(buf, size, "\n");
199*76fdad1fSMario Six
200*76fdad1fSMario Six return 0;
201*76fdad1fSMario Six }
202*76fdad1fSMario Six
203*76fdad1fSMario Six static struct sysreset_ops mpc83xx_sysreset = {
204*76fdad1fSMario Six .request = mpc83xx_sysreset_request,
205*76fdad1fSMario Six .get_status = mpc83xx_sysreset_get_status,
206*76fdad1fSMario Six };
207*76fdad1fSMario Six
208*76fdad1fSMario Six U_BOOT_DRIVER(sysreset_mpc83xx) = {
209*76fdad1fSMario Six .name = "mpc83xx_sysreset",
210*76fdad1fSMario Six .id = UCLASS_SYSRESET,
211*76fdad1fSMario Six .ops = &mpc83xx_sysreset,
212*76fdad1fSMario Six };
213