Esempio n. 1
0
static int sh_tmu_enable(struct sh_tmu_priv *p)
{
	int ret;

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

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

	/* maximum timeout */
	sh_tmu_write(p, TCOR, 0xffffffff);
	sh_tmu_write(p, TCNT, 0xffffffff);

	/* configure channel to parent clock / 4, irq off */
	p->rate = clk_get_rate(p->clk) / 4;
	sh_tmu_write(p, TCR, 0x0000);

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

	return 0;
}
Esempio n. 2
0
static int __sh_tmu_enable(struct sh_tmu_channel *ch)
{
	int ret;

	/* enable clock */
	ret = clk_enable(ch->tmu->clk);
	if (ret) {
		dev_err(&ch->tmu->pdev->dev, "ch%u: cannot enable clock\n",
			ch->index);
		return ret;
	}

	/* make sure channel is disabled */
	sh_tmu_start_stop_ch(ch, 0);

	/* maximum timeout */
	sh_tmu_write(ch, TCOR, 0xffffffff);
	sh_tmu_write(ch, TCNT, 0xffffffff);

	/* configure channel to parent clock / 4, irq off */
	ch->rate = clk_get_rate(ch->tmu->clk) / 4;
	sh_tmu_write(ch, TCR, TCR_TPSC_CLK4);

	/* enable channel */
	sh_tmu_start_stop_ch(ch, 1);

	return 0;
}
Esempio n. 3
0
static int sh_tmu_enable(struct sh_tmu_priv *p)
{
	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
	int ret;

	/* enable clock */
	ret = clk_enable(p->clk);
	if (ret) {
		pr_err("sh_tmu: cannot enable clock \"%s\"\n", cfg->clk);
		return ret;
	}

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

	/* maximum timeout */
	sh_tmu_write(p, TCOR, 0xffffffff);
	sh_tmu_write(p, TCNT, 0xffffffff);

	/* configure channel to parent clock / 4, irq off */
	p->rate = clk_get_rate(p->clk) / 4;
	sh_tmu_write(p, TCR, 0x0000);

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

	return 0;
}
Esempio n. 4
0
/* A Channel not used as clock source or for clock event (e.g. TMU2)
 * can be used as generic timer and registered by another device. */
struct sh_timer_callb *sh_timer_register(void *handler, void *data)
{
	struct sh_tmu_priv *p = NULL;
	int ret, i;
	/* As first element, look at the channel 2 because usually not
	 * used. */
	char *c[] = { "sh_tmu.2", "sh_tmu.1", "sh_tmu.0" };

	for (i = 0; i < ARRAY_SIZE(c); i++) {
		struct device *dev = bus_find_device_by_name(&platform_bus_type,
							     NULL, c[i]);
		if (dev) {
			struct sh_timer_config *cfg = dev->platform_data;

			if (!cfg->clockevent_rating &&
			    !cfg->clocksource_rating) {
				p = dev_get_drvdata(dev);
				break;
			}
		}
	}

	/* Check if the channel has been not already registered as timer. */
	if ((p == NULL) || (p->tm.fnc != NULL))
		return NULL;

	if (handler == NULL) {
		pr_err("sh_tmu: invalid handler\n");
		return NULL;
	}

	p->tm.fnc = kmalloc(sizeof(struct sh_timer_callb *),
				      GFP_KERNEL);
	if  (p->tm.fnc == NULL)
		return NULL;

	/* Prepare the new handler */
	p->irqaction.handler = sh_timer_interrupt;
	p->tm.priv_handler = handler;
	p->tm.data = data;

	ret = setup_irq(p->irqaction.irq, &p->irqaction);
	if (ret) {
		pr_err("sh_tmu: failed to request irq %d\n", p->irqaction.irq);
		return NULL;
	}

	/* Channel is stopped and irq off */
	sh_timer_stop(p);
	sh_tmu_write(p, TCOR, 0xffffffff);
	sh_tmu_write(p, TCNT, 0xffffffff);
	p->rate = clk_get_rate(p->clk) / 4;

	p->tm.fnc->tmu_priv = p; /* hook to invoke the timer callbacks */
	p->tm.fnc->timer_start = sh_timer_start;
	p->tm.fnc->timer_stop = sh_timer_stop;
	p->tm.fnc->set_rate = sh_timer_set_rate;

