1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <linux/i2c.h>
21#include <linux/interrupt.h>
22#include <linux/pci.h>
23#include <linux/platform_device.h>
24#include <linux/property.h>
25#include <linux/regulator/consumer.h>
26#include <linux/slab.h>
27#include <linux/usb/pd.h>
28
29#include "intel_cht_int33fe_common.h"
30
31
32
33
34
35
36
37
38
39static int cht_int33fe_check_for_max17047(struct device *dev, void *data)
40{
41 struct i2c_client **max17047 = data;
42 struct acpi_device *adev;
43
44 adev = ACPI_COMPANION(dev);
45 if (!adev)
46 return 0;
47
48
49 if (!acpi_dev_hid_uid_match(adev, "MAX17047", NULL))
50 return 0;
51
52 *max17047 = to_i2c_client(dev);
53 return 1;
54}
55
56static const char * const max17047_suppliers[] = { "bq24190-charger" };
57
58static const struct property_entry max17047_properties[] = {
59 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", max17047_suppliers),
60 { }
61};
62
63static const struct software_node max17047_node = {
64 .name = "max17047",
65 .properties = max17047_properties,
66};
67
68
69
70
71
72
73static struct software_node_ref_args fusb302_mux_refs[] = {
74 { .node = NULL },
75};
76
77static const struct property_entry fusb302_properties[] = {
78 PROPERTY_ENTRY_STRING("linux,extcon-name", "cht_wcove_pwrsrc"),
79 PROPERTY_ENTRY_REF_ARRAY("usb-role-switch", fusb302_mux_refs),
80 { }
81};
82
83static const struct software_node fusb302_node = {
84 .name = "fusb302",
85 .properties = fusb302_properties,
86};
87
88#define PDO_FIXED_FLAGS \
89 (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_USB_COMM)
90
91static const u32 src_pdo[] = {
92 PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS),
93};
94
95static const u32 snk_pdo[] = {
96 PDO_FIXED(5000, 400, PDO_FIXED_FLAGS),
97 PDO_VAR(5000, 12000, 3000),
98};
99
100static const struct software_node pi3usb30532_node = {
101 .name = "pi3usb30532",
102};
103
104static const struct software_node displayport_node = {
105 .name = "displayport",
106};
107
108static const struct property_entry usb_connector_properties[] = {
109 PROPERTY_ENTRY_STRING("data-role", "dual"),
110 PROPERTY_ENTRY_STRING("power-role", "dual"),
111 PROPERTY_ENTRY_STRING("try-power-role", "sink"),
112 PROPERTY_ENTRY_U32_ARRAY("source-pdos", src_pdo),
113 PROPERTY_ENTRY_U32_ARRAY("sink-pdos", snk_pdo),
114 PROPERTY_ENTRY_U32("op-sink-microwatt", 2500000),
115 PROPERTY_ENTRY_REF("orientation-switch", &pi3usb30532_node),
116 PROPERTY_ENTRY_REF("mode-switch", &pi3usb30532_node),
117 PROPERTY_ENTRY_REF("displayport", &displayport_node),
118 { }
119};
120
121static const struct software_node usb_connector_node = {
122 .name = "connector",
123 .parent = &fusb302_node,
124 .properties = usb_connector_properties,
125};
126
127static const struct software_node altmodes_node = {
128 .name = "altmodes",
129 .parent = &usb_connector_node,
130};
131
132static const struct property_entry dp_altmode_properties[] = {
133 PROPERTY_ENTRY_U32("svid", 0xff01),
134 PROPERTY_ENTRY_U32("vdo", 0x0c0086),
135 { }
136};
137
138static const struct software_node dp_altmode_node = {
139 .name = "displayport-altmode",
140 .parent = &altmodes_node,
141 .properties = dp_altmode_properties,
142};
143
144static const struct software_node *node_group[] = {
145 &fusb302_node,
146 &max17047_node,
147 &pi3usb30532_node,
148 &displayport_node,
149 &usb_connector_node,
150 &altmodes_node,
151 &dp_altmode_node,
152 NULL
153};
154
155static int cht_int33fe_setup_dp(struct cht_int33fe_data *data)
156{
157 struct fwnode_handle *fwnode;
158 struct pci_dev *pdev;
159
160 fwnode = software_node_fwnode(&displayport_node);
161 if (!fwnode)
162 return -ENODEV;
163
164
165 pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
166 if (!pdev || pdev->vendor != PCI_VENDOR_ID_INTEL) {
167 pci_dev_put(pdev);
168 return -ENODEV;
169 }
170
171
172 data->dp = device_get_named_child_node(&pdev->dev, "DD04");
173 pci_dev_put(pdev);
174 if (!data->dp)
175 return -ENODEV;
176
177 fwnode->secondary = ERR_PTR(-ENODEV);
178 data->dp->secondary = fwnode;
179
180 return 0;
181}
182
183static void cht_int33fe_remove_nodes(struct cht_int33fe_data *data)
184{
185 software_node_unregister_node_group(node_group);
186
187 if (fusb302_mux_refs[0].node) {
188 fwnode_handle_put(software_node_fwnode(fusb302_mux_refs[0].node));
189 fusb302_mux_refs[0].node = NULL;
190 }
191
192 if (data->dp) {
193 data->dp->secondary = NULL;
194 fwnode_handle_put(data->dp);
195 data->dp = NULL;
196 }
197}
198
199static int cht_int33fe_add_nodes(struct cht_int33fe_data *data)
200{
201 const struct software_node *mux_ref_node;
202 int ret;
203
204
205
206
207
208
209
210 mux_ref_node = software_node_find_by_name(NULL, "intel-xhci-usb-sw");
211 if (!mux_ref_node)
212 return -EPROBE_DEFER;
213
214
215
216
217
218
219 fusb302_mux_refs[0].node = mux_ref_node;
220
221 ret = software_node_register_node_group(node_group);
222 if (ret)
223 return ret;
224
225
226
227
228
229
230
231 ret = cht_int33fe_setup_dp(data);
232 if (ret)
233 goto err_remove_nodes;
234
235 return 0;
236
237err_remove_nodes:
238 cht_int33fe_remove_nodes(data);
239
240 return ret;
241}
242
243static int
244cht_int33fe_register_max17047(struct device *dev, struct cht_int33fe_data *data)
245{
246 struct i2c_client *max17047 = NULL;
247 struct i2c_board_info board_info;
248 struct fwnode_handle *fwnode;
249 int ret;
250
251 fwnode = software_node_fwnode(&max17047_node);
252 if (!fwnode)
253 return -ENODEV;
254
255 i2c_for_each_dev(&max17047, cht_int33fe_check_for_max17047);
256 if (max17047) {
257
258 set_secondary_fwnode(&max17047->dev, fwnode);
259
260 ret = device_reprobe(&max17047->dev);
261 if (ret)
262 dev_warn(dev, "Reprobing max17047 error: %d\n", ret);
263 return 0;
264 }
265
266 memset(&board_info, 0, sizeof(board_info));
267 strlcpy(board_info.type, "max17047", I2C_NAME_SIZE);
268 board_info.dev_name = "max17047";
269 board_info.fwnode = fwnode;
270 data->battery_fg = i2c_acpi_new_device(dev, 1, &board_info);
271
272 return PTR_ERR_OR_ZERO(data->battery_fg);
273}
274
275int cht_int33fe_typec_probe(struct cht_int33fe_data *data)
276{
277 struct device *dev = data->dev;
278 struct i2c_board_info board_info;
279 struct fwnode_handle *fwnode;
280 struct regulator *regulator;
281 int fusb302_irq;
282 int ret;
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298 regulator = regulator_get_optional(dev, "cht_wc_usb_typec_vbus");
299 if (IS_ERR(regulator)) {
300 ret = PTR_ERR(regulator);
301 return (ret == -ENODEV) ? -EPROBE_DEFER : ret;
302 }
303 regulator_put(regulator);
304
305
306 fusb302_irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 1);
307 if (fusb302_irq < 0) {
308 if (fusb302_irq != -EPROBE_DEFER)
309 dev_err(dev, "Error getting FUSB302 irq\n");
310 return fusb302_irq;
311 }
312
313 ret = cht_int33fe_add_nodes(data);
314 if (ret)
315 return ret;
316
317
318 ret = cht_int33fe_register_max17047(dev, data);
319 if (ret)
320 goto out_remove_nodes;
321
322 fwnode = software_node_fwnode(&fusb302_node);
323 if (!fwnode) {
324 ret = -ENODEV;
325 goto out_unregister_max17047;
326 }
327
328 memset(&board_info, 0, sizeof(board_info));
329 strlcpy(board_info.type, "typec_fusb302", I2C_NAME_SIZE);
330 board_info.dev_name = "fusb302";
331 board_info.fwnode = fwnode;
332 board_info.irq = fusb302_irq;
333
334 data->fusb302 = i2c_acpi_new_device(dev, 2, &board_info);
335 if (IS_ERR(data->fusb302)) {
336 ret = PTR_ERR(data->fusb302);
337 goto out_unregister_max17047;
338 }
339
340 fwnode = software_node_fwnode(&pi3usb30532_node);
341 if (!fwnode) {
342 ret = -ENODEV;
343 goto out_unregister_fusb302;
344 }
345
346 memset(&board_info, 0, sizeof(board_info));
347 board_info.dev_name = "pi3usb30532";
348 board_info.fwnode = fwnode;
349 strlcpy(board_info.type, "pi3usb30532", I2C_NAME_SIZE);
350
351 data->pi3usb30532 = i2c_acpi_new_device(dev, 3, &board_info);
352 if (IS_ERR(data->pi3usb30532)) {
353 ret = PTR_ERR(data->pi3usb30532);
354 goto out_unregister_fusb302;
355 }
356
357 return 0;
358
359out_unregister_fusb302:
360 i2c_unregister_device(data->fusb302);
361
362out_unregister_max17047:
363 i2c_unregister_device(data->battery_fg);
364
365out_remove_nodes:
366 cht_int33fe_remove_nodes(data);
367
368 return ret;
369}
370
371int cht_int33fe_typec_remove(struct cht_int33fe_data *data)
372{
373 i2c_unregister_device(data->pi3usb30532);
374 i2c_unregister_device(data->fusb302);
375 i2c_unregister_device(data->battery_fg);
376
377 cht_int33fe_remove_nodes(data);
378
379 return 0;
380}
381