1 | /* |
2 | * LatticeMico32 hwsetup helper functions. |
3 | * |
4 | * Copyright (c) 2010 Michael Walle <michael@walle.cc> |
5 | * |
6 | * This library is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU Lesser General Public |
8 | * License as published by the Free Software Foundation; either |
9 | * version 2 of the License, or (at your option) any later version. |
10 | * |
11 | * This library is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * Lesser General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU Lesser General Public |
17 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
18 | */ |
19 | |
20 | /* |
21 | * These are helper functions for creating the hardware description blob used |
22 | * in the Theobroma's uClinux port. |
23 | */ |
24 | |
25 | #ifndef QEMU_HW_LM32_HWSETUP_H |
26 | #define QEMU_HW_LM32_HWSETUP_H |
27 | |
28 | #include "qemu/cutils.h" |
29 | #include "hw/loader.h" |
30 | |
31 | typedef struct { |
32 | void *data; |
33 | void *ptr; |
34 | } HWSetup; |
35 | |
36 | enum hwsetup_tag { |
37 | HWSETUP_TAG_EOL = 0, |
38 | HWSETUP_TAG_CPU = 1, |
39 | HWSETUP_TAG_ASRAM = 2, |
40 | HWSETUP_TAG_FLASH = 3, |
41 | HWSETUP_TAG_SDRAM = 4, |
42 | HWSETUP_TAG_OCM = 5, |
43 | HWSETUP_TAG_DDR_SDRAM = 6, |
44 | HWSETUP_TAG_DDR2_SDRAM = 7, |
45 | HWSETUP_TAG_TIMER = 8, |
46 | HWSETUP_TAG_UART = 9, |
47 | HWSETUP_TAG_GPIO = 10, |
48 | HWSETUP_TAG_TRISPEEDMAC = 11, |
49 | HWSETUP_TAG_I2CM = 12, |
50 | HWSETUP_TAG_LEDS = 13, |
51 | HWSETUP_TAG_7SEG = 14, |
52 | HWSETUP_TAG_SPI_S = 15, |
53 | HWSETUP_TAG_SPI_M = 16, |
54 | }; |
55 | |
56 | static inline HWSetup *hwsetup_init(void) |
57 | { |
58 | HWSetup *hw; |
59 | |
60 | hw = g_malloc(sizeof(HWSetup)); |
61 | hw->data = g_malloc0(TARGET_PAGE_SIZE); |
62 | hw->ptr = hw->data; |
63 | |
64 | return hw; |
65 | } |
66 | |
67 | static inline void hwsetup_free(HWSetup *hw) |
68 | { |
69 | g_free(hw->data); |
70 | g_free(hw); |
71 | } |
72 | |
73 | static inline void hwsetup_create_rom(HWSetup *hw, |
74 | hwaddr base) |
75 | { |
76 | rom_add_blob("hwsetup" , hw->data, TARGET_PAGE_SIZE, |
77 | TARGET_PAGE_SIZE, base, NULL, NULL, NULL, NULL, true); |
78 | } |
79 | |
80 | static inline void hwsetup_add_u8(HWSetup *hw, uint8_t u) |
81 | { |
82 | stb_p(hw->ptr, u); |
83 | hw->ptr += 1; |
84 | } |
85 | |
86 | static inline void hwsetup_add_u32(HWSetup *hw, uint32_t u) |
87 | { |
88 | stl_p(hw->ptr, u); |
89 | hw->ptr += 4; |
90 | } |
91 | |
92 | static inline void hwsetup_add_tag(HWSetup *hw, enum hwsetup_tag t) |
93 | { |
94 | stl_p(hw->ptr, t); |
95 | hw->ptr += 4; |
96 | } |
97 | |
98 | static inline void hwsetup_add_str(HWSetup *hw, const char *str) |
99 | { |
100 | pstrcpy(hw->ptr, 32, str); |
101 | hw->ptr += 32; |
102 | } |
103 | |
104 | static inline void hwsetup_add_trailer(HWSetup *hw) |
105 | { |
106 | hwsetup_add_u32(hw, 8); /* size */ |
107 | hwsetup_add_tag(hw, HWSETUP_TAG_EOL); |
108 | } |
109 | |
110 | static inline void hwsetup_add_cpu(HWSetup *hw, |
111 | const char *name, uint32_t frequency) |
112 | { |
113 | hwsetup_add_u32(hw, 44); /* size */ |
114 | hwsetup_add_tag(hw, HWSETUP_TAG_CPU); |
115 | hwsetup_add_str(hw, name); |
116 | hwsetup_add_u32(hw, frequency); |
117 | } |
118 | |
119 | static inline void hwsetup_add_flash(HWSetup *hw, |
120 | const char *name, uint32_t base, uint32_t size) |
121 | { |
122 | hwsetup_add_u32(hw, 52); /* size */ |
123 | hwsetup_add_tag(hw, HWSETUP_TAG_FLASH); |
124 | hwsetup_add_str(hw, name); |
125 | hwsetup_add_u32(hw, base); |
126 | hwsetup_add_u32(hw, size); |
127 | hwsetup_add_u8(hw, 8); /* read latency */ |
128 | hwsetup_add_u8(hw, 8); /* write latency */ |
129 | hwsetup_add_u8(hw, 25); /* address width */ |
130 | hwsetup_add_u8(hw, 32); /* data width */ |
131 | } |
132 | |
133 | static inline void hwsetup_add_ddr_sdram(HWSetup *hw, |
134 | const char *name, uint32_t base, uint32_t size) |
135 | { |
136 | hwsetup_add_u32(hw, 48); /* size */ |
137 | hwsetup_add_tag(hw, HWSETUP_TAG_DDR_SDRAM); |
138 | hwsetup_add_str(hw, name); |
139 | hwsetup_add_u32(hw, base); |
140 | hwsetup_add_u32(hw, size); |
141 | } |
142 | |
143 | static inline void hwsetup_add_timer(HWSetup *hw, |
144 | const char *name, uint32_t base, uint32_t irq) |
145 | { |
146 | hwsetup_add_u32(hw, 56); /* size */ |
147 | hwsetup_add_tag(hw, HWSETUP_TAG_TIMER); |
148 | hwsetup_add_str(hw, name); |
149 | hwsetup_add_u32(hw, base); |
150 | hwsetup_add_u8(hw, 1); /* wr_tickcount */ |
151 | hwsetup_add_u8(hw, 1); /* rd_tickcount */ |
152 | hwsetup_add_u8(hw, 1); /* start_stop_control */ |
153 | hwsetup_add_u8(hw, 32); /* counter_width */ |
154 | hwsetup_add_u32(hw, 20); /* reload_ticks */ |
155 | hwsetup_add_u8(hw, irq); |
156 | hwsetup_add_u8(hw, 0); /* padding */ |
157 | hwsetup_add_u8(hw, 0); /* padding */ |
158 | hwsetup_add_u8(hw, 0); /* padding */ |
159 | } |
160 | |
161 | static inline void hwsetup_add_uart(HWSetup *hw, |
162 | const char *name, uint32_t base, uint32_t irq) |
163 | { |
164 | hwsetup_add_u32(hw, 56); /* size */ |
165 | hwsetup_add_tag(hw, HWSETUP_TAG_UART); |
166 | hwsetup_add_str(hw, name); |
167 | hwsetup_add_u32(hw, base); |
168 | hwsetup_add_u32(hw, 115200); /* baudrate */ |
169 | hwsetup_add_u8(hw, 8); /* databits */ |
170 | hwsetup_add_u8(hw, 1); /* stopbits */ |
171 | hwsetup_add_u8(hw, 1); /* use_interrupt */ |
172 | hwsetup_add_u8(hw, 1); /* block_on_transmit */ |
173 | hwsetup_add_u8(hw, 1); /* block_on_receive */ |
174 | hwsetup_add_u8(hw, 4); /* rx_buffer_size */ |
175 | hwsetup_add_u8(hw, 4); /* tx_buffer_size */ |
176 | hwsetup_add_u8(hw, irq); |
177 | } |
178 | |
179 | #endif /* QEMU_HW_LM32_HWSETUP_H */ |
180 | |