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