	return p->tm.fnc;
}
Esempio n. 5
0
static irqreturn_t sh_tmu_interrupt(int irq, void *dev_id)
{
	struct sh_tmu_channel *ch = dev_id;

	/* disable or acknowledge interrupt */
	if (ch->ced.mode == CLOCK_EVT_MODE_ONESHOT)
		sh_tmu_write(ch, TCR, TCR_TPSC_CLK4);
	else
		sh_tmu_write(ch, TCR, TCR_UNIE | TCR_TPSC_CLK4);

	/* notify clockevent layer */
	ch->ced.event_handler(&ch->ced);
	return IRQ_HANDLED;
}
Esempio n. 6
0
static irqreturn_t sh_tmu_interrupt(int irq, void *dev_id)
{
	struct sh_tmu_priv *p = dev_id;

	/* disable or acknowledge interrupt */
	if (p->ced.mode == CLOCK_EVT_MODE_ONESHOT)
		sh_tmu_write(p, TCR, 0x0000);
	else
		sh_tmu_write(p, TCR, 0x0020);

	/* notify clockevent layer */
	p->ced.event_handler(&p->ced);
	return IRQ_HANDLED;
}
Esempio n. 7
0
static void sh_timer_stop(void *priv)
{
	struct sh_tmu_priv *p = priv;

	sh_tmu_start_stop_ch(p, 0);
	sh_tmu_write(p, TCR, 0x0000);
}
Esempio n. 8
0
static irqreturn_t sh_timer_interrupt(int irq, void *dev_id)
{
	struct sh_tmu_priv *p = dev_id;

	sh_tmu_write(p, TCR, 0x0020);

	p->tm.priv_handler(p->tm.data);
	return IRQ_HANDLED;
}
Esempio n. 9
0
static void __sh_tmu_disable(struct sh_tmu_channel *ch)
{
	/* disable channel */
	sh_tmu_start_stop_ch(ch, 0);

	/* disable interrupts in TMU block */
	sh_tmu_write(ch, TCR, TCR_TPSC_CLK4);

	/* stop clock */
	clk_disable(ch->tmu->clk);
}
Esempio n. 10
0
static void sh_tmu_disable(struct sh_tmu_priv *p)
{
	/* disable channel */
	sh_tmu_start_stop_ch(p, 0);

	/* disable interrupts in TMU block */
	sh_tmu_write(p, TCR, 0x0000);

	/* stop clock */
	clk_disable(p->clk);
}
Esempio n. 11
0
static void sh_tmu_set_next(struct sh_tmu_channel *ch, unsigned long delta,
			    int periodic)
{
	/* stop timer */
	sh_tmu_start_stop_ch(ch, 0);

	/* acknowledge interrupt */
	sh_tmu_read(ch, TCR);

	/* enable interrupt */
	sh_tmu_write(ch, TCR, TCR_UNIE | TCR_TPSC_CLK4);

	/* reload delta value in case of periodic timer */
	if (periodic)
		sh_tmu_write(ch, TCOR, delta);
	else
		sh_tmu_write(ch, TCOR, 0xffffffff);

	sh_tmu_write(ch, TCNT, delta);

	/* start timer */
	sh_tmu_start_stop_ch(ch, 1);
}
Esempio n. 12
0
static void sh_tmu_set_next(struct sh_tmu_priv *p, unsigned long delta,
			    int periodic)
{
	/* stop timer */
	sh_tmu_start_stop_ch(p, 0);

	/* acknowledge interrupt */
	sh_tmu_read(p, TCR);

	/* enable interrupt */
	sh_tmu_write(p, TCR, 0x0020);

	/* reload delta value in case of periodic timer */
	if (periodic)
		sh_tmu_write(p, TCOR, delta);
	else
		sh_tmu_write(p, TCOR, 0xffffffff);

	sh_tmu_write(p, TCNT, delta);

	/* start timer */
	sh_tmu_start_stop_ch(p, 1);
}
Esempio n. 13
0
static void sh_tmu_start_stop_ch(struct sh_tmu_channel *ch, int start)
{
	unsigned long flags, value;

	/* start stop register shared by multiple timer channels */
	raw_spin_lock_irqsave(&ch->tmu->lock, flags);
	value = sh_tmu_read(ch, TSTR);

	if (start)
		value |= 1 << ch->index;
	else
		value &= ~(1 << ch->index);

	sh_tmu_write(ch, TSTR, value);
	raw_spin_unlock_irqrestore(&ch->tmu->lock, flags);
}
Esempio n. 14
0
static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start)
{
	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
	unsigned long flags, value;

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

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

	sh_tmu_write(p, TSTR, value);
	spin_unlock_irqrestore(&sh_tmu_lock, flags);
}