summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCástor Muñoz <cmvidal@gmail.com>2016-02-04 20:12:02 +0100
committerCástor Muñoz <cmvidal@gmail.com>2016-05-15 21:16:54 +0200
commit469d64539007584241ccd475e81038ea4166f17b (patch)
tree2de03ef2c45cfa845afd8015775d7457029404f7
parent44ce4eebd61302a22cbcc8fdaa0851adc103550f (diff)
downloadrockbox-469d64539007584241ccd475e81038ea4166f17b.tar.gz
rockbox-469d64539007584241ccd475e81038ea4166f17b.zip
iPod Classic: prepare i2c and PMU for bootloader
When the bootloader starts only IRAM is available, the first task is to ask the PMU to verify if the iPod has previously been hibernated by OF. Due to memory limitations, the kernel cannot be used on this stage. This patch modifies I2C and PMU low level functions to not to depend on kernel (removes mutexes, and uses HW timer instead of current_tick), actual kernel functions are modified to be 'mutexed' wrappers of the new functions. Change-Id: I7cef9e95dedaf176dc0659315f3dc33166d5b116
-rw-r--r--firmware/export/i2c-s5l8702.h6
-rw-r--r--firmware/target/arm/s5l8702/i2c-s5l8702.c87
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c24
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/pmu-target.h9
4 files changed, 73 insertions, 53 deletions
diff --git a/firmware/export/i2c-s5l8702.h b/firmware/export/i2c-s5l8702.h
index 02dc40d89e..3883c8abc0 100644
--- a/firmware/export/i2c-s5l8702.h
+++ b/firmware/export/i2c-s5l8702.h
@@ -28,5 +28,9 @@ void i2c_init(void);
28int i2c_write(int bus, unsigned char slave, int address, int len, const unsigned char *data); 28int i2c_write(int bus, unsigned char slave, int address, int len, const unsigned char *data);
29int i2c_read(int bus, unsigned char slave, int address, int len, unsigned char *data); 29int i2c_read(int bus, unsigned char slave, int address, int len, unsigned char *data);
30 30
31#endif /* _I2C_S5l8702_H */ 31#ifdef BOOTLOADER
32int i2c_wr(int bus, unsigned char slave, int address, int len, const unsigned char *data);
33int i2c_rd(int bus, unsigned char slave, int address, int len, unsigned char *data);
34#endif
32 35
36#endif /* _I2C_S5l8702_H */
diff --git a/firmware/target/arm/s5l8702/i2c-s5l8702.c b/firmware/target/arm/s5l8702/i2c-s5l8702.c
index 4d0e4188ab..619768410a 100644
--- a/firmware/target/arm/s5l8702/i2c-s5l8702.c
+++ b/firmware/target/arm/s5l8702/i2c-s5l8702.c
@@ -18,7 +18,7 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#include "config.h" 22#include "config.h"
23#include "system.h" 23#include "system.h"
24#include "kernel.h" 24#include "kernel.h"
@@ -71,68 +71,52 @@ void i2c_init()
71 mutex_init(&i2c_mtx[1]); 71 mutex_init(&i2c_mtx[1]);
72} 72}
73 73
74int i2c_write(int bus, unsigned char slave, int address, int len, const unsigned char *data) 74int i2c_wr(int bus, unsigned char slave, int address, int len, const unsigned char *data)
75{ 75{
76 mutex_lock(&i2c_mtx[bus]);
77 i2c_on(bus); 76 i2c_on(bus);
78 long timeout = current_tick + HZ / 50; 77 long timeout = USEC_TIMER + 20000;
79 78
80 /* START */ 79 /* START */
81 IICDS(bus) = slave & ~1; 80 IICDS(bus) = slave & ~1;
82 IICSTAT(bus) = 0xF0; 81 IICSTAT(bus) = 0xF0;
83 IICCON(bus) = 0xB3; 82 IICCON(bus) = 0xB3;
84 while ((IICCON(bus) & 0x10) == 0) 83 while ((IICCON(bus) & 0x10) == 0)
85 if (TIME_AFTER(current_tick, timeout)) 84 if (TIME_AFTER(USEC_TIMER, timeout))
86 {
87 mutex_unlock(&i2c_mtx[bus]);
88 return 1; 85 return 1;
89 }
90 86
91
92 if (address >= 0) { 87 if (address >= 0) {
93 /* write address */ 88 /* write address */
94 IICDS(bus) = address; 89 IICDS(bus) = address;
95 IICCON(bus) = 0xB3; 90 IICCON(bus) = 0xB3;
96 while ((IICCON(bus) & 0x10) == 0) 91 while ((IICCON(bus) & 0x10) == 0)
97 if (TIME_AFTER(current_tick, timeout)) 92 if (TIME_AFTER(USEC_TIMER, timeout))
98 {
99 mutex_unlock(&i2c_mtx[bus]);
100 return 2; 93 return 2;
101 }
102 } 94 }
103 95
104 /* write data */ 96 /* write data */
105 while (len--) { 97 while (len--) {
106 IICDS(bus) = *data++; 98 IICDS(bus) = *data++;
107 IICCON(bus) = 0xB3; 99 IICCON(bus) = 0xB3;
108 while ((IICCON(bus) & 0x10) == 0) 100 while ((IICCON(bus) & 0x10) == 0)
109 if (TIME_AFTER(current_tick, timeout)) 101 if (TIME_AFTER(USEC_TIMER, timeout))
110 {
111 mutex_unlock(&i2c_mtx[bus]);
112 return 4; 102 return 4;
113 }
114 } 103 }
115 104
116 /* STOP */ 105 /* STOP */
117 IICSTAT(bus) = 0xD0; 106 IICSTAT(bus) = 0xD0;
118 IICCON(bus) = 0xB3; 107 IICCON(bus) = 0xB3;
119 while ((IICSTAT(bus) & (1 << 5)) != 0) 108 while ((IICSTAT(bus) & (1 << 5)) != 0)
120 if (TIME_AFTER(current_tick, timeout)) 109 if (TIME_AFTER(USEC_TIMER, timeout))
121 {
122 mutex_unlock(&i2c_mtx[bus]);
123 return 5; 110 return 5;
124 } 111
125
126 i2c_off(bus); 112 i2c_off(bus);
127 mutex_unlock(&i2c_mtx[bus]);
128 return 0; 113 return 0;
129} 114}
130 115
131int i2c_read(int bus, unsigned char slave, int address, int len, unsigned char *data) 116int i2c_rd(int bus, unsigned char slave, int address, int len, unsigned char *data)
132{ 117{
133 mutex_lock(&i2c_mtx[bus]);
134 i2c_on(bus); 118 i2c_on(bus);
135 long timeout = current_tick + HZ / 50; 119 long timeout = USEC_TIMER + 20000;
136 120
137 if (address >= 0) { 121 if (address >= 0) {
138 /* START */ 122 /* START */
@@ -140,42 +124,30 @@ int i2c_read(int bus, unsigned char slave, int address, int len, unsigned char *
140 IICSTAT(bus) = 0xF0; 124 IICSTAT(bus) = 0xF0;
141 IICCON(bus) = 0xB3; 125 IICCON(bus) = 0xB3;
142 while ((IICCON(bus) & 0x10) == 0) 126 while ((IICCON(bus) & 0x10) == 0)
143 if (TIME_AFTER(current_tick, timeout)) 127 if (TIME_AFTER(USEC_TIMER, timeout))
144 {
145 mutex_unlock(&i2c_mtx[bus]);
146 return 1; 128 return 1;
147 }
148 129
149 /* write address */ 130 /* write address */
150 IICDS(bus) = address; 131 IICDS(bus) = address;
151 IICCON(bus) = 0xB3; 132 IICCON(bus) = 0xB3;
152 while ((IICCON(bus) & 0x10) == 0) 133 while ((IICCON(bus) & 0x10) == 0)
153 if (TIME_AFTER(current_tick, timeout)) 134 if (TIME_AFTER(USEC_TIMER, timeout))
154 {
155 mutex_unlock(&i2c_mtx[bus]);
156 return 2; 135 return 2;
157 }
158 } 136 }
159 137
160 /* (repeated) START */ 138 /* (repeated) START */
161 IICDS(bus) = slave | 1; 139 IICDS(bus) = slave | 1;
162 IICSTAT(bus) = 0xB0; 140 IICSTAT(bus) = 0xB0;
163 IICCON(bus) = 0xB3; 141 IICCON(bus) = 0xB3;
164 while ((IICCON(bus) & 0x10) == 0) 142 while ((IICCON(bus) & 0x10) == 0)
165 if (TIME_AFTER(current_tick, timeout)) 143 if (TIME_AFTER(USEC_TIMER, timeout))
166 {
167 mutex_unlock(&i2c_mtx[bus]);
168 return 3; 144 return 3;
169 } 145
170
171 while (len--) { 146 while (len--) {
172 IICCON(bus) = (len == 0) ? 0x33 : 0xB3; /* NAK or ACK */ 147 IICCON(bus) = (len == 0) ? 0x33 : 0xB3; /* NAK or ACK */
173 while ((IICCON(bus) & 0x10) == 0) 148 while ((IICCON(bus) & 0x10) == 0)
174 if (TIME_AFTER(current_tick, timeout)) 149 if (TIME_AFTER(USEC_TIMER, timeout))
175 {
176 mutex_unlock(&i2c_mtx[bus]);
177 return 4; 150 return 4;
178 }
179 *data++ = IICDS(bus); 151 *data++ = IICDS(bus);
180 } 152 }
181 153
@@ -183,14 +155,27 @@ int i2c_read(int bus, unsigned char slave, int address, int len, unsigned char *
183 IICSTAT(bus) = 0x90; 155 IICSTAT(bus) = 0x90;
184 IICCON(bus) = 0xB3; 156 IICCON(bus) = 0xB3;
185 while ((IICSTAT(bus) & (1 << 5)) != 0) 157 while ((IICSTAT(bus) & (1 << 5)) != 0)
186 if (TIME_AFTER(current_tick, timeout)) 158 if (TIME_AFTER(USEC_TIMER, timeout))
187 {
188 mutex_unlock(&i2c_mtx[bus]);
189 return 5; 159 return 5;
190 } 160
191
192 i2c_off(bus); 161 i2c_off(bus);
193 mutex_unlock(&i2c_mtx[bus]);
194 return 0; 162 return 0;
195} 163}
196 164
165int i2c_write(int bus, unsigned char slave, int address, int len, const unsigned char *data)
166{
167 int ret;
168 mutex_lock(&i2c_mtx[bus]);
169 ret = i2c_wr(bus, slave, address, len, data);
170 mutex_unlock(&i2c_mtx[bus]);
171 return ret;
172}
173
174int i2c_read(int bus, unsigned char slave, int address, int len, unsigned char *data)
175{
176 int ret;
177 mutex_lock(&i2c_mtx[bus]);
178 ret = i2c_rd(bus, slave, address, len, data);
179 mutex_unlock(&i2c_mtx[bus]);
180 return ret;
181}
diff --git a/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c
index 946beb1519..2a9236046c 100644
--- a/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c
+++ b/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c
@@ -142,3 +142,27 @@ void pmu_write_rtc(unsigned char* buffer)
142{ 142{
143 pmu_write_multiple(0x59, 7, buffer); 143 pmu_write_multiple(0x59, 7, buffer);
144} 144}
145
146#ifdef BOOTLOADER
147int pmu_rd_multiple(int address, int count, unsigned char* buffer)
148{
149 return i2c_rd(0, 0xe6, address, count, buffer);
150}
151
152int pmu_wr_multiple(int address, int count, unsigned char* buffer)
153{
154 return i2c_wr(0, 0xe6, address, count, buffer);
155}
156
157unsigned char pmu_rd(int address)
158{
159 unsigned char val;
160 pmu_rd_multiple(address, 1, &val);
161 return val;
162}
163
164int pmu_wr(int address, unsigned char val)
165{
166 return pmu_wr_multiple(address, 1, &val);
167}
168#endif /* BOOTLOADER */
diff --git a/firmware/target/arm/s5l8702/ipod6g/pmu-target.h b/firmware/target/arm/s5l8702/ipod6g/pmu-target.h
index 94fd17010b..3a90ad8789 100644
--- a/firmware/target/arm/s5l8702/ipod6g/pmu-target.h
+++ b/firmware/target/arm/s5l8702/ipod6g/pmu-target.h
@@ -25,7 +25,7 @@
25#include <stdbool.h> 25#include <stdbool.h>
26#include "config.h" 26#include "config.h"
27 27
28#include <pcf5063x.h> 28#include "pcf5063x.h"
29 29
30/* undocummented PMU registers */ 30/* undocummented PMU registers */
31#define PCF50635_REG_INT6 0x85 31#define PCF50635_REG_INT6 0x85
@@ -77,4 +77,11 @@ void pmu_read_rtc(unsigned char* buffer);
77void pmu_write_rtc(unsigned char* buffer); 77void pmu_write_rtc(unsigned char* buffer);
78void pmu_hdd_power(bool on); 78void pmu_hdd_power(bool on);
79 79
80#ifdef BOOTLOADER
81unsigned char pmu_rd(int address);
82int pmu_wr(int address, unsigned char val);
83int pmu_rd_multiple(int address, int count, unsigned char* buffer);
84int pmu_wr_multiple(int address, int count, unsigned char* buffer);
80#endif 85#endif
86
87#endif /* __PMU_TARGET_H__ */