Beispiel #1
0
static void s5pv310_pwm_init(unsigned int pwm_id, unsigned long tcnt)
{
	unsigned long tcon;

	tcon = __raw_readl(S3C2410_TCON);

	/* timers reload after counting zero, so reduce the count by 1 */
	tcnt--;

	/* ensure timer is stopped... */
	switch (pwm_id) {
	case 2:
		tcon &= ~(0xf<<12);
		tcon |= S3C2410_TCON_T2MANUALUPD;

		__raw_writel(tcnt, S3C2410_TCNTB(2));
		__raw_writel(tcnt, S3C2410_TCMPB(2));
		__raw_writel(tcon, S3C2410_TCON);

		break;
	case 4:
		tcon &= ~(7<<20);
		tcon |= S3C2410_TCON_T4MANUALUPD;

		__raw_writel(tcnt, S3C2410_TCNTB(4));
		__raw_writel(tcnt, S3C2410_TCMPB(4));
		__raw_writel(tcon, S3C2410_TCON);

		break;
	default:
		break;
	}
}
Beispiel #2
0
static inline void s3c64xx_pwm_reconfigure(unsigned int pwm_id,
					unsigned long tcnt, bool periodic)
{
	unsigned long tcon = __raw_readl(S3C2410_TCON);

	switch (pwm_id) {
	case 3:
		tcon |= S3C2410_TCON_T3START;
		tcon &= ~S3C2410_TCON_T3MANUALUPD;

		if (periodic)
			tcon |= S3C2410_TCON_T3RELOAD;
		else
			tcon &= ~S3C2410_TCON_T3RELOAD;
		break;
	case 4:
		tcon |= S3C2410_TCON_T4START;
		tcon &= ~S3C2410_TCON_T4MANUALUPD;

		if (periodic)
			tcon |= S3C2410_TCON_T4RELOAD;
		else
			tcon &= ~S3C2410_TCON_T4RELOAD;
		break;
	}

	__raw_writel(tcnt, S3C2410_TCNTB(pwm_id));
	__raw_writel(tcnt, S3C2410_TCMPB(pwm_id));
	__raw_writel(tcon, S3C2410_TCON);
}
Beispiel #3
0
static void s3c210_set_timer1(unsigned long Val)
{
#if 0
//#ifdef CONFIG_S3C210_PWM
	s3c_gpio_cfgpin(S3C64XX_GPF(15),S3C64XX_GPF15_PWM_TOUT1);
	pwm_config(beeper->pwm, beeper->step_ns*Val, beeper->period);
#else
        unsigned long tcon;//用于存放时钟控制寄存器的数值
        unsigned long tcnt;//用于存放TCNTB1的数值
        unsigned long tcmp;//用于存放TCMPB1的数值
        unsigned long tcfg1;//用于存放定时器配置寄存器1的数值
        unsigned long tcfg0;//用于存放定时器配置寄存器0的数值
	unsigned char i;
      
	 tcnt = 0xffffffff;  /* 默认的TCTB1数值*/

        /* 读取TCON,TCFG0以及TCFG1寄存器的数值*/
        tcon = __raw_readl(S3C2410_TCON);
        tcfg1 =__raw_readl(S3C2410_TCFG1);
        tcfg0 =__raw_readl(S3C2410_TCFG0);

	/*定时器输入频率 = PCLK / ( {预分频数值 + 1} ) / {分割数值}
	*{预分频数值} = 1~255,由TCFG0配置寄存器来配置
	*{分割数值} = 1, 2, 4, 8, 16, TCLK,由TCFG1配置寄存器来配置
	*/
      
	//配置GPF15为输出
	for (i = 0; i < sizeof(gpio_table)/sizeof(unsigned long); i++)
	{
		s3c_gpio_cfgpin(gpio_table[i], gpio_cfg_table[i]);
		s3c_gpio_setpull(gpio_table[i], S3C_GPIO_PULL_NONE);
	}
	//清零TCFG1[4:7]
        tcfg1 &= ~S3C2410_TCFG1_MUX1_MASK;
	//设置分割值为2
        tcfg1 |= S3C2410_TCFG1_MUX1_DIV2;//set [4:7]== 1/2
	//清零预分频位TCFG0[0:7]
        tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
	//设置预分频数值,这里是254
 //       tcfg0 |= (PRESCALER) << 0;//backlight pwm0
	//清零TCON[8:10]
        tcon &= ~(7<<8); //set bit [8:10] to zero
	//设置定时器工作模式为自动加载模式(auto-reload)
        tcon |= S3C2410_TCON_T1RELOAD;
	//将配置好的TCON,TCFG0,TCFG1的数值写回寄存器
	__raw_writel(tcfg1, S3C2410_TCFG1);
//	__raw_writel(tcfg0, S3C2410_TCFG0);//backlight pwm0 div
	__raw_writel(tcon, S3C2410_TCON);
	
	//准备更新TCMPB1数值,先置1 TCON[9]
	tcon |= S3C2410_TCON_T1MANUALUPD;
	__raw_writel(tcon, S3C2410_TCON);	
	//TCNTB1==200,改数值决定了PWM的频率
	tcnt = 101*255;
	 __raw_writel(tcnt, S3C2410_TCNTB(1));
	//改变TCMPB1的数值,改数值决定PWM的频宽
	tcmp = Val*255;
	__raw_writel(tcmp, S3C2410_TCMPB(1));
#endif
}
Beispiel #4
0
static int tq2440_pwm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	unsigned long tcfg0;
	unsigned long tcfg1;
	unsigned long tcntb;
	unsigned long tcmpb;
	unsigned long tcon;

	switch (cmd) {
	case BEEP_OFF:
		s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPIO_OUTPUT);
		s3c2410_gpio_setpin(S3C2410_GPB(0), 0);
		break;
	case BEEP_ON_TIMES:
	{
		void __user *argp =  (void __user *)arg;
		unsigned int args = *((unsigned int *)argp);
		struct clk *clk_p;
		unsigned long pclk;

		//set GPB0 as tout0, pwm output
		s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0);

		tcon = __raw_readl(S3C2410_TCON);
		tcfg1 = __raw_readl(S3C2410_TCFG1);
		tcfg0 = __raw_readl(S3C2410_TCFG0);

		//prescaler = 50
		tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
		tcfg0 |= (50 - 1); 

		//mux = 1/16
		tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;
		tcfg1 |= S3C2410_TCFG1_MUX0_DIV16;

		__raw_writel(tcfg1, S3C2410_TCFG1);
		__raw_writel(tcfg0, S3C2410_TCFG0);

		clk_p = clk_get(NULL, "pclk");
		pclk  = clk_get_rate(clk_p);
		tcntb  = (pclk/128)/args;
		tcmpb = tcntb>>1;

		__raw_writel(tcntb, S3C2410_TCNTB(0));
		__raw_writel(tcmpb, S3C2410_TCMPB(0));
			
		tcon &= ~0x1f;
		tcon |= 0xb;		//start timer
		__raw_writel(tcon, S3C2410_TCON);

		tcon &= ~2;
		__raw_writel(tcon, S3C2410_TCON);
	}
		break;
	}

	
	return 0;
}
Beispiel #5
0
static long tq2440_pwm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	unsigned long tcfg0;
	unsigned long tcfg1;
	unsigned long tcntb;
	unsigned long tcmpb;
	unsigned long tcon;

	mutex_lock(&tq2440bzr_mutex);

	if(cmd <= 0)
	{
		s3c_gpio_cfgpin(S3C2410_GPB(0), S3C_GPIO_OUTPUT);
		gpio_set_value(S3C2410_GPB(0), 0);
	}
	else
	{
		struct clk *clk_p;
		unsigned long pclk;

		//set GPB0 as tout0, pwm output
		s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0);

		tcon = __raw_readl(S3C2410_TCON);
		tcfg1 = __raw_readl(S3C2410_TCFG1);
		tcfg0 = __raw_readl(S3C2410_TCFG0);

		//prescaler = 50
		tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
		tcfg0 |= (50 - 1); 

		//mux = 1/16
		tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;
		tcfg1 |= S3C2410_TCFG1_MUX0_DIV16;

		__raw_writel(tcfg1, S3C2410_TCFG1);
		__raw_writel(tcfg0, S3C2410_TCFG0);

		clk_p = clk_get(NULL, "pclk");
		pclk  = clk_get_rate(clk_p);
		tcntb  = (pclk/128)/arg;
		tcmpb = tcntb>>1;

		__raw_writel(tcntb, S3C2410_TCNTB(0));
		__raw_writel(tcmpb, S3C2410_TCMPB(0));
			
		tcon &= ~0x1f;
		tcon |= 0xb;		//start timer
		__raw_writel(tcon, S3C2410_TCON);

		tcon &= ~2;
		__raw_writel(tcon, S3C2410_TCON);
	}

	mutex_unlock(&tq2440bzr_mutex);

	return 0;
}
Beispiel #6
0
/* freq:  pclk/50/16/65536 ~ pclk/50/16/1 
  * if pclk = 50MHz, freq is 1Hz to 62500Hz
  * human ear : 20Hz~ 20000Hz
  */
