diff options
| author | Rafał Bilski <rafalbilski@interia.pl> | 2007-02-04 12:43:12 -0500 |
|---|---|---|
| committer | Dave Jones <davej@redhat.com> | 2007-02-04 18:09:19 -0500 |
| commit | 786f46b262cb7a491f4b144e42f076d5a1ef8eef (patch) | |
| tree | 8b8c95679d18f9b1966484bd274d35108d88d607 | |
| parent | 46ef955f5c9de0507859a3f9a92989b7425b73cc (diff) | |
[CPUFREQ] Longhaul - Add VT8235 support
I don't know why it is working and how, but it is working. On my
Epia transition time is by default set to 100us. I'm changing it to
200us. After that I can change frequency from min (x4.0) to max (x7.5)
without lockup. Many times.
There is a paranoid check at a beginning of a patch. Probably dead
code, but I don't have better ideas for CL10000 case at the moment.
Only way to to detect broken chip seems to be looking in log for
spurious interrupts.
Signed-off-by: Rafal Bilski <rafalbilski@interia.pl>
Signed-off-by: Dave Jones <davej@redhat.com>
| -rw-r--r-- | arch/i386/kernel/cpu/cpufreq/longhaul.c | 62 |
1 files changed, 50 insertions, 12 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index 8b5ad308d656..98fbe28affff 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c | |||
| @@ -56,6 +56,7 @@ | |||
| 56 | /* Flags */ | 56 | /* Flags */ |
| 57 | #define USE_ACPI_C3 (1 << 1) | 57 | #define USE_ACPI_C3 (1 << 1) |
| 58 | #define USE_NORTHBRIDGE (1 << 2) | 58 | #define USE_NORTHBRIDGE (1 << 2) |
| 59 | #define USE_VT8235 (1 << 3) | ||
| 59 | 60 | ||
| 60 | static int cpu_model; | 61 | static int cpu_model; |
| 61 | static unsigned int numscales=16; | 62 | static unsigned int numscales=16; |
| @@ -544,20 +545,50 @@ static int enable_arbiter_disable(void) | |||
| 544 | if (dev != NULL) { | 545 | if (dev != NULL) { |
| 545 | /* Enable access to port 0x22 */ | 546 | /* Enable access to port 0x22 */ |
| 546 | pci_read_config_byte(dev, reg, &pci_cmd); | 547 | pci_read_config_byte(dev, reg, &pci_cmd); |
| 547 | if ( !(pci_cmd & 1<<7) ) { | 548 | if (!(pci_cmd & 1<<7)) { |
| 548 | pci_cmd |= 1<<7; | 549 | pci_cmd |= 1<<7; |
| 549 | pci_write_config_byte(dev, reg, pci_cmd); | 550 | pci_write_config_byte(dev, reg, pci_cmd); |
| 551 | pci_read_config_byte(dev, reg, &pci_cmd); | ||
| 552 | if (!(pci_cmd & 1<<7)) { | ||
| 553 | printk(KERN_ERR PFX | ||
| 554 | "Can't enable access to port 0x22.\n"); | ||
| 555 | return 0; | ||
| 556 | } | ||
| 550 | } | 557 | } |
| 551 | return 1; | 558 | return 1; |
| 552 | } | 559 | } |
| 553 | return 0; | 560 | return 0; |
| 554 | } | 561 | } |
| 555 | 562 | ||
| 563 | static int longhaul_setup_vt8235(void) | ||
| 564 | { | ||
| 565 | struct pci_dev *dev; | ||
| 566 | u8 pci_cmd; | ||
| 567 | |||
| 568 | /* Find VT8235 southbridge */ | ||
| 569 | dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL); | ||
| 570 | if (dev != NULL) { | ||
| 571 | /* Set transition time to max */ | ||
| 572 | pci_read_config_byte(dev, 0xec, &pci_cmd); | ||
| 573 | pci_cmd &= ~(1 << 2); | ||
| 574 | pci_write_config_byte(dev, 0xec, pci_cmd); | ||
| 575 | pci_read_config_byte(dev, 0xe4, &pci_cmd); | ||
| 576 | pci_cmd &= ~(1 << 7); | ||
| 577 | pci_write_config_byte(dev, 0xe4, pci_cmd); | ||
| 578 | pci_read_config_byte(dev, 0xe5, &pci_cmd); | ||
| 579 | pci_cmd |= 1 << 7; | ||
| 580 | pci_write_config_byte(dev, 0xe5, pci_cmd); | ||
| 581 | return 1; | ||
| 582 | } | ||
| 583 | return 0; | ||
| 584 | } | ||
| 585 | |||
| 556 | static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | 586 | static int __init longhaul_cpu_init(struct cpufreq_policy *policy) |
| 557 | { | 587 | { |
| 558 | struct cpuinfo_x86 *c = cpu_data; | 588 | struct cpuinfo_x86 *c = cpu_data; |
| 559 | char *cpuname=NULL; | 589 | char *cpuname=NULL; |
| 560 | int ret; | 590 | int ret; |
| 591 | int vt8235_present; | ||
| 561 | 592 | ||
| 562 | /* Check what we have on this motherboard */ | 593 | /* Check what we have on this motherboard */ |
| 563 | switch (c->x86_model) { | 594 | switch (c->x86_model) { |
| @@ -641,12 +672,16 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | |||
| 641 | break; | 672 | break; |
| 642 | }; | 673 | }; |
| 643 | 674 | ||
| 675 | /* Doesn't hurt */ | ||
| 676 | vt8235_present = longhaul_setup_vt8235(); | ||
| 677 | |||
| 644 | /* Find ACPI data for processor */ | 678 | /* Find ACPI data for processor */ |
| 645 | acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, | 679 | acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, |
| 646 | &longhaul_walk_callback, NULL, (void *)&pr); | 680 | ACPI_UINT32_MAX, &longhaul_walk_callback, |
| 681 | NULL, (void *)&pr); | ||
| 647 | 682 | ||
| 648 | /* Check ACPI support for C3 state */ | 683 | /* Check ACPI support for C3 state */ |
| 649 | if ((pr != NULL) && (longhaul_version == TYPE_POWERSAVER)) { | 684 | if (pr != NULL && longhaul_version == TYPE_POWERSAVER) { |
| 650 | cx = &pr->power.states[ACPI_STATE_C3]; | 685 | cx = &pr->power.states[ACPI_STATE_C3]; |
| 651 | if (cx->address > 0 && cx->latency <= 1000) { | 686 | if (cx->address > 0 && cx->latency <= 1000) { |
| 652 | longhaul_flags |= USE_ACPI_C3; | 687 | longhaul_flags |= USE_ACPI_C3; |
| @@ -658,8 +693,11 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | |||
| 658 | longhaul_flags |= USE_NORTHBRIDGE; | 693 | longhaul_flags |= USE_NORTHBRIDGE; |
| 659 | goto print_support_type; | 694 | goto print_support_type; |
| 660 | } | 695 | } |
| 661 | 696 | /* Use VT8235 southbridge if present */ | |
| 662 | /* No ACPI C3 or we can't use it */ | 697 | if (longhaul_version == TYPE_POWERSAVER && vt8235_present) { |
| 698 | longhaul_flags |= USE_VT8235; | ||
| 699 | goto print_support_type; | ||
| 700 | } | ||
| 663 | /* Check ACPI support for bus master arbiter disable */ | 701 | /* Check ACPI support for bus master arbiter disable */ |
| 664 | if ((pr == NULL) || !(pr->flags.bm_control)) { | 702 | if ((pr == NULL) || !(pr->flags.bm_control)) { |
| 665 | printk(KERN_ERR PFX | 703 | printk(KERN_ERR PFX |
| @@ -668,18 +706,18 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | |||
| 668 | } | 706 | } |
| 669 | 707 | ||
| 670 | print_support_type: | 708 | print_support_type: |
| 671 | if (!(longhaul_flags & USE_NORTHBRIDGE)) { | 709 | if (longhaul_flags & USE_NORTHBRIDGE) |
| 672 | printk (KERN_INFO PFX "Using ACPI support.\n"); | ||
| 673 | } else { | ||
| 674 | printk (KERN_INFO PFX "Using northbridge support.\n"); | 710 | printk (KERN_INFO PFX "Using northbridge support.\n"); |
| 675 | } | 711 | else if (longhaul_flags & USE_VT8235) |
| 712 | printk (KERN_INFO PFX "Using VT8235 support.\n"); | ||
| 713 | else | ||
| 714 | printk (KERN_INFO PFX "Using ACPI support.\n"); | ||
| 676 | 715 | ||
| 677 | ret = longhaul_get_ranges(); | 716 | ret = longhaul_get_ranges(); |
| 678 | if (ret != 0) | 717 | if (ret != 0) |
| 679 | return ret; | 718 | return ret; |
| 680 | 719 | ||
| 681 | if ((longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) && | 720 | if ((longhaul_version != TYPE_LONGHAUL_V1) && (scale_voltage != 0)) |
| 682 | (scale_voltage != 0)) | ||
| 683 | longhaul_setup_voltagescaling(); | 721 | longhaul_setup_voltagescaling(); |
| 684 | 722 | ||
| 685 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | 723 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; |
