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