Blame view

drivers/cpufreq/cris-artpec3-cpufreq.c 2.22 KB
035e111f9   Jesper Nilsson   CRIS v32: Add new...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  #include <linux/init.h>
  #include <linux/module.h>
  #include <linux/cpufreq.h>
  #include <hwregs/reg_map.h>
  #include <hwregs/reg_rdwr.h>
  #include <hwregs/clkgen_defs.h>
  #include <hwregs/ddr2_defs.h>
  
  static int
  cris_sdram_freq_notifier(struct notifier_block *nb, unsigned long val,
  	void *data);
  
  static struct notifier_block cris_sdram_freq_notifier_block = {
  	.notifier_call = cris_sdram_freq_notifier
  };
  
  static struct cpufreq_frequency_table cris_freq_table[] = {
7f4b04614   Viresh Kumar   cpufreq: create a...
18
19
20
  	{0, 0x01, 6000},
  	{0, 0x02, 200000},
  	{0, 0, CPUFREQ_TABLE_END},
035e111f9   Jesper Nilsson   CRIS v32: Add new...
21
22
23
24
25
26
27
28
  };
  
  static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu)
  {
  	reg_clkgen_rw_clk_ctrl clk_ctrl;
  	clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);
  	return clk_ctrl.pll ? 200000 : 6000;
  }
9c0ebcf78   Viresh Kumar   cpufreq: Implemen...
29
  static int cris_freq_target(struct cpufreq_policy *policy, unsigned int state)
035e111f9   Jesper Nilsson   CRIS v32: Add new...
30
  {
035e111f9   Jesper Nilsson   CRIS v32: Add new...
31
32
  	reg_clkgen_rw_clk_ctrl clk_ctrl;
  	clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);
035e111f9   Jesper Nilsson   CRIS v32: Add new...
33
34
35
36
37
38
39
40
41
42
43
  	local_irq_disable();
  
  	/* Even though we may be SMP they will share the same clock
  	 * so all settings are made on CPU0. */
  	if (cris_freq_table[state].frequency == 200000)
  		clk_ctrl.pll = 1;
  	else
  		clk_ctrl.pll = 0;
  	REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, clk_ctrl);
  
  	local_irq_enable();
035e111f9   Jesper Nilsson   CRIS v32: Add new...
44
45
46
47
48
  	return 0;
  }
  
  static int cris_freq_cpu_init(struct cpufreq_policy *policy)
  {
1870e1119   Viresh Kumar   cpufreq: cris: us...
49
  	return cpufreq_generic_init(policy, cris_freq_table, 1000000);
035e111f9   Jesper Nilsson   CRIS v32: Add new...
50
  }
035e111f9   Jesper Nilsson   CRIS v32: Add new...
51
52
  static struct cpufreq_driver cris_freq_driver = {
  	.get	= cris_freq_get_cpu_frequency,
361db10f6   Viresh Kumar   cpufreq: cris: Us...
53
  	.verify	= cpufreq_generic_frequency_table_verify,
9c0ebcf78   Viresh Kumar   cpufreq: Implemen...
54
  	.target_index = cris_freq_target,
035e111f9   Jesper Nilsson   CRIS v32: Add new...
55
  	.init	= cris_freq_cpu_init,
035e111f9   Jesper Nilsson   CRIS v32: Add new...
56
  	.name	= "cris_freq",
361db10f6   Viresh Kumar   cpufreq: cris: Us...
57
  	.attr	= cpufreq_generic_attr,
035e111f9   Jesper Nilsson   CRIS v32: Add new...
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  };
  
  static int __init cris_freq_init(void)
  {
  	int ret;
  	ret = cpufreq_register_driver(&cris_freq_driver);
  	cpufreq_register_notifier(&cris_sdram_freq_notifier_block,
  		CPUFREQ_TRANSITION_NOTIFIER);
  	return ret;
  }
  
  static int
  cris_sdram_freq_notifier(struct notifier_block *nb, unsigned long val,
  	void *data)
  {
  	int i;
  	struct cpufreq_freqs *freqs = data;
  	if (val == CPUFREQ_PRECHANGE) {
  		reg_ddr2_rw_cfg cfg =
  		  REG_RD(ddr2, regi_ddr2_ctrl, rw_cfg);
  		cfg.ref_interval = (freqs->new == 200000 ? 1560 : 46);
  
  		if (freqs->new == 200000)
  			for (i = 0; i < 50000; i++);
  		REG_WR(bif_core, regi_bif_core, rw_sdram_timing, timing);
  	}
  	return 0;
  }
  
  
  module_init(cris_freq_init);