#include <mach/pmu.h>
-#define PWM_VCORE_120 40
-#define PWM_VCORE_125 32
-#define PWM_VCORE_130 21
-#define PWM_VCORE_135 10
-#define PWM_VCORE_140 0
-
/* CRU PLL CON */
#define PLL_HIGH_BAND (0x01 << 16)
#define PLL_LOW_BAND (0x00 << 16)
#define CORE_PARENT_ARM_PLL (0 << 23)
#define CORE_PARENT_GENERAL_PLL (1 << 23)
-#define PWM_DIV2 (0<<9)
-#define PWM_DIV4 (1<<9)
-#define PWM_DIV8 (2<<9)
-#define PWM_DIV16 (3<<9)
-#define PWM_DIV32 (4<<9)
-#define PWM_DIV64 (5<<9)
-#define PWM_DIV128 (6<<9)
-#define PWM_DIV256 (7<<9)
-#define PWM_DIV512 (8<<9)
-#define PWM_DIV1024 (9<<9)
-
-#define PWM_CAPTURE (1<<8)
-#define PWM_RESET (1<<7)
-#define PWM_INTCLR (1<<6)
-#define PWM_INTEN (1<<5)
-#define PWM_SINGLE (1<<6)
-
-#define PWM_ENABLE (1<<3)
-#define PWM_TimeEN (1)
-
-#define PWM_DIV PWM_DIV2
-
-static struct clk pclk_periph;
-static struct clk clk_pwm;
-void PWMInit(u32 nHz, u32 rate)
-{
- u32 divh;
-
- clk_enable_nolock(&clk_pwm);
- // iomux to pwm2
-#define REG_FILE_BASE_ADDR RK29_GRF_BASE
- volatile unsigned int * pGRF_GPIO2L_IOMUX = (volatile unsigned int *)(REG_FILE_BASE_ADDR + 0x58);
- *pGRF_GPIO2L_IOMUX &= ~(0x3<<6);
- *pGRF_GPIO2L_IOMUX |= (0x2<<6);
- // pwm2 clk enable
-
- // set pwm rate
-#define PWM_BASE_ADDR RK29_PWM_BASE
- volatile unsigned int * pPWM2_CTRL = (volatile unsigned int *)(PWM_BASE_ADDR + 0x2C);
- volatile unsigned int * pPWM2_LRC = (volatile unsigned int *)(PWM_BASE_ADDR + 0x28);
- volatile unsigned int * pPWM2_HRC = (volatile unsigned int *)(PWM_BASE_ADDR + 0x24);
- volatile unsigned int * pPWM2_CNTR = (volatile unsigned int *)(PWM_BASE_ADDR + 0x20);
-
-#define GPIO2_BASE_ADDR RK29_GPIO2_BASE
- volatile unsigned int *pGPIO2_DIR = (volatile unsigned int *)(GPIO2_BASE_ADDR + 0x4);
- volatile unsigned int *pGPIO2_LEVEL = (volatile unsigned int *)GPIO2_BASE_ADDR;
-
- if (rate == 0) {
- // iomux pwm2 to gpio2_a[3]
- *pGRF_GPIO2L_IOMUX &= ~(0x3<<6);
- // set gpio to low level
- *pGPIO2_DIR |= 0x1<<3;
- *pGPIO2_LEVEL &= ~(0x1<<3);
- } else {
- *pPWM2_CTRL= PWM_DIV|PWM_RESET;
- divh = pclk_periph.rate / nHz;
- divh = divh >> (1+(PWM_DIV>>9));
- *pPWM2_LRC = (divh == 0)?1:divh;
-
- divh = (*pPWM2_LRC)*rate/100;
- *pPWM2_HRC = divh?divh:1;
-
- *pPWM2_CNTR = 0x0;
- *pPWM2_CTRL = PWM_DIV|PWM_ENABLE|PWM_TimeEN;
- printk("pclk_periph %d LRC %08x HRC %08x\n", pclk_periph.rate, *pPWM2_LRC, *pPWM2_HRC);
- }
-
- int i; for (i = 0; i < 6000; i++)
- delay_500ns();
-}
-
static int arm_pll_clk_set_rate(struct clk *clk, unsigned long rate)
{
const struct arm_pll_set *ps, *pt;
pt++;
}
- PWMInit(1 * MHZ, PWM_VCORE_130); // 1.30V
-
/* make aclk safe & reparent to general pll */
cru_writel((cru_readl(CRU_CLKSEL0_CON) & ~(CORE_PARENT_MASK | CORE_ACLK_MASK)) | CORE_PARENT_GENERAL_PLL | CORE_ACLK_21, CRU_CLKSEL0_CON);
--- /dev/null
+/* arch/arm/mach-rk2818/cpufreq.c
+ *
+ * Copyright (C) 2010 ROCKCHIP, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/cpufreq.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/regulator/consumer.h>
+
+static struct cpufreq_frequency_table freq_table[] = {
+#if 0
+// { .index = 950000, .frequency = 204000 },
+// { .index = 1050000, .frequency = 300000 },
+ { .index = 1050000, .frequency = 408000 },
+// { .index = 1125000, .frequency = 600000 },
+ { .index = 1225000, .frequency = 816000 },
+ { .index = 1250000, .frequency = 1008000 },
+// { .index = 1300000, .frequency = 1200000 },
+#else
+ { .index = 1100000, .frequency = 408000 },
+// { .index = 1200000, .frequency = 600000 },
+ { .index = 1300000, .frequency = 816000 },
+// { .index = 1350000, .frequency = 1008000 },
+#endif
+ { .frequency = CPUFREQ_TABLE_END },
+};
+static struct clk *arm_clk;
+static struct regulator *vcore;
+
+static int rk29_cpufreq_verify(struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy, freq_table);
+}
+
+static int rk29_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation)
+{
+ int index;
+ struct cpufreq_freqs freqs;
+ const struct cpufreq_frequency_table *freq;
+ int err = 0;
+
+ if (policy->cpu != 0)
+ return -EINVAL;
+ if (cpufreq_frequency_table_target(policy, freq_table, target_freq, relation, &index)) {
+ pr_err("cpufreq: invalid target_freq: %d\n", target_freq);
+ return -EINVAL;
+ }
+ freq = &freq_table[index];
+
+ if (policy->cur == freq->frequency)
+ return 0;
+
+ freqs.old = policy->cur;
+ freqs.new = freq->frequency;
+ freqs.cpu = 0;
+#ifdef CONFIG_CPU_FREQ_DEBUG
+ printk(KERN_DEBUG "%s %d r %d (%d-%d) selected %d (%duV)\n", __func__, target_freq, relation, policy->min, policy->max, freq->frequency, freq->index);
+#endif
+
+#ifdef CONFIG_REGULATOR
+ if (vcore && freqs.new > freqs.old) {
+ err = regulator_set_voltage(vcore, freq->index, freq->index);
+ if (err) {
+ pr_err("cpufreq: fail to set vcore (%duV) for %dkHz: %d\n",
+ freq->index, freqs.new, err);
+ goto err_vol;
+ }
+ }
+#endif
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ clk_set_rate(arm_clk, freqs.new * 1000);
+ freqs.new = clk_get_rate(arm_clk) / 1000;
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+#ifdef CONFIG_REGULATOR
+ if (vcore && freqs.new < freqs.old) {
+ err = regulator_set_voltage(vcore, freq->index, freq->index);
+ if (err) {
+ pr_err("cpufreq: fail to set vcore (%duV) for %dkHz: %d\n",
+ freq->index, freqs.new, err);
+ }
+ }
+#endif
+
+err_vol:
+ return err;
+}
+
+extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
+
+static int __init rk29_cpufreq_init(struct cpufreq_policy *policy)
+{
+ arm_clk = clk_get(NULL, "arm_pll");
+ if (IS_ERR(arm_clk))
+ return PTR_ERR(arm_clk);
+
+ if (policy->cpu != 0)
+ return -EINVAL;
+
+#ifdef CONFIG_REGULATOR
+ vcore = regulator_get(NULL, "vcore");
+ if (IS_ERR(vcore)) {
+ pr_err("cpufreq: fail to get regulator vcore: %ld\n", PTR_ERR(vcore));
+ vcore = NULL;
+ }
+#endif
+
+ BUG_ON(cpufreq_frequency_table_cpuinfo(policy, freq_table));
+ cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
+ policy->cur = clk_get_rate(arm_clk) / 1000;
+
+ policy->cpuinfo.transition_latency = 400 * NSEC_PER_USEC; // make default sampling_rate to 40000
+
+ return 0;
+}
+
+static int rk29_cpufreq_exit(struct cpufreq_policy *policy)
+{
+ if (vcore)
+ regulator_put(vcore);
+ clk_put(arm_clk);
+ return 0;
+}
+
+static struct freq_attr *rk29_cpufreq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
+static struct cpufreq_driver rk29_cpufreq_driver = {
+ .flags = CPUFREQ_STICKY,
+ .init = rk29_cpufreq_init,
+ .exit = rk29_cpufreq_exit,
+ .verify = rk29_cpufreq_verify,
+ .target = rk29_cpufreq_target,
+ .name = "rk29",
+ .attr = rk29_cpufreq_attr,
+};
+
+static int __init rk29_cpufreq_register(void)
+{
+ return cpufreq_register_driver(&rk29_cpufreq_driver);
+}
+
+device_initcall(rk29_cpufreq_register);
+
\r
\r
const static int pwm_voltage_map[] = {\r
- 1200, 1250, 1300, 1350, 1400\r
+ 950, 975, 1000, 1025, 1050, 1075, 1100, 1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300, 1325, 1350, 1375, 1400\r
};\r
\r
static int pwm_set_rate(struct pwm_platform_data *pdata,int nHz,u32 rate)\r
return -1;\r
}\r
\r
- msleep(50);\r
+ msleep(5);\r
\r
\r
return (0);\r
\r
static int pwm_regulator_list_voltage(struct regulator_dev *dev,unsigned int index)\r
{\r
- int *pwm_voltage_table = pwm_voltage_map;\r
-
DBG("Enter %s, index =%d\n",__FUNCTION__,index);\r
if (index < sizeof(pwm_voltage_map)/sizeof(int))\r
- return pwm_voltage_table[index];\r
+ return pwm_voltage_map[index];\r
else\r
return -1;\r
}\r
}
\r
\r
-module_init(pwm_regulator_module_init);\r
+subsys_initcall(pwm_regulator_module_init);\r
\r
module_exit(pwm_regulator_module_exit);\r