nslu2_buttons.c revision 1.1
11.1Sscw/* $NetBSD: nslu2_buttons.c,v 1.1 2006/02/28 20:40:33 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.1Sscw__KERNEL_RCSID(0, "$NetBSD: nslu2_buttons.c,v 1.1 2006/02/28 20:40:33 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.1Sscwstatic void 631.1Sscwpower_event(void *arg) 641.1Sscw{ 651.1Sscw struct slugbutt_softc *sc = arg; 661.1Sscw 671.1Sscw sysmon_pswitch_event(&sc->sc_smpwr, PSWITCH_EVENT_PRESSED); 681.1Sscw} 691.1Sscw 701.1Sscwstatic int 711.1Sscwpower_intr(void *arg) 721.1Sscw{ 731.1Sscw struct slugbutt_softc *sc = arg; 741.1Sscw int rv; 751.1Sscw 761.1Sscw GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPISR, 771.1Sscw 1u << GPIO_BUTTON_PWR); 781.1Sscw 791.1Sscw rv = sysmon_task_queue_sched(0, power_event, sc); 801.1Sscw if (rv) { 811.1Sscw printf("%s: WARNING: unable to queue power button " 821.1Sscw "callback: %d\n", sc->sc_dev.dv_xname, rv); 831.1Sscw } 841.1Sscw 851.1Sscw return (1); 861.1Sscw} 871.1Sscw 881.1Sscwstatic void 891.1Sscwreset_event(void *arg) 901.1Sscw{ 911.1Sscw struct slugbutt_softc *sc = arg; 921.1Sscw 931.1Sscw sysmon_pswitch_event(&sc->sc_smrst, PSWITCH_EVENT_PRESSED); 941.1Sscw} 951.1Sscw 961.1Sscwstatic int 971.1Sscwreset_intr(void *arg) 981.1Sscw{ 991.1Sscw struct slugbutt_softc *sc = arg; 1001.1Sscw int rv; 1011.1Sscw 1021.1Sscw GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPISR, 1031.1Sscw 1u << GPIO_BUTTON_RST); 1041.1Sscw 1051.1Sscw rv = sysmon_task_queue_sched(0, reset_event, sc); 1061.1Sscw if (rv) { 1071.1Sscw printf("%s: WARNING: unable to queue reset button " 1081.1Sscw "callback: %d\n", sc->sc_dev.dv_xname, rv); 1091.1Sscw } 1101.1Sscw 1111.1Sscw return (1); 1121.1Sscw} 1131.1Sscw 1141.1Sscwstatic void 1151.1Sscwslugbutt_deferred(struct device *self) 1161.1Sscw{ 1171.1Sscw struct slugbutt_softc *sc = (struct slugbutt_softc *) self; 1181.1Sscw struct ixp425_softc *ixsc = ixp425_softc; 1191.1Sscw uint32_t reg; 1201.1Sscw 1211.1Sscw /* Configure the GPIO pins as inputs */ 1221.1Sscw reg = GPIO_CONF_READ_4(ixsc, IXP425_GPIO_GPOER); 1231.1Sscw reg |= GPIO_BUTTON_PWR | GPIO_BUTTON_RST; 1241.1Sscw GPIO_CONF_WRITE_4(ixsc, IXP425_GPIO_GPOER, reg); 1251.1Sscw 1261.1Sscw /* Configure the input type: Falling edge */ 1271.1Sscw reg = GPIO_CONF_READ_4(ixsc, GPIO_TYPE_REG(GPIO_BUTTON_PWR)); 1281.1Sscw reg &= ~GPIO_TYPE(GPIO_BUTTON_PWR, GPIO_TYPE_MASK); 1291.1Sscw reg |= GPIO_TYPE(GPIO_BUTTON_PWR, GPIO_TYPE_EDG_FALLING); 1301.1Sscw GPIO_CONF_WRITE_4(ixsc, GPIO_TYPE_REG(GPIO_BUTTON_PWR), reg); 1311.1Sscw 1321.1Sscw reg = GPIO_CONF_READ_4(ixsc, GPIO_TYPE_REG(GPIO_BUTTON_RST)); 1331.1Sscw reg &= ~GPIO_TYPE(GPIO_BUTTON_RST, GPIO_TYPE_MASK); 1341.1Sscw reg |= GPIO_TYPE(GPIO_BUTTON_RST, GPIO_TYPE_EDG_FALLING); 1351.1Sscw GPIO_CONF_WRITE_4(ixsc, GPIO_TYPE_REG(GPIO_BUTTON_RST), reg); 1361.1Sscw 1371.1Sscw /* Clear any existing interrupt */ 1381.1Sscw GPIO_CONF_WRITE_4(ixsc, IXP425_GPIO_GPISR, (1u << GPIO_BUTTON_PWR) | 1391.1Sscw (1u << GPIO_BUTTON_RST)); 1401.1Sscw 1411.1Sscw sysmon_task_queue_init(); 1421.1Sscw 1431.1Sscw sc->sc_smpwr.smpsw_name = sc->sc_dev.dv_xname; 1441.1Sscw sc->sc_smpwr.smpsw_type = PSWITCH_TYPE_POWER; 1451.1Sscw 1461.1Sscw if (sysmon_pswitch_register(&sc->sc_smpwr) != 0) { 1471.1Sscw printf("%s: unable to register power button with sysmon\n", 1481.1Sscw sc->sc_dev.dv_xname); 1491.1Sscw return; 1501.1Sscw } 1511.1Sscw 1521.1Sscw sc->sc_smrst.smpsw_name = sc->sc_dev.dv_xname; 1531.1Sscw sc->sc_smrst.smpsw_type = PSWITCH_TYPE_RESET; 1541.1Sscw 1551.1Sscw if (sysmon_pswitch_register(&sc->sc_smrst) != 0) { 1561.1Sscw printf("%s: unable to register reset button with sysmon\n", 1571.1Sscw sc->sc_dev.dv_xname); 1581.1Sscw return; 1591.1Sscw } 1601.1Sscw 1611.1Sscw /* Hook the interrupts */ 1621.1Sscw ixp425_intr_establish(BUTTON_PWR_INT, IPL_TTY, power_intr, sc); 1631.1Sscw ixp425_intr_establish(BUTTON_RST_INT, IPL_TTY, reset_intr, sc); 1641.1Sscw} 1651.1Sscw 1661.1Sscw 1671.1Sscwstatic int 1681.1Sscwslugbutt_match(struct device *parent, struct cfdata *cf, void *arg) 1691.1Sscw{ 1701.1Sscw 1711.1Sscw return (slugbutt_attached == 0); 1721.1Sscw} 1731.1Sscw 1741.1Sscwstatic void 1751.1Sscwslugbutt_attach(struct device *parent, struct device *self, void *arg) 1761.1Sscw{ 1771.1Sscw 1781.1Sscw slugbutt_attached = 1; 1791.1Sscw 1801.1Sscw aprint_normal(": Power and Reset buttons\n"); 1811.1Sscw 1821.1Sscw /* Defer, to ensure ixp425_softc has been initialised */ 1831.1Sscw config_interrupts(self, slugbutt_deferred); 1841.1Sscw} 1851.1Sscw 1861.1SscwCFATTACH_DECL(slugbutt, sizeof(struct slugbutt_softc), 1871.1Sscw slugbutt_match, slugbutt_attach, NULL, NULL); 188