diff options
author | Cástor Muñoz <cmvidal@gmail.com> | 2016-05-12 06:47:38 +0200 |
---|---|---|
committer | Cástor Muñoz <cmvidal@gmail.com> | 2016-05-13 23:21:42 +0200 |
commit | 8fb67f48ab57770c3233352de17846a8a773192a (patch) | |
tree | fcf00f022dcd297c10ab92df8b85021f55e96f6f /firmware/target/arm/s5l8702/uart-s5l8702.c | |
parent | 2a1e9eb8a8f50f636f86988de1f0cd1b3acf55bb (diff) | |
download | rockbox-8fb67f48ab57770c3233352de17846a8a773192a.tar.gz rockbox-8fb67f48ab57770c3233352de17846a8a773192a.zip |
iPod Classic: updates for uc8702 driver
- Small rework on the UC8702 UART controller to make it compatible with
other s5l870x SOCs. Files moved and renamed, many conditional code
added to deal with capabilities and 'features' of the different CPUs.
- A couple of optimizacions that should not affect the functionality.
Change-Id: I705169f7e8b18d5d1da642f81ffc31c4089780a6
Diffstat (limited to 'firmware/target/arm/s5l8702/uart-s5l8702.c')
-rw-r--r-- | firmware/target/arm/s5l8702/uart-s5l8702.c | 155 |
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 | /* |
38 | struct uartc s5l8702_uart = { | 33 | * s5l8702 UC870X HW: 1 UARTC, 4 ports |
39 | .baddr = S5L8702_UART_BASE | 34 | */ |
35 | static struct uartc_port *uartc_port_l[UARTC_N_PORTS]; | ||
36 | const 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 | */ |
45 | void uart_gpio_control(int port_id, bool onoff) | 48 | void 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 | |||
68 | void 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 */ | 86 | void uart_target_enable_irq(int uart_id, int port_id) |
82 | static 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 | ||
90 | void uart_init(void) | 92 | void 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 | ||
97 | void uart_close(void) | 98 | void 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 | ||
104 | void uart_port_init(struct uartc_port *port) | 104 | void 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 | ||
111 | void uart_port_close(struct uartc_port *port) | 110 | void 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) | ||
119 | void ICODE_ATTR INT_UART0(void) | 122 | void 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 | ||
124 | void ICODE_ATTR INT_UART1(void) | 130 | void ICODE_ATTR INT_UART1(void) |
125 | { | 131 | { |
126 | uartc_callback(&s5l8702_uart, 1); | 132 | uartc_callback(&s5l8702_uartc, 1); |
133 | } | ||
134 | |||
135 | void ICODE_ATTR INT_UART2(void) | ||
136 | { | ||
137 | uartc_callback(&s5l8702_uartc, 2); | ||
138 | } | ||
139 | |||
140 | void ICODE_ATTR INT_UART3(void) | ||
141 | { | ||
142 | uartc_callback(&s5l8702_uartc, 3); | ||
143 | } | ||
144 | #endif | ||
145 | |||
146 | /* Main init */ | ||
147 | void uart_init(void) | ||
148 | { | ||
149 | uartc_open(&s5l8702_uartc); | ||
127 | } | 150 | } |