⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dmtimer.c

📁 linux-2.6.15.6
💻 C
字号:
/* * linux/arch/arm/plat-omap/dmtimer.c * * OMAP Dual-Mode Timers * * Copyright (C) 2005 Nokia Corporation * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You should have received a copy of the  GNU General Public License along * with this program; if not, write  to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */#include <linux/init.h>#include <asm/hardware.h>#include <asm/arch/dmtimer.h>#include <asm/io.h>#include <asm/arch/irqs.h>#include <linux/spinlock.h>#include <linux/list.h>#define OMAP_TIMER_COUNT		8#define OMAP_TIMER_ID_REG		0x00#define OMAP_TIMER_OCP_CFG_REG		0x10#define OMAP_TIMER_SYS_STAT_REG		0x14#define OMAP_TIMER_STAT_REG		0x18#define OMAP_TIMER_INT_EN_REG		0x1c#define OMAP_TIMER_WAKEUP_EN_REG	0x20#define OMAP_TIMER_CTRL_REG		0x24#define OMAP_TIMER_COUNTER_REG		0x28#define OMAP_TIMER_LOAD_REG		0x2c#define OMAP_TIMER_TRIGGER_REG		0x30#define OMAP_TIMER_WRITE_PEND_REG 	0x34#define OMAP_TIMER_MATCH_REG		0x38#define OMAP_TIMER_CAPTURE_REG		0x3c#define OMAP_TIMER_IF_CTRL_REG		0x40static struct dmtimer_info_struct {	struct list_head	unused_timers;	struct list_head	reserved_timers;} dm_timer_info;static struct omap_dm_timer dm_timers[] = {	{ .base=0xfffb1400, .irq=INT_1610_GPTIMER1 },	{ .base=0xfffb1c00, .irq=INT_1610_GPTIMER2 },	{ .base=0xfffb2400, .irq=INT_1610_GPTIMER3 },	{ .base=0xfffb2c00, .irq=INT_1610_GPTIMER4 },	{ .base=0xfffb3400, .irq=INT_1610_GPTIMER5 },	{ .base=0xfffb3c00, .irq=INT_1610_GPTIMER6 },	{ .base=0xfffb4400, .irq=INT_1610_GPTIMER7 },	{ .base=0xfffb4c00, .irq=INT_1610_GPTIMER8 },	{ .base=0x0 },};static spinlock_t dm_timer_lock;inline void omap_dm_timer_write_reg(struct omap_dm_timer *timer, int reg, u32 value){	omap_writel(value, timer->base + reg);	while (omap_dm_timer_read_reg(timer, OMAP_TIMER_WRITE_PEND_REG))		;}u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg){	return omap_readl(timer->base + reg);}int omap_dm_timers_active(void){	struct omap_dm_timer *timer;	for (timer = &dm_timers[0]; timer->base; ++timer)		if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &		    OMAP_TIMER_CTRL_ST)			return 1;	return 0;}void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source){	int n = (timer - dm_timers) << 1;	u32 l;	l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);	l |= source << n;	omap_writel(l, MOD_CONF_CTRL_1);}static void omap_dm_timer_reset(struct omap_dm_timer *timer){	/* Reset and set posted mode */	omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);	omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, 0x02);	omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_ARMXOR);}struct omap_dm_timer * omap_dm_timer_request(void){	struct omap_dm_timer *timer = NULL;	unsigned long flags;	spin_lock_irqsave(&dm_timer_lock, flags);	if (!list_empty(&dm_timer_info.unused_timers)) {		timer = (struct omap_dm_timer *)				dm_timer_info.unused_timers.next;		list_move_tail((struct list_head *)timer,				&dm_timer_info.reserved_timers);	}	spin_unlock_irqrestore(&dm_timer_lock, flags);	return timer;}void omap_dm_timer_free(struct omap_dm_timer *timer){	unsigned long flags;	omap_dm_timer_reset(timer);	spin_lock_irqsave(&dm_timer_lock, flags);	list_move_tail((struct list_head *)timer, &dm_timer_info.unused_timers);	spin_unlock_irqrestore(&dm_timer_lock, flags);}void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,				unsigned int value){	omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);}unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer){	return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);}void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value){	omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);}void omap_dm_timer_enable_autoreload(struct omap_dm_timer *timer){	u32 l;	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);	l |= OMAP_TIMER_CTRL_AR;	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);}void omap_dm_timer_trigger(struct omap_dm_timer *timer){	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 1);}void omap_dm_timer_set_trigger(struct omap_dm_timer *timer, unsigned int value){	u32 l;	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);	l |= value & 0x3;	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);}void omap_dm_timer_start(struct omap_dm_timer *timer){	u32 l;	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);	l |= OMAP_TIMER_CTRL_ST;	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);}void omap_dm_timer_stop(struct omap_dm_timer *timer){	u32 l;	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);	l &= ~0x1;	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);}unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer){	return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);}void omap_dm_timer_reset_counter(struct omap_dm_timer *timer){	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, 0);}void omap_dm_timer_set_load(struct omap_dm_timer *timer, unsigned int load){	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);}void omap_dm_timer_set_match(struct omap_dm_timer *timer, unsigned int match){	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);}void omap_dm_timer_enable_compare(struct omap_dm_timer *timer){	u32 l;	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);	l |= OMAP_TIMER_CTRL_CE;	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);}static inline void __dm_timer_init(void){	struct omap_dm_timer *timer;	spin_lock_init(&dm_timer_lock);	INIT_LIST_HEAD(&dm_timer_info.unused_timers);	INIT_LIST_HEAD(&dm_timer_info.reserved_timers);	timer = &dm_timers[0];	while (timer->base) {		list_add_tail((struct list_head *)timer, &dm_timer_info.unused_timers);		omap_dm_timer_reset(timer);		timer++;	}}static int __init omap_dm_timer_init(void){	if (cpu_is_omap16xx())		__dm_timer_init();	return 0;}arch_initcall(omap_dm_timer_init);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -