1 | /* |
---|
2 | * Copyright (c) 2013 embedded brains GmbH. All rights reserved. |
---|
3 | * |
---|
4 | * embedded brains GmbH |
---|
5 | * Dornierstr. 4 |
---|
6 | * 82178 Puchheim |
---|
7 | * Germany |
---|
8 | * <info@embedded-brains.de> |
---|
9 | * |
---|
10 | * The license and distribution terms for this file may be |
---|
11 | * found in the file LICENSE in this distribution or at |
---|
12 | * http://www.rtems.com/license/LICENSE. |
---|
13 | */ |
---|
14 | |
---|
15 | #include <assert.h> |
---|
16 | |
---|
17 | #include <bsp/irq.h> |
---|
18 | #include <bsp/arm-pl050.h> |
---|
19 | #include <bsp/arm-pl050-regs.h> |
---|
20 | |
---|
21 | #include <libchip/sersupp.h> |
---|
22 | |
---|
23 | static volatile pl050 *pl050_get_regs(int minor) |
---|
24 | { |
---|
25 | const console_tbl *ct = Console_Port_Tbl[minor]; |
---|
26 | |
---|
27 | return (volatile pl050 *) ct->ulCtrlPort1; |
---|
28 | } |
---|
29 | |
---|
30 | static void pl050_interrupt(void *arg) |
---|
31 | { |
---|
32 | int minor = (int) arg; |
---|
33 | const console_data *cd = &Console_Port_Data[minor]; |
---|
34 | volatile pl050 *regs = pl050_get_regs(minor); |
---|
35 | uint32_t kmiir_rx = PL050_KMIIR_KMIRXINTR; |
---|
36 | uint32_t kmiir_tx = (regs->kmicr & PL050_KMICR_KMITXINTREN) != 0 ? |
---|
37 | PL050_KMIIR_KMITXINTR : 0; |
---|
38 | uint32_t kmiir = regs->kmiir; |
---|
39 | |
---|
40 | if ((kmiir & kmiir_rx) != 0) { |
---|
41 | char c = (char) PL050_KMIDATA_KMIDATA_GET(regs->kmidata); |
---|
42 | |
---|
43 | rtems_termios_enqueue_raw_characters(cd->termios_data, &c, 1); |
---|
44 | } |
---|
45 | |
---|
46 | if ((kmiir & kmiir_tx) != 0) { |
---|
47 | rtems_termios_dequeue_characters(cd->termios_data, 1); |
---|
48 | } |
---|
49 | } |
---|
50 | |
---|
51 | static void pl050_initialize(int minor) |
---|
52 | { |
---|
53 | /* Nothing to do */ |
---|
54 | } |
---|
55 | |
---|
56 | static int pl050_first_open(int major, int minor, void *arg) |
---|
57 | { |
---|
58 | rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg; |
---|
59 | struct rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1; |
---|
60 | console_data *cd = &Console_Port_Data[minor]; |
---|
61 | const console_tbl *ct = Console_Port_Tbl[minor]; |
---|
62 | volatile pl050 *regs = pl050_get_regs(minor); |
---|
63 | rtems_status_code sc; |
---|
64 | |
---|
65 | cd->termios_data = tty; |
---|
66 | rtems_termios_set_initial_baud(tty, (rtems_termios_baud_t) ct->pDeviceParams); |
---|
67 | |
---|
68 | regs->kmicr = PL050_KMICR_KMIEN | PL050_KMICR_KMIRXINTREN; |
---|
69 | |
---|
70 | sc = rtems_interrupt_handler_install( |
---|
71 | ct->ulIntVector, |
---|
72 | ct->sDeviceName, |
---|
73 | RTEMS_INTERRUPT_UNIQUE, |
---|
74 | pl050_interrupt, |
---|
75 | (void *) minor |
---|
76 | ); |
---|
77 | assert(sc == RTEMS_SUCCESSFUL); |
---|
78 | |
---|
79 | return 0; |
---|
80 | } |
---|
81 | |
---|
82 | static int pl050_last_close(int major, int minor, void *arg) |
---|
83 | { |
---|
84 | const console_tbl *ct = Console_Port_Tbl[minor]; |
---|
85 | volatile pl050 *regs = pl050_get_regs(minor); |
---|
86 | rtems_status_code sc; |
---|
87 | |
---|
88 | regs->kmicr = 0; |
---|
89 | |
---|
90 | sc = rtems_interrupt_handler_remove( |
---|
91 | ct->ulIntVector, |
---|
92 | pl050_interrupt, |
---|
93 | (void *) minor |
---|
94 | ); |
---|
95 | assert(sc == RTEMS_SUCCESSFUL); |
---|
96 | |
---|
97 | return 0; |
---|
98 | } |
---|
99 | |
---|
100 | static ssize_t pl050_write_support( |
---|
101 | int minor, |
---|
102 | const char *s, |
---|
103 | size_t n |
---|
104 | ) |
---|
105 | { |
---|
106 | volatile pl050 *regs = pl050_get_regs(minor); |
---|
107 | |
---|
108 | if (n > 0) { |
---|
109 | regs->kmidata = PL050_KMIDATA_KMIDATA(s[0]); |
---|
110 | regs->kmicr |= PL050_KMICR_KMITXINTREN; |
---|
111 | } else { |
---|
112 | regs->kmicr &= ~PL050_KMICR_KMITXINTREN; |
---|
113 | } |
---|
114 | |
---|
115 | return 0; |
---|
116 | } |
---|
117 | |
---|
118 | static int pl050_set_attribues(int minor, const struct termios *term) |
---|
119 | { |
---|
120 | return -1; |
---|
121 | } |
---|
122 | |
---|
123 | const console_fns arm_pl050_fns = { |
---|
124 | .deviceProbe = libchip_serial_default_probe, |
---|
125 | .deviceFirstOpen = pl050_first_open, |
---|
126 | .deviceLastClose = pl050_last_close, |
---|
127 | .deviceRead = NULL, |
---|
128 | .deviceWrite = pl050_write_support, |
---|
129 | .deviceInitialize = pl050_initialize, |
---|
130 | .deviceWritePolled = NULL, |
---|
131 | .deviceSetAttributes = pl050_set_attribues, |
---|
132 | .deviceOutputUsesInterrupts = true |
---|
133 | }; |
---|