summaryrefslogtreecommitdiff
path: root/firmware/target/arm/s5l8702
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/s5l8702')
-rw-r--r--firmware/target/arm/s5l8702/debug-s5l8702.c12
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/adc-ipod6g.c84
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/adc-target.h20
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c108
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/pmu-target.h15
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/powermgmt-ipod6g.c11
6 files changed, 195 insertions, 55 deletions
diff --git a/firmware/target/arm/s5l8702/debug-s5l8702.c b/firmware/target/arm/s5l8702/debug-s5l8702.c
index a61a728d43..1bf59e94fe 100644
--- a/firmware/target/arm/s5l8702/debug-s5l8702.c
+++ b/firmware/target/arm/s5l8702/debug-s5l8702.c
@@ -19,6 +19,7 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#include <stdio.h>
22#include <stdbool.h> 23#include <stdbool.h>
23#include "system.h" 24#include "system.h"
24#include "config.h" 25#include "config.h"
@@ -28,6 +29,7 @@
28#include "font.h" 29#include "font.h"
29#include "storage.h" 30#include "storage.h"
30#include "power.h" 31#include "power.h"
32#include "adc.h"
31#include "pmu-target.h" 33#include "pmu-target.h"
32#include "pcm-target.h" 34#include "pcm-target.h"
33#ifdef HAVE_SERIAL 35#ifdef HAVE_SERIAL
@@ -134,11 +136,19 @@ bool dbg_hw_info(void)
134 pmu_accessory_present() ? "true" : "false"); 136 pmu_accessory_present() ? "true" : "false");
135#endif 137#endif
136 line++; 138 line++;
139 _DEBUG_PRINTF("ADC:");
140 _DEBUG_PRINTF("%s: %d mV", adc_name(ADC_BATTERY),
141 adc_read_battery_voltage());
142 _DEBUG_PRINTF("%s: %d Ohms", adc_name(ADC_ACCESSORY),
143 adc_read_accessory_resistor());
144 _DEBUG_PRINTF("USB D+: %d mV", adc_read_usbdata_voltage(true));
145 _DEBUG_PRINTF("USB D-: %d mV", adc_read_usbdata_voltage(false));
146 line++;
137 extern unsigned long i2c_rd_err, i2c_wr_err; 147 extern unsigned long i2c_rd_err, i2c_wr_err;
138 _DEBUG_PRINTF("i2c rd/wr errors: %lu/%lu", i2c_rd_err, i2c_wr_err); 148 _DEBUG_PRINTF("i2c rd/wr errors: %lu/%lu", i2c_rd_err, i2c_wr_err);
139 } 149 }
140#ifdef UC870X_DEBUG 150#ifdef UC870X_DEBUG
141 else if(state==2) 151 else if(state==(max_states-1))
142 { 152 {
143 extern struct uartc_port ser_port; 153 extern struct uartc_port ser_port;
144 bool opened = !!ser_port.uartc->port_l[ser_port.id]; 154 bool opened = !!ser_port.uartc->port_l[ser_port.id];
diff --git a/firmware/target/arm/s5l8702/ipod6g/adc-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/adc-ipod6g.c
index 201af5ee00..fbe5ef805e 100644
--- a/firmware/target/arm/s5l8702/ipod6g/adc-ipod6g.c
+++ b/firmware/target/arm/s5l8702/ipod6g/adc-ipod6g.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 23
24#include "inttypes.h" 24#include "inttypes.h"
@@ -28,12 +28,90 @@
28#include "pmu-target.h" 28#include "pmu-target.h"
29#include "kernel.h" 29#include "kernel.h"
30 30
31
32/* MS_TO_TICKS converts a milisecond time period into the
33 * corresponding amount of ticks. If the time period cannot
34 * be accurately measured in ticks it will round up.
35 */
36#define MS_PER_HZ (1000/HZ)
37#define MS_TO_TICKS(x) (((x)+MS_PER_HZ-1)/MS_PER_HZ)
38
39static const struct pmu_adc_channel adc_channels[] =
40{
41 [ADC_BATTERY] =
42 {
43 .name = "Battery",
44 .adcc1 = PCF5063X_ADCC1_MUX_BATSNS_SUBTR
45 | PCF5063X_ADCC1_AVERAGE_4
46 | PCF5063X_ADCC1_RES_10BIT,
47 },
48
49 [ADC_USBDATA] =
50 {
51 .name = "USB D+/D-",
52 .adcc1 = PCF5063X_ADCC1_MUX_ADCIN2_RES
53 | PCF5063X_ADCC1_AVERAGE_16
54 | PCF5063X_ADCC1_RES_10BIT,
55 .adcc3 = PCF5063X_ADCC3_RES_DIV_THREE,
56 },
57
58 [ADC_ACCESSORY] =
59 {
60 .name = "Accessory",
61 .adcc1 = PCF5063X_ADCC1_MUX_ADCIN1
62 | PCF5063X_ADCC1_AVERAGE_16
63 | PCF5063X_ADCC1_RES_10BIT,
64 .adcc2 = PCF5063X_ADCC2_RATIO_ADCIN1
65 | PCF5063X_ADCC2_RATIOSETTL_10US,
66 .adcc3 = PCF5063X_ADCC3_ACCSW_EN,
67 .bias_dly = MS_TO_TICKS(50),
68 },
69};
70
71const char *adc_name(int channel)
72{
73 return adc_channels[channel].name;
74}
75
76unsigned short adc_read_millivolts(int channel)
77{
78 const struct pmu_adc_channel *ch = &adc_channels[channel];
79 return pmu_adc_raw2mv(ch, pmu_read_adc(ch));
80}
81
82/* Returns battery voltage [millivolts] */
83unsigned int adc_read_battery_voltage(void)
84{
85 return adc_read_millivolts(ADC_BATTERY);
86}
87
88/* Returns USB D+/D- voltage from ADC [millivolts] */
89unsigned int adc_read_usbdata_voltage(bool dp)
90{
91 unsigned int mvolts;
92 int gpio = dp ? 0xb0300 : 0xb0200; /* select D+/D- */
93 GPIOCMD = gpio | 0xf; /* route to ADCIN2 */
94 mvolts = adc_read_millivolts(ADC_USBDATA);
95 GPIOCMD = gpio | 0xe; /* unroute */
96 return mvolts;
97}
98
99/* Returns resistor connected to "Accessory identify" pin [ohms] */
100#define IAP_DEVICE_RESISTOR 100000 /* ohms */
101int adc_read_accessory_resistor(void)
102{
103 int raw = pmu_read_adc(&adc_channels[ADC_ACCESSORY]);
104 return (1023-raw) ? raw * IAP_DEVICE_RESISTOR / (1023-raw)
105 : -1 /* open circuit */;
106}
107
108
109/* API functions */
31unsigned short adc_read(int channel) 110unsigned short adc_read(int channel)
32{ 111{
33 return pmu_read_adc(channel); 112 return pmu_read_adc(&adc_channels[channel]);
34} 113}
35 114
36void adc_init(void) 115void adc_init(void)
37{ 116{
38} 117}
39
diff --git a/firmware/target/arm/s5l8702/ipod6g/adc-target.h b/firmware/target/arm/s5l8702/ipod6g/adc-target.h
index d4dce3d31f..bedc0a8447 100644
--- a/firmware/target/arm/s5l8702/ipod6g/adc-target.h
+++ b/firmware/target/arm/s5l8702/ipod6g/adc-target.h
@@ -21,13 +21,23 @@
21#ifndef _ADC_TARGET_H_ 21#ifndef _ADC_TARGET_H_
22#define _ADC_TARGET_H_ 22#define _ADC_TARGET_H_
23 23
24#define NUM_ADC_CHANNELS 4 24#include <stdbool.h>
25#include "config.h"
25 26
26#define ADC_UNKNOWN_0 0 27enum
27#define ADC_UNKNOWN_1 1 28{
28#define ADC_BATTERY 2 29 ADC_BATTERY = 0,
29#define ADC_UNKNOWN_3 3 30 ADC_USBDATA,
31 ADC_ACCESSORY,
32 NUM_ADC_CHANNELS
33};
30 34
31#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */ 35#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */
32 36
37unsigned short adc_read_millivolts(int channel);
38unsigned int adc_read_battery_voltage(void);
39unsigned int adc_read_usbdata_voltage(bool dp);
40int adc_read_accessory_resistor(void);
41const char *adc_name(int channel);
42
33#endif 43#endif
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) */
diff --git a/firmware/target/arm/s5l8702/ipod6g/pmu-target.h b/firmware/target/arm/s5l8702/ipod6g/pmu-target.h
index 5552e2196a..d33db42717 100644
--- a/firmware/target/arm/s5l8702/ipod6g/pmu-target.h
+++ b/firmware/target/arm/s5l8702/ipod6g/pmu-target.h
@@ -22,6 +22,7 @@
22#ifndef __PMU_TARGET_H__ 22#ifndef __PMU_TARGET_H__
23#define __PMU_TARGET_H__ 23#define __PMU_TARGET_H__
24 24
25#include <stdint.h>
25#include <stdbool.h> 26#include <stdbool.h>
26#include "config.h" 27#include "config.h"
27 28
@@ -72,14 +73,22 @@ enum pcf50635_reg_gpiostat {
72 * GPIO3: output, unknown 73 * GPIO3: output, unknown
73 */ 74 */
74 75
76struct pmu_adc_channel
77{
78 const char *name;
79 uint8_t adcc1;
80 uint8_t adcc2;
81 uint8_t adcc3;
82 uint8_t bias_dly; /* RB ticks */
83};
75 84
76unsigned char pmu_read(int address); 85unsigned char pmu_read(int address);
77int pmu_write(int address, unsigned char val); 86int pmu_write(int address, unsigned char val);
78int pmu_read_multiple(int address, int count, unsigned char* buffer); 87int pmu_read_multiple(int address, int count, unsigned char* buffer);
79int pmu_write_multiple(int address, int count, unsigned char* buffer); 88int pmu_write_multiple(int address, int count, unsigned char* buffer);
80int pmu_read_adc(unsigned int adc); 89unsigned short pmu_read_adc(const struct pmu_adc_channel *ch);
81int pmu_read_battery_voltage(void); 90unsigned short pmu_adc_raw2mv(
82int pmu_read_battery_current(void); 91 const struct pmu_adc_channel *ch, unsigned short raw);
83void pmu_init(void); 92void pmu_init(void);
84void pmu_ldo_on_in_standby(unsigned int ldo, int onoff); 93void pmu_ldo_on_in_standby(unsigned int ldo, int onoff);
85void pmu_ldo_set_voltage(unsigned int ldo, unsigned char voltage); 94void pmu_ldo_set_voltage(unsigned int ldo, unsigned char voltage);
diff --git a/firmware/target/arm/s5l8702/ipod6g/powermgmt-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/powermgmt-ipod6g.c
index 4553b03685..c5f9c9b9f5 100644
--- a/firmware/target/arm/s5l8702/ipod6g/powermgmt-ipod6g.c
+++ b/firmware/target/arm/s5l8702/ipod6g/powermgmt-ipod6g.c
@@ -24,6 +24,7 @@
24#include "pmu-target.h" 24#include "pmu-target.h"
25#include "power.h" 25#include "power.h"
26#include "audiohw.h" 26#include "audiohw.h"
27#include "adc-target.h"
27 28
28const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = 29const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
29{ 30{
@@ -49,20 +50,12 @@ const unsigned short percent_to_volt_charge[11] =
49}; 50};
50#endif /* CONFIG_CHARGING */ 51#endif /* CONFIG_CHARGING */
51 52
52/* ADC should read 0x3ff=6.00V */
53#define BATTERY_SCALE_FACTOR 6000
54/* full-scale ADC readout (2^10) in millivolt */
55
56
57/* Returns battery voltage from ADC [millivolts] */ 53/* Returns battery voltage from ADC [millivolts] */
58int _battery_voltage(void) 54int _battery_voltage(void)
59{ 55{
60 int compensation = (10 * (pmu_read_battery_current() - 7)) / 12; 56 return adc_read_battery_voltage();
61 if (charging_state()) return pmu_read_battery_voltage() - compensation;
62 return pmu_read_battery_voltage() + compensation;
63} 57}
64 58
65
66#ifdef HAVE_ACCESSORY_SUPPLY 59#ifdef HAVE_ACCESSORY_SUPPLY
67void accessory_supply_set(bool enable) 60void accessory_supply_set(bool enable)
68{ 61{