smsc47m1.c (fde0950903ce8cc38a91dd095280decceda2ff82) smsc47m1.c (2d8672c5a6ba0d3f1d8d3ad61ef67868941364f0)
1/*
2 smsc47m1.c - Part of lm_sensors, Linux kernel modules
3 for hardware monitoring
4
5 Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x and LPC47M14x
6 Super-I/O chips.
7
8 Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>

--- 23 unchanged lines hidden (view full) ---

32#include <linux/i2c.h>
33#include <linux/i2c-isa.h>
34#include <linux/i2c-sensor.h>
35#include <linux/hwmon.h>
36#include <linux/err.h>
37#include <linux/init.h>
38#include <asm/io.h>
39
1/*
2 smsc47m1.c - Part of lm_sensors, Linux kernel modules
3 for hardware monitoring
4
5 Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x and LPC47M14x
6 Super-I/O chips.
7
8 Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>

--- 23 unchanged lines hidden (view full) ---

32#include <linux/i2c.h>
33#include <linux/i2c-isa.h>
34#include <linux/i2c-sensor.h>
35#include <linux/hwmon.h>
36#include <linux/err.h>
37#include <linux/init.h>
38#include <asm/io.h>
39
40static unsigned short normal_i2c[] = { I2C_CLIENT_END };
41/* Address is autodetected, there is no default value */
40/* Address is autodetected, there is no default value */
42static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
43static struct i2c_force_data forces[] = {{NULL}};
41static unsigned short address;
44
42
45enum chips { any_chip, smsc47m1 };
46static struct i2c_address_data addr_data = {
47 .normal_i2c = normal_i2c,
48 .normal_isa = normal_isa,
49 .forces = forces,
50};
51
52/* Super-I/0 registers and commands */
53
54#define REG 0x2e /* The register to read/write */
55#define VAL 0x2f /* The value to read/write */
56
57static inline void
58superio_outb(int reg, int val)
59{

--- 60 unchanged lines hidden (view full) ---

120 u8 fan[2]; /* Register value */
121 u8 fan_preload[2]; /* Register value */
122 u8 fan_div[2]; /* Register encoding, shifted right */
123 u8 alarms; /* Register encoding */
124 u8 pwm[2]; /* Register value (bit 7 is enable) */
125};
126
127
43/* Super-I/0 registers and commands */
44
45#define REG 0x2e /* The register to read/write */
46#define VAL 0x2f /* The value to read/write */
47
48static inline void
49superio_outb(int reg, int val)
50{

--- 60 unchanged lines hidden (view full) ---

111 u8 fan[2]; /* Register value */
112 u8 fan_preload[2]; /* Register value */
113 u8 fan_div[2]; /* Register encoding, shifted right */
114 u8 alarms; /* Register encoding */
115 u8 pwm[2]; /* Register value (bit 7 is enable) */
116};
117
118
128static int smsc47m1_attach_adapter(struct i2c_adapter *adapter);
129static int smsc47m1_find(int *address);
130static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind);
119static int smsc47m1_detect(struct i2c_adapter *adapter);
131static int smsc47m1_detach_client(struct i2c_client *client);
132
133static int smsc47m1_read_value(struct i2c_client *client, u8 reg);
134static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value);
135
136static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
137 int init);
138
139
140static struct i2c_driver smsc47m1_driver = {
141 .owner = THIS_MODULE,
142 .name = "smsc47m1",
120static int smsc47m1_detach_client(struct i2c_client *client);
121
122static int smsc47m1_read_value(struct i2c_client *client, u8 reg);
123static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value);
124
125static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
126 int init);
127
128
129static struct i2c_driver smsc47m1_driver = {
130 .owner = THIS_MODULE,
131 .name = "smsc47m1",
143 .id = I2C_DRIVERID_SMSC47M1,
144 .flags = I2C_DF_NOTIFY,
145 .attach_adapter = smsc47m1_attach_adapter,
132 .attach_adapter = smsc47m1_detect,
146 .detach_client = smsc47m1_detach_client,
147};
148
149/* nr is 0 or 1 in the callback functions below */
150
151static ssize_t get_fan(struct device *dev, char *buf, int nr)
152{
153 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);

--- 199 unchanged lines hidden (view full) ---

353static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \
354 get_pwm##offset##_en, set_pwm##offset##_en);
355
356fan_present(1);
357fan_present(2);
358
359static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL);
360
133 .detach_client = smsc47m1_detach_client,
134};
135
136/* nr is 0 or 1 in the callback functions below */
137
138static ssize_t get_fan(struct device *dev, char *buf, int nr)
139{
140 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);

--- 199 unchanged lines hidden (view full) ---

