svn commit: r282827 - in head/sys: arm/ti/am335x boot/fdt/dts/arm

Luiz Otavio O Souza loos at FreeBSD.org
Wed May 13 01:10:29 UTC 2015


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 <meloun at 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 at 48 {
 				compatible = "ti,am335x-pmic";
 				reg = <0x48>;
+				interrupts = <7>; /* nNMI */
+				interrupt-parent = <&AINTC>;
 			};
 		};
 	};


More information about the svn-src-all mailing list