dv-bfin_rtc.c revision 1.11 1 1.1 christos /* Blackfin Real Time Clock (RTC) model.
2 1.1 christos
3 1.11 christos Copyright (C) 2010-2024 Free Software Foundation, Inc.
4 1.1 christos Contributed by Analog Devices, Inc.
5 1.1 christos
6 1.1 christos This file is part of simulators.
7 1.1 christos
8 1.1 christos This program is free software; you can redistribute it and/or modify
9 1.1 christos it under the terms of the GNU General Public License as published by
10 1.1 christos the Free Software Foundation; either version 3 of the License, or
11 1.1 christos (at your option) any later version.
12 1.1 christos
13 1.1 christos This program is distributed in the hope that it will be useful,
14 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
15 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 1.1 christos GNU General Public License for more details.
17 1.1 christos
18 1.1 christos You should have received a copy of the GNU General Public License
19 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 1.1 christos
21 1.10 christos /* This must come before any other includes. */
22 1.10 christos #include "defs.h"
23 1.1 christos
24 1.1 christos #include <time.h>
25 1.1 christos #include "sim-main.h"
26 1.1 christos #include "dv-sockser.h"
27 1.1 christos #include "devices.h"
28 1.1 christos #include "dv-bfin_rtc.h"
29 1.1 christos
30 1.1 christos /* XXX: This read-only stub setup is based on host system clock. */
31 1.1 christos
32 1.1 christos struct bfin_rtc
33 1.1 christos {
34 1.1 christos bu32 base;
35 1.1 christos bu32 stat_shadow;
36 1.1 christos
37 1.1 christos /* Order after here is important -- matches hardware MMR layout. */
38 1.1 christos bu32 stat;
39 1.1 christos bu16 BFIN_MMR_16(ictl);
40 1.1 christos bu16 BFIN_MMR_16(istat);
41 1.1 christos bu16 BFIN_MMR_16(swcnt);
42 1.1 christos bu32 alarm;
43 1.1 christos bu16 BFIN_MMR_16(pren);
44 1.1 christos };
45 1.1 christos #define mmr_base() offsetof(struct bfin_rtc, stat)
46 1.1 christos #define mmr_offset(mmr) (offsetof(struct bfin_rtc, mmr) - mmr_base())
47 1.1 christos
48 1.1 christos static const char * const mmr_names[] =
49 1.1 christos {
50 1.1 christos "RTC_STAT", "RTC_ICTL", "RTC_ISTAT", "RTC_SWCNT", "RTC_ALARM", "RTC_PREN",
51 1.1 christos };
52 1.1 christos #define mmr_name(off) mmr_names[(off) / 4]
53 1.1 christos
54 1.1 christos static unsigned
55 1.1 christos bfin_rtc_io_write_buffer (struct hw *me, const void *source,
56 1.1 christos int space, address_word addr, unsigned nr_bytes)
57 1.1 christos {
58 1.1 christos struct bfin_rtc *rtc = hw_data (me);
59 1.1 christos bu32 mmr_off;
60 1.1 christos bu32 value;
61 1.1 christos bu16 *value16p;
62 1.1 christos void *valuep;
63 1.1 christos
64 1.6 christos /* Invalid access mode is higher priority than missing register. */
65 1.6 christos if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, true))
66 1.6 christos return 0;
67 1.6 christos
68 1.1 christos if (nr_bytes == 4)
69 1.1 christos value = dv_load_4 (source);
70 1.1 christos else
71 1.1 christos value = dv_load_2 (source);
72 1.1 christos
73 1.1 christos mmr_off = addr - rtc->base;
74 1.10 christos valuep = (void *)((uintptr_t)rtc + mmr_base() + mmr_off);
75 1.1 christos value16p = valuep;
76 1.1 christos
77 1.1 christos HW_TRACE_WRITE ();
78 1.1 christos
79 1.1 christos /* XXX: These probably need more work. */
80 1.1 christos switch (mmr_off)
81 1.1 christos {
82 1.1 christos case mmr_offset(stat):
83 1.1 christos /* XXX: Ignore these since we are wired to host. */
84 1.1 christos break;
85 1.1 christos case mmr_offset(istat):
86 1.1 christos dv_w1c_2 (value16p, value, ~(1 << 14));
87 1.1 christos break;
88 1.1 christos case mmr_offset(alarm):
89 1.1 christos break;
90 1.1 christos case mmr_offset(ictl):
91 1.1 christos /* XXX: This should schedule an event handler. */
92 1.1 christos case mmr_offset(swcnt):
93 1.1 christos case mmr_offset(pren):
94 1.1 christos break;
95 1.1 christos }
96 1.1 christos
97 1.1 christos return nr_bytes;
98 1.1 christos }
99 1.1 christos
100 1.1 christos static unsigned
101 1.1 christos bfin_rtc_io_read_buffer (struct hw *me, void *dest,
102 1.1 christos int space, address_word addr, unsigned nr_bytes)
103 1.1 christos {
104 1.1 christos struct bfin_rtc *rtc = hw_data (me);
105 1.1 christos bu32 mmr_off;
106 1.1 christos bu16 *value16p;
107 1.1 christos bu32 *value32p;
108 1.1 christos void *valuep;
109 1.1 christos
110 1.6 christos /* Invalid access mode is higher priority than missing register. */
111 1.6 christos if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, false))
112 1.6 christos return 0;
113 1.6 christos
114 1.1 christos mmr_off = addr - rtc->base;
115 1.10 christos valuep = (void *)((uintptr_t)rtc + mmr_base() + mmr_off);
116 1.1 christos value16p = valuep;
117 1.1 christos value32p = valuep;
118 1.1 christos
119 1.1 christos HW_TRACE_READ ();
120 1.1 christos
121 1.1 christos switch (mmr_off)
122 1.1 christos {
123 1.1 christos case mmr_offset(stat):
124 1.1 christos {
125 1.1 christos time_t t = time (NULL);
126 1.1 christos struct tm *tm = localtime (&t);
127 1.1 christos bu32 value =
128 1.1 christos (((tm->tm_year - 70) * 365 + tm->tm_yday) << 17) |
129 1.1 christos (tm->tm_hour << 12) |
130 1.1 christos (tm->tm_min << 6) |
131 1.1 christos (tm->tm_sec << 0);
132 1.1 christos dv_store_4 (dest, value);
133 1.1 christos break;
134 1.1 christos }
135 1.1 christos case mmr_offset(alarm):
136 1.1 christos dv_store_4 (dest, *value32p);
137 1.1 christos break;
138 1.1 christos case mmr_offset(istat):
139 1.1 christos case mmr_offset(ictl):
140 1.1 christos case mmr_offset(swcnt):
141 1.1 christos case mmr_offset(pren):
142 1.1 christos dv_store_2 (dest, *value16p);
143 1.1 christos break;
144 1.1 christos }
145 1.1 christos
146 1.1 christos return nr_bytes;
147 1.1 christos }
148 1.1 christos
149 1.1 christos static const struct hw_port_descriptor bfin_rtc_ports[] =
150 1.1 christos {
151 1.1 christos { "rtc", 0, 0, output_port, },
152 1.1 christos { NULL, 0, 0, 0, },
153 1.1 christos };
154 1.1 christos
155 1.1 christos static void
156 1.1 christos attach_bfin_rtc_regs (struct hw *me, struct bfin_rtc *rtc)
157 1.1 christos {
158 1.1 christos address_word attach_address;
159 1.1 christos int attach_space;
160 1.1 christos unsigned attach_size;
161 1.1 christos reg_property_spec reg;
162 1.1 christos
163 1.1 christos if (hw_find_property (me, "reg") == NULL)
164 1.1 christos hw_abort (me, "Missing \"reg\" property");
165 1.1 christos
166 1.1 christos if (!hw_find_reg_array_property (me, "reg", 0, ®))
167 1.1 christos hw_abort (me, "\"reg\" property must contain three addr/size entries");
168 1.1 christos
169 1.1 christos hw_unit_address_to_attach_address (hw_parent (me),
170 1.1 christos ®.address,
171 1.1 christos &attach_space, &attach_address, me);
172 1.1 christos hw_unit_size_to_attach_size (hw_parent (me), ®.size, &attach_size, me);
173 1.1 christos
174 1.1 christos if (attach_size != BFIN_MMR_RTC_SIZE)
175 1.1 christos hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_RTC_SIZE);
176 1.1 christos
177 1.1 christos hw_attach_address (hw_parent (me),
178 1.1 christos 0, attach_space, attach_address, attach_size, me);
179 1.1 christos
180 1.1 christos rtc->base = attach_address;
181 1.1 christos }
182 1.1 christos
183 1.1 christos static void
184 1.1 christos bfin_rtc_finish (struct hw *me)
185 1.1 christos {
186 1.1 christos struct bfin_rtc *rtc;
187 1.1 christos
188 1.1 christos rtc = HW_ZALLOC (me, struct bfin_rtc);
189 1.1 christos
190 1.1 christos set_hw_data (me, rtc);
191 1.1 christos set_hw_io_read_buffer (me, bfin_rtc_io_read_buffer);
192 1.1 christos set_hw_io_write_buffer (me, bfin_rtc_io_write_buffer);
193 1.1 christos set_hw_ports (me, bfin_rtc_ports);
194 1.1 christos
195 1.1 christos attach_bfin_rtc_regs (me, rtc);
196 1.1 christos
197 1.1 christos /* Initialize the RTC. */
198 1.1 christos }
199 1.1 christos
200 1.1 christos const struct hw_descriptor dv_bfin_rtc_descriptor[] =
201 1.1 christos {
202 1.1 christos {"bfin_rtc", bfin_rtc_finish,},
203 1.1 christos {NULL, NULL},
204 1.1 christos };
205