blob: 234e21a3abdad2b6e16733d3ad3083e4fee8b107 [file] [log] [blame]
Rajesh Bharathwajdcc7af82019-12-15 22:42:55 -08001/*
2 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#include <linux/device.h>
16#include <linux/i2c.h>
17#include <linux/slab.h>
18#include <linux/platform_device.h>
19#include <linux/input.h>
20#include <linux/types.h>
21#include <linux/module.h>
22#include <linux/fs.h>
23#include <linux/kernel.h>
24#include <linux/gpio.h>
25#include <linux/delay.h>
26
27struct tusb1064 {
28 struct device *dev;
29 struct device_node *host_node;
30 u8 i2c_addr;
31 u32 dp_3v3_en;
32 struct i2c_client *i2c_client;
33 bool power_on;
34};
35
36static struct tusb1064 *pdata;
Rajesh Bharathwaj00b57ac2020-03-24 23:16:35 -070037static bool standalone_mode;
Rajesh Bharathwajdcc7af82019-12-15 22:42:55 -080038
39static int tusb1064_read(struct i2c_client *client, u8 reg, char *buf, u32 size)
40{
41 struct i2c_msg msg[2] = {
42 {
43 .addr = client->addr,
44 .flags = 0,
45 .len = 1,
46 .buf = &reg,
47 },
48 {
49 .addr = client->addr,
50 .flags = I2C_M_RD,
51 .len = size,
52 .buf = buf,
53 }
54 };
55
56 if (i2c_transfer(client->adapter, msg, 2) != 2) {
57 pr_err("%s i2c read failed\n", __func__);
58 return -EIO;
59 }
60 pr_debug("%s, reg:%x buf[0]:%x\n", __func__, reg, buf[0]);
61
62 return 0;
63}
64
65static int tusb1064_write(struct i2c_client *client, u8 reg, u8 val)
66{
67 u8 buf[2] = {reg, val};
68 struct i2c_msg msg = {
69 .addr = client->addr,
70 .flags = 0,
71 .len = 2,
72 .buf = buf,
73 };
74
75 pr_debug("%s, reg:%x, val:%x\n", __func__, reg, val);
76 if (i2c_transfer(client->adapter, &msg, 1) < 1) {
77 pr_err("i2c write failed\n");
78 return -EIO;
79 }
80 return 0;
81}
82
83void tusb1064_flip(bool flip)
84{
85 if (pdata) {
86 if (flip) {
87 pr_debug("%s flipping the switch\n", __func__);
88 /*AUXn->SBU2, AUXp->SBU1*/
89 tusb1064_write(pdata->i2c_client, 0x13, 0x2F);
90 } else {
91 pr_debug("%s not flipping the switch\n", __func__);
92 /*AUXn->SBU2, AUXp->SBU1*/
93 tusb1064_write(pdata->i2c_client, 0x13, 0x1F);
94 }
95 }
96}
97EXPORT_SYMBOL(tusb1064_flip);
98
99static int tusb1064_probe(struct i2c_client *client,
100 const struct i2c_device_id *id)
101{
102 char buf[2];
103
104 if (!client || !client->dev.of_node) {
105 pr_err("%s invalid input\n", __func__);
106 return -EINVAL;
107 }
108
109 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
110 pr_err("%s device doesn't support I2C\n", __func__);
111 return -ENODEV;
112 }
113
114 pdata = devm_kzalloc(&client->dev,
115 sizeof(struct tusb1064), GFP_KERNEL);
116 if (!pdata)
117 return -ENOMEM;
118
119 pdata->dev = &client->dev;
120 pdata->i2c_client = client;
121 pr_debug("%s I2C address is %x\n", __func__, client->addr);
122
123 i2c_set_clientdata(client, pdata);
124 dev_set_drvdata(&client->dev, pdata);
125
126 tusb1064_read(pdata->i2c_client, 0x0A, buf, 2);
127 tusb1064_read(pdata->i2c_client, 0x13, buf, 2);
128 /*Enable 4-lane DP with FLip and enable EQ_OVERRIDe*/
129 /*tusb1064_write(pdata, 0x0A, 0x13); */
130 /*written usb sideEnable 4-lane DP with FLip and enable EQ_OVERRIDe */
131 /*tusb1064_write(pdata, 0x0A, 0x12); */
132
Rajesh Bharathwaj00b57ac2020-03-24 23:16:35 -0700133 if (standalone_mode) {
134 /*Enable 3.1 USB, no DP */
135 if (tusb1064_write(pdata->i2c_client, 0x0A, 0x01) < 0)
136 goto fail;
137 } else {
138 /*Enable 4-lane DP with Flip and enable EQ_OVERRIDe */
139 if (tusb1064_write(pdata->i2c_client, 0x0A, 0x02) < 0)
140 goto fail;
Rajesh Bharathwajdcc7af82019-12-15 22:42:55 -0800141
Rajesh Bharathwaj00b57ac2020-03-24 23:16:35 -0700142 pr_debug("%s setting SBU1 to AUXN, SBU2 to AUXP\n", __func__);
143 /*AUXn->SBU2, AUXp->SBU1 */
144 if (tusb1064_write(pdata->i2c_client, 0x13, 0x1F) < 0)
145 goto fail;
146 //tusb1064_write(pdata, 0x13, 0x01);//AUXn->SBU1, AUXp->SBU2
Rajesh Bharathwajdcc7af82019-12-15 22:42:55 -0800147
Rajesh Bharathwaj00b57ac2020-03-24 23:16:35 -0700148 /*Enable 4-lane DP */
149 if (tusb1064_write(pdata->i2c_client, 0x10, 0x55) < 0)
150 goto fail;
151 /*Enable 4-lane DP */
152 if (tusb1064_write(pdata->i2c_client, 0x11, 0x55) < 0)
153 goto fail;
154 //pr_err("setting SBU1 to AUXp and SBU2 to AUXN\n");
155 //tusb1064_write(pdata, 0x13, 0x8F);//Enable 4-lane DP
156 }
Rajesh Bharathwajdcc7af82019-12-15 22:42:55 -0800157 tusb1064_read(pdata->i2c_client, 0x0A, buf, 2);
158 tusb1064_read(pdata->i2c_client, 0x13, buf, 2);
159 tusb1064_read(pdata->i2c_client, 0x10, buf, 2);
160 tusb1064_read(pdata->i2c_client, 0x11, buf, 2);
161
162 pr_debug("%s probe successfully\n", __func__);
163 return 0;
164fail:
165 devm_kfree(&client->dev, pdata);
166 return -EINVAL;
167}
168
169static int tusb1064_remove(struct i2c_client *client)
170{
171 struct tusb1064 *pdata = i2c_get_clientdata(client);
172
173 if (pdata)
174 devm_kfree(&client->dev, pdata);
175 return 0;
176}
177
178static void tusb1064_shutdown(struct i2c_client *client)
179{
180 dev_info(&(client->dev), "shutdown");
181}
182
183static int tusb1064_suspend(struct device *dev, pm_message_t state)
184{
185 dev_info(dev, "suspend");
186 return 0;
187}
188
189static int tusb1064_resume(struct device *dev)
190{
191 dev_info(dev, "resume");
192 return 0;
193}
194
195static const struct i2c_device_id tusb1064_id_table[] = {
196 {"tusb1064", 0},
197 {}
198};
199
200static struct i2c_driver tusb1064_i2c_driver = {
201 .probe = tusb1064_probe,
202 .remove = tusb1064_remove,
203 .shutdown = tusb1064_shutdown,
204 .driver = {
205 .name = "tusb1064",
206 .owner = THIS_MODULE,
207 .suspend = tusb1064_suspend,
208 .resume = tusb1064_resume,
209 },
210 .id_table = tusb1064_id_table,
211};
Rajesh Bharathwaj00b57ac2020-03-24 23:16:35 -0700212
213static int __init tusb1064_init(void)
214{
215 char *cmdline;
216
217 cmdline = strnstr(boot_command_line,
218 "msm_drm.dsi_display0=dsi_sim_vid_display",
219 strlen(boot_command_line));
220 if (cmdline) {
221 pr_debug("%s tethered mode cmdline:%s\n",
222 __func__, cmdline);
223 standalone_mode = false;
224 } else {
225 pr_debug("%s standalone mode cmdline:%s\n",
226 __func__, cmdline);
227 standalone_mode = true;
228 }
229
230 return 0;
231}
232
233device_initcall(tusb1064_init);
Rajesh Bharathwajdcc7af82019-12-15 22:42:55 -0800234module_i2c_driver(tusb1064_i2c_driver);
235MODULE_DEVICE_TABLE(i2c, tusb1064_id_table);
236MODULE_DESCRIPTION("TUSB1064 USB Bridge");