2 * tp_smapi.c - ThinkPad SMAPI support
4 * This driver exposes some features of the System Management Application
5 * Program Interface (SMAPI) BIOS found on ThinkPad laptops. It works on
6 * models in which the SMAPI BIOS runs in SMM and is invoked by writing
7 * to the APM control port 0xB2.
8 * It also exposes battery status information, obtained from the ThinkPad
9 * embedded controller (via the thinkpad_ec module).
10 * Ancient ThinkPad models use a different interface, supported by the
11 * "thinkpad" module from "tpctl".
13 * Many of the battery status values obtained from the EC simply mirror
14 * values provided by the battery's Smart Battery System (SBS) interface, so
15 * their meaning is defined by the Smart Battery Data Specification (see
16 * http://sbs-forum.org/specs/sbdat110.pdf). References to this SBS spec
17 * are given in the code where relevant.
19 * Copyright (C) 2006 Shem Multinymous <multinymous@gmail.com>.
20 * SMAPI access code based on the mwave driver by Mike Sullivan.
22 * This program is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation; either version 2 of the License, or
25 * (at your option) any later version.
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37 #include <linux/kernel.h>
38 #include <linux/module.h>
39 #include <linux/init.h>
40 #include <linux/types.h>
41 #include <linux/proc_fs.h>
42 #include <linux/mc146818rtc.h> /* CMOS defines */
43 #include <linux/delay.h>
44 #include <linux/version.h>
45 #include "thinkpad_ec.h"
46 #include <linux/platform_device.h>
47 #include <asm/uaccess.h>
50 #define TP_VERSION "0.43"
51 #define TP_DESC "ThinkPad SMAPI Support"
52 #define TP_DIR "smapi"
54 MODULE_AUTHOR("Shem Multinymous");
55 MODULE_DESCRIPTION(TP_DESC);
56 MODULE_VERSION(TP_VERSION);
57 MODULE_LICENSE("GPL");
59 static struct platform_device *pdev;
62 module_param_named(debug, tp_debug, int, 0600);
63 MODULE_PARM_DESC(debug, "Debug level (0=off, 1=on)");
65 /* A few macros for printk()ing: */
66 #define TPRINTK(level, fmt, args...) \
67 dev_printk(level, &(pdev->dev), "%s: " fmt "\n", __func__, ## args)
68 #define DPRINTK(fmt, args...) \
69 do { if (tp_debug) TPRINTK(KERN_DEBUG, fmt, ## args); } while (0)
71 /*********************************************************************
75 /* SMAPI functions (register BX when making the SMM call). */
76 #define SMAPI_GET_INHIBIT_CHARGE 0x2114
77 #define SMAPI_SET_INHIBIT_CHARGE 0x2115
78 #define SMAPI_GET_THRESH_START 0x2116
79 #define SMAPI_SET_THRESH_START 0x2117
80 #define SMAPI_GET_FORCE_DISCHARGE 0x2118
81 #define SMAPI_SET_FORCE_DISCHARGE 0x2119
82 #define SMAPI_GET_THRESH_STOP 0x211a
83 #define SMAPI_SET_THRESH_STOP 0x211b
85 /* SMAPI error codes (see ThinkPad 770 Technical Reference Manual p.83 at
86 http://www-307.ibm.com/pc/support/site.wss/document.do?lndocid=PFAN-3TUQQD */
87 #define SMAPI_RETCODE_EOF 0xff
88 static struct { u8 rc; char *msg; int ret; } smapi_retcode[] =
91 {0x53, "SMAPI function is not available", -ENXIO},
92 {0x81, "Invalid parameter", -EINVAL},
93 {0x86, "Function is not supported by SMAPI BIOS", -EOPNOTSUPP},
94 {0x90, "System error", -EIO},
95 {0x91, "System is invalid", -EIO},
96 {0x92, "System is busy, -EBUSY"},
97 {0xa0, "Device error (disk read error)", -EIO},
98 {0xa1, "Device is busy", -EBUSY},
99 {0xa2, "Device is not attached", -ENXIO},
100 {0xa3, "Device is disbled", -EIO},
101 {0xa4, "Request parameter is out of range", -EINVAL},
102 {0xa5, "Request parameter is not accepted", -EINVAL},
103 {0xa6, "Transient error", -EBUSY}, /* ? */
104 {SMAPI_RETCODE_EOF, "Unknown error code", -EIO}
108 #define SMAPI_MAX_RETRIES 10
109 #define SMAPI_PORT2 0x4F /* fixed port, meaning unclear */
110 static u16 smapi_port; /* APM control port, normally 0xB2 */
112 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
113 static DECLARE_MUTEX(smapi_mutex);
115 static DEFINE_SEMAPHORE(smapi_mutex);
119 * find_smapi_port - read SMAPI port from NVRAM
121 static int __init find_smapi_port(void)
124 unsigned short port = 0;
127 spin_lock_irqsave(&rtc_lock, flags);
128 smapi_id = CMOS_READ(0x7C);
129 smapi_id |= (CMOS_READ(0x7D) << 8);
130 spin_unlock_irqrestore(&rtc_lock, flags);
132 if (smapi_id != 0x5349) {
133 printk(KERN_ERR "SMAPI not supported (ID=0x%x)\n", smapi_id);
136 spin_lock_irqsave(&rtc_lock, flags);
137 port = CMOS_READ(0x7E);
138 port |= (CMOS_READ(0x7F) << 8);
139 spin_unlock_irqrestore(&rtc_lock, flags);
141 printk(KERN_ERR "unable to read SMAPI port number\n");
148 * smapi_request - make a SMAPI call
149 * @inEBX, @inECX, @inEDI, @inESI: input registers
150 * @outEBX, @outECX, @outEDX, @outEDI, @outESI: outputs registers
151 * @msg: textual error message
152 * Invokes the SMAPI SMBIOS with the given input and outpu args.
153 * All outputs are optional (can be %NULL).
154 * Returns 0 when successful, and a negative errno constant
155 * (see smapi_retcode above) upon failure.
157 static int smapi_request(u32 inEBX, u32 inECX,
158 u32 inEDI, u32 inESI,
159 u32 *outEBX, u32 *outECX, u32 *outEDX,
160 u32 *outEDI, u32 *outESI, const char **msg)
166 /* Must use local vars for output regs, due to reg pressure. */
167 u32 tmpEAX, tmpEBX, tmpECX, tmpEDX, tmpEDI, tmpESI;
169 for (retries = 0; retries < SMAPI_MAX_RETRIES; ++retries) {
170 DPRINTK("req_in: BX=%x CX=%x DI=%x SI=%x",
171 inEBX, inECX, inEDI, inESI);
173 /* SMAPI's SMBIOS call and thinkpad_ec end up using use
174 * different interfaces to the same chip, so play it safe. */
175 ret = thinkpad_ec_lock();
179 __asm__ __volatile__(
180 "movl $0x00005380,%%eax\n\t"
185 "xorl %%edx,%%edx\n\t"
187 "out %%al,%%dx\n\t" /* trigger SMI to SMBIOS */
201 :"m"(inEBX), "m"(inECX), "m"(inEDI), "m"(inESI),
203 :"%eax", "%ebx", "%ecx", "%edx", "%edi",
206 thinkpad_ec_invalidate();
207 thinkpad_ec_unlock();
209 /* Don't let the next SMAPI access happen too quickly,
210 * may case problems. (We're hold smapi_mutex). */
213 if (outEBX) *outEBX = tmpEBX;
214 if (outECX) *outECX = tmpECX;
215 if (outEDX) *outEDX = tmpEDX;
216 if (outESI) *outESI = tmpESI;
217 if (outEDI) *outEDI = tmpEDI;
219 /* Look up error code */
220 rc = (tmpEAX>>8)&0xFF;
221 for (i = 0; smapi_retcode[i].rc != SMAPI_RETCODE_EOF &&
222 smapi_retcode[i].rc != rc; ++i) {}
223 ret = smapi_retcode[i].ret;
225 *msg = smapi_retcode[i].msg;
227 DPRINTK("req_out: AX=%x BX=%x CX=%x DX=%x DI=%x SI=%x r=%d",
228 tmpEAX, tmpEBX, tmpECX, tmpEDX, tmpEDI, tmpESI, ret);
230 TPRINTK(KERN_NOTICE, "SMAPI error: %s (func=%x)",
231 smapi_retcode[i].msg, inEBX);
239 /* Convenience wrapper: discard output arguments */
240 static int smapi_write(u32 inEBX, u32 inECX,
241 u32 inEDI, u32 inESI, const char **msg)
243 return smapi_request(inEBX, inECX, inEDI, inESI,
244 NULL, NULL, NULL, NULL, NULL, msg);
248 /*********************************************************************
249 * Specific SMAPI services
250 * All of these functions return 0 upon success, and a negative errno
251 * constant (see smapi_retcode) on failure.
255 THRESH_STOP = 0, /* the code assumes this is 0 for brevity */
258 #define THRESH_NAME(which) ((which == THRESH_START) ? "start" : "stop")
261 * __get_real_thresh - read battery charge start/stop threshold from SMAPI
262 * @bat: battery number (0 or 1)
263 * @which: THRESH_START or THRESH_STOP
264 * @thresh: 1..99, 0=default 1..99, 0=default (pass this as-is to SMAPI)
265 * @outEDI: some additional state that needs to be preserved, meaning unknown
266 * @outESI: some additional state that needs to be preserved, meaning unknown
268 static int __get_real_thresh(int bat, enum thresh_type which, int *thresh,
269 u32 *outEDI, u32 *outESI)
271 u32 ebx = (which == THRESH_START) ? SMAPI_GET_THRESH_START
272 : SMAPI_GET_THRESH_STOP;
273 u32 ecx = (bat+1)<<8;
275 int ret = smapi_request(ebx, ecx, 0, 0, NULL,
276 &ecx, NULL, outEDI, outESI, &msg);
278 TPRINTK(KERN_NOTICE, "cannot get %s_thresh of bat=%d: %s",
279 THRESH_NAME(which), bat, msg);
282 if (!(ecx&0x00000100)) {
283 TPRINTK(KERN_NOTICE, "cannot get %s_thresh of bat=%d: ecx=0%x",
284 THRESH_NAME(which), bat, ecx);
293 * get_real_thresh - read battery charge start/stop threshold from SMAPI
294 * @bat: battery number (0 or 1)
295 * @which: THRESH_START or THRESH_STOP
296 * @thresh: 1..99, 0=default (passes as-is to SMAPI)
298 static int get_real_thresh(int bat, enum thresh_type which, int *thresh)
300 return __get_real_thresh(bat, which, thresh, NULL, NULL);
304 * set_real_thresh - write battery start/top charge threshold to SMAPI
305 * @bat: battery number (0 or 1)
306 * @which: THRESH_START or THRESH_STOP
307 * @thresh: 1..99, 0=default (passes as-is to SMAPI)
309 static int set_real_thresh(int bat, enum thresh_type which, int thresh)
311 u32 ebx = (which == THRESH_START) ? SMAPI_SET_THRESH_START
312 : SMAPI_SET_THRESH_STOP;
313 u32 ecx = ((bat+1)<<8) + thresh;
318 /* verify read before writing */
319 ret = __get_real_thresh(bat, which, NULL, &getDI, &getSI);
323 ret = smapi_write(ebx, ecx, getDI, getSI, &msg);
325 TPRINTK(KERN_NOTICE, "set %s to %d for bat=%d failed: %s",
326 THRESH_NAME(which), thresh, bat, msg);
328 TPRINTK(KERN_INFO, "set %s to %d for bat=%d",
329 THRESH_NAME(which), thresh, bat);
334 * __get_inhibit_charge_minutes - get inhibit charge period from SMAPI
335 * @bat: battery number (0 or 1)
336 * @minutes: period in minutes (1..65535 minutes, 0=disabled)
337 * @outECX: some additional state that needs to be preserved, meaning unknown
338 * Note that @minutes is the originally set value, it does not count down.
340 static int __get_inhibit_charge_minutes(int bat, int *minutes, u32 *outECX)
342 u32 ecx = (bat+1)<<8;
345 int ret = smapi_request(SMAPI_GET_INHIBIT_CHARGE, ecx, 0, 0,
346 NULL, &ecx, NULL, NULL, &esi, &msg);
348 TPRINTK(KERN_NOTICE, "failed for bat=%d: %s", bat, msg);
352 TPRINTK(KERN_NOTICE, "bad ecx=0x%x for bat=%d", ecx, bat);
356 *minutes = (ecx&0x0001)?esi:0;
363 * get_inhibit_charge_minutes - get inhibit charge period from SMAPI
364 * @bat: battery number (0 or 1)
365 * @minutes: period in minutes (1..65535 minutes, 0=disabled)
366 * Note that @minutes is the originally set value, it does not count down.
368 static int get_inhibit_charge_minutes(int bat, int *minutes)
370 return __get_inhibit_charge_minutes(bat, minutes, NULL);
374 * set_inhibit_charge_minutes - write inhibit charge period to SMAPI
375 * @bat: battery number (0 or 1)
376 * @minutes: period in minutes (1..65535 minutes, 0=disabled)
378 static int set_inhibit_charge_minutes(int bat, int minutes)
384 /* verify read before writing */
385 ret = __get_inhibit_charge_minutes(bat, NULL, &ecx);
389 ecx = ((bat+1)<<8) | (ecx&0x00FE) | (minutes > 0 ? 0x0001 : 0x0000);
390 if (minutes > 0xFFFF)
392 ret = smapi_write(SMAPI_SET_INHIBIT_CHARGE, ecx, 0, minutes, &msg);
395 "set to %d failed for bat=%d: %s", minutes, bat, msg);
397 TPRINTK(KERN_INFO, "set to %d for bat=%d\n", minutes, bat);
403 * get_force_discharge - get status of forced discharging from SMAPI
404 * @bat: battery number (0 or 1)
405 * @enabled: 1 if forced discharged is enabled, 0 if not
407 static int get_force_discharge(int bat, int *enabled)
409 u32 ecx = (bat+1)<<8;
411 int ret = smapi_request(SMAPI_GET_FORCE_DISCHARGE, ecx, 0, 0,
412 NULL, &ecx, NULL, NULL, NULL, &msg);
414 TPRINTK(KERN_NOTICE, "failed for bat=%d: %s", bat, msg);
417 *enabled = (!(ecx&0x00000100) && (ecx&0x00000001))?1:0;
422 * set_force_discharge - write status of forced discharging to SMAPI
423 * @bat: battery number (0 or 1)
424 * @enabled: 1 if forced discharged is enabled, 0 if not
426 static int set_force_discharge(int bat, int enabled)
428 u32 ecx = (bat+1)<<8;
430 int ret = smapi_request(SMAPI_GET_FORCE_DISCHARGE, ecx, 0, 0,
431 NULL, &ecx, NULL, NULL, NULL, &msg);
433 TPRINTK(KERN_NOTICE, "get failed for bat=%d: %s", bat, msg);
436 if (ecx&0x00000100) {
437 TPRINTK(KERN_NOTICE, "cannot force discharge bat=%d", bat);
441 ecx = ((bat+1)<<8) | (ecx&0x000000FA) | (enabled?0x00000001:0);
442 ret = smapi_write(SMAPI_SET_FORCE_DISCHARGE, ecx, 0, 0, &msg);
444 TPRINTK(KERN_NOTICE, "set to %d failed for bat=%d: %s",
447 TPRINTK(KERN_INFO, "set to %d for bat=%d", enabled, bat);
452 /*********************************************************************
453 * Wrappers to threshold-related SMAPI functions, which handle default
454 * thresholds and related quirks.
457 /* Minimum, default and minimum difference for battery charging thresholds: */
458 #define MIN_THRESH_DELTA 4 /* Min delta between start and stop thresh */
459 #define MIN_THRESH_START 2
460 #define MAX_THRESH_START (100-MIN_THRESH_DELTA)
461 #define MIN_THRESH_STOP (MIN_THRESH_START + MIN_THRESH_DELTA)
462 #define MAX_THRESH_STOP 100
463 #define DEFAULT_THRESH_START MAX_THRESH_START
464 #define DEFAULT_THRESH_STOP MAX_THRESH_STOP
466 /* The GUI of IBM's Battery Maximizer seems to show a start threshold that
467 * is 1 more than the value we set/get via SMAPI. Since the threshold is
468 * maintained across reboot, this can be confusing. So we kludge our
469 * interface for interoperability: */
472 /* Get charge start/stop threshold (1..100),
473 * substituting default values if needed and applying BATMAT_FIX. */
474 static int get_thresh(int bat, enum thresh_type which, int *thresh)
476 int ret = get_real_thresh(bat, which, thresh);
480 *thresh = (which == THRESH_START) ? DEFAULT_THRESH_START
481 : DEFAULT_THRESH_STOP;
482 else if (which == THRESH_START)
483 *thresh += BATMAX_FIX;
488 /* Set charge start/stop threshold (1..100),
489 * substituting default values if needed and applying BATMAT_FIX. */
490 static int set_thresh(int bat, enum thresh_type which, int thresh)
492 if (which == THRESH_STOP && thresh == DEFAULT_THRESH_STOP)
493 thresh = 0; /* 100 is out of range, but default means 100 */
494 if (which == THRESH_START)
495 thresh -= BATMAX_FIX;
496 return set_real_thresh(bat, which, thresh);
499 /*********************************************************************
500 * ThinkPad embedded controller readout and basic functions
504 * read_tp_ec_row - read data row from the ThinkPad embedded controller
505 * @arg0: EC command code
506 * @bat: battery number, 0 or 1
507 * @j: the byte value to be used for "junk" (unused) input/outputs
508 * @dataval: result vector
510 static int read_tp_ec_row(u8 arg0, int bat, u8 j, u8 *dataval)
513 const struct thinkpad_ec_row args = { .mask = 0xFFFF,
514 .val = {arg0, j,j,j,j,j,j,j,j,j,j,j,j,j,j, (u8)bat} };
515 struct thinkpad_ec_row data = { .mask = 0xFFFF };
517 ret = thinkpad_ec_lock();
520 ret = thinkpad_ec_read_row(&args, &data);
521 thinkpad_ec_unlock();
522 memcpy(dataval, &data.val, TP_CONTROLLER_ROW_LEN);
527 * power_device_present - check for presence of battery or AC power
528 * @bat: 0 for battery 0, 1 for battery 1, otherwise AC power
529 * Returns 1 if present, 0 if not present, negative if error.
531 static int power_device_present(int bat)
533 u8 row[TP_CONTROLLER_ROW_LEN];
535 int ret = read_tp_ec_row(1, bat, 0, row);
539 case 0: test = 0x40; break; /* battery 0 */
540 case 1: test = 0x20; break; /* battery 1 */
541 default: test = 0x80; /* AC power */
543 return (row[0] & test) ? 1 : 0;
547 * bat_has_status - check if battery can report detailed status
548 * @bat: 0 for battery 0, 1 for battery 1
549 * Returns 1 if yes, 0 if no, negative if error.
551 static int bat_has_status(int bat)
553 u8 row[TP_CONTROLLER_ROW_LEN];
554 int ret = read_tp_ec_row(1, bat, 0, row);
557 if ((row[0] & (bat?0x20:0x40)) == 0) /* no battery */
559 if ((row[1] & (0x60)) == 0) /* no status */
565 * get_tp_ec_bat_16 - read a 16-bit value from EC battery status data
566 * @arg0: first argument to EC
567 * @off: offset in row returned from EC
568 * @bat: battery (0 or 1)
569 * @val: the 16-bit value obtained
570 * Returns nonzero on error.
572 static int get_tp_ec_bat_16(u8 arg0, int offset, int bat, u16 *val)
574 u8 row[TP_CONTROLLER_ROW_LEN];
576 if (bat_has_status(bat) != 1)
578 ret = read_tp_ec_row(arg0, bat, 0, row);
581 *val = *(u16 *)(row+offset);
585 /*********************************************************************
586 * sysfs attributes for batteries -
587 * definitions and helper functions
590 /* A custom device attribute struct which holds a battery number */
591 struct bat_device_attribute {
592 struct device_attribute dev_attr;
597 * attr_get_bat - get the battery to which the attribute belongs
599 static int attr_get_bat(struct device_attribute *attr)
601 return container_of(attr, struct bat_device_attribute, dev_attr)->bat;
605 * show_tp_ec_bat_u16 - show an unsigned 16-bit battery attribute
606 * @arg0: specified 1st argument of EC raw to read
607 * @offset: byte offset in EC raw data
608 * @mul: correction factor to multiply by
609 * @na_msg: string to output is value not available (0xFFFFFFFF)
610 * @attr: battery attribute
611 * @buf: output buffer
612 * The 16-bit value is read from the EC, treated as unsigned,
613 * transformed as x->mul*x, and printed to the buffer.
614 * If the value is 0xFFFFFFFF and na_msg!=%NULL, na_msg is printed instead.
616 static ssize_t show_tp_ec_bat_u16(u8 arg0, int offset, int mul,
618 struct device_attribute *attr, char *buf)
621 int ret = get_tp_ec_bat_16(arg0, offset, attr_get_bat(attr), &val);
624 if (na_msg && val == 0xFFFF)
625 return sprintf(buf, "%s\n", na_msg);
627 return sprintf(buf, "%u\n", mul*(unsigned int)val);
631 * show_tp_ec_bat_s16 - show an signed 16-bit battery attribute
632 * @arg0: specified 1st argument of EC raw to read
633 * @offset: byte offset in EC raw data
634 * @mul: correction factor to multiply by
635 * @add: correction term to add after multiplication
636 * @attr: battery attribute
637 * @buf: output buffer
638 * The 16-bit value is read from the EC, treated as signed,
639 * transformed as x->mul*x+add, and printed to the buffer.
641 static ssize_t show_tp_ec_bat_s16(u8 arg0, int offset, int mul, int add,
642 struct device_attribute *attr, char *buf)
645 int ret = get_tp_ec_bat_16(arg0, offset, attr_get_bat(attr), &val);
648 return sprintf(buf, "%d\n", mul*(s16)val+add);
652 * show_tp_ec_bat_str - show a string from EC battery status data
653 * @arg0: specified 1st argument of EC raw to read
654 * @offset: byte offset in EC raw data
655 * @maxlen: maximum string length
656 * @attr: battery attribute
657 * @buf: output buffer
659 static ssize_t show_tp_ec_bat_str(u8 arg0, int offset, int maxlen,
660 struct device_attribute *attr, char *buf)
662 int bat = attr_get_bat(attr);
663 u8 row[TP_CONTROLLER_ROW_LEN];
665 if (bat_has_status(bat) != 1)
667 ret = read_tp_ec_row(arg0, bat, 0, row);
670 strncpy(buf, (char *)row+offset, maxlen);
677 * show_tp_ec_bat_power - show a power readout from EC battery status data
678 * @arg0: specified 1st argument of EC raw to read
679 * @offV: byte offset of voltage in EC raw data
680 * @offI: byte offset of current in EC raw data
681 * @attr: battery attribute
682 * @buf: output buffer
683 * Computes the power as current*voltage from the two given readout offsets.
685 static ssize_t show_tp_ec_bat_power(u8 arg0, int offV, int offI,
686 struct device_attribute *attr, char *buf)
688 u8 row[TP_CONTROLLER_ROW_LEN];
689 int milliamp, millivolt, ret;
690 int bat = attr_get_bat(attr);
691 if (bat_has_status(bat) != 1)
693 ret = read_tp_ec_row(1, bat, 0, row);
696 millivolt = *(u16 *)(row+offV);
697 milliamp = *(s16 *)(row+offI);
698 return sprintf(buf, "%d\n", milliamp*millivolt/1000); /* units: mW */
702 * show_tp_ec_bat_date - decode and show a date from EC battery status data
703 * @arg0: specified 1st argument of EC raw to read
704 * @offset: byte offset in EC raw data
705 * @attr: battery attribute
706 * @buf: output buffer
708 static ssize_t show_tp_ec_bat_date(u8 arg0, int offset,
709 struct device_attribute *attr, char *buf)
711 u8 row[TP_CONTROLLER_ROW_LEN];
714 int day, month, year;
715 int bat = attr_get_bat(attr);
716 if (bat_has_status(bat) != 1)
718 ret = read_tp_ec_row(arg0, bat, 0, row);
722 /* Decode bit-packed: v = day | (month<<5) | ((year-1980)<<9) */
723 v = *(u16 *)(row+offset);
725 month = (v >> 5) & 0xF;
726 year = (v >> 9) + 1980;
728 return sprintf(buf, "%04d-%02d-%02d\n", year, month, day);
732 /*********************************************************************
733 * sysfs attribute I/O for batteries -
734 * the actual attribute show/store functions
737 static ssize_t show_battery_start_charge_thresh(struct device *dev,
738 struct device_attribute *attr, char *buf)
741 int bat = attr_get_bat(attr);
742 int ret = get_thresh(bat, THRESH_START, &thresh);
745 return sprintf(buf, "%d\n", thresh); /* units: percent */
748 static ssize_t show_battery_stop_charge_thresh(struct device *dev,
749 struct device_attribute *attr, char *buf)
752 int bat = attr_get_bat(attr);
753 int ret = get_thresh(bat, THRESH_STOP, &thresh);
756 return sprintf(buf, "%d\n", thresh); /* units: percent */
760 * store_battery_start_charge_thresh - store battery_start_charge_thresh attr
761 * Since this is a kernel<->user interface, we ensure a valid state for
762 * the hardware. We do this by clamping the requested threshold to the
763 * valid range and, if necessary, moving the other threshold so that
764 * it's MIN_THRESH_DELTA away from this one.
766 static ssize_t store_battery_start_charge_thresh(struct device *dev,
767 struct device_attribute *attr, const char *buf, size_t count)
769 int thresh, other_thresh, ret;
770 int bat = attr_get_bat(attr);
772 if (sscanf(buf, "%d", &thresh) != 1 || thresh < 1 || thresh > 100)
775 if (thresh < MIN_THRESH_START) /* clamp up to MIN_THRESH_START */
776 thresh = MIN_THRESH_START;
777 if (thresh > MAX_THRESH_START) /* clamp down to MAX_THRESH_START */
778 thresh = MAX_THRESH_START;
781 ret = get_thresh(bat, THRESH_STOP, &other_thresh);
782 if (ret != -EOPNOTSUPP && ret != -ENXIO) {
783 if (ret) /* other threshold is set? */
785 ret = get_real_thresh(bat, THRESH_START, NULL);
786 if (ret) /* this threshold is set? */
788 if (other_thresh < thresh+MIN_THRESH_DELTA) {
789 /* move other thresh to keep it above this one */
790 ret = set_thresh(bat, THRESH_STOP,
791 thresh+MIN_THRESH_DELTA);
796 ret = set_thresh(bat, THRESH_START, thresh);
804 * store_battery_stop_charge_thresh - store battery_stop_charge_thresh attr
805 * Since this is a kernel<->user interface, we ensure a valid state for
806 * the hardware. We do this by clamping the requested threshold to the
807 * valid range and, if necessary, moving the other threshold so that
808 * it's MIN_THRESH_DELTA away from this one.
810 static ssize_t store_battery_stop_charge_thresh(struct device *dev,
811 struct device_attribute *attr, const char *buf, size_t count)
813 int thresh, other_thresh, ret;
814 int bat = attr_get_bat(attr);
816 if (sscanf(buf, "%d", &thresh) != 1 || thresh < 1 || thresh > 100)
819 if (thresh < MIN_THRESH_STOP) /* clamp up to MIN_THRESH_STOP */
820 thresh = MIN_THRESH_STOP;
823 ret = get_thresh(bat, THRESH_START, &other_thresh);
824 if (ret != -EOPNOTSUPP && ret != -ENXIO) { /* other threshold exists? */
827 /* this threshold exists? */
828 ret = get_real_thresh(bat, THRESH_STOP, NULL);
831 if (other_thresh >= thresh-MIN_THRESH_DELTA) {
832 /* move other thresh to be below this one */
833 ret = set_thresh(bat, THRESH_START,
834 thresh-MIN_THRESH_DELTA);
839 ret = set_thresh(bat, THRESH_STOP, thresh);
845 static ssize_t show_battery_inhibit_charge_minutes(struct device *dev,
846 struct device_attribute *attr, char *buf)
849 int bat = attr_get_bat(attr);
850 int ret = get_inhibit_charge_minutes(bat, &minutes);
853 return sprintf(buf, "%d\n", minutes); /* units: minutes */
856 static ssize_t store_battery_inhibit_charge_minutes(struct device *dev,
857 struct device_attribute *attr,
858 const char *buf, size_t count)
862 int bat = attr_get_bat(attr);
863 if (sscanf(buf, "%d", &minutes) != 1 || minutes < 0) {
864 TPRINTK(KERN_ERR, "inhibit_charge_minutes: "
865 "must be a non-negative integer");
868 ret = set_inhibit_charge_minutes(bat, minutes);
874 static ssize_t show_battery_force_discharge(struct device *dev,
875 struct device_attribute *attr, char *buf)
878 int bat = attr_get_bat(attr);
879 int ret = get_force_discharge(bat, &enabled);
882 return sprintf(buf, "%d\n", enabled); /* type: boolean */
885 static ssize_t store_battery_force_discharge(struct device *dev,
886 struct device_attribute *attr, const char *buf, size_t count)
890 int bat = attr_get_bat(attr);
891 if (sscanf(buf, "%d", &enabled) != 1 || enabled < 0 || enabled > 1)
893 ret = set_force_discharge(bat, enabled);
899 static ssize_t show_battery_installed(
900 struct device *dev, struct device_attribute *attr, char *buf)
902 int bat = attr_get_bat(attr);
903 int ret = power_device_present(bat);
906 return sprintf(buf, "%d\n", ret); /* type: boolean */
909 static ssize_t show_battery_state(
910 struct device *dev, struct device_attribute *attr, char *buf)
912 u8 row[TP_CONTROLLER_ROW_LEN];
915 int bat = attr_get_bat(attr);
916 if (bat_has_status(bat) != 1)
917 return sprintf(buf, "none\n");
918 ret = read_tp_ec_row(1, bat, 0, row);
921 switch (row[1] & 0xf0) {
922 case 0xc0: txt = "idle"; break;
923 case 0xd0: txt = "discharging"; break;
924 case 0xe0: txt = "charging"; break;
925 default: return sprintf(buf, "unknown (0x%x)\n", row[1]);
927 return sprintf(buf, "%s\n", txt); /* type: string from fixed set */
930 static ssize_t show_battery_manufacturer(
931 struct device *dev, struct device_attribute *attr, char *buf)
933 /* type: string. SBS spec v1.1 p34: ManufacturerName() */
934 return show_tp_ec_bat_str(4, 2, TP_CONTROLLER_ROW_LEN-2, attr, buf);
937 static ssize_t show_battery_model(
938 struct device *dev, struct device_attribute *attr, char *buf)
940 /* type: string. SBS spec v1.1 p34: DeviceName() */
941 return show_tp_ec_bat_str(5, 2, TP_CONTROLLER_ROW_LEN-2, attr, buf);
944 static ssize_t show_battery_barcoding(
945 struct device *dev, struct device_attribute *attr, char *buf)
948 return show_tp_ec_bat_str(7, 2, TP_CONTROLLER_ROW_LEN-2, attr, buf);
951 static ssize_t show_battery_chemistry(
952 struct device *dev, struct device_attribute *attr, char *buf)
954 /* type: string. SBS spec v1.1 p34-35: DeviceChemistry() */
955 return show_tp_ec_bat_str(6, 2, 5, attr, buf);
958 static ssize_t show_battery_voltage(
959 struct device *dev, struct device_attribute *attr, char *buf)
961 /* units: mV. SBS spec v1.1 p24: Voltage() */
962 return show_tp_ec_bat_u16(1, 6, 1, NULL, attr, buf);
965 static ssize_t show_battery_design_voltage(
966 struct device *dev, struct device_attribute *attr, char *buf)
968 /* units: mV. SBS spec v1.1 p32: DesignVoltage() */
969 return show_tp_ec_bat_u16(3, 4, 1, NULL, attr, buf);
972 static ssize_t show_battery_charging_max_voltage(
973 struct device *dev, struct device_attribute *attr, char *buf)
975 /* units: mV. SBS spec v1.1 p37,39: ChargingVoltage() */
976 return show_tp_ec_bat_u16(9, 8, 1, NULL, attr, buf);
979 static ssize_t show_battery_group0_voltage(
980 struct device *dev, struct device_attribute *attr, char *buf)
983 return show_tp_ec_bat_u16(0xA, 12, 1, NULL, attr, buf);
986 static ssize_t show_battery_group1_voltage(
987 struct device *dev, struct device_attribute *attr, char *buf)
990 return show_tp_ec_bat_u16(0xA, 10, 1, NULL, attr, buf);
993 static ssize_t show_battery_group2_voltage(
994 struct device *dev, struct device_attribute *attr, char *buf)
997 return show_tp_ec_bat_u16(0xA, 8, 1, NULL, attr, buf);
1000 static ssize_t show_battery_group3_voltage(
1001 struct device *dev, struct device_attribute *attr, char *buf)
1004 return show_tp_ec_bat_u16(0xA, 6, 1, NULL, attr, buf);
1007 static ssize_t show_battery_current_now(
1008 struct device *dev, struct device_attribute *attr, char *buf)
1010 /* units: mA. SBS spec v1.1 p24: Current() */
1011 return show_tp_ec_bat_s16(1, 8, 1, 0, attr, buf);
1014 static ssize_t show_battery_current_avg(
1015 struct device *dev, struct device_attribute *attr, char *buf)
1017 /* units: mA. SBS spec v1.1 p24: AverageCurrent() */
1018 return show_tp_ec_bat_s16(1, 10, 1, 0, attr, buf);
1021 static ssize_t show_battery_charging_max_current(
1022 struct device *dev, struct device_attribute *attr, char *buf)
1024 /* units: mA. SBS spec v1.1 p36,38: ChargingCurrent() */
1025 return show_tp_ec_bat_s16(9, 6, 1, 0, attr, buf);
1028 static ssize_t show_battery_power_now(
1029 struct device *dev, struct device_attribute *attr, char *buf)
1031 /* units: mW. SBS spec v1.1: Voltage()*Current() */
1032 return show_tp_ec_bat_power(1, 6, 8, attr, buf);
1035 static ssize_t show_battery_power_avg(
1036 struct device *dev, struct device_attribute *attr, char *buf)
1038 /* units: mW. SBS spec v1.1: Voltage()*AverageCurrent() */
1039 return show_tp_ec_bat_power(1, 6, 10, attr, buf);
1042 static ssize_t show_battery_remaining_percent(
1043 struct device *dev, struct device_attribute *attr, char *buf)
1045 /* units: percent. SBS spec v1.1 p25: RelativeStateOfCharge() */
1046 return show_tp_ec_bat_u16(1, 12, 1, NULL, attr, buf);
1049 static ssize_t show_battery_remaining_percent_error(
1050 struct device *dev, struct device_attribute *attr, char *buf)
1052 /* units: percent. SBS spec v1.1 p25: MaxError() */
1053 return show_tp_ec_bat_u16(9, 4, 1, NULL, attr, buf);
1056 static ssize_t show_battery_remaining_charging_time(
1057 struct device *dev, struct device_attribute *attr, char *buf)
1059 /* units: minutes. SBS spec v1.1 p27: AverageTimeToFull() */
1060 return show_tp_ec_bat_u16(2, 8, 1, "not_charging", attr, buf);
1063 static ssize_t show_battery_remaining_running_time(
1064 struct device *dev, struct device_attribute *attr, char *buf)
1066 /* units: minutes. SBS spec v1.1 p27: RunTimeToEmpty() */
1067 return show_tp_ec_bat_u16(2, 6, 1, "not_discharging", attr, buf);
1070 static ssize_t show_battery_remaining_running_time_now(
1071 struct device *dev, struct device_attribute *attr, char *buf)
1073 /* units: minutes. SBS spec v1.1 p27: RunTimeToEmpty() */
1074 return show_tp_ec_bat_u16(2, 4, 1, "not_discharging", attr, buf);
1077 static ssize_t show_battery_remaining_capacity(
1078 struct device *dev, struct device_attribute *attr, char *buf)
1080 /* units: mWh. SBS spec v1.1 p26. */
1081 return show_tp_ec_bat_u16(1, 14, 10, "", attr, buf);
1084 static ssize_t show_battery_last_full_capacity(
1085 struct device *dev, struct device_attribute *attr, char *buf)
1087 /* units: mWh. SBS spec v1.1 p26: FullChargeCapacity() */
1088 return show_tp_ec_bat_u16(2, 2, 10, "", attr, buf);
1091 static ssize_t show_battery_design_capacity(
1092 struct device *dev, struct device_attribute *attr, char *buf)
1094 /* units: mWh. SBS spec v1.1 p32: DesignCapacity() */
1095 return show_tp_ec_bat_u16(3, 2, 10, "", attr, buf);
1098 static ssize_t show_battery_cycle_count(
1099 struct device *dev, struct device_attribute *attr, char *buf)
1101 /* units: ordinal. SBS spec v1.1 p32: CycleCount() */
1102 return show_tp_ec_bat_u16(2, 12, 1, "", attr, buf);
1105 static ssize_t show_battery_temperature(
1106 struct device *dev, struct device_attribute *attr, char *buf)
1108 /* units: millicelsius. SBS spec v1.1: Temperature()*10 */
1109 return show_tp_ec_bat_s16(1, 4, 100, -273100, attr, buf);
1112 static ssize_t show_battery_serial(
1113 struct device *dev, struct device_attribute *attr, char *buf)
1115 /* type: int. SBS spec v1.1 p34: SerialNumber() */
1116 return show_tp_ec_bat_u16(3, 10, 1, "", attr, buf);
1119 static ssize_t show_battery_manufacture_date(
1120 struct device *dev, struct device_attribute *attr, char *buf)
1122 /* type: YYYY-MM-DD. SBS spec v1.1 p34: ManufactureDate() */
1123 return show_tp_ec_bat_date(3, 8, attr, buf);
1126 static ssize_t show_battery_first_use_date(
1127 struct device *dev, struct device_attribute *attr, char *buf)
1129 /* type: YYYY-MM-DD */
1130 return show_tp_ec_bat_date(8, 2, attr, buf);
1134 * show_battery_dump - show the battery's dump attribute
1135 * The dump attribute gives a hex dump of all EC readouts related to a
1136 * battery. Some of the enumerated values don't really exist (i.e., the
1137 * EC function just leaves them untouched); we use a kludge to detect and
1140 #define MIN_DUMP_ARG0 0x00
1141 #define MAX_DUMP_ARG0 0x0a /* 0x0b is useful too but hangs old EC firmware */
1142 static ssize_t show_battery_dump(
1143 struct device *dev, struct device_attribute *attr, char *buf)
1147 int bat = attr_get_bat(attr);
1148 u8 arg0; /* first argument to EC */
1149 u8 rowa[TP_CONTROLLER_ROW_LEN],
1150 rowb[TP_CONTROLLER_ROW_LEN];
1151 const u8 junka = 0xAA,
1152 junkb = 0x55; /* junk values for testing changes */
1155 for (arg0 = MIN_DUMP_ARG0; arg0 <= MAX_DUMP_ARG0; ++arg0) {
1156 if ((p-buf) > PAGE_SIZE-TP_CONTROLLER_ROW_LEN*5)
1157 return -ENOMEM; /* don't overflow sysfs buf */
1158 /* Read raw twice with different junk values,
1159 * to detect unused output bytes which are left unchaged: */
1160 ret = read_tp_ec_row(arg0, bat, junka, rowa);
1163 ret = read_tp_ec_row(arg0, bat, junkb, rowb);
1166 for (i = 0; i < TP_CONTROLLER_ROW_LEN; i++) {
1167 if (rowa[i] == junka && rowb[i] == junkb)
1168 p += sprintf(p, "-- "); /* unused by EC */
1170 p += sprintf(p, "%02x ", rowa[i]);
1172 p += sprintf(p, "\n");
1178 /*********************************************************************
1179 * sysfs attribute I/O, other than batteries
1182 static ssize_t show_ac_connected(
1183 struct device *dev, struct device_attribute *attr, char *buf)
1185 int ret = power_device_present(0xFF);
1188 return sprintf(buf, "%d\n", ret); /* type: boolean */
1191 /*********************************************************************
1192 * The the "smapi_request" sysfs attribute executes a raw SMAPI call.
1193 * You write to make a request and read to get the result. The state
1194 * is saved globally rather than per fd (sysfs limitation), so
1195 * simultaenous requests may get each other's results! So this is for
1196 * development and debugging only.
1198 #define MAX_SMAPI_ATTR_ANSWER_LEN 128
1199 static char smapi_attr_answer[MAX_SMAPI_ATTR_ANSWER_LEN] = "";
1201 static ssize_t show_smapi_request(struct device *dev,
1202 struct device_attribute *attr, char *buf)
1204 int ret = snprintf(buf, PAGE_SIZE, "%s", smapi_attr_answer);
1205 smapi_attr_answer[0] = '\0';
1209 static ssize_t store_smapi_request(struct device *dev,
1210 struct device_attribute *attr,
1211 const char *buf, size_t count)
1213 unsigned int inEBX, inECX, inEDI, inESI;
1214 u32 outEBX, outECX, outEDX, outEDI, outESI;
1217 if (sscanf(buf, "%x %x %x %x", &inEBX, &inECX, &inEDI, &inESI) != 4) {
1218 smapi_attr_answer[0] = '\0';
1221 ret = smapi_request(
1222 inEBX, inECX, inEDI, inESI,
1223 &outEBX, &outECX, &outEDX, &outEDI, &outESI, &msg);
1224 snprintf(smapi_attr_answer, MAX_SMAPI_ATTR_ANSWER_LEN,
1225 "%x %x %x %x %x %d '%s'\n",
1226 (unsigned int)outEBX, (unsigned int)outECX,
1227 (unsigned int)outEDX, (unsigned int)outEDI,
1228 (unsigned int)outESI, ret, msg);
1235 /*********************************************************************
1236 * Power management: the embedded controller forgets the battery
1237 * thresholds when the system is suspended to disk and unplugged from
1238 * AC and battery, so we restore it upon resume.
1241 static int saved_threshs[4] = {-1, -1, -1, -1}; /* -1 = don't know */
1243 static int tp_suspend(struct platform_device *dev, pm_message_t state)
1245 int restore = (state.event == PM_EVENT_HIBERNATE ||
1246 state.event == PM_EVENT_FREEZE);
1247 if (!restore || get_real_thresh(0, THRESH_STOP , &saved_threshs[0]))
1248 saved_threshs[0] = -1;
1249 if (!restore || get_real_thresh(0, THRESH_START, &saved_threshs[1]))
1250 saved_threshs[1] = -1;
1251 if (!restore || get_real_thresh(1, THRESH_STOP , &saved_threshs[2]))
1252 saved_threshs[2] = -1;
1253 if (!restore || get_real_thresh(1, THRESH_START, &saved_threshs[3]))
1254 saved_threshs[3] = -1;
1255 DPRINTK("suspend saved: %d %d %d %d", saved_threshs[0],
1256 saved_threshs[1], saved_threshs[2], saved_threshs[3]);
1260 static int tp_resume(struct platform_device *dev)
1262 DPRINTK("resume restoring: %d %d %d %d", saved_threshs[0],
1263 saved_threshs[1], saved_threshs[2], saved_threshs[3]);
1264 if (saved_threshs[0] >= 0)
1265 set_real_thresh(0, THRESH_STOP , saved_threshs[0]);
1266 if (saved_threshs[1] >= 0)
1267 set_real_thresh(0, THRESH_START, saved_threshs[1]);
1268 if (saved_threshs[2] >= 0)
1269 set_real_thresh(1, THRESH_STOP , saved_threshs[2]);
1270 if (saved_threshs[3] >= 0)
1271 set_real_thresh(1, THRESH_START, saved_threshs[3]);
1276 /*********************************************************************
1280 static struct platform_driver tp_driver = {
1281 .suspend = tp_suspend,
1282 .resume = tp_resume,
1285 .owner = THIS_MODULE
1290 /*********************************************************************
1291 * Sysfs device model
1294 /* Attributes in /sys/devices/platform/smapi/ */
1296 static DEVICE_ATTR(ac_connected, 0444, show_ac_connected, NULL);
1297 static DEVICE_ATTR(smapi_request, 0600, show_smapi_request,
1298 store_smapi_request);
1300 static struct attribute *tp_root_attributes[] = {
1301 &dev_attr_ac_connected.attr,
1302 &dev_attr_smapi_request.attr,
1305 static struct attribute_group tp_root_attribute_group = {
1306 .attrs = tp_root_attributes
1309 /* Attributes under /sys/devices/platform/smapi/BAT{0,1}/ :
1310 * Every attribute needs to be defined (i.e., statically allocated) for
1311 * each battery, and then referenced in the attribute list of each battery.
1312 * We use preprocessor voodoo to avoid duplicating the list of attributes 4
1313 * times. The preprocessor output is just normal sysfs attributes code.
1317 * FOREACH_BAT_ATTR - invoke the given macros on all our battery attributes
1318 * @_BAT: battery number (0 or 1)
1319 * @_ATTR_RW: macro to invoke for each read/write attribute
1320 * @_ATTR_R: macro to invoke for each read-only attribute
1322 #define FOREACH_BAT_ATTR(_BAT, _ATTR_RW, _ATTR_R) \
1323 _ATTR_RW(_BAT, start_charge_thresh) \
1324 _ATTR_RW(_BAT, stop_charge_thresh) \
1325 _ATTR_RW(_BAT, inhibit_charge_minutes) \
1326 _ATTR_RW(_BAT, force_discharge) \
1327 _ATTR_R(_BAT, installed) \
1328 _ATTR_R(_BAT, state) \
1329 _ATTR_R(_BAT, manufacturer) \
1330 _ATTR_R(_BAT, model) \
1331 _ATTR_R(_BAT, barcoding) \
1332 _ATTR_R(_BAT, chemistry) \
1333 _ATTR_R(_BAT, voltage) \
1334 _ATTR_R(_BAT, group0_voltage) \
1335 _ATTR_R(_BAT, group1_voltage) \
1336 _ATTR_R(_BAT, group2_voltage) \
1337 _ATTR_R(_BAT, group3_voltage) \
1338 _ATTR_R(_BAT, current_now) \
1339 _ATTR_R(_BAT, current_avg) \
1340 _ATTR_R(_BAT, charging_max_current) \
1341 _ATTR_R(_BAT, power_now) \
1342 _ATTR_R(_BAT, power_avg) \
1343 _ATTR_R(_BAT, remaining_percent) \
1344 _ATTR_R(_BAT, remaining_percent_error) \
1345 _ATTR_R(_BAT, remaining_charging_time) \
1346 _ATTR_R(_BAT, remaining_running_time) \
1347 _ATTR_R(_BAT, remaining_running_time_now) \
1348 _ATTR_R(_BAT, remaining_capacity) \
1349 _ATTR_R(_BAT, last_full_capacity) \
1350 _ATTR_R(_BAT, design_voltage) \
1351 _ATTR_R(_BAT, charging_max_voltage) \
1352 _ATTR_R(_BAT, design_capacity) \
1353 _ATTR_R(_BAT, cycle_count) \
1354 _ATTR_R(_BAT, temperature) \
1355 _ATTR_R(_BAT, serial) \
1356 _ATTR_R(_BAT, manufacture_date) \
1357 _ATTR_R(_BAT, first_use_date) \
1360 /* Define several macros we will feed into FOREACH_BAT_ATTR: */
1362 #define DEFINE_BAT_ATTR_RW(_BAT,_NAME) \
1363 static struct bat_device_attribute dev_attr_##_NAME##_##_BAT = { \
1364 .dev_attr = __ATTR(_NAME, 0644, show_battery_##_NAME, \
1365 store_battery_##_NAME), \
1369 #define DEFINE_BAT_ATTR_R(_BAT,_NAME) \
1370 static struct bat_device_attribute dev_attr_##_NAME##_##_BAT = { \
1371 .dev_attr = __ATTR(_NAME, 0644, show_battery_##_NAME, 0), \
1375 #define REF_BAT_ATTR(_BAT,_NAME) \
1376 &dev_attr_##_NAME##_##_BAT.dev_attr.attr,
1378 /* This provide all attributes for one battery: */
1380 #define PROVIDE_BAT_ATTRS(_BAT) \
1381 FOREACH_BAT_ATTR(_BAT, DEFINE_BAT_ATTR_RW, DEFINE_BAT_ATTR_R) \
1382 static struct attribute *tp_bat##_BAT##_attributes[] = { \
1383 FOREACH_BAT_ATTR(_BAT, REF_BAT_ATTR, REF_BAT_ATTR) \
1386 static struct attribute_group tp_bat##_BAT##_attribute_group = { \
1387 .name = "BAT" #_BAT, \
1388 .attrs = tp_bat##_BAT##_attributes \
1391 /* Finally genereate the attributes: */
1393 PROVIDE_BAT_ATTRS(0)
1394 PROVIDE_BAT_ATTRS(1)
1396 /* List of attribute groups */
1398 static struct attribute_group *attr_groups[] = {
1399 &tp_root_attribute_group,
1400 &tp_bat0_attribute_group,
1401 &tp_bat1_attribute_group,
1406 /*********************************************************************
1410 static struct attribute_group **next_attr_group; /* next to register */
1412 static int __init tp_init(void)
1415 printk(KERN_INFO "tp_smapi " TP_VERSION " loading...\n");
1417 ret = find_smapi_port();
1423 if (!request_region(smapi_port, 1, "smapi")) {
1424 printk(KERN_ERR "tp_smapi cannot claim port 0x%x\n",
1430 if (!request_region(SMAPI_PORT2, 1, "smapi")) {
1431 printk(KERN_ERR "tp_smapi cannot claim port 0x%x\n",
1437 ret = platform_driver_register(&tp_driver);
1441 pdev = platform_device_alloc("smapi", -1);
1447 ret = platform_device_add(pdev);
1449 goto err_device_free;
1451 for (next_attr_group = attr_groups; *next_attr_group;
1452 ++next_attr_group) {
1453 ret = sysfs_create_group(&pdev->dev.kobj, *next_attr_group);
1458 printk(KERN_INFO "tp_smapi successfully loaded (smapi_port=0x%x).\n",
1463 while (--next_attr_group >= attr_groups)
1464 sysfs_remove_group(&pdev->dev.kobj, *next_attr_group);
1465 platform_device_unregister(pdev);
1467 platform_device_put(pdev);
1469 platform_driver_unregister(&tp_driver);
1471 release_region(SMAPI_PORT2, 1);
1473 release_region(smapi_port, 1);
1475 printk(KERN_ERR "tp_smapi init failed (ret=%d)!\n", ret);
1479 static void __exit tp_exit(void)
1481 while (next_attr_group && --next_attr_group >= attr_groups)
1482 sysfs_remove_group(&pdev->dev.kobj, *next_attr_group);
1483 platform_device_unregister(pdev);
1484 platform_driver_unregister(&tp_driver);
1485 release_region(SMAPI_PORT2, 1);
1487 release_region(smapi_port, 1);
1489 printk(KERN_INFO "tp_smapi unloaded.\n");
1492 module_init(tp_init);
1493 module_exit(tp_exit);