blob: 5cc262580e9fbd755900c2b7ddbf0b15e8075f7f [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
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 <trace.h>
25#include <sys/types.h>
26#include <dev/i2c.h>
27#include <dev/twl4030.h>
28#include "twl4030_hw.h"
29
30// XXX move to target specific setup
31#define TWL_I2C_BUS 0
32
33void twl4030_init(void)
34{
35}
36
37static int twl4030_usb_write(uint8_t address, uint8_t data)
38{
39 return i2c_write_reg(TWL_I2C_BUS, TWL_USB_ADDR, address, data);
40}
41
42static int twl4030_usb_read(uint8_t address)
43{
44 uint8_t data;
45
46 int err = i2c_read_reg(TWL_I2C_BUS, TWL_USB_ADDR, address, &data);
47 if (err < 0)
48 return err;
49
50 return data;
51}
52
53static int twl4030_usb_set_bits(uint8_t reg, uint8_t bits)
54{
55 return twl4030_usb_write(reg + 1, bits);
56}
57
58static int twl4030_usb_clear_bits(uint8_t reg, uint8_t bits)
59{
60 return twl4030_usb_write(reg + 2, bits);
61}
62
63static void twl4030_i2c_access(bool on)
64{
65 int val;
66
67 if ((val = twl4030_usb_read(PHY_CLK_CTRL)) >= 0) {
68 if (on) {
69 /* enable DPLL to access PHY registers over I2C */
70 val |= REQ_PHY_DPLL_CLK;
71 twl4030_usb_write(PHY_CLK_CTRL, (uint8_t)val);
72
73 while (!(twl4030_usb_read(PHY_CLK_CTRL_STS) & PHY_DPLL_CLK)) {
74 spin(10);
75 }
76 if (!(twl4030_usb_read(PHY_CLK_CTRL_STS) & PHY_DPLL_CLK))
77 printf("Timeout setting T2 HSUSB " "PHY DPLL clock\n");
78 } else {
79 /* let ULPI control the DPLL clock */
80 val &= ~REQ_PHY_DPLL_CLK;
81 twl4030_usb_write(PHY_CLK_CTRL, (uint8_t)val);
82 }
83 }
84 return;
85}
86
87int twl4030_usb_reset(void)
88{
89 TRACE_ENTRY;
90#if 0
91 twl4030_usb_clear_bits(OTG_CTRL, DMPULLDOWN | DPPULLDOWN);
92 twl4030_usb_clear_bits(USB_INT_EN_RISE, ~0);
93 twl4030_usb_clear_bits(USB_INT_EN_FALL, ~0);
94 twl4030_usb_clear_bits(MCPC_IO_CTRL, ~TXDTYP);
95 twl4030_usb_set_bits(MCPC_IO_CTRL, TXDTYP);
96 twl4030_usb_clear_bits(OTHER_FUNC_CTRL, (BDIS_ACON_EN | FIVEWIRE_MODE));
97 twl4030_usb_clear_bits(OTHER_IFC_CTRL, ~0);
98 twl4030_usb_clear_bits(OTHER_INT_EN_RISE, ~0);
99 twl4030_usb_clear_bits(OTHER_INT_EN_FALL, ~0);
100 twl4030_usb_clear_bits(OTHER_IFC_CTRL2, ~0);
101 twl4030_usb_clear_bits(REG_CTRL_EN, ULPI_I2C_CONFLICT_INTEN);
102 twl4030_usb_clear_bits(OTHER_FUNC_CTRL2, VBAT_TIMER_EN);
103#endif
104
105 /* Enable writing to power configuration registers */
106 i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, PROTECT_KEY, 0xC0);
107 i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, PROTECT_KEY, 0x0C);
108
109 /* put VUSB3V1 LDO in active state */
110 i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB_DEDICATED2, 0);
111
112 /* input to VUSB3V1 LDO is from VBAT, not VBUS */
113 i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB_DEDICATED1, 0x14);
114
115 /* turn on 3.1V regulator */
116 i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB3V1_DEV_GRP, 0x20);
117 i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB3V1_TYPE, 0);
118
119 /* turn on 1.5V regulator */
120 i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V5_DEV_GRP, 0x20);
121 i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V5_TYPE, 0);
122
123 /* turn on 1.8V regulator */
124 i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V8_DEV_GRP, 0x20);
125 i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V8_TYPE, 0);
126
127 /* disable access to power configuration registers */
128 i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, PROTECT_KEY, 0);
129
130 /* turn on the phy */
131 uint8_t pwr = twl4030_usb_read(PHY_PWR_CTRL);
132 pwr &= ~PHYPWD;
133 twl4030_usb_write(PHY_PWR_CTRL, pwr);
134 twl4030_usb_write(PHY_CLK_CTRL,
135 twl4030_usb_read(PHY_CLK_CTRL) |
136 (CLOCKGATING_EN | CLK32K_EN));
137
138 /* set DPLL i2c access mode */
139 twl4030_i2c_access(true);
140 /* set ulpi mode */
141 twl4030_usb_clear_bits(IFC_CTRL, CARKITMODE);
142 twl4030_usb_set_bits(POWER_CTRL, OTG_ENAB);
143 twl4030_usb_write(FUNC_CTRL, XCVRSELECT_HS); // set high speed mode
144// twl4030_usb_write(FUNC_CTRL, XCVRSELECT_FS); // set full speed mode
145 twl4030_i2c_access(false);
146
147 return 0;
148}
149
150int twl4030_init_hs(void)
151{
152 return 0;
153}
154
155int twl4030_set_usb_pullup(bool pullup)
156{
157 TRACE_ENTRY;
158
159 if (pullup) {
160 twl4030_usb_clear_bits(OTG_CTRL, DPPULLDOWN);
161 twl4030_usb_set_bits(FUNC_CTRL, TERMSELECT);
162 } else {
163 twl4030_usb_clear_bits(FUNC_CTRL, TERMSELECT);
164 twl4030_usb_set_bits(OTG_CTRL, DPPULLDOWN);
165 }
166
167 return 0;
168}
169
170