source: mainline/kernel/genarch/src/drivers/am335x/timer.c@ 6f07226

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6f07226 was 42f2a45, checked in by Maurizio Lombardi <m.lombardi85@…>, 13 years ago

am335x: Add the timer driver implementation

  • Property mode set to 100644
File size: 4.0 KB
Line 
1/*
2 * Copyright (c) 2012 Maurizio Lombardi
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28/** @addtogroup genarch
29 * @{
30 */
31/**
32 * @file
33 * @brief Texas Instruments AM335x timer driver.
34 */
35
36#include <genarch/drivers/am335x/timer.h>
37#include <mm/km.h>
38#include <errno.h>
39
40
41typedef struct timer_regs_mmap {
42 uintptr_t base;
43 size_t size;
44} timer_regs_mmap_t;
45
46static const timer_regs_mmap_t regs_map[TIMERS_MAX] = {
47 { .base = AM335x_DMTIMER0_BASE_ADDRESS, .size = AM335x_DMTIMER0_SIZE },
48 {0, 0},
49 { .base = AM335x_DMTIMER2_BASE_ADDRESS, .size = AM335x_DMTIMER2_SIZE },
50 { .base = AM335x_DMTIMER3_BASE_ADDRESS, .size = AM335x_DMTIMER3_SIZE },
51 { .base = AM335x_DMTIMER4_BASE_ADDRESS, .size = AM335x_DMTIMER4_SIZE },
52 { .base = AM335x_DMTIMER5_BASE_ADDRESS, .size = AM335x_DMTIMER5_SIZE },
53 { .base = AM335x_DMTIMER6_BASE_ADDRESS, .size = AM335x_DMTIMER6_SIZE },
54 { .base = AM335x_DMTIMER7_BASE_ADDRESS, .size = AM335x_DMTIMER7_SIZE },
55};
56
57void
58am335x_timer_init(am335x_timer_t *timer, am335x_timer_id_t id, unsigned hz)
59{
60 uintptr_t base_addr;
61 size_t size;
62
63 ASSERT(id < TIMERS_MAX);
64
65 if (id == DMTIMER1_1MS)
66 return; /* Not supported yet */
67
68 base_addr = regs_map[id].base;
69 size = regs_map[id].size;
70
71 timer->regs = (void *) km_map(base_addr, size, PAGE_NOT_CACHEABLE);
72 timer->id = id;
73
74 am335x_timer_regs_t *regs = timer->regs;
75
76 /* Stop the timer */
77 am335x_timer_stop(timer);
78
79 /* Perform a soft reset */
80 am335x_timer_reset(timer);
81
82 /* Disable the prescaler */
83 regs->tclr &= ~AM335x_TIMER_TCLR_PRE_FLAG;
84
85 /* Enable auto-reload mode */
86 regs->tclr |= AM335x_TIMER_TCLR_AR_FLAG;
87
88 /* XXX Here we assume that the timer clock source
89 * is running at 32 Khz but this is not always the
90 * case; DMTIMER[2 - 7] can use the internal system 24 Mhz
91 * clock source or an external clock also.
92 */
93 unsigned const count = 0xFFFFFFFE - 32768 / hz;
94 regs->tcrr = count;
95 regs->tldr = count;
96}
97
98void
99am335x_timer_intr_ack(am335x_timer_t *timer)
100{
101 /* Clear pending OVF event */
102 timer->regs->irqstatus |= AM335x_TIMER_IRQSTATUS_OVF_FLAG;
103}
104
105void
106am335x_timer_reset(am335x_timer_t *timer)
107{
108 /* Initiate soft reset */
109 timer->regs->tiocp_cfg |= AM335x_TIMER_TIOCPCFG_SOFTRESET_FLAG;
110 /* Wait until the reset is done */
111 while (timer->regs->tiocp_cfg & AM335x_TIMER_TIOCPCFG_SOFTRESET_FLAG);
112}
113
114void
115am335x_timer_stop(am335x_timer_t *timer)
116{
117 /* Disable the interrupt */
118 timer->regs->irqenable_clr |= AM335x_TIMER_IRQENABLE_CLR_OVF_FLAG;
119 /* Stop the timer */
120 timer->regs->tclr &= ~AM335x_TIMER_TCLR_ST_FLAG;
121}
122
123void
124am335x_timer_start(am335x_timer_t *timer)
125{
126 /* Enable the interrupt */
127 timer->regs->irqenable_set |= AM335x_TIMER_IRQENABLE_SET_OVF_FLAG;
128 /* Start the clock */
129 timer->regs->tclr |= AM335x_TIMER_TCLR_ST_FLAG;
130}
131
132/**
133 * @}
134 */
135
Note: See TracBrowser for help on using the repository browser.