nslu2_buttons.c revision 1.2
11.2Sscw/* $NetBSD: nslu2_buttons.c,v 1.2 2006/03/01 21:02:50 scw Exp $ */ 21.1Sscw 31.1Sscw/*- 41.1Sscw * Copyright (c) 2006 The NetBSD Foundation, Inc. 51.1Sscw * All rights reserved. 61.1Sscw * 71.1Sscw * This code is derived from software contributed to The NetBSD Foundation 81.1Sscw * by Steve C. Woodford. 91.1Sscw * 101.1Sscw * Redistribution and use in source and binary forms, with or without 111.1Sscw * modification, are permitted provided that the following conditions 121.1Sscw * are met: 131.1Sscw * 1. Redistributions of source code must retain the above copyright 141.1Sscw * notice, this list of conditions and the following disclaimer. 151.1Sscw * 2. Redistributions in binary form must reproduce the above copyright 161.1Sscw * notice, this list of conditions and the following disclaimer in the 171.1Sscw * documentation and/or other materials provided with the distribution. 181.1Sscw * 3. All advertising materials mentioning features or use of this software 191.1Sscw * must display the following acknowledgement: 201.1Sscw * This product includes software developed by the NetBSD 211.1Sscw * Foundation, Inc. and its contributors. 221.1Sscw * 4. Neither the name of The NetBSD Foundation nor the names of its 231.1Sscw * contributors may be used to endorse or promote products derived 241.1Sscw * from this software without specific prior written permission. 251.1Sscw * 261.1Sscw * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 271.1Sscw * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 281.1Sscw * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 291.1Sscw * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 301.1Sscw * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 311.1Sscw * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 321.1Sscw * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 331.1Sscw * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 341.1Sscw * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 351.1Sscw * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 361.1Sscw * POSSIBILITY OF SUCH DAMAGE. 371.1Sscw */ 381.1Sscw 391.1Sscw#include <sys/cdefs.h> 401.2Sscw__KERNEL_RCSID(0, "$NetBSD: nslu2_buttons.c,v 1.2 2006/03/01 21:02:50 scw Exp $"); 411.1Sscw 421.1Sscw#include <sys/param.h> 431.1Sscw#include <sys/systm.h> 441.1Sscw#include <sys/device.h> 451.1Sscw 461.1Sscw#include <dev/sysmon/sysmonvar.h> 471.1Sscw#include <dev/sysmon/sysmon_taskq.h> 481.1Sscw 491.1Sscw#include <arm/xscale/ixp425reg.h> 501.1Sscw#include <arm/xscale/ixp425var.h> 511.1Sscw 521.1Sscw#include <evbarm/nslu2/nslu2reg.h> 531.1Sscw 541.1Sscwstruct slugbutt_softc { 551.1Sscw struct device sc_dev; 561.1Sscw struct sysmon_pswitch sc_smpwr; 571.1Sscw struct sysmon_pswitch sc_smrst; 581.1Sscw}; 591.1Sscw 601.1Sscwstatic int slugbutt_attached; 611.1Sscw 621.2Sscw#define SLUGBUTT_PWR_BIT (1u << GPIO_BUTTON_PWR) 631.2Sscw#define SLUGBUTT_RST_BIT (1u << GPIO_BUTTON_RST) 641.2Sscw 651.1Sscwstatic void 661.1Sscwpower_event(void *arg) 671.1Sscw{ 681.1Sscw struct slugbutt_softc *sc = arg; 691.1Sscw 701.1Sscw sysmon_pswitch_event(&sc->sc_smpwr, PSWITCH_EVENT_PRESSED); 711.1Sscw} 721.1Sscw 731.1Sscwstatic int 741.1Sscwpower_intr(void *arg) 751.1Sscw{ 761.1Sscw struct slugbutt_softc *sc = arg; 771.1Sscw int rv; 781.1Sscw 791.2Sscw GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPISR, SLUGBUTT_PWR_BIT); 801.1Sscw 811.1Sscw rv = sysmon_task_queue_sched(0, power_event, sc); 821.1Sscw if (rv) { 831.1Sscw printf("%s: WARNING: unable to queue power button " 841.1Sscw "callback: %d\n", sc->sc_dev.dv_xname, rv); 851.1Sscw } 861.1Sscw 871.1Sscw return (1); 881.1Sscw} 891.1Sscw 901.1Sscwstatic void 911.1Sscwreset_event(void *arg) 921.1Sscw{ 931.1Sscw struct slugbutt_softc *sc = arg; 941.1Sscw 951.1Sscw sysmon_pswitch_event(&sc->sc_smrst, PSWITCH_EVENT_PRESSED); 961.1Sscw} 971.1Sscw 981.1Sscwstatic int 991.1Sscwreset_intr(void *arg) 1001.1Sscw{ 1011.1Sscw struct slugbutt_softc *sc = arg; 1021.1Sscw int rv; 1031.1Sscw 1041.2Sscw GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPISR, SLUGBUTT_RST_BIT); 1051.1Sscw 1061.1Sscw rv = sysmon_task_queue_sched(0, reset_event, sc); 1071.1Sscw if (rv) { 1081.1Sscw printf("%s: WARNING: unable to queue reset button " 1091.1Sscw "callback: %d\n", sc->sc_dev.dv_xname, rv); 1101.1Sscw } 1111.1Sscw 1121.1Sscw return (1); 1131.1Sscw} 1141.1Sscw 1151.1Sscwstatic void 1161.1Sscwslugbutt_deferred(struct device *self) 1171.1Sscw{ 1181.1Sscw struct slugbutt_softc *sc = (struct slugbutt_softc *) self; 1191.1Sscw struct ixp425_softc *ixsc = ixp425_softc; 1201.1Sscw uint32_t reg; 1211.1Sscw 1221.1Sscw /* Configure the GPIO pins as inputs */ 1231.1Sscw reg = GPIO_CONF_READ_4(ixsc, IXP425_GPIO_GPOER); 1241.2Sscw reg |= SLUGBUTT_PWR_BIT | SLUGBUTT_RST_BIT; 1251.1Sscw GPIO_CONF_WRITE_4(ixsc, IXP425_GPIO_GPOER, reg); 1261.1Sscw 1271.1Sscw /* Configure the input type: Falling edge */ 1281.1Sscw reg = GPIO_CONF_READ_4(ixsc, GPIO_TYPE_REG(GPIO_BUTTON_PWR)); 1291.1Sscw reg &= ~GPIO_TYPE(GPIO_BUTTON_PWR, GPIO_TYPE_MASK); 1301.1Sscw reg |= GPIO_TYPE(GPIO_BUTTON_PWR, GPIO_TYPE_EDG_FALLING); 1311.1Sscw GPIO_CONF_WRITE_4(ixsc, GPIO_TYPE_REG(GPIO_BUTTON_PWR), reg); 1321.1Sscw 1331.1Sscw reg = GPIO_CONF_READ_4(ixsc, GPIO_TYPE_REG(GPIO_BUTTON_RST)); 1341.1Sscw reg &= ~GPIO_TYPE(GPIO_BUTTON_RST, GPIO_TYPE_MASK); 1351.1Sscw reg |= GPIO_TYPE(GPIO_BUTTON_RST, GPIO_TYPE_EDG_FALLING); 1361.1Sscw GPIO_CONF_WRITE_4(ixsc, GPIO_TYPE_REG(GPIO_BUTTON_RST), reg); 1371.1Sscw 1381.1Sscw /* Clear any existing interrupt */ 1391.2Sscw GPIO_CONF_WRITE_4(ixsc, IXP425_GPIO_GPISR, SLUGBUTT_PWR_BIT | 1401.2Sscw SLUGBUTT_RST_BIT); 1411.1Sscw 1421.1Sscw sysmon_task_queue_init(); 1431.1Sscw 1441.1Sscw sc->sc_smpwr.smpsw_name = sc->sc_dev.dv_xname; 1451.1Sscw sc->sc_smpwr.smpsw_type = PSWITCH_TYPE_POWER; 1461.1Sscw 1471.1Sscw if (sysmon_pswitch_register(&sc->sc_smpwr) != 0) { 1481.1Sscw printf("%s: unable to register power button with sysmon\n", 1491.1Sscw sc->sc_dev.dv_xname); 1501.1Sscw return; 1511.1Sscw } 1521.1Sscw 1531.1Sscw sc->sc_smrst.smpsw_name = sc->sc_dev.dv_xname; 1541.1Sscw sc->sc_smrst.smpsw_type = PSWITCH_TYPE_RESET; 1551.1Sscw 1561.1Sscw if (sysmon_pswitch_register(&sc->sc_smrst) != 0) { 1571.1Sscw printf("%s: unable to register reset button with sysmon\n", 1581.1Sscw sc->sc_dev.dv_xname); 1591.1Sscw return; 1601.1Sscw } 1611.1Sscw 1621.1Sscw /* Hook the interrupts */ 1631.1Sscw ixp425_intr_establish(BUTTON_PWR_INT, IPL_TTY, power_intr, sc); 1641.1Sscw ixp425_intr_establish(BUTTON_RST_INT, IPL_TTY, reset_intr, sc); 1651.1Sscw} 1661.1Sscw 1671.1Sscw 1681.1Sscwstatic int 1691.1Sscwslugbutt_match(struct device *parent, struct cfdata *cf, void *arg) 1701.1Sscw{ 1711.1Sscw 1721.1Sscw return (slugbutt_attached == 0); 1731.1Sscw} 1741.1Sscw 1751.1Sscwstatic void 1761.1Sscwslugbutt_attach(struct device *parent, struct device *self, void *arg) 1771.1Sscw{ 1781.1Sscw 1791.1Sscw slugbutt_attached = 1; 1801.1Sscw 1811.1Sscw aprint_normal(": Power and Reset buttons\n"); 1821.1Sscw 1831.1Sscw /* Defer, to ensure ixp425_softc has been initialised */ 1841.1Sscw config_interrupts(self, slugbutt_deferred); 1851.1Sscw} 1861.1Sscw 1871.1SscwCFATTACH_DECL(slugbutt, sizeof(struct slugbutt_softc), 1881.1Sscw slugbutt_match, slugbutt_attach, NULL, NULL); 189