source: mainline/kernel/genarch/src/drivers/am335x/timer.c@ 4c754f6

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

Improve the dmtimer modules initialization.

  • 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 unsigned srcclk_hz)
60{
61 uintptr_t base_addr;
62 size_t size;
63
64 ASSERT(id < TIMERS_MAX);
65
66 if (id == DMTIMER1_1MS)
67 return; /* Not supported yet */
68
69 base_addr = regs_map[id].base;
70 size = regs_map[id].size;
71
72 timer->regs = (void *) km_map(base_addr, size, PAGE_NOT_CACHEABLE);
73 timer->id = id;
74
75 am335x_timer_regs_t *regs = timer->regs;
76
77 /* Stop the timer */
78 am335x_timer_stop(timer);
79
80 /* Perform a soft reset */
81 am335x_timer_reset(timer);
82
83 /* Disable the prescaler */
84 regs->tclr &= ~AM335x_TIMER_TCLR_PRE_FLAG;
85
86 /* Enable auto-reload mode */
87 regs->tclr |= AM335x_TIMER_TCLR_AR_FLAG;
88
89 /* Disable the emulation mode */
90 regs->tiocp_cfg |= AM335x_TIMER_TIOCPCFG_EMUFREE_FLAG;
91
92 unsigned const count = 0xFFFFFFFE - (srcclk_hz / hz);
93 regs->tcrr = count;
94 regs->tldr = count;
95}
96
97void
98am335x_timer_intr_ack(am335x_timer_t *timer)
99{
100 /* Clear pending OVF event */
101 timer->regs->irqstatus |= AM335x_TIMER_IRQSTATUS_OVF_FLAG;
102}
103
104void
105am335x_timer_reset(am335x_timer_t *timer)
106{
107 /* Initiate soft reset */
108 timer->regs->tiocp_cfg |= AM335x_TIMER_TIOCPCFG_SOFTRESET_FLAG;
109 /* Wait until the reset is done */
110 while (timer->regs->tiocp_cfg & AM335x_TIMER_TIOCPCFG_SOFTRESET_FLAG);
111}
112
113void
114am335x_timer_stop(am335x_timer_t *timer)
115{
116 /* Disable the interrupt */
117 timer->regs->irqenable_clr |= AM335x_TIMER_IRQENABLE_CLR_OVF_FLAG;
118 /* Stop the timer */
119 timer->regs->tclr &= ~AM335x_TIMER_TCLR_ST_FLAG;
120}
121
122void
123am335x_timer_start(am335x_timer_t *timer)
124{
125 /* Enable the interrupt */
126 timer->regs->irqenable_set |= AM335x_TIMER_IRQENABLE_SET_OVF_FLAG;
127 /* Start the clock */
128 timer->regs->tclr |= AM335x_TIMER_TCLR_ST_FLAG;
129}
130
131/**
132 * @}
133 */
134
Note: See TracBrowser for help on using the repository browser.