First version
[3rdparty/ote_partner/tlk.git] / dev / pmic / twl4030 / twl4030.c
1 /*
2  * Copyright (c) 2008 Travis Geiselbrecht
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 #include <debug.h>
24 #include <sys/types.h>
25 #include <dev/i2c.h>
26 #include <dev/twl4030.h>
27 #include "twl4030_hw.h"
28
29 // XXX move to target specific setup
30 #define TWL_I2C_BUS 0
31
32 void twl4030_init(void)
33 {
34 }
35
36 static int twl4030_usb_write(uint8_t address, uint8_t data)
37 {
38         return i2c_write_reg(TWL_I2C_BUS, TWL_USB_ADDR, address, data); 
39 }
40
41 static int twl4030_usb_read(uint8_t address)
42 {
43         uint8_t data;
44
45         int err = i2c_read_reg(TWL_I2C_BUS, TWL_USB_ADDR, address, &data);      
46         if (err < 0)
47                 return err;
48
49         return data;
50 }
51
52 static int twl4030_usb_set_bits(uint8_t reg, uint8_t bits)
53 {
54     return twl4030_usb_write(reg + 1, bits);
55 }
56
57 static int twl4030_usb_clear_bits(uint8_t reg, uint8_t bits)
58 {
59     return twl4030_usb_write(reg + 2, bits);
60 }
61
62 static void twl4030_i2c_access(bool on)
63 {
64         int val;
65
66         if ((val = twl4030_usb_read(PHY_CLK_CTRL)) >= 0) {
67                 if (on) {
68                         /* enable DPLL to access PHY registers over I2C */
69                         val |= REQ_PHY_DPLL_CLK;
70                         twl4030_usb_write(PHY_CLK_CTRL, (uint8_t)val);
71
72                         while (!(twl4030_usb_read(PHY_CLK_CTRL_STS) & PHY_DPLL_CLK)) {
73                                 spin(10);
74                         }
75                         if (!(twl4030_usb_read(PHY_CLK_CTRL_STS) & PHY_DPLL_CLK))
76                                 printf("Timeout setting T2 HSUSB " "PHY DPLL clock\n");
77                 } else {
78                         /* let ULPI control the DPLL clock */
79                         val &= ~REQ_PHY_DPLL_CLK;
80                         twl4030_usb_write(PHY_CLK_CTRL, (uint8_t)val);
81                 }
82         }
83         return;
84 }
85
86 int twl4030_usb_reset(void)
87 {
88         TRACE_ENTRY;
89 #if 0
90     twl4030_usb_clear_bits(OTG_CTRL, DMPULLDOWN | DPPULLDOWN);
91     twl4030_usb_clear_bits(USB_INT_EN_RISE, ~0);
92     twl4030_usb_clear_bits(USB_INT_EN_FALL, ~0);
93     twl4030_usb_clear_bits(MCPC_IO_CTRL, ~TXDTYP);
94     twl4030_usb_set_bits(MCPC_IO_CTRL, TXDTYP);
95     twl4030_usb_clear_bits(OTHER_FUNC_CTRL, (BDIS_ACON_EN | FIVEWIRE_MODE));
96     twl4030_usb_clear_bits(OTHER_IFC_CTRL, ~0);
97     twl4030_usb_clear_bits(OTHER_INT_EN_RISE, ~0);
98     twl4030_usb_clear_bits(OTHER_INT_EN_FALL, ~0);
99     twl4030_usb_clear_bits(OTHER_IFC_CTRL2, ~0);
100     twl4030_usb_clear_bits(REG_CTRL_EN, ULPI_I2C_CONFLICT_INTEN);
101     twl4030_usb_clear_bits(OTHER_FUNC_CTRL2, VBAT_TIMER_EN);
102 #endif
103
104     /* Enable writing to power configuration registers */
105     i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, PROTECT_KEY, 0xC0);
106     i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, PROTECT_KEY, 0x0C);
107
108     /* put VUSB3V1 LDO in active state */
109     i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB_DEDICATED2, 0);
110
111     /* input to VUSB3V1 LDO is from VBAT, not VBUS */
112     i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB_DEDICATED1, 0x14);
113
114     /* turn on 3.1V regulator */
115     i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB3V1_DEV_GRP, 0x20);
116     i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB3V1_TYPE, 0);
117
118     /* turn on 1.5V regulator */
119     i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V5_DEV_GRP, 0x20);
120     i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V5_TYPE, 0);
121
122     /* turn on 1.8V regulator */
123     i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V8_DEV_GRP, 0x20);
124     i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V8_TYPE, 0);
125
126     /* disable access to power configuration registers */
127     i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, PROTECT_KEY, 0);
128
129         /* turn on the phy */
130     uint8_t pwr = twl4030_usb_read(PHY_PWR_CTRL);
131         pwr &= ~PHYPWD;
132         twl4030_usb_write(PHY_PWR_CTRL, pwr);
133         twl4030_usb_write(PHY_CLK_CTRL,
134                 twl4030_usb_read(PHY_CLK_CTRL) |
135                 (CLOCKGATING_EN | CLK32K_EN));
136
137         /* set DPLL i2c access mode */
138         twl4030_i2c_access(true);
139         /* set ulpi mode */
140         twl4030_usb_clear_bits(IFC_CTRL, CARKITMODE);
141         twl4030_usb_set_bits(POWER_CTRL, OTG_ENAB);
142         twl4030_usb_write(FUNC_CTRL, XCVRSELECT_HS); // set high speed mode
143 //      twl4030_usb_write(FUNC_CTRL, XCVRSELECT_FS); // set full speed mode
144         twl4030_i2c_access(false);
145
146         return 0;
147 }
148
149 int twl4030_init_hs(void)
150 {
151         return 0;
152 }
153
154 int twl4030_set_usb_pullup(bool pullup)
155 {
156         TRACE_ENTRY;
157
158         if (pullup) {
159                 twl4030_usb_clear_bits(OTG_CTRL, DPPULLDOWN);
160                 twl4030_usb_set_bits(FUNC_CTRL, TERMSELECT);
161         } else {
162                 twl4030_usb_clear_bits(FUNC_CTRL, TERMSELECT);
163                 twl4030_usb_set_bits(OTG_CTRL, DPPULLDOWN);
164         }
165
166         return 0;
167 }
168
169