static void PWM_Set_Freq( unsigned long freq )
{
	unsigned long tcon=0;
	unsigned long tcnt=0;
	unsigned long tcfg1=0;
	unsigned long tcfg0=0;

	struct clk *clk_p=0;
	unsigned long pclk=1;

	unsigned tmp;
        
	freq=freq>0?freq:1;

        printk ("in module Freq is %d\n",freq);

	tmp = readl(GPD0CON);//PWM out use timer0 TOUT_0 here

          tmp &=~(0xfU);//  TOUT_0 here 
          tmp |=  (0x2U); //use TOUT_0 

	writel(tmp, GPD0CON);// Set hightest bit is '10' to pwm out

	tcon = __raw_readl(S5PV210_TCON);
	
	tcfg1 = __raw_readl(S5PV210_TCFG1);
	tcfg0 = __raw_readl(S5PV210_TCFG0);

	//prescaler = 50
	tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;//S3C_TCFG_PRESCALER0_MASK;
	tcfg0 |= (50 - 1); 

	//mux = 1/16
          tcfg1 &= ~S5PV210_TCFG1_MUX1_MASK ;//S3C_TCFG1_MUX1_MASK;
          tcfg1 |= S5PV210_TCFG1_MUX1_DIV16;//S3C_TCFG1_MUX1_DIV16;

	__raw_writel(tcfg1, S5PV210_TCFG1);
	__raw_writel(tcfg0, S5PV210_TCFG0);

	
	clk_p = clk_get(NULL, "pclk");
    pclk  = clk_get_rate(clk_p);
    tcnt  = pclk/50/16/freq;
	
    printk ("in module pclk is %dHz\n", pclk);
    printk ("in module tcntb is %d \n",tcnt);
	__raw_writel(tcnt, S3C2410_TCNTB(0));//use timer0  tcntb
	__raw_writel(tcnt/2, S3C2410_TCMPB(0));//use timer0 tcmpb
				
	
	
	tcon &= ~(0xf);
	tcon |= (0xb);		// set 3-0 bit of TCON is '1011'  . auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0
	__raw_writel(tcon, S5PV210_TCON);
	
	tcon &= ~(2);	  //set set 11-8 bit of S3C_TCON is '1001' 
	__raw_writel(tcon, S5PV210_TCON);
}
/****************************************************************************
 * Backlight control
 ****************************************************************************/
