Commit 28ff2f7a742daba86ccd7021be7b27a4673b2797

Authored by Hans de Goede
Committed by Jean Delvare
1 parent b6844e8f64

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>

Showing 5 changed files with 390 additions and 310 deletions Side-by-side Diff

drivers/hwmon/Kconfig
... ... @@ -1041,8 +1041,13 @@
1041 1041 This driver can also be built as a module. If so, the module
1042 1042 will be called smsc47b397.
1043 1043  
  1044 +config SENSORS_SCH56XX_COMMON
  1045 + tristate
  1046 + default n
  1047 +
1044 1048 config SENSORS_SCH5627
1045 1049 tristate "SMSC SCH5627"
  1050 + select SENSORS_SCH56XX_COMMON
1046 1051 help
1047 1052 If you say yes here you get support for the hardware monitoring
1048 1053 features of the SMSC SCH5627 Super-I/O chip.
drivers/hwmon/Makefile
... ... @@ -95,6 +95,7 @@
95 95 obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
96 96 obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
97 97 obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o
  98 +obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
98 99 obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o
99 100 obj-$(CONFIG_SENSORS_SHT15) += sht15.o
100 101 obj-$(CONFIG_SENSORS_SHT21) += sht21.o
drivers/hwmon/sch5627.c
... ... @@ -28,33 +28,15 @@
28 28 #include <linux/hwmon-sysfs.h>
29 29 #include <linux/err.h>
30 30 #include <linux/mutex.h>
31   -#include <linux/io.h>
32   -#include <linux/acpi.h>
33   -#include <linux/delay.h>
  31 +#include "sch56xx-common.h"
