summaryrefslogtreecommitdiff
path: root/firmware/target/arm/s5l8702/uart-s5l8702.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/s5l8702/uart-s5l8702.c')
-rw-r--r--firmware/target/arm/s5l8702/uart-s5l8702.c155
1 files changed, 89 insertions, 66 deletions
diff --git a/firmware/target/arm/s5l8702/uart-s5l8702.c b/firmware/target/arm/s5l8702/uart-s5l8702.c
index 45d61ba627..9d8faaa173 100644
--- a/firmware/target/arm/s5l8702/uart-s5l8702.c
+++ b/firmware/target/arm/s5l8702/uart-s5l8702.c
@@ -18,110 +18,133 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21 21#include <stdint.h>
22/* Include Standard files */ 22#include <stdbool.h>
23#include <stdlib.h>
24#include <stdio.h>
25#include <stdarg.h>
26 23
27#include "config.h" 24#include "config.h"
28#include "cpu.h" 25#include "cpu.h"
29#include "system.h" 26#include "system.h"
30#include "kernel.h"
31 27
32#include "s5l8702.h" 28#include "s5l8702.h"
33#include "uc8702.h" 29#include "uc870x.h"
34#include "uart-s5l8702.h"
35 30
36 31
37/* s5l8702 UART configuration */ 32/*
38struct uartc s5l8702_uart = { 33 * s5l8702 UC870X HW: 1 UARTC, 4 ports
39 .baddr = S5L8702_UART_BASE 34 */
35static struct uartc_port *uartc_port_l[UARTC_N_PORTS];
36const struct uartc s5l8702_uartc =
37{
38 .id = 0,
39 .baddr = UARTC_BASE_ADDR,
40 .port_off = UARTC_PORT_OFFSET,
41 .n_ports = UARTC_N_PORTS,
42 .port_l = uartc_port_l,
40}; 43};
41 44
42/* 45/*
43 * Device level functions specific to S5L8702 46 * Device level functions specific to S5L8702
44 */ 47 */
45void uart_gpio_control(int port_id, bool onoff) 48void uart_target_enable_gpio(int uart_id, int port_id)
46{ 49{
47 if (onoff) { 50 (void) uart_id;
48 switch (port_id) { 51 switch (port_id) {
49 case 0: 52 case 0:
50 /* configure UART0 Tx/Rx GPIO ports */ 53 /* configure UART0 Tx/Rx GPIO ports */
51 PCON0 = (PCON0 & 0xff00ffff) | 0x00220000; 54 PCON0 = (PCON0 & 0xff00ffff) | 0x00220000;
52 break; 55 break;
53 case 1: 56 case 1:
54 /* configure UART1 GPIO ports, including RTS/CTS signals */ 57 /* configure UART1 GPIO ports, including RTS/CTS signals */
55 PCOND = (PCOND & 0xff0000ff) | 0x00222200; 58 PCOND = (PCOND & 0xff0000ff) | 0x00222200;
56 break; 59 break;
57 case 2: 60 case 2:
58 case 3: 61 case 3:
59 /* unknown, probably UART3/4 not routed on s5l8702 */ 62 /* unknown */
60 default: 63 default:
61 break; 64 break;
62 }
63 } 65 }
64 else { 66}
67
68void uart_target_disable_gpio(int uart_id, int port_id)
69{
70 (void) uart_id;
71 switch (port_id) {
65 /* configure minimal power consumption */ 72 /* configure minimal power consumption */
66 switch (port_id) { 73 case 0:
67 case 0: 74 PCON0 = (PCON0 & 0xff00ffff) | 0x00ee0000;
68 PCON0 = (PCON0 & 0xff00ffff) | 0x00ee0000; 75 break;
69 break; 76 case 1:
70 case 1: 77 PCOND = (PCOND & 0xff0000ff) | 0x00eeee00;
71 PCOND = (PCOND & 0xff0000ff) | 0x00eeee00; 78 break;
72 break; 79 case 2:
73 case 2: 80 case 3:
74 case 3: 81 default:
75 default: 82 break;
76 break;
77 }
78 } 83 }
79} 84}
80 85
81/* reset s5l8702 uart related hardware */ 86void uart_target_enable_irq(int uart_id, int port_id)
82static void s5l8702_uart_hw_init(void)
83{ 87{
84 for (int id = 0; id < S5L8702_UART_PORT_MAX; id++) { 88 (void) uart_id;
85 VIC0INTENCLEAR = 1 << IRQ_UART(id); /* mask INT */ 89 VIC0INTENABLE = 1 << IRQ_UART(port_id);
86 uart_gpio_control(id, 0);
87 }
88} 90}
89 91
90void uart_init(void) 92void uart_target_disable_irq(int uart_id, int port_id)
91{ 93{
92 s5l8702_uart_hw_init(); 94 (void) uart_id;
93 PWRCON(1) &= ~(1 << (CLOCKGATE_UART - 32)); /* on */ 95 VIC0INTENCLEAR = 1 << IRQ_UART(port_id);
94 uartc_open(&s5l8702_uart);
95} 96}
96 97
97void uart_close(void) 98void uart_target_clear_irq(int uart_id, int port_id)
98{ 99{
99 uartc_close(&s5l8702_uart); 100 (void) uart_id;
100 PWRCON(1) |= (1 << (CLOCKGATE_UART - 32)); /* off */ 101 (void) port_id;
101 s5l8702_uart_hw_init();
102} 102}
103 103
104void uart_port_init(struct uartc_port *port) 104void uart_target_enable_clocks(int uart_id)
105{ 105{
106 uart_gpio_control(port->id, 1); 106 (void) uart_id;
107 uartc_port_open(port); 107 PWRCON(1) &= ~(1 << (CLOCKGATE_UARTC - 32));
108 VIC0INTENABLE = 1 << IRQ_UART(port->id); /* unmask INT */
109} 108}
110 109
111void uart_port_close(struct uartc_port *port) 110void uart_target_disable_clocks(int uart_id)
112{ 111{
113 VIC0INTENCLEAR = 1 << IRQ_UART(port->id); /* mask INT */ 112 (void) uart_id;
114 uartc_port_close(port); 113 PWRCON(1) |= (1 << (CLOCKGATE_UARTC - 32));
115 uart_gpio_control(port->id, 0);
116} 114}
117 115
118/* ISRs */ 116/*
117 * ISRs
118 */
119
120/* On Classic, PORT0 interrupts are not used when iAP is disabled */
121#if !defined(IPOD_6G) || defined(IPOD_ACCESSORY_PROTOCOL)
119void ICODE_ATTR INT_UART0(void) 122void ICODE_ATTR INT_UART0(void)
120{ 123{
121 uartc_callback(&s5l8702_uart, 0); 124 uartc_callback(&s5l8702_uartc, 0);
122} 125}
126#endif
123 127
128/* PORT1,2,3 not used on Classic */
129#ifndef IPOD_6G
124void ICODE_ATTR INT_UART1(void) 130void ICODE_ATTR INT_UART1(void)
125{ 131{
126 uartc_callback(&s5l8702_uart, 1); 132 uartc_callback(&s5l8702_uartc, 1);
133}
134
135void ICODE_ATTR INT_UART2(void)
136{
137 uartc_callback(&s5l8702_uartc, 2);
138}
139
140void ICODE_ATTR INT_UART3(void)
141{
142 uartc_callback(&s5l8702_uartc, 3);
143}
144#endif
145
146/* Main init */
147void uart_init(void)
148{
149 uartc_open(&s5l8702_uartc);
127} 150}