void reciva_bl_set_backlight(int level)
{
  if (level > 31)
    level = 31;

  /* Still get pulses if we set it to zero
   * Setting to 32 removes the pulses
   * XXX ideally need to work out why, but don't have time now */
  if (level == 0)
    level = 32;

  __raw_writel (level, S3C2410_TCMPB(1));
}  
/*  freq:  pclk/50/16/65536 ~ pclk/50/16 
 *  if pclk = 50MHz, freq is 1Hz to 62500Hz
 *  human ear : 20Hz~ 20000Hz
 */
static void PWM_Set_Freq( unsigned long freq )
{
	unsigned long tcon;
	unsigned long tcnt;
	unsigned long tcfg1;
	unsigned long tcfg0;

	struct clk *clk_p;
	unsigned long pclk;

	unsigned tmp;

    /* buzzer setup */
	tmp = readl(S3C2410_GPBCON);
	tmp &= ~(0x3U);
	tmp |=  (0x2U);
	writel(tmp, S3C2410_GPBCON);

	tcon  = __raw_readl(S3C2410_TCON);
	tcfg1 = __raw_readl(S3C2410_TCFG1);
	tcfg0 = __raw_readl(S3C2410_TCFG0);

	/* prescaler = 50 */
	tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
	tcfg0 |= (50 - 1); 

	/* mux = 1/16 */
	tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;
	tcfg1 |= S3C2410_TCFG1_MUX0_DIV16;

	__raw_writel(tcfg1, S3C2410_TCFG1);
	__raw_writel(tcfg0, S3C2410_TCFG0);

	clk_p = clk_get(NULL, "pclk");
	pclk  = clk_get_rate(clk_p);
	tcnt  = (pclk/50/16)/freq;
	
	__raw_writel(tcnt, S3C2410_TCNTB(0));
	__raw_writel(tcnt/2, S3C2410_TCMPB(0));
				
	tcon &= ~0x1f;
	//tcon |= 0xb;		//disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0
    tcon |= (S3C2410_TCON_T0START | S3C2410_TCON_T0MANUALUPD | S3C2410_TCON_T0RELOAD);
    __raw_writel(tcon, S3C2410_TCON);
	
	//tcon &= ~2;			//clear manual update bit
    tcon &= ~S3C2410_TCON_T0MANUALUPD;
    __raw_writel(tcon, S3C2410_TCON);
}
/****************************************************************************
 * Backlight control
 ****************************************************************************/
