blob: f5992ec7eeb7f42a19aeb9edc8dca8a434707278 [file] [log] [blame]
Loic Poulain855a70c2020-10-21 19:18:19 +02001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * MHI PCI driver - MHI over PCI controller driver
4 *
5 * This module is a generic driver for registering MHI-over-PCI devices,
6 * such as PCIe QCOM modems.
7 *
8 * Copyright (C) 2020 Linaro Ltd <loic.poulain@linaro.org>
9 */
10
Loic Poulainb012ee62021-01-04 17:14:55 +010011#include <linux/aer.h>
Loic Poulain8ccc3272021-01-04 17:14:53 +010012#include <linux/delay.h>
Loic Poulain855a70c2020-10-21 19:18:19 +020013#include <linux/device.h>
14#include <linux/mhi.h>
15#include <linux/module.h>
16#include <linux/pci.h>
Loic Poulaind3800c12021-03-05 20:16:48 +010017#include <linux/pm_runtime.h>
Loic Poulain8562d4f2021-01-04 17:14:56 +010018#include <linux/timer.h>
Loic Poulain73893372021-01-04 17:14:54 +010019#include <linux/workqueue.h>
Loic Poulain855a70c2020-10-21 19:18:19 +020020
21#define MHI_PCI_DEFAULT_BAR_NUM 0
22
Loic Poulain8ccc3272021-01-04 17:14:53 +010023#define MHI_POST_RESET_DELAY_MS 500
Loic Poulain8562d4f2021-01-04 17:14:56 +010024
25#define HEALTH_CHECK_PERIOD (HZ * 2)
26
Loic Poulain855a70c2020-10-21 19:18:19 +020027/**
28 * struct mhi_pci_dev_info - MHI PCI device specific information
29 * @config: MHI controller configuration
30 * @name: name of the PCI module
31 * @fw: firmware path (if any)
32 * @edl: emergency download mode firmware path (if any)
33 * @bar_num: PCI base address register to use for MHI MMIO register space
34 * @dma_data_width: DMA transfer word size (32 or 64 bits)
35 */
36struct mhi_pci_dev_info {
37 const struct mhi_controller_config *config;
38 const char *name;
39 const char *fw;
40 const char *edl;
41 unsigned int bar_num;
42 unsigned int dma_data_width;
43};
44
45#define MHI_CHANNEL_CONFIG_UL(ch_num, ch_name, el_count, ev_ring) \
46 { \
47 .num = ch_num, \
48 .name = ch_name, \
49 .num_elements = el_count, \
50 .event_ring = ev_ring, \
51 .dir = DMA_TO_DEVICE, \
52 .ee_mask = BIT(MHI_EE_AMSS), \
53 .pollcfg = 0, \
54 .doorbell = MHI_DB_BRST_DISABLE, \
55 .lpm_notify = false, \
56 .offload_channel = false, \
57 .doorbell_mode_switch = false, \
58 } \
59
60#define MHI_CHANNEL_CONFIG_DL(ch_num, ch_name, el_count, ev_ring) \
61 { \
62 .num = ch_num, \
63 .name = ch_name, \
64 .num_elements = el_count, \
65 .event_ring = ev_ring, \
66 .dir = DMA_FROM_DEVICE, \
67 .ee_mask = BIT(MHI_EE_AMSS), \
68 .pollcfg = 0, \
69 .doorbell = MHI_DB_BRST_DISABLE, \
70 .lpm_notify = false, \
71 .offload_channel = false, \
72 .doorbell_mode_switch = false, \
73 }
74
Loic Poulain9ea48ef2021-03-05 20:16:43 +010075#define MHI_EVENT_CONFIG_CTRL(ev_ring, el_count) \
Loic Poulain855a70c2020-10-21 19:18:19 +020076 { \
Loic Poulain9ea48ef2021-03-05 20:16:43 +010077 .num_elements = el_count, \
Loic Poulain855a70c2020-10-21 19:18:19 +020078 .irq_moderation_ms = 0, \
79 .irq = (ev_ring) + 1, \
80 .priority = 1, \
81 .mode = MHI_DB_BRST_DISABLE, \
82 .data_type = MHI_ER_CTRL, \
83 .hardware_event = false, \
84 .client_managed = false, \
85 .offload_channel = false, \
86 }
87
Loic Poulaineb967872021-01-04 17:14:52 +010088#define MHI_CHANNEL_CONFIG_HW_UL(ch_num, ch_name, el_count, ev_ring) \
89 { \
90 .num = ch_num, \
91 .name = ch_name, \
92 .num_elements = el_count, \
93 .event_ring = ev_ring, \
94 .dir = DMA_TO_DEVICE, \
95 .ee_mask = BIT(MHI_EE_AMSS), \
96 .pollcfg = 0, \
97 .doorbell = MHI_DB_BRST_ENABLE, \
98 .lpm_notify = false, \
99 .offload_channel = false, \
100 .doorbell_mode_switch = true, \
101 } \
102
103#define MHI_CHANNEL_CONFIG_HW_DL(ch_num, ch_name, el_count, ev_ring) \
104 { \
105 .num = ch_num, \
106 .name = ch_name, \
107 .num_elements = el_count, \
108 .event_ring = ev_ring, \
109 .dir = DMA_FROM_DEVICE, \
110 .ee_mask = BIT(MHI_EE_AMSS), \
111 .pollcfg = 0, \
112 .doorbell = MHI_DB_BRST_ENABLE, \
113 .lpm_notify = false, \
114 .offload_channel = false, \
115 .doorbell_mode_switch = true, \
116 }
117
Loic Poulainac4bf602021-03-05 20:16:44 +0100118#define MHI_CHANNEL_CONFIG_UL_SBL(ch_num, ch_name, el_count, ev_ring) \
119 { \
120 .num = ch_num, \
121 .name = ch_name, \
122 .num_elements = el_count, \
123 .event_ring = ev_ring, \
124 .dir = DMA_TO_DEVICE, \
125 .ee_mask = BIT(MHI_EE_SBL), \
126 .pollcfg = 0, \
127 .doorbell = MHI_DB_BRST_DISABLE, \
128 .lpm_notify = false, \
129 .offload_channel = false, \
130 .doorbell_mode_switch = false, \
131 } \
132
133#define MHI_CHANNEL_CONFIG_DL_SBL(ch_num, ch_name, el_count, ev_ring) \
134 { \
135 .num = ch_num, \
136 .name = ch_name, \
137 .num_elements = el_count, \
138 .event_ring = ev_ring, \
139 .dir = DMA_FROM_DEVICE, \
140 .ee_mask = BIT(MHI_EE_SBL), \
141 .pollcfg = 0, \
142 .doorbell = MHI_DB_BRST_DISABLE, \
143 .lpm_notify = false, \
144 .offload_channel = false, \
145 .doorbell_mode_switch = false, \
146 }
147
Loic Poulain9ea48ef2021-03-05 20:16:43 +0100148#define MHI_EVENT_CONFIG_DATA(ev_ring, el_count) \
Loic Poulain855a70c2020-10-21 19:18:19 +0200149 { \
Loic Poulain9ea48ef2021-03-05 20:16:43 +0100150 .num_elements = el_count, \
Loic Poulain855a70c2020-10-21 19:18:19 +0200151 .irq_moderation_ms = 5, \
152 .irq = (ev_ring) + 1, \
153 .priority = 1, \
154 .mode = MHI_DB_BRST_DISABLE, \
155 .data_type = MHI_ER_DATA, \
156 .hardware_event = false, \
157 .client_managed = false, \
158 .offload_channel = false, \
159 }
160
Loic Poulain9ea48ef2021-03-05 20:16:43 +0100161#define MHI_EVENT_CONFIG_HW_DATA(ev_ring, el_count, ch_num) \
Loic Poulain855a70c2020-10-21 19:18:19 +0200162 { \
Loic Poulain9ea48ef2021-03-05 20:16:43 +0100163 .num_elements = el_count, \
Loic Poulainec7513692021-01-04 17:14:59 +0100164 .irq_moderation_ms = 1, \
Loic Poulain855a70c2020-10-21 19:18:19 +0200165 .irq = (ev_ring) + 1, \
166 .priority = 1, \
167 .mode = MHI_DB_BRST_DISABLE, \
168 .data_type = MHI_ER_DATA, \
169 .hardware_event = true, \
170 .client_managed = false, \
171 .offload_channel = false, \
172 .channel = ch_num, \
173 }
174
175static const struct mhi_channel_config modem_qcom_v1_mhi_channels[] = {
Loic Poulain4da3d072021-01-04 17:14:58 +0100176 MHI_CHANNEL_CONFIG_UL(4, "DIAG", 16, 1),
177 MHI_CHANNEL_CONFIG_DL(5, "DIAG", 16, 1),
Loic Poulain855a70c2020-10-21 19:18:19 +0200178 MHI_CHANNEL_CONFIG_UL(12, "MBIM", 4, 0),
179 MHI_CHANNEL_CONFIG_DL(13, "MBIM", 4, 0),
180 MHI_CHANNEL_CONFIG_UL(14, "QMI", 4, 0),
181 MHI_CHANNEL_CONFIG_DL(15, "QMI", 4, 0),
182 MHI_CHANNEL_CONFIG_UL(20, "IPCR", 8, 0),
183 MHI_CHANNEL_CONFIG_DL(21, "IPCR", 8, 0),
Loic Poulain4da3d072021-01-04 17:14:58 +0100184 MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0", 128, 2),
185 MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0", 128, 3),
Loic Poulain855a70c2020-10-21 19:18:19 +0200186};
187
Loic Poulainb91c3b32021-01-05 17:44:36 +0100188static struct mhi_event_config modem_qcom_v1_mhi_events[] = {
Loic Poulain855a70c2020-10-21 19:18:19 +0200189 /* first ring is control+data ring */
Loic Poulain9ea48ef2021-03-05 20:16:43 +0100190 MHI_EVENT_CONFIG_CTRL(0, 64),
Loic Poulain4da3d072021-01-04 17:14:58 +0100191 /* DIAG dedicated event ring */
Loic Poulain9ea48ef2021-03-05 20:16:43 +0100192 MHI_EVENT_CONFIG_DATA(1, 128),
Loic Poulain855a70c2020-10-21 19:18:19 +0200193 /* Hardware channels request dedicated hardware event rings */
Loic Poulain9ea48ef2021-03-05 20:16:43 +0100194 MHI_EVENT_CONFIG_HW_DATA(2, 1024, 100),
195 MHI_EVENT_CONFIG_HW_DATA(3, 2048, 101)
Loic Poulain855a70c2020-10-21 19:18:19 +0200196};
197
Loic Poulainb91c3b32021-01-05 17:44:36 +0100198static struct mhi_controller_config modem_qcom_v1_mhiv_config = {
Loic Poulain855a70c2020-10-21 19:18:19 +0200199 .max_channels = 128,
Loic Poulain84026a52021-01-04 17:14:57 +0100200 .timeout_ms = 8000,
Loic Poulain855a70c2020-10-21 19:18:19 +0200201 .num_channels = ARRAY_SIZE(modem_qcom_v1_mhi_channels),
202 .ch_cfg = modem_qcom_v1_mhi_channels,
203 .num_events = ARRAY_SIZE(modem_qcom_v1_mhi_events),
204 .event_cfg = modem_qcom_v1_mhi_events,
205};
206
Bhaumik Bhatt49d38eb2021-04-02 14:33:19 -0700207static const struct mhi_pci_dev_info mhi_qcom_sdx65_info = {
208 .name = "qcom-sdx65m",
209 .fw = "qcom/sdx65m/xbl.elf",
210 .edl = "qcom/sdx65m/edl.mbn",
211 .config = &modem_qcom_v1_mhiv_config,
212 .bar_num = MHI_PCI_DEFAULT_BAR_NUM,
213 .dma_data_width = 32
214};
215
Loic Poulain855a70c2020-10-21 19:18:19 +0200216static const struct mhi_pci_dev_info mhi_qcom_sdx55_info = {
217 .name = "qcom-sdx55m",
218 .fw = "qcom/sdx55m/sbl1.mbn",
219 .edl = "qcom/sdx55m/edl.mbn",
220 .config = &modem_qcom_v1_mhiv_config,
221 .bar_num = MHI_PCI_DEFAULT_BAR_NUM,
222 .dma_data_width = 32
223};
224
Loic Poulain59d05b72021-03-05 20:16:45 +0100225static const struct mhi_pci_dev_info mhi_qcom_sdx24_info = {
226 .name = "qcom-sdx24",
227 .edl = "qcom/prog_firehose_sdx24.mbn",
228 .config = &modem_qcom_v1_mhiv_config,
229 .bar_num = MHI_PCI_DEFAULT_BAR_NUM,
230 .dma_data_width = 32
231};
232
Loic Poulainac4bf602021-03-05 20:16:44 +0100233static const struct mhi_channel_config mhi_quectel_em1xx_channels[] = {
234 MHI_CHANNEL_CONFIG_UL(0, "NMEA", 32, 0),
235 MHI_CHANNEL_CONFIG_DL(1, "NMEA", 32, 0),
236 MHI_CHANNEL_CONFIG_UL_SBL(2, "SAHARA", 32, 0),
237 MHI_CHANNEL_CONFIG_DL_SBL(3, "SAHARA", 32, 0),
238 MHI_CHANNEL_CONFIG_UL(4, "DIAG", 32, 1),
239 MHI_CHANNEL_CONFIG_DL(5, "DIAG", 32, 1),
240 MHI_CHANNEL_CONFIG_UL(12, "MBIM", 32, 0),
241 MHI_CHANNEL_CONFIG_DL(13, "MBIM", 32, 0),
242 MHI_CHANNEL_CONFIG_UL(32, "DUN", 32, 0),
243 MHI_CHANNEL_CONFIG_DL(33, "DUN", 32, 0),
244 MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0_MBIM", 128, 2),
245 MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0_MBIM", 128, 3),
246};
247
248static struct mhi_event_config mhi_quectel_em1xx_events[] = {
249 MHI_EVENT_CONFIG_CTRL(0, 128),
250 MHI_EVENT_CONFIG_DATA(1, 128),
251 MHI_EVENT_CONFIG_HW_DATA(2, 1024, 100),
252 MHI_EVENT_CONFIG_HW_DATA(3, 1024, 101)
253};
254
255static struct mhi_controller_config modem_quectel_em1xx_config = {
256 .max_channels = 128,
257 .timeout_ms = 20000,
258 .num_channels = ARRAY_SIZE(mhi_quectel_em1xx_channels),
259 .ch_cfg = mhi_quectel_em1xx_channels,
260 .num_events = ARRAY_SIZE(mhi_quectel_em1xx_events),
261 .event_cfg = mhi_quectel_em1xx_events,
262};
263
264static const struct mhi_pci_dev_info mhi_quectel_em1xx_info = {
265 .name = "quectel-em1xx",
266 .edl = "qcom/prog_firehose_sdx24.mbn",
267 .config = &modem_quectel_em1xx_config,
268 .bar_num = MHI_PCI_DEFAULT_BAR_NUM,
269 .dma_data_width = 32
270};
271
Loic Poulain855a70c2020-10-21 19:18:19 +0200272static const struct pci_device_id mhi_pci_id_table[] = {
273 { PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0306),
274 .driver_data = (kernel_ulong_t) &mhi_qcom_sdx55_info },
Loic Poulain59d05b72021-03-05 20:16:45 +0100275 { PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0304),
276 .driver_data = (kernel_ulong_t) &mhi_qcom_sdx24_info },
Loic Poulainac4bf602021-03-05 20:16:44 +0100277 { PCI_DEVICE(0x1eac, 0x1001), /* EM120R-GL (sdx24) */
278 .driver_data = (kernel_ulong_t) &mhi_quectel_em1xx_info },
279 { PCI_DEVICE(0x1eac, 0x1002), /* EM160R-GL (sdx24) */
280 .driver_data = (kernel_ulong_t) &mhi_quectel_em1xx_info },
Bhaumik Bhatt49d38eb2021-04-02 14:33:19 -0700281 { PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0308),
282 .driver_data = (kernel_ulong_t) &mhi_qcom_sdx65_info },
Loic Poulain855a70c2020-10-21 19:18:19 +0200283 { }
284};
285MODULE_DEVICE_TABLE(pci, mhi_pci_id_table);
286
Loic Poulain8ccc3272021-01-04 17:14:53 +0100287enum mhi_pci_device_status {
288 MHI_PCI_DEV_STARTED,
Loic Poulaind3800c12021-03-05 20:16:48 +0100289 MHI_PCI_DEV_SUSPENDED,
Loic Poulain8ccc3272021-01-04 17:14:53 +0100290};
291
292struct mhi_pci_device {
293 struct mhi_controller mhi_cntrl;
294 struct pci_saved_state *pci_state;
Loic Poulain73893372021-01-04 17:14:54 +0100295 struct work_struct recovery_work;
Loic Poulain8562d4f2021-01-04 17:14:56 +0100296 struct timer_list health_check_timer;
Loic Poulain8ccc3272021-01-04 17:14:53 +0100297 unsigned long status;
298};
299
Loic Poulain855a70c2020-10-21 19:18:19 +0200300static int mhi_pci_read_reg(struct mhi_controller *mhi_cntrl,
301 void __iomem *addr, u32 *out)
302{
303 *out = readl(addr);
304 return 0;
305}
306
307static void mhi_pci_write_reg(struct mhi_controller *mhi_cntrl,
308 void __iomem *addr, u32 val)
309{
310 writel(val, addr);
311}
312
313static void mhi_pci_status_cb(struct mhi_controller *mhi_cntrl,
314 enum mhi_callback cb)
315{
Loic Poulain1e2f29b2021-02-03 17:39:42 +0100316 struct pci_dev *pdev = to_pci_dev(mhi_cntrl->cntrl_dev);
317
Loic Poulain855a70c2020-10-21 19:18:19 +0200318 /* Nothing to do for now */
Loic Poulain1e2f29b2021-02-03 17:39:42 +0100319 switch (cb) {
320 case MHI_CB_FATAL_ERROR:
321 case MHI_CB_SYS_ERROR:
322 dev_warn(&pdev->dev, "firmware crashed (%u)\n", cb);
Loic Poulaind3800c12021-03-05 20:16:48 +0100323 pm_runtime_forbid(&pdev->dev);
324 break;
325 case MHI_CB_EE_MISSION_MODE:
326 pm_runtime_allow(&pdev->dev);
Loic Poulain1e2f29b2021-02-03 17:39:42 +0100327 break;
328 default:
329 break;
330 }
Loic Poulain855a70c2020-10-21 19:18:19 +0200331}
332
Loic Poulaine3e5e6502021-03-05 20:16:46 +0100333static void mhi_pci_wake_get_nop(struct mhi_controller *mhi_cntrl, bool force)
334{
335 /* no-op */
336}
337
338static void mhi_pci_wake_put_nop(struct mhi_controller *mhi_cntrl, bool override)
339{
340 /* no-op */
341}
342
343static void mhi_pci_wake_toggle_nop(struct mhi_controller *mhi_cntrl)
344{
345 /* no-op */
346}
347
Loic Poulain8ccc3272021-01-04 17:14:53 +0100348static bool mhi_pci_is_alive(struct mhi_controller *mhi_cntrl)
349{
350 struct pci_dev *pdev = to_pci_dev(mhi_cntrl->cntrl_dev);
351 u16 vendor = 0;
352
353 if (pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor))
354 return false;
355
356 if (vendor == (u16) ~0 || vendor == 0)
357 return false;
358
359 return true;
360}
361
Loic Poulain855a70c2020-10-21 19:18:19 +0200362static int mhi_pci_claim(struct mhi_controller *mhi_cntrl,
363 unsigned int bar_num, u64 dma_mask)
364{
365 struct pci_dev *pdev = to_pci_dev(mhi_cntrl->cntrl_dev);
366 int err;
367
368 err = pci_assign_resource(pdev, bar_num);
369 if (err)
370 return err;
371
372 err = pcim_enable_device(pdev);
373 if (err) {
374 dev_err(&pdev->dev, "failed to enable pci device: %d\n", err);
375 return err;
376 }
377
378 err = pcim_iomap_regions(pdev, 1 << bar_num, pci_name(pdev));
379 if (err) {
380 dev_err(&pdev->dev, "failed to map pci region: %d\n", err);
381 return err;
382 }
383 mhi_cntrl->regs = pcim_iomap_table(pdev)[bar_num];
384
385 err = pci_set_dma_mask(pdev, dma_mask);
386 if (err) {
387 dev_err(&pdev->dev, "Cannot set proper DMA mask\n");
388 return err;
389 }
390
391 err = pci_set_consistent_dma_mask(pdev, dma_mask);
392 if (err) {
393 dev_err(&pdev->dev, "set consistent dma mask failed\n");
394 return err;
395 }
396
397 pci_set_master(pdev);
398
399 return 0;
400}
401
402static int mhi_pci_get_irqs(struct mhi_controller *mhi_cntrl,
403 const struct mhi_controller_config *mhi_cntrl_config)
404{
405 struct pci_dev *pdev = to_pci_dev(mhi_cntrl->cntrl_dev);
406 int nr_vectors, i;
407 int *irq;
408
409 /*
410 * Alloc one MSI vector for BHI + one vector per event ring, ideally...
411 * No explicit pci_free_irq_vectors required, done by pcim_release.
412 */
413 mhi_cntrl->nr_irqs = 1 + mhi_cntrl_config->num_events;
414
415 nr_vectors = pci_alloc_irq_vectors(pdev, 1, mhi_cntrl->nr_irqs, PCI_IRQ_MSI);
416 if (nr_vectors < 0) {
417 dev_err(&pdev->dev, "Error allocating MSI vectors %d\n",
418 nr_vectors);
419 return nr_vectors;
420 }
421
422 if (nr_vectors < mhi_cntrl->nr_irqs) {
Loic Poulainb91c3b32021-01-05 17:44:36 +0100423 dev_warn(&pdev->dev, "using shared MSI\n");
424
425 /* Patch msi vectors, use only one (shared) */
426 for (i = 0; i < mhi_cntrl_config->num_events; i++)
427 mhi_cntrl_config->event_cfg[i].irq = 0;
428 mhi_cntrl->nr_irqs = 1;
Loic Poulain855a70c2020-10-21 19:18:19 +0200429 }
430
431 irq = devm_kcalloc(&pdev->dev, mhi_cntrl->nr_irqs, sizeof(int), GFP_KERNEL);
432 if (!irq)
433 return -ENOMEM;
434
435 for (i = 0; i < mhi_cntrl->nr_irqs; i++) {
436 int vector = i >= nr_vectors ? (nr_vectors - 1) : i;
437
438 irq[i] = pci_irq_vector(pdev, vector);
439 }
440
441 mhi_cntrl->irq = irq;
442
443 return 0;
444}
445
446static int mhi_pci_runtime_get(struct mhi_controller *mhi_cntrl)
447{
Loic Poulaind3800c12021-03-05 20:16:48 +0100448 /* The runtime_get() MHI callback means:
449 * Do whatever is requested to leave M3.
450 */
451 return pm_runtime_get(mhi_cntrl->cntrl_dev);
Loic Poulain855a70c2020-10-21 19:18:19 +0200452}
453
454static void mhi_pci_runtime_put(struct mhi_controller *mhi_cntrl)
455{
Loic Poulaind3800c12021-03-05 20:16:48 +0100456 /* The runtime_put() MHI callback means:
457 * Device can be moved in M3 state.
458 */
459 pm_runtime_mark_last_busy(mhi_cntrl->cntrl_dev);
460 pm_runtime_put(mhi_cntrl->cntrl_dev);
Loic Poulain855a70c2020-10-21 19:18:19 +0200461}
462
Loic Poulain73893372021-01-04 17:14:54 +0100463static void mhi_pci_recovery_work(struct work_struct *work)
464{
465 struct mhi_pci_device *mhi_pdev = container_of(work, struct mhi_pci_device,
466 recovery_work);
467 struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
468 struct pci_dev *pdev = to_pci_dev(mhi_cntrl->cntrl_dev);
469 int err;
470
471 dev_warn(&pdev->dev, "device recovery started\n");
472
Loic Poulain8562d4f2021-01-04 17:14:56 +0100473 del_timer(&mhi_pdev->health_check_timer);
Loic Poulaind3800c12021-03-05 20:16:48 +0100474 pm_runtime_forbid(&pdev->dev);
Loic Poulain8562d4f2021-01-04 17:14:56 +0100475
Loic Poulain73893372021-01-04 17:14:54 +0100476 /* Clean up MHI state */
477 if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) {
478 mhi_power_down(mhi_cntrl, false);
479 mhi_unprepare_after_power_down(mhi_cntrl);
480 }
481
Loic Poulain73893372021-01-04 17:14:54 +0100482 pci_set_power_state(pdev, PCI_D0);
483 pci_load_saved_state(pdev, mhi_pdev->pci_state);
484 pci_restore_state(pdev);
485
486 if (!mhi_pci_is_alive(mhi_cntrl))
487 goto err_try_reset;
488
489 err = mhi_prepare_for_power_up(mhi_cntrl);
490 if (err)
491 goto err_try_reset;
492
493 err = mhi_sync_power_up(mhi_cntrl);
494 if (err)
495 goto err_unprepare;
496
497 dev_dbg(&pdev->dev, "Recovery completed\n");
498
499 set_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status);
Loic Poulain8562d4f2021-01-04 17:14:56 +0100500 mod_timer(&mhi_pdev->health_check_timer, jiffies + HEALTH_CHECK_PERIOD);
Loic Poulain73893372021-01-04 17:14:54 +0100501 return;
502
503err_unprepare:
504 mhi_unprepare_after_power_down(mhi_cntrl);
505err_try_reset:
506 if (pci_reset_function(pdev))
507 dev_err(&pdev->dev, "Recovery failed\n");
508}
509
Loic Poulain8562d4f2021-01-04 17:14:56 +0100510static void health_check(struct timer_list *t)
511{
512 struct mhi_pci_device *mhi_pdev = from_timer(mhi_pdev, t, health_check_timer);
513 struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
514
Loic Poulaind3800c12021-03-05 20:16:48 +0100515 if (!test_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status) ||
516 test_bit(MHI_PCI_DEV_SUSPENDED, &mhi_pdev->status))
517 return;
518
Loic Poulain8562d4f2021-01-04 17:14:56 +0100519 if (!mhi_pci_is_alive(mhi_cntrl)) {
520 dev_err(mhi_cntrl->cntrl_dev, "Device died\n");
521 queue_work(system_long_wq, &mhi_pdev->recovery_work);
522 return;
523 }
524
525 /* reschedule in two seconds */
526 mod_timer(&mhi_pdev->health_check_timer, jiffies + HEALTH_CHECK_PERIOD);
527}
528
Loic Poulain855a70c2020-10-21 19:18:19 +0200529static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
530{
531 const struct mhi_pci_dev_info *info = (struct mhi_pci_dev_info *) id->driver_data;
532 const struct mhi_controller_config *mhi_cntrl_config;
Loic Poulain8ccc3272021-01-04 17:14:53 +0100533 struct mhi_pci_device *mhi_pdev;
Loic Poulain855a70c2020-10-21 19:18:19 +0200534 struct mhi_controller *mhi_cntrl;
535 int err;
536
537 dev_dbg(&pdev->dev, "MHI PCI device found: %s\n", info->name);
538
Loic Poulain8ccc3272021-01-04 17:14:53 +0100539 /* mhi_pdev.mhi_cntrl must be zero-initialized */
540 mhi_pdev = devm_kzalloc(&pdev->dev, sizeof(*mhi_pdev), GFP_KERNEL);
541 if (!mhi_pdev)
Loic Poulain855a70c2020-10-21 19:18:19 +0200542 return -ENOMEM;
543
Loic Poulain73893372021-01-04 17:14:54 +0100544 INIT_WORK(&mhi_pdev->recovery_work, mhi_pci_recovery_work);
Loic Poulain8562d4f2021-01-04 17:14:56 +0100545 timer_setup(&mhi_pdev->health_check_timer, health_check, 0);
Loic Poulain73893372021-01-04 17:14:54 +0100546
Loic Poulain855a70c2020-10-21 19:18:19 +0200547 mhi_cntrl_config = info->config;
Loic Poulain8ccc3272021-01-04 17:14:53 +0100548 mhi_cntrl = &mhi_pdev->mhi_cntrl;
549
Loic Poulain855a70c2020-10-21 19:18:19 +0200550 mhi_cntrl->cntrl_dev = &pdev->dev;
551 mhi_cntrl->iova_start = 0;
Loic Poulain4ea6fa22020-12-02 09:12:30 +0100552 mhi_cntrl->iova_stop = (dma_addr_t)DMA_BIT_MASK(info->dma_data_width);
Loic Poulain855a70c2020-10-21 19:18:19 +0200553 mhi_cntrl->fw_image = info->fw;
554 mhi_cntrl->edl_image = info->edl;
555
556 mhi_cntrl->read_reg = mhi_pci_read_reg;
557 mhi_cntrl->write_reg = mhi_pci_write_reg;
558 mhi_cntrl->status_cb = mhi_pci_status_cb;
559 mhi_cntrl->runtime_get = mhi_pci_runtime_get;
560 mhi_cntrl->runtime_put = mhi_pci_runtime_put;
Loic Poulaine3e5e6502021-03-05 20:16:46 +0100561 mhi_cntrl->wake_get = mhi_pci_wake_get_nop;
562 mhi_cntrl->wake_put = mhi_pci_wake_put_nop;
563 mhi_cntrl->wake_toggle = mhi_pci_wake_toggle_nop;
Loic Poulain855a70c2020-10-21 19:18:19 +0200564
565 err = mhi_pci_claim(mhi_cntrl, info->bar_num, DMA_BIT_MASK(info->dma_data_width));
566 if (err)
Loic Poulain8ccc3272021-01-04 17:14:53 +0100567 return err;
Loic Poulain855a70c2020-10-21 19:18:19 +0200568
569 err = mhi_pci_get_irqs(mhi_cntrl, mhi_cntrl_config);
570 if (err)
Loic Poulain8ccc3272021-01-04 17:14:53 +0100571 return err;
Loic Poulain855a70c2020-10-21 19:18:19 +0200572
Loic Poulain8ccc3272021-01-04 17:14:53 +0100573 pci_set_drvdata(pdev, mhi_pdev);
574
Loic Poulaine89878a2021-03-05 20:16:47 +0100575 /* Have stored pci confspace at hand for restore in sudden PCI error.
576 * cache the state locally and discard the PCI core one.
577 */
Loic Poulain8ccc3272021-01-04 17:14:53 +0100578 pci_save_state(pdev);
579 mhi_pdev->pci_state = pci_store_saved_state(pdev);
Loic Poulaine89878a2021-03-05 20:16:47 +0100580 pci_load_saved_state(pdev, NULL);
Loic Poulain855a70c2020-10-21 19:18:19 +0200581
Loic Poulainb012ee62021-01-04 17:14:55 +0100582 pci_enable_pcie_error_reporting(pdev);
583
Loic Poulain855a70c2020-10-21 19:18:19 +0200584 err = mhi_register_controller(mhi_cntrl, mhi_cntrl_config);
585 if (err)
Loic Poulain8ccc3272021-01-04 17:14:53 +0100586 return err;
Loic Poulain855a70c2020-10-21 19:18:19 +0200587
588 /* MHI bus does not power up the controller by default */
589 err = mhi_prepare_for_power_up(mhi_cntrl);
590 if (err) {
591 dev_err(&pdev->dev, "failed to prepare MHI controller\n");
592 goto err_unregister;
593 }
594
595 err = mhi_sync_power_up(mhi_cntrl);
596 if (err) {
597 dev_err(&pdev->dev, "failed to power up MHI controller\n");
598 goto err_unprepare;
599 }
600
Loic Poulain8ccc3272021-01-04 17:14:53 +0100601 set_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status);
602
Loic Poulain8562d4f2021-01-04 17:14:56 +0100603 /* start health check */
604 mod_timer(&mhi_pdev->health_check_timer, jiffies + HEALTH_CHECK_PERIOD);
605
Loic Poulaind3800c12021-03-05 20:16:48 +0100606 /* Only allow runtime-suspend if PME capable (for wakeup) */
607 if (pci_pme_capable(pdev, PCI_D3hot)) {
608 pm_runtime_set_autosuspend_delay(&pdev->dev, 2000);
609 pm_runtime_use_autosuspend(&pdev->dev);
610 pm_runtime_mark_last_busy(&pdev->dev);
611 pm_runtime_put_noidle(&pdev->dev);
612 }
613
Loic Poulain855a70c2020-10-21 19:18:19 +0200614 return 0;
615
616err_unprepare:
617 mhi_unprepare_after_power_down(mhi_cntrl);
618err_unregister:
619 mhi_unregister_controller(mhi_cntrl);
Loic Poulain855a70c2020-10-21 19:18:19 +0200620
621 return err;
622}
623
624static void mhi_pci_remove(struct pci_dev *pdev)
625{
Loic Poulain8ccc3272021-01-04 17:14:53 +0100626 struct mhi_pci_device *mhi_pdev = pci_get_drvdata(pdev);
627 struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
Loic Poulain855a70c2020-10-21 19:18:19 +0200628
Loic Poulain8562d4f2021-01-04 17:14:56 +0100629 del_timer(&mhi_pdev->health_check_timer);
Loic Poulain73893372021-01-04 17:14:54 +0100630 cancel_work_sync(&mhi_pdev->recovery_work);
631
Loic Poulain8ccc3272021-01-04 17:14:53 +0100632 if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) {
633 mhi_power_down(mhi_cntrl, true);
634 mhi_unprepare_after_power_down(mhi_cntrl);
635 }
636
Loic Poulaind3800c12021-03-05 20:16:48 +0100637 /* balancing probe put_noidle */
638 if (pci_pme_capable(pdev, PCI_D3hot))
639 pm_runtime_get_noresume(&pdev->dev);
640
Loic Poulain855a70c2020-10-21 19:18:19 +0200641 mhi_unregister_controller(mhi_cntrl);
Loic Poulain855a70c2020-10-21 19:18:19 +0200642}
643
Loic Poulain757072a2021-03-19 16:50:37 +0100644static void mhi_pci_shutdown(struct pci_dev *pdev)
645{
646 mhi_pci_remove(pdev);
647 pci_set_power_state(pdev, PCI_D3hot);
648}
649
Loic Poulain8ccc3272021-01-04 17:14:53 +0100650static void mhi_pci_reset_prepare(struct pci_dev *pdev)
651{
652 struct mhi_pci_device *mhi_pdev = pci_get_drvdata(pdev);
653 struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
654
655 dev_info(&pdev->dev, "reset\n");
656
Loic Poulain8562d4f2021-01-04 17:14:56 +0100657 del_timer(&mhi_pdev->health_check_timer);
658
Loic Poulain8ccc3272021-01-04 17:14:53 +0100659 /* Clean up MHI state */
660 if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) {
661 mhi_power_down(mhi_cntrl, false);
662 mhi_unprepare_after_power_down(mhi_cntrl);
663 }
664
665 /* cause internal device reset */
666 mhi_soc_reset(mhi_cntrl);
667
668 /* Be sure device reset has been executed */
669 msleep(MHI_POST_RESET_DELAY_MS);
670}
671
672static void mhi_pci_reset_done(struct pci_dev *pdev)
673{
674 struct mhi_pci_device *mhi_pdev = pci_get_drvdata(pdev);
675 struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
676 int err;
677
678 /* Restore initial known working PCI state */
679 pci_load_saved_state(pdev, mhi_pdev->pci_state);
680 pci_restore_state(pdev);
681
682 /* Is device status available ? */
683 if (!mhi_pci_is_alive(mhi_cntrl)) {
684 dev_err(&pdev->dev, "reset failed\n");
685 return;
686 }
687
688 err = mhi_prepare_for_power_up(mhi_cntrl);
689 if (err) {
690 dev_err(&pdev->dev, "failed to prepare MHI controller\n");
691 return;
692 }
693
694 err = mhi_sync_power_up(mhi_cntrl);
695 if (err) {
696 dev_err(&pdev->dev, "failed to power up MHI controller\n");
697 mhi_unprepare_after_power_down(mhi_cntrl);
698 return;
699 }
700
701 set_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status);
Loic Poulain8562d4f2021-01-04 17:14:56 +0100702 mod_timer(&mhi_pdev->health_check_timer, jiffies + HEALTH_CHECK_PERIOD);
Loic Poulain8ccc3272021-01-04 17:14:53 +0100703}
704
Loic Poulainb012ee62021-01-04 17:14:55 +0100705static pci_ers_result_t mhi_pci_error_detected(struct pci_dev *pdev,
706 pci_channel_state_t state)
707{
708 struct mhi_pci_device *mhi_pdev = pci_get_drvdata(pdev);
709 struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
710
711 dev_err(&pdev->dev, "PCI error detected, state = %u\n", state);
712
713 if (state == pci_channel_io_perm_failure)
714 return PCI_ERS_RESULT_DISCONNECT;
715
716 /* Clean up MHI state */
717 if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) {
718 mhi_power_down(mhi_cntrl, false);
719 mhi_unprepare_after_power_down(mhi_cntrl);
720 } else {
721 /* Nothing to do */
722 return PCI_ERS_RESULT_RECOVERED;
723 }
724
725 pci_disable_device(pdev);
726
727 return PCI_ERS_RESULT_NEED_RESET;
728}
729
730static pci_ers_result_t mhi_pci_slot_reset(struct pci_dev *pdev)
731{
732 if (pci_enable_device(pdev)) {
733 dev_err(&pdev->dev, "Cannot re-enable PCI device after reset.\n");
734 return PCI_ERS_RESULT_DISCONNECT;
735 }
736
737 return PCI_ERS_RESULT_RECOVERED;
738}
739
740static void mhi_pci_io_resume(struct pci_dev *pdev)
741{
742 struct mhi_pci_device *mhi_pdev = pci_get_drvdata(pdev);
743
744 dev_err(&pdev->dev, "PCI slot reset done\n");
745
746 queue_work(system_long_wq, &mhi_pdev->recovery_work);
747}
748
Loic Poulain8ccc3272021-01-04 17:14:53 +0100749static const struct pci_error_handlers mhi_pci_err_handler = {
Loic Poulainb012ee62021-01-04 17:14:55 +0100750 .error_detected = mhi_pci_error_detected,
751 .slot_reset = mhi_pci_slot_reset,
752 .resume = mhi_pci_io_resume,
Loic Poulain8ccc3272021-01-04 17:14:53 +0100753 .reset_prepare = mhi_pci_reset_prepare,
754 .reset_done = mhi_pci_reset_done,
755};
756
Loic Poulaind3800c12021-03-05 20:16:48 +0100757static int __maybe_unused mhi_pci_runtime_suspend(struct device *dev)
Loic Poulain73893372021-01-04 17:14:54 +0100758{
759 struct pci_dev *pdev = to_pci_dev(dev);
760 struct mhi_pci_device *mhi_pdev = dev_get_drvdata(dev);
761 struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
Loic Poulaind3800c12021-03-05 20:16:48 +0100762 int err;
763
764 if (test_and_set_bit(MHI_PCI_DEV_SUSPENDED, &mhi_pdev->status))
765 return 0;
Loic Poulain73893372021-01-04 17:14:54 +0100766
Loic Poulain8562d4f2021-01-04 17:14:56 +0100767 del_timer(&mhi_pdev->health_check_timer);
Loic Poulain73893372021-01-04 17:14:54 +0100768 cancel_work_sync(&mhi_pdev->recovery_work);
769
Loic Poulaind3800c12021-03-05 20:16:48 +0100770 if (!test_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status) ||
771 mhi_cntrl->ee != MHI_EE_AMSS)
772 goto pci_suspend; /* Nothing to do at MHI level */
Loic Poulain73893372021-01-04 17:14:54 +0100773
Loic Poulaind3800c12021-03-05 20:16:48 +0100774 /* Transition to M3 state */
775 err = mhi_pm_suspend(mhi_cntrl);
776 if (err) {
777 dev_err(&pdev->dev, "failed to suspend device: %d\n", err);
778 clear_bit(MHI_PCI_DEV_SUSPENDED, &mhi_pdev->status);
779 return -EBUSY;
780 }
781
782pci_suspend:
Loic Poulain73893372021-01-04 17:14:54 +0100783 pci_disable_device(pdev);
784 pci_wake_from_d3(pdev, true);
Loic Poulain73893372021-01-04 17:14:54 +0100785
786 return 0;
787}
788
Loic Poulaind3800c12021-03-05 20:16:48 +0100789static int __maybe_unused mhi_pci_runtime_resume(struct device *dev)
Loic Poulain73893372021-01-04 17:14:54 +0100790{
791 struct pci_dev *pdev = to_pci_dev(dev);
792 struct mhi_pci_device *mhi_pdev = dev_get_drvdata(dev);
793 struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
794 int err;
795
Loic Poulaind3800c12021-03-05 20:16:48 +0100796 if (!test_and_clear_bit(MHI_PCI_DEV_SUSPENDED, &mhi_pdev->status))
797 return 0;
798
Loic Poulain73893372021-01-04 17:14:54 +0100799 err = pci_enable_device(pdev);
800 if (err)
801 goto err_recovery;
802
Loic Poulaine89878a2021-03-05 20:16:47 +0100803 pci_set_master(pdev);
804 pci_wake_from_d3(pdev, false);
805
Loic Poulaind3800c12021-03-05 20:16:48 +0100806 if (!test_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status) ||
807 mhi_cntrl->ee != MHI_EE_AMSS)
808 return 0; /* Nothing to do at MHI level */
809
Loic Poulain73893372021-01-04 17:14:54 +0100810 /* Exit M3, transition to M0 state */
811 err = mhi_pm_resume(mhi_cntrl);
812 if (err) {
813 dev_err(&pdev->dev, "failed to resume device: %d\n", err);
814 goto err_recovery;
815 }
816
Loic Poulain8562d4f2021-01-04 17:14:56 +0100817 /* Resume health check */
818 mod_timer(&mhi_pdev->health_check_timer, jiffies + HEALTH_CHECK_PERIOD);
819
Loic Poulaind3800c12021-03-05 20:16:48 +0100820 /* It can be a remote wakeup (no mhi runtime_get), update access time */
821 pm_runtime_mark_last_busy(dev);
822
Loic Poulain73893372021-01-04 17:14:54 +0100823 return 0;
824
825err_recovery:
Loic Poulaind3800c12021-03-05 20:16:48 +0100826 /* Do not fail to not mess up our PCI device state, the device likely
827 * lost power (d3cold) and we simply need to reset it from the recovery
828 * procedure, trigger the recovery asynchronously to prevent system
829 * suspend exit delaying.
830 */
Loic Poulain73893372021-01-04 17:14:54 +0100831 queue_work(system_long_wq, &mhi_pdev->recovery_work);
Loic Poulaind3800c12021-03-05 20:16:48 +0100832 pm_runtime_mark_last_busy(dev);
Loic Poulain73893372021-01-04 17:14:54 +0100833
Loic Poulaind3800c12021-03-05 20:16:48 +0100834 return 0;
835}
836
837static int __maybe_unused mhi_pci_suspend(struct device *dev)
838{
839 pm_runtime_disable(dev);
840 return mhi_pci_runtime_suspend(dev);
841}
842
843static int __maybe_unused mhi_pci_resume(struct device *dev)
844{
845 int ret;
846
847 /* Depending the platform, device may have lost power (d3cold), we need
848 * to resume it now to check its state and recover when necessary.
849 */
850 ret = mhi_pci_runtime_resume(dev);
851 pm_runtime_enable(dev);
852
853 return ret;
Loic Poulain73893372021-01-04 17:14:54 +0100854}
855
856static const struct dev_pm_ops mhi_pci_pm_ops = {
Loic Poulaind3800c12021-03-05 20:16:48 +0100857 SET_RUNTIME_PM_OPS(mhi_pci_runtime_suspend, mhi_pci_runtime_resume, NULL)
Loic Poulain73893372021-01-04 17:14:54 +0100858 SET_SYSTEM_SLEEP_PM_OPS(mhi_pci_suspend, mhi_pci_resume)
859};
860
Loic Poulain855a70c2020-10-21 19:18:19 +0200861static struct pci_driver mhi_pci_driver = {
862 .name = "mhi-pci-generic",
863 .id_table = mhi_pci_id_table,
864 .probe = mhi_pci_probe,
Loic Poulain8ccc3272021-01-04 17:14:53 +0100865 .remove = mhi_pci_remove,
Loic Poulain757072a2021-03-19 16:50:37 +0100866 .shutdown = mhi_pci_shutdown,
Loic Poulain8ccc3272021-01-04 17:14:53 +0100867 .err_handler = &mhi_pci_err_handler,
Loic Poulain73893372021-01-04 17:14:54 +0100868 .driver.pm = &mhi_pci_pm_ops
Loic Poulain855a70c2020-10-21 19:18:19 +0200869};
870module_pci_driver(mhi_pci_driver);
871
872MODULE_AUTHOR("Loic Poulain <loic.poulain@linaro.org>");
873MODULE_DESCRIPTION("Modem Host Interface (MHI) PCI controller driver");
874MODULE_LICENSE("GPL");