nslu2_buttons.c revision 1.4
11.4Smsaitoh/* $NetBSD: nslu2_buttons.c,v 1.4 2012/10/14 14:20:58 msaitoh 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 * 191.1Sscw * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 201.1Sscw * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 211.1Sscw * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 221.1Sscw * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 231.1Sscw * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 241.1Sscw * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 251.1Sscw * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 261.1Sscw * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 271.1Sscw * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 281.1Sscw * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 291.1Sscw * POSSIBILITY OF SUCH DAMAGE. 301.1Sscw */ 311.1Sscw 321.1Sscw#include <sys/cdefs.h> 331.4Smsaitoh__KERNEL_RCSID(0, "$NetBSD: nslu2_buttons.c,v 1.4 2012/10/14 14:20:58 msaitoh Exp $"); 341.1Sscw 351.1Sscw#include <sys/param.h> 361.1Sscw#include <sys/systm.h> 371.1Sscw#include <sys/device.h> 381.1Sscw 391.1Sscw#include <dev/sysmon/sysmonvar.h> 401.1Sscw#include <dev/sysmon/sysmon_taskq.h> 411.1Sscw 421.1Sscw#include <arm/xscale/ixp425reg.h> 431.1Sscw#include <arm/xscale/ixp425var.h> 441.1Sscw 451.1Sscw#include <evbarm/nslu2/nslu2reg.h> 461.1Sscw 471.1Sscwstruct slugbutt_softc { 481.4Smsaitoh device_t sc_dev; 491.1Sscw struct sysmon_pswitch sc_smpwr; 501.1Sscw struct sysmon_pswitch sc_smrst; 511.1Sscw}; 521.1Sscw 531.1Sscwstatic int slugbutt_attached; 541.1Sscw 551.2Sscw#define SLUGBUTT_PWR_BIT (1u << GPIO_BUTTON_PWR) 561.2Sscw#define SLUGBUTT_RST_BIT (1u << GPIO_BUTTON_RST) 571.2Sscw 581.1Sscwstatic void 591.1Sscwpower_event(void *arg) 601.1Sscw{ 611.1Sscw struct slugbutt_softc *sc = arg; 621.1Sscw 631.1Sscw sysmon_pswitch_event(&sc->sc_smpwr, PSWITCH_EVENT_PRESSED); 641.1Sscw} 651.1Sscw 661.1Sscwstatic int 671.1Sscwpower_intr(void *arg) 681.1Sscw{ 691.1Sscw struct slugbutt_softc *sc = arg; 701.1Sscw int rv; 711.1Sscw 721.2Sscw GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPISR, SLUGBUTT_PWR_BIT); 731.1Sscw 741.1Sscw rv = sysmon_task_queue_sched(0, power_event, sc); 751.1Sscw if (rv) { 761.1Sscw printf("%s: WARNING: unable to queue power button " 771.4Smsaitoh "callback: %d\n", device_xname(sc->sc_dev), rv); 781.1Sscw } 791.1Sscw 801.1Sscw return (1); 811.1Sscw} 821.1Sscw 831.1Sscwstatic void 841.1Sscwreset_event(void *arg) 851.1Sscw{ 861.1Sscw struct slugbutt_softc *sc = arg; 871.1Sscw 881.1Sscw sysmon_pswitch_event(&sc->sc_smrst, PSWITCH_EVENT_PRESSED); 891.1Sscw} 901.1Sscw 911.1Sscwstatic int 921.1Sscwreset_intr(void *arg) 931.1Sscw{ 941.1Sscw struct slugbutt_softc *sc = arg; 951.1Sscw int rv; 961.1Sscw 971.2Sscw GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPISR, SLUGBUTT_RST_BIT); 981.1Sscw 991.1Sscw rv = sysmon_task_queue_sched(0, reset_event, sc); 1001.1Sscw if (rv) { 1011.1Sscw printf("%s: WARNING: unable to queue reset button " 1021.4Smsaitoh "callback: %d\n", device_xname(sc->sc_dev), rv); 1031.1Sscw } 1041.1Sscw 1051.1Sscw return (1); 1061.1Sscw} 1071.1Sscw 1081.1Sscwstatic void 1091.4Smsaitohslugbutt_deferred(device_t self) 1101.1Sscw{ 1111.4Smsaitoh struct slugbutt_softc *sc = device_private(self); 1121.1Sscw struct ixp425_softc *ixsc = ixp425_softc; 1131.1Sscw uint32_t reg; 1141.1Sscw 1151.4Smsaitoh sc->sc_dev = self; 1161.4Smsaitoh 1171.1Sscw /* Configure the GPIO pins as inputs */ 1181.1Sscw reg = GPIO_CONF_READ_4(ixsc, IXP425_GPIO_GPOER); 1191.2Sscw reg |= SLUGBUTT_PWR_BIT | SLUGBUTT_RST_BIT; 1201.1Sscw GPIO_CONF_WRITE_4(ixsc, IXP425_GPIO_GPOER, reg); 1211.1Sscw 1221.1Sscw /* Configure the input type: Falling edge */ 1231.1Sscw reg = GPIO_CONF_READ_4(ixsc, GPIO_TYPE_REG(GPIO_BUTTON_PWR)); 1241.1Sscw reg &= ~GPIO_TYPE(GPIO_BUTTON_PWR, GPIO_TYPE_MASK); 1251.1Sscw reg |= GPIO_TYPE(GPIO_BUTTON_PWR, GPIO_TYPE_EDG_FALLING); 1261.1Sscw GPIO_CONF_WRITE_4(ixsc, GPIO_TYPE_REG(GPIO_BUTTON_PWR), reg); 1271.1Sscw 1281.1Sscw reg = GPIO_CONF_READ_4(ixsc, GPIO_TYPE_REG(GPIO_BUTTON_RST)); 1291.1Sscw reg &= ~GPIO_TYPE(GPIO_BUTTON_RST, GPIO_TYPE_MASK); 1301.1Sscw reg |= GPIO_TYPE(GPIO_BUTTON_RST, GPIO_TYPE_EDG_FALLING); 1311.1Sscw GPIO_CONF_WRITE_4(ixsc, GPIO_TYPE_REG(GPIO_BUTTON_RST), reg); 1321.1Sscw 1331.1Sscw /* Clear any existing interrupt */ 1341.2Sscw GPIO_CONF_WRITE_4(ixsc, IXP425_GPIO_GPISR, SLUGBUTT_PWR_BIT | 1351.2Sscw SLUGBUTT_RST_BIT); 1361.1Sscw 1371.1Sscw sysmon_task_queue_init(); 1381.1Sscw 1391.4Smsaitoh sc->sc_smpwr.smpsw_name = device_xname(sc->sc_dev); 1401.1Sscw sc->sc_smpwr.smpsw_type = PSWITCH_TYPE_POWER; 1411.1Sscw 1421.1Sscw if (sysmon_pswitch_register(&sc->sc_smpwr) != 0) { 1431.1Sscw printf("%s: unable to register power button with sysmon\n", 1441.4Smsaitoh device_xname(sc->sc_dev)); 1451.1Sscw return; 1461.1Sscw } 1471.1Sscw 1481.4Smsaitoh sc->sc_smrst.smpsw_name = device_xname(sc->sc_dev); 1491.1Sscw sc->sc_smrst.smpsw_type = PSWITCH_TYPE_RESET; 1501.1Sscw 1511.1Sscw if (sysmon_pswitch_register(&sc->sc_smrst) != 0) { 1521.1Sscw printf("%s: unable to register reset button with sysmon\n", 1531.4Smsaitoh device_xname(sc->sc_dev)); 1541.1Sscw return; 1551.1Sscw } 1561.1Sscw 1571.1Sscw /* Hook the interrupts */ 1581.1Sscw ixp425_intr_establish(BUTTON_PWR_INT, IPL_TTY, power_intr, sc); 1591.1Sscw ixp425_intr_establish(BUTTON_RST_INT, IPL_TTY, reset_intr, sc); 1601.1Sscw} 1611.1Sscw 1621.1Sscw 1631.1Sscwstatic int 1641.4Smsaitohslugbutt_match(device_t parent, cfdata_t cf, void *aux) 1651.1Sscw{ 1661.1Sscw 1671.1Sscw return (slugbutt_attached == 0); 1681.1Sscw} 1691.1Sscw 1701.1Sscwstatic void 1711.4Smsaitohslugbutt_attach(device_t parent, device_t self, void *aux) 1721.1Sscw{ 1731.1Sscw 1741.1Sscw slugbutt_attached = 1; 1751.1Sscw 1761.1Sscw aprint_normal(": Power and Reset buttons\n"); 1771.1Sscw 1781.1Sscw /* Defer, to ensure ixp425_softc has been initialised */ 1791.1Sscw config_interrupts(self, slugbutt_deferred); 1801.1Sscw} 1811.1Sscw 1821.4SmsaitohCFATTACH_DECL_NEW(slugbutt, sizeof(struct slugbutt_softc), 1831.1Sscw slugbutt_match, slugbutt_attach, NULL, NULL); 184