rk: add pwm scale arm voltage support && update rk3026 test frequencies

This commit is contained in:
chenxing
2013-10-08 15:55:46 +08:00
parent 8c9b21bad0
commit 6eb352d200
4 changed files with 253 additions and 12 deletions

View File

@@ -1,3 +1,4 @@
obj-y += ft_cpu_tst.o
obj-y += ft_cpu_tst1.o
obj-y += ft_test.o
obj-y += ft_pwm.o

View File

@@ -0,0 +1,178 @@
/*
*
* Copyright (C) 2013 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/bug.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/rk29-pwm-regulator.h>
#include <mach/iomux.h>
#include <linux/gpio.h>
#include <mach/board.h>
#include <plat/pwm.h>
#include "ft_pwm.h"
#if 0
#define DBG(x...) printk(KERN_INFO x)
#else
#define DBG(x...)
#endif
#if defined(CONFIG_SOC_RK3168) || defined(CONFIG_SOC_RK3168M) || defined(CONFIG_ARCH_RK3188) || defined(CONFIG_ARCH_RK3026)
const static int pwm_voltage_map[] = {
800000,825000,850000, 875000,900000, 925000 ,950000, 975000,1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000,1375000
};
#else
const static int pwm_voltage_map[] = {
950000, 975000,1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 1400000
};
#endif
#if 0
struct ft_pwm_data {
int pwm_id;
char* gpio_name;
char* pwm_iomux_name;
unsigned int pwm_gpio;
unsigned int pwm_iomux_pwm;
unsigned int pwm_iomux_gpio;
int pwm_voltage;
int suspend_voltage;
int min_uV;
int max_uV;
int coefficient;
const int *pwm_voltage_map;
};
#endif
static struct ft_pwm_data ft_pwm[2] = {
{
.pwm_id = 0,
.min_uV = 820000,
.max_uV = 1380000,
.coefficient = 560, //56%
.pwm_voltage_map = pwm_voltage_map,
}, {
.pwm_id = 1,
.min_uV = 820000,
.max_uV = 1380000,
.coefficient = 560, //56%
.pwm_voltage_map = pwm_voltage_map,
},
};
int ft_pwm_set_rate(struct ft_pwm_data* pwm, int nHz, u32 rate)
{
u32 lrc, hrc;
unsigned long clkrate;
clkrate = clk_get_rate(clk_get(NULL, "pwm01"));
printk("%s: out_rate=%d, get clkrate=%lu\n", __func__, nHz, clkrate);
gpio_request(pwm->pwm_gpio, "ft pwm gpio");
if (rate == 0) {
// iomux pwm to gpio
rk30_mux_api_set(pwm->gpio_name, pwm->pwm_iomux_gpio);
//disable pull up or down
gpio_pull_updown(pwm->pwm_gpio, PullDisable);
// set gpio to low level
gpio_direction_output(pwm->pwm_gpio, GPIO_LOW);
} else if (rate < 100) {
// iomux pwm to gpio
lrc = clkrate / nHz;
lrc = lrc >> (1 + (PWM_DIV >> 9));
lrc = lrc ? lrc : 1;
hrc = lrc * rate / 100;
hrc = hrc ? hrc : 1;
// iomux pwm
rk30_mux_api_set(pwm->pwm_iomux_name, pwm->pwm_iomux_pwm);
printk("%s: lrc=%d, hrc=%d\n", __func__, lrc, hrc);
rk_pwm_setup(pwm->pwm_id, PWM_DIV, hrc, lrc);
} else if (rate == 100) {
// iomux pwm to gpio
rk30_mux_api_set(pwm->gpio_name, pwm->pwm_iomux_gpio);
//disable pull up or down
gpio_pull_updown(pwm->pwm_gpio, PullDisable);
// set gpio to low level
gpio_direction_output(pwm->pwm_gpio, GPIO_HIGH);
} else {
printk("%s:rate error\n",__func__);
return -1;
}
usleep_range(10 * 1000, 10 * 1000);
return (0);
}
int ft_pwm_regulator_get_voltage(char* name)
{
DBG("%s: get %s voltage\n", __func__, name);
return 0;
}
int ft_pwm_set_voltage(char *name, int vol)
{
int ret = 0;
// VDD12 = 1.40 - 0.455*D , 其中D为PWM占空比,
int pwm_value, pwm_id = 0;
if (strcmp(name, "arm") == 0) {
pwm_id = 0;
} else if (strcmp(name, "logic") == 0) {
pwm_id = 1;
} else {
printk("unknown name");
return -EINVAL;
}
printk("%s: name=%s, pwm_id=%d, vol=%d\n", __func__, name, pwm_id, vol);
/* pwm_value %, coefficient * 1000 */
pwm_value = (ft_pwm[pwm_id].max_uV - vol) / ft_pwm[pwm_id].coefficient / 10;
printk("%s: name=%s, pwm_id=%d, duty=%d%%, [min,max]=[%d, %d], coefficient=%d\n",
__func__, name, pwm_id, pwm_value,
ft_pwm[pwm_id].min_uV,
ft_pwm[pwm_id].max_uV,
ft_pwm[pwm_id].coefficient);
ret = ft_pwm_set_rate(&ft_pwm[pwm_id], 1000 * 1000, pwm_value);
if (ret != 0) {
printk("%s: fail to set pwm rate, pwm_value = %d\n", __func__, pwm_value);
return -1;
}
return 0;
}
static int pwm_mode[] = {PWM0, PWM1, PWM2};
void ft_pwm_init(void)
{
int i = 0;
for (i = 0; i < ARRAY_SIZE(ft_pwm); i++) {
ft_pwm[i].pwm_gpio = iomux_mode_to_gpio(pwm_mode[ft_pwm[i].pwm_id]);
ft_pwm[i].pwm_iomux_pwm = pwm_mode[ft_pwm[i].pwm_id];
ft_pwm[i].pwm_iomux_gpio = iomux_switch_gpio_mode(pwm_mode[ft_pwm[i].pwm_id]);
}
}

