Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  AMD K7 Powernow driver.
0004  *  (C) 2003 Dave Jones on behalf of SuSE Labs.
0005  *
0006  *  Based upon datasheets & sample CPUs kindly provided by AMD.
0007  *
0008  * Errata 5:
0009  *  CPU may fail to execute a FID/VID change in presence of interrupt.
0010  *  - We cli/sti on stepping A0 CPUs around the FID/VID transition.
0011  * Errata 15:
0012  *  CPU with half frequency multipliers may hang upon wakeup from disconnect.
0013  *  - We disable half multipliers if ACPI is used on A0 stepping CPUs.
0014  */
0015 
0016 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0017 
0018 #include <linux/kernel.h>
0019 #include <linux/module.h>
0020 #include <linux/moduleparam.h>
0021 #include <linux/init.h>
0022 #include <linux/cpufreq.h>
0023 #include <linux/slab.h>
0024 #include <linux/string.h>
0025 #include <linux/dmi.h>
0026 #include <linux/timex.h>
0027 #include <linux/io.h>
0028 
0029 #include <asm/timer.h>      /* Needed for recalibrate_cpu_khz() */
0030 #include <asm/msr.h>
0031 #include <asm/cpu_device_id.h>
0032 
0033 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
0034 #include <linux/acpi.h>
0035 #include <acpi/processor.h>
0036 #endif
0037 
0038 #include "powernow-k7.h"
0039 
0040 struct psb_s {
0041     u8 signature[10];
0042     u8 tableversion;
0043     u8 flags;
0044     u16 settlingtime;
0045     u8 reserved1;
0046     u8 numpst;
0047 };
0048 
0049 struct pst_s {
0050     u32 cpuid;
0051     u8 fsbspeed;
0052     u8 maxfid;
0053     u8 startvid;
0054     u8 numpstates;
0055 };
0056 
0057 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
0058 union powernow_acpi_control_t {
0059     struct {
0060         unsigned long fid:5,
0061             vid:5,
0062             sgtc:20,
0063             res1:2;
0064     } bits;
0065     unsigned long val;
0066 };
0067 #endif
0068 
0069 /* divide by 1000 to get VCore voltage in V. */
0070 static const int mobile_vid_table[32] = {
0071     2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,
0072     1600, 1550, 1500, 1450, 1400, 1350, 1300, 0,
0073     1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100,
0074     1075, 1050, 1025, 1000, 975, 950, 925, 0,
0075 };
0076 
0077 /* divide by 10 to get FID. */
0078 static const int fid_codes[32] = {
0079     110, 115, 120, 125, 50, 55, 60, 65,
0080     70, 75, 80, 85, 90, 95, 100, 105,
0081     30, 190, 40, 200, 130, 135, 140, 210,
0082     150, 225, 160, 165, 170, 180, -1, -1,
0083 };
0084 
0085 /* This parameter is used in order to force ACPI instead of legacy method for
0086  * configuration purpose.
0087  */
0088 
0089 static int acpi_force;
0090 
0091 static struct cpufreq_frequency_table *powernow_table;
0092 
0093 static unsigned int can_scale_bus;
0094 static unsigned int can_scale_vid;
0095 static unsigned int minimum_speed = -1;
0096 static unsigned int maximum_speed;
0097 static unsigned int number_scales;
0098 static unsigned int fsb;
0099 static unsigned int latency;
0100 static char have_a0;
0101 
0102 static int check_fsb(unsigned int fsbspeed)
0103 {
0104     int delta;
0105     unsigned int f = fsb / 1000;
0106 
0107     delta = (fsbspeed > f) ? fsbspeed - f : f - fsbspeed;
0108     return delta < 5;
0109 }
0110 
0111 static const struct x86_cpu_id powernow_k7_cpuids[] = {
0112     X86_MATCH_VENDOR_FAM(AMD, 6, NULL),
0113     {}
0114 };
0115 MODULE_DEVICE_TABLE(x86cpu, powernow_k7_cpuids);
0116 
0117 static int check_powernow(void)
0118 {
0119     struct cpuinfo_x86 *c = &cpu_data(0);
0120     unsigned int maxei, eax, ebx, ecx, edx;
0121 
0122     if (!x86_match_cpu(powernow_k7_cpuids))
0123         return 0;
0124 
0125     /* Get maximum capabilities */
0126     maxei = cpuid_eax(0x80000000);
0127     if (maxei < 0x80000007) {   /* Any powernow info ? */
0128 #ifdef MODULE
0129         pr_info("No powernow capabilities detected\n");
0130 #endif
0131         return 0;
0132     }
0133 
0134     if ((c->x86_model == 6) && (c->x86_stepping == 0)) {
0135         pr_info("K7 660[A0] core detected, enabling errata workarounds\n");
0136         have_a0 = 1;
0137     }
0138 
0139     cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
0140 
0141     /* Check we can actually do something before we say anything.*/
0142     if (!(edx & (1 << 1 | 1 << 2)))
0143         return 0;
0144 
0145     pr_info("PowerNOW! Technology present. Can scale: ");
0146 
0147     if (edx & 1 << 1) {
0148         pr_cont("frequency");
0149         can_scale_bus = 1;
0150     }
0151 
0152     if ((edx & (1 << 1 | 1 << 2)) == 0x6)
0153         pr_cont(" and ");
0154 
0155     if (edx & 1 << 2) {
0156         pr_cont("voltage");
0157         can_scale_vid = 1;
0158     }
0159 
0160     pr_cont("\n");
0161     return 1;
0162 }
0163 
0164 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
0165 static void invalidate_entry(unsigned int entry)
0166 {
0167     powernow_table[entry].frequency = CPUFREQ_ENTRY_INVALID;
0168 }
0169 #endif
0170 
0171 static int get_ranges(unsigned char *pst)
0172 {
0173     unsigned int j;
0174     unsigned int speed;
0175     u8 fid, vid;
0176 
0177     powernow_table = kzalloc((sizeof(*powernow_table) *
0178                 (number_scales + 1)), GFP_KERNEL);
0179     if (!powernow_table)
0180         return -ENOMEM;
0181 
0182     for (j = 0 ; j < number_scales; j++) {
0183         fid = *pst++;
0184 
0185         powernow_table[j].frequency = (fsb * fid_codes[fid]) / 10;
0186         powernow_table[j].driver_data = fid; /* lower 8 bits */
0187 
0188         speed = powernow_table[j].frequency;
0189 
0190         if ((fid_codes[fid] % 10) == 5) {
0191 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
0192             if (have_a0 == 1)
0193                 invalidate_entry(j);
0194 #endif
0195         }
0196 
0197         if (speed < minimum_speed)
0198             minimum_speed = speed;
0199         if (speed > maximum_speed)
0200             maximum_speed = speed;
0201 
0202         vid = *pst++;
0203         powernow_table[j].driver_data |= (vid << 8); /* upper 8 bits */
0204 
0205         pr_debug("   FID: 0x%x (%d.%dx [%dMHz])  "
0206              "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
0207              fid_codes[fid] % 10, speed/1000, vid,
0208              mobile_vid_table[vid]/1000,
0209              mobile_vid_table[vid]%1000);
0210     }
0211     powernow_table[number_scales].frequency = CPUFREQ_TABLE_END;
0212     powernow_table[number_scales].driver_data = 0;
0213 
0214     return 0;
0215 }
0216 
0217 
0218 static void change_FID(int fid)
0219 {
0220     union msr_fidvidctl fidvidctl;
0221 
0222     rdmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
0223     if (fidvidctl.bits.FID != fid) {
0224         fidvidctl.bits.SGTC = latency;
0225         fidvidctl.bits.FID = fid;
0226         fidvidctl.bits.VIDC = 0;
0227         fidvidctl.bits.FIDC = 1;
0228         wrmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
0229     }
0230 }
0231 
0232 
0233 static void change_VID(int vid)
0234 {
0235     union msr_fidvidctl fidvidctl;
0236 
0237     rdmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
0238     if (fidvidctl.bits.VID != vid) {
0239         fidvidctl.bits.SGTC = latency;
0240         fidvidctl.bits.VID = vid;
0241         fidvidctl.bits.FIDC = 0;
0242         fidvidctl.bits.VIDC = 1;
0243         wrmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
0244     }
0245 }
0246 
0247 
0248 static int powernow_target(struct cpufreq_policy *policy, unsigned int index)
0249 {
0250     u8 fid, vid;
0251     struct cpufreq_freqs freqs;
0252     union msr_fidvidstatus fidvidstatus;
0253     int cfid;
0254 
0255     /* fid are the lower 8 bits of the index we stored into
0256      * the cpufreq frequency table in powernow_decode_bios,
0257      * vid are the upper 8 bits.
0258      */
0259 
0260     fid = powernow_table[index].driver_data & 0xFF;
0261     vid = (powernow_table[index].driver_data & 0xFF00) >> 8;
0262 
0263     rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val);
0264     cfid = fidvidstatus.bits.CFID;
0265     freqs.old = fsb * fid_codes[cfid] / 10;
0266 
0267     freqs.new = powernow_table[index].frequency;
0268 
0269     /* Now do the magic poking into the MSRs.  */
0270 
0271     if (have_a0 == 1)   /* A0 errata 5 */
0272         local_irq_disable();
0273 
0274     if (freqs.old > freqs.new) {
0275         /* Going down, so change FID first */
0276         change_FID(fid);
0277         change_VID(vid);
0278     } else {
0279         /* Going up, so change VID first */
0280         change_VID(vid);
0281         change_FID(fid);
0282     }
0283 
0284 
0285     if (have_a0 == 1)
0286         local_irq_enable();
0287 
0288     return 0;
0289 }
0290 
0291 
0292 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
0293 
0294 static struct acpi_processor_performance *acpi_processor_perf;
0295 
0296 static int powernow_acpi_init(void)
0297 {
0298     int i;
0299     int retval = 0;
0300     union powernow_acpi_control_t pc;
0301 
0302     if (acpi_processor_perf != NULL && powernow_table != NULL) {
0303         retval = -EINVAL;
0304         goto err0;
0305     }
0306 
0307     acpi_processor_perf = kzalloc(sizeof(*acpi_processor_perf), GFP_KERNEL);
0308     if (!acpi_processor_perf) {
0309         retval = -ENOMEM;
0310         goto err0;
0311     }
0312 
0313     if (!zalloc_cpumask_var(&acpi_processor_perf->shared_cpu_map,
0314                                 GFP_KERNEL)) {
0315         retval = -ENOMEM;
0316         goto err05;
0317     }
0318 
0319     if (acpi_processor_register_performance(acpi_processor_perf, 0)) {
0320         retval = -EIO;
0321         goto err1;
0322     }
0323 
0324     if (acpi_processor_perf->control_register.space_id !=
0325             ACPI_ADR_SPACE_FIXED_HARDWARE) {
0326         retval = -ENODEV;
0327         goto err2;
0328     }
0329 
0330     if (acpi_processor_perf->status_register.space_id !=
0331             ACPI_ADR_SPACE_FIXED_HARDWARE) {
0332         retval = -ENODEV;
0333         goto err2;
0334     }
0335 
0336     number_scales = acpi_processor_perf->state_count;
0337 
0338     if (number_scales < 2) {
0339         retval = -ENODEV;
0340         goto err2;
0341     }
0342 
0343     powernow_table = kzalloc((sizeof(*powernow_table) *
0344                 (number_scales + 1)), GFP_KERNEL);
0345     if (!powernow_table) {
0346         retval = -ENOMEM;
0347         goto err2;
0348     }
0349 
0350     pc.val = (unsigned long) acpi_processor_perf->states[0].control;
0351     for (i = 0; i < number_scales; i++) {
0352         u8 fid, vid;
0353         struct acpi_processor_px *state =
0354             &acpi_processor_perf->states[i];
0355         unsigned int speed, speed_mhz;
0356 
0357         pc.val = (unsigned long) state->control;
0358         pr_debug("acpi:  P%d: %d MHz %d mW %d uS control %08x SGTC %d\n",
0359              i,
0360              (u32) state->core_frequency,
0361              (u32) state->power,
0362              (u32) state->transition_latency,
0363              (u32) state->control,
0364              pc.bits.sgtc);
0365 
0366         vid = pc.bits.vid;
0367         fid = pc.bits.fid;
0368 
0369         powernow_table[i].frequency = fsb * fid_codes[fid] / 10;
0370         powernow_table[i].driver_data = fid; /* lower 8 bits */
0371         powernow_table[i].driver_data |= (vid << 8); /* upper 8 bits */
0372 
0373         speed = powernow_table[i].frequency;
0374         speed_mhz = speed / 1000;
0375 
0376         /* processor_perflib will multiply the MHz value by 1000 to
0377          * get a KHz value (e.g. 1266000). However, powernow-k7 works
0378          * with true KHz values (e.g. 1266768). To ensure that all
0379          * powernow frequencies are available, we must ensure that
0380          * ACPI doesn't restrict them, so we round up the MHz value
0381          * to ensure that perflib's computed KHz value is greater than
0382          * or equal to powernow's KHz value.
0383          */
0384         if (speed % 1000 > 0)
0385             speed_mhz++;
0386 
0387         if ((fid_codes[fid] % 10) == 5) {
0388             if (have_a0 == 1)
0389                 invalidate_entry(i);
0390         }
0391 
0392         pr_debug("   FID: 0x%x (%d.%dx [%dMHz])  "
0393              "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
0394              fid_codes[fid] % 10, speed_mhz, vid,
0395              mobile_vid_table[vid]/1000,
0396              mobile_vid_table[vid]%1000);
0397 
0398         if (state->core_frequency != speed_mhz) {
0399             state->core_frequency = speed_mhz;
0400             pr_debug("   Corrected ACPI frequency to %d\n",
0401                 speed_mhz);
0402         }
0403 
0404         if (latency < pc.bits.sgtc)
0405             latency = pc.bits.sgtc;
0406 
0407         if (speed < minimum_speed)
0408             minimum_speed = speed;
0409         if (speed > maximum_speed)
0410             maximum_speed = speed;
0411     }
0412 
0413     powernow_table[i].frequency = CPUFREQ_TABLE_END;
0414     powernow_table[i].driver_data = 0;
0415 
0416     /* notify BIOS that we exist */
0417     acpi_processor_notify_smm(THIS_MODULE);
0418 
0419     return 0;
0420 
0421 err2:
0422     acpi_processor_unregister_performance(0);
0423 err1:
0424     free_cpumask_var(acpi_processor_perf->shared_cpu_map);
0425 err05:
0426     kfree(acpi_processor_perf);
0427 err0:
0428     pr_warn("ACPI perflib can not be used on this platform\n");
0429     acpi_processor_perf = NULL;
0430     return retval;
0431 }
0432 #else
0433 static int powernow_acpi_init(void)
0434 {
0435     pr_info("no support for ACPI processor found - please recompile your kernel with ACPI processor\n");
0436     return -EINVAL;
0437 }
0438 #endif
0439 
0440 static void print_pst_entry(struct pst_s *pst, unsigned int j)
0441 {
0442     pr_debug("PST:%d (@%p)\n", j, pst);
0443     pr_debug(" cpuid: 0x%x  fsb: %d  maxFID: 0x%x  startvid: 0x%x\n",
0444         pst->cpuid, pst->fsbspeed, pst->maxfid, pst->startvid);
0445 }
0446 
0447 static int powernow_decode_bios(int maxfid, int startvid)
0448 {
0449     struct psb_s *psb;
0450     struct pst_s *pst;
0451     unsigned int i, j;
0452     unsigned char *p;
0453     unsigned int etuple;
0454     unsigned int ret;
0455 
0456     etuple = cpuid_eax(0x80000001);
0457 
0458     for (i = 0xC0000; i < 0xffff0 ; i += 16) {
0459 
0460         p = phys_to_virt(i);
0461 
0462         if (memcmp(p, "AMDK7PNOW!",  10) == 0) {
0463             pr_debug("Found PSB header at %p\n", p);
0464             psb = (struct psb_s *) p;
0465             pr_debug("Table version: 0x%x\n", psb->tableversion);
0466             if (psb->tableversion != 0x12) {
0467                 pr_info("Sorry, only v1.2 tables supported right now\n");
0468                 return -ENODEV;
0469             }
0470 
0471             pr_debug("Flags: 0x%x\n", psb->flags);
0472             if ((psb->flags & 1) == 0)
0473                 pr_debug("Mobile voltage regulator\n");
0474             else
0475                 pr_debug("Desktop voltage regulator\n");
0476 
0477             latency = psb->settlingtime;
0478             if (latency < 100) {
0479                 pr_info("BIOS set settling time to %d microseconds. Should be at least 100. Correcting.\n",
0480                     latency);
0481                 latency = 100;
0482             }
0483             pr_debug("Settling Time: %d microseconds.\n",
0484                     psb->settlingtime);
0485             pr_debug("Has %d PST tables. (Only dumping ones "
0486                     "relevant to this CPU).\n",
0487                     psb->numpst);
0488 
0489             p += sizeof(*psb);
0490 
0491             pst = (struct pst_s *) p;
0492 
0493             for (j = 0; j < psb->numpst; j++) {
0494                 pst = (struct pst_s *) p;
0495                 number_scales = pst->numpstates;
0496 
0497                 if ((etuple == pst->cpuid) &&
0498                     check_fsb(pst->fsbspeed) &&
0499                     (maxfid == pst->maxfid) &&
0500                     (startvid == pst->startvid)) {
0501                     print_pst_entry(pst, j);
0502                     p = (char *)pst + sizeof(*pst);
0503                     ret = get_ranges(p);
0504                     return ret;
0505                 } else {
0506                     unsigned int k;
0507                     p = (char *)pst + sizeof(*pst);
0508                     for (k = 0; k < number_scales; k++)
0509                         p += 2;
0510                 }
0511             }
0512             pr_info("No PST tables match this cpuid (0x%x)\n",
0513                 etuple);
0514             pr_info("This is indicative of a broken BIOS\n");
0515 
0516             return -EINVAL;
0517         }
0518         p++;
0519     }
0520 
0521     return -ENODEV;
0522 }
0523 
0524 
0525 /*
0526  * We use the fact that the bus frequency is somehow
0527  * a multiple of 100000/3 khz, then we compute sgtc according
0528  * to this multiple.
0529  * That way, we match more how AMD thinks all of that work.
0530  * We will then get the same kind of behaviour already tested under
0531  * the "well-known" other OS.
0532  */
0533 static int fixup_sgtc(void)
0534 {
0535     unsigned int sgtc;
0536     unsigned int m;
0537 
0538     m = fsb / 3333;
0539     if ((m % 10) >= 5)
0540         m += 5;
0541 
0542     m /= 10;
0543 
0544     sgtc = 100 * m * latency;
0545     sgtc = sgtc / 3;
0546     if (sgtc > 0xfffff) {
0547         pr_warn("SGTC too large %d\n", sgtc);
0548         sgtc = 0xfffff;
0549     }
0550     return sgtc;
0551 }
0552 
0553 static unsigned int powernow_get(unsigned int cpu)
0554 {
0555     union msr_fidvidstatus fidvidstatus;
0556     unsigned int cfid;
0557 
0558     if (cpu)
0559         return 0;
0560     rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val);
0561     cfid = fidvidstatus.bits.CFID;
0562 
0563     return fsb * fid_codes[cfid] / 10;
0564 }
0565 
0566 
0567 static int acer_cpufreq_pst(const struct dmi_system_id *d)
0568 {
0569     pr_warn("%s laptop with broken PST tables in BIOS detected\n",
0570         d->ident);
0571     pr_warn("You need to downgrade to 3A21 (09/09/2002), or try a newer BIOS than 3A71 (01/20/2003)\n");
0572     pr_warn("cpufreq scaling has been disabled as a result of this\n");
0573     return 0;
0574 }
0575 
0576 /*
0577  * Some Athlon laptops have really fucked PST tables.
0578  * A BIOS update is all that can save them.
0579  * Mention this, and disable cpufreq.
0580  */
0581 static const struct dmi_system_id powernow_dmi_table[] = {
0582     {
0583         .callback = acer_cpufreq_pst,
0584         .ident = "Acer Aspire",
0585         .matches = {
0586             DMI_MATCH(DMI_SYS_VENDOR, "Insyde Software"),
0587             DMI_MATCH(DMI_BIOS_VERSION, "3A71"),
0588         },
0589     },
0590     { }
0591 };
0592 
0593 static int powernow_cpu_init(struct cpufreq_policy *policy)
0594 {
0595     union msr_fidvidstatus fidvidstatus;
0596     int result;
0597 
0598     if (policy->cpu != 0)
0599         return -ENODEV;
0600 
0601     rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val);
0602 
0603     recalibrate_cpu_khz();
0604 
0605     fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID];
0606     if (!fsb) {
0607         pr_warn("can not determine bus frequency\n");
0608         return -EINVAL;
0609     }
0610     pr_debug("FSB: %3dMHz\n", fsb/1000);
0611 
0612     if (dmi_check_system(powernow_dmi_table) || acpi_force) {
0613         pr_info("PSB/PST known to be broken - trying ACPI instead\n");
0614         result = powernow_acpi_init();
0615     } else {
0616         result = powernow_decode_bios(fidvidstatus.bits.MFID,
0617                 fidvidstatus.bits.SVID);
0618         if (result) {
0619             pr_info("Trying ACPI perflib\n");
0620             maximum_speed = 0;
0621             minimum_speed = -1;
0622             latency = 0;
0623             result = powernow_acpi_init();
0624             if (result) {
0625                 pr_info("ACPI and legacy methods failed\n");
0626             }
0627         } else {
0628             /* SGTC use the bus clock as timer */
0629             latency = fixup_sgtc();
0630             pr_info("SGTC: %d\n", latency);
0631         }
0632     }
0633 
0634     if (result)
0635         return result;
0636 
0637     pr_info("Minimum speed %d MHz - Maximum speed %d MHz\n",
0638         minimum_speed/1000, maximum_speed/1000);
0639 
0640     policy->cpuinfo.transition_latency =
0641         cpufreq_scale(2000000UL, fsb, latency);
0642     policy->freq_table = powernow_table;
0643 
0644     return 0;
0645 }
0646 
0647 static int powernow_cpu_exit(struct cpufreq_policy *policy)
0648 {
0649 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
0650     if (acpi_processor_perf) {
0651         acpi_processor_unregister_performance(0);
0652         free_cpumask_var(acpi_processor_perf->shared_cpu_map);
0653         kfree(acpi_processor_perf);
0654     }
0655 #endif
0656 
0657     kfree(powernow_table);
0658     return 0;
0659 }
0660 
0661 static struct cpufreq_driver powernow_driver = {
0662     .verify     = cpufreq_generic_frequency_table_verify,
0663     .target_index   = powernow_target,
0664     .get        = powernow_get,
0665 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
0666     .bios_limit = acpi_processor_get_bios_limit,
0667 #endif
0668     .init       = powernow_cpu_init,
0669     .exit       = powernow_cpu_exit,
0670     .name       = "powernow-k7",
0671     .attr       = cpufreq_generic_attr,
0672 };
0673 
0674 static int __init powernow_init(void)
0675 {
0676     if (check_powernow() == 0)
0677         return -ENODEV;
0678     return cpufreq_register_driver(&powernow_driver);
0679 }
0680 
0681 
0682 static void __exit powernow_exit(void)
0683 {
0684     cpufreq_unregister_driver(&powernow_driver);
0685 }
0686 
0687 module_param(acpi_force,  int, 0444);
0688 MODULE_PARM_DESC(acpi_force, "Force ACPI to be used.");
0689 
0690 MODULE_AUTHOR("Dave Jones");
0691 MODULE_DESCRIPTION("Powernow driver for AMD K7 processors.");
0692 MODULE_LICENSE("GPL");
0693 
0694 late_initcall(powernow_init);
0695 module_exit(powernow_exit);
0696