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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b7fd2a0 was b7fd2a0, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

Use errno_t in all uspace and kernel code.

Change type of every variable, parameter and return value that holds an
<errno.h> constant to either errno_t (the usual case), or sys_errno_t
(some places in kernel). This is for the purpose of self-documentation,
as well as for type-checking with a bit of type definition hackery.

Although this is a massive commit, it is a simple text replacement, and thus
is very easy to verify. Simply do the following:

`
git checkout <this commit's hash>
git reset HEAD
git add .
tools/srepl '\berrno_t\b' int
git add .
tools/srepl '\bsys_errno_t\b' sysarg_t
git reset
git diff
`

While this doesn't ensure that the replacements are correct, it does ensure
that the commit doesn't do anything except those replacements. Since errno_t
is typedef'd to int in the usual case (and sys_errno_t to sysarg_t), even if
incorrect, this commit cannot change behavior.

  • Property mode set to 100644
File size: 5.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 <assert.h>
37#include <genarch/drivers/am335x/timer.h>
38#include <mm/km.h>
39#include <errno.h>
40
41typedef enum {
42 REG_TCLR = 0x00,
43 REG_TCRR = 0x01,
44 REG_TLDR = 0x02,
45 REG_TTGR = 0x04
46} timer_reg_t;
47
48typedef struct timer_regs_mmap {
49 uintptr_t base;
50 size_t size;
51} timer_regs_mmap_t;
52
53static const timer_regs_mmap_t regs_map[TIMERS_MAX] = {
54 { .base = AM335x_DMTIMER0_BASE_ADDRESS, .size = AM335x_DMTIMER0_SIZE },
55 {0, 0}, /* DMTIMER1 is not supported by this driver */
56 { .base = AM335x_DMTIMER2_BASE_ADDRESS, .size = AM335x_DMTIMER2_SIZE },
57 { .base = AM335x_DMTIMER3_BASE_ADDRESS, .size = AM335x_DMTIMER3_SIZE },
58 { .base = AM335x_DMTIMER4_BASE_ADDRESS, .size = AM335x_DMTIMER4_SIZE },
59 { .base = AM335x_DMTIMER5_BASE_ADDRESS, .size = AM335x_DMTIMER5_SIZE },
60 { .base = AM335x_DMTIMER6_BASE_ADDRESS, .size = AM335x_DMTIMER6_SIZE },
61 { .base = AM335x_DMTIMER7_BASE_ADDRESS, .size = AM335x_DMTIMER7_SIZE },
62};
63
64static void
65write_register_posted(am335x_timer_t *timer, timer_reg_t reg, uint32_t value)
66{
67 am335x_timer_regs_t *regs = timer->regs;
68
69 while (regs->twps & reg);
70
71 switch (reg) {
72 default:
73 return;
74 case REG_TCLR:
75 regs->tclr = value;
76 break;
77 case REG_TCRR:
78 regs->tcrr = value;
79 break;
80 case REG_TLDR:
81 regs->tldr = value;
82 break;
83 }
84}
85
86errno_t
87am335x_timer_init(am335x_timer_t *timer, am335x_timer_id_t id, unsigned hz,
88 unsigned srcclk_hz)
89{
90 uintptr_t base_addr;
91 size_t size;
92
93 assert(id < TIMERS_MAX);
94 assert(timer != NULL);
95
96 if (id == DMTIMER1_1MS)
97 return ENOTSUP; /* Not supported yet */
98
99 base_addr = regs_map[id].base;
100 size = regs_map[id].size;
101
102 timer->regs = (void *) km_map(base_addr, size, PAGE_NOT_CACHEABLE);
103 assert(timer->regs != NULL);
104
105 timer->id = id;
106
107 am335x_timer_regs_t *regs = timer->regs;
108
109 /* Enable the posted mode of operation */
110 regs->tsicr |= AM335x_TIMER_TSICR_POSTED_FLAG;
111
112 /* Stop the timer */
113 am335x_timer_stop(timer);
114
115 /* Perform a soft reset */
116 am335x_timer_reset(timer);
117
118 unsigned tclr = regs->tclr;
119
120 /* Disable compare mode */
121 tclr &= ~AM335x_TIMER_TCLR_CE_FLAG;
122
123 /* Enable auto-reload mode */
124 tclr |= AM335x_TIMER_TCLR_AR_FLAG;
125
126 write_register_posted(timer, REG_TCLR, tclr);
127
128 /* Disable the emulation mode */
129 regs->tiocp_cfg |= AM335x_TIMER_TIOCPCFG_EMUFREE_FLAG;
130
131 unsigned const count = 0xFFFFFFFF - (srcclk_hz / hz + 1);
132 write_register_posted(timer, REG_TCRR, count);
133 write_register_posted(timer, REG_TLDR, count);
134
135 return EOK;
136}
137
138void
139am335x_timer_intr_ack(am335x_timer_t *timer)
140{
141 /* Clear pending OVF event */
142 timer->regs->irqstatus |= AM335x_TIMER_IRQSTATUS_OVF_FLAG;
143}
144
145void
146am335x_timer_reset(am335x_timer_t *timer)
147{
148 /* Initiate soft reset */
149 timer->regs->tiocp_cfg |= AM335x_TIMER_TIOCPCFG_SOFTRESET_FLAG;
150 /* Wait until the reset is done */
151 while (timer->regs->tiocp_cfg & AM335x_TIMER_TIOCPCFG_SOFTRESET_FLAG);
152}
153
154void
155am335x_timer_stop(am335x_timer_t *timer)
156{
157 /* Disable the interrupt */
158 timer->regs->irqenable_clr |= AM335x_TIMER_IRQENABLE_CLR_OVF_FLAG;
159 timer->regs->irqwakeen &= ~AM335x_TIMER_IRQWAKEEN_OVF_FLAG;
160 /* Stop the timer */
161 write_register_posted(timer, REG_TCLR,
162 timer->regs->tclr & ~AM335x_TIMER_TCLR_ST_FLAG);
163}
164
165void
166am335x_timer_start(am335x_timer_t *timer)
167{
168 /* Enable the interrupt */
169 timer->regs->irqenable_set |= AM335x_TIMER_IRQENABLE_SET_OVF_FLAG;
170 timer->regs->irqwakeen |= AM335x_TIMER_IRQWAKEEN_OVF_FLAG;
171 /* Start the clock */
172 write_register_posted(timer, REG_TCLR,
173 timer->regs->tclr | AM335x_TIMER_TCLR_ST_FLAG);
174}
175
176/**
177 * @}
178 */
179
Note: See TracBrowser for help on using the repository browser.