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