dv-bfin_wdog.c revision 1.1.1.1.8.1 1 1.1 christos /* Blackfin Watchdog (WDOG) model.
2 1.1 christos
3 1.1.1.1.8.1 tls Copyright (C) 2010-2014 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.1 christos #include "config.h"
22 1.1 christos
23 1.1 christos #include "sim-main.h"
24 1.1 christos #include "dv-sockser.h"
25 1.1 christos #include "devices.h"
26 1.1 christos #include "dv-bfin_wdog.h"
27 1.1 christos
28 1.1 christos /* XXX: Should we bother emulating the TX/RX FIFOs ? */
29 1.1 christos
30 1.1 christos struct bfin_wdog
31 1.1 christos {
32 1.1 christos bu32 base;
33 1.1 christos
34 1.1 christos /* Order after here is important -- matches hardware MMR layout. */
35 1.1 christos bu16 BFIN_MMR_16(ctl);
36 1.1 christos bu32 cnt, stat;
37 1.1 christos };
38 1.1 christos #define mmr_base() offsetof(struct bfin_wdog, ctl)
39 1.1 christos #define mmr_offset(mmr) (offsetof(struct bfin_wdog, mmr) - mmr_base())
40 1.1 christos
41 1.1 christos static const char * const mmr_names[] =
42 1.1 christos {
43 1.1 christos "WDOG_CTL", "WDOG_CNT", "WDOG_STAT",
44 1.1 christos };
45 1.1 christos #define mmr_name(off) mmr_names[(off) / 4]
46 1.1 christos
47 1.1 christos static bool
48 1.1 christos bfin_wdog_enabled (struct bfin_wdog *wdog)
49 1.1 christos {
50 1.1 christos return ((wdog->ctl & WDEN) != WDDIS);
51 1.1 christos }
52 1.1 christos
53 1.1 christos static unsigned
54 1.1 christos bfin_wdog_io_write_buffer (struct hw *me, const void *source,
55 1.1 christos int space, address_word addr, unsigned nr_bytes)
56 1.1 christos {
57 1.1 christos struct bfin_wdog *wdog = hw_data (me);
58 1.1 christos bu32 mmr_off;
59 1.1 christos bu32 value;
60 1.1 christos bu16 *value16p;
61 1.1 christos bu32 *value32p;
62 1.1 christos void *valuep;
63 1.1 christos
64 1.1 christos if (nr_bytes == 4)
65 1.1 christos value = dv_load_4 (source);
66 1.1 christos else
67 1.1 christos value = dv_load_2 (source);
68 1.1 christos
69 1.1 christos mmr_off = addr - wdog->base;
70 1.1 christos valuep = (void *)((unsigned long)wdog + mmr_base() + mmr_off);
71 1.1 christos value16p = valuep;
72 1.1 christos value32p = valuep;
73 1.1 christos
74 1.1 christos HW_TRACE_WRITE ();
75 1.1 christos
76 1.1 christos switch (mmr_off)
77 1.1 christos {
78 1.1 christos case mmr_offset(ctl):
79 1.1 christos dv_w1c_2_partial (value16p, value, WDRO);
80 1.1 christos /* XXX: Should enable an event here to handle timeouts. */
81 1.1 christos break;
82 1.1 christos
83 1.1 christos case mmr_offset(cnt):
84 1.1 christos /* Writes are discarded when enabeld. */
85 1.1 christos if (!bfin_wdog_enabled (wdog))
86 1.1 christos {
87 1.1 christos *value32p = value;
88 1.1 christos /* Writes to CNT preloads the STAT. */
89 1.1 christos wdog->stat = wdog->cnt;
90 1.1 christos }
91 1.1 christos break;
92 1.1 christos
93 1.1 christos case mmr_offset(stat):
94 1.1 christos /* When enabled, writes to STAT reload the counter. */
95 1.1 christos if (bfin_wdog_enabled (wdog))
96 1.1 christos wdog->stat = wdog->cnt;
97 1.1 christos /* XXX: When disabled, are writes just ignored ? */
98 1.1 christos break;
99 1.1 christos }
100 1.1 christos
101 1.1 christos return nr_bytes;
102 1.1 christos }
103 1.1 christos
104 1.1 christos static unsigned
105 1.1 christos bfin_wdog_io_read_buffer (struct hw *me, void *dest,
106 1.1 christos int space, address_word addr, unsigned nr_bytes)
107 1.1 christos {
108 1.1 christos struct bfin_wdog *wdog = hw_data (me);
109 1.1 christos bu32 mmr_off;
110 1.1 christos bu16 *value16p;
111 1.1 christos bu32 *value32p;
112 1.1 christos void *valuep;
113 1.1 christos
114 1.1 christos mmr_off = addr - wdog->base;
115 1.1 christos valuep = (void *)((unsigned long)wdog + 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(ctl):
124 1.1 christos dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
125 1.1 christos dv_store_2 (dest, *value16p);
126 1.1 christos break;
127 1.1 christos
128 1.1 christos case mmr_offset(cnt):
129 1.1 christos case mmr_offset(stat):
130 1.1 christos dv_store_4 (dest, *value32p);
131 1.1 christos break;
132 1.1 christos }
133 1.1 christos
134 1.1 christos return nr_bytes;
135 1.1 christos }
136 1.1 christos
137 1.1 christos static const struct hw_port_descriptor bfin_wdog_ports[] =
138 1.1 christos {
139 1.1 christos { "reset", WDEV_RESET, 0, output_port, },
140 1.1 christos { "nmi", WDEV_NMI, 0, output_port, },
141 1.1 christos { "gpi", WDEV_GPI, 0, output_port, },
142 1.1 christos { NULL, 0, 0, 0, },
143 1.1 christos };
144 1.1 christos
145 1.1 christos static void
146 1.1 christos bfin_wdog_port_event (struct hw *me, int my_port, struct hw *source,
147 1.1 christos int source_port, int level)
148 1.1 christos {
149 1.1 christos struct bfin_wdog *wdog = hw_data (me);
150 1.1 christos bu16 wdev;
151 1.1 christos
152 1.1 christos wdog->ctl |= WDRO;
153 1.1 christos wdev = (wdog->ctl & WDEV);
154 1.1 christos if (wdev != WDEV_NONE)
155 1.1 christos hw_port_event (me, wdev, 1);
156 1.1 christos }
157 1.1 christos
158 1.1 christos static void
159 1.1 christos attach_bfin_wdog_regs (struct hw *me, struct bfin_wdog *wdog)
160 1.1 christos {
161 1.1 christos address_word attach_address;
162 1.1 christos int attach_space;
163 1.1 christos unsigned attach_size;
164 1.1 christos reg_property_spec reg;
165 1.1 christos
166 1.1 christos if (hw_find_property (me, "reg") == NULL)
167 1.1 christos hw_abort (me, "Missing \"reg\" property");
168 1.1 christos
169 1.1 christos if (!hw_find_reg_array_property (me, "reg", 0, ®))
170 1.1 christos hw_abort (me, "\"reg\" property must contain three addr/size entries");
171 1.1 christos
172 1.1 christos hw_unit_address_to_attach_address (hw_parent (me),
173 1.1 christos ®.address,
174 1.1 christos &attach_space, &attach_address, me);
175 1.1 christos hw_unit_size_to_attach_size (hw_parent (me), ®.size, &attach_size, me);
176 1.1 christos
177 1.1 christos if (attach_size != BFIN_MMR_WDOG_SIZE)
178 1.1 christos hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_WDOG_SIZE);
179 1.1 christos
180 1.1 christos hw_attach_address (hw_parent (me),
181 1.1 christos 0, attach_space, attach_address, attach_size, me);
182 1.1 christos
183 1.1 christos wdog->base = attach_address;
184 1.1 christos }
185 1.1 christos
186 1.1 christos static void
187 1.1 christos bfin_wdog_finish (struct hw *me)
188 1.1 christos {
189 1.1 christos struct bfin_wdog *wdog;
190 1.1 christos
191 1.1 christos wdog = HW_ZALLOC (me, struct bfin_wdog);
192 1.1 christos
193 1.1 christos set_hw_data (me, wdog);
194 1.1 christos set_hw_io_read_buffer (me, bfin_wdog_io_read_buffer);
195 1.1 christos set_hw_io_write_buffer (me, bfin_wdog_io_write_buffer);
196 1.1 christos set_hw_ports (me, bfin_wdog_ports);
197 1.1 christos set_hw_port_event (me, bfin_wdog_port_event);
198 1.1 christos
199 1.1 christos attach_bfin_wdog_regs (me, wdog);
200 1.1 christos
201 1.1 christos /* Initialize the Watchdog. */
202 1.1 christos wdog->ctl = WDDIS;
203 1.1 christos }
204 1.1 christos
205 1.1 christos const struct hw_descriptor dv_bfin_wdog_descriptor[] =
206 1.1 christos {
207 1.1 christos {"bfin_wdog", bfin_wdog_finish,},
208 1.1 christos {NULL, NULL},
209 1.1 christos };
210