void reciva_bl_set_backlight(int level)
{
  if (level < 0 )
    level = 0;
  else if (level > BL_DEFAULT_MAX_BACKLIGHT)
    level = BL_DEFAULT_MAX_BACKLIGHT;

  /* NB. This solves the same issue as different code in
   * reciva_backlight_potas.c. The two modules could probably be merged in
   * future, in which case, only one solution is required. */
  /* Still get pulses if we set it to zero
   * Setting to 32 removes the pulses
   * XXX ideally need to work out why, but don't have time now */
  if (level == 0)
    level = 32;

  __raw_writel (level, S3C2410_TCMPB(1));
}  
Beispiel #10
0
static void s5p_time_setup(enum s5p_timer_mode mode, unsigned long tcnt)
{
	unsigned long tcon;

	tcon = __raw_readl(S3C2410_TCON);

	tcnt--;

	switch (mode) {
	case S5P_PWM0:
		tcon &= ~(0x0f << 0);
		tcon |= S3C2410_TCON_T0MANUALUPD;
		break;

	case S5P_PWM1:
		tcon &= ~(0x0f << 8);
		tcon |= S3C2410_TCON_T1MANUALUPD;
		break;

	case S5P_PWM2:
		tcon &= ~(0x0f << 12);
		tcon |= S3C2410_TCON_T2MANUALUPD;
		break;

	case S5P_PWM3:
		tcon &= ~(0x0f << 16);
		tcon |= S3C2410_TCON_T3MANUALUPD;
		break;

	case S5P_PWM4:
		tcon &= ~(0x07 << 20);
		tcon |= S3C2410_TCON_T4MANUALUPD;
		break;

	default:
		printk(KERN_ERR "Invalid Timer %d\n", mode);
		break;
	}

	__raw_writel(tcnt, S3C2410_TCNTB(mode));
	__raw_writel(tcnt, S3C2410_TCMPB(mode));
	__raw_writel(tcon, S3C2410_TCON);
}
Beispiel #11
0
static int buzzer_ioctl (struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
{
	if (cmd <= 0)
	{	
		s3c2410_gpio_cfgpin(S3C2410_GPB0,S3C2410_GPB0_OUTP);//关闭蜂鸣器
		s3c2410_gpio_setpin(S3C2410_GPB0,0);
	}
	
	else
	{	
		unsigned long tcnt = 0;
		unsigned long tcon = 0;
		unsigned long tcfg0 = 0;
		unsigned long tcfg1 = 0;
		unsigned long pclk = 0;
	

		tcfg0 = __raw_readl(S3C2410_TCFG0); //定时器配置寄存器
		tcfg1 = __raw_readl(S3C2410_TCFG1);
		tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK; //相应位清零
		tcfg0 |= (50-1);//49 定时器预分频值
		tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK; //相应位清零 
		tcfg1 |= S3C2410_TCFG1_MUX0_DIV4;//1/4 分频值 PWM定时器0选通选择DIV4
		__raw_writel(tcfg0,S3C2410_TCFG0);//写入寄存器
		__raw_writel(tcfg1,S3C2410_TCFG1);



		pclk = 50000000;   //时钟50MHZ
		tcnt = (pclk/50/4)/cmd;//计算对应cmd频率的定时计数器值   定时器控制寄存器  PCLK/预分频值 + 1(0~255)/分频值
		__raw_writel(tcnt,S3C2410_TCNTB(0));//定时器0计数缓冲寄存器
		__raw_writel(tcnt/2,S3C2410_TCMPB(0)); //定时器0比较缓冲器
		tcon = __raw_readl(S3C2410_TCON);
		tcon	&= ~0x1f;  //00011111  相应位清零 
		tcon |= 0xb;//禁止死区0,自动重载1,关闭变相0,更新1,启动定时器1  01011 
		__raw_writel(tcon,S3C2410_TCON);
		tcon &= ~0x2;//清除手动更新//0010
		__raw_writel(tcon,S3C2410_TCON);
	}
	
	return 0;
}
Beispiel #12
0
static void s3c64xx_sched_timer_start(unsigned long load_val,
					int autoreset)
{
	unsigned long tcon;
	unsigned long tcnt;
	unsigned long tcfg1;
	unsigned long tcfg0;
	unsigned long tcstat;

	tcstat = __raw_readl(S3C64XX_TINT_CSTAT);
	tcstat |=  0x04;
	__raw_writel(tcstat, S3C64XX_TINT_CSTAT);

	tcon  = __raw_readl(S3C2410_TCON);
	tcfg1 = __raw_readl(S3C2410_TCFG1);
	tcfg0 = __raw_readl(S3C2410_TCFG0);
		
	tcnt = load_val;
	tcnt--;
	__raw_writel(tcnt, S3C2410_TCNTB(2));
	__raw_writel(tcnt, S3C2410_TCMPB(2));	
	
	tcon &= ~(0x0b<<12);
	
	if (autoreset) 
		tcon |= S3C2410_TCON_T2RELOAD;

	tcon |= S3C2410_TCON_T2MANUALUPD;

	__raw_writel(tcon, S3C2410_TCON);
	

	
	/* start the timer running */
	tcon |= S3C2410_TCON_T2START;
	tcon &= ~S3C2410_TCON_T2MANUALUPD;
	__raw_writel(tcon, S3C2410_TCON);

}
Beispiel #13
0
static inline void s3c64xx_pwm_init(unsigned int pwm_id, unsigned long tcnt)
{
	unsigned long tcon = __raw_readl(S3C2410_TCON);

	/* timers reload after counting zero, so reduce the count by 1 */
	--tcnt;

	/* stop the timer and ask it to load the new value */
	switch (pwm_id) {
	case 3:
		tcon &= ~(0xf<<16);
		tcon |= S3C2410_TCON_T3MANUALUPD;
		break;
	case 4:
		tcon &= ~(7<<20);
		tcon |= S3C2410_TCON_T4MANUALUPD;
		break;
	}

	__raw_writel(tcnt, S3C2410_TCNTB(pwm_id));
	__raw_writel(tcnt, S3C2410_TCMPB(pwm_id));
	__raw_writel(tcon, S3C2410_TCON);
}
Beispiel #14
0
	SAVE_ITEM(S5P_CLKGATE_IP2),
	SAVE_ITEM(S5P_CLKGATE_IP3),
	SAVE_ITEM(S5P_CLKGATE_IP4),
/* Clock Blcok and Bus gate */
	SAVE_ITEM(S5P_CLKGATE_BLOCK),
	SAVE_ITEM(S5P_CLKGATE_IP5),
/* Clock ETC */
	SAVE_ITEM(S5P_CLK_OUT),
	SAVE_ITEM(S5P_MDNIE_SEL),
/* PWM Register */
	SAVE_ITEM(S3C2410_TCFG0),
	SAVE_ITEM(S3C2410_TCFG1),
	SAVE_ITEM(S3C64XX_TINT_CSTAT),
	SAVE_ITEM(S3C2410_TCON),
	SAVE_ITEM(S3C2410_TCNTB(0)),
	SAVE_ITEM(S3C2410_TCMPB(0)),
	SAVE_ITEM(S3C2410_TCNTO(0)),
};

