aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/sch5627.c
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/hwmon/sch5627.c
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/hwmon/sch5627.c')
-rw-r--r--drivers/hwmon/sch5627.c334
1 files changed, 24 insertions, 310 deletions
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