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