static struct sleep_save sromc_save[] = {
	SAVE_ITEM(S5P_SROM_BW),
	SAVE_ITEM(S5P_SROM_BC0),
	SAVE_ITEM(S5P_SROM_BC1),
	SAVE_ITEM(S5P_SROM_BC2),
	SAVE_ITEM(S5P_SROM_BC3),
	SAVE_ITEM(S5P_SROM_BC4),
	SAVE_ITEM(S5P_SROM_BC5),
};

/* s3c_pm_check_resume_pin
 *
Beispiel #15
0
static void GPTimerSetValue(unsigned long load,unsigned long cmp)
{
	 __raw_writel(load, S3C2410_TCNTB(1));
	 __raw_writel(cmp, S3C2410_TCMPB(1));
}
static int s3c_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
		int duty_ns, int period_ns)
{
	struct s3c_chip *s3c = to_s3c_chip(chip);
	unsigned long tin_rate;
	unsigned long tin_ns;
	unsigned long period;
	unsigned long flags;
	unsigned long tcon;
	unsigned long tcnt;
	long tcmp;

	/* We currently avoid using 64bit arithmetic by using the
	 * fact that anything faster than 1Hz is easily representable
	 * by 32bits. */

	if (period_ns > NS_IN_HZ || duty_ns > NS_IN_HZ)
		return -ERANGE;

	if (duty_ns > period_ns)
		return -EINVAL;

	if (period_ns == s3c->period_ns &&
	    duty_ns == s3c->duty_ns)
		return 0;

	/* The TCMP and TCNT can be read without a lock, they're not
	 * shared between the timers. */

	tcmp = __raw_readl(S3C2410_TCMPB(s3c->pwm_id));
	tcnt = __raw_readl(S3C2410_TCNTB(s3c->pwm_id));

	period = NS_IN_HZ / period_ns;

	pwm_dbg(s3c, "duty_ns=%d, period_ns=%d (%lu)\n",
		duty_ns, period_ns, period);

	/* Check to see if we are changing the clock rate of the PWM */

	if (s3c->period_ns != period_ns) {
		if (pwm_is_tdiv(s3c)) {
			tin_rate = pwm_calc_tin(s3c, period);
			clk_set_rate(s3c->clk_div, tin_rate);
		} else
			tin_rate = clk_get_rate(s3c->clk);

		s3c->period_ns = period_ns;

		pwm_dbg(s3c, "tin_rate=%lu\n", tin_rate);

		tin_ns = NS_IN_HZ / tin_rate;
		tcnt = period_ns / tin_ns;
	} else
		tin_ns = NS_IN_HZ / clk_get_rate(s3c->clk);

	/* Note, counters count down */

	tcmp = duty_ns / tin_ns;
	tcmp = tcnt - tcmp;
	/* the pwm hw only checks the compare register after a decrement,
	   so the pin never toggles if tcmp = tcnt */
	if (tcmp == tcnt)
		tcmp--;

	pwm_dbg(s3c, "tin_ns=%lu, tcmp=%ld/%lu\n", tin_ns, tcmp, tcnt);

	if (tcmp < 0)
		tcmp = 0;

	/* Update the PWM register block. */

	local_irq_save(flags);

	__raw_writel(tcmp, S3C2410_TCMPB(s3c->pwm_id));
	__raw_writel(tcnt, S3C2410_TCNTB(s3c->pwm_id));

	tcon = __raw_readl(S3C2410_TCON);
	tcon |= pwm_tcon_manulupdate(s3c);
	tcon |= pwm_tcon_autoreload(s3c);
	__raw_writel(tcon, S3C2410_TCON);

	tcon &= ~pwm_tcon_manulupdate(s3c);
	__raw_writel(tcon, S3C2410_TCON);

	local_irq_restore(flags);

	return 0;
}
Beispiel #17
0
static int PWM_open(struct inode *inode, struct file *file)
{
	struct clk *clk_p;
	unsigned long pclk;
	
	s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0);
	s3c2410_gpio_cfgpin(S3C2410_GPB(1), S3C2410_GPB1_TOUT1);
	s3c2410_gpio_cfgpin(S3C2410_GPB(2), S3C2410_GPB2_TOUT2);
	s3c2410_gpio_cfgpin(S3C2410_GPB(3), S3C2410_GPB3_TOUT3);

	tcon = __raw_readl(S3C2410_TCON);
	tcfg0 = __raw_readl(S3C2410_TCFG0); 
	tcfg1 = __raw_readl(S3C2410_TCFG1); 
	
	//设置TCFG0寄存器,prescaler = 50
	//Timer input clock Frequency = PCLK / {prescaler value+1} / {divider value}
	tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK; // S3C2410_TCFG_PRESCALER0_MASK 定时器 0 和1 的预分频值的掩码,清除TCFG[0~8]
    tcfg0 |= (100 - 1); // 设置预分频为 50
    tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK; // S3C2410_TCFG_PRESCALER0_MASK 定时器 2 3 4 的预分频值的掩码,清除TCFG[0~8]
	tcfg0 |= (100 - 1) << 8; // 设置预分频为 50

	tcfg1 &= ~(S3C2410_TCFG1_MUX0_MASK | S3C2410_TCFG1_MUX1_MASK | S3C2410_TCFG1_MUX2_MASK
				| S3C2410_TCFG1_MUX3_MASK);
	tcfg1 |= S3C2410_TCFG1_MUX0_DIV16 | S3C2410_TCFG1_MUX1_DIV16 | S3C2410_TCFG1_MUX2_DIV16
				| S3C2410_TCFG1_MUX3_DIV16;
	
	__raw_writel(tcfg1, S3C2410_TCFG1); //把 tcfg1 的值写到分割寄存器 S3C2410_TCFG1 中
	__raw_writel(tcfg0, S3C2410_TCFG0); //把 tcfg0 的值写到预分频寄存器 S3C2410_TCFG0 中

	clk_p = clk_get(NULL, "pclk"); //得到 pclk
	pclk  = clk_get_rate(clk_p);
	PDEBUG("plck %ld \n",pclk);
	tcnt[0] = (pclk/100/16)/1;
	tcmp[0] = tcnt[0]/2;
    tcnt[3] = tcnt[2] = tcnt[1] = tcnt[0];
    tcmp[3] = tcmp[2] = tcmp[1] = tcmp[0];
	__raw_writel(tcnt[0], S3C2410_TCNTB(0)); __raw_writel(tcmp[0], S3C2410_TCMPB(0));//tcnt[0]  tcmp[0] 4000
	__raw_writel(tcnt[0], S3C2410_TCNTB(1)); __raw_writel(tcmp[0], S3C2410_TCMPB(1));
	__raw_writel(tcnt[0], S3C2410_TCNTB(2)); __raw_writel(tcmp[0], S3C2410_TCMPB(2));
	__raw_writel(tcnt[0], S3C2410_TCNTB(3)); __raw_writel(tcmp[0], S3C2410_TCMPB(3));

	tcon &= ~(S3C2410_TCON_T0DEADZONE | S3C2410_TCON_T0INVERT);
	tcon |= S3C2410_TCON_T0RELOAD | S3C2410_TCON_T0MANUALUPD |S3C2410_TCON_T0START;
	
	tcon &= ~(S3C2410_TCON_T1INVERT);
	tcon |= S3C2410_TCON_T1RELOAD | S3C2410_TCON_T1MANUALUPD |S3C2410_TCON_T1START;

	tcon &= ~(S3C2410_TCON_T2INVERT);
	tcon |= S3C2410_TCON_T2RELOAD | S3C2410_TCON_T2MANUALUPD |S3C2410_TCON_T2START;

	tcon &= ~(S3C2410_TCON_T3INVERT);
	tcon |= S3C2410_TCON_T3RELOAD | S3C2410_TCON_T3MANUALUPD |S3C2410_TCON_T3START;
	__raw_writel(tcon, S3C2410_TCON);

	tcon &= ~(S3C2410_TCON_T0MANUALUPD | S3C2410_TCON_T1MANUALUPD |
				S3C2410_TCON_T2MANUALUPD | S3C2410_TCON_T3MANUALUPD);
	__raw_writel(tcon, S3C2410_TCON);
	
	return 0;

}
Beispiel #18
0
/*
 * Set up timer interrupt, and return the current time in seconds.
 *
 * Currently we only use timer4, as it is the only timer which has no
 * other function that can be exploited externally
 */