View File

@@ -0,0 +1,49 @@
/*
*
* Copyright (C) 2013 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/bug.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/rk29-pwm-regulator.h>
#include <mach/iomux.h>
#include <linux/gpio.h>
#include <mach/board.h>
#include <plat/pwm.h>
struct ft_pwm_data {
int pwm_id;
char* gpio_name;
char* pwm_iomux_name;
unsigned int pwm_gpio;
unsigned int pwm_iomux_pwm;
unsigned int pwm_iomux_gpio;
int pwm_voltage;
int suspend_voltage;
int min_uV;
int max_uV;
int coefficient;
const int *pwm_voltage_map;
};
int ft_pwm_set_rate(struct ft_pwm_data* pwm, int nHz, u32 rate);
int ft_pwm_regulator_get_voltage(char* name);
int ft_pwm_set_voltage(char *name, int vol);
void ft_pwm_init(void);

View File

@@ -49,9 +49,9 @@ REVISION 0.01
#include <linux/kthread.h>
#include <linux/clk.h>
#include <linux/suspend.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include "ft_pwm.h"
#if 0
@@ -75,6 +75,9 @@ REVISION 0.01
#define ft_printk_info(fmt, arg...) {while(0);}
#endif
#define FT_PWM 0
int pwm_volt[5] = {900000, 1250000, 1350000, 0, 0};
#define MHZ (1000*1000)
#define TST_SETUPS (4)
@@ -138,7 +141,7 @@ const static unsigned long l2_cpy_cnt[TST_SETUPS]={5*3,5*4,0,0};
#elif defined(CONFIG_ARCH_RK3026)
const static unsigned long arm_setups_rate[4] = {312 * MHZ, 816 * MHZ, 0, 0};
const static unsigned long arm_setups_rate[4] = {312 * MHZ, 816 * MHZ, 1008 * MHZ, 0};
const static unsigned long l1_tst_cnt[TST_SETUPS]={5 * 10, 5 * 10, 0, 0};
const static unsigned long l2_cpy_cnt[TST_SETUPS]={5 * 3, 5 * 4, 0, 0};
@@ -510,6 +513,10 @@ void ft_cpu_test_type0(int steps)
ft_printk_dbg("test typ0 step%d cpu=%d start\n",steps,cpu);
//arm rate init
ft_cpu_l1_test(l1_tst_cnt[steps]);
#if FT_PWM
ft_pwm_set_voltage("arm", pwm_volt[0]);
mdelay(5);
#endif
per_cpu(cpu_tst_flags, cpu)&=~setup_l1_bits[steps];
//temp=ft_test_cpus_l2(l2_test_buf[cpu],sizeof(char)*BUF_SIZE,20);
@@ -534,8 +541,9 @@ int ft_cpu_test_type0_check(int steps,const char *str)
for (cpu = 0; cpu < NR_CPUS; cpu++)
{
ret|=per_cpu(cpu_tst_flags, cpu);
ft_printk_dbg("setup%d,cpu%d flags=%x(%x)\n",steps,cpu,per_cpu(cpu_tst_flags, cpu)&setup_bits_msk[steps],
per_cpu(cpu_tst_flags, cpu));
ft_printk_dbg("setup%d,cpu%d flags=%x(%x)\n",
steps, cpu, per_cpu(cpu_tst_flags, cpu) & setup_bits_msk[steps],
per_cpu(cpu_tst_flags, cpu));
}
ret&=setup_bits_msk[steps];// test setup1
@@ -607,24 +615,27 @@ int ft_cpu_test_type1_check(int steps,const char *str)
if(arm_setups_rate[steps]<rate)
clk_set_rate(arm_clk,arm_setups_rate[steps]);
#ifdef ENABLE_FT_TEST_GPIO
#if FT_PWM
ft_pwm_set_voltage("arm", pwm_volt[steps]);
mdelay(5);
#else
#ifdef ENABLE_FT_TEST_GPIO
// send msg to ctr board to up the volt
gpio_request(FT_CLIENT_READY_PIN, "client ready");
gpio_request(FT_CLIENT_IDLE_PIN, "client idle");
gpio_direction_output(FT_CLIENT_READY_PIN, GPIO_HIGH);
gpio_direction_input(FT_CLIENT_IDLE_PIN);
// waiting for volt upping ok
if((steps%2))
while( 0 == gpio_get_value(FT_CLIENT_IDLE_PIN));
else
while( 1 == gpio_get_value(FT_CLIENT_IDLE_PIN));
gpio_set_value(FT_CLIENT_READY_PIN, GPIO_LOW);
#endif
gpio_set_value(FT_CLIENT_READY_PIN, GPIO_LOW);
#endif
#endif
if(arm_setups_rate[steps]>=rate)
clk_set_rate(arm_clk,arm_setups_rate[steps]);
@@ -640,8 +651,9 @@ int ft_cpu_test_type1_check(int steps,const char *str)
for (cpu = 0; cpu < NR_CPUS; cpu++)
{
ret|=per_cpu(cpu_tst_flags, cpu);
ft_printk_dbg("setup%d,cpu%d flags=%x(%x)\n",steps,cpu,per_cpu(cpu_tst_flags, cpu)&setup_bits_msk[steps],
per_cpu(cpu_tst_flags, cpu));
ft_printk_dbg("setup%d,cpu%d flags=%x(%x)\n",
steps, cpu, per_cpu(cpu_tst_flags, cpu) & setup_bits_msk[steps],
per_cpu(cpu_tst_flags, cpu));
}
ret&=setup_bits_msk[steps];// test setup2
@@ -692,6 +704,7 @@ static int __init rk_ft_tests_init(void)
char *buf;
arm_clk=clk_get(NULL, "cpu");
ft_pwm_init();
for (cpu = 0; cpu < NR_CPUS; cpu++) {
l2_test_mbuf[cpu]=NULL;
buf = kmalloc(BUF_SIZE_M, GFP_KERNEL);