]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-pinebook-pro.patch
update arm/arm64 configs for 6.6
[packages/kernel.git] / kernel-pinebook-pro.patch
CommitLineData
03acaa9b
JP
1From 8149051c34bc3d4c55adc56d04ffb7f7a04c2fd9 Mon Sep 17 00:00:00 2001
2From: Dan Johansen <strit@manjaro.org>
3Date: Sun, 2 Jan 2022 16:45:28 +0100
4Subject: [PATCH 1/2] Add megis extcon changes to fusb302
8c9054af 5
03acaa9b 6Signed-off-by: Dan Johansen <strit@manjaro.org>
8c9054af 7---
03acaa9b
JP
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(-)
8c9054af 14
03acaa9b
JP
15diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c
16index 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)
8c9054af 52
03acaa9b 53 reset_control_deassert(tcphy->tcphy_rst);
8c9054af 54
03acaa9b
JP
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);
8c9054af 58
03acaa9b
JP
59diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig
60index ab480f38523a..01ecc5e590f1 100644
61--- a/drivers/usb/typec/Kconfig
62+++ b/drivers/usb/typec/Kconfig
63@@ -88,6 +88,13 @@ config TYPEC_QCOM_PMIC
74b60f45
JP
64 If you choose to build this driver as a dynamically linked module, the
65 module will be called wusb3801.ko.
03acaa9b
JP
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.
8c9054af 73+
03acaa9b
JP
74 source "drivers/usb/typec/mux/Kconfig"
75
76 source "drivers/usb/typec/altmodes/Kconfig"
77diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
78index 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/
03acaa9b 82 obj-$(CONFIG_TYPEC_STUSB160X) += stusb160x.o
74b60f45
JP
83 obj-$(CONFIG_TYPEC_RT1719) += rt1719.o
84 obj-$(CONFIG_TYPEC_WUSB3801) += wusb3801.o
03acaa9b
JP
85+obj-$(CONFIG_TYPEC_EXTCON) += typec-extcon.o
86 obj-$(CONFIG_TYPEC) += mux/
87diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
88index 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;
8c9054af
JP
103+ }
104+
03acaa9b
JP
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");
8c9054af 120+
03acaa9b
JP
121+ /* clear interrupts */
122+ ret = fusb302_i2c_read(chip, FUSB_REG_INTERRUPT, &reg);
123+ if (ret < 0)
124+ return ret;
8c9054af 125+
03acaa9b
JP
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;
8c9054af 139+ }
8c9054af 140+
03acaa9b
JP
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;
8c9054af 147
03acaa9b
JP
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;
8c9054af 154- }
03acaa9b
JP
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);
8c9054af 162
03acaa9b
JP
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);
8c9054af 172- }
03acaa9b
JP
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);
8c9054af 179 }
8c9054af 180
03acaa9b
JP
181 if ((interrupta & FUSB_REG_INTERRUPTA_TOGDONE) && intr_togdone) {
182diff --git a/drivers/usb/typec/tcpm/fusb302_reg.h b/drivers/usb/typec/tcpm/fusb302_reg.h
183index 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
8c9054af 216--
03acaa9b 2172.34.1
8c9054af 218
03acaa9b
JP
219From 6af2e6a2d59bd755234e5e15a47dfa669788143c Mon Sep 17 00:00:00 2001
220From: Dan Johansen <strit@manjaro.org>
221Date: Sun, 2 Jan 2022 16:47:40 +0100
222Subject: [PATCH 2/2] usb: typec: Add megis typex to extcon bridge driver
8c9054af 223
03acaa9b 224Signed-off-by: Dan Johansen <strit@manjaro.org>
8c9054af 225---
03acaa9b
JP
226 drivers/usb/typec/typec-extcon.c | 337 +++++++++++++++++++++++++++++++
227 1 file changed, 337 insertions(+)
228 create mode 100644 drivers/usb/typec/typec-extcon.c
8c9054af 229
03acaa9b
JP
230diff --git a/drivers/usb/typec/typec-extcon.c b/drivers/usb/typec/typec-extcon.c
231new file mode 100644
232index 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;
0592a12c
JP
261+ struct typec_switch_dev *sw;
262+ struct typec_mux_dev *mux;
03acaa9b
JP
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)
8c9054af 294+{
03acaa9b
JP
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);
8c9054af
JP
318+ }
319+}
320+
03acaa9b 321+static int typec_extcon_sync_extcon(struct typec_extcon *tce)
8c9054af 322+{
03acaa9b
JP
323+ union extcon_property_value prop_ss, prop_or;
324+ bool has_dp = false;
8c9054af 325+
03acaa9b
JP
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;
8c9054af 340+ }
03acaa9b
JP
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+ }
8c9054af 363+ }
8c9054af 364+
03acaa9b
JP
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);
8c9054af 369+
03acaa9b
JP
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+
0592a12c 377+static int typec_extcon_sw_set(struct typec_switch_dev *sw,
03acaa9b 378+ enum typec_orientation orientation)
8c9054af 379+{
03acaa9b
JP
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;
8c9054af
JP
391+}
392+
0592a12c 393+static int typec_extcon_mux_set(struct typec_mux_dev *mux,
03acaa9b 394+ struct typec_mux_state *state)
8c9054af 395+{
03acaa9b
JP
396+ struct typec_extcon *tce = typec_mux_get_drvdata(mux);
397+ struct typec_altmode *alt = state->alt;
8c9054af 398+
03acaa9b
JP
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;
8c9054af
JP
414+}
415+
03acaa9b
JP
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;
8c9054af
JP
430+}
431+
03acaa9b
JP
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);
8c9054af 436+
03acaa9b
JP
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);
8c9054af 443+
03acaa9b
JP
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);
8c9054af 446+
03acaa9b
JP
447+ return NOTIFY_OK;
448+}
8c9054af 449+
03acaa9b 450+static int typec_extcon_probe(struct platform_device *pdev)
8c9054af 451+{
03acaa9b
JP
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;
8c9054af 458+
03acaa9b
JP
459+ tce = devm_kzalloc(dev, sizeof(*tce), GFP_KERNEL);
460+ if (!tce)
461+ return -ENOMEM;
8c9054af 462+
03acaa9b
JP
463+ tce->dev = &pdev->dev;
464+ mutex_init(&tce->lock);
465+ tce->mode = TYPEC_STATE_SAFE;
8c9054af 466+
03acaa9b
JP
467+ sw_desc.drvdata = tce;
468+ sw_desc.fwnode = dev->fwnode;
469+ sw_desc.set = typec_extcon_sw_set;
8c9054af 470+
03acaa9b
JP
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");
8c9054af 475+
03acaa9b
JP
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;
8c9054af 485+ }
8c9054af 486+
03acaa9b
JP
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;
8c9054af 497+ }
03acaa9b
JP
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;
8c9054af 503+ }
03acaa9b
JP
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;
8c9054af 509+ }
03acaa9b
JP
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;
8c9054af
JP
529+ }
530+
03acaa9b
JP
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");
8c9054af 573--
03acaa9b 5742.34.1
8c9054af 575
03acaa9b
JP
576From 4c839ce95766910235ff558b2959589c9068917c Mon Sep 17 00:00:00 2001
577From: Dan Johansen <strit@manjaro.org>
578Date: Sun, 2 Jan 2022 19:15:39 +0100
579Subject: [PATCH] arm64: dts: rockchip: add typec extcon hack
8c9054af 580
03acaa9b 581Signed-off-by: Dan Johansen <strit@manjaro.org>
8c9054af 582---
03acaa9b
JP
583 .../boot/dts/rockchip/rk3399-pinebook-pro.dts | 31 +++++++++++++++++--
584 1 file changed, 29 insertions(+), 2 deletions(-)
8c9054af 585
03acaa9b
JP
586diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
587index 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>;
ace9f2bf 637+ vdo = <0x0c0006>;
03acaa9b
JP
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 };
8c9054af 650
8c9054af 651--
03acaa9b 6522.34.1
8c9054af 653
This page took 0.432627 seconds and 4 git commands to generate.