Author: loos
Date: Wed May 13 01:10:28 2015
New Revision: 282827
URL: https://svnweb.freebsd.org/changeset/base/282827

Log:
  Add support for the power button on BeagleBone Black.
  
  Shutdown and turn off the board when the power button is pressed.
  
  Submitted by: Michal Meloun <mel...@miracle.cz>
  Relnotes:     yes

Modified:
  head/sys/arm/ti/am335x/am335x_pmic.c
  head/sys/boot/fdt/dts/arm/beaglebone-black.dts

Modified: head/sys/arm/ti/am335x/am335x_pmic.c
==============================================================================
--- head/sys/arm/ti/am335x/am335x_pmic.c        Wed May 13 00:28:36 2015        
(r282826)
+++ head/sys/arm/ti/am335x/am335x_pmic.c        Wed May 13 01:10:28 2015        
(r282827)
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/clock.h>
 #include <sys/time.h>
 #include <sys/bus.h>
+#include <sys/proc.h>
 #include <sys/reboot.h>
 #include <sys/resource.h>
 #include <sys/rman.h>
@@ -58,12 +59,20 @@ __FBSDID("$FreeBSD$");
 #define TPS65217D              0x6
 
 /* TPS65217 Reisters */
-#define TPS65217_CHIPID_REG    0x00
-#define TPS65217_STATUS_REG    0x0A
-#define        TPS65217_STATUS_OFF             (1U << 7)
-#define        TPS65217_STATUS_ACPWR           (1U << 3)
-#define        TPS65217_STATUS_USBPWR          (1U << 2)
-#define        TPS65217_STATUS_BT              (1U << 0)
+#define        TPS65217_CHIPID_REG     0x00
+#define        TPS65217_INT_REG        0x02
+#define         TPS65217_INT_PBM               (1U << 6)
+#define         TPS65217_INT_ACM               (1U << 5)
+#define         TPS65217_INT_USBM              (1U << 4)
+#define         TPS65217_INT_PBI               (1U << 2)
+#define         TPS65217_INT_ACI               (1U << 1)
+#define         TPS65217_INT_USBI              (1U << 0)
+
+#define        TPS65217_STATUS_REG     0x0A
+#define         TPS65217_STATUS_OFF            (1U << 7)
+#define         TPS65217_STATUS_ACPWR          (1U << 3)
+#define         TPS65217_STATUS_USBPWR         (1U << 2)
+#define         TPS65217_STATUS_BT             (1U << 0)
 
 #define MAX_IIC_DATA_SIZE      2
 
@@ -72,6 +81,8 @@ struct am335x_pmic_softc {
        device_t                sc_dev;
        uint32_t                sc_addr;
        struct intr_config_hook enum_hook;
+       struct resource         *sc_irq_res;
+       void                    *sc_intrhand;
 };
 
 static void am335x_pmic_shutdown(void *, int);
@@ -105,6 +116,38 @@ am335x_pmic_write(device_t dev, uint8_t 
        return (iicbus_transfer(dev, msg, 1));
 }
 
+static void
+am335x_pmic_intr(void *arg)
+{
+       struct am335x_pmic_softc *sc = (struct am335x_pmic_softc *)arg;
+       uint8_t int_reg, status_reg;
+       int rv;
+       char notify_buf[16];
+
+       THREAD_SLEEPING_OK();
+       rv = am335x_pmic_read(sc->sc_dev, TPS65217_INT_REG, &int_reg, 1);
+       if (rv != 0) {
+               device_printf(sc->sc_dev, "Cannot read interrupt register\n");
+               THREAD_NO_SLEEPING();
+               return;
+       }
+       rv = am335x_pmic_read(sc->sc_dev, TPS65217_STATUS_REG, &status_reg, 1);
+       if (rv != 0) {
+               device_printf(sc->sc_dev, "Cannot read status register\n");
+               THREAD_NO_SLEEPING();
+               return;
+       }
+       THREAD_NO_SLEEPING();
+
+       if ((int_reg & TPS65217_INT_PBI) && (status_reg & TPS65217_STATUS_BT))
+               shutdown_nice(RB_POWEROFF);
+       if (int_reg & TPS65217_INT_ACI) {
+               snprintf(notify_buf, sizeof(notify_buf), "notify=0x%02x",
+                   (status_reg & TPS65217_STATUS_ACPWR) ? 1 : 0);
+               devctl_notify_f("ACPI", "ACAD", "power", notify_buf, M_NOWAIT);
+       }
+}
+
 static int
 am335x_pmic_probe(device_t dev)
 {
@@ -130,6 +173,7 @@ am335x_pmic_start(void *xdev)
        uint8_t reg;
        char name[20];
        char pwr[4][11] = {"Unknown", "USB", "AC", "USB and AC"};
+       int rv;
 
        sc = device_get_softc(dev);
 
@@ -158,15 +202,38 @@ am335x_pmic_start(void *xdev)
            SHUTDOWN_PRI_LAST);
 
        config_intrhook_disestablish(&sc->enum_hook);
+
+       /* Unmask all interrupts and clear pending status */
+       reg = 0;
+       am335x_pmic_write(dev, TPS65217_INT_REG, &reg, 1);
+       am335x_pmic_read(dev, TPS65217_INT_REG, &reg, 1);
+
+       if (sc->sc_irq_res != NULL) {
+               rv = bus_setup_intr(dev, sc->sc_irq_res,
+                   INTR_TYPE_MISC | INTR_MPSAFE, NULL, am335x_pmic_intr,
+                   sc, &sc->sc_intrhand);
+               if (rv != 0)
+                       device_printf(dev,
+                           "Unable to setup the irq handler.\n");
+       }
 }
 
 static int
 am335x_pmic_attach(device_t dev)
 {
        struct am335x_pmic_softc *sc;
+       int rid;
 
        sc = device_get_softc(dev);
 
+       rid = 0;
+       sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+           RF_ACTIVE);
+       if (!sc->sc_irq_res) {
+               device_printf(dev, "cannot allocate interrupt\n");
+               /* return (ENXIO); */
+       }
+
        sc->enum_hook.ich_func = am335x_pmic_start;
        sc->enum_hook.ich_arg = dev;
 

Modified: head/sys/boot/fdt/dts/arm/beaglebone-black.dts
==============================================================================
--- head/sys/boot/fdt/dts/arm/beaglebone-black.dts      Wed May 13 00:28:36 
2015        (r282826)
+++ head/sys/boot/fdt/dts/arm/beaglebone-black.dts      Wed May 13 01:10:28 
2015        (r282827)
@@ -149,6 +149,8 @@
                        pmic@48 {
                                compatible = "ti,am335x-pmic";
                                reg = <0x48>;
+                               interrupts = <7>; /* nNMI */
+                               interrupt-parent = <&AINTC>;
                        };
                };
        };
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to