]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-pinebook-pro.patch
up to 6.8.8
[packages/kernel.git] / kernel-pinebook-pro.patch
1 From 8149051c34bc3d4c55adc56d04ffb7f7a04c2fd9 Mon Sep 17 00:00:00 2001
2 From: Dan Johansen <strit@manjaro.org>
3 Date: Sun, 2 Jan 2022 16:45:28 +0100
4 Subject: [PATCH 1/2] Add megis extcon changes to fusb302
5
6 Signed-off-by: Dan Johansen <strit@manjaro.org>
7 ---
8  drivers/phy/rockchip/phy-rockchip-typec.c |  5 +++
9  drivers/usb/typec/Kconfig                 |  7 ++++
10  drivers/usb/typec/Makefile                |  1 +
11  drivers/usb/typec/tcpm/fusb302.c          | 47 ++++++++++++++++-------
12  drivers/usb/typec/tcpm/fusb302_reg.h      | 16 ++++----
13  5 files changed, 53 insertions(+), 23 deletions(-)
14
15 diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c
16 index d2bbdc96a167..fa10ee9a5794 100644
17 --- a/drivers/phy/rockchip/phy-rockchip-typec.c
18 +++ b/drivers/phy/rockchip/phy-rockchip-typec.c
19 @@ -350,6 +350,7 @@ struct usb3phy_reg {
20   * struct rockchip_usb3phy_port_cfg - usb3-phy port configuration.
21   * @reg: the base address for usb3-phy config.
22   * @typec_conn_dir: the register of type-c connector direction.
23 + * @typec_conn_dir_sel: the register of type-c connector direction source.
24   * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
25   * @external_psm: the register of type-c phy external psm clock.
26   * @pipe_status: the register of type-c phy pipe status.
27 @@ -360,6 +361,7 @@ struct usb3phy_reg {
28  struct rockchip_usb3phy_port_cfg {
29         unsigned int reg;
30         struct usb3phy_reg typec_conn_dir;
31 +       struct usb3phy_reg typec_conn_dir_sel;
32         struct usb3phy_reg usb3tousb2_en;
33         struct usb3phy_reg external_psm;
34         struct usb3phy_reg pipe_status;
35 @@ -434,6 +436,7 @@ static const struct rockchip_usb3phy_port_cfg rk3399_usb3phy_port_cfgs[] = {
36         {
37                 .reg = 0xff7c0000,
38                 .typec_conn_dir = { 0xe580, 0, 16 },
39 +               .typec_conn_dir_sel     = { 0xe580, 8, 16+8 },
40                 .usb3tousb2_en  = { 0xe580, 3, 19 },
41                 .external_psm   = { 0xe588, 14, 30 },
42                 .pipe_status    = { 0xe5c0, 0, 0 },
43 @@ -444,6 +447,7 @@ static const struct rockchip_usb3phy_port_cfg rk3399_usb3phy_port_cfgs[] = {
44         {
45                 .reg = 0xff800000,
46                 .typec_conn_dir = { 0xe58c, 0, 16 },
47 +               .typec_conn_dir_sel     = { 0xe58c, 8, 16+8 },
48                 .usb3tousb2_en  = { 0xe58c, 3, 19 },
49                 .external_psm   = { 0xe594, 14, 30 },
50                 .pipe_status    = { 0xe5c0, 16, 16 },
51 @@ -739,6 +743,7 @@ static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode)
52  
53         reset_control_deassert(tcphy->tcphy_rst);
54  
55 +       property_enable(tcphy, &cfg->typec_conn_dir_sel, 0);
56         property_enable(tcphy, &cfg->typec_conn_dir, tcphy->flip);
57         tcphy_dp_aux_set_flip(tcphy);
58  
59 diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig
60 index ab480f38523a..01ecc5e590f1 100644
61 --- a/drivers/usb/typec/Kconfig
62 +++ b/drivers/usb/typec/Kconfig
63 @@ -88,6 +88,13 @@ config TYPEC_QCOM_PMIC
64           If you choose to build this driver as a dynamically linked module, the
65           module will be called wusb3801.ko.
66  
67 +config TYPEC_EXTCON
68 +       tristate "Type-C switch/mux -> extcon interface bridge driver"
69 +       depends on USB_ROLE_SWITCH
70 +       help
71 +         Say Y or M here if your system needs bridging between typec class
72 +         and extcon interfaces.
73 +
74  source "drivers/usb/typec/mux/Kconfig"
75  
76  source "drivers/usb/typec/altmodes/Kconfig"
77 diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
78 index a0adb8947a30..d9d829386b73 100644
79 --- a/drivers/usb/typec/Makefile
80 +++ b/drivers/usb/typec/Makefile
81 @@ -8,4 +8,5 @@ obj-$(CONFIG_TYPEC_TPS6598X)    += tipd/
82  obj-$(CONFIG_TYPEC_STUSB160X)  += stusb160x.o
83  obj-$(CONFIG_TYPEC_RT1719)     += rt1719.o
84  obj-$(CONFIG_TYPEC_WUSB3801)   += wusb3801.o
85 +obj-$(CONFIG_TYPEC_EXTCON)     += typec-extcon.o
86  obj-$(CONFIG_TYPEC)            += mux/
87 diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
88 index 72f9001b0792..cb26793f90f8 100644
89 --- a/drivers/usb/typec/tcpm/fusb302.c
90 +++ b/drivers/usb/typec/tcpm/fusb302.c
91 @@ -440,6 +440,16 @@ static int tcpm_get_current_limit(struct tcpc_dev *dev)
92         int current_limit = 0;
93         unsigned long timeout;
94  
95 +       /*
96 +        * To avoid cycles in OF dependencies, we get extcon when necessary
97 +        * outside of probe function.
98 +        */
99 +       if (of_property_read_bool(chip->dev->of_node, "extcon") && !chip->extcon) {
100 +               chip->extcon = extcon_get_edev_by_phandle(chip->dev, 0);
101 +               if (IS_ERR(chip->extcon))
102 +                       chip->extcon = NULL;
103 +       }
104 +
105         if (!chip->extcon)
106                 return 0;
107  
108 @@ -498,6 +508,7 @@ static int fusb302_set_toggling(struct fusb302_chip *chip,
109                                 enum toggling_mode mode)
110  {
111         int ret = 0;
112 +       u8 reg;
113  
114         /* first disable toggling */
115         ret = fusb302_i2c_clear_bits(chip, FUSB_REG_CONTROL2,
116 @@ -556,6 +567,12 @@ static int fusb302_set_toggling(struct fusb302_chip *chip,
117         } else {
118                 /* Datasheet says vconn MUST be off when toggling */
119                 WARN(chip->vconn_on, "Vconn is on during toggle start");
120 +
121 +               /* clear interrupts */
122 +                ret = fusb302_i2c_read(chip, FUSB_REG_INTERRUPT, &reg);
123 +               if (ret < 0)
124 +                       return ret;
125 +
126                 /* unmask TOGDONE interrupt */
127                 ret = fusb302_i2c_clear_bits(chip, FUSB_REG_MASKA,
128                                              FUSB_REG_MASKA_TOGDONE);
129 @@ -635,6 +652,14 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc)
130                 goto done;
131         }
132  
133 +       /* adjust current for SRC */
134 +       ret = fusb302_set_src_current(chip, cc_src_current[cc]);
135 +       if (ret < 0) {
136 +               fusb302_log(chip, "cannot set src current %s, ret=%d",
137 +                           typec_cc_status_name[cc], ret);
138 +               goto done;
139 +       }
140 +
141         ret = fusb302_i2c_mask_write(chip, FUSB_REG_SWITCHES0,
142                                      switches0_mask, switches0_data);
143         if (ret < 0) {
144 @@ -645,14 +670,6 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc)
145         chip->cc1 = TYPEC_CC_OPEN;
146         chip->cc2 = TYPEC_CC_OPEN;
147  
148 -       /* adjust current for SRC */
149 -       ret = fusb302_set_src_current(chip, cc_src_current[cc]);
150 -       if (ret < 0) {
151 -               fusb302_log(chip, "cannot set src current %s, ret=%d",
152 -                           typec_cc_status_name[cc], ret);
153 -               goto done;
154 -       }
155 -
156         /* enable/disable interrupts, BC_LVL for SNK and COMP_CHNG for SRC */
157         switch (cc) {
158         case TYPEC_CC_RP_DEF:
159 @@ -1528,14 +1545,16 @@ static void fusb302_irq_work(struct work_struct *work)
160                     "IRQ: 0x%02x, a: 0x%02x, b: 0x%02x, status0: 0x%02x",
161                     interrupt, interrupta, interruptb, status0);
162  
163 -       if (interrupt & FUSB_REG_INTERRUPT_VBUSOK) {
164 -               vbus_present = !!(status0 & FUSB_REG_STATUS0_VBUSOK);
165 +       vbus_present = !!(status0 & FUSB_REG_STATUS0_VBUSOK);
166 +       if (interrupt & FUSB_REG_INTERRUPT_VBUSOK)
167                 fusb302_log(chip, "IRQ: VBUS_OK, vbus=%s",
168                             vbus_present ? "On" : "Off");
169 -               if (vbus_present != chip->vbus_present) {
170 -                       chip->vbus_present = vbus_present;
171 -                       tcpm_vbus_change(chip->tcpm_port);
172 -               }
173 +       if (vbus_present != chip->vbus_present) {
174 +               chip->vbus_present = vbus_present;
175 +               if (!(interrupt & FUSB_REG_INTERRUPT_VBUSOK))
176 +               fusb302_log(chip, "IRQ: VBUS changed without interrupt, vbus=%s",
177 +                           vbus_present ? "On" : "Off");
178 +               tcpm_vbus_change(chip->tcpm_port);
179         }
180  
181         if ((interrupta & FUSB_REG_INTERRUPTA_TOGDONE) && intr_togdone) {
182 diff --git a/drivers/usb/typec/tcpm/fusb302_reg.h b/drivers/usb/typec/tcpm/fusb302_reg.h
183 index edc0e4b0f1e6..f37d226c5027 100644
184 --- a/drivers/usb/typec/tcpm/fusb302_reg.h
185 +++ b/drivers/usb/typec/tcpm/fusb302_reg.h
186 @@ -27,14 +27,13 @@
187  #define FUSB_REG_SWITCHES1_TXCC2_EN            BIT(1)
188  #define FUSB_REG_SWITCHES1_TXCC1_EN            BIT(0)
189  #define FUSB_REG_MEASURE                       0x04
190 -#define FUSB_REG_MEASURE_MDAC5                 BIT(7)
191 -#define FUSB_REG_MEASURE_MDAC4                 BIT(6)
192 -#define FUSB_REG_MEASURE_MDAC3                 BIT(5)
193 -#define FUSB_REG_MEASURE_MDAC2                 BIT(4)
194 -#define FUSB_REG_MEASURE_MDAC1                 BIT(3)
195 -#define FUSB_REG_MEASURE_MDAC0                 BIT(2)
196 -#define FUSB_REG_MEASURE_VBUS                  BIT(1)
197 -#define FUSB_REG_MEASURE_XXXX5                 BIT(0)
198 +#define FUSB_REG_MEASURE_VBUS                  BIT(6)
199 +#define FUSB_REG_MEASURE_MDAC5                 BIT(5)
200 +#define FUSB_REG_MEASURE_MDAC4                 BIT(4)
201 +#define FUSB_REG_MEASURE_MDAC3                 BIT(3)
202 +#define FUSB_REG_MEASURE_MDAC2                 BIT(2)
203 +#define FUSB_REG_MEASURE_MDAC1                 BIT(1)
204 +#define FUSB_REG_MEASURE_MDAC0                 BIT(0)
205  #define FUSB_REG_CONTROL0                      0x06
206  #define FUSB_REG_CONTROL0_TX_FLUSH             BIT(6)
207  #define FUSB_REG_CONTROL0_INT_MASK             BIT(5)
208 @@ -105,7 +104,6 @@
209  #define FUSB_REG_STATUS0A_RX_SOFT_RESET                BIT(1)
210  #define FUSB_REG_STATUS0A_RX_HARD_RESET                BIT(0)
211  #define FUSB_REG_STATUS1A                      0x3D
212 -#define FUSB_REG_STATUS1A_TOGSS                        BIT(3)
213  #define FUSB_REG_STATUS1A_TOGSS_RUNNING                0x0
214  #define FUSB_REG_STATUS1A_TOGSS_SRC1           0x1
215  #define FUSB_REG_STATUS1A_TOGSS_SRC2           0x2
216 -- 
217 2.34.1
218
219 From 6af2e6a2d59bd755234e5e15a47dfa669788143c Mon Sep 17 00:00:00 2001
220 From: Dan Johansen <strit@manjaro.org>
221 Date: Sun, 2 Jan 2022 16:47:40 +0100
222 Subject: [PATCH 2/2] usb: typec: Add megis typex to extcon bridge driver
223
224 Signed-off-by: Dan Johansen <strit@manjaro.org>
225 ---
226  drivers/usb/typec/typec-extcon.c | 337 +++++++++++++++++++++++++++++++
227  1 file changed, 337 insertions(+)
228  create mode 100644 drivers/usb/typec/typec-extcon.c
229
230 diff --git a/drivers/usb/typec/typec-extcon.c b/drivers/usb/typec/typec-extcon.c
231 new file mode 100644
232 index 000000000000..143ff2486f2f
233 --- /dev/null
234 +++ b/drivers/usb/typec/typec-extcon.c
235 @@ -0,0 +1,337 @@
236 +/*
237 + * typec -> extcon bridge
238 + * Copyright (c) 2021 OndÅ™ej Jirman <megi@xff.cz>
239 + *
240 + * This driver bridges standard type-c interfaces to drivers that
241 + * expect extcon interface.
242 + */
243 +
244 +#include <linux/delay.h>
245 +#include <linux/kernel.h>
246 +#include <linux/module.h>
247 +#include <linux/power_supply.h>
248 +#include <linux/platform_device.h>
249 +#include <linux/usb/pd.h>
250 +#include <linux/usb/role.h>
251 +#include <linux/usb/typec.h>
252 +#include <linux/usb/typec_dp.h>
253 +#include <linux/usb/typec_mux.h>
254 +#include <linux/extcon-provider.h>
255 +
256 +struct typec_extcon {
257 +        struct device *dev;
258 +
259 +       /* consumers */
260 +       struct usb_role_switch *role_sw;
261 +        struct typec_switch_dev *sw;
262 +        struct typec_mux_dev *mux;
263 +
264 +       /* providers */
265 +       struct extcon_dev *extcon;
266 +       struct notifier_block extcon_nb;
267 +
268 +       /* cached state from typec controller */
269 +       enum usb_role role;
270 +       enum typec_orientation orientation;
271 +       struct typec_altmode alt;
272 +       unsigned long mode;
273 +       bool has_alt;
274 +       struct mutex lock;
275 +};
276 +
277 +static const unsigned int typec_extcon_cable[] = {
278 +       EXTCON_DISP_DP,
279 +
280 +       EXTCON_USB,
281 +       EXTCON_USB_HOST,
282 +
283 +       EXTCON_CHG_USB_SDP,
284 +       EXTCON_CHG_USB_CDP,
285 +       EXTCON_CHG_USB_DCP,
286 +       EXTCON_CHG_USB_ACA,
287 +
288 +       EXTCON_NONE,
289 +};
290 +
291 +static void typec_extcon_set_cable(struct typec_extcon *tce, int id, bool on,
292 +                                  union extcon_property_value prop_ss,
293 +                                  union extcon_property_value prop_or)
294 +{
295 +       union extcon_property_value cur_ss, cur_or;
296 +       bool prop_diff = false;
297 +       int ret;
298 +
299 +       ret = extcon_get_property(tce->extcon, id,
300 +                                 EXTCON_PROP_USB_SS, &cur_ss);
301 +       if (ret || cur_ss.intval != prop_ss.intval)
302 +               prop_diff = true;
303 +
304 +       ret = extcon_get_property(tce->extcon, id,
305 +                                 EXTCON_PROP_USB_TYPEC_POLARITY, &cur_or);
306 +       if (ret || cur_or.intval != prop_or.intval)
307 +               prop_diff = true;
308 +
309 +       if (!on && extcon_get_state(tce->extcon, id)) {
310 +               extcon_set_state_sync(tce->extcon, id, false);
311 +       } else if (on && (!extcon_get_state(tce->extcon, id) || prop_diff)) {
312 +               extcon_set_state(tce->extcon, id, true);
313 +               extcon_set_property(tce->extcon, id,
314 +                                   EXTCON_PROP_USB_SS, prop_ss);
315 +               extcon_set_property(tce->extcon, id,
316 +                                   EXTCON_PROP_USB_TYPEC_POLARITY, prop_or);
317 +               extcon_sync(tce->extcon, id);
318 +       }
319 +}
320 +
321 +static int typec_extcon_sync_extcon(struct typec_extcon *tce)
322 +{
323 +       union extcon_property_value prop_ss, prop_or;
324 +       bool has_dp = false;
325 +
326 +        mutex_lock(&tce->lock);
327 +
328 +       /* connector is disconnected */
329 +       if (tce->orientation == TYPEC_ORIENTATION_NONE) {
330 +               typec_extcon_set_cable(tce, EXTCON_USB, false, prop_ss, prop_or);
331 +               typec_extcon_set_cable(tce, EXTCON_USB_HOST, false, prop_ss, prop_or);
332 +               typec_extcon_set_cable(tce, EXTCON_DISP_DP, false, prop_ss, prop_or);
333 +
334 +               extcon_set_state_sync(tce->extcon, EXTCON_CHG_USB_SDP, false);
335 +               extcon_set_state_sync(tce->extcon, EXTCON_CHG_USB_DCP, false);
336 +               extcon_set_state_sync(tce->extcon, EXTCON_CHG_USB_CDP, false);
337 +               extcon_set_state_sync(tce->extcon, EXTCON_CHG_USB_ACA, false);
338 +
339 +                goto out_unlock;
340 +       }
341 +
342 +       prop_or.intval = tce->orientation == TYPEC_ORIENTATION_NORMAL ? 0 : 1;
343 +       prop_ss.intval = 0;
344 +
345 +       if (tce->has_alt && tce->alt.svid == USB_TYPEC_DP_SID) {
346 +               switch (tce->mode) {
347 +               case TYPEC_STATE_SAFE:
348 +                       break;
349 +               case TYPEC_DP_STATE_C:
350 +               case TYPEC_DP_STATE_E:
351 +                       has_dp = true;
352 +                       break;
353 +               case TYPEC_DP_STATE_D:
354 +                       has_dp = true;
355 +                       fallthrough;
356 +               case TYPEC_STATE_USB:
357 +                       prop_ss.intval = 1;
358 +                       break;
359 +               default:
360 +                       dev_err(tce->dev, "unhandled mux mode=%lu\n", tce->mode);
361 +                       break;
362 +               }
363 +       }
364 +
365 +       typec_extcon_set_cable(tce, EXTCON_USB,
366 +                       tce->role == USB_ROLE_DEVICE, prop_ss, prop_or);
367 +       typec_extcon_set_cable(tce, EXTCON_USB_HOST,
368 +                       tce->role == USB_ROLE_HOST, prop_ss, prop_or);
369 +
370 +       typec_extcon_set_cable(tce, EXTCON_DISP_DP, has_dp, prop_ss, prop_or);
371 +
372 +out_unlock:
373 +       mutex_unlock(&tce->lock);
374 +       return 0;
375 +}
376 +
377 +static int typec_extcon_sw_set(struct typec_switch_dev *sw,
378 +                              enum typec_orientation orientation)
379 +{
380 +        struct typec_extcon *tce = typec_switch_get_drvdata(sw);
381 +
382 +       dev_dbg(tce->dev, "SW SET: orientation=%d\n", orientation);
383 +
384 +        mutex_lock(&tce->lock);
385 +       tce->orientation = orientation;
386 +        mutex_unlock(&tce->lock);
387 +
388 +       typec_extcon_sync_extcon(tce);
389 +
390 +        return 0;
391 +}
392 +
393 +static int typec_extcon_mux_set(struct typec_mux_dev *mux,
394 +                               struct typec_mux_state *state)
395 +{
396 +        struct typec_extcon *tce = typec_mux_get_drvdata(mux);
397 +       struct typec_altmode *alt = state->alt;
398 +
399 +       dev_dbg(tce->dev, "MUX SET: state->mode=%lu\n", state->mode);
400 +       if (alt)
401 +               dev_dbg(tce->dev, "      ...alt: svid=%04hx mode=%d vdo=%08x active=%u\n",
402 +                       alt->svid, alt->mode, alt->vdo, alt->active);
403 +
404 +        mutex_lock(&tce->lock);
405 +       tce->mode = state->mode;
406 +       tce->has_alt = alt != NULL;
407 +        if (alt)
408 +               tce->alt = *alt;
409 +       mutex_unlock(&tce->lock);
410 +
411 +       typec_extcon_sync_extcon(tce);
412 +
413 +        return 0;
414 +}
415 +
416 +static int typec_extcon_usb_set_role(struct usb_role_switch *sw,
417 +                                    enum usb_role role)
418 +{
419 +        struct typec_extcon *tce = usb_role_switch_get_drvdata(sw);
420 +
421 +       dev_dbg(tce->dev, "ROLE SET: role=%d\n", role);
422 +
423 +        mutex_lock(&tce->lock);
424 +       tce->role = role;
425 +       mutex_unlock(&tce->lock);
426 +
427 +       typec_extcon_sync_extcon(tce);
428 +
429 +        return 0;
430 +}
431 +
432 +static int typec_extcon_notifier(struct notifier_block *nb,
433 +                                        unsigned long action, void *data)
434 +{
435 +       struct typec_extcon *tce = container_of(nb, struct typec_extcon, extcon_nb);
436 +
437 +       bool sdp = extcon_get_state(tce->extcon, EXTCON_CHG_USB_SDP);
438 +       bool cdp = extcon_get_state(tce->extcon, EXTCON_CHG_USB_CDP);
439 +       bool dcp = extcon_get_state(tce->extcon, EXTCON_CHG_USB_DCP);
440 +       bool usb = extcon_get_state(tce->extcon, EXTCON_USB);
441 +       bool usb_host = extcon_get_state(tce->extcon, EXTCON_USB_HOST);
442 +       bool dp = extcon_get_state(tce->extcon, EXTCON_DISP_DP);
443 +
444 +       dev_info(tce->dev, "extcon changed sdp=%d cdp=%d dcp=%d usb=%d usb_host=%d dp=%d\n",
445 +                sdp, cdp, dcp, usb, usb_host, dp);
446 +
447 +       return NOTIFY_OK;
448 +}
449 +
450 +static int typec_extcon_probe(struct platform_device *pdev)
451 +{
452 +        struct typec_switch_desc sw_desc = { };
453 +        struct typec_mux_desc mux_desc = { };
454 +        struct usb_role_switch_desc role_desc = { };
455 +        struct device *dev = &pdev->dev;
456 +        struct typec_extcon *tce;
457 +        int ret = 0;
458 +
459 +        tce = devm_kzalloc(dev, sizeof(*tce), GFP_KERNEL);
460 +        if (!tce)
461 +                return -ENOMEM;
462 +
463 +        tce->dev = &pdev->dev;
464 +       mutex_init(&tce->lock);
465 +       tce->mode = TYPEC_STATE_SAFE;
466 +
467 +       sw_desc.drvdata = tce;
468 +       sw_desc.fwnode = dev->fwnode;
469 +       sw_desc.set = typec_extcon_sw_set;
470 +
471 +       tce->sw = typec_switch_register(dev, &sw_desc);
472 +       if (IS_ERR(tce->sw))
473 +               return dev_err_probe(dev, PTR_ERR(tce->sw),
474 +                                    "Error registering typec switch\n");
475 +
476 +       mux_desc.drvdata = tce;
477 +       mux_desc.fwnode = dev->fwnode;
478 +       mux_desc.set = typec_extcon_mux_set;
479 +
480 +       tce->mux = typec_mux_register(dev, &mux_desc);
481 +       if (IS_ERR(tce->mux)) {
482 +               ret = dev_err_probe(dev, PTR_ERR(tce->mux),
483 +                                   "Error registering typec mux\n");
484 +               goto err_sw;
485 +       }
486 +
487 +       role_desc.driver_data = tce;
488 +       role_desc.fwnode = dev->fwnode;
489 +       role_desc.name = fwnode_get_name(dev->fwnode);
490 +       role_desc.set = typec_extcon_usb_set_role;
491 +
492 +       tce->role_sw = usb_role_switch_register(dev, &role_desc);
493 +       if (IS_ERR(tce->role_sw)) {
494 +               ret = dev_err_probe(dev, PTR_ERR(tce->role_sw),
495 +                                   "Error registering USB role switch\n");
496 +               goto err_mux;
497 +       }
498 +
499 +       tce->extcon = devm_extcon_dev_allocate(dev, typec_extcon_cable);
500 +       if (IS_ERR(tce->extcon)) {
501 +               ret = PTR_ERR(tce->extcon);
502 +               goto err_role;
503 +       }
504 +
505 +       ret = devm_extcon_dev_register(dev, tce->extcon);
506 +       if (ret) {
507 +               ret = dev_err_probe(dev, ret, "failed to register extcon device\n");
508 +               goto err_role;
509 +       }
510 +
511 +       extcon_set_property_capability(tce->extcon, EXTCON_USB,
512 +                                      EXTCON_PROP_USB_SS);
513 +       extcon_set_property_capability(tce->extcon, EXTCON_USB,
514 +                                      EXTCON_PROP_USB_TYPEC_POLARITY);
515 +       extcon_set_property_capability(tce->extcon, EXTCON_USB_HOST,
516 +                                      EXTCON_PROP_USB_SS);
517 +       extcon_set_property_capability(tce->extcon, EXTCON_USB_HOST,
518 +                                      EXTCON_PROP_USB_TYPEC_POLARITY);
519 +       extcon_set_property_capability(tce->extcon, EXTCON_DISP_DP,
520 +                                      EXTCON_PROP_USB_SS);
521 +       extcon_set_property_capability(tce->extcon, EXTCON_DISP_DP,
522 +                                      EXTCON_PROP_USB_TYPEC_POLARITY);
523 +
524 +       tce->extcon_nb.notifier_call = typec_extcon_notifier;
525 +       ret = devm_extcon_register_notifier_all(dev, tce->extcon, &tce->extcon_nb);
526 +       if (ret) {
527 +               dev_err_probe(dev, ret, "Failed to register extcon notifier\n");
528 +               goto err_role;
529 +       }
530 +
531 +       return 0;
532 +
533 +err_role:
534 +       usb_role_switch_unregister(tce->role_sw);
535 +err_mux:
536 +       typec_mux_unregister(tce->mux);
537 +err_sw:
538 +       typec_switch_unregister(tce->sw);
539 +       return ret;
540 +}
541 +
542 +static int typec_extcon_remove(struct platform_device *pdev)
543 +{
544 +        struct typec_extcon *tce = platform_get_drvdata(pdev);
545 +
546 +       usb_role_switch_unregister(tce->role_sw);
547 +       typec_mux_unregister(tce->mux);
548 +       typec_switch_unregister(tce->sw);
549 +
550 +        return 0;
551 +}
552 +
553 +static struct of_device_id typec_extcon_of_match_table[] = {
554 +        { .compatible = "linux,typec-extcon-bridge" },
555 +        { },
556 +};
557 +MODULE_DEVICE_TABLE(of, typec_extcon_of_match_table);
558 +
559 +static struct platform_driver typec_extcon_driver = {
560 +        .driver = {
561 +                .name = "typec-extcon",
562 +                .of_match_table = typec_extcon_of_match_table,
563 +        },
564 +        .probe = typec_extcon_probe,
565 +        .remove = typec_extcon_remove,
566 +};
567 +
568 +module_platform_driver(typec_extcon_driver);
569 +
570 +MODULE_LICENSE("GPL");
571 +MODULE_AUTHOR("Ondrej Jirman <megous@megous.com>");
572 +MODULE_DESCRIPTION("typec -> extcon bridge driver");
573 -- 
574 2.34.1
575
576 From 4c839ce95766910235ff558b2959589c9068917c Mon Sep 17 00:00:00 2001
577 From: Dan Johansen <strit@manjaro.org>
578 Date: Sun, 2 Jan 2022 19:15:39 +0100
579 Subject: [PATCH] arm64: dts: rockchip: add typec extcon hack
580
581 Signed-off-by: Dan Johansen <strit@manjaro.org>
582 ---
583  .../boot/dts/rockchip/rk3399-pinebook-pro.dts | 31 +++++++++++++++++--
584  1 file changed, 29 insertions(+), 2 deletions(-)
585
586 diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
587 index c2f021a1a18f..fc33e111bbee 100644
588 --- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
589 +++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
590 @@ -384,6 +384,20 @@ mains_charger: dc-charger {
591                 pinctrl-names = "default";
592                 pinctrl-0 = <&dc_det_pin>;
593         };
594 +       
595 +    typec_extcon_bridge: typec-extcon {
596 +               compatible = "linux,typec-extcon-bridge";
597 +               usb-role-switch;
598 +               orientation-switch;
599 +               mode-switch;
600 +               svid = /bits/ 16 <0xff01>;
601 +       };
602 +};
603 +
604 +&cdn_dp {
605 +       status = "okay";
606 +       extcon = <&typec_extcon_bridge>;
607 +       phys = <&tcphy0_dp>;
608  };
609  
610  &cpu_b0 {
611 @@ -705,6 +719,8 @@ fusb0: fusb30x@22 {
612                 pinctrl-names = "default";
613                 pinctrl-0 = <&fusb0_int_pin>;
614                 vbus-supply = <&vbus_typec>;
615 +               extcon = <&typec_extcon_bridge>;
616 +               usb-role-switch = <&typec_extcon_bridge>;
617  
618                 connector {
619                         compatible = "usb-c-connector";
620 @@ -713,10 +729,20 @@ connector {
621                         op-sink-microwatt = <1000000>;
622                         power-role = "dual";
623                         sink-pdos =
624 -                               <PDO_FIXED(5000, 2500, PDO_FIXED_USB_COMM)>;
625 +                               <PDO_FIXED(5000, 2500, PDO_FIXED_USB_COMM | PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP)>;
626                         source-pdos =
627 -                               <PDO_FIXED(5000, 1400, PDO_FIXED_USB_COMM)>;
628 +                               <PDO_FIXED(5000, 1400, PDO_FIXED_USB_COMM | PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP)>;
629                         try-power-role = "sink";
630 +                       
631 +                       mode-switch = <&typec_extcon_bridge>;
632 +                       orientation-switch = <&typec_extcon_bridge>;
633 +
634 +                       altmodes {
635 +                               dp {
636 +                                       svid = <0xff01>;
637 +                                       vdo = <0x0c0006>;
638 +                               };
639 +                       };
640  
641                         ports {
642                                 #address-cells = <1>;
643 @@ -984,6 +1010,7 @@ spiflash: flash@0 {
644  };
645  
646  &tcphy0 {
647 +       extcon = <&typec_extcon_bridge>;
648         status = "okay";
649  };
650  
651 -- 
652 2.34.1
653
This page took 0.077235 seconds and 3 git commands to generate.