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 /arch | |
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>
Diffstat (limited to 'arch')
-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; |