Ejemplo n.º 1
0
static void r_tpu_start_stop_ch(struct r_tpu_priv *p, int start)
{
	struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
	unsigned long flags, value;

	/* start stop register shared by multiple timer channels */
	spin_lock_irqsave(&r_tpu_lock, flags);
	value = r_tpu_read(p, TSTR);

	if (start)
		value |= 1 << cfg->timer_bit;
	else
		value &= ~(1 << cfg->timer_bit);

	r_tpu_write(p, TSTR, value);
	spin_unlock_irqrestore(&r_tpu_lock, flags);
}
Ejemplo n.º 2
0
static int r_tpu_enable(struct r_tpu_priv *p, enum led_brightness brightness)
{
	struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
	int prescaler[] = { 1, 4, 16, 64 };
	int k, ret;
	unsigned long rate, tmp;

	if (p->timer_state == R_TPU_TIMER_ON)
		return 0;

	/* wake up device and enable clock */
	pm_runtime_get_sync(&p->pdev->dev);
	ret = clk_enable(p->clk);
	if (ret) {
		dev_err(&p->pdev->dev, "cannot enable clock\n");
		return ret;
	}

	/* make sure channel is disabled */
	r_tpu_start_stop_ch(p, 0);

	/* get clock rate after enabling it */
	rate = clk_get_rate(p->clk);

	/* pick the lowest acceptable rate */
	for (k = 0; k < ARRAY_SIZE(prescaler); k++)
		if ((rate / prescaler[k]) < p->min_rate)
			break;

	if (!k) {
		dev_err(&p->pdev->dev, "clock rate mismatch\n");
		goto err0;
	}
	dev_dbg(&p->pdev->dev, "rate = %lu, prescaler %u\n",
		rate, prescaler[k - 1]);

	/* clear TCNT on TGRB match, count on rising edge, set prescaler */
	r_tpu_write(p, TCR, 0x0040 | (k - 1));

	/* output 0 until TGRA, output 1 until TGRB */
	r_tpu_write(p, TIOR, 0x0002);

	rate /= prescaler[k - 1] * p->refresh_rate;
	r_tpu_write(p, TGRB, rate);
	dev_dbg(&p->pdev->dev, "TRGB = 0x%04lx\n", rate);

	tmp = (cfg->max_brightness - brightness) * rate;
	r_tpu_write(p, TGRA, tmp / cfg->max_brightness);
	dev_dbg(&p->pdev->dev, "TRGA = 0x%04lx\n", tmp / cfg->max_brightness);

	/* PWM mode */
	r_tpu_write(p, TMDR, 0x0002);

	/* enable channel */
	r_tpu_start_stop_ch(p, 1);

	p->timer_state = R_TPU_TIMER_ON;
	return 0;
 err0:
	clk_disable(p->clk);
	pm_runtime_put_sync(&p->pdev->dev);
	return -ENOTSUPP;
}
static int r_tpu_enable(struct r_tpu_priv *p, enum led_brightness brightness)
{
	struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
	int prescaler[] = { 1, 4, 16, 64 };
	int k, ret;
	unsigned long rate, tmp;

	if (p->timer_state == R_TPU_TIMER_ON)
		return 0;

	
	pm_runtime_get_sync(&p->pdev->dev);
	ret = clk_enable(p->clk);
	if (ret) {
		dev_err(&p->pdev->dev, "cannot enable clock\n");
		return ret;
	}

	
	r_tpu_start_stop_ch(p, 0);

	
	rate = clk_get_rate(p->clk);

	
	for (k = 0; k < ARRAY_SIZE(prescaler); k++)
		if ((rate / prescaler[k]) < p->min_rate)
			break;

	if (!k) {
		dev_err(&p->pdev->dev, "clock rate mismatch\n");
		goto err0;
	}
	dev_dbg(&p->pdev->dev, "rate = %lu, prescaler %u\n",
		rate, prescaler[k - 1]);

	
	r_tpu_write(p, TCR, 0x0040 | (k - 1));

	
	r_tpu_write(p, TIOR, 0x0002);

	rate /= prescaler[k - 1] * p->refresh_rate;
	r_tpu_write(p, TGRB, rate);
	dev_dbg(&p->pdev->dev, "TRGB = 0x%04lx\n", rate);

	tmp = (cfg->max_brightness - brightness) * rate;
	r_tpu_write(p, TGRA, tmp / cfg->max_brightness);
	dev_dbg(&p->pdev->dev, "TRGA = 0x%04lx\n", tmp / cfg->max_brightness);

	
	r_tpu_write(p, TMDR, 0x0002);

	
	r_tpu_start_stop_ch(p, 1);

	p->timer_state = R_TPU_TIMER_ON;
	return 0;
 err0:
	clk_disable(p->clk);
	pm_runtime_put_sync(&p->pdev->dev);
	return -ENOTSUPP;
}