Home | History | Annotate | Line # | Download | only in dev
      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