aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/nct6775.c
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2013-04-05 10:35:25 -0400
committerGuenter Roeck <linux@roeck-us.net>2013-08-12 01:10:39 -0400
commit698a7c24a5447ffd940bfc9f5e6e8448d836a2b4 (patch)
tree5aff6d30fdaac32a3412acdf1c9e241afd166056 /drivers/hwmon/nct6775.c
parentf73cf632dfb43d6236210aa38038cc91fd053ff6 (diff)
hwmon: (nct6775) Support two SuperIO chips in the same system
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon/nct6775.c')
-rw-r--r--drivers/hwmon/nct6775.c113
1 files changed, 63 insertions, 50 deletions
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c
index 778772d6bdda..caff72658c1a 100644
--- a/drivers/hwmon/nct6775.c
+++ b/drivers/hwmon/nct6775.c
@@ -3484,11 +3484,11 @@ static const char * const nct6775_sio_names[] __initconst = {
3484}; 3484};
3485 3485
3486/* nct6775_find() looks for a '627 in the Super-I/O config space */ 3486/* nct6775_find() looks for a '627 in the Super-I/O config space */
3487static int __init nct6775_find(int sioaddr, unsigned short *addr, 3487static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
3488 struct nct6775_sio_data *sio_data)
3489{ 3488{
3490 u16 val; 3489 u16 val;
3491 int err; 3490 int err;
3491 int addr;
3492 3492
3493 err = superio_enter(sioaddr); 3493 err = superio_enter(sioaddr);
3494 if (err) 3494 if (err)
@@ -3520,8 +3520,8 @@ static int __init nct6775_find(int sioaddr, unsigned short *addr,
3520 superio_select(sioaddr, NCT6775_LD_HWM); 3520 superio_select(sioaddr, NCT6775_LD_HWM);
3521 val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8) 3521 val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
3522 | superio_inb(sioaddr, SIO_REG_ADDR + 1); 3522 | superio_inb(sioaddr, SIO_REG_ADDR + 1);
3523 *addr = val & IOREGION_ALIGNMENT; 3523 addr = val & IOREGION_ALIGNMENT;
3524 if (*addr == 0) { 3524 if (addr == 0) {
3525 pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n"); 3525 pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
3526 superio_exit(sioaddr); 3526 superio_exit(sioaddr);
3527 return -ENODEV; 3527 return -ENODEV;
@@ -3535,11 +3535,11 @@ static int __init nct6775_find(int sioaddr, unsigned short *addr,
3535 } 3535 }
3536 3536
3537 superio_exit(sioaddr); 3537 superio_exit(sioaddr);
3538 pr_info("Found %s or compatible chip at %#x\n", 3538 pr_info("Found %s or compatible chip at %#x:%#x\n",
3539 nct6775_sio_names[sio_data->kind], *addr); 3539 nct6775_sio_names[sio_data->kind], sioaddr, addr);
3540 sio_data->sioreg = sioaddr; 3540 sio_data->sioreg = sioaddr;
3541 3541
3542 return 0; 3542 return addr;
3543} 3543}
3544 3544
3545/* 3545/*
@@ -3548,14 +3548,20 @@ static int __init nct6775_find(int sioaddr, unsigned short *addr,
3548 * track of the nct6775 driver. But since we platform_device_alloc(), we 3548 * track of the nct6775 driver. But since we platform_device_alloc(), we
3549 * must keep track of the device 3549 * must keep track of the device
3550 */ 3550 */
3551static struct platform_device *pdev; 3551static struct platform_device *pdev[2];
3552 3552
3553static int __init sensors_nct6775_init(void) 3553static int __init sensors_nct6775_init(void)
3554{ 3554{
3555 int err; 3555 int i, err;
3556 unsigned short address; 3556 bool found = false;
3557 int address;
3557 struct resource res; 3558 struct resource res;
3558 struct nct6775_sio_data sio_data; 3559 struct nct6775_sio_data sio_data;
3560 int sioaddr[2] = { 0x2e, 0x4e };
3561
3562 err = platform_driver_register(&nct6775_driver);
3563 if (err)
3564 return err;
3559 3565
3560 /* 3566 /*
3561 * initialize sio_data->kind and sio_data->sioreg. 3567 * initialize sio_data->kind and sio_data->sioreg.
@@ -3564,64 +3570,71 @@ static int __init sensors_nct6775_init(void)
3564 * driver will probe 0x2e and 0x4e and auto-detect the presence of a 3570 * driver will probe 0x2e and 0x4e and auto-detect the presence of a
3565 * nct6775 hardware monitor, and call probe() 3571 * nct6775 hardware monitor, and call probe()
3566 */ 3572 */
3567 if (nct6775_find(0x2e, &address, &sio_data) && 3573 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
3568 nct6775_find(0x4e, &address, &sio_data)) 3574 address = nct6775_find(sioaddr[i], &sio_data);
3569 return -ENODEV; 3575 if (address <= 0)
3570 3576 continue;
3571 err = platform_driver_register(&nct6775_driver);
3572 if (err)
3573 goto exit;
3574 3577
3575 pdev = platform_device_alloc(DRVNAME, address); 3578 found = true;
3576 if (!pdev) {
3577 err = -ENOMEM;
3578 pr_err("Device allocation failed\n");
3579 goto exit_unregister;
3580 }
3581 3579
3582 err = platform_device_add_data(pdev, &sio_data, 3580 pdev[i] = platform_device_alloc(DRVNAME, address);
3583 sizeof(struct nct6775_sio_data)); 3581 if (!pdev[i]) {
3584 if (err) { 3582 err = -ENOMEM;
3585 pr_err("Platform data allocation failed\n"); 3583 goto exit_device_put;
3586 goto exit_device_put; 3584 }
3587 }
3588 3585
3589 memset(&res, 0, sizeof(res)); 3586 err = platform_device_add_data(pdev[i], &sio_data,
3590 res.name = DRVNAME; 3587 sizeof(struct nct6775_sio_data));
3591 res.start = address + IOREGION_OFFSET; 3588 if (err)
3592 res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1; 3589 goto exit_device_put;
3593 res.flags = IORESOURCE_IO; 3590
3591 memset(&res, 0, sizeof(res));
3592 res.name = DRVNAME;
3593 res.start = address + IOREGION_OFFSET;
3594 res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
3595 res.flags = IORESOURCE_IO;
3596
3597 err = acpi_check_resource_conflict(&res);
3598 if (err) {
3599 platform_device_put(pdev[i]);
3600 pdev[i] = NULL;
3601 continue;
3602 }
3594 3603
3595 err = acpi_check_resource_conflict(&res); 3604 err = platform_device_add_resources(pdev[i], &res, 1);
3596 if (err) 3605 if (err)
3597 goto exit_device_put; 3606 goto exit_device_put;
3598 3607
3599 err = platform_device_add_resources(pdev, &res, 1); 3608 /* platform_device_add calls probe() */
3600 if (err) { 3609 err = platform_device_add(pdev[i]);
3601 pr_err("Device resource addition failed (%d)\n", err); 3610 if (err)
3602 goto exit_device_put; 3611 goto exit_device_put;
3603 } 3612 }
3604 3613 if (!found) {
3605 /* platform_device_add calls probe() */ 3614 err = -ENODEV;
3606 err = platform_device_add(pdev); 3615 goto exit_unregister;
3607 if (err) {
3608 pr_err("Device addition failed (%d)\n", err);
3609 goto exit_device_put;
3610 } 3616 }
3611 3617
3612 return 0; 3618 return 0;
3613 3619
3614exit_device_put: 3620exit_device_put:
3615 platform_device_put(pdev); 3621 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
3622 if (pdev[i])
3623 platform_device_put(pdev[i]);
3624 }
3616exit_unregister: 3625exit_unregister:
3617 platform_driver_unregister(&nct6775_driver); 3626 platform_driver_unregister(&nct6775_driver);
3618exit:
3619 return err; 3627 return err;
3620} 3628}
3621 3629
3622static void __exit sensors_nct6775_exit(void) 3630static void __exit sensors_nct6775_exit(void)
3623{ 3631{
3624 platform_device_unregister(pdev); 3632 int i;
3633
3634 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
3635 if (pdev[i])
3636 platform_device_unregister(pdev[i]);
3637 }
3625 platform_driver_unregister(&nct6775_driver); 3638 platform_driver_unregister(&nct6775_driver);
3626} 3639}
3627 3640