summaryrefslogtreecommitdiff
path: root/firmware/target/coldfire/iaudio/pcf50606-iaudio.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/coldfire/iaudio/pcf50606-iaudio.c')
-rw-r--r--firmware/target/coldfire/iaudio/pcf50606-iaudio.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/firmware/target/coldfire/iaudio/pcf50606-iaudio.c b/firmware/target/coldfire/iaudio/pcf50606-iaudio.c
new file mode 100644
index 0000000000..f8f6c1d675
--- /dev/null
+++ b/firmware/target/coldfire/iaudio/pcf50606-iaudio.c
@@ -0,0 +1,127 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "config.h"
20#include "system.h"
21#include "kernel.h"
22#include "pcf50606.h"
23#include "button-target.h"
24#include "powermgmt.h"
25
26/* These voltages were determined by measuring the output of the PCF50606
27 on a running X5, and verified by disassembling the original firmware */
28static void set_voltages(void)
29{
30 static const unsigned char buf[4] =
31 {
32 0xf4, /* IOREGC = 2.9V, ON in all states */
33 0xf0, /* D1REGC = 2.5V, ON in all states */
34 0xf6, /* D2REGC = 3.1V, ON in all states */
35 0xf4, /* D3REGC = 2.9V, ON in all states */
36 };
37
38 pcf50606_write_multiple(0x23, buf, 4);
39}
40
41static void init_pmu_interrupts(void)
42{
43 /* inital data is interrupt masks */
44 unsigned char data[3] =
45 {
46 ~0x04, /* unmask ONKEY1S */
47 ~0x00,
48 ~0x06, /* unmask ACDREM, ACDINS */
49 };
50
51 /* make sure GPI0 interrupt is off before unmasking anything */
52 and_l(~0xf, &INTPRI5); /* INT32 - Priority 0 (Off) */
53
54 /* unmask the PMU interrupts we want to service */
55 pcf50606_write_multiple(0x05, data, 3);
56 /* clear INT1-3 as these are left set after standby */
57 pcf50606_read_multiple(0x02, data, 3);
58
59 /* Set to read pcf50606 INT but keep GPI0 off until init completes */
60 and_l(~0x00000001, &GPIO_ENABLE);
61 or_l(0x00000001, &GPIO_FUNCTION);
62 or_l(0x00000100, &GPIO_INT_EN); /* GPI0 H-L */
63}
64
65static inline void enable_pmu_interrupts(void)
66{
67 /* clear pending GPI0 interrupts first or it may miss the first
68 H-L transition */
69 or_l(0x00000100, &GPIO_INT_CLEAR);
70 or_l(0x3, &INTPRI5); /* INT32 - Priority 3 */
71}
72
73void pcf50606_init(void)
74{
75 pcf50606_i2c_init();
76
77 /* initialize pmu interrupts but don't service them yet */
78 init_pmu_interrupts();
79 set_voltages();
80
81 pcf50606_write(0x39, 0x00); /* GPOOD0 = green led OFF */
82 pcf50606_write(0x3a, 0x00); /* GPOOD1 = red led OFF */
83
84 /* Accessory detect */
85 pcf50606_write(0x33, 0x8c); /* ACDAPE=1, THRSHLD=2.20V */
86
87 /* allow GPI0 interrupts from PMU now */
88 enable_pmu_interrupts();
89}
90
91void pcf50606_reset_timeout(void)
92{
93 int level = set_irq_level(HIGHEST_IRQ_LEVEL);
94 pcf50606_write(0x08, pcf50606_read(0x08) | 0x02); /* OOCC1 - TOTRST=1 */
95 set_irq_level(level);
96}
97
98/* Handles interrupts generated by the pcf50606 */
99void GPI0(void) __attribute__ ((interrupt_handler, section(".text")));
100void GPI0(void)
101{
102 unsigned char data[3]; /* 0 = INT1, 1 = INT2, 2 = INT3 */
103
104 /* Clear pending GPI0 interrupts */
105 or_l(0x00000100, &GPIO_INT_CLEAR);
106
107 /* clear pending interrupts from pcf50606 */
108 pcf50606_read_multiple(0x02, data, 3);
109
110 if (data[0] & 0x04)
111 {
112 /* ONKEY1S */
113 if (GPIO_READ & 0x02000000)
114 sys_poweroff(); /* main ONKEY */
115 else
116 pcf50606_reset_timeout(); /* remote ONKEY */
117 }
118
119 if (data[2] & 0x06)
120 {
121 /* ACDINS/ACDREM */
122 /* Check if main buttons should be actually be scanned or not
123 - bias towards "yes" out of paranoia. */
124 button_enable_scan((data[2] & 0x02) != 0 ||
125 (pcf50606_read(0x33) & 0x01) != 0);
126 }
127}