1/* $NetBSD: plumpower.c,v 1.14 2023/12/20 14:50:02 thorpej 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.14 2023/12/20 14:50:02 thorpej 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 50int 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 58int plumpower_match(device_t, cfdata_t, void *); 59void plumpower_attach(device_t, device_t, void *); 60 61struct 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 67CFATTACH_DECL_NEW(plumpower, sizeof(struct plumpower_softc), 68 plumpower_match, plumpower_attach, NULL, NULL); 69 70#ifdef PLUMPOWERDEBUG 71static void plumpower_dump(struct plumpower_softc *); 72#endif 73 74int 75plumpower_match(device_t parent, cfdata_t cf, void *aux) 76{ 77 return 2; /* 1st attach group */ 78} 79 80void 81plumpower_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 110void 111plum_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_IO5CL1 | 119 PLUM_POWER_RESETC_IO5CL1); 120 plum_conf_write(regt, regh, PLUM_POWER_RESETC_REG, 0); 121} 122 123void* 124plum_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 198void 199plum_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) 263static void 264plumpower_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