source: mainline/uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c@ d776329b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d776329b was b688fd8, checked in by Martin Decky <martin@…>, 10 years ago

gradually introduce async ports, initial phase

The initial phase is to reimplement the traditional async client connections as an untyped fallback port. This creates the possibility to introduce ports typed by interface type gradually in later changesets.

  • Property mode set to 100644
File size: 5.9 KB
Line 
1/*
2 * Copyright (c) 2010 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/** @addtogroup driver_serial
30 * @{
31 */
32/**
33 * @file
34 * @brief Samsung S3C24xx on-chip UART driver.
35 *
36 * This UART is present on the Samsung S3C24xx CPU (on the gta02 platform).
37 */
38
39#include <ddi.h>
40#include <loc.h>
41#include <ipc/char.h>
42#include <async.h>
43#include <unistd.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <sysinfo.h>
47#include <errno.h>
48#include <inttypes.h>
49#include "s3c24xx_uart.h"
50
51#define NAME "s3c24ser"
52#define NAMESPACE "char"
53
54static irq_cmd_t uart_irq_cmds[] = {
55 {
56 .cmd = CMD_ACCEPT
57 }
58};
59
60static irq_code_t uart_irq_code = {
61 0,
62 NULL,
63 sizeof(uart_irq_cmds) / sizeof(irq_cmd_t),
64 uart_irq_cmds
65};
66
67/** S3C24xx UART instance structure */
68static s3c24xx_uart_t *uart;
69
70static void s3c24xx_uart_connection(ipc_callid_t, ipc_call_t *, void *);
71static void s3c24xx_uart_irq_handler(ipc_callid_t, ipc_call_t *, void *);
72static int s3c24xx_uart_init(s3c24xx_uart_t *);
73static void s3c24xx_uart_sendb(s3c24xx_uart_t *, uint8_t);
74
75int main(int argc, char *argv[])
76{
77 printf("%s: S3C24xx on-chip UART driver\n", NAME);
78
79 async_set_fallback_port_handler(s3c24xx_uart_connection, NULL);
80 int rc = loc_server_register(NAME);
81 if (rc != EOK) {
82 printf("%s: Unable to register server.\n", NAME);
83 return rc;
84 }
85
86 uart = malloc(sizeof(s3c24xx_uart_t));
87 if (uart == NULL)
88 return -1;
89
90 if (s3c24xx_uart_init(uart) != EOK)
91 return -1;
92
93 rc = loc_service_register(NAMESPACE "/" NAME, &uart->service_id);
94 if (rc != EOK) {
95 printf(NAME ": Unable to register device %s.\n",
96 NAMESPACE "/" NAME);
97 return -1;
98 }
99
100 printf(NAME ": Registered device %s.\n", NAMESPACE "/" NAME);
101
102 printf(NAME ": Accepting connections\n");
103 task_retval(0);
104 async_manager();
105
106 /* Not reached */
107 return 0;
108}
109
110/** Character device connection handler. */
111static void s3c24xx_uart_connection(ipc_callid_t iid, ipc_call_t *icall,
112 void *arg)
113{
114 /* Answer the IPC_M_CONNECT_ME_TO call. */
115 async_answer_0(iid, EOK);
116
117 while (true) {
118 ipc_call_t call;
119 ipc_callid_t callid = async_get_call(&call);
120 sysarg_t method = IPC_GET_IMETHOD(call);
121
122 if (!method) {
123 /* The other side has hung up. */
124 async_answer_0(callid, EOK);
125 return;
126 }
127
128 async_sess_t *sess =
129 async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
130 if (sess != NULL) {
131 if (uart->client_sess == NULL) {
132 uart->client_sess = sess;
133 async_answer_0(callid, EOK);
134 } else
135 async_answer_0(callid, ELIMIT);
136 } else {
137 switch (method) {
138 case CHAR_WRITE_BYTE:
139 printf(NAME ": write %" PRIun " to device\n",
140 IPC_GET_ARG1(call));
141 s3c24xx_uart_sendb(uart, (uint8_t) IPC_GET_ARG1(call));
142 async_answer_0(callid, EOK);
143 break;
144 default:
145 async_answer_0(callid, EINVAL);
146 }
147 }
148 }
149}
150
151static void s3c24xx_uart_irq_handler(ipc_callid_t iid, ipc_call_t *call,
152 void *arg)
153{
154 (void) iid;
155 (void) call;
156 (void) arg;
157
158 while ((pio_read_32(&uart->io->ufstat) & S3C24XX_UFSTAT_RX_COUNT) != 0) {
159 uint32_t data = pio_read_32(&uart->io->urxh) & 0xff;
160 uint32_t status = pio_read_32(&uart->io->uerstat);
161
162 if (uart->client_sess != NULL) {
163 async_exch_t *exch = async_exchange_begin(uart->client_sess);
164 async_msg_1(exch, CHAR_NOTIF_BYTE, data);
165 async_exchange_end(exch);
166 }
167
168 if (status != 0)
169 printf(NAME ": Error status 0x%x\n", status);
170 }
171}
172
173/** Initialize S3C24xx on-chip UART. */
174static int s3c24xx_uart_init(s3c24xx_uart_t *uart)
175{
176 void *vaddr;
177 sysarg_t inr;
178
179 if (sysinfo_get_value("s3c24xx_uart.address.physical",
180 &uart->paddr) != EOK)
181 return -1;
182
183 if (pio_enable((void *) uart->paddr, sizeof(s3c24xx_uart_io_t),
184 &vaddr) != 0)
185 return -1;
186
187 if (sysinfo_get_value("s3c24xx_uart.inr", &inr) != EOK)
188 return -1;
189
190 uart->io = vaddr;
191 uart->client_sess = NULL;
192
193 printf(NAME ": device at physical address %p, inr %" PRIun ".\n",
194 (void *) uart->paddr, inr);
195
196 async_irq_subscribe(inr, device_assign_devno(), s3c24xx_uart_irq_handler,
197 NULL, &uart_irq_code);
198
199 /* Enable FIFO, Tx trigger level: empty, Rx trigger level: 1 byte. */
200 pio_write_32(&uart->io->ufcon, UFCON_FIFO_ENABLE |
201 UFCON_TX_FIFO_TLEVEL_EMPTY | UFCON_RX_FIFO_TLEVEL_1B);
202
203 /* Set RX interrupt to pulse mode */
204 pio_write_32(&uart->io->ucon,
205 pio_read_32(&uart->io->ucon) & ~UCON_RX_INT_LEVEL);
206
207 return EOK;
208}
209
210/** Send a byte to the UART. */
211static void s3c24xx_uart_sendb(s3c24xx_uart_t *uart, uint8_t byte)
212{
213 /* Wait for space becoming available in Tx FIFO. */
214 while ((pio_read_32(&uart->io->ufstat) & S3C24XX_UFSTAT_TX_FULL) != 0)
215 ;
216
217 pio_write_32(&uart->io->utxh, byte);
218}
219
220/** @}
221 */
Note: See TracBrowser for help on using the repository browser.