1 /* $NetBSD: plumpower.c,v 1.15 2024/09/07 14:28:19 andvar Exp $ */ 2 3 /*- 4 * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: plumpower.c,v 1.15 2024/09/07 14:28:19 andvar Exp $"); 34 35 #undef PLUMPOWERDEBUG 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/device.h> 40 41 #include <machine/bus.h> 42 #include <machine/intr.h> 43 44 #include <hpcmips/tx/tx39var.h> 45 #include <hpcmips/dev/plumvar.h> 46 #include <hpcmips/dev/plumpowervar.h> 47 #include <hpcmips/dev/plumpowerreg.h> 48 49 #ifdef PLUMPOWERDEBUG 50 int plumpower_debug = 1; 51 #define DPRINTF(arg) if (plumpower_debug) printf arg; 52 #define DPRINTFN(n, arg) if (plumpower_debug > (n)) printf arg; 53 #else 54 #define DPRINTF(arg) 55 #define DPRINTFN(n, arg) 56 #endif 57 58 int plumpower_match(device_t, cfdata_t, void *); 59 void plumpower_attach(device_t, device_t, void *); 60 61 struct plumpower_softc { 62 plum_chipset_tag_t sc_pc; 63 bus_space_tag_t sc_regt; 64 bus_space_handle_t sc_regh; 65 }; 66 67 CFATTACH_DECL_NEW(plumpower, sizeof(struct plumpower_softc), 68 plumpower_match, plumpower_attach, NULL, NULL); 69 70 #ifdef PLUMPOWERDEBUG 71 static void plumpower_dump(struct plumpower_softc *); 72 #endif 73 74 int 75 plumpower_match(device_t parent, cfdata_t cf, void *aux) 76 { 77 return 2; /* 1st attach group */ 78 } 79 80 void 81 plumpower_attach(device_t parent, device_t self, void *aux) 82 { 83 struct plum_attach_args *pa = aux; 84 struct plumpower_softc *sc = device_private(self); 85 86 printf("\n"); 87 sc->sc_pc = pa->pa_pc; 88 sc->sc_regt = pa->pa_regt; 89 90 if (bus_space_map(sc->sc_regt, PLUM_POWER_REGBASE, 91 PLUM_POWER_REGSIZE, 0, &sc->sc_regh)) { 92 printf(": register map failed\n"); 93 return; 94 } 95 plum_conf_register_power(sc->sc_pc, (void*)sc); 96 #ifdef PLUMPOWERDEBUG 97 plumpower_dump(sc); 98 #endif 99 /* disable all power/clock */ 100 plum_conf_write(sc->sc_regt, sc->sc_regh, 101 PLUM_POWER_PWRCONT_REG, 0); 102 plum_conf_write(sc->sc_regt, sc->sc_regh, 103 PLUM_POWER_CLKCONT_REG, 0); 104 105 /* enable MCS interface from TX3922 */ 106 plum_conf_write(sc->sc_regt, sc->sc_regh, PLUM_POWER_INPENA_REG, 107 PLUM_POWER_INPENA); 108 } 109 110 void 111 plum_power_ioreset(plum_chipset_tag_t pc) 112 { 113 struct plumpower_softc *sc = pc->pc_powert; 114 bus_space_tag_t regt = sc->sc_regt; 115 bus_space_handle_t regh = sc->sc_regh; 116 117 plum_conf_write(regt, regh, PLUM_POWER_RESETC_REG, 118 PLUM_POWER_RESETC_IO5CL0 | 119 PLUM_POWER_RESETC_IO5CL1); 120 plum_conf_write(regt, regh, PLUM_POWER_RESETC_REG, 0); 121 } 122 123 void* 124 plum_power_establish(plum_chipset_tag_t pc, int src) 125 { 126 struct plumpower_softc *sc = pc->pc_powert; 127 bus_space_tag_t regt = sc->sc_regt; 128 bus_space_handle_t regh = sc->sc_regh; 129 plumreg_t pwrreg, clkreg; 130 131 pwrreg = plum_conf_read(regt, regh, PLUM_POWER_PWRCONT_REG); 132 clkreg = plum_conf_read(regt, regh, PLUM_POWER_CLKCONT_REG); 133 134 switch(src) { 135 default: 136 panic("plum_power_establish: unknown power source"); 137 case PLUM_PWR_LCD: 138 pwrreg |= PLUM_POWER_PWRCONT_LCDPWR; 139 plum_conf_write(regt, regh, PLUM_POWER_PWRCONT_REG, pwrreg); 140 pwrreg |= PLUM_POWER_PWRCONT_LCDDSP; 141 plum_conf_write(regt, regh, PLUM_POWER_PWRCONT_REG, pwrreg); 142 pwrreg |= PLUM_POWER_PWRCONT_LCDOE; 143 break; 144 case PLUM_PWR_BKL: 145 pwrreg |= PLUM_POWER_PWRCONT_BKLIGHT; 146 break; 147 case PLUM_PWR_IO5: 148 /* reset I/O bus (High/Low) */ 149 plum_power_ioreset(pc); 150 151 /* supply power */ 152 pwrreg |= PLUM_POWER_PWRCONT_IO5PWR; 153 plum_conf_write(regt, regh, PLUM_POWER_PWRCONT_REG, pwrreg); 154 155 /* output enable & supply clock */ 156 pwrreg |= PLUM_POWER_PWRCONT_IO5OE; 157 clkreg |= PLUM_POWER_CLKCONT_IO5CLK; 158 break; 159 case PLUM_PWR_EXTPW0: 160 pwrreg |= PLUM_POWER_PWRCONT_EXTPW0; 161 break; 162 case PLUM_PWR_EXTPW1: 163 pwrreg |= PLUM_POWER_PWRCONT_EXTPW1; 164 break; 165 case PLUM_PWR_EXTPW2: 166 pwrreg |= PLUM_POWER_PWRCONT_EXTPW2; 167 break; 168 case PLUM_PWR_USB: 169 /* output enable */ 170 pwrreg |= PLUM_POWER_PWRCONT_USBEN; 171 /* supply clock to the USB host controller */ 172 clkreg |= PLUM_POWER_CLKCONT_USBCLK1; 173 /* 174 * clock supply is adaptively controlled by hardware 175 * (recommended) 176 */ 177 clkreg &= ~PLUM_POWER_CLKCONT_USBCLK2; 178 break; 179 case PLUM_PWR_SM: 180 clkreg |= PLUM_POWER_CLKCONT_SMCLK; 181 break; 182 case PLUM_PWR_PCC1: 183 clkreg |= PLUM_POWER_CLKCONT_PCCCLK1; 184 break; 185 case PLUM_PWR_PCC2: 186 clkreg |= PLUM_POWER_CLKCONT_PCCCLK2; 187 break; 188 } 189 190 plum_conf_write(regt, regh, PLUM_POWER_PWRCONT_REG, pwrreg); 191 plum_conf_write(regt, regh, PLUM_POWER_CLKCONT_REG, clkreg); 192 #ifdef PLUMPOWERDEBUG 193 plumpower_dump(sc); 194 #endif 195 return (void*)src; 196 } 197 198 void 199 plum_power_disestablish(plum_chipset_tag_t pc, int ph) 200 { 201 struct plumpower_softc *sc = pc->pc_powert; 202 bus_space_tag_t regt = sc->sc_regt; 203 bus_space_handle_t regh = sc->sc_regh; 204 int src = (int)ph; 205 plumreg_t pwrreg, clkreg; 206 207 pwrreg = plum_conf_read(regt, regh, PLUM_POWER_PWRCONT_REG); 208 clkreg = plum_conf_read(regt, regh, PLUM_POWER_CLKCONT_REG); 209 210 switch(src) { 211 default: 212 panic("plum_power_disestablish: unknown power source"); 213 case PLUM_PWR_LCD: 214 pwrreg &= ~PLUM_POWER_PWRCONT_LCDOE; 215 plum_conf_write(regt, regh, PLUM_POWER_PWRCONT_REG, pwrreg); 216 pwrreg &= ~PLUM_POWER_PWRCONT_LCDDSP; 217 plum_conf_write(regt, regh, PLUM_POWER_PWRCONT_REG, pwrreg); 218 pwrreg &= ~PLUM_POWER_PWRCONT_LCDPWR; 219 break; 220 case PLUM_PWR_BKL: 221 pwrreg &= ~PLUM_POWER_PWRCONT_BKLIGHT; 222 break; 223 case PLUM_PWR_IO5: 224 pwrreg &= ~(PLUM_POWER_PWRCONT_IO5PWR | 225 PLUM_POWER_PWRCONT_IO5OE); 226 clkreg &= ~PLUM_POWER_CLKCONT_IO5CLK; 227 break; 228 case PLUM_PWR_EXTPW0: 229 pwrreg &= ~PLUM_POWER_PWRCONT_EXTPW0; 230 break; 231 case PLUM_PWR_EXTPW1: 232 pwrreg &= ~PLUM_POWER_PWRCONT_EXTPW1; 233 break; 234 case PLUM_PWR_EXTPW2: 235 pwrreg &= ~PLUM_POWER_PWRCONT_EXTPW2; 236 break; 237 case PLUM_PWR_USB: 238 pwrreg &= ~PLUM_POWER_PWRCONT_USBEN; 239 clkreg &= ~(PLUM_POWER_CLKCONT_USBCLK1 | 240 PLUM_POWER_CLKCONT_USBCLK2); 241 break; 242 case PLUM_PWR_SM: 243 clkreg &= ~PLUM_POWER_CLKCONT_SMCLK; 244 break; 245 case PLUM_PWR_PCC1: 246 clkreg &= ~PLUM_POWER_CLKCONT_PCCCLK1; 247 break; 248 case PLUM_PWR_PCC2: 249 clkreg &= ~PLUM_POWER_CLKCONT_PCCCLK2; 250 break; 251 } 252 253 plum_conf_write(regt, regh, PLUM_POWER_PWRCONT_REG, pwrreg); 254 plum_conf_write(regt, regh, PLUM_POWER_CLKCONT_REG, clkreg); 255 #ifdef PLUMPOWERDEBUG 256 plumpower_dump(sc); 257 #endif 258 } 259 260 #ifdef PLUMPOWERDEBUG 261 #define ISPOWERSUPPLY(r, m) dbg_bitmask_print(r, PLUM_POWER_PWRCONT_##m, #m) 262 #define ISCLOCKSUPPLY(r, m) dbg_bitmask_print(r, PLUM_POWER_CLKCONT_##m, #m) 263 static void 264 plumpower_dump(struct plumpower_softc *sc) 265 { 266 bus_space_tag_t regt = sc->sc_regt; 267 bus_space_handle_t regh = sc->sc_regh; 268 plumreg_t reg; 269 270 reg = plum_conf_read(regt, regh, PLUM_POWER_PWRCONT_REG); 271 printf(" power:"); 272 ISPOWERSUPPLY(reg, USBEN); 273 ISPOWERSUPPLY(reg, IO5OE); 274 ISPOWERSUPPLY(reg, LCDOE); 275 ISPOWERSUPPLY(reg, EXTPW2); 276 ISPOWERSUPPLY(reg, EXTPW1); 277 ISPOWERSUPPLY(reg, EXTPW0); 278 ISPOWERSUPPLY(reg, IO5PWR); 279 ISPOWERSUPPLY(reg, BKLIGHT); 280 ISPOWERSUPPLY(reg, LCDPWR); 281 ISPOWERSUPPLY(reg, LCDDSP); 282 reg = plum_conf_read(regt, regh, PLUM_POWER_CLKCONT_REG); 283 printf("\n clock:"); 284 ISCLOCKSUPPLY(reg, USBCLK2); 285 ISCLOCKSUPPLY(reg, USBCLK1); 286 ISCLOCKSUPPLY(reg, IO5CLK); 287 ISCLOCKSUPPLY(reg, SMCLK); 288 ISCLOCKSUPPLY(reg, PCCCLK2); 289 ISCLOCKSUPPLY(reg, PCCCLK1); 290 reg = plum_conf_read(regt, regh, PLUM_POWER_INPENA_REG); 291 printf("\n MCS interface %sebled", 292 reg & PLUM_POWER_INPENA ? "en" : "dis"); 293 reg = plum_conf_read(regt, regh, PLUM_POWER_RESETC_REG); 294 printf("\n IO5 reset:%s %s", 295 reg & PLUM_POWER_RESETC_IO5CL0 ? "CLRL" : "", 296 reg & PLUM_POWER_RESETC_IO5CL1 ? "CLRH" : ""); 297 printf("\n"); 298 } 299 #endif /* PLUMPOWERDEBUG */ 300 301