| | 507 | static int |
|---|
| | 508 | w83792d_create_subclient(struct i2c_adapter *adapter, |
|---|
| | 509 | struct i2c_client *new_client, int addr, |
|---|
| | 510 | struct i2c_client **sub_cli) |
|---|
| | 511 | { |
|---|
| | 512 | int err; |
|---|
| | 513 | struct i2c_client *sub_client; |
|---|
| | 514 | |
|---|
| | 515 | (*sub_cli) = sub_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); |
|---|
| | 516 | if (!(sub_client)) { |
|---|
| | 517 | return -ENOMEM; |
|---|
| | 518 | } |
|---|
| | 519 | memset(sub_client, 0x00, sizeof(struct i2c_client)); |
|---|
| | 520 | sub_client->addr = 0x48 + addr; |
|---|
| | 521 | sub_client->data = NULL; |
|---|
| | 522 | sub_client->adapter = adapter; |
|---|
| | 523 | sub_client->driver = &w83792d_driver; |
|---|
| | 524 | sub_client->flags = 0; |
|---|
| | 525 | strcpy(sub_client->name, "w83792d subclient"); |
|---|
| | 526 | if ((err = i2c_attach_client(sub_client))) { |
|---|
| | 527 | printk(KERN_ERR "w83792: subclient registration " |
|---|
| | 528 | "at address 0x%x failed\n", sub_client->addr); |
|---|
| | 529 | kfree(sub_client); |
|---|
| | 530 | return err; |
|---|
| | 531 | } |
|---|
| | 532 | return 0; |
|---|
| | 533 | } |
|---|
| | 534 | |
|---|
| | 535 | static int |
|---|
| | 536 | w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind, |
|---|
| | 537 | struct i2c_client *new_client) |
|---|
| | 538 | { |
|---|
| | 539 | int i, id, err; |
|---|
| | 540 | u8 val; |
|---|
| | 541 | struct w83792d_data *data = new_client->data; |
|---|
| | 542 | |
|---|
| | 543 | data->lm75[0] = NULL; |
|---|
| | 544 | data->lm75[1] = NULL; |
|---|
| | 545 | |
|---|
| | 546 | id = i2c_adapter_id(adapter); |
|---|
| | 547 | if (force_subclients[0] == id && force_subclients[1] == address) { |
|---|
| | 548 | for (i = 2; i <= 3; i++) { |
|---|
| | 549 | if (force_subclients[i] < 0x48 || |
|---|
| | 550 | force_subclients[i] > 0x4f) { |
|---|
| | 551 | printk(KERN_ERR "w83792d: invalid subclient " |
|---|
| | 552 | "address %d; must be 0x48-0x4f\n", |
|---|
| | 553 | force_subclients[i]); |
|---|
| | 554 | err = -ENODEV; |
|---|
| | 555 | goto ERROR_SC_0; |
|---|
| | 556 | } |
|---|
| | 557 | } |
|---|
| | 558 | w83792d_write_value(new_client, W83792D_REG_I2C_SUBADDR, |
|---|
| | 559 | (force_subclients[2] & 0x07) | |
|---|
| | 560 | ((force_subclients[3] & 0x07) << 4)); |
|---|
| | 561 | } |
|---|
| | 562 | |
|---|
| | 563 | val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR); |
|---|
| | 564 | if (!(val & 0x08)) { |
|---|
| | 565 | err = w83792d_create_subclient(adapter, new_client, val & 0x7, |
|---|
| | 566 | &data->lm75[0]); |
|---|
| | 567 | if (err < 0) |
|---|
| | 568 | goto ERROR_SC_0; |
|---|
| | 569 | } |
|---|
| | 570 | if (!(val & 0x80)) { |
|---|
| | 571 | if ((data->lm75[0] != NULL) && |
|---|
| | 572 | ((val & 0x7) == ((val >> 4) & 0x7))) { |
|---|
| | 573 | printk(KERN_ERR "w83792d: duplicate addresses 0x%x, " |
|---|
| | 574 | "use force_subclient\n", data->lm75[0]->addr); |
|---|
| | 575 | err = -ENODEV; |
|---|
| | 576 | goto ERROR_SC_1; |
|---|
| | 577 | } |
|---|
| | 578 | err = w83792d_create_subclient(adapter, new_client, |
|---|
| | 579 | (val >> 4) & 0x7, &data->lm75[1]); |
|---|
| | 580 | if (err < 0) |
|---|
| | 581 | goto ERROR_SC_1; |
|---|
| | 582 | } |
|---|
| | 583 | |
|---|
| | 584 | return 0; |
|---|
| | 585 | |
|---|
| | 586 | /* Undo inits in case of errors */ |
|---|
| | 587 | |
|---|
| | 588 | ERROR_SC_1: |
|---|
| | 589 | if (data->lm75[0] != NULL) { |
|---|
| | 590 | i2c_detach_client(data->lm75[0]); |
|---|
| | 591 | kfree(data->lm75[0]); |
|---|
| | 592 | } |
|---|
| | 593 | ERROR_SC_0: |
|---|
| | 594 | return err; |
|---|
| | 595 | } |
|---|
| | 596 | |
|---|
| | 597 | |
|---|
| 621 | | |
|---|
| 622 | | /* attach secondary i2c lm75-like clients */ |
|---|
| 623 | | if (!(data->lm75 = kmalloc(2 * sizeof(struct i2c_client), |
|---|
| 624 | | GFP_KERNEL))) { |
|---|
| 625 | | err = -ENOMEM; |
|---|
| 626 | | goto ERROR2; |
|---|
| 627 | | } |
|---|
| 628 | | id = i2c_adapter_id(adapter); |
|---|
| 629 | | if(force_subclients[0] == id && force_subclients[1] == address) { |
|---|
| 630 | | if(force_subclients[2] < 0x48 || force_subclients[2] > 0x4b) { |
|---|
| 631 | | printk(KERN_ERR "w83792d.o: Invalid subclient address %d; must be 0x48-0x4b\n", |
|---|
| 632 | | force_subclients[2]); |
|---|
| 633 | | goto ERROR5; |
|---|
| 634 | | } |
|---|
| 635 | | if(force_subclients[3] < 0x4c || force_subclients[3] > 0x4f) { |
|---|
| 636 | | printk(KERN_ERR "w83792d.o: Invalid subclient address %d; must be 0x4c-0x4f\n", |
|---|
| 637 | | force_subclients[3]); |
|---|
| 638 | | goto ERROR5; |
|---|
| 639 | | } |
|---|
| 640 | | w83792d_write_value(new_client, |
|---|
| 641 | | W83792D_REG_I2C_SUBADDR, |
|---|
| 642 | | 0x40 | (force_subclients[2] & 0x03) | |
|---|
| 643 | | ((force_subclients[3] & 0x03) <<4)); |
|---|
| 644 | | data->lm75[0].addr = force_subclients[2]; |
|---|
| 645 | | data->lm75[1].addr = force_subclients[3]; |
|---|
| 646 | | } else { |
|---|
| 647 | | val1 = w83792d_read_value(new_client, |
|---|
| 648 | | W83792D_REG_I2C_SUBADDR); |
|---|
| 649 | | data->lm75[0].addr = 0x48 + (val1 & 0x07); |
|---|
| 650 | | data->lm75[1].addr = 0x48 + ((val1 >> 4) & 0x07); |
|---|
| 651 | | if (data->lm75[0].addr == data->lm75[1].addr) |
|---|
| 652 | | printk(KERN_WARNING "w83792d: Subclients have the same " |
|---|
| 653 | | "address (0x%02x)! Use force_subclients.\n", |
|---|
| 654 | | data->lm75[0].addr); |
|---|
| 655 | | } |
|---|
| 656 | | client_name = "W83792D subclient"; |
|---|
| 657 | | |
|---|
| 658 | | |
|---|
| 659 | | for (i = 0; i <= 1; i++) { |
|---|
| 660 | | data->lm75[i].data = NULL; /* store all data in w83792d */ |
|---|
| 661 | | data->lm75[i].adapter = adapter; |
|---|
| 662 | | data->lm75[i].driver = &w83792d_driver; |
|---|
| 663 | | data->lm75[i].flags = 0; |
|---|
| 664 | | strcpy(data->lm75[i].name, client_name); |
|---|
| 665 | | if ((err = i2c_attach_client(&(data->lm75[i])))) { |
|---|
| 666 | | printk(KERN_ERR "w83792d.o: Subclient %d registration at address 0x%x failed.\n", |
|---|
| 667 | | i, data->lm75[i].addr); |
|---|
| 668 | | if (i == 1) |
|---|
| 669 | | goto ERROR6; |
|---|
| 670 | | goto ERROR5; |
|---|
| 671 | | } |
|---|
| 672 | | } |
|---|
| | 712 | |
|---|
| | 713 | if ((err = w83792d_detect_subclients(adapter, address, |
|---|
| | 714 | kind, new_client))) |
|---|
| | 715 | goto ERROR2; |
|---|