Commit | Line | Data |
---|---|---|
ef016f83 MF |
1 | /* Common Blackfin device stuff. |
2 | ||
ecd75fc8 | 3 | Copyright (C) 2010-2014 Free Software Foundation, Inc. |
ef016f83 MF |
4 | Contributed by Analog Devices, Inc. |
5 | ||
6 | This file is part of simulators. | |
7 | ||
8 | This program is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 3 of the License, or | |
11 | (at your option) any later version. | |
12 | ||
13 | This program is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
20 | ||
21 | #ifndef DEVICES_H | |
22 | #define DEVICES_H | |
23 | ||
24 | #include "hw-base.h" | |
25 | #include "hw-main.h" | |
26 | #include "hw-device.h" | |
27 | #include "hw-tree.h" | |
28 | ||
29 | /* We keep the same inital structure layout with DMA enabled devices. */ | |
30 | struct dv_bfin { | |
31 | bu32 base; | |
32 | struct hw *dma_master; | |
33 | bool acked; | |
34 | }; | |
35 | ||
36 | #define BFIN_MMR_16(mmr) mmr, __pad_##mmr | |
37 | ||
38 | /* Most peripherals have either one interrupt or these three. */ | |
39 | #define DV_PORT_TX 0 | |
40 | #define DV_PORT_RX 1 | |
41 | #define DV_PORT_STAT 2 | |
42 | ||
43 | unsigned int dv_get_bus_num (struct hw *); | |
44 | \f | |
45 | static inline bu8 dv_load_1 (const void *ptr) | |
46 | { | |
47 | const unsigned char *c = ptr; | |
48 | return c[0]; | |
49 | } | |
50 | ||
51 | static inline void dv_store_1 (void *ptr, bu8 val) | |
52 | { | |
53 | unsigned char *c = ptr; | |
54 | c[0] = val; | |
55 | } | |
56 | ||
57 | static inline bu16 dv_load_2 (const void *ptr) | |
58 | { | |
59 | const unsigned char *c = ptr; | |
60 | return (c[1] << 8) | dv_load_1 (ptr); | |
61 | } | |
62 | ||
63 | static inline void dv_store_2 (void *ptr, bu16 val) | |
64 | { | |
65 | unsigned char *c = ptr; | |
66 | c[1] = val >> 8; | |
67 | dv_store_1 (ptr, val); | |
68 | } | |
69 | ||
70 | static inline bu32 dv_load_4 (const void *ptr) | |
71 | { | |
72 | const unsigned char *c = ptr; | |
73 | return (c[3] << 24) | (c[2] << 16) | dv_load_2 (ptr); | |
74 | } | |
75 | ||
76 | static inline void dv_store_4 (void *ptr, bu32 val) | |
77 | { | |
78 | unsigned char *c = ptr; | |
79 | c[3] = val >> 24; | |
80 | c[2] = val >> 16; | |
81 | dv_store_2 (ptr, val); | |
82 | } | |
83 | \f | |
9922f803 MF |
84 | /* Helpers for MMRs where only the specified bits are W1C. The |
85 | rest are left unmodified. */ | |
ef016f83 MF |
86 | #define dv_w1c(ptr, val, bits) (*(ptr) &= ~((val) & (bits))) |
87 | static inline void dv_w1c_2 (bu16 *ptr, bu16 val, bu16 bits) | |
88 | { | |
89 | dv_w1c (ptr, val, bits); | |
90 | } | |
91 | static inline void dv_w1c_4 (bu32 *ptr, bu32 val, bu32 bits) | |
92 | { | |
93 | dv_w1c (ptr, val, bits); | |
94 | } | |
95 | ||
96 | /* Helpers for MMRs where all bits are RW except for the specified | |
97 | bits -- those ones are W1C. */ | |
98 | #define dv_w1c_partial(ptr, val, bits) \ | |
99 | (*(ptr) = ((val) | (*(ptr) & (bits))) & ~((val) & (bits))) | |
100 | static inline void dv_w1c_2_partial (bu16 *ptr, bu16 val, bu16 bits) | |
101 | { | |
102 | dv_w1c_partial (ptr, val, bits); | |
103 | } | |
104 | static inline void dv_w1c_4_partial (bu32 *ptr, bu32 val, bu32 bits) | |
105 | { | |
106 | dv_w1c_partial (ptr, val, bits); | |
107 | } | |
108 | \f | |
109 | /* XXX: Grubbing around in device internals is probably wrong, but | |
110 | until someone shows me what's right ... */ | |
111 | static inline struct hw * | |
112 | dv_get_device (SIM_CPU *cpu, const char *device_name) | |
113 | { | |
114 | SIM_DESC sd = CPU_STATE (cpu); | |
115 | void *root = STATE_HW (sd); | |
116 | return hw_tree_find_device (root, device_name); | |
117 | } | |
118 | ||
119 | static inline void * | |
120 | dv_get_state (SIM_CPU *cpu, const char *device_name) | |
121 | { | |
122 | return hw_data (dv_get_device (cpu, device_name)); | |
123 | } | |
124 | ||
125 | #define DV_STATE(cpu, dv) dv_get_state (cpu, "/core/bfin_"#dv) | |
126 | ||
127 | #define DV_STATE_CACHED(cpu, dv) \ | |
128 | ({ \ | |
129 | struct bfin_##dv *__##dv = BFIN_CPU_STATE.dv##_cache; \ | |
130 | if (!__##dv) \ | |
131 | BFIN_CPU_STATE.dv##_cache = __##dv = dv_get_state (cpu, "/core/bfin_"#dv); \ | |
132 | __##dv; \ | |
133 | }) | |
134 | \f | |
135 | void dv_bfin_mmr_invalid (struct hw *, address_word, unsigned nr_bytes, bool write); | |
136 | void dv_bfin_mmr_require (struct hw *, address_word, unsigned nr_bytes, unsigned size, bool write); | |
137 | bool dv_bfin_mmr_check (struct hw *, address_word, unsigned nr_bytes, bool write); | |
138 | ||
139 | #define dv_bfin_mmr_require_16(hw, addr, nr_bytes, write) dv_bfin_mmr_require (hw, addr, nr_bytes, 2, write) | |
140 | #define dv_bfin_mmr_require_32(hw, addr, nr_bytes, write) dv_bfin_mmr_require (hw, addr, nr_bytes, 4, write) | |
141 | \f | |
142 | #define HW_TRACE_WRITE() \ | |
143 | HW_TRACE ((me, "write 0x%08lx (%s) length %u with 0x%x", \ | |
144 | (unsigned long) addr, mmr_name (mmr_off), nr_bytes, value)) | |
145 | #define HW_TRACE_READ() \ | |
146 | HW_TRACE ((me, "read 0x%08lx (%s) length %u", \ | |
147 | (unsigned long) addr, mmr_name (mmr_off), nr_bytes)) | |
148 | ||
149 | #define HW_TRACE_DMA_WRITE() \ | |
150 | HW_TRACE ((me, "dma write 0x%08lx length %u", \ | |
151 | (unsigned long) addr, nr_bytes)) | |
152 | #define HW_TRACE_DMA_READ() \ | |
153 | HW_TRACE ((me, "dma read 0x%08lx length %u", \ | |
154 | (unsigned long) addr, nr_bytes)) | |
155 | ||
156 | #endif |