dont-smoke.patch
[u-boot-openmoko/mini2440.git] / drivers / misc / pcf50633.c
blobca0258752bb1da8c6b9a350d86bc07a0fb72963f
1 #include <common.h>
3 #ifdef CONFIG_DRIVER_PCF50633
5 #include <i2c.h>
6 #include <pcf50633.h>
7 #include <asm/atomic.h>
8 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
11 #define ADC_NOMINAL_RES_1A 6
12 #define ADC_NOMINAL_RES_NC_R_USB 43
14 #define PCF50633_I2C_ADDR 0x73
16 void __pcf50633_reg_write(u_int8_t reg, u_int8_t val)
18 i2c_write(PCF50633_I2C_ADDR, reg, 1, &val, 1);
21 u_int8_t __pcf50633_reg_read(u_int8_t reg)
23 u_int8_t tmp;
24 i2c_read(PCF50633_I2C_ADDR, reg, 1, &tmp, 1);
25 return tmp;
28 void pcf50633_reg_write(u_int8_t reg, u_int8_t val)
30 unsigned long flags;
32 local_irq_save(flags);
33 __pcf50633_reg_write(reg, val);
34 local_irq_restore(flags);
37 u_int8_t pcf50633_reg_read(u_int8_t reg)
39 unsigned long flags;
40 u_int8_t tmp;
42 local_irq_save(flags);
43 tmp = __pcf50633_reg_read(reg);
44 local_irq_restore(flags);
46 return tmp;
49 void pcf50633_reg_set_bit_mask(u_int8_t reg, u_int8_t mask, u_int8_t val)
51 unsigned long flags;
52 u_int8_t tmp;
54 local_irq_save(flags);
55 tmp = __pcf50633_reg_read(reg);
56 __pcf50633_reg_write(reg, (val & mask) | (tmp & ~mask));
57 local_irq_restore(flags);
60 void pcf50633_reg_clear_bits(u_int8_t reg, u_int8_t bits)
62 unsigned long flags;
63 u_int8_t tmp;
65 local_irq_save(flags);
66 tmp = pcf50633_reg_read(reg);
67 pcf50633_reg_write(reg, (tmp & ~bits));
68 local_irq_restore(flags);
71 static const u_int8_t regs_invalid[] = {
72 PCF50633_REG_VERSION,
73 PCF50633_REG_VARIANT,
74 PCF50633_REG_OOCSHDWN,
75 PCF50633_REG_INT1,
76 PCF50633_REG_INT2,
77 PCF50633_REG_INT3,
78 PCF50633_REG_INT4,
79 PCF50633_REG_INT5,
80 PCF50633_REG_OOCSTAT,
81 0x2c,
82 PCF50633_REG_DCDCSTAT,
83 PCF50633_REG_LDOSTAT,
84 PCF50633_REG_MBCS1,
85 PCF50633_REG_MBCS2,
86 PCF50633_REG_MBCS3,
87 PCF50633_REG_ALMDATA,
88 0x51,
89 /* 0x55 ... 0x6e: don't write */
90 /* 0x6f ... 0x83: reserved */
92 #define PCF50633_LAST_REG 0x55
94 static int reg_is_invalid(u_int8_t reg)
96 int i;
98 /* all registers above 0x55 (ADCS1) except 0x84 */
99 if (reg == PCF50633_REG_DCDCPFM)
100 return 0;
101 if (reg >= 0x55)
102 return 1;
104 for (i = 0; i < ARRAY_SIZE(regs_invalid); i++) {
105 if (regs_invalid[i] > reg)
106 return 0;
107 if (regs_invalid[i] == reg)
108 return 1;
111 return 0;
114 /* figure out our charger situation */
115 int pcf50633_read_charger_type(void)
117 u_int16_t ret;
119 /* kill ratiometric, but enable ACCSW biasing */
120 pcf50633_reg_write(PCF50633_REG_ADCC2, 0x00);
121 pcf50633_reg_write(PCF50633_REG_ADCC3, 0x01);
123 /* start ADC conversion of selected channel */
124 pcf50633_reg_write(PCF50633_REG_ADCC1, PCF50633_ADCC1_MUX_ADCIN1 |
125 PCF50633_ADCC1_AVERAGE_16 |
126 PCF50633_ADCC1_ADCSTART |
127 PCF50633_ADCC1_RES_10BIT);
129 /* spin until completed */
130 while (!(pcf50633_reg_read(PCF50633_REG_ADCS3) & 0x80))
133 /* grab the result */
134 ret = (pcf50633_reg_read(PCF50633_REG_ADCS1) << 2) |
135 (pcf50633_reg_read(PCF50633_REG_ADCS3) &
136 PCF50633_ADCS3_ADCDAT1L_MASK);
138 /* well it is nearest to the 1A resistor */
139 if (ret < ((ADC_NOMINAL_RES_1A + ADC_NOMINAL_RES_NC_R_USB) / 2))
140 return 1000;
142 /* ok all we know is there is no resistor, it can be USB pwr or none */
143 if ((pcf50633_reg_read(PCF50633_REG_MBCS1) & 0x3) == 0x3)
144 return 100; /* USB power then */
146 return 0; /* nope, no power, just battery */
151 /* initialize PCF50633 register set */
152 void pcf50633_init(void)
154 unsigned long flags;
155 u_int8_t i;
156 int limit;
158 local_irq_save(flags);
159 for (i = 0; i < PCF50633_LAST_REG; i++) {
160 if (reg_is_invalid(i))
161 continue;
162 __pcf50633_reg_write(i, pcf50633_initial_regs[i]);
164 local_irq_restore(flags);
166 printf("Power: ");
167 limit = pcf50633_read_charger_type();
169 * If we're on real USB, don't change the setting to avoid racing with
170 * USB signaling.
172 if (limit != 100) {
173 printf("%dmA\n", limit);
174 pcf50633_usb_maxcurrent(limit);
178 void pcf50633_usb_maxcurrent(unsigned int ma)
180 u_int8_t val;
182 if (ma < 100)
183 val = PCF50633_MBCC7_USB_SUSPEND;
184 else if (ma < 500)
185 val = PCF50633_MBCC7_USB_100mA;
186 else if (ma < 1000)
187 val = PCF50633_MBCC7_USB_500mA;
188 else
189 val = PCF50633_MBCC7_USB_1000mA;
191 return pcf50633_reg_set_bit_mask(PCF50633_REG_MBCC7, 0x03, val);
195 static const char *charger_states[] = {
196 [0] = "play_only",
197 [1] = "usb_precharge",
198 [2] = "usb_precharge_wait",
199 [3] = "usb_fast_charge",
200 [4] = "usb_fast_charge_wait",
201 [5] = "usb_suspend",
202 [6] = "adapter_precharge",
203 [7] = "adapter_precharge_wait",
204 [8] = "adapter_fast_charge",
205 [9] = "adapter_fast_charge_wait",
206 [10] = "battery_full",
207 [11] = "halt",
210 const char *pcf50633_charger_state(void)
212 u_int8_t val = pcf50633_reg_read(PCF50633_REG_MBCS2);
214 val &= 0x0f;
215 if (val > 11)
216 return "error";
218 return charger_states[val];
221 #if defined(CONFIG_RTC_PCF50633) && defined(CONFIG_CMD_DATE)
223 #include <rtc.h>
225 static unsigned bcd2bin (uchar n)
227 return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
230 static unsigned char bin2bcd (unsigned int n)
232 return (((n / 10) << 4) | (n % 10));
236 void rtc_get(struct rtc_time *tmp)
238 tmp->tm_sec = bcd2bin(pcf50633_reg_read(PCF50633_REG_RTCSC));
239 tmp->tm_min = bcd2bin(pcf50633_reg_read(PCF50633_REG_RTCMN));
240 tmp->tm_hour = bcd2bin(pcf50633_reg_read(PCF50633_REG_RTCHR));
241 tmp->tm_wday = bcd2bin(pcf50633_reg_read(PCF50633_REG_RTCWD));
242 tmp->tm_mday = bcd2bin(pcf50633_reg_read(PCF50633_REG_RTCDT));
243 tmp->tm_mon = bcd2bin(pcf50633_reg_read(PCF50633_REG_RTCMT));
244 tmp->tm_year = bcd2bin(pcf50633_reg_read(PCF50633_REG_RTCYR));
245 if (tmp->tm_year < 70)
246 tmp->tm_year += 2000;
247 else
248 tmp->tm_year += 1900;
249 tmp->tm_yday = 0;
250 tmp->tm_isdst = 0;
253 void rtc_set(struct rtc_time *tmp)
255 pcf50633_reg_write(PCF50633_REG_RTCSC, bin2bcd(tmp->tm_sec));
256 pcf50633_reg_write(PCF50633_REG_RTCMN, bin2bcd(tmp->tm_min));
257 pcf50633_reg_write(PCF50633_REG_RTCHR, bin2bcd(tmp->tm_hour));
258 pcf50633_reg_write(PCF50633_REG_RTCWD, bin2bcd(tmp->tm_wday));
259 pcf50633_reg_write(PCF50633_REG_RTCDT, bin2bcd(tmp->tm_mday));
260 pcf50633_reg_write(PCF50633_REG_RTCMN, bin2bcd(tmp->tm_mon));
261 pcf50633_reg_write(PCF50633_REG_RTCYR, bin2bcd(tmp->tm_year % 100));
264 void rtc_reset(void)
266 /* FIXME */
268 #endif /* CONFIG_RTC_PCF50633 && CONFIG_CMD_DATE */
271 #endif /* CONFIG DRIVER_PCF50633 */