summaryrefslogtreecommitdiff
path: root/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c')
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c108
1 files changed, 74 insertions, 34 deletions
diff --git a/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c
index c439a30fc1..d282a48d5b 100644
--- a/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c
+++ b/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c
@@ -24,12 +24,11 @@
24#include "thread.h" 24#include "thread.h"
25 25
26#include "pmu-target.h" 26#include "pmu-target.h"
27#include "adc-target.h"
27#include "i2c-s5l8702.h" 28#include "i2c-s5l8702.h"
28#include "gpio-s5l8702.h" 29#include "gpio-s5l8702.h"
29 30
30 31
31static struct mutex pmu_adc_mutex;
32
33int pmu_read_multiple(int address, int count, unsigned char* buffer) 32int pmu_read_multiple(int address, int count, unsigned char* buffer)
34{ 33{
35 return i2c_read(0, 0xe6, address, count, buffer); 34 return i2c_read(0, 0xe6, address, count, buffer);
@@ -54,35 +53,6 @@ int pmu_write(int address, unsigned char val)
54 return pmu_write_multiple(address, 1, &val); 53 return pmu_write_multiple(address, 1, &val);
55} 54}
56 55
57int pmu_read_adc(unsigned int adc)
58{
59 int data = 0;
60 mutex_lock(&pmu_adc_mutex);
61 pmu_write(0x54, 5 | (adc << 4));
62 while ((data & 0x80) == 0)
63 {
64 yield();
65 data = pmu_read(0x57);
66 }
67 int value = (pmu_read(0x55) << 2) | (data & 3);
68 mutex_unlock(&pmu_adc_mutex);
69 return value;
70}
71
72/* millivolts */
73int pmu_read_battery_voltage(void)
74{
75 return (pmu_read_adc(1) * 2000 / 1023) + 2250;
76}
77
78/* milliamps */
79int pmu_read_battery_current(void)
80{
81//TODO: Figure out how to read the battery current
82// return pmu_read_adc(2);
83 return 0;
84}
85
86void pmu_ldo_on_in_standby(unsigned int ldo, int onoff) 56void pmu_ldo_on_in_standby(unsigned int ldo, int onoff)
87{ 57{
88 if (ldo < 4) 58 if (ldo < 4)
@@ -143,17 +113,86 @@ void pmu_write_rtc(unsigned char* buffer)
143} 113}
144 114
145/* 115/*
116 * ADC
117 */
118#define ADC_FULL_SCALE 2000
119#define ADC_FULL_SCALE_VISA 2400
120#define ADC_SUBTR_OFFSET 2250
121
122static struct mutex pmu_adc_mutex;
123
124/* converts raw 8/10-bit value to millivolts */
125unsigned short pmu_adc_raw2mv(
126 const struct pmu_adc_channel *ch, unsigned short raw)
127{
128 int full_scale = ADC_FULL_SCALE;
129 int offset = 0;
130
131 switch (ch->adcc1 & PCF5063X_ADCC1_ADCMUX_MASK)
132 {
133 case PCF5063X_ADCC1_MUX_BATSNS_RES:
134 case PCF5063X_ADCC1_MUX_ADCIN2_RES:
135 full_scale *= ((ch->adcc1 & PCF5063X_ADCC3_RES_DIV_MASK) ==
136 PCF5063X_ADCC3_RES_DIV_TWO) ? 2 : 3;
137 break;
138 case PCF5063X_ADCC1_MUX_BATSNS_SUBTR:
139 case PCF5063X_ADCC1_MUX_ADCIN2_SUBTR:
140 offset = ADC_SUBTR_OFFSET;
141 break;
142 case PCF5063X_ADCC1_MUX_BATTEMP:
143 if (ch->adcc2 & PCF5063X_ADCC2_RATIO_BATTEMP)
144 full_scale = ADC_FULL_SCALE_VISA;
145 break;
146 case PCF5063X_ADCC1_MUX_ADCIN1:
147 if (ch->adcc2 & PCF5063X_ADCC2_RATIO_ADCIN1)
148 full_scale = ADC_FULL_SCALE_VISA;
149 break;
150 }
151
152 int nrb = ((ch->adcc1 & PCF5063X_ADCC1_RES_MASK) ==
153 PCF5063X_ADCC1_RES_8BIT) ? 8 : 10;
154 return (raw * full_scale / ((1<<nrb)-1)) + offset;
155}
156
157/* returns raw value, 8 or 10-bit resolution */
158unsigned short pmu_read_adc(const struct pmu_adc_channel *ch)
159{
160 mutex_lock(&pmu_adc_mutex);
161
162 pmu_write(PCF5063X_REG_ADCC3, ch->adcc3);
163 if (ch->bias_dly)
164 sleep(ch->bias_dly);
165 uint8_t buf[2] = { ch->adcc2, ch->adcc1 | PCF5063X_ADCC1_ADCSTART };
166 pmu_write_multiple(PCF5063X_REG_ADCC2, 2, buf);
167
168 int adcs3 = 0;
169 while (!(adcs3 & PCF5063X_ADCS3_ADCRDY))
170 {
171 yield();
172 adcs3 = pmu_read(PCF5063X_REG_ADCS3);
173 }
174
175 int raw = pmu_read(PCF5063X_REG_ADCS1);
176 if ((ch->adcc1 & PCF5063X_ADCC1_RES_MASK) == PCF5063X_ADCC1_RES_10BIT)
177 raw = (raw << 2) | (adcs3 & PCF5063X_ADCS3_ADCDAT1L_MASK);
178
179 mutex_unlock(&pmu_adc_mutex);
180 return raw;
181}
182
183/*
146 * eINT 184 * eINT
147 */ 185 */
148#define Q_EINT 0 186#define Q_EINT 0
149 187
150static char pmu_thread_stack[DEFAULT_STACK_SIZE/4]; 188static char pmu_thread_stack[DEFAULT_STACK_SIZE/2];
151static struct event_queue pmu_queue; 189static struct event_queue pmu_queue;
152static unsigned char ints_msk[6]; 190static unsigned char ints_msk[6];
153 191
154static void pmu_eint_isr(struct eint_handler*); 192static void pmu_eint_isr(struct eint_handler*);
155 193
156static struct eint_handler pmu_eint = { 194static struct eint_handler pmu_eint =
195{
157 .gpio_n = GPIO_EINT_PMU, 196 .gpio_n = GPIO_EINT_PMU,
158 .type = EIC_INTTYPE_LEVEL, 197 .type = EIC_INTTYPE_LEVEL,
159 .level = EIC_INTLEVEL_LOW, 198 .level = EIC_INTLEVEL_LOW,
@@ -355,10 +394,11 @@ void pmu_preinit(void)
355 PCF5063X_REG_STBYCTL1, 0x0, 394 PCF5063X_REG_STBYCTL1, 0x0,
356 PCF5063X_REG_STBYCTL2, 0x8c, 395 PCF5063X_REG_STBYCTL2, 0x8c,
357 396
358 /* GPIO1,2 = input, GPIO3 = output */ 397 /* GPIO1,2 = input, GPIO3 = output High (NoPower default) */
359 PCF5063X_REG_GPIOCTL, 0x3, 398 PCF5063X_REG_GPIOCTL, 0x3,
360 PCF5063X_REG_GPIO1CFG, 0x0, 399 PCF5063X_REG_GPIO1CFG, 0x0,
361 PCF5063X_REG_GPIO2CFG, 0x0, 400 PCF5063X_REG_GPIO2CFG, 0x0,
401 PCF5063X_REG_GPIO3CFG, 0x7,
362 402
363 /* DOWN2 converter (SDRAM): 1800 mV, enabled, 403 /* DOWN2 converter (SDRAM): 1800 mV, enabled,
364 startup current limit = 15mA*0x10 (TBC) */ 404 startup current limit = 15mA*0x10 (TBC) */