source: mainline/uspace/drv/platform/icp/icp.c

Last change on this file was 4122410, checked in by Jakub Jermar <jakub@…>, 7 years ago

Improve Doxygen documentaion

This is stil WiP. A number of libraries, drivers and services were
converted to using a more hierarchical and decentralized scheme when it
comes to specifying to which doxygen group they belong.

  • Property mode set to 100644
File size: 6.9 KB
Line 
1/*
2 * Copyright (c) 2014 Jiri Svoboda
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
29/**
30 * @addtogroup icp
31 * @{
32 */
33
34/** @file
35 */
36
37#include <assert.h>
38#include <stdio.h>
39#include <errno.h>
40#include <irc.h>
41#include <stdbool.h>
42#include <stdlib.h>
43
44#include <ddf/driver.h>
45#include <ddf/log.h>
46#include <ops/hw_res.h>
47#include <ops/pio_window.h>
48
49#define NAME "icp"
50
51enum {
52 icp_kbd_base = 0x18000000,
53 icp_kbd_irq = 3,
54 icp_mouse_base = 0x19000000,
55 icp_mouse_irq = 4,
56 icp_ic_base = 0x14000000
57};
58
59typedef struct icp_fun {
60 hw_resource_list_t hw_resources;
61} icp_fun_t;
62
63static errno_t icp_dev_add(ddf_dev_t *dev);
64
65static driver_ops_t icp_ops = {
66 .dev_add = &icp_dev_add
67};
68
69static driver_t icp_driver = {
70 .name = NAME,
71 .driver_ops = &icp_ops
72};
73
74static hw_resource_t icp_kbd_res[] = {
75 {
76 .type = MEM_RANGE,
77 .res.mem_range = {
78 .address = icp_kbd_base,
79 .size = 9,
80 .relative = false,
81 .endianness = LITTLE_ENDIAN
82 }
83 },
84 {
85 .type = INTERRUPT,
86 .res.interrupt = {
87 .irq = icp_kbd_irq
88 }
89 }
90};
91
92static hw_resource_t icp_mouse_res[] = {
93 {
94 .type = MEM_RANGE,
95 .res.mem_range = {
96 .address = icp_mouse_base,
97 .size = 9,
98 .relative = false,
99 .endianness = LITTLE_ENDIAN
100 }
101 },
102 {
103 .type = INTERRUPT,
104 .res.interrupt = {
105 .irq = icp_mouse_irq
106 }
107 }
108};
109
110static hw_resource_t icp_ic_res[] = {
111 {
112 .type = MEM_RANGE,
113 .res.mem_range = {
114 .address = icp_ic_base,
115 .size = 40,
116 .relative = false,
117 .endianness = LITTLE_ENDIAN
118 }
119 }
120};
121
122static pio_window_t icp_pio_window = {
123 .mem = {
124 .base = 0,
125 .size = -1
126 }
127};
128
129static icp_fun_t icp_kbd_fun_proto = {
130 .hw_resources = {
131 sizeof(icp_kbd_res) / sizeof(icp_kbd_res[0]),
132 icp_kbd_res
133 },
134};
135
136static icp_fun_t icp_mouse_fun_proto = {
137 .hw_resources = {
138 sizeof(icp_mouse_res) / sizeof(icp_mouse_res[0]),
139 icp_mouse_res
140 },
141};
142
143static icp_fun_t icp_ic_fun_proto = {
144 .hw_resources = {
145 sizeof(icp_ic_res) / sizeof(icp_ic_res[0]),
146 icp_ic_res
147 },
148};
149
150/** Obtain function soft-state from DDF function node */
151static icp_fun_t *icp_fun(ddf_fun_t *fnode)
152{
153 return ddf_fun_data_get(fnode);
154}
155
156static hw_resource_list_t *icp_get_resources(ddf_fun_t *fnode)
157{
158 icp_fun_t *fun = icp_fun(fnode);
159
160 assert(fun != NULL);
161 return &fun->hw_resources;
162}
163
164static bool icp_fun_owns_interrupt(icp_fun_t *fun, int irq)
165{
166 const hw_resource_list_t *res = &fun->hw_resources;
167
168 /* Check that specified irq really belongs to the function */
169 for (size_t i = 0; i < res->count; ++i) {
170 if (res->resources[i].type == INTERRUPT &&
171 res->resources[i].res.interrupt.irq == irq) {
172 return true;
173 }
174 }
175
176 return false;
177}
178
179static errno_t icp_fun_enable_interrupt(ddf_fun_t *fnode, int irq)
180{
181 icp_fun_t *fun = icp_fun(fnode);
182
183 if (!icp_fun_owns_interrupt(fun, irq))
184 return EINVAL;
185
186 return irc_enable_interrupt(irq);
187}
188
189static errno_t icp_fun_disable_interrupt(ddf_fun_t *fnode, int irq)
190{
191 icp_fun_t *fun = icp_fun(fnode);
192
193 if (!icp_fun_owns_interrupt(fun, irq))
194 return EINVAL;
195
196 return irc_disable_interrupt(irq);
197}
198
199static errno_t icp_fun_clear_interrupt(ddf_fun_t *fnode, int irq)
200{
201 icp_fun_t *fun = icp_fun(fnode);
202
203 if (!icp_fun_owns_interrupt(fun, irq))
204 return EINVAL;
205
206 return irc_clear_interrupt(irq);
207}
208
209static pio_window_t *icp_get_pio_window(ddf_fun_t *fnode)
210{
211 return &icp_pio_window;
212}
213
214static hw_res_ops_t icp_hw_res_ops = {
215 .get_resource_list = &icp_get_resources,
216 .enable_interrupt = &icp_fun_enable_interrupt,
217 .disable_interrupt = &icp_fun_disable_interrupt,
218 .clear_interrupt = &icp_fun_clear_interrupt
219};
220
221static pio_window_ops_t icp_pio_window_ops = {
222 .get_pio_window = &icp_get_pio_window
223};
224
225static ddf_dev_ops_t icp_fun_ops = {
226 .interfaces = {
227 [HW_RES_DEV_IFACE] = &icp_hw_res_ops,
228 [PIO_WINDOW_DEV_IFACE] = &icp_pio_window_ops
229 }
230};
231
232static errno_t icp_add_fun(ddf_dev_t *dev, const char *name, const char *str_match_id,
233 icp_fun_t *fun_proto)
234{
235 ddf_msg(LVL_NOTE, "Adding function '%s'.", name);
236
237 ddf_fun_t *fnode = NULL;
238 errno_t rc;
239
240 /* Create new device. */
241 fnode = ddf_fun_create(dev, fun_inner, name);
242 if (fnode == NULL) {
243 ddf_msg(LVL_ERROR, "Error creating function '%s'", name);
244 rc = ENOMEM;
245 goto error;
246 }
247
248 icp_fun_t *fun = ddf_fun_data_alloc(fnode, sizeof(icp_fun_t));
249 *fun = *fun_proto;
250
251 /* Add match ID */
252 rc = ddf_fun_add_match_id(fnode, str_match_id, 100);
253 if (rc != EOK) {
254 ddf_msg(LVL_ERROR, "Error adding match ID");
255 goto error;
256 }
257
258 /* Set provided operations to the device. */
259 ddf_fun_set_ops(fnode, &icp_fun_ops);
260
261 /* Register function. */
262 if (ddf_fun_bind(fnode) != EOK) {
263 ddf_msg(LVL_ERROR, "Failed binding function %s.", name);
264 goto error;
265 }
266
267 return EOK;
268
269error:
270 if (fnode != NULL)
271 ddf_fun_destroy(fnode);
272
273 return rc;
274}
275
276static errno_t icp_add_functions(ddf_dev_t *dev)
277{
278 errno_t rc;
279
280 rc = icp_add_fun(dev, "intctl", "integratorcp/intctl",
281 &icp_ic_fun_proto);
282 if (rc != EOK)
283 return rc;
284
285 rc = icp_add_fun(dev, "kbd", "arm/pl050", &icp_kbd_fun_proto);
286 if (rc != EOK)
287 return rc;
288
289 rc = icp_add_fun(dev, "mouse", "arm/pl050", &icp_mouse_fun_proto);
290 if (rc != EOK)
291 return rc;
292
293 return EOK;
294}
295
296/** Add device. */
297static errno_t icp_dev_add(ddf_dev_t *dev)
298{
299 ddf_msg(LVL_NOTE, "icp_dev_add, device handle = %d",
300 (int)ddf_dev_get_handle(dev));
301
302 /* Register functions. */
303 if (icp_add_functions(dev)) {
304 ddf_msg(LVL_ERROR, "Failed to add functions for ICP platform.");
305 }
306
307 return EOK;
308}
309
310int main(int argc, char *argv[])
311{
312 errno_t rc;
313
314 printf(NAME ": HelenOS IntegratorCP platform driver\n");
315
316 rc = ddf_log_init(NAME);
317 if (rc != EOK) {
318 printf(NAME ": Failed initializing logging service");
319 return 1;
320 }
321
322 return ddf_driver_main(&icp_driver);
323}
324
325/**
326 * @}
327 */
Note: See TracBrowser for help on using the repository browser.