diff options
author | Guenter Roeck <linux@roeck-us.net> | 2013-04-05 10:35:25 -0400 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2013-08-12 01:10:39 -0400 |
commit | 698a7c24a5447ffd940bfc9f5e6e8448d836a2b4 (patch) | |
tree | 5aff6d30fdaac32a3412acdf1c9e241afd166056 /drivers/hwmon/nct6775.c | |
parent | f73cf632dfb43d6236210aa38038cc91fd053ff6 (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.c | 113 |
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 */ |
3487 | static int __init nct6775_find(int sioaddr, unsigned short *addr, | 3487 | static 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 | */ |
3551 | static struct platform_device *pdev; | 3551 | static struct platform_device *pdev[2]; |
3552 | 3552 | ||
3553 | static int __init sensors_nct6775_init(void) | 3553 | static 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 | ||
3614 | exit_device_put: | 3620 | exit_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 | } | ||
3616 | exit_unregister: | 3625 | exit_unregister: |
3617 | platform_driver_unregister(&nct6775_driver); | 3626 | platform_driver_unregister(&nct6775_driver); |
3618 | exit: | ||
3619 | return err; | 3627 | return err; |
3620 | } | 3628 | } |
3621 | 3629 | ||
3622 | static void __exit sensors_nct6775_exit(void) | 3630 | static 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 | ||