source: mainline/kernel/arch/sparc64/src/drivers/kbd.c@ 86018c1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 86018c1 was 387416b, checked in by Pavel Rimsky <pavel@…>, 16 years ago

Synchronizing with head.

  • Property mode set to 100644
File size: 6.6 KB
RevLine 
[82da5f5]1/*
[df4ed85]2 * Copyright (c) 2006 Jakub Jermar
[82da5f5]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
[1462d35]29/** @addtogroup sparc64
[b45c443]30 * @{
31 */
32/** @file
33 */
34
[287920f]35#include <arch/drivers/kbd.h>
[28ecadb]36#include <genarch/ofw/ofw_tree.h>
[e731b0d]37#include <genarch/ofw/fhc.h>
38#include <genarch/ofw/ebus.h>
39#include <console/console.h>
40#include <ddi/irq.h>
[387416b]41#include <mm/page.h>
[e731b0d]42#include <arch/mm/page.h>
43#include <arch/types.h>
44#include <align.h>
45#include <string.h>
46#include <print.h>
47#include <sysinfo/sysinfo.h>
[411b6a6]48
49#ifdef CONFIG_SUN_KBD
50#include <genarch/kbrd/kbrd.h>
51#endif
[e731b0d]52
[da74747]53#ifdef CONFIG_Z8530
[411b6a6]54#include <genarch/drivers/z8530/z8530.h>
[da74747]55#endif
[e731b0d]56
[8b4be29]57#ifdef CONFIG_NS16550
[411b6a6]58#include <genarch/drivers/ns16550/ns16550.h>
[da74747]59#endif
[411b6a6]60
[9693835]61#ifdef CONFIG_SUN_KBD
[63b1537]62
[c2417bc]63#ifdef CONFIG_Z8530
64
65static bool kbd_z8530_init(ofw_tree_node_t *node)
[82da5f5]66{
[c2417bc]67 const char *name = ofw_tree_node_name(node);
68
69 if (str_cmp(name, "zs") != 0)
70 return false;
71
72 /*
73 * Read 'interrupts' property.
74 */
75 ofw_tree_property_t *prop = ofw_tree_getprop(node, "interrupts");
76 if ((!prop) || (!prop->value)) {
77 printf("z8530: Unable to find interrupts property\n");
78 return false;
79 }
80
81 uint32_t interrupts = *((uint32_t *) prop->value);
82
83 /*
84 * Read 'reg' property.
85 */
86 prop = ofw_tree_getprop(node, "reg");
87 if ((!prop) || (!prop->value)) {
88 printf("z8530: Unable to find reg property\n");
89 return false;
90 }
91
92 size_t size = ((ofw_fhc_reg_t *) prop->value)->size;
93
94 uintptr_t pa;
95 if (!ofw_fhc_apply_ranges(node->parent,
96 ((ofw_fhc_reg_t *) prop->value), &pa)) {
97 printf("z8530: Failed to determine address\n");
98 return false;
99 }
100
101 inr_t inr;
[8d2760f]102 cir_t cir;
103 void *cir_arg;
[c2417bc]104 if (!ofw_fhc_map_interrupt(node->parent,
105 ((ofw_fhc_reg_t *) prop->value), interrupts, &inr, &cir,
106 &cir_arg)) {
107 printf("z8530: Failed to determine interrupt\n");
108 return false;
109 }
[84afc7b]110
[c2417bc]111 /*
112 * We need to pass aligned address to hw_map().
113 * However, the physical keyboard address can
114 * be pretty much unaligned, depending on the
115 * underlying controller.
116 */
117 uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
118 size_t offset = pa - aligned_addr;
119
120 z8530_t *z8530 = (z8530_t *)
121 (hw_map(aligned_addr, offset + size) + offset);
[28ecadb]122
[c2417bc]123 z8530_instance_t *z8530_instance = z8530_init(z8530, inr, cir, cir_arg);
124 if (z8530_instance) {
125 kbrd_instance_t *kbrd_instance = kbrd_init();
126 if (kbrd_instance) {
127 indev_t *sink = stdin_wire();
128 indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
129 z8530_wire(z8530_instance, kbrd);
130 }
131 }
[28ecadb]132
[0b414b5]133 /*
[c2417bc]134 * This is the necessary evil until the userspace drivers are
135 * entirely self-sufficient.
[0b414b5]136 */
[c2417bc]137 sysinfo_set_item_val("kbd", NULL, true);
138 sysinfo_set_item_val("kbd.inr", NULL, inr);
139 sysinfo_set_item_val("kbd.address.kernel", NULL,
140 (uintptr_t) z8530);
141 sysinfo_set_item_val("kbd.address.physical", NULL, pa);
142 sysinfo_set_item_val("kbd.type.z8530", NULL, true);
143
144 return true;
145}
146
147#endif /* CONFIG_Z8530 */
148
149#ifdef CONFIG_NS16550
150
151static bool kbd_ns16550_init(ofw_tree_node_t *node)
152{
153 const char *name = ofw_tree_node_name(node);
154
155 if (str_cmp(name, "su") != 0)
156 return false;
[28ecadb]157
[0b414b5]158 /*
159 * Read 'interrupts' property.
160 */
[c2417bc]161 ofw_tree_property_t *prop = ofw_tree_getprop(node, "interrupts");
162 if ((!prop) || (!prop->value)) {
163 printf("ns16550: Unable to find interrupts property\n");
164 return false;
165 }
166
167 uint32_t interrupts = *((uint32_t *) prop->value);
[64c7e14]168
[0b414b5]169 /*
170 * Read 'reg' property.
171 */
[28ecadb]172 prop = ofw_tree_getprop(node, "reg");
[c2417bc]173 if ((!prop) || (!prop->value)) {
174 printf("ns16550: Unable to find reg property\n");
175 return false;
176 }
177
178 size_t size = ((ofw_ebus_reg_t *) prop->value)->size;
[28ecadb]179
180 uintptr_t pa;
[c2417bc]181 if (!ofw_ebus_apply_ranges(node->parent,
182 ((ofw_ebus_reg_t *) prop->value), &pa)) {
183 printf("ns16550: Failed to determine address\n");
184 return false;
185 }
[0d107f31]186
[c2417bc]187 inr_t inr;
188 cir_t cir;
189 void *cir_arg;
190 if (!ofw_ebus_map_interrupt(node->parent,
191 ((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir,
192 &cir_arg)) {
193 printf("ns16550: Failed to determine interrupt\n");
194 return false;
[28ecadb]195 }
196
[da74747]197 /*
198 * We need to pass aligned address to hw_map().
199 * However, the physical keyboard address can
[28ecadb]200 * be pretty much unaligned, depending on the
201 * underlying controller.
[da74747]202 */
[c2417bc]203 uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
204 size_t offset = pa - aligned_addr;
205
206 ns16550_t *ns16550 = (ns16550_t *)
207 (hw_map(aligned_addr, offset + size) + offset);
208
209 ns16550_instance_t *ns16550_instance = ns16550_init(ns16550, inr, cir, cir_arg);
210 if (ns16550_instance) {
211 kbrd_instance_t *kbrd_instance = kbrd_init();
212 if (kbrd_instance) {
213 indev_t *sink = stdin_wire();
214 indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
215 ns16550_wire(ns16550_instance, kbrd);
216 }
217 }
218
219 /*
220 * This is the necessary evil until the userspace drivers are
221 * entirely self-sufficient.
222 */
223 sysinfo_set_item_val("kbd", NULL, true);
224 sysinfo_set_item_val("kbd.inr", NULL, inr);
225 sysinfo_set_item_val("kbd.address.kernel", NULL,
226 (uintptr_t) ns16550);
227 sysinfo_set_item_val("kbd.address.physical", NULL, pa);
228 sysinfo_set_item_val("kbd.type.ns16550", NULL, true);
[64c7e14]229
[c2417bc]230 return true;
231}
232
233#endif /* CONFIG_NS16550 */
234
235/** Initialize keyboard.
236 *
237 * Traverse OpenFirmware device tree in order to find necessary
238 * info about the keyboard device.
239 *
240 * @param node Keyboard device node.
241 *
242 */
243void kbd_init(ofw_tree_node_t *node)
244{
[da74747]245#ifdef CONFIG_Z8530
[c2417bc]246 kbd_z8530_init(node);
[da74747]247#endif
[c2417bc]248
[8b4be29]249#ifdef CONFIG_NS16550
[c2417bc]250 kbd_ns16550_init(node);
[da74747]251#endif
[82da5f5]252}
[b45c443]253
[c2417bc]254#endif /* CONFIG_SUN_KBD */
[9693835]255
[0ffa3ef5]256/** @}
[b45c443]257 */
Note: See TracBrowser for help on using the repository browser.