1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2023, Linaro Ltd. All rights reserved.
4 */
5
6 #include <linux/err.h>
7 #include <linux/interrupt.h>
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/platform_device.h>
11 #include <linux/regmap.h>
12 #include <linux/regulator/consumer.h>
13 #include <linux/slab.h>
14 #include <linux/string_choices.h>
15 #include <linux/usb/pd.h>
16 #include <linux/usb/tcpm.h>
17 #include "qcom_pmic_typec.h"
18 #include "qcom_pmic_typec_pdphy.h"
19
20 /* PD PHY register offsets and bit fields */
21 #define USB_PDPHY_MSG_CONFIG_REG 0x40
22 #define MSG_CONFIG_PORT_DATA_ROLE BIT(3)
23 #define MSG_CONFIG_PORT_POWER_ROLE BIT(2)
24 #define MSG_CONFIG_SPEC_REV_MASK (BIT(1) | BIT(0))
25
26 #define USB_PDPHY_EN_CONTROL_REG 0x46
27 #define CONTROL_ENABLE BIT(0)
28
29 #define USB_PDPHY_RX_STATUS_REG 0x4A
30 #define RX_FRAME_TYPE (BIT(0) | BIT(1) | BIT(2))
31
32 #define USB_PDPHY_FRAME_FILTER_REG 0x4C
33 #define FRAME_FILTER_EN_HARD_RESET BIT(5)
34 #define FRAME_FILTER_EN_SOP BIT(0)
35
36 #define USB_PDPHY_TX_SIZE_REG 0x42
37 #define TX_SIZE_MASK 0xF
38
39 #define USB_PDPHY_TX_CONTROL_REG 0x44
40 #define TX_CONTROL_RETRY_COUNT(n) (((n) & 0x3) << 5)
41 #define TX_CONTROL_FRAME_TYPE(n) (((n) & 0x7) << 2)
42 #define TX_CONTROL_FRAME_TYPE_CABLE_RESET (0x1 << 2)
43 #define TX_CONTROL_SEND_SIGNAL BIT(1)
44 #define TX_CONTROL_SEND_MSG BIT(0)
45
46 #define USB_PDPHY_RX_SIZE_REG 0x48
47
48 #define USB_PDPHY_RX_ACKNOWLEDGE_REG 0x4B
49 #define RX_BUFFER_TOKEN BIT(0)
50
51 #define USB_PDPHY_BIST_MODE_REG 0x4E
52 #define BIST_MODE_MASK 0xF
53 #define BIST_ENABLE BIT(7)
54 #define PD_MSG_BIST 0x3
55 #define PD_BIST_TEST_DATA_MODE 0x8
56
57 #define USB_PDPHY_TX_BUFFER_HDR_REG 0x60
58 #define USB_PDPHY_TX_BUFFER_DATA_REG 0x62
59
60 #define USB_PDPHY_RX_BUFFER_REG 0x80
61
62 /* VDD regulator */
63 #define VDD_PDPHY_VOL_MIN 2800000 /* uV */
64 #define VDD_PDPHY_VOL_MAX 3300000 /* uV */
65 #define VDD_PDPHY_HPM_LOAD 3000 /* uA */
66
67 /* Message Spec Rev field */
68 #define PD_MSG_HDR_REV(hdr) (((hdr) >> 6) & 3)
69
70 /* timers */
71 #define RECEIVER_RESPONSE_TIME 15 /* tReceiverResponse */
72 #define HARD_RESET_COMPLETE_TIME 5 /* tHardResetComplete */
73
74 /* Interrupt numbers */
75 #define PMIC_PDPHY_SIG_TX_IRQ 0x0
76 #define PMIC_PDPHY_SIG_RX_IRQ 0x1
77 #define PMIC_PDPHY_MSG_TX_IRQ 0x2
78 #define PMIC_PDPHY_MSG_RX_IRQ 0x3
79 #define PMIC_PDPHY_MSG_TX_FAIL_IRQ 0x4
80 #define PMIC_PDPHY_MSG_TX_DISCARD_IRQ 0x5
81 #define PMIC_PDPHY_MSG_RX_DISCARD_IRQ 0x6
82 #define PMIC_PDPHY_FR_SWAP_IRQ 0x7
83
84
85 struct pmic_typec_pdphy_irq_data {
86 int virq;
87 int irq;
88 struct pmic_typec_pdphy *pmic_typec_pdphy;
89 };
90
91 struct pmic_typec_pdphy {
92 struct device *dev;
93 struct tcpm_port *tcpm_port;
94 struct regmap *regmap;
95 u32 base;
96
97 unsigned int nr_irqs;
98 struct pmic_typec_pdphy_irq_data *irq_data;
99
100 struct work_struct reset_work;
101 struct work_struct receive_work;
102 struct regulator *vdd_pdphy;
103 spinlock_t lock; /* Register atomicity */
104 };
105
qcom_pmic_typec_pdphy_reset_on(struct pmic_typec_pdphy * pmic_typec_pdphy)106 static void qcom_pmic_typec_pdphy_reset_on(struct pmic_typec_pdphy *pmic_typec_pdphy)
107 {
108 struct device *dev = pmic_typec_pdphy->dev;
109 int ret;
110
111 /* Terminate TX */
112 ret = regmap_write(pmic_typec_pdphy->regmap,
113 pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, 0);
114 if (ret)
115 goto err;
116
117 ret = regmap_write(pmic_typec_pdphy->regmap,
118 pmic_typec_pdphy->base + USB_PDPHY_FRAME_FILTER_REG, 0);
119 if (ret)
120 goto err;
121
122 return;
123 err:
124 dev_err(dev, "pd_reset_on error\n");
125 }
126
qcom_pmic_typec_pdphy_reset_off(struct pmic_typec_pdphy * pmic_typec_pdphy)127 static void qcom_pmic_typec_pdphy_reset_off(struct pmic_typec_pdphy *pmic_typec_pdphy)
128 {
129 struct device *dev = pmic_typec_pdphy->dev;
130 int ret;
131
132 ret = regmap_write(pmic_typec_pdphy->regmap,
133 pmic_typec_pdphy->base + USB_PDPHY_FRAME_FILTER_REG,
134 FRAME_FILTER_EN_SOP | FRAME_FILTER_EN_HARD_RESET);
135 if (ret)
136 dev_err(dev, "pd_reset_off error\n");
137 }
138
qcom_pmic_typec_pdphy_sig_reset_work(struct work_struct * work)139 static void qcom_pmic_typec_pdphy_sig_reset_work(struct work_struct *work)
140 {
141 struct pmic_typec_pdphy *pmic_typec_pdphy = container_of(work, struct pmic_typec_pdphy,
142 reset_work);
143 unsigned long flags;
144
145 spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
146
147 qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy);
148 qcom_pmic_typec_pdphy_reset_off(pmic_typec_pdphy);
149
150 spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
151
152 tcpm_pd_hard_reset(pmic_typec_pdphy->tcpm_port);
153 }
154
155 static int
qcom_pmic_typec_pdphy_clear_tx_control_reg(struct pmic_typec_pdphy * pmic_typec_pdphy)156 qcom_pmic_typec_pdphy_clear_tx_control_reg(struct pmic_typec_pdphy *pmic_typec_pdphy)
157 {
158 struct device *dev = pmic_typec_pdphy->dev;
159 unsigned int val;
160 int ret;
161
162 /* Clear TX control register */
163 ret = regmap_write(pmic_typec_pdphy->regmap,
164 pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, 0);
165 if (ret)
166 goto done;
167
168 /* Perform readback to ensure sufficient delay for command to latch */
169 ret = regmap_read(pmic_typec_pdphy->regmap,
170 pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, &val);
171
172 done:
173 if (ret)
174 dev_err(dev, "pd_clear_tx_control_reg: clear tx flag\n");
175
176 return ret;
177 }
178
179 static int
qcom_pmic_typec_pdphy_pd_transmit_signal(struct pmic_typec_pdphy * pmic_typec_pdphy,enum tcpm_transmit_type type,unsigned int negotiated_rev)180 qcom_pmic_typec_pdphy_pd_transmit_signal(struct pmic_typec_pdphy *pmic_typec_pdphy,
181 enum tcpm_transmit_type type,
182 unsigned int negotiated_rev)
183 {
184 struct device *dev = pmic_typec_pdphy->dev;
185 unsigned int val;
186 unsigned long flags;
187 int ret;
188
189 spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
190
191 /* Clear TX control register */
192 ret = qcom_pmic_typec_pdphy_clear_tx_control_reg(pmic_typec_pdphy);
193 if (ret)
194 goto done;
195
196 val = TX_CONTROL_SEND_SIGNAL;
197 if (negotiated_rev == PD_REV30)
198 val |= TX_CONTROL_RETRY_COUNT(2);
199 else
200 val |= TX_CONTROL_RETRY_COUNT(3);
201
202 if (type == TCPC_TX_CABLE_RESET || type == TCPC_TX_HARD_RESET)
203 val |= TX_CONTROL_FRAME_TYPE(1);
204
205 ret = regmap_write(pmic_typec_pdphy->regmap,
206 pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, val);
207
208 done:
209 spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
210
211 dev_vdbg(dev, "pd_transmit_signal: type %d negotiate_rev %d send %d\n",
212 type, negotiated_rev, ret);
213
214 return ret;
215 }
216
217 static int
qcom_pmic_typec_pdphy_pd_transmit_payload(struct pmic_typec_pdphy * pmic_typec_pdphy,enum tcpm_transmit_type type,const struct pd_message * msg,unsigned int negotiated_rev)218 qcom_pmic_typec_pdphy_pd_transmit_payload(struct pmic_typec_pdphy *pmic_typec_pdphy,
219 enum tcpm_transmit_type type,
220 const struct pd_message *msg,
221 unsigned int negotiated_rev)
222 {
223 struct device *dev = pmic_typec_pdphy->dev;
224 unsigned int val, hdr_len, txbuf_len, txsize_len;
225 unsigned long flags;
226 int ret;
227
228 spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
229
230 hdr_len = sizeof(msg->header);
231 txbuf_len = pd_header_cnt_le(msg->header) * 4;
232 txsize_len = hdr_len + txbuf_len - 1;
233
234 ret = regmap_read(pmic_typec_pdphy->regmap,
235 pmic_typec_pdphy->base + USB_PDPHY_RX_ACKNOWLEDGE_REG,
236 &val);
237 if (ret)
238 goto done;
239
240 if (val) {
241 dev_err(dev, "pd_transmit_payload: RX message pending\n");
242 ret = -EBUSY;
243 goto done;
244 }
245
246 /* Clear TX control register */
247 ret = qcom_pmic_typec_pdphy_clear_tx_control_reg(pmic_typec_pdphy);
248 if (ret)
249 goto done;
250
251 /* Write message header sizeof(u16) to USB_PDPHY_TX_BUFFER_HDR_REG */
252 ret = regmap_bulk_write(pmic_typec_pdphy->regmap,
253 pmic_typec_pdphy->base + USB_PDPHY_TX_BUFFER_HDR_REG,
254 &msg->header, hdr_len);
255 if (ret)
256 goto done;
257
258 /* Write payload to USB_PDPHY_TX_BUFFER_DATA_REG for txbuf_len */
259 if (txbuf_len) {
260 ret = regmap_bulk_write(pmic_typec_pdphy->regmap,
261 pmic_typec_pdphy->base + USB_PDPHY_TX_BUFFER_DATA_REG,
262 &msg->payload, txbuf_len);
263 if (ret)
264 goto done;
265 }
266
267 /* Write total length ((header + data) - 1) to USB_PDPHY_TX_SIZE_REG */
268 ret = regmap_write(pmic_typec_pdphy->regmap,
269 pmic_typec_pdphy->base + USB_PDPHY_TX_SIZE_REG,
270 txsize_len);
271 if (ret)
272 goto done;
273
274 /* Clear TX control register */
275 ret = qcom_pmic_typec_pdphy_clear_tx_control_reg(pmic_typec_pdphy);
276 if (ret)
277 goto done;
278
279 /* Initiate transmit with retry count as indicated by PD revision */
280 val = TX_CONTROL_FRAME_TYPE(type) | TX_CONTROL_SEND_MSG;
281 if (pd_header_rev(msg->header) == PD_REV30)
282 val |= TX_CONTROL_RETRY_COUNT(2);
283 else
284 val |= TX_CONTROL_RETRY_COUNT(3);
285
286 ret = regmap_write(pmic_typec_pdphy->regmap,
287 pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, val);
288
289 done:
290 spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
291
292 if (ret) {
293 dev_err(dev, "pd_transmit_payload: hdr %*ph data %*ph ret %d\n",
294 hdr_len, &msg->header, txbuf_len, &msg->payload, ret);
295 }
296
297 return ret;
298 }
299
qcom_pmic_typec_pdphy_pd_transmit(struct tcpc_dev * tcpc,enum tcpm_transmit_type type,const struct pd_message * msg,unsigned int negotiated_rev)300 static int qcom_pmic_typec_pdphy_pd_transmit(struct tcpc_dev *tcpc,
301 enum tcpm_transmit_type type,
302 const struct pd_message *msg,
303 unsigned int negotiated_rev)
304 {
305 struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
306 struct pmic_typec_pdphy *pmic_typec_pdphy = tcpm->pmic_typec_pdphy;
307 struct device *dev = pmic_typec_pdphy->dev;
308 int ret;
309
310 if (msg) {
311 ret = qcom_pmic_typec_pdphy_pd_transmit_payload(pmic_typec_pdphy,
312 type, msg,
313 negotiated_rev);
314 } else {
315 ret = qcom_pmic_typec_pdphy_pd_transmit_signal(pmic_typec_pdphy,
316 type,
317 negotiated_rev);
318 }
319
320 if (ret)
321 dev_dbg(dev, "pd_transmit: type %x result %d\n", type, ret);
322
323 return ret;
324 }
325
qcom_pmic_typec_pdphy_pd_receive(struct pmic_typec_pdphy * pmic_typec_pdphy)326 static void qcom_pmic_typec_pdphy_pd_receive(struct pmic_typec_pdphy *pmic_typec_pdphy)
327 {
328 struct device *dev = pmic_typec_pdphy->dev;
329 struct pd_message msg;
330 unsigned int size, rx_status;
331 unsigned long flags;
332 int ret;
333
334 spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
335
336 ret = regmap_read(pmic_typec_pdphy->regmap,
337 pmic_typec_pdphy->base + USB_PDPHY_RX_SIZE_REG, &size);
338 if (ret)
339 goto done;
340
341 /* Hardware requires +1 of the real read value to be passed */
342 if (size < 1 || size > sizeof(msg.payload) + 1) {
343 dev_dbg(dev, "pd_receive: invalid size %d\n", size);
344 goto done;
345 }
346
347 size += 1;
348 ret = regmap_read(pmic_typec_pdphy->regmap,
349 pmic_typec_pdphy->base + USB_PDPHY_RX_STATUS_REG,
350 &rx_status);
351
352 if (ret)
353 goto done;
354
355 ret = regmap_bulk_read(pmic_typec_pdphy->regmap,
356 pmic_typec_pdphy->base + USB_PDPHY_RX_BUFFER_REG,
357 (u8 *)&msg, size);
358 if (ret)
359 goto done;
360
361 /* Return ownership of RX buffer to hardware */
362 ret = regmap_write(pmic_typec_pdphy->regmap,
363 pmic_typec_pdphy->base + USB_PDPHY_RX_ACKNOWLEDGE_REG, 0);
364
365 done:
366 spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
367
368 if (!ret) {
369 dev_vdbg(dev, "pd_receive: handing %d bytes to tcpm\n", size);
370 tcpm_pd_receive(pmic_typec_pdphy->tcpm_port, &msg, TCPC_TX_SOP);
371 }
372 }
373
qcom_pmic_typec_pdphy_isr(int irq,void * dev_id)374 static irqreturn_t qcom_pmic_typec_pdphy_isr(int irq, void *dev_id)
375 {
376 struct pmic_typec_pdphy_irq_data *irq_data = dev_id;
377 struct pmic_typec_pdphy *pmic_typec_pdphy = irq_data->pmic_typec_pdphy;
378 struct device *dev = pmic_typec_pdphy->dev;
379
380 switch (irq_data->virq) {
381 case PMIC_PDPHY_SIG_TX_IRQ:
382 dev_err(dev, "isr: tx_sig\n");
383 break;
384 case PMIC_PDPHY_SIG_RX_IRQ:
385 schedule_work(&pmic_typec_pdphy->reset_work);
386 break;
387 case PMIC_PDPHY_MSG_TX_IRQ:
388 tcpm_pd_transmit_complete(pmic_typec_pdphy->tcpm_port,
389 TCPC_TX_SUCCESS);
390 break;
391 case PMIC_PDPHY_MSG_RX_IRQ:
392 qcom_pmic_typec_pdphy_pd_receive(pmic_typec_pdphy);
393 break;
394 case PMIC_PDPHY_MSG_TX_FAIL_IRQ:
395 tcpm_pd_transmit_complete(pmic_typec_pdphy->tcpm_port,
396 TCPC_TX_FAILED);
397 break;
398 case PMIC_PDPHY_MSG_TX_DISCARD_IRQ:
399 tcpm_pd_transmit_complete(pmic_typec_pdphy->tcpm_port,
400 TCPC_TX_DISCARDED);
401 break;
402 }
403
404 return IRQ_HANDLED;
405 }
406
qcom_pmic_typec_pdphy_set_pd_rx(struct tcpc_dev * tcpc,bool on)407 static int qcom_pmic_typec_pdphy_set_pd_rx(struct tcpc_dev *tcpc, bool on)
408 {
409 struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
410 struct pmic_typec_pdphy *pmic_typec_pdphy = tcpm->pmic_typec_pdphy;
411 unsigned long flags;
412 int ret;
413
414 spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
415
416 ret = regmap_write(pmic_typec_pdphy->regmap,
417 pmic_typec_pdphy->base + USB_PDPHY_RX_ACKNOWLEDGE_REG, !on);
418
419 spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
420
421 dev_dbg(pmic_typec_pdphy->dev, "set_pd_rx: %s\n", str_on_off(on));
422
423 return ret;
424 }
425
qcom_pmic_typec_pdphy_set_roles(struct tcpc_dev * tcpc,bool attached,enum typec_role power_role,enum typec_data_role data_role)426 static int qcom_pmic_typec_pdphy_set_roles(struct tcpc_dev *tcpc, bool attached,
427 enum typec_role power_role,
428 enum typec_data_role data_role)
429 {
430 struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
431 struct pmic_typec_pdphy *pmic_typec_pdphy = tcpm->pmic_typec_pdphy;
432 struct device *dev = pmic_typec_pdphy->dev;
433 unsigned long flags;
434 int ret;
435
436 spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
437
438 ret = regmap_update_bits(pmic_typec_pdphy->regmap,
439 pmic_typec_pdphy->base + USB_PDPHY_MSG_CONFIG_REG,
440 MSG_CONFIG_PORT_DATA_ROLE |
441 MSG_CONFIG_PORT_POWER_ROLE,
442 (data_role == TYPEC_HOST ? MSG_CONFIG_PORT_DATA_ROLE : 0) |
443 (power_role == TYPEC_SOURCE ? MSG_CONFIG_PORT_POWER_ROLE : 0));
444
445 spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
446
447 dev_dbg(dev, "pdphy_set_roles: data_role_host=%d power_role_src=%d\n",
448 data_role, power_role);
449
450 return ret;
451 }
452
qcom_pmic_typec_pdphy_enable(struct pmic_typec_pdphy * pmic_typec_pdphy)453 static int qcom_pmic_typec_pdphy_enable(struct pmic_typec_pdphy *pmic_typec_pdphy)
454 {
455 struct device *dev = pmic_typec_pdphy->dev;
456 int ret;
457
458 /* PD 2.0, DR=TYPEC_DEVICE, PR=TYPEC_SINK */
459 ret = regmap_update_bits(pmic_typec_pdphy->regmap,
460 pmic_typec_pdphy->base + USB_PDPHY_MSG_CONFIG_REG,
461 MSG_CONFIG_SPEC_REV_MASK, PD_REV20);
462 if (ret)
463 goto done;
464
465 ret = regmap_write(pmic_typec_pdphy->regmap,
466 pmic_typec_pdphy->base + USB_PDPHY_EN_CONTROL_REG, 0);
467 if (ret)
468 goto done;
469
470 ret = regmap_write(pmic_typec_pdphy->regmap,
471 pmic_typec_pdphy->base + USB_PDPHY_EN_CONTROL_REG,
472 CONTROL_ENABLE);
473 if (ret)
474 goto done;
475
476 qcom_pmic_typec_pdphy_reset_off(pmic_typec_pdphy);
477 done:
478 if (ret)
479 dev_err(dev, "pdphy_enable fail %d\n", ret);
480
481 return ret;
482 }
483
qcom_pmic_typec_pdphy_disable(struct pmic_typec_pdphy * pmic_typec_pdphy)484 static int qcom_pmic_typec_pdphy_disable(struct pmic_typec_pdphy *pmic_typec_pdphy)
485 {
486 int ret;
487
488 qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy);
489
490 ret = regmap_write(pmic_typec_pdphy->regmap,
491 pmic_typec_pdphy->base + USB_PDPHY_EN_CONTROL_REG, 0);
492
493 return ret;
494 }
495
pmic_typec_pdphy_reset(struct pmic_typec_pdphy * pmic_typec_pdphy)496 static int pmic_typec_pdphy_reset(struct pmic_typec_pdphy *pmic_typec_pdphy)
497 {
498 int ret;
499
500 ret = qcom_pmic_typec_pdphy_disable(pmic_typec_pdphy);
501 if (ret)
502 goto done;
503
504 usleep_range(400, 500);
505 ret = qcom_pmic_typec_pdphy_enable(pmic_typec_pdphy);
506 done:
507 return ret;
508 }
509
qcom_pmic_typec_pdphy_start(struct pmic_typec * tcpm,struct tcpm_port * tcpm_port)510 static int qcom_pmic_typec_pdphy_start(struct pmic_typec *tcpm,
511 struct tcpm_port *tcpm_port)
512 {
513 struct pmic_typec_pdphy *pmic_typec_pdphy = tcpm->pmic_typec_pdphy;
514 int i;
515 int ret;
516
517 ret = regulator_enable(pmic_typec_pdphy->vdd_pdphy);
518 if (ret)
519 return ret;
520
521 pmic_typec_pdphy->tcpm_port = tcpm_port;
522
523 ret = pmic_typec_pdphy_reset(pmic_typec_pdphy);
524 if (ret)
525 goto err_disable_vdd_pdhy;
526
527 for (i = 0; i < pmic_typec_pdphy->nr_irqs; i++)
528 enable_irq(pmic_typec_pdphy->irq_data[i].irq);
529
530 return 0;
531
532 err_disable_vdd_pdhy:
533 regulator_disable(pmic_typec_pdphy->vdd_pdphy);
534
535 return ret;
536 }
537
qcom_pmic_typec_pdphy_stop(struct pmic_typec * tcpm)538 static void qcom_pmic_typec_pdphy_stop(struct pmic_typec *tcpm)
539 {
540 struct pmic_typec_pdphy *pmic_typec_pdphy = tcpm->pmic_typec_pdphy;
541 int i;
542
543 for (i = 0; i < pmic_typec_pdphy->nr_irqs; i++)
544 disable_irq(pmic_typec_pdphy->irq_data[i].irq);
545
546 cancel_work_sync(&pmic_typec_pdphy->reset_work);
547
548 qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy);
549
550 regulator_disable(pmic_typec_pdphy->vdd_pdphy);
551 }
552
qcom_pmic_typec_pdphy_probe(struct platform_device * pdev,struct pmic_typec * tcpm,const struct pmic_typec_pdphy_resources * res,struct regmap * regmap,u32 base)553 int qcom_pmic_typec_pdphy_probe(struct platform_device *pdev,
554 struct pmic_typec *tcpm,
555 const struct pmic_typec_pdphy_resources *res,
556 struct regmap *regmap,
557 u32 base)
558 {
559 struct pmic_typec_pdphy *pmic_typec_pdphy;
560 struct device *dev = &pdev->dev;
561 struct pmic_typec_pdphy_irq_data *irq_data;
562 int i, ret, irq;
563
564 pmic_typec_pdphy = devm_kzalloc(dev, sizeof(*pmic_typec_pdphy), GFP_KERNEL);
565 if (!pmic_typec_pdphy)
566 return -ENOMEM;
567
568 if (!res->nr_irqs || res->nr_irqs > PMIC_PDPHY_MAX_IRQS)
569 return -EINVAL;
570
571 irq_data = devm_kcalloc(dev, res->nr_irqs, sizeof(*irq_data),
572 GFP_KERNEL);
573 if (!irq_data)
574 return -ENOMEM;
575
576 pmic_typec_pdphy->vdd_pdphy = devm_regulator_get(dev, "vdd-pdphy");
577 if (IS_ERR(pmic_typec_pdphy->vdd_pdphy))
578 return PTR_ERR(pmic_typec_pdphy->vdd_pdphy);
579
580 pmic_typec_pdphy->dev = dev;
581 pmic_typec_pdphy->base = base;
582 pmic_typec_pdphy->regmap = regmap;
583 pmic_typec_pdphy->nr_irqs = res->nr_irqs;
584 pmic_typec_pdphy->irq_data = irq_data;
585 spin_lock_init(&pmic_typec_pdphy->lock);
586 INIT_WORK(&pmic_typec_pdphy->reset_work, qcom_pmic_typec_pdphy_sig_reset_work);
587
588 for (i = 0; i < res->nr_irqs; i++, irq_data++) {
589 irq = platform_get_irq_byname(pdev, res->irq_params[i].irq_name);
590 if (irq < 0)
591 return irq;
592
593 irq_data->pmic_typec_pdphy = pmic_typec_pdphy;
594 irq_data->irq = irq;
595 irq_data->virq = res->irq_params[i].virq;
596
597 ret = devm_request_threaded_irq(dev, irq, NULL,
598 qcom_pmic_typec_pdphy_isr,
599 IRQF_ONESHOT | IRQF_NO_AUTOEN,
600 res->irq_params[i].irq_name,
601 irq_data);
602 if (ret)
603 return ret;
604 }
605
606 tcpm->pmic_typec_pdphy = pmic_typec_pdphy;
607
608 tcpm->tcpc.set_pd_rx = qcom_pmic_typec_pdphy_set_pd_rx;
609 tcpm->tcpc.set_roles = qcom_pmic_typec_pdphy_set_roles;
610 tcpm->tcpc.pd_transmit = qcom_pmic_typec_pdphy_pd_transmit;
611
612 tcpm->pdphy_start = qcom_pmic_typec_pdphy_start;
613 tcpm->pdphy_stop = qcom_pmic_typec_pdphy_stop;
614
615 return 0;
616 }
617
618 const struct pmic_typec_pdphy_resources pm8150b_pdphy_res = {
619 .irq_params = {
620 {
621 .virq = PMIC_PDPHY_SIG_TX_IRQ,
622 .irq_name = "sig-tx",
623 },
624 {
625 .virq = PMIC_PDPHY_SIG_RX_IRQ,
626 .irq_name = "sig-rx",
627 },
628 {
629 .virq = PMIC_PDPHY_MSG_TX_IRQ,
630 .irq_name = "msg-tx",
631 },
632 {
633 .virq = PMIC_PDPHY_MSG_RX_IRQ,
634 .irq_name = "msg-rx",
635 },
636 {
637 .virq = PMIC_PDPHY_MSG_TX_FAIL_IRQ,
638 .irq_name = "msg-tx-failed",
639 },
640 {
641 .virq = PMIC_PDPHY_MSG_TX_DISCARD_IRQ,
642 .irq_name = "msg-tx-discarded",
643 },
644 {
645 .virq = PMIC_PDPHY_MSG_RX_DISCARD_IRQ,
646 .irq_name = "msg-rx-discarded",
647 },
648 },
649 .nr_irqs = 7,
650 };
651