The BeagleBone Black is powered by the AM335X ARM Cortex-A8 Processor. The board provides a push button near the Ethernet connector for powering off and powering on the board. The AM335X works in concert with the TPS65217C Power Management IC (PMIC) and the operating system to do a proper shutdown when the button is pressed. By proper shutdown, I mean the file systems are sync()'d and services are shutdown cleanly. As part of my Google Summer of Code project, I've been implementing this functionality in Minix. I've got the basics working (clean shutdown and power off when the power button is pressed), but a lot of clean-up, re-factoring, and testing remains before I can think about submitting it for inclusion in Minix. The dance between the PMIC and SoC is interesting, so I thought I'd share how it works while it's fresh in my head.
There's a bit of setup to get this to work. It requires drivers for the SoC's I2C controller and RTC. A driver for the PMIC (an i2c slave) is also needed. First, the push button interrupt in the TPS65217C needs to be unmasked, and the driver for the TPS65217C needs to handle interrupts from the NNMI pin (irq 7). That pin signals the AM335X to let it know that there is an interrupt pending on the TPS65217C. This gets notifications about the button press to the TPS65217C driver. With just that part functional, you can do safe shutdowns of the operating system when the user presses the button.
Powering off the board takes a few more steps. The TPS65217C driver also has to set the OFF bit in the STATUS register. This enables power-off when the AM335X signals a power off by toggling the PWR_EN pin. Toggling the pin is done by setting the POWER_EN bit in RTC_PMIC, setting the time to power off the chip in the RTC's ALARM2 registers, enabling the the ALARM2 interrupt in the RTC_INTERRUPTS_REG register, and waiting for the alarm to go off which will automatically toggle the pin to alert the PMIC to power down the board. Finally, the PMIC will sense the toggle and cut the power. The user can press the power button again to boot the system.