From 0c6aa28083a42fbca66cb18289860c1e6f53e984 Mon Sep 17 00:00:00 2001 From: Lady Ada Date: Thu, 19 Feb 2015 14:17:54 -0500 Subject: [PATCH 1/4] power switch patches & fixes for 3.18 This is a squashed commit, rounding up @ladyada's powerswitch patch and @toddtreece's later import of a slight fix to that from a tarball. --- drivers/power/Kconfig | 5 + drivers/power/Makefile | 1 + drivers/power/rpi_power_switch.c | 449 +++++++++++++++++++++++++++++++ 3 files changed, 455 insertions(+) create mode 100644 drivers/power/rpi_power_switch.c diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 0108c2af005b92..e241ad715a0102 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -75,6 +75,11 @@ config BATTERY_88PM860X help Say Y here to enable battery monitor for Marvell 88PM860x chip. +config RPI_POWER_SWITCH + tristate "Raspberry Pi GPIO power switch" + help + Use a GPIO as a pseudo power switch. + config BATTERY_DS2760 tristate "DS2760 battery driver (HP iPAQ & others)" depends on W1 && W1_SLAVE_DS2760 diff --git a/drivers/power/Makefile b/drivers/power/Makefile index dfa89427392636..d18fdd3f18a712 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_WM831X_BACKUP) += wm831x_backup.o obj-$(CONFIG_WM831X_POWER) += wm831x_power.o obj-$(CONFIG_WM8350_POWER) += wm8350_power.o obj-$(CONFIG_TEST_POWER) += test_power.o +obj-$(CONFIG_RPI_POWER_SWITCH) += rpi_power_switch.o obj-$(CONFIG_BATTERY_88PM860X) += 88pm860x_battery.o obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o diff --git a/drivers/power/rpi_power_switch.c b/drivers/power/rpi_power_switch.c new file mode 100644 index 00000000000000..049af002122ae2 --- /dev/null +++ b/drivers/power/rpi_power_switch.c @@ -0,0 +1,449 @@ +/* + * Adafruit power switch driver for Raspberry Pi + * + * Simulated power switch / button, using the GPIO banks. + * + * - Written by Sean Cross for Adafruit Industries (www.adafruit.com) + */ + +#define RPI_POWER_SWITCH_VERSION "1.7" +#define POWER_SWITCH_CLASS_NAME "rpi-power-switch" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* the BCM2709 redefines this for us right! +#define BCM2708_PERI_BASE 0x20000000 +*/ +#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) + +#define GPPUD (gpio_reg+0x94) +#define GPPUDCLK0 (gpio_reg+0x98) +#define GPPUDCLK1 (gpio_reg+0x9C) +#define GPSET0 (gpio_reg+0x1c) +#define GPSET1 (gpio_reg+0x20) +#define GPCLR0 (gpio_reg+0x28) +#define GPCLR1 (gpio_reg+0x2c) + +#define GPIO_REG(g) (gpio_reg+((g/10)*4)) +#define SET_GPIO_OUTPUT(g) \ + __raw_writel( \ + (1<<(((g)%10)*3)) \ + | (__raw_readl(GPIO_REG(g)) & (~(7<<(((g)%10)*3)))), \ + GPIO_REG(g)) +#define SET_GPIO_INPUT(g) \ + __raw_writel( \ + 0 \ + | (__raw_readl(GPIO_REG(g)) & (~(7<<(((g)%10)*3)))), \ + GPIO_REG(g)) +#define SET_GPIO_ALT(g,a) \ + __raw_writel( \ + (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3)) \ + | (__raw_readl(GPIO_REG(g)) & (~(7<<(((g)%10)*3)))), \ + GPIO_REG(g)) + +enum button_mode { + MODE_BUTTON = 0, + MODE_SWITCH = 1, +}; + + +enum gpio_pull_direction { + GPIO_PULL_NONE = 0, + GPIO_PULL_DOWN = 1, + GPIO_PULL_UP = 2, +}; + + +/* Module Parameters */ +static int gpio_pin = 22; +static int mode = MODE_SWITCH; +static int led_pin = 16; + +/* This is the base state. When this changes, do a shutdown. */ +static int gpio_pol; + +static void __iomem *gpio_reg; +static void (*old_pm_power_off)(void); +static struct device *switch_dev; +static int raw_gpio = 0; + + +/* Attach either a pull up or pull down to the specified GPIO pin. Or + * clear any pull on the pin, if requested. + */ +static int set_gpio_pull(int gpio, enum gpio_pull_direction direction) { + long *bank; + int pin; + + bank = ((gpio&(~31))?GPPUDCLK1:GPPUDCLK0); + pin = gpio & 31; + + /* Set the direction (involves two writes and a clock wait) */ + __raw_writel(direction, GPPUD); + udelay(20); + __raw_writel(1< 63) + return -1; + else if (gpio < 32) + __raw_writel(1< 100) + duty = 100; + low = duty; + high = 100-duty; + + if (raw_gpio) + raw_gpio_set(gpio, 0); + else + gpio_set_value(gpio, 0); + udelay(RATE*low); + + if (raw_gpio) + raw_gpio_set(gpio, 1); + else + gpio_set_value(gpio, 1); + udelay(RATE*high); + + return (RATE*low)+(RATE*high); +} + + + +/* Give an indication that it's safe to turn off the board. Pulse the LED + * in a kind of "breathing" pattern, so the user knows that it's + * "powered down". + */ +static int do_breathing_forever(int gpio) { + int err; + err = gpio_request(gpio, "LED light"); + if (err < 0) { + pr_err("Unable to request GPIO, switching to raw access"); + raw_gpio = 1; + } + SET_GPIO_OUTPUT(gpio); + + while (1) { + int usecs; + /* We want four seconds: + * - One second of ramp-up + * - One second of ramp-down + * - Two seconds of low + */ + for (usecs=0; usecs < 800000; ) + usecs += gpio_pulse(gpio, ((usecs*9)/80000)+10); + + for (usecs=0; usecs < 800000; ) + usecs += gpio_pulse(gpio, 100-((usecs*9)/80000)); + + for (usecs=0; usecs < 800000; ) + usecs += gpio_pulse(gpio, 10); + + for (usecs=0; usecs < 800000; ) + usecs += gpio_pulse(gpio, 10); + } + return 0; +} + + + +/* Our shutdown function. Execution will stay here until the switch is + * flipped. + * NOTE: The default power_off function sends a message to the GPU via + * a mailbox message to shut down most parts of the core. Since we don't + * have any documentation on the mailbox message formats, we will leave + * the CPU powered up here but not executing any code in order to simulate + * an "off" state. + */ +static void rpi_power_switch_power_off(void) { + int ret; + pr_info("Waiting for the switch to be flipped back...\n"); + if (mode == MODE_SWITCH) + gpio_pol = !gpio_pol; + ret = request_irq(gpio_to_irq(gpio_pin), reboot_isr, + gpio_pol?IRQF_TRIGGER_RISING:IRQF_TRIGGER_FALLING, + "Reboot ISR", NULL); + + /* If it's taken us so long to reboot that the switch was flipped, + * immediately reboot. + */ + if (gpio_pol == gpio_get_value(gpio_pin)) + reboot_isr(0, NULL); + + do_breathing_forever(led_pin); + return; +} + + +static irqreturn_t power_isr(int irqno, void *param) { + schedule_delayed_work(&initiate_shutdown_work, msecs_to_jiffies(100)); + return IRQ_HANDLED; +} + + + +/* Sysfs entry */ + +static ssize_t do_shutdown_show(struct device *d, + struct device_attribute *attr, char *buf) +{ + ssize_t ret; + ret = sprintf(buf, "Write into this file to initiate a shutdown\n"); + return ret; +} + +static ssize_t do_shutdown_store(struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + if (mode == MODE_SWITCH) + gpio_pol = !gpio_pol; + schedule_delayed_work(&initiate_shutdown_work, msecs_to_jiffies(10)); + return count; +} +static DEVICE_ATTR(do_shutdown, 0660, do_shutdown_show, do_shutdown_store); + +static struct attribute *rpi_power_switch_sysfs_entries[] = { + &dev_attr_do_shutdown.attr, + NULL, +}; + +static struct attribute_group rpi_power_switch_attribute_group = { + .name = NULL, + .attrs = rpi_power_switch_sysfs_entries, +}; + +static struct class power_switch_class = { + .name = POWER_SWITCH_CLASS_NAME, + .owner = THIS_MODULE, +}; + + + + +/* Main module entry point */ + +int __init rpi_power_switch_init(void) +{ + int ret = 0; + + old_pm_power_off = pm_power_off; + pm_power_off = rpi_power_switch_power_off; + + pr_info("Adafruit Industries' power switch driver v%s\n", + RPI_POWER_SWITCH_VERSION); + + INIT_DELAYED_WORK(&initiate_shutdown_work, initiate_shutdown); + +//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + + /* Register our own class for the power switch */ + ret = class_register(&power_switch_class); + if (ret < 0) { + pr_err("%s: Unable to register class\n", power_switch_class.name); + goto out0; + } + + +//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + + /* Create devices for each PWM present */ + switch_dev = device_create(&power_switch_class, &platform_bus, + MKDEV(0, 0), NULL, "pswitch%u", 0); + if (IS_ERR(switch_dev)) { + pr_err("%s: device_create failed\n", power_switch_class.name); + ret = PTR_ERR(switch_dev); + goto out1; + } + +//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + + ret = sysfs_create_group(&switch_dev->kobj, + &rpi_power_switch_attribute_group); + if (ret < 0) { + pr_err("%s: create_group failed\n", power_switch_class.name); + goto out2; + } + +//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + + /* GPIO register memory must be mapped before doing any direct + * accesses such as changing GPIO alt functions or changing GPIO + * pull ups or pull downs. + */ + gpio_reg = ioremap(GPIO_BASE, 1024); + + /* Set the specified pin as a GPIO input */ + SET_GPIO_INPUT(gpio_pin); + + /* Set the pin as a pulldown. Most pins should default to having + * pulldowns, and this seems most intuitive. + */ + set_gpio_pull(gpio_pin, GPIO_PULL_UP); + + ret = gpio_request(gpio_pin, "Power switch"); + if (ret) { + printk(KERN_ALERT "GPIO request failure: %d\n", ret); + goto out3; + } + +//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + + gpio_direction_input(gpio_pin); + + /* The targeted polarity should be the opposite of the current value. + * I.e. we want the pin to transition to this state in order to + * initiate a shutdown. + */ + gpio_pol = !gpio_get_value(gpio_pin); + + /* Request an interrupt to fire when the pin transitions to our + * desired state. + */ + ret = request_irq(__gpio_to_irq(gpio_pin), power_isr, + gpio_pol?IRQF_TRIGGER_RISING:IRQF_TRIGGER_FALLING, + "Power button", NULL); + if (ret) { + pr_err("Unable to request IRQ\n"); + goto out3; + } + +//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + + return 0; + + + /* Error handling */ +out3: + sysfs_remove_group(&switch_dev->kobj,&rpi_power_switch_attribute_group); +out2: + device_unregister(switch_dev); +out1: + class_unregister(&power_switch_class); +out0: + iounmap(gpio_reg); + pm_power_off = old_pm_power_off; + return ret; +} + + +/* Main module exit point (called at unload) */ + +void __exit rpi_power_switch_cleanup(void) +{ + +//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + sysfs_remove_group(&switch_dev->kobj,&rpi_power_switch_attribute_group); + device_unregister(switch_dev); + free_irq(__gpio_to_irq(gpio_pin), NULL); +//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + gpio_free(gpio_pin); + pm_power_off = old_pm_power_off; + class_unregister(&power_switch_class); + iounmap(gpio_reg); +//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + +} + +module_init(rpi_power_switch_init); +module_exit(rpi_power_switch_cleanup); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Sean Cross for Adafruit Industries "); +MODULE_ALIAS("platform:bcm2708_power_switch"); +module_param(gpio_pin, int, 0); +module_param(led_pin, int, 0); +module_param(mode, int, 0); From 467cdfbe3781a6a91ad3cf2d8a36c20f0f091395 Mon Sep 17 00:00:00 2001 From: Brennen Bearnes Date: Tue, 9 Jun 2015 10:02:45 -0600 Subject: [PATCH 2/4] rpi_power_switch: make Kconfig option depend on Raspberry Pi platform Per Phil Elwell here: https://github.com/raspberrypi/linux/pull/1014 --- drivers/power/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index e241ad715a0102..94dad4a1dc40b8 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -77,6 +77,7 @@ config BATTERY_88PM860X config RPI_POWER_SWITCH tristate "Raspberry Pi GPIO power switch" + depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 help Use a GPIO as a pseudo power switch. From 7bbc84b041e3a5266b720ee9f1f706b51592d74e Mon Sep 17 00:00:00 2001 From: Brennen Bearnes Date: Tue, 9 Jun 2015 10:09:09 -0600 Subject: [PATCH 3/4] rpi_power_switch: add copyright / GPL notice; tidy code - Adds copyright notice (I'm assuming work for hire here, maybe should be Copyright Sean Cross instead?) - Adds GPL notice - Removes a pile of printk()s - Removes some blank lines - K&Rifies some functions --- drivers/power/rpi_power_switch.c | 131 ++++++++++++++----------------- 1 file changed, 59 insertions(+), 72 deletions(-) diff --git a/drivers/power/rpi_power_switch.c b/drivers/power/rpi_power_switch.c index 049af002122ae2..1813fd6dcb97d7 100644 --- a/drivers/power/rpi_power_switch.c +++ b/drivers/power/rpi_power_switch.c @@ -1,9 +1,23 @@ /* * Adafruit power switch driver for Raspberry Pi * - * Simulated power switch / button, using the GPIO banks. + * Written by Sean Cross for Adafruit Industries * - * - Written by Sean Cross for Adafruit Industries (www.adafruit.com) + * Copyright (C) 2014 Adafruit Industries (www.adafruit.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #define RPI_POWER_SWITCH_VERSION "1.7" @@ -23,7 +37,6 @@ #include #include - /* the BCM2709 redefines this for us right! #define BCM2708_PERI_BASE 0x20000000 */ @@ -59,14 +72,12 @@ enum button_mode { MODE_SWITCH = 1, }; - enum gpio_pull_direction { GPIO_PULL_NONE = 0, GPIO_PULL_DOWN = 1, GPIO_PULL_UP = 2, }; - /* Module Parameters */ static int gpio_pin = 22; static int mode = MODE_SWITCH; @@ -80,11 +91,12 @@ static void (*old_pm_power_off)(void); static struct device *switch_dev; static int raw_gpio = 0; - -/* Attach either a pull up or pull down to the specified GPIO pin. Or +/* + * Attach either a pull up or pull down to the specified GPIO pin. Or * clear any pull on the pin, if requested. */ -static int set_gpio_pull(int gpio, enum gpio_pull_direction direction) { +static int set_gpio_pull(int gpio, enum gpio_pull_direction direction) +{ long *bank; int pin; @@ -103,13 +115,14 @@ static int set_gpio_pull(int gpio, enum gpio_pull_direction direction) { return 0; } - -/* If the GPIO we want to use is already being used (e.g. if a driver +/* + * If the GPIO we want to use is already being used (e.g. if a driver * forgot to call gpio_free() during its module_exit() call), then we * will have to directly access the GPIO registers in order to set or * clear values. */ -static int raw_gpio_set(int gpio, int val) { +static int raw_gpio_set(int gpio, int val) +{ if (gpio < 0 || gpio > 63) return -1; else if (gpio < 32) @@ -119,12 +132,16 @@ static int raw_gpio_set(int gpio, int val) { return 0; } -/* Bottom half of the power switch ISR. +/* + * Bottom half of the power switch ISR. + * * We need to break this out here, as you can't run call_usermodehelper * from an interrupt context. + * * This function will actually Call /sbin/shutdown when the switch gets hit. */ -static void initiate_shutdown(struct work_struct *work) { +static void initiate_shutdown(struct work_struct *work) +{ int ret; char *cmd = "/sbin/shutdown"; char *argv[] = { @@ -139,45 +156,36 @@ static void initiate_shutdown(struct work_struct *work) { NULL, }; -//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); - /* We only want this IRQ to fire once, ever. */ free_irq(gpio_to_irq(gpio_pin), NULL); -//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); - /* Make sure the switch hasn't just bounced */ if (mode == MODE_SWITCH && gpio_get_value(gpio_pin) != gpio_pol) return; -//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); - - ret = call_usermodehelper(cmd, argv, envp, UMH_WAIT_PROC); - -//printk(KERN_ALERT "returned %d\n", ret); - } static struct delayed_work initiate_shutdown_work; - -/* This ISR gets called when the board is "off" and the switch changes. +/* + * This ISR gets called when the board is "off" and the switch changes. * It indicates we should start back up again, which means we need to * do a reboot. */ -static irqreturn_t reboot_isr(int irqno, void *param) { +static irqreturn_t reboot_isr(int irqno, void *param) +{ emergency_restart(); return IRQ_HANDLED; } - - -/* Pulse the GPIO low for /duty/ cycles and then /high/ for 100-duty cycles. +/* + * Pulse the GPIO low for /duty/ cycles and then /high/ for 100-duty cycles. * Returns the number of usecs delayed. */ #define RATE 1 -static int gpio_pulse(int gpio, int duty) { +static int gpio_pulse(int gpio, int duty) +{ int low; int high; @@ -203,13 +211,13 @@ static int gpio_pulse(int gpio, int duty) { return (RATE*low)+(RATE*high); } - - -/* Give an indication that it's safe to turn off the board. Pulse the LED +/* + * Give an indication that it's safe to turn off the board. Pulse the LED * in a kind of "breathing" pattern, so the user knows that it's * "powered down". */ -static int do_breathing_forever(int gpio) { +static int do_breathing_forever(int gpio) +{ int err; err = gpio_request(gpio, "LED light"); if (err < 0) { @@ -240,17 +248,18 @@ static int do_breathing_forever(int gpio) { return 0; } - - -/* Our shutdown function. Execution will stay here until the switch is +/* + * Our shutdown function. Execution will stay here until the switch is * flipped. + * * NOTE: The default power_off function sends a message to the GPU via * a mailbox message to shut down most parts of the core. Since we don't * have any documentation on the mailbox message formats, we will leave * the CPU powered up here but not executing any code in order to simulate * an "off" state. */ -static void rpi_power_switch_power_off(void) { +static void rpi_power_switch_power_off(void) +{ int ret; pr_info("Waiting for the switch to be flipped back...\n"); if (mode == MODE_SWITCH) @@ -259,7 +268,8 @@ static void rpi_power_switch_power_off(void) { gpio_pol?IRQF_TRIGGER_RISING:IRQF_TRIGGER_FALLING, "Reboot ISR", NULL); - /* If it's taken us so long to reboot that the switch was flipped, + /* + * If it's taken us so long to reboot that the switch was flipped, * immediately reboot. */ if (gpio_pol == gpio_get_value(gpio_pin)) @@ -269,14 +279,12 @@ static void rpi_power_switch_power_off(void) { return; } - -static irqreturn_t power_isr(int irqno, void *param) { +static irqreturn_t power_isr(int irqno, void *param) +{ schedule_delayed_work(&initiate_shutdown_work, msecs_to_jiffies(100)); return IRQ_HANDLED; } - - /* Sysfs entry */ static ssize_t do_shutdown_show(struct device *d, @@ -312,11 +320,7 @@ static struct class power_switch_class = { .owner = THIS_MODULE, }; - - - /* Main module entry point */ - int __init rpi_power_switch_init(void) { int ret = 0; @@ -329,8 +333,6 @@ int __init rpi_power_switch_init(void) INIT_DELAYED_WORK(&initiate_shutdown_work, initiate_shutdown); -//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); - /* Register our own class for the power switch */ ret = class_register(&power_switch_class); if (ret < 0) { @@ -338,9 +340,6 @@ int __init rpi_power_switch_init(void) goto out0; } - -//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); - /* Create devices for each PWM present */ switch_dev = device_create(&power_switch_class, &platform_bus, MKDEV(0, 0), NULL, "pswitch%u", 0); @@ -350,8 +349,6 @@ int __init rpi_power_switch_init(void) goto out1; } -//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); - ret = sysfs_create_group(&switch_dev->kobj, &rpi_power_switch_attribute_group); if (ret < 0) { @@ -359,9 +356,8 @@ int __init rpi_power_switch_init(void) goto out2; } -//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); - - /* GPIO register memory must be mapped before doing any direct + /* + * GPIO register memory must be mapped before doing any direct * accesses such as changing GPIO alt functions or changing GPIO * pull ups or pull downs. */ @@ -370,7 +366,8 @@ int __init rpi_power_switch_init(void) /* Set the specified pin as a GPIO input */ SET_GPIO_INPUT(gpio_pin); - /* Set the pin as a pulldown. Most pins should default to having + /* + * Set the pin as a pulldown. Most pins should default to having * pulldowns, and this seems most intuitive. */ set_gpio_pull(gpio_pin, GPIO_PULL_UP); @@ -381,17 +378,17 @@ int __init rpi_power_switch_init(void) goto out3; } -//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); - gpio_direction_input(gpio_pin); - /* The targeted polarity should be the opposite of the current value. + /* + * The targeted polarity should be the opposite of the current value. * I.e. we want the pin to transition to this state in order to * initiate a shutdown. */ gpio_pol = !gpio_get_value(gpio_pin); - /* Request an interrupt to fire when the pin transitions to our + /* + * Request an interrupt to fire when the pin transitions to our * desired state. */ ret = request_irq(__gpio_to_irq(gpio_pin), power_isr, @@ -402,11 +399,8 @@ int __init rpi_power_switch_init(void) goto out3; } -//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); - return 0; - /* Error handling */ out3: sysfs_remove_group(&switch_dev->kobj,&rpi_power_switch_attribute_group); @@ -420,23 +414,16 @@ int __init rpi_power_switch_init(void) return ret; } - /* Main module exit point (called at unload) */ - void __exit rpi_power_switch_cleanup(void) { - -//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); sysfs_remove_group(&switch_dev->kobj,&rpi_power_switch_attribute_group); device_unregister(switch_dev); free_irq(__gpio_to_irq(gpio_pin), NULL); -//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); gpio_free(gpio_pin); pm_power_off = old_pm_power_off; class_unregister(&power_switch_class); iounmap(gpio_reg); -//printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); - } module_init(rpi_power_switch_init); From 8a556fbf9fde154b858383466382033838feb053 Mon Sep 17 00:00:00 2001 From: Brennen Bearnes Date: Tue, 9 Jun 2015 11:40:53 -0600 Subject: [PATCH 4/4] rpi_power_switch: add module parameter descriptions --- drivers/power/rpi_power_switch.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/power/rpi_power_switch.c b/drivers/power/rpi_power_switch.c index 1813fd6dcb97d7..bacf1de0dd6071 100644 --- a/drivers/power/rpi_power_switch.c +++ b/drivers/power/rpi_power_switch.c @@ -432,5 +432,8 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Sean Cross for Adafruit Industries "); MODULE_ALIAS("platform:bcm2708_power_switch"); module_param(gpio_pin, int, 0); +MODULE_PARM_DESC(gpio_pin, "GPIO pin number of the BCM processor for shutdown switch (default 23)"); module_param(led_pin, int, 0); +MODULE_PARM_DESC(led_pin, "Pin for LED to pulse after shutdown (default 16)"); module_param(mode, int, 0); +MODULE_PARM_DESC(mode, "Shutdown switch mode (0 for button, 1 for switch)");