34 32  
35 33 #define DRVNAME "sch5627"
36 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 36 #define SCH5627_HWMON_ID 0xa5
52 37 #define SCH5627_COMPANY_ID 0x5c
53 38 #define SCH5627_PRIMARY_ID 0xa0
54 39  
55   -#define SCH5627_CMD_READ 0x02
56   -#define SCH5627_CMD_WRITE 0x03
57   -
58 40 #define SCH5627_REG_BUILD_CODE 0x39
59 41 #define SCH5627_REG_BUILD_ID 0x3a
60 42 #define SCH5627_REG_HWMON_ID 0x3c
... ... @@ -111,182 +93,6 @@
111 93 u16 in[SCH5627_NO_IN];
112 94 };
113 95  
114   -static struct platform_device *sch5627_pdev;
115   -
116   -/* Super I/O functions */
117   -static inline int superio_inb(int base, int reg)
118   -{
119   - outb(reg, base);
120   - return inb(base + 1);
121   -}
122   -
123   -static 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   -
136   -static inline void superio_select(int base, int ld)
137   -{
138   - outb(SIO_REG_LDSEL, base);
139   - outb(ld, base + 1);
140   -}
141   -
142   -static inline void superio_exit(int base)
143   -{
144   - outb(SIO_LOCK_KEY, base);
145   - release_region(base, 2);
146   -}
147   -
148   -static 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   -
243   -static 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   -
248   -static 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   -
254   -static 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   -
270   -static 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   -
290 96 static struct sch5627_data *sch5627_update_device(struct device *dev)
291 97 {
292 98 struct sch5627_data *data = dev_get_drvdata(dev);
... ... @@ -297,7 +103,7 @@
297 103  
298 104 /* Trigger a Vbat voltage measurement every 5 minutes */
299 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 107 data->control | 0x10);
302 108 data->last_battery = jiffies;
303 109 }
... ... @@ -305,7 +111,7 @@
305 111 /* Cache the values for 1 second */
306 112 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
307 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 115 SCH5627_REG_TEMP_MSB[i],
310 116 SCH5627_REG_TEMP_LSN[i],
311 117 SCH5627_REG_TEMP_HIGH_NIBBLE[i]);
... ... @@ -317,7 +123,7 @@
317 123 }
318 124  
319 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 127 SCH5627_REG_FAN[i]);
322 128 if (unlikely(val < 0)) {
323 129 ret = ERR_PTR(val);
... ... @@ -327,7 +133,7 @@
327 133 }
328 134  
329 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 137 SCH5627_REG_IN_MSB[i],
332 138 SCH5627_REG_IN_LSN[i],
333 139 SCH5627_REG_IN_HIGH_NIBBLE[i]);
334 140  
335 141  
... ... @@ -355,18 +161,21 @@
355 161 * Note what SMSC calls ABS, is what lm_sensors calls max
356 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 166 if (val < 0)
360 167 return val;
361 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 172 if (val < 0)
365 173 return val;
366 174 data->temp_crit[i] = val;
367 175 }
368 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 179 if (val < 0)
371 180 return val;
372 181 data->fan_min[i] = val;
... ... @@ -667,7 +476,7 @@
667 476 mutex_init(&data->update_lock);
668 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 480 if (val < 0) {
672 481 err = val;
673 482 goto error;
... ... @@ -679,7 +488,7 @@
679 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 492 if (val < 0) {
684 493 err = val;
685 494 goto error;
... ... @@ -691,7 +500,7 @@
691 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 504 if (val < 0) {
696 505 err = val;
697 506 goto error;
698 507  
699 508  
700 509  
... ... @@ -703,25 +512,28 @@
703 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 517 if (build_code < 0) {
708 518 err = build_code;
709 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 524 if (build_id < 0) {
714 525 err = build_id;
715 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 531 if (hwmon_rev < 0) {
720 532 err = hwmon_rev;
721 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 537 if (val < 0) {
726 538 err = val;
727 539 goto error;
... ... @@ -734,7 +546,7 @@
734 546 }
735 547 /* Trigger a Vbat voltage measurement, so that we get a valid reading
736 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 550 data->control | 0x10);
739 551 data->last_battery = jiffies;
740 552  
... ... @@ -746,6 +558,7 @@
746 558 if (err)
747 559 goto error;
748 560  
  561 + pr_info("found %s chip at %#hx\n", DEVNAME, data->addr);
749 562 pr_info("firmware build: code 0x%02X, id 0x%04X, hwmon: rev 0x%02X\n",
750 563 build_code, build_id, hwmon_rev);
751 564  
... ... @@ -768,85 +581,6 @@
768 581 return err;
769 582 }
770 583  
771   -static 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);
807   -exit:
808   - superio_exit(sioaddr);
809   - return err;
810   -}
811   -
812   -static 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   -
844   -exit_device_put:
845   - platform_device_put(sch5627_pdev);
846   -
847   - return err;
848   -}
849   -
850 584 static struct platform_driver sch5627_driver = {
851 585 .driver = {
852 586 .owner = THIS_MODULE,
853 587  
... ... @@ -858,31 +592,11 @@
858 592  
859 593 static int __init sch5627_init(void)
860 594 {
861   - int err = -ENODEV;
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   -
877   -exit_driver:
878   - platform_driver_unregister(&sch5627_driver);
879   -exit:
880   - return err;
  595 + return platform_driver_register(&sch5627_driver);
881 596 }
882 597  
883 598 static void __exit sch5627_exit(void)
884 599 {
885   - platform_device_unregister(sch5627_pdev);
886 600 platform_driver_unregister(&sch5627_driver);
887 601 }
888 602  
drivers/hwmon/sch56xx-common.c
  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 +
  47 +static struct platform_device *sch56xx_pdev;
  48 +
  49 +/* Super I/O functions */
  50 +static inline int superio_inb(int base, int reg)
  51 +{
  52 + outb(reg, base);
  53 + return inb(base + 1);
  54 +}
  55 +
  56 +static 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 +
  69 +static inline void superio_select(int base, int ld)
  70 +{
  71 + outb(SIO_REG_LDSEL, base);
  72 + outb(ld, base + 1);
  73 +}
  74 +
  75 +static inline void superio_exit(int base)
  76 +{
  77 + outb(SIO_LOCK_KEY, base);
  78 + release_region(base, 2);
  79 +}
  80 +
  81 +static 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 +
  176 +int sch56xx_read_virtual_reg(u16 addr, u16 reg)
  177 +{
  178 + return sch56xx_send_cmd(addr, SCH56XX_CMD_READ, reg, 0);
  179 +}
  180 +EXPORT_SYMBOL(sch56xx_read_virtual_reg);
  181 +
  182 +int sch56xx_write_virtual_reg(u16 addr, u16 reg, u8 val)
  183 +{
  184 + return sch56xx_send_cmd(addr, SCH56XX_CMD_WRITE, reg, val);
  185 +}
  186 +EXPORT_SYMBOL(sch56xx_write_virtual_reg);
  187 +
  188 +int 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 +}
  203 +EXPORT_SYMBOL(sch56xx_read_virtual_reg16);
  204 +
  205 +int 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 +}
  224 +EXPORT_SYMBOL(sch56xx_read_virtual_reg12);
  225 +
  226 +static 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 +
  268 +exit:
  269 + superio_exit(sioaddr);
  270 + return err;
  271 +}
  272 +
  273 +static 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 +
  305 +exit_device_put:
  306 + platform_device_put(sch56xx_pdev);
  307 +
  308 + return err;
  309 +}
  310 +
  311 +static 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 +
  326 +static void __exit sch56xx_exit(void)
  327 +{
  328 + platform_device_unregister(sch56xx_pdev);
  329 +}
  330 +
  331 +MODULE_DESCRIPTION("SMSC SCH56xx Hardware Monitoring Common Code");
  332 +MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
  333 +MODULE_LICENSE("GPL");
  334 +
  335 +module_init(sch56xx_init);
  336 +module_exit(sch56xx_exit);
drivers/hwmon/sch56xx-common.h
  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 +int sch56xx_read_virtual_reg(u16 addr, u16 reg);
  21 +int sch56xx_write_virtual_reg(u16 addr, u16 reg, u8 val);
  22 +int sch56xx_read_virtual_reg16(u16 addr, u16 reg);
  23 +int sch56xx_read_virtual_reg12(u16 addr, u16 msb_reg, u16 lsn_reg,
  24 + int high_nibble);