340static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \
341 get_pwm##offset##_en, set_pwm##offset##_en);
342
343fan_present(1);
344fan_present(2);
345
346static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL);
347
361static int smsc47m1_attach_adapter(struct i2c_adapter *adapter)
348static int smsc47m1_find(unsigned short *addr)
362{
349{
363 if (!(adapter->class & I2C_CLASS_HWMON))
364 return 0;
365 return i2c_detect(adapter, &addr_data, smsc47m1_detect);
366}
367
368static int smsc47m1_find(int *address)
369{
370 u8 val;
371
372 superio_enter();
373 val = superio_inb(SUPERIO_REG_DEVID);
374
375 /*
376 * SMSC LPC47M10x/LPC47M13x (device id 0x59), LPC47M14x (device id
377 * 0x5F) and LPC47B27x (device id 0x51) have fan control.

--- 9 unchanged lines hidden (view full) ---

387 else if (val == 0x60)
388 printk(KERN_INFO "smsc47m1: Found SMSC LPC47M15x/LPC47M192\n");
389 else {
390 superio_exit();
391 return -ENODEV;
392 }
393
394 superio_select();
350 u8 val;
351
352 superio_enter();
353 val = superio_inb(SUPERIO_REG_DEVID);
354
355 /*
356 * SMSC LPC47M10x/LPC47M13x (device id 0x59), LPC47M14x (device id
357 * 0x5F) and LPC47B27x (device id 0x51) have fan control.

--- 9 unchanged lines hidden (view full) ---

367 else if (val == 0x60)
368 printk(KERN_INFO "smsc47m1: Found SMSC LPC47M15x/LPC47M192\n");
369 else {
370 superio_exit();
371 return -ENODEV;
372 }
373
374 superio_select();
395 *address = (superio_inb(SUPERIO_REG_BASE) << 8)
396 | superio_inb(SUPERIO_REG_BASE + 1);
375 *addr = (superio_inb(SUPERIO_REG_BASE) << 8)
376 | superio_inb(SUPERIO_REG_BASE + 1);
397 val = superio_inb(SUPERIO_REG_ACT);
377 val = superio_inb(SUPERIO_REG_ACT);
398 if (*address == 0 || (val & 0x01) == 0) {
378 if (*addr == 0 || (val & 0x01) == 0) {
399 printk(KERN_INFO "smsc47m1: Device is disabled, will not use\n");
400 superio_exit();
401 return -ENODEV;
402 }
403
404 superio_exit();
405 return 0;
406}
407
379 printk(KERN_INFO "smsc47m1: Device is disabled, will not use\n");
380 superio_exit();
381 return -ENODEV;
382 }
383
384 superio_exit();
385 return 0;
386}
387
408static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
388static int smsc47m1_detect(struct i2c_adapter *adapter)
409{
410 struct i2c_client *new_client;
411 struct smsc47m1_data *data;
412 int err = 0;
413 int fan1, fan2, pwm1, pwm2;
414
389{
390 struct i2c_client *new_client;
391 struct smsc47m1_data *data;
392 int err = 0;
393 int fan1, fan2, pwm1, pwm2;
394
415 if (!i2c_is_isa_adapter(adapter)) {
416 return 0;
417 }
418
419 if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.name)) {
420 dev_err(&adapter->dev, "Region 0x%x already in use!\n", address);
421 return -EBUSY;
422 }
423
424 if (!(data = kmalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
425 err = -ENOMEM;
426 goto error_release;

--- 157 unchanged lines hidden (view full) ---

584 }
585
586 up(&data->update_lock);
587 return data;
588}
589
590static int __init sm_smsc47m1_init(void)
591{
395 if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.name)) {
396 dev_err(&adapter->dev, "Region 0x%x already in use!\n", address);
397 return -EBUSY;
398 }
399
400 if (!(data = kmalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
401 err = -ENOMEM;
402 goto error_release;

--- 157 unchanged lines hidden (view full) ---

560 }
561
562 up(&data->update_lock);
563 return data;
564}
565
566static int __init sm_smsc47m1_init(void)
567{
592 if (smsc47m1_find(normal_isa)) {
568 if (smsc47m1_find(&address)) {
593 return -ENODEV;
594 }
595
596 return i2c_isa_add_driver(&smsc47m1_driver);
597}
598
599static void __exit sm_smsc47m1_exit(void)
600{
601 i2c_isa_del_driver(&smsc47m1_driver);
602}
603
604MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
605MODULE_DESCRIPTION("SMSC LPC47M1xx fan sensors driver");
606MODULE_LICENSE("GPL");
607
608module_init(sm_smsc47m1_init);
609module_exit(sm_smsc47m1_exit);
569 return -ENODEV;
570 }
571
572 return i2c_isa_add_driver(&smsc47m1_driver);
573}
574
575static void __exit sm_smsc47m1_exit(void)
576{
577 i2c_isa_del_driver(&smsc47m1_driver);
578}
579
580MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
581MODULE_DESCRIPTION("SMSC LPC47M1xx fan sensors driver");
582MODULE_LICENSE("GPL");
583
584module_init(sm_smsc47m1_init);
585module_exit(sm_smsc47m1_exit);