cpufreq之实例分析.

    xiaoxiao2026-04-16  0

    我们看一个注册cpufreq_register_driver 的例子.先看makefile。只要定义了 CONFIG_X86_CPUFREQ_NFORCE2。就会build 出cpufreq-nforce2.o,我们就以它为例 42 obj-$(CONFIG_X86_CPUFREQ_NFORCE2)       += cpufreq-nforce2.o 果然在init函数中调用cpufreq_register_driver 416 static int __init nforce2_init(void) 417 { 418         /* TODO: do we need to detect the processor? */ 419  420         /* detect chipset */ 421         if (nforce2_detect_chipset()) { 422                 pr_info("No nForce2 chipset\n"); 423                 return -ENODEV; 424         } 425  426         return cpufreq_register_driver(&nforce2_driver); 427 } 我们来看看nforce2_driver 370 static struct cpufreq_driver nforce2_driver = { 371         .name = "nforce2", 372         .verify = nforce2_verify, 373         .target = nforce2_target, 374         .get = nforce2_get, 375         .init = nforce2_cpu_init, 376         .exit = nforce2_cpu_exit, 377 }; 在使用中会调用__cpufreq_driver_target 来设定频率。这个函数target方法或者target_index 来将freq设定到cpu的寄存器中。对这点不明白可以参考前面的博文. 在本例中实现了target方法. 在调用target之前会调用init方法,init方法就给出了cpu 这里支持的最大和最小频率。如358行359所示. 309 static int nforce2_cpu_init(struct cpufreq_policy *policy) 310 { 356  357         /* cpuinfo and default policy values */ 358         policy->min = policy->cpuinfo.min_freq = min_fsb * fid * 100; 359         policy->max = policy->cpuinfo.max_freq = max_fsb * fid * 100; 360         policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; 361  362         return 0; 363 } 其次看看target是如何设定freq的 252 static int nforce2_target(struct cpufreq_policy *policy, 253                           unsigned int target_freq, unsigned int relation) 254 { 255 /*        unsigned long         flags; */ 256         struct cpufreq_freqs freqs; 257         unsigned int target_fsb; 258  259         if ((target_freq > policy->max) || (target_freq < policy->min)) 260                 return -EINVAL; 261  262         target_fsb = target_freq / (fid * 100); 263  264         freqs.old = nforce2_get(policy->cpu); 265         freqs.new = target_fsb * fid * 100; 266  267         if (freqs.old == freqs.new) 268                 return 0; 269  270         pr_debug("Old CPU frequency %d kHz, new %d kHz\n", 271                freqs.old, freqs.new); 272  273         cpufreq_freq_transition_begin(policy, &freqs); 274  275         /* Disable IRQs */ 276         /* local_irq_save(flags); */ 277  278         if (nforce2_set_fsb(target_fsb) < 0) 279                 pr_err("Changing FSB to %d failed\n", target_fsb); 280         else 281                 pr_debug("Changed FSB successfully to %d\n", 282                         target_fsb); 283  284         /* Enable IRQs */ 285         /* local_irq_restore(flags); */ 286  287         cpufreq_freq_transition_end(policy, &freqs, 0); 288  289         return 0; 290 } 在262上所处      target_fsb = target_freq / (fid * 100); 可以看到是通过nforce2_set_fsb(target_fsb)来设定的频率的。 169 static int nforce2_set_fsb(unsigned int fsb) 170 { 171         u32 temp = 0; 172         unsigned int tfsb; 173         int diff; 174         int pll = 0; 175  176         if ((fsb > max_fsb) || (fsb < NFORCE2_MIN_FSB)) { 177                 pr_err("FSB %d is out of range!\n", fsb); 178                 return -EINVAL; 179         } 180  181         tfsb = nforce2_fsb_read(0); 182         if (!tfsb) { 183                 pr_err("Error while reading the FSB\n"); 184                 return -EINVAL; 185         } 186  187         /* First write? Then set actual value */ 188         pci_read_config_byte(nforce2_dev, NFORCE2_PLLENABLE, (u8 *)&temp); 189         if (!temp) { 190                 pll = nforce2_calc_pll(tfsb); 191  192                 if (pll < 0) 193                         return -EINVAL; 194  195                 nforce2_write_pll(pll); 196         } 197  198         /* Enable write access */ 199         temp = 0x01; 200         pci_write_config_byte(nforce2_dev, NFORCE2_PLLENABLE, (u8)temp); 201  202         diff = tfsb - fsb; 203  204         if (!diff) 205                 return 0; 206  207         while ((tfsb != fsb) && (tfsb <= max_fsb) && (tfsb >= min_fsb)) { 208                 if (diff < 0) 209                         tfsb++; 210                 else 211                         tfsb--; 212  213                 /* Calculate the PLL reg. value */ 214                 pll = nforce2_calc_pll(tfsb); 215                 if (pll == -1) 216                         return -EINVAL; 217  218                 nforce2_write_pll(pll); 219 #ifdef NFORCE2_DELAY 220                 mdelay(NFORCE2_DELAY); 221 #endif 222         } 223  224         temp = 0x40; 225         pci_write_config_byte(nforce2_dev, NFORCE2_PLLADR, (u8)temp); 226  227         return 0; 228 } 229  从214行可以看出在这个例子中是将通过nforce2_calc_pll将freq转成成pll 通过调用nforce2_write_pll来设定到pll寄存器中的 116 static void nforce2_write_pll(int pll) 117 { 118         int temp; 119  120         /* Set the pll addr. to 0x00 */ 121         pci_write_config_dword(nforce2_dev, NFORCE2_PLLADR, 0); 122  123         /* Now write the value in all 64 registers */ 124         for (temp = 0; temp <= 0x3f; temp++) 125                 pci_write_config_dword(nforce2_dev, NFORCE2_PLLREG, pll); 126  127         return; 128 } 哈哈,125行终于看见真的是在写寄存器了吧
    转载请注明原文地址: https://ju.6miu.com/read-1308914.html
    最新回复(0)