aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2011-07-25 15:46:09 -0400
committerJean Delvare <khali@endymion.delvare>2011-07-25 15:46:09 -0400
commit28ff2f7a742daba86ccd7021be7b27a4673b2797 (patch)
tree1c6d11e31c793adbdef731a2640842ea06566539 /drivers
parentb6844e8f64920cdee620157252169ba63afb0c89 (diff)
hwmon: (sch5627) Factor out some code shared with sch5636 driver
This patch adds a new sch56xx-common.ko which contains code which will also be used in the new sch5636 driver. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hwmon/Kconfig5
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/sch5627.c334
-rw-r--r--drivers/hwmon/sch56xx-common.c336
-rw-r--r--drivers/hwmon/sch56xx-common.h24
5 files changed, 390 insertions, 310 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 5f888f7e7dcb..0ed767715cb0 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1041,8 +1041,13 @@ config SENSORS_SMSC47B397
1041 This driver can also be built as a module. If so, the module 1041 This driver can also be built as a module. If so, the module
1042 will be called smsc47b397. 1042 will be called smsc47b397.
1043 1043
1044config SENSORS_SCH56XX_COMMON
1045 tristate
1046 default n
1047
1044config SENSORS_SCH5627 1048config SENSORS_SCH5627
1045 tristate "SMSC SCH5627" 1049 tristate "SMSC SCH5627"
1050 select SENSORS_SCH56XX_COMMON
1046 help 1051 help
1047 If you say yes here you get support for the hardware monitoring 1052 If you say yes here you get support for the hardware monitoring
1048 features of the SMSC SCH5627 Super-I/O chip. 1053 features of the SMSC SCH5627 Super-I/O chip.
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 28061cfa0cdb..ae59bca3852a 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -95,6 +95,7 @@ obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
95obj-$(CONFIG_SENSORS_PC87427) += pc87427.o 95obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
96obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o 96obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
97obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o 97obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o
98obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
98obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o 99obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o
99obj-$(CONFIG_SENSORS_SHT15) += sht15.o 100obj-$(CONFIG_SENSORS_SHT15) += sht15.o
100obj-$(CONFIG_SENSORS_SHT21) += sht21.o 101obj-$(CONFIG_SENSORS_SHT21) += sht21.o
diff --git a/drivers/hwmon/sch5627.c b/drivers/hwmon/sch5627.c
index 3494a4cce414..e3b5c6039c25 100644
--- a/drivers/hwmon/sch5627.c
+++ b/drivers/hwmon/sch5627.c
@@ -28,33 +28,15 @@
28#include <linux/hwmon-sysfs.h> 28#include <linux/hwmon-sysfs.h>
29#include <linux/err.h> 29#include <linux/err.h>
30#include <linux/mutex.h> 30#include <linux/mutex.h>
31#include <linux/io.h> 31#include "sch56xx-common.h"
32#include <linux/acpi.h>
33#include <linux/delay.h>
34 32
35#define DRVNAME "sch5627" 33#define DRVNAME "sch5627"
36#define DEVNAME DRVNAME /* We only support one model */ 34#define DEVNAME DRVNAME /* We only support one model */
37 35
38#define SIO_SCH5627_EM_LD 0x0C /* Embedded Microcontroller LD */
39#define SIO_UNLOCK_KEY 0x55 /* Key to enable Super-I/O */
40#define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */
41
42#define SIO_REG_LDSEL 0x07 /* Logical device select */
43#define SIO_REG_DEVID 0x20 /* Device ID */
44#define SIO_REG_ENABLE 0x30 /* Logical device enable */
45#define SIO_REG_ADDR 0x66 /* Logical device address (2 bytes) */
46
47#define SIO_SCH5627_ID 0xC6 /* Chipset ID */
48
49#define REGION_LENGTH 9
50
51#define SCH5627_HWMON_ID 0xa5 36#define SCH5627_HWMON_ID 0xa5
52#define SCH5627_COMPANY_ID 0x5c 37#define SCH5627_COMPANY_ID 0x5c
53#define SCH5627_PRIMARY_ID 0xa0 38#define SCH5627_PRIMARY_ID 0xa0
54 39
55#define SCH5627_CMD_READ 0x02
56#define SCH5627_CMD_WRITE 0x03
57
58#define SCH5627_REG_BUILD_CODE 0x39 40#define SCH5627_REG_BUILD_CODE 0x39
59#define SCH5627_REG_BUILD_ID 0x3a 41#define SCH5627_REG_BUILD_ID 0x3a
60#define SCH5627_REG_HWMON_ID 0x3c 42#define SCH5627_REG_HWMON_ID 0x3c
@@ -111,182 +93,6 @@ struct sch5627_data {
111 u16 in[SCH5627_NO_IN]; 93 u16 in[SCH5627_NO_IN];
112}; 94};
113 95
114static struct platform_device *sch5627_pdev;
115
116/* Super I/O functions */
117static inline int superio_inb(int base, int reg)
118{
119 outb(reg, base);
120 return inb(base + 1);
121}
122
123static inline int superio_enter(int base)
124{
125 /* Don't step on other drivers' I/O space by accident */
126 if (!request_muxed_region(base, 2, DRVNAME)) {
127 pr_err("I/O address 0x%04x already in use\n", base);
128 return -EBUSY;
129 }
130
131 outb(SIO_UNLOCK_KEY, base);
132
133 return 0;
134}
135
136static inline void superio_select(int base, int ld)
137{
138 outb(SIO_REG_LDSEL, base);
139 outb(ld, base + 1);
140}
141
142static inline void superio_exit(int base)
143{
144 outb(SIO_LOCK_KEY, base);
145 release_region(base, 2);
146}
147
148static int sch5627_send_cmd(struct sch5627_data *data, u8 cmd, u16 reg, u8 v)
149{
150 u8 val;
151 int i;
152 /*
153 * According to SMSC for the commands we use the maximum time for
154 * the EM to respond is 15 ms, but testing shows in practice it
155 * responds within 15-32 reads, so we first busy poll, and if
156 * that fails sleep a bit and try again until we are way past
157 * the 15 ms maximum response time.
158 */
159 const int max_busy_polls = 64;
160 const int max_lazy_polls = 32;
161
162 /* (Optional) Write-Clear the EC to Host Mailbox Register */
163 val = inb(data->addr + 1);
164 outb(val, data->addr + 1);
165
166 /* Set Mailbox Address Pointer to first location in Region 1 */
167 outb(0x00, data->addr + 2);
168 outb(0x80, data->addr + 3);
169
170 /* Write Request Packet Header */
171 outb(cmd, data->addr + 4); /* VREG Access Type read:0x02 write:0x03 */
172 outb(0x01, data->addr + 5); /* # of Entries: 1 Byte (8-bit) */
173 outb(0x04, data->addr + 2); /* Mailbox AP to first data entry loc. */
174
175 /* Write Value field */
176 if (cmd == SCH5627_CMD_WRITE)
177 outb(v, data->addr + 4);
178
179 /* Write Address field */
180 outb(reg & 0xff, data->addr + 6);
181 outb(reg >> 8, data->addr + 7);
182
183 /* Execute the Random Access Command */
184 outb(0x01, data->addr); /* Write 01h to the Host-to-EC register */
185
186 /* EM Interface Polling "Algorithm" */
187 for (i = 0; i < max_busy_polls + max_lazy_polls; i++) {
188 if (i >= max_busy_polls)
189 msleep(1);
190 /* Read Interrupt source Register */
191 val = inb(data->addr + 8);
192 /* Write Clear the interrupt source bits */
193 if (val)
194 outb(val, data->addr + 8);
195 /* Command Completed ? */
196 if (val & 0x01)
197 break;
198 }
199 if (i == max_busy_polls + max_lazy_polls) {
200 pr_err("Max retries exceeded reading virtual "
201 "register 0x%04hx (%d)\n", reg, 1);
202 return -EIO;
203 }
204
205 /*
206 * According to SMSC we may need to retry this, but sofar I've always
207 * seen this succeed in 1 try.
208 */
209 for (i = 0; i < max_busy_polls; i++) {
210 /* Read EC-to-Host Register */
211 val = inb(data->addr + 1);
212 /* Command Completed ? */
213 if (val == 0x01)
214 break;
215
216 if (i == 0)
217 pr_warn("EC reports: 0x%02x reading virtual register "
218 "0x%04hx\n", (unsigned int)val, reg);
219 }
220 if (i == max_busy_polls) {
221 pr_err("Max retries exceeded reading virtual "
222 "register 0x%04hx (%d)\n", reg, 2);
223 return -EIO;
224 }
225
226 /*
227 * According to the SMSC app note we should now do:
228 *
229 * Set Mailbox Address Pointer to first location in Region 1 *
230 * outb(0x00, data->addr + 2);
231 * outb(0x80, data->addr + 3);
232 *
233 * But if we do that things don't work, so let's not.
234 */
235
236 /* Read Value field */
237 if (cmd == SCH5627_CMD_READ)
238 return inb(data->addr + 4);
239
240 return 0;
241}
242
243static int sch5627_read_virtual_reg(struct sch5627_data *data, u16 reg)
244{
245 return sch5627_send_cmd(data, SCH5627_CMD_READ, reg, 0);
246}
247
248static int sch5627_write_virtual_reg(struct sch5627_data *data,
249 u16 reg, u8 val)
250{
251 return sch5627_send_cmd(data, SCH5627_CMD_WRITE, reg, val);
252}
253
254static int sch5627_read_virtual_reg16(struct sch5627_data *data, u16 reg)
255{
256 int lsb, msb;
257
258 /* Read LSB first, this will cause the matching MSB to be latched */
259 lsb = sch5627_read_virtual_reg(data, reg);
260 if (lsb < 0)
261 return lsb;
262
263 msb = sch5627_read_virtual_reg(data, reg + 1);
264 if (msb < 0)
265 return msb;
266
267 return lsb | (msb << 8);
268}
269
270static int sch5627_read_virtual_reg12(struct sch5627_data *data, u16 msb_reg,
271 u16 lsn_reg, int high_nibble)
272{
273 int msb, lsn;
274
275 /* Read MSB first, this will cause the matching LSN to be latched */
276 msb = sch5627_read_virtual_reg(data, msb_reg);
277 if (msb < 0)
278 return msb;
279
280 lsn = sch5627_read_virtual_reg(data, lsn_reg);
281 if (lsn < 0)
282 return lsn;
283
284 if (high_nibble)
285 return (msb << 4) | (lsn >> 4);
286 else
287 return (msb << 4) | (lsn & 0x0f);
288}
289
290static struct sch5627_data *sch5627_update_device(struct device *dev) 96static struct sch5627_data *sch5627_update_device(struct device *dev)
291{ 97{
292 struct sch5627_data *data = dev_get_drvdata(dev); 98 struct sch5627_data *data = dev_get_drvdata(dev);
@@ -297,7 +103,7 @@ static struct sch5627_data *sch5627_update_device(struct device *dev)
297 103
298 /* Trigger a Vbat voltage measurement every 5 minutes */ 104 /* Trigger a Vbat voltage measurement every 5 minutes */
299 if (time_after(jiffies, data->last_battery + 300 * HZ)) { 105 if (time_after(jiffies, data->last_battery + 300 * HZ)) {
300 sch5627_write_virtual_reg(data, SCH5627_REG_CTRL, 106 sch56xx_write_virtual_reg(data->addr, SCH5627_REG_CTRL,
301 data->control | 0x10); 107 data->control | 0x10);
302 data->last_battery = jiffies; 108 data->last_battery = jiffies;
303 } 109 }
@@ -305,7 +111,7 @@ static struct sch5627_data *sch5627_update_device(struct device *dev)
305 /* Cache the values for 1 second */ 111 /* Cache the values for 1 second */
306 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { 112 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
307 for (i = 0; i < SCH5627_NO_TEMPS; i++) { 113 for (i = 0; i < SCH5627_NO_TEMPS; i++) {
308 val = sch5627_read_virtual_reg12(data, 114 val = sch56xx_read_virtual_reg12(data->addr,
309 SCH5627_REG_TEMP_MSB[i], 115 SCH5627_REG_TEMP_MSB[i],
310 SCH5627_REG_TEMP_LSN[i], 116 SCH5627_REG_TEMP_LSN[i],
311 SCH5627_REG_TEMP_HIGH_NIBBLE[i]); 117 SCH5627_REG_TEMP_HIGH_NIBBLE[i]);
@@ -317,7 +123,7 @@ static struct sch5627_data *sch5627_update_device(struct device *dev)
317 } 123 }
318 124
319 for (i = 0; i < SCH5627_NO_FANS; i++) { 125 for (i = 0; i < SCH5627_NO_FANS; i++) {
320 val = sch5627_read_virtual_reg16(data, 126 val = sch56xx_read_virtual_reg16(data->addr,
321 SCH5627_REG_FAN[i]); 127 SCH5627_REG_FAN[i]);
322 if (unlikely(val < 0)) { 128 if (unlikely(val < 0)) {
323 ret = ERR_PTR(val); 129 ret = ERR_PTR(val);
@@ -327,7 +133,7 @@ static struct sch5627_data *sch5627_update_device(struct device *dev)
327 } 133 }
328 134
329 for (i = 0; i < SCH5627_NO_IN; i++) { 135 for (i = 0; i < SCH5627_NO_IN; i++) {
330 val = sch5627_read_virtual_reg12(data, 136 val = sch56xx_read_virtual_reg12(data->addr,
331 SCH5627_REG_IN_MSB[i], 137 SCH5627_REG_IN_MSB[i],
332 SCH5627_REG_IN_LSN[i], 138 SCH5627_REG_IN_LSN[i],
333 SCH5627_REG_IN_HIGH_NIBBLE[i]); 139 SCH5627_REG_IN_HIGH_NIBBLE[i]);
@@ -355,18 +161,21 @@ static int __devinit sch5627_read_limits(struct sch5627_data *data)
355 * Note what SMSC calls ABS, is what lm_sensors calls max 161 * Note what SMSC calls ABS, is what lm_sensors calls max
356 * (aka high), and HIGH is what lm_sensors calls crit. 162 * (aka high), and HIGH is what lm_sensors calls crit.
357 */ 163 */
358 val = sch5627_read_virtual_reg(data, SCH5627_REG_TEMP_ABS[i]); 164 val = sch56xx_read_virtual_reg(data->addr,
165 SCH5627_REG_TEMP_ABS[i]);
359 if (val < 0) 166 if (val < 0)
360 return val; 167 return val;
361 data->temp_max[i] = val; 168 data->temp_max[i] = val;
362 169
363 val = sch5627_read_virtual_reg(data, SCH5627_REG_TEMP_HIGH[i]); 170 val = sch56xx_read_virtual_reg(data->addr,
171 SCH5627_REG_TEMP_HIGH[i]);
364 if (val < 0) 172 if (val < 0)
365 return val; 173 return val;
366 data->temp_crit[i] = val; 174 data->temp_crit[i] = val;
367 } 175 }
368 for (i = 0; i < SCH5627_NO_FANS; i++) { 176 for (i = 0; i < SCH5627_NO_FANS; i++) {
369 val = sch5627_read_virtual_reg16(data, SCH5627_REG_FAN_MIN[i]); 177 val = sch56xx_read_virtual_reg16(data->addr,
178 SCH5627_REG_FAN_MIN[i]);
370 if (val < 0) 179 if (val < 0)
371 return val; 180 return val;
372 data->fan_min[i] = val; 181 data->fan_min[i] = val;
@@ -667,7 +476,7 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
667 mutex_init(&data->update_lock); 476 mutex_init(&data->update_lock);
668 platform_set_drvdata(pdev, data); 477 platform_set_drvdata(pdev, data);
669 478
670 val = sch5627_read_virtual_reg(data, SCH5627_REG_HWMON_ID); 479 val = sch56xx_read_virtual_reg(data->addr, SCH5627_REG_HWMON_ID);
671 if (val < 0) { 480 if (val < 0) {
672 err = val; 481 err = val;
673 goto error; 482 goto error;
@@ -679,7 +488,7 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
679 goto error; 488 goto error;
680 } 489 }
681 490
682 val = sch5627_read_virtual_reg(data, SCH5627_REG_COMPANY_ID); 491 val = sch56xx_read_virtual_reg(data->addr, SCH5627_REG_COMPANY_ID);
683 if (val < 0) { 492 if (val < 0) {
684 err = val; 493 err = val;
685 goto error; 494 goto error;
@@ -691,7 +500,7 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
691 goto error; 500 goto error;
692 } 501 }
693 502
694 val = sch5627_read_virtual_reg(data, SCH5627_REG_PRIMARY_ID); 503 val = sch56xx_read_virtual_reg(data->addr, SCH5627_REG_PRIMARY_ID);
695 if (val < 0) { 504 if (val < 0) {
696 err = val; 505 err = val;
697 goto error; 506 goto error;
@@ -703,25 +512,28 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
703 goto error; 512 goto error;
704 } 513 }
705 514
706 build_code = sch5627_read_virtual_reg(data, SCH5627_REG_BUILD_CODE); 515 build_code = sch56xx_read_virtual_reg(data->addr,
516 SCH5627_REG_BUILD_CODE);
707 if (build_code < 0) { 517 if (build_code < 0) {
708 err = build_code; 518 err = build_code;
709 goto error; 519 goto error;
710 } 520 }
711 521
712 build_id = sch5627_read_virtual_reg16(data, SCH5627_REG_BUILD_ID); 522 build_id = sch56xx_read_virtual_reg16(data->addr,
523 SCH5627_REG_BUILD_ID);
713 if (build_id < 0) { 524 if (build_id < 0) {
714 err = build_id; 525 err = build_id;
715 goto error; 526 goto error;
716 } 527 }
717 528
718 hwmon_rev = sch5627_read_virtual_reg(data, SCH5627_REG_HWMON_REV); 529 hwmon_rev = sch56xx_read_virtual_reg(data->addr,
530 SCH5627_REG_HWMON_REV);
719 if (hwmon_rev < 0) { 531 if (hwmon_rev < 0) {
720 err = hwmon_rev; 532 err = hwmon_rev;
721 goto error; 533 goto error;
722 } 534 }
723 535
724 val = sch5627_read_virtual_reg(data, SCH5627_REG_CTRL); 536 val = sch56xx_read_virtual_reg(data->addr, SCH5627_REG_CTRL);
725 if (val < 0) { 537 if (val < 0) {
726 err = val; 538 err = val;
727 goto error; 539 goto error;
@@ -734,7 +546,7 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
734 } 546 }
735 /* Trigger a Vbat voltage measurement, so that we get a valid reading 547 /* Trigger a Vbat voltage measurement, so that we get a valid reading
736 the first time we read Vbat */ 548 the first time we read Vbat */
737 sch5627_write_virtual_reg(data, SCH5627_REG_CTRL, 549 sch56xx_write_virtual_reg(data->addr, SCH5627_REG_CTRL,
738 data->control | 0x10); 550 data->control | 0x10);
739 data->last_battery = jiffies; 551 data->last_battery = jiffies;
740 552
@@ -746,6 +558,7 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
746 if (err) 558 if (err)
747 goto error; 559 goto error;
748 560
561 pr_info("found %s chip at %#hx\n", DEVNAME, data->addr);
749 pr_info("firmware build: code 0x%02X, id 0x%04X, hwmon: rev 0x%02X\n", 562 pr_info("firmware build: code 0x%02X, id 0x%04X, hwmon: rev 0x%02X\n",
750 build_code, build_id, hwmon_rev); 563 build_code, build_id, hwmon_rev);
751 564
@@ -768,85 +581,6 @@ error:
768 return err; 581 return err;
769} 582}
770 583
771static int __init sch5627_find(int sioaddr, unsigned short *address)
772{
773 u8 devid;
774 int err = superio_enter(sioaddr);
775 if (err)
776 return err;
777
778 devid = superio_inb(sioaddr, SIO_REG_DEVID);
779 if (devid != SIO_SCH5627_ID) {
780 pr_debug("Unsupported device id: 0x%02x\n",
781 (unsigned int)devid);
782 err = -ENODEV;
783 goto exit;
784 }
785
786 superio_select(sioaddr, SIO_SCH5627_EM_LD);
787
788 if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
789 pr_warn("Device not activated\n");
790 err = -ENODEV;
791 goto exit;
792 }
793
794 /*
795 * Warning the order of the low / high byte is the other way around
796 * as on most other superio devices!!
797 */
798 *address = superio_inb(sioaddr, SIO_REG_ADDR) |
799 superio_inb(sioaddr, SIO_REG_ADDR + 1) << 8;
800 if (*address == 0) {
801 pr_warn("Base address not set\n");
802 err = -ENODEV;
803 goto exit;
804 }
805
806 pr_info("Found %s chip at %#hx\n", DEVNAME, *address);
807exit:
808 superio_exit(sioaddr);
809 return err;
810}
811
812static int __init sch5627_device_add(unsigned short address)
813{
814 struct resource res = {
815 .start = address,
816 .end = address + REGION_LENGTH - 1,
817 .flags = IORESOURCE_IO,
818 };
819 int err;
820
821 sch5627_pdev = platform_device_alloc(DRVNAME, address);
822 if (!sch5627_pdev)
823 return -ENOMEM;
824
825 res.name = sch5627_pdev->name;
826 err = acpi_check_resource_conflict(&res);
827 if (err)
828 goto exit_device_put;
829
830 err = platform_device_add_resources(sch5627_pdev, &res, 1);
831 if (err) {
832 pr_err("Device resource addition failed\n");
833 goto exit_device_put;
834 }
835
836 err = platform_device_add(sch5627_pdev);
837 if (err) {
838 pr_err("Device addition failed\n");
839 goto exit_device_put;
840 }
841
842 return 0;
843
844exit_device_put:
845 platform_device_put(sch5627_pdev);
846
847 return err;
848}
849
850static struct platform_driver sch5627_driver = { 584static struct platform_driver sch5627_driver = {
851 .driver = { 585 .driver = {
852 .owner = THIS_MODULE, 586 .owner = THIS_MODULE,
@@ -858,31 +592,11 @@ static struct platform_driver sch5627_driver = {
858 592
859static int __init sch5627_init(void) 593static int __init sch5627_init(void)
860{ 594{
861 int err = -ENODEV; 595 return platform_driver_register(&sch5627_driver);
862 unsigned short address;
863
864 if (sch5627_find(0x4e, &address) && sch5627_find(0x2e, &address))
865 goto exit;
866
867 err = platform_driver_register(&sch5627_driver);
868 if (err)
869 goto exit;
870
871 err = sch5627_device_add(address);
872 if (err)
873 goto exit_driver;
874
875 return 0;
876
877exit_driver:
878 platform_driver_unregister(&sch5627_driver);
879exit:
880 return err;
881} 596}
882 597
883static void __exit sch5627_exit(void) 598static void __exit sch5627_exit(void)
884{ 599{
885 platform_device_unregister(sch5627_pdev);
886 platform_driver_unregister(&sch5627_driver); 600 platform_driver_unregister(&sch5627_driver);
887} 601}
888 602
diff --git a/drivers/hwmon/sch56xx-common.c b/drivers/hwmon/sch56xx-common.c
new file mode 100644
index 000000000000..a579313b55df
--- /dev/null
+++ b/drivers/hwmon/sch56xx-common.c
@@ -0,0 +1,336 @@
1/***************************************************************************
2 * Copyright (C) 2010-2011 Hans de Goede <hdegoede@redhat.com> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
19
20#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
21
22#include <linux/module.h>
23#include <linux/init.h>
24#include <linux/platform_device.h>
25#include <linux/err.h>
26#include <linux/io.h>
27#include <linux/acpi.h>
28#include <linux/delay.h>
29#include "sch56xx-common.h"
30
31#define SIO_SCH56XX_LD_EM 0x0C /* Embedded uController Logical Dev */
32#define SIO_UNLOCK_KEY 0x55 /* Key to enable Super-I/O */
33#define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */
34
35#define SIO_REG_LDSEL 0x07 /* Logical device select */
36#define SIO_REG_DEVID 0x20 /* Device ID */
37#define SIO_REG_ENABLE 0x30 /* Logical device enable */
38#define SIO_REG_ADDR 0x66 /* Logical device address (2 bytes) */
39
40#define SIO_SCH5627_ID 0xC6 /* Chipset ID */
41
42#define REGION_LENGTH 9
43
44#define SCH56XX_CMD_READ 0x02
45#define SCH56XX_CMD_WRITE 0x03
46
47static struct platform_device *sch56xx_pdev;
48
49/* Super I/O functions */
50static inline int superio_inb(int base, int reg)
51{
52 outb(reg, base);
53 return inb(base + 1);
54}
55
56static inline int superio_enter(int base)
57{
58 /* Don't step on other drivers' I/O space by accident */
59 if (!request_muxed_region(base, 2, "sch56xx")) {
60 pr_err("I/O address 0x%04x already in use\n", base);
61 return -EBUSY;
62 }
63
64 outb(SIO_UNLOCK_KEY, base);
65
66 return 0;
67}
68
69static inline void superio_select(int base, int ld)
70{
71 outb(SIO_REG_LDSEL, base);
72 outb(ld, base + 1);
73}
74
75static inline void superio_exit(int base)
76{
77 outb(SIO_LOCK_KEY, base);
78 release_region(base, 2);
79}
80
81static int sch56xx_send_cmd(u16 addr, u8 cmd, u16 reg, u8 v)
82{
83 u8 val;
84 int i;
85 /*
86 * According to SMSC for the commands we use the maximum time for
87 * the EM to respond is 15 ms, but testing shows in practice it
88 * responds within 15-32 reads, so we first busy poll, and if
89 * that fails sleep a bit and try again until we are way past
90 * the 15 ms maximum response time.
91 */
92 const int max_busy_polls = 64;
93 const int max_lazy_polls = 32;
94
95 /* (Optional) Write-Clear the EC to Host Mailbox Register */
96 val = inb(addr + 1);
97 outb(val, addr + 1);
98
99 /* Set Mailbox Address Pointer to first location in Region 1 */
100 outb(0x00, addr + 2);
101 outb(0x80, addr + 3);
102
103 /* Write Request Packet Header */
104 outb(cmd, addr + 4); /* VREG Access Type read:0x02 write:0x03 */
105 outb(0x01, addr + 5); /* # of Entries: 1 Byte (8-bit) */
106 outb(0x04, addr + 2); /* Mailbox AP to first data entry loc. */
107
108 /* Write Value field */
109 if (cmd == SCH56XX_CMD_WRITE)
110 outb(v, addr + 4);
111
112 /* Write Address field */
113 outb(reg & 0xff, addr + 6);
114 outb(reg >> 8, addr + 7);
115
116 /* Execute the Random Access Command */
117 outb(0x01, addr); /* Write 01h to the Host-to-EC register */
118
119 /* EM Interface Polling "Algorithm" */
120 for (i = 0; i < max_busy_polls + max_lazy_polls; i++) {
121 if (i >= max_busy_polls)
122 msleep(1);
123 /* Read Interrupt source Register */
124 val = inb(addr + 8);
125 /* Write Clear the interrupt source bits */
126 if (val)
127 outb(val, addr + 8);
128 /* Command Completed ? */
129 if (val & 0x01)
130 break;
131 }
132 if (i == max_busy_polls + max_lazy_polls) {
133 pr_err("Max retries exceeded reading virtual "
134 "register 0x%04hx (%d)\n", reg, 1);
135 return -EIO;
136 }
137
138 /*
139 * According to SMSC we may need to retry this, but sofar I've always
140 * seen this succeed in 1 try.
141 */
142 for (i = 0; i < max_busy_polls; i++) {
143 /* Read EC-to-Host Register */
144 val = inb(addr + 1);
145 /* Command Completed ? */
146 if (val == 0x01)
147 break;
148
149 if (i == 0)
150 pr_warn("EC reports: 0x%02x reading virtual register "
151 "0x%04hx\n", (unsigned int)val, reg);
152 }
153 if (i == max_busy_polls) {
154 pr_err("Max retries exceeded reading virtual "
155 "register 0x%04hx (%d)\n", reg, 2);
156 return -EIO;
157 }
158
159 /*
160 * According to the SMSC app note we should now do:
161 *
162 * Set Mailbox Address Pointer to first location in Region 1 *
163 * outb(0x00, addr + 2);
164 * outb(0x80, addr + 3);
165 *
166 * But if we do that things don't work, so let's not.
167 */
168
169 /* Read Value field */
170 if (cmd == SCH56XX_CMD_READ)
171 return inb(addr + 4);
172
173 return 0;
174}
175
176int sch56xx_read_virtual_reg(u16 addr, u16 reg)
177{
178 return sch56xx_send_cmd(addr, SCH56XX_CMD_READ, reg, 0);
179}
180EXPORT_SYMBOL(sch56xx_read_virtual_reg);
181
182int sch56xx_write_virtual_reg(u16 addr, u16 reg, u8 val)
183{
184 return sch56xx_send_cmd(addr, SCH56XX_CMD_WRITE, reg, val);
185}
186EXPORT_SYMBOL(sch56xx_write_virtual_reg);
187
188int sch56xx_read_virtual_reg16(u16 addr, u16 reg)
189{
190 int lsb, msb;
191
192 /* Read LSB first, this will cause the matching MSB to be latched */
193 lsb = sch56xx_read_virtual_reg(addr, reg);
194 if (lsb < 0)
195 return lsb;
196
197 msb = sch56xx_read_virtual_reg(addr, reg + 1);
198 if (msb < 0)
199 return msb;
200
201 return lsb | (msb << 8);
202}
203EXPORT_SYMBOL(sch56xx_read_virtual_reg16);
204
205int sch56xx_read_virtual_reg12(u16 addr, u16 msb_reg, u16 lsn_reg,
206 int high_nibble)
207{
208 int msb, lsn;
209
210 /* Read MSB first, this will cause the matching LSN to be latched */
211 msb = sch56xx_read_virtual_reg(addr, msb_reg);
212 if (msb < 0)
213 return msb;
214
215 lsn = sch56xx_read_virtual_reg(addr, lsn_reg);
216 if (lsn < 0)
217 return lsn;
218
219 if (high_nibble)
220 return (msb << 4) | (lsn >> 4);
221 else
222 return (msb << 4) | (lsn & 0x0f);
223}
224EXPORT_SYMBOL(sch56xx_read_virtual_reg12);
225
226static int __init sch56xx_find(int sioaddr, unsigned short *address,
227 const char **name)
228{
229 u8 devid;
230 int err;
231
232 err = superio_enter(sioaddr);
233 if (err)
234 return err;
235
236 devid = superio_inb(sioaddr, SIO_REG_DEVID);
237 switch (devid) {
238 case SIO_SCH5627_ID:
239 *name = "sch5627";
240 break;
241 default:
242 pr_debug("Unsupported device id: 0x%02x\n",
243 (unsigned int)devid);
244 err = -ENODEV;
245 goto exit;
246 }
247
248 superio_select(sioaddr, SIO_SCH56XX_LD_EM);
249
250 if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
251 pr_warn("Device not activated\n");
252 err = -ENODEV;
253 goto exit;
254 }
255
256 /*
257 * Warning the order of the low / high byte is the other way around
258 * as on most other superio devices!!
259 */
260 *address = superio_inb(sioaddr, SIO_REG_ADDR) |
261 superio_inb(sioaddr, SIO_REG_ADDR + 1) << 8;
262 if (*address == 0) {
263 pr_warn("Base address not set\n");
264 err = -ENODEV;
265 goto exit;
266 }
267
268exit:
269 superio_exit(sioaddr);
270 return err;
271}
272
273static int __init sch56xx_device_add(unsigned short address, const char *name)
274{
275 struct resource res = {
276 .start = address,
277 .end = address + REGION_LENGTH - 1,
278 .flags = IORESOURCE_IO,
279 };
280 int err;
281
282 sch56xx_pdev = platform_device_alloc(name, address);
283 if (!sch56xx_pdev)
284 return -ENOMEM;
285
286 res.name = sch56xx_pdev->name;
287 err = acpi_check_resource_conflict(&res);
288 if (err)
289 goto exit_device_put;
290
291 err = platform_device_add_resources(sch56xx_pdev, &res, 1);
292 if (err) {
293 pr_err("Device resource addition failed\n");
294 goto exit_device_put;
295 }
296
297 err = platform_device_add(sch56xx_pdev);
298 if (err) {
299 pr_err("Device addition failed\n");
300 goto exit_device_put;
301 }
302
303 return 0;
304
305exit_device_put:
306 platform_device_put(sch56xx_pdev);
307
308 return err;
309}
310
311static int __init sch56xx_init(void)
312{
313 int err;
314 unsigned short address;
315 const char *name;
316
317 err = sch56xx_find(0x4e, &address, &name);
318 if (err)
319 err = sch56xx_find(0x2e, &address, &name);
320 if (err)
321 return err;
322
323 return sch56xx_device_add(address, name);
324}
325
326static void __exit sch56xx_exit(void)
327{
328 platform_device_unregister(sch56xx_pdev);
329}
330
331MODULE_DESCRIPTION("SMSC SCH56xx Hardware Monitoring Common Code");
332MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
333MODULE_LICENSE("GPL");
334
335module_init(sch56xx_init);
336module_exit(sch56xx_exit);
diff --git a/drivers/hwmon/sch56xx-common.h b/drivers/hwmon/sch56xx-common.h
new file mode 100644
index 000000000000..d5eaf3b9ebf5
--- /dev/null
+++ b/drivers/hwmon/sch56xx-common.h
@@ -0,0 +1,24 @@
1/***************************************************************************
2 * Copyright (C) 2010-2011 Hans de Goede <hdegoede@redhat.com> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
19
20int sch56xx_read_virtual_reg(u16 addr, u16 reg);
21int sch56xx_write_virtual_reg(u16 addr, u16 reg, u8 val);
22int sch56xx_read_virtual_reg16(u16 addr, u16 reg);
23int sch56xx_read_virtual_reg12(u16 addr, u16 msb_reg, u16 lsn_reg,
24 int high_nibble);