void __init s3c2410_init_time (void)
{
	unsigned long tcon;
	unsigned long tcnt;
	unsigned long tcfg1;
	unsigned long tcfg0;

	gettimeoffset = s3c2410_gettimeoffset;

	tcnt = 0xffff;  /* default value for tcnt */

	/* read the current timer configuration bits */

	tcon = __raw_readl(S3C2410_TCON);
	tcfg1 = __raw_readl(S3C2410_TCFG1);
	tcfg0 = __raw_readl(S3C2410_TCFG0);

	/* configure the system for whichever machine is in use */

	if (machine_is_bast() || machine_is_vr1000()) {
		timer_ticks_usec = 12;	      /* timer is at 12MHz */
		tcnt = (timer_ticks_usec * (1000*1000)) / HZ;
	}

	/* for the h1940, we use the pclk from the core to generate
	 * the timer values. since 67.5MHz is not a value we can directly
	 * generate the timer value from, we need to pre-scale and
	 * divied before using it.
	 *
	 * overall divsior to get 200Hz is 337500
	 *   we can fit tcnt if we pre-scale by 6, producing a tick rate
	 *   of 11.25MHz, and a tcnt of 56250.
	 */

	if (machine_is_h1940() || machine_is_smdk2410() ) {
		timer_ticks_usec = s3c2410_pclk / (1000*1000);
		timer_ticks_usec /= 6;

		tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
		tcfg1 |= S3C2410_TCFG1_MUX4_DIV2;

		tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
		tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT;

		tcnt = (s3c2410_pclk / 6) / HZ;
	}


	printk("setup_timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx\n",
	       tcon, tcnt, tcfg0, tcfg1);

	/* check to see if timer is within 16bit range... */
	if (tcnt > 0xffff) {
		panic("setup_timer: HZ is too small, cannot configure timer!");
		return;
	}

	__raw_writel(tcfg1, S3C2410_TCFG1);
	__raw_writel(tcfg0, S3C2410_TCFG0);

	timer_startval = tcnt;
	__raw_writel(tcnt, S3C2410_TCNTB(4));

	/* ensure timer is stopped... */

	tcon &= ~(7<<20);
	tcon |= S3C2410_TCON_T4RELOAD;
	tcon |= S3C2410_TCON_T4MANUALUPD;

	__raw_writel(tcon, S3C2410_TCON);
	__raw_writel(tcnt, S3C2410_TCNTB(4));
	__raw_writel(tcnt, S3C2410_TCMPB(4));

	setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);

	/* start the timer running */
	tcon |= S3C2410_TCON_T4START;
	tcon &= ~S3C2410_TCON_T4MANUALUPD;
	__raw_writel(tcon, S3C2410_TCON);
}
Beispiel #19
0
int s3c2450_timer_setup (int channel, int usec, unsigned long g_tcnt, unsigned long g_tcmp)
{
	unsigned long tcon;
	unsigned long tcnt;
	unsigned long tcmp;
	unsigned long tcfg1;
	unsigned long tcfg0;
	unsigned long pclk;
	struct clk *clk;

	printk("\n\nPWM channel %d set g_tcnt = %ld, g_tcmp = %ld \n\n", channel, g_tcnt, g_tcmp);

	tcnt = 0xffffffff;  /* default value for tcnt */
	tcmp = 0;

	/* read the current timer configuration bits */
	tcon = __raw_readl(S3C2410_TCON);
	tcfg1 = __raw_readl(S3C2410_TCFG1);
	tcfg0 = __raw_readl(S3C2410_TCFG0);

	clk = clk_get(NULL, "timers");
	if (IS_ERR(clk))
		panic("failed to get clock for pwm timer");

	clk_enable(clk);

	pclk = clk_get_rate(clk);

	/* configure clock tick */

	switch(channel)
	{
		case 0:
			/* set gpio as PWM TIMER0 to signal output*/
			s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_TOUT0);
			s3c2410_gpio_setpin(S3C2410_GPB0, 0);
			tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;
			tcfg1 |= S3C2410_TCFG1_MUX0_DIV2;

			tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
			tcfg0 |= (4) << 0;
			tcon &= ~(7<<0);
			tcon |= S3C2410_TCON_T0RELOAD;
			break;

		case 1:
			/* set gpio as PWM TIMER1 to signal output*/
			s3c2410_gpio_cfgpin(S3C2410_GPB1, S3C2410_GPB1_TOUT1);
			s3c2410_gpio_setpin(S3C2410_GPB1, 0);
			tcfg1 &= ~S3C2410_TCFG1_MUX1_MASK;
			tcfg1 |= S3C2410_TCFG1_MUX1_DIV2;

			tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
			tcfg0 |= (4) << 0;

			tcon &= ~(7<<8);
			tcon |= S3C2410_TCON_T1RELOAD;
			break;
		case 2:
			s3c2410_gpio_cfgpin(S3C2410_GPB2, S3C2410_GPB2_TOUT2);
			s3c2410_gpio_setpin(S3C2410_GPB2, 0);
			tcfg1 &= ~S3C2410_TCFG1_MUX2_MASK;
			tcfg1 |= S3C2410_TCFG1_MUX2_DIV2;

			tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
			tcfg0 |= (4) << S3C2410_TCFG_PRESCALER1_SHIFT;

			tcon &= ~(7<<12);
			tcon |= S3C2410_TCON_T2RELOAD;
			break;
		case 3:
			s3c2410_gpio_cfgpin(S3C2410_GPB3, S3C2410_GPB3_TOUT3);
			s3c2410_gpio_setpin(S3C2410_GPB3, 0);
			tcfg1 &= ~S3C2410_TCFG1_MUX3_MASK;
			tcfg1 |= S3C2410_TCFG1_MUX3_DIV2;

			tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
			tcfg0 |= (4) << S3C2410_TCFG_PRESCALER1_SHIFT;
			tcon &= ~(7<<16);
			tcon |= S3C2410_TCON_T3RELOAD;
			break;
	}

