diff options
-rw-r--r-- | drivers/power/Kconfig | 7 | ||||
-rw-r--r-- | drivers/power/Makefile | 1 | ||||
-rw-r--r-- | drivers/power/tegra_bpc_mgmt.c | 139 | ||||
-rw-r--r-- | include/linux/platform_data/tegra_bpc_mgmt.h | 25 |
4 files changed, 172 insertions, 0 deletions
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index b679e2d9785b..d70887fa2e1e 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -272,3 +272,10 @@ config CHARGER_MAX8998 platform data of MAX8998/LP3974 PMICs. endif # POWER_SUPPLY + +config TEGRA_BPC_MGMT + tristate "battery peak current management" + depends on ARCH_TEGRA + help + This driver reduces cpu frequency/voltage on gpio event from the + battery current monitor device. diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 6c457346a537..82bdd18e3d81 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -41,3 +41,4 @@ obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o obj-$(CONFIG_MAX8907C_CHARGER) += max8907c-charger.o +obj-$(CONFIG_TEGRA_BPC_MGMT) += tegra_bpc_mgmt.o diff --git a/drivers/power/tegra_bpc_mgmt.c b/drivers/power/tegra_bpc_mgmt.c new file mode 100644 index 000000000000..0d9ddeee282e --- /dev/null +++ b/drivers/power/tegra_bpc_mgmt.c @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2010-2011 NVIDIA Corporation + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include <linux/module.h> +#include <linux/gpio.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/irqflags.h> +#include <linux/slab.h> +#include <linux/irq.h> +#include <linux/sched.h> +#include <linux/jiffies.h> +#include <linux/platform_data/tegra_bpc_mgmt.h> + +#include <mach/edp.h> + +static irqreturn_t tegra_bpc_mgmt_bh(int irq, void *data) +{ + int gpio_val = 0; + struct tegra_bpc_mgmt_platform_data *bpc_platform_data; + bpc_platform_data = (struct tegra_bpc_mgmt_platform_data *)data; + + tegra_system_edp_alarm(true); + /** + * Keep on checking whether event has passed or not. + */ + while (!gpio_val) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(msecs_to_jiffies( + bpc_platform_data->bpc_mgmt_timeout)); + + gpio_val = gpio_get_value(bpc_platform_data->gpio_trigger); + } + + tegra_system_edp_alarm(false); + + return IRQ_HANDLED; +} + +static irqreturn_t tegra_bpc_mgmt_isr(int irq, void *data) +{ + tegra_edp_throttle_cpu_now(2); + return IRQ_WAKE_THREAD; +} + +static __devinit int tegra_bpc_mgmt_probe(struct platform_device *pdev) +{ + u32 ret; + struct task_struct *bh_thread; + struct irq_desc *bat_desc; + struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; + struct tegra_bpc_mgmt_platform_data *bpc_platform_data; + + bpc_platform_data = pdev->dev.platform_data; + if (!bpc_platform_data) + return -ENODEV; + + if (gpio_is_valid(bpc_platform_data->gpio_trigger)) { + ret = gpio_request(bpc_platform_data->gpio_trigger, + "tegra-bpc-mgmt"); + + if (ret < 0) { + pr_err("BPC: GPIO request failed"); + return -ENODEV; + } + } else { + pr_err("BPC: GPIO check failed, gpio %d", + bpc_platform_data->gpio_trigger); + return -ENODEV; + } + + gpio_direction_input(bpc_platform_data->gpio_trigger); + + ret = request_threaded_irq( + gpio_to_irq(bpc_platform_data->gpio_trigger), + tegra_bpc_mgmt_isr, + tegra_bpc_mgmt_bh, IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "tegra-bpc-mgmt", bpc_platform_data); + if (ret < 0) { + pr_err("BPC:IRQ Installation failed\n"); + return -ENODEV; + } + bat_desc = irq_to_desc( + gpio_to_irq(bpc_platform_data->gpio_trigger)); + + if (bat_desc) { + bh_thread = bat_desc->action->thread; + if (bh_thread) + sched_setscheduler_nocheck(bh_thread, + SCHED_FIFO, ¶m); + } + + return 0; +} + +static __devexit int tegra_bpc_mgmt_remove(struct platform_device *pdev) +{ + struct tegra_bpc_mgmt_platform_data *bpc_platform_data; + bpc_platform_data = pdev->dev.platform_data; + free_irq(gpio_to_irq(bpc_platform_data->gpio_trigger), NULL); + return 0; +} + +static struct platform_driver tegra_bpc_mgmt_driver = { + .probe = tegra_bpc_mgmt_probe, + .remove = tegra_bpc_mgmt_remove, + .driver = { + .name = "tegra-bpc-mgmt", + .owner = THIS_MODULE, + }, +}; + +static int __init tegra_bpc_mgmt_init(void) +{ + return platform_driver_register(&tegra_bpc_mgmt_driver); +} + +static void __exit tegra_bpc_mgmt_exit(void) +{ + platform_driver_unregister(&tegra_bpc_mgmt_driver); +} + +module_init(tegra_bpc_mgmt_init); +module_exit(tegra_bpc_mgmt_exit); + +MODULE_DESCRIPTION("TEGRA Battery Peak current Management"); +MODULE_AUTHOR("NVIDIA"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/platform_data/tegra_bpc_mgmt.h b/include/linux/platform_data/tegra_bpc_mgmt.h new file mode 100644 index 000000000000..bdd4862d63a3 --- /dev/null +++ b/include/linux/platform_data/tegra_bpc_mgmt.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2010-2011 NVIDIA Corporation + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef __TEGRA_BPC_MGMT_H +#define __TEGRA_BPC_MGMT_H +#include <linux/cpumask.h> + +struct tegra_bpc_mgmt_platform_data { + int gpio_trigger; + struct cpumask affinity_mask; + int bpc_mgmt_timeout; +}; + +#endif /*__TEGRA_BPC_MGMT_H*/ |