Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3f86b832 authored by Rich Townsend's avatar Rich Townsend Committed by Len Brown
Browse files

ACPI: add support for Smart Battery

Most batteries today are ACPI "Control Method" batteries,
but some models ship with the older "Smart Battery"
that requires this code.

Rich Townsend and Bruno Ducrot were the original authors.
Vladimir Lebedev updated to run on latest kernel.

http://bugzilla.kernel.org/show_bug.cgi?id=3734



Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 37672d4c
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -352,6 +352,18 @@ config ACPI_HOTPLUG_MEMORY
	  If one selects "m," this driver can be loaded using the following
	  command: 
		$>modprobe acpi_memhotplug 

config ACPI_SBS
	tristate "Smart Battery System (EXPERIMENTAL)"
	depends on X86 && I2C
	depends on EXPERIMENTAL
	default y
	help
	  This driver adds support for the Smart Battery System.
	  Depends on I2C (Device Drivers ---> I2C support)
	  A "Smart Battery" is quite old and quite rare compared
	  to today's ACPI "Control Method" battery.

endif	# ACPI

endmenu
+2 −0
Original line number Diff line number Diff line
@@ -58,3 +58,5 @@ obj-$(CONFIG_ACPI_IBM) += ibm_acpi.o
obj-$(CONFIG_ACPI_TOSHIBA)	+= toshiba_acpi.o
obj-y				+= scan.o motherboard.o
obj-$(CONFIG_ACPI_HOTPLUG_MEMORY)	+= acpi_memhotplug.o
obj-y				+= cm_sbs.o
obj-$(CONFIG_ACPI_SBS)		+= i2c_ec.o sbs.o
+7 −5
Original line number Diff line number Diff line
@@ -50,6 +50,9 @@ ACPI_MODULE_NAME("acpi_ac")
MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME);
MODULE_LICENSE("GPL");

extern struct proc_dir_entry *acpi_lock_ac_dir(void);
extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);

static int acpi_ac_add(struct acpi_device *device);
static int acpi_ac_remove(struct acpi_device *device, int type);
static int acpi_ac_open_fs(struct inode *inode, struct file *file);
@@ -278,17 +281,16 @@ static int acpi_ac_remove(struct acpi_device *device, int type)

static int __init acpi_ac_init(void)
{
	int result = 0;
	int result;


	acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir);
	acpi_ac_dir = acpi_lock_ac_dir();
	if (!acpi_ac_dir)
		return -ENODEV;
	acpi_ac_dir->owner = THIS_MODULE;

	result = acpi_bus_register_driver(&acpi_ac_driver);
	if (result < 0) {
		remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
		acpi_unlock_ac_dir(acpi_ac_dir);
		return -ENODEV;
	}

@@ -300,7 +302,7 @@ static void __exit acpi_ac_exit(void)

	acpi_bus_unregister_driver(&acpi_ac_driver);

	remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
	acpi_unlock_ac_dir(acpi_ac_dir);

	return;
}
+7 −6
Original line number Diff line number Diff line
@@ -59,6 +59,9 @@ ACPI_MODULE_NAME("acpi_battery")
MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME);
MODULE_LICENSE("GPL");

extern struct proc_dir_entry *acpi_lock_battery_dir(void);
extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);

static int acpi_battery_add(struct acpi_device *device);
static int acpi_battery_remove(struct acpi_device *device, int type);

@@ -750,17 +753,15 @@ static int acpi_battery_remove(struct acpi_device *device, int type)

static int __init acpi_battery_init(void)
{
	int result = 0;

	int result;

	acpi_battery_dir = proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir);
	acpi_battery_dir = acpi_lock_battery_dir();
	if (!acpi_battery_dir)
		return -ENODEV;
	acpi_battery_dir->owner = THIS_MODULE;

	result = acpi_bus_register_driver(&acpi_battery_driver);
	if (result < 0) {
		remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
		acpi_unlock_battery_dir(acpi_battery_dir);
		return -ENODEV;
	}

@@ -772,7 +773,7 @@ static void __exit acpi_battery_exit(void)

	acpi_bus_unregister_driver(&acpi_battery_driver);

	remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
	acpi_unlock_battery_dir(acpi_battery_dir);

	return;
}

drivers/acpi/cm_sbs.c

0 → 100644
+135 −0
Original line number Diff line number Diff line
/*
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 *  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.,
 *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/acpi.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include <acpi/acmacros.h>
#include <acpi/actypes.h>
#include <acpi/acutils.h>

ACPI_MODULE_NAME("cm_sbs")
#define ACPI_AC_CLASS		"ac_adapter"
#define ACPI_BATTERY_CLASS	"battery"
#define ACPI_SBS_COMPONENT	0x00080000
#define _COMPONENT		ACPI_SBS_COMPONENT
static struct proc_dir_entry *acpi_ac_dir;
static struct proc_dir_entry *acpi_battery_dir;

static struct semaphore cm_sbs_sem;

static int lock_ac_dir_cnt = 0;
static int lock_battery_dir_cnt = 0;

struct proc_dir_entry *acpi_lock_ac_dir(void)
{
	ACPI_FUNCTION_TRACE("acpi_lock_ac_dir");

	down(&cm_sbs_sem);
	if (!acpi_ac_dir) {
		acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir);
	}
	if (acpi_ac_dir) {
		lock_ac_dir_cnt++;
	} else {
		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
				  "Cannot create %s\n", ACPI_AC_CLASS));
	}
	up(&cm_sbs_sem);
	return (acpi_ac_dir);
}

EXPORT_SYMBOL(acpi_lock_ac_dir);

void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir_param)
{
	ACPI_FUNCTION_TRACE("acpi_unlock_ac_dir");

	down(&cm_sbs_sem);
	if (acpi_ac_dir_param) {
		lock_ac_dir_cnt--;
	}
	if (lock_ac_dir_cnt == 0 && acpi_ac_dir_param && acpi_ac_dir) {
		remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
		acpi_ac_dir = 0;
	}
	up(&cm_sbs_sem);
}

EXPORT_SYMBOL(acpi_unlock_ac_dir);

struct proc_dir_entry *acpi_lock_battery_dir(void)
{
	ACPI_FUNCTION_TRACE("acpi_lock_battery_dir");

	down(&cm_sbs_sem);
	if (!acpi_battery_dir) {
		acpi_battery_dir =
		    proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir);
	}
	if (acpi_battery_dir) {
		lock_battery_dir_cnt++;
	} else {
		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
				  "Cannot create %s\n", ACPI_BATTERY_CLASS));
	}
	up(&cm_sbs_sem);
	return (acpi_battery_dir);
}

EXPORT_SYMBOL(acpi_lock_battery_dir);

void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir_param)
{
	ACPI_FUNCTION_TRACE("acpi_unlock_battery_dir");

	down(&cm_sbs_sem);
	if (acpi_battery_dir_param) {
		lock_battery_dir_cnt--;
	}
	if (lock_battery_dir_cnt == 0 && acpi_battery_dir_param
	    && acpi_battery_dir) {
		remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
		acpi_battery_dir = 0;
	}
	up(&cm_sbs_sem);
}

EXPORT_SYMBOL(acpi_unlock_battery_dir);

static int __init acpi_cm_sbs_init(void)
{
	ACPI_FUNCTION_TRACE("acpi_cm_sbs_init");

	if (acpi_disabled)
		return_VALUE(0);

	init_MUTEX(&cm_sbs_sem);

	return_VALUE(0);
}

subsys_initcall(acpi_cm_sbs_init);
Loading