Ejemplo n.º 1
0
static inline int
pmu_read_byte(struct pmu_softc *sc, uint8_t *data)
{
	pmu_in(sc);
	(void)pmu_read_reg(sc, vSR);
	pmu_ack_off(sc);
	/* wait for intr to come up */
	do {} while (pmu_intr_state(sc) == 0);
	pmu_ack_on(sc);
	do {} while (pmu_intr_state(sc));
	*data = pmu_read_reg(sc, vSR);
	DPRINTF(" <%02x", *data);
	return 0;
}
Ejemplo n.º 2
0
static int
pmu_send(void *cookie, int cmd, int length, uint8_t *in_msg, int rlen,
    uint8_t *out_msg)
{
	struct pmu_softc *sc = cookie;
	int i, rcv_len = -1, s;
	uint8_t out_len, intreg;

	DPRINTF("pmu_send: ");

	s = splhigh();
	intreg = pmu_read_reg(sc, vIER);
	intreg &= 0x10;
	pmu_write_reg(sc, vIER, intreg);

	/* wait idle */
	do {} while (pmu_intr_state(sc));
	sc->sc_error = 0;

	/* send command */
	pmu_send_byte(sc, cmd);

	/* send length if necessary */
	if (pm_send_cmd_type[cmd] < 0) {
		pmu_send_byte(sc, length);
	}

	for (i = 0; i < length; i++) {
		pmu_send_byte(sc, in_msg[i]);
		DPRINTF(" next ");
	}
	DPRINTF("done sending\n");

	/* see if there's data to read */
	rcv_len = pm_receive_cmd_type[cmd];
	if (rcv_len == 0) 
		goto done;

	/* read command */
	if (rcv_len == 1) {
		pmu_read_byte(sc, out_msg);
		goto done;
	} else
		out_msg[0] = cmd;
	if (rcv_len < 0) {
		pmu_read_byte(sc, &out_len);
		rcv_len = out_len + 1;
	}
	for (i = 1; i < min(rcv_len, rlen); i++)
		pmu_read_byte(sc, &out_msg[i]);

done:
	DPRINTF("\n");
	pmu_write_reg(sc, vIER, (intreg == 0) ? 0 : 0x90);
	splx(s);

	return rcv_len;
}
Ejemplo n.º 3
0
static void
pmu_ack_on(struct pmu_softc *sc)
{
	uint8_t reg;

	reg = pmu_read_reg(sc, vBufB);
	reg |= vPB4;
	pmu_write_reg(sc, vBufB, reg);
}
Ejemplo n.º 4
0
static void
pmu_out(struct pmu_softc *sc)
{
	uint8_t reg;

	reg = pmu_read_reg(sc, vACR);
	reg |= vSR_OUT;
	reg |= 0x0c;
	pmu_write_reg(sc, vACR, reg);
}
Ejemplo n.º 5
0
static int
pmu_intr_state(struct pmu_softc *sc)
{
	return ((pmu_read_reg(sc, vBufB) & vPB3) == 0);
}
Ejemplo n.º 6
0
static int
pmu_attach(device_t dev)
{
	struct pmu_softc *sc;

	int i;
	uint8_t reg;
	uint8_t cmd[2] = {2, 0};
	uint8_t resp[16];
	phandle_t node,child;
	struct sysctl_ctx_list *ctx;
	struct sysctl_oid *tree;
	
	sc = device_get_softc(dev);
	sc->sc_dev = dev;
	
	sc->sc_memrid = 0;
	sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 
		          &sc->sc_memrid, RF_ACTIVE);

	mtx_init(&sc->sc_mutex,"pmu",NULL,MTX_DEF | MTX_RECURSE);

	if (sc->sc_memr == NULL) {
		device_printf(dev, "Could not alloc mem resource!\n");
		return (ENXIO);
	}

	/*
	 * Our interrupt is attached to a GPIO pin. Depending on probe order,
	 * we may not have found it yet. If we haven't, it will find us, and
	 * attach our interrupt then.
	 */
	pmu = dev;
	if (pmu_extint != NULL) {
		if (setup_pmu_intr(dev,pmu_extint) != 0)
			return (ENXIO);
	}

	sc->sc_autopoll = 0;
	sc->sc_batteries = 0;
	sc->adb_bus = NULL;
	sc->sc_leddev = NULL;

	/* Init PMU */

	pmu_write_reg(sc, vBufB, pmu_read_reg(sc, vBufB) | vPB4);
	pmu_write_reg(sc, vDirB, (pmu_read_reg(sc, vDirB) | vPB4) & ~vPB3);

	reg = PMU_DEFAULTS;
	pmu_send(sc, PMU_SET_IMASK, 1, &reg, 16, resp);

	pmu_write_reg(sc, vIER, 0x94); /* make sure VIA interrupts are on */

	pmu_send(sc, PMU_SYSTEM_READY, 1, cmd, 16, resp);
	pmu_send(sc, PMU_GET_VERSION, 0, cmd, 16, resp);

	/* Initialize child buses (ADB) */
	node = ofw_bus_get_node(dev);

	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
		char name[32];

		memset(name, 0, sizeof(name));
		OF_getprop(child, "name", name, sizeof(name));

		if (bootverbose)
			device_printf(dev, "PMU child <%s>\n",name);

		if (strncmp(name, "adb", 4) == 0) {
			sc->adb_bus = device_add_child(dev,"adb",-1);
		}

		if (strncmp(name, "power-mgt", 9) == 0) {
			uint32_t prim_info[9];

			if (OF_getprop(child, "prim-info", prim_info, 
			    sizeof(prim_info)) >= 7) 
				sc->sc_batteries = (prim_info[6] >> 16) & 0xff;

			if (bootverbose && sc->sc_batteries > 0)
				device_printf(dev, "%d batteries detected\n",
				    sc->sc_batteries);
		}
	}