#if 0

	tcnt = (pclk / ((PRESCALER)*DIVIDER)) / usec;

	printk("s3c2450 pwm timer tcnt=0x%08lx, pclk=0x%08lx, PRESCALER=%d, DIVIDER=%d, usec=%d\n",
	       tcnt, pclk, PRESCALER, DIVIDER, usec);

	/* timers reload after counting zero, so reduce the count by 1 */

	tcnt--;
#endif

	__raw_writel(tcfg1, S3C2410_TCFG1);
	__raw_writel(tcfg0, S3C2410_TCFG0);

	__raw_writel(tcon, S3C2410_TCON);
#if 0
	if (tcnt > 0xffffffff) {
		panic("setup_timer: HZ is too small, cannot configure timer!");
		return 0;
	}
#endif
	__raw_writel(tcnt, S3C2410_TCNTB(channel));
	__raw_writel(tcmp, S3C2410_TCMPB(channel));

	switch(channel)
	{
		case 0:
			tcon |= S3C2410_TCON_T0MANUALUPD;
			break;
		case 1:
			tcon |= S3C2410_TCON_T1MANUALUPD;
			break;
		case 2:
			tcon |= S3C2410_TCON_T2MANUALUPD;
			break;
		case 3:
			tcon |= S3C2410_TCON_T3MANUALUPD;
			break;
	}
	__raw_writel(tcon, S3C2410_TCON);

	tcnt = g_tcnt;
	__raw_writel(tcnt, S3C2410_TCNTB(channel));

	tcmp = g_tcmp;
	__raw_writel(tcmp, S3C2410_TCMPB(channel));

	/* start the timer running */

	s3c2450_pwm_start (channel);

	return 0;
}