1 //==========================================================================
5 // SA1110/iPAQ - Atmel micro-controller support routines
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
44 // Contributors: gthomas
46 // Description: Simple Atmel support
47 //####DESCRIPTIONEND####
49 #include <pkgconf/system.h>
50 #include <pkgconf/hal.h>
56 #include <cyg/infra/diag.h>
57 #include <cyg/hal/hal_if.h> // Virtual vector functions
58 #include <cyg/hal/hal_io.h> // IO macros
59 #include <cyg/hal/hal_arch.h> // Register state info
60 #include <cyg/hal/hal_intr.h> // HAL interrupt macros
62 #include <cyg/hal/hal_sa11x0.h> // Board definitions
63 #include <cyg/hal/ipaq.h>
64 #include <cyg/hal/hal_cache.h>
67 // Need to export interrupt driven interfaces
68 #include <cyg/hal/drv_api.h>
69 #define ATMEL_INT CYGNUM_HAL_INTERRUPT_UART1
70 static cyg_interrupt atmel_interrupt;
71 static cyg_handle_t atmel_interrupt_handle;
74 #include <cyg/hal/atmel_support.h> // Interfaces, commands
76 externC void *memcpy(void *, const void *, size_t);
78 struct sa11x0_serial {
79 volatile cyg_uint32 utcr0;
80 volatile cyg_uint32 utcr1;
81 volatile cyg_uint32 utcr2;
82 volatile cyg_uint32 utcr3;
83 volatile cyg_uint32 pad0010;
84 volatile cyg_uint32 utdr;
85 volatile cyg_uint32 pad0018;
86 volatile cyg_uint32 utsr0;
87 volatile cyg_uint32 utsr1;
90 #define ATMEL_PUTQ_SIZE 32
91 unsigned char atmel_putq[ATMEL_PUTQ_SIZE];
92 int atmel_putq_put, atmel_putq_get;
97 atmel_putc(unsigned char c)
99 atmel_putq[atmel_putq_put++] = c;
100 if (atmel_putq_put == ATMEL_PUTQ_SIZE) {
105 static atmel_handler *handlers[NUM_ATMEL_CMDS];
108 null_handler(atmel_pkt *pkt)
110 diag_printf("Atmel - packet ignored: %x\n", pkt->data[0]);
111 diag_dump_buf(pkt->data, 16);
115 // Register a handler for a particular packet type
118 atmel_register(int cmd, atmel_handler *fun)
124 // This routine is called to process an input character from the
125 // Atmel micro-controller. Since command packets are multiple
126 // characters, this routine has to keep state for the packet. Once
127 // a complete packet is received, the appropriate handler function
128 // will be called (if the checksum matches)
131 atmel_in(unsigned char ch)
133 static atmel_pkt pkt;
134 static unsigned char cksum;
135 static bool sof = false;
138 // Wait for start of packet (SOF)
140 return; // Just ignore out of order characters
147 // First byte of packet - command+length;
148 pkt.len = (ch & 0x0F) + 1;
151 pkt.data[pkt.size++] = ch;
152 if (pkt.size > pkt.len) {
153 // End of packet data
155 (*handlers[pkt.data[0] >> 4])(&pkt);
164 // This [internal] routine is used to handle data from the Atmel micro-controller
169 volatile struct sa11x0_serial *base = (volatile struct sa11x0_serial *)SA11X0_UART1_BASE;
172 while ((base->utsr1 & SA11X0_UART_RX_FIFO_NOT_EMPTY) != 0) {
173 ch = (char)base->utdr;
179 // This [internal] routine is used to send data to the Atmel micro-controller
184 volatile struct sa11x0_serial *base = (volatile struct sa11x0_serial *)SA11X0_UART1_BASE;
189 while (atmel_putq_get != atmel_putq_put) {
190 if ((base->utsr1 & SA11X0_UART_TX_FIFO_NOT_FULL) == 0) {
191 // Wait forever if in non-interrupt mode
192 if (atmel_use_ints) {
196 base->utdr = atmel_putq[atmel_putq_get++];
197 if (atmel_putq_get == ATMEL_PUTQ_SIZE) {
203 cyg_drv_isr_unlock();
209 // Low level interrupt handler (ISR)
211 atmel_ISR(cyg_vector_t vector, cyg_addrword_t data)
213 cyg_drv_interrupt_mask(vector);
214 cyg_drv_interrupt_acknowledge(vector);
215 return CYG_ISR_CALL_DSR; // Cause DSR to be run
218 // High level interrupt handler (DSR)
220 atmel_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
222 volatile struct sa11x0_serial *base = (volatile struct sa11x0_serial *)SA11X0_UART1_BASE;
223 unsigned int stat0 = base->utsr0;
225 if (stat0 & SA11X0_UART_TX_SERVICE_REQUEST) {
228 if (stat0 & (SA11X0_UART_RX_SERVICE_REQUEST|SA11X0_UART_RX_IDLE)) {
230 base->utsr0 = SA11X0_UART_RX_IDLE; // Need to clear this manually
232 cyg_drv_interrupt_unmask(vector);
236 // Connect/disconnect interrupt processing
239 atmel_interrupt_mode(bool enable)
241 volatile struct sa11x0_serial *base = (volatile struct sa11x0_serial *)SA11X0_UART1_BASE;
244 // Enable the receiver (with interrupts) and the transmitter.
245 base->utcr3 = SA11X0_UART_RX_ENABLED |
246 SA11X0_UART_TX_ENABLED |
247 SA11X0_UART_RX_FIFO_INT_ENABLED;
248 cyg_drv_interrupt_unmask(ATMEL_INT);
250 cyg_drv_interrupt_mask(ATMEL_INT);
252 atmel_use_ints = enable;
257 // Set up the Atmel micro-controller environment
262 volatile struct sa11x0_serial *base = (volatile struct sa11x0_serial *)SA11X0_UART1_BASE;
265 static bool _init = false;
269 // Disable Receiver and Transmitter (clears FIFOs)
270 base->utcr3 = SA11X0_UART_RX_DISABLED | SA11X0_UART_TX_DISABLED;
272 // Clear sticky (writable) status bits.
273 base->utsr0 = SA11X0_UART_RX_IDLE | SA11X0_UART_RX_BEGIN_OF_BREAK |
274 SA11X0_UART_RX_END_OF_BREAK;
276 // Set UART to 8N1 (8 data bits, no partity, 1 stop bit)
277 base->utcr0 = SA11X0_UART_PARITY_DISABLED | SA11X0_UART_STOP_BITS_1 |
278 SA11X0_UART_DATA_BITS_8;
280 // Set the desired baud rate.
281 brd = SA11X0_UART_BAUD_RATE_DIVISOR(115200);
282 base->utcr1 = (brd >> 8) & SA11X0_UART_H_BAUD_RATE_DIVISOR_MASK;
283 base->utcr2 = brd & SA11X0_UART_L_BAUD_RATE_DIVISOR_MASK;
285 // Enable the receiver and the transmitter.
286 base->utcr3 = SA11X0_UART_RX_ENABLED | SA11X0_UART_TX_ENABLED;
288 // Set up character queues
289 atmel_putq_put = atmel_putq_get = 0;
290 atmel_use_ints = false;
293 for (i = 0; i < NUM_ATMEL_CMDS; i++) {
294 atmel_register(i, null_handler);
298 cyg_drv_interrupt_create(ATMEL_INT,
299 99, // Priority - unused
300 (cyg_addrword_t)base, // Data item passed to interrupt handler
303 &atmel_interrupt_handle,
305 cyg_drv_interrupt_attach(atmel_interrupt_handle);
312 atmel_pkt_send(atmel_pkt *pkt)
316 for (i = 0; i < pkt->len; i++) {
317 atmel_putc(pkt->data[i]);
323 atmel_send(int cmd, unsigned char *data, int len)
326 unsigned char cksum, *dp;
331 *dp++ = cksum = (cmd << 4) | len;
332 for (i = 0; i < len; i++) {
338 atmel_pkt_send(&pkt);
342 #define MAX_TS_EVENTS 32
343 static struct ts_event ts_event_list[MAX_TS_EVENTS];
344 static int num_ts_events = 0;
345 static int ts_event_get, ts_event_put;
348 ts_event_handler(atmel_pkt *pkt)
350 unsigned char *buf = pkt->data;
351 static bool up = true;
352 static int down_count = 0;
353 struct ts_event *tse;
355 if (num_ts_events == MAX_TS_EVENTS) {
358 if ((buf[0] & 0x0F) == 0) {
362 tse = &ts_event_list[ts_event_put++];
363 if (ts_event_put == MAX_TS_EVENTS) {
367 tse->x = (buf[1] << 8) | buf[2];
368 tse->y = (buf[3] << 8) | buf[4];
372 if (down_count++ == 0) {
373 // First 'down' event
377 tse = &ts_event_list[ts_event_put++];
378 if (ts_event_put == MAX_TS_EVENTS) {
382 tse->x = (buf[1] << 8) | buf[2];
383 tse->y = (buf[3] << 8) | buf[4];
390 ts_get_event(struct ts_event *tse)
392 static bool _init = false;
395 atmel_register(ATMEL_CMD_TOUCH, ts_event_handler);
396 atmel_register(ATMEL_CMD_UNKNOWN, ts_event_handler);
400 if (num_ts_events == 0) {
405 memcpy(tse, &ts_event_list[ts_event_get++], sizeof(*tse));
406 if (ts_event_get == MAX_TS_EVENTS) {
415 #define MAX_KEY_EVENTS 8
416 static struct key_event key_event_list[MAX_KEY_EVENTS];
417 static int num_key_events = 0;
418 static int key_event_get, key_event_put;
421 kbd_event_handler(atmel_pkt *pkt)
423 unsigned char *buf = pkt->data;
424 struct key_event *ke;
426 if (num_key_events == MAX_KEY_EVENTS) {
429 // printf("Keybd = %x\n", buf[1]);
430 ke = &key_event_list[key_event_put++];
431 if (key_event_put == MAX_KEY_EVENTS) {
434 ke->button_info = buf[1];
439 key_get_event(struct key_event *ke)
441 static bool _init = false;
444 atmel_register(ATMEL_CMD_KEYBD, kbd_event_handler);
448 if (num_key_events == 0) {
451 if (num_key_events) {
453 memcpy(ke, &key_event_list[key_event_get++], sizeof(*ke));
454 if (key_event_get == MAX_KEY_EVENTS) {
463 #ifdef CYGPKG_REDBOOT
466 atmel_check(bool is_idle)
469 RedBoot_idle(atmel_check, RedBoot_BEFORE_NETIO);