diff options
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c')
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c b/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c new file mode 100644 index 0000000000..3af8f35f69 --- /dev/null +++ b/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c | |||
@@ -0,0 +1,173 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (c) 2008 by Michael Sevakis | ||
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 "system.h" | ||
20 | #include "cpu.h" | ||
21 | #include "spi-imx31.h" | ||
22 | #include "mc13783.h" | ||
23 | #include "debug.h" | ||
24 | #include "kernel.h" | ||
25 | |||
26 | /* This is all based on communicating with the MC13783 PMU which is on | ||
27 | * CSPI2 with the chip select at 0. The LCD controller resides on | ||
28 | * CSPI3 cs1, but we have no idea how to communicate to it */ | ||
29 | static struct spi_node mc13783_spi = | ||
30 | { | ||
31 | CSPI2_NUM, /* CSPI module 2 */ | ||
32 | CSPI_CONREG_CHIP_SELECT_SS0 | /* Chip select 0 */ | ||
33 | CSPI_CONREG_DRCTL_DONT_CARE | /* Don't care about CSPI_RDY */ | ||
34 | CSPI_CONREG_DATA_RATE_DIV_4 | /* Clock = IPG_CLK/4 - 16.5MHz */ | ||
35 | CSPI_BITCOUNT(32-1) | /* All 32 bits are to be transferred */ | ||
36 | CSPI_CONREG_SSPOL | /* SS active high */ | ||
37 | CSPI_CONREG_SSCTL | /* Negate SS between SPI bursts */ | ||
38 | CSPI_CONREG_MODE, /* Master mode */ | ||
39 | 0, /* SPI clock - no wait states */ | ||
40 | }; | ||
41 | |||
42 | static int mc13783_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)]; | ||
43 | static const char *mc13783_thread_name = "pmic"; | ||
44 | static struct wakeup mc13783_wake; | ||
45 | |||
46 | static __attribute__((noreturn)) void mc13783_interrupt_thread(void) | ||
47 | { | ||
48 | while (1) | ||
49 | { | ||
50 | wakeup_wait(&mc13783_wake, TIMEOUT_BLOCK); | ||
51 | } | ||
52 | } | ||
53 | |||
54 | static __attribute__((interrupt("IRQ"))) void mc13783_interrupt(void) | ||
55 | { | ||
56 | wakeup_signal(&mc13783_wake); | ||
57 | } | ||
58 | |||
59 | void mc13783_init(void) | ||
60 | { | ||
61 | /* Serial interface must have been initialized first! */ | ||
62 | wakeup_init(&mc13783_wake); | ||
63 | |||
64 | /* Enable the PMIC SPI module */ | ||
65 | spi_enable_module(&mc13783_spi); | ||
66 | |||
67 | create_thread(mc13783_interrupt_thread, mc13783_thread_stack, | ||
68 | sizeof(mc13783_thread_stack), 0, mc13783_thread_name | ||
69 | IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU)); | ||
70 | } | ||
71 | |||
72 | void mc13783_set(unsigned address, uint32_t bits) | ||
73 | { | ||
74 | spi_lock(&mc13783_spi); | ||
75 | uint32_t data = mc13783_read(address); | ||
76 | mc13783_write(address, data | bits); | ||
77 | spi_unlock(&mc13783_spi); | ||
78 | } | ||
79 | |||
80 | void mc13783_clear(unsigned address, uint32_t bits) | ||
81 | { | ||
82 | spi_lock(&mc13783_spi); | ||
83 | uint32_t data = mc13783_read(address); | ||
84 | mc13783_write(address, data & ~bits); | ||
85 | spi_unlock(&mc13783_spi); | ||
86 | } | ||
87 | |||
88 | int mc13783_write(unsigned address, uint32_t data) | ||
89 | { | ||
90 | struct spi_transfer xfer; | ||
91 | uint32_t packet; | ||
92 | |||
93 | if (address >= MC13783_NUM_REGS) | ||
94 | return -1; | ||
95 | |||
96 | packet = (1 << 31) | (address << 25) | (data & 0xffffff); | ||
97 | xfer.txbuf = &packet; | ||
98 | xfer.rxbuf = &packet; | ||
99 | xfer.count = 1; | ||
100 | |||
101 | if (!spi_transfer(&mc13783_spi, &xfer)) | ||
102 | return -1; | ||
103 | |||
104 | return 1 - xfer.count; | ||
105 | } | ||
106 | |||
107 | int mc13783_write_multiple(unsigned start, const uint32_t *data, int count) | ||
108 | { | ||
109 | int i; | ||
110 | struct spi_transfer xfer; | ||
111 | uint32_t packets[64]; | ||
112 | |||
113 | if (start + count > MC13783_NUM_REGS) | ||
114 | return -1; | ||
115 | |||
116 | /* Prepare payload */ | ||
117 | for (i = 0; i < count; i++, start++) | ||
118 | { | ||
119 | packets[i] = (1 << 31) | (start << 25) | (data[i] & 0xffffff); | ||
120 | } | ||
121 | |||
122 | xfer.txbuf = packets; | ||
123 | xfer.rxbuf = packets; | ||
124 | xfer.count = count; | ||
125 | |||
126 | if (!spi_transfer(&mc13783_spi, &xfer)) | ||
127 | return -1; | ||
128 | |||
129 | return count - xfer.count; | ||
130 | } | ||
131 | |||
132 | uint32_t mc13783_read(unsigned address) | ||
133 | { | ||
134 | uint32_t packet; | ||
135 | struct spi_transfer xfer; | ||
136 | |||
137 | if (address >= MC13783_NUM_REGS) | ||
138 | return (uint32_t)-1; | ||
139 | |||
140 | packet = address << 25; | ||
141 | |||
142 | xfer.txbuf = &packet; | ||
143 | xfer.rxbuf = &packet; | ||
144 | xfer.count = 1; | ||
145 | |||
146 | if (!spi_transfer(&mc13783_spi, &xfer)) | ||
147 | return (uint32_t)-1; | ||
148 | |||
149 | return packet & 0xffffff; | ||
150 | } | ||
151 | |||
152 | int mc13783_read_multiple(unsigned start, uint32_t *buffer, int count) | ||
153 | { | ||
154 | int i; | ||
155 | uint32_t packets[64]; | ||
156 | struct spi_transfer xfer; | ||
157 | |||
158 | if (start + count > MC13783_NUM_REGS) | ||
159 | return -1; | ||
160 | |||
161 | xfer.txbuf = packets; | ||
162 | xfer.rxbuf = buffer; | ||
163 | xfer.count = count; | ||
164 | |||
165 | /* Prepare TX payload */ | ||
166 | for (i = 0; i < count; i++, start++) | ||
167 | packets[i] = start << 25; | ||
168 | |||
169 | if (!spi_transfer(&mc13783_spi, &xfer)) | ||
170 | return -1; | ||
171 | |||
172 | return count - xfer.count; | ||
173 | } | ||