media: intel/ipu6: Fix some redundant resources freeing in ipu6_pci_remove()
[linux-block.git] / drivers / media / pci / intel / ipu6 / ipu6.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2013--2024 Intel Corporation
4  */
5
6 #include <linux/bitfield.h>
7 #include <linux/bits.h>
8 #include <linux/dma-mapping.h>
9 #include <linux/err.h>
10 #include <linux/firmware.h>
11 #include <linux/kernel.h>
12 #include <linux/interrupt.h>
13 #include <linux/io.h>
14 #include <linux/list.h>
15 #include <linux/module.h>
16 #include <linux/pci-ats.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/property.h>
19 #include <linux/scatterlist.h>
20 #include <linux/slab.h>
21 #include <linux/types.h>
22
23 #include <media/ipu-bridge.h>
24 #include <media/ipu6-pci-table.h>
25
26 #include "ipu6.h"
27 #include "ipu6-bus.h"
28 #include "ipu6-buttress.h"
29 #include "ipu6-cpd.h"
30 #include "ipu6-isys.h"
31 #include "ipu6-mmu.h"
32 #include "ipu6-platform-buttress-regs.h"
33 #include "ipu6-platform-isys-csi2-reg.h"
34 #include "ipu6-platform-regs.h"
35
36 #define IPU6_PCI_BAR            0
37
38 struct ipu6_cell_program {
39         u32 magic_number;
40
41         u32 blob_offset;
42         u32 blob_size;
43
44         u32 start[3];
45
46         u32 icache_source;
47         u32 icache_target;
48         u32 icache_size;
49
50         u32 pmem_source;
51         u32 pmem_target;
52         u32 pmem_size;
53
54         u32 data_source;
55         u32 data_target;
56         u32 data_size;
57
58         u32 bss_target;
59         u32 bss_size;
60
61         u32 cell_id;
62         u32 regs_addr;
63
64         u32 cell_pmem_data_bus_address;
65         u32 cell_dmem_data_bus_address;
66         u32 cell_pmem_control_bus_address;
67         u32 cell_dmem_control_bus_address;
68
69         u32 next;
70         u32 dummy[2];
71 };
72
73 static struct ipu6_isys_internal_pdata isys_ipdata = {
74         .hw_variant = {
75                 .offset = IPU6_UNIFIED_OFFSET,
76                 .nr_mmus = 3,
77                 .mmu_hw = {
78                         {
79                                 .offset = IPU6_ISYS_IOMMU0_OFFSET,
80                                 .info_bits = IPU6_INFO_REQUEST_DESTINATION_IOSF,
81                                 .nr_l1streams = 16,
82                                 .l1_block_sz = {
83                                         3, 8, 2, 2, 2, 2, 2, 2, 1, 1,
84                                         1, 1, 1, 1, 1, 1
85                                 },
86                                 .nr_l2streams = 16,
87                                 .l2_block_sz = {
88                                         2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
89                                         2, 2, 2, 2, 2, 2
90                                 },
91                                 .insert_read_before_invalidate = false,
92                                 .l1_stream_id_reg_offset =
93                                 IPU6_MMU_L1_STREAM_ID_REG_OFFSET,
94                                 .l2_stream_id_reg_offset =
95                                 IPU6_MMU_L2_STREAM_ID_REG_OFFSET,
96                         },
97                         {
98                                 .offset = IPU6_ISYS_IOMMU1_OFFSET,
99                                 .info_bits = 0,
100                                 .nr_l1streams = 16,
101                                 .l1_block_sz = {
102                                         2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
103                                         2, 2, 2, 1, 1, 4
104                                 },
105                                 .nr_l2streams = 16,
106                                 .l2_block_sz = {
107                                         2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
108                                         2, 2, 2, 2, 2, 2
109                                 },
110                                 .insert_read_before_invalidate = false,
111                                 .l1_stream_id_reg_offset =
112                                 IPU6_MMU_L1_STREAM_ID_REG_OFFSET,
113                                 .l2_stream_id_reg_offset =
114                                 IPU6_MMU_L2_STREAM_ID_REG_OFFSET,
115                         },
116                         {
117                                 .offset = IPU6_ISYS_IOMMUI_OFFSET,
118                                 .info_bits = 0,
119                                 .nr_l1streams = 0,
120                                 .nr_l2streams = 0,
121                                 .insert_read_before_invalidate = false,
122                         },
123                 },
124                 .cdc_fifos = 3,
125                 .cdc_fifo_threshold = {6, 8, 2},
126                 .dmem_offset = IPU6_ISYS_DMEM_OFFSET,
127                 .spc_offset = IPU6_ISYS_SPC_OFFSET,
128         },
129         .isys_dma_overshoot = IPU6_ISYS_OVERALLOC_MIN,
130 };
131
132 static struct ipu6_psys_internal_pdata psys_ipdata = {
133         .hw_variant = {
134                 .offset = IPU6_UNIFIED_OFFSET,
135                 .nr_mmus = 4,
136                 .mmu_hw = {
137                         {
138                                 .offset = IPU6_PSYS_IOMMU0_OFFSET,
139                                 .info_bits =
140                                 IPU6_INFO_REQUEST_DESTINATION_IOSF,
141                                 .nr_l1streams = 16,
142                                 .l1_block_sz = {
143                                         2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
144                                         2, 2, 2, 2, 2, 2
145                                 },
146                                 .nr_l2streams = 16,
147                                 .l2_block_sz = {
148                                         2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
149                                         2, 2, 2, 2, 2, 2
150                                 },
151                                 .insert_read_before_invalidate = false,
152                                 .l1_stream_id_reg_offset =
153                                 IPU6_MMU_L1_STREAM_ID_REG_OFFSET,
154                                 .l2_stream_id_reg_offset =
155                                 IPU6_MMU_L2_STREAM_ID_REG_OFFSET,
156                         },
157                         {
158                                 .offset = IPU6_PSYS_IOMMU1_OFFSET,
159                                 .info_bits = 0,
160                                 .nr_l1streams = 32,
161                                 .l1_block_sz = {
162                                         1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
163                                         2, 2, 2, 2, 2, 10,
164                                         5, 4, 14, 6, 4, 14, 6, 4, 8,
165                                         4, 2, 1, 1, 1, 1, 14
166                                 },
167                                 .nr_l2streams = 32,
168                                 .l2_block_sz = {
169                                         2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
170                                         2, 2, 2, 2, 2, 2,
171                                         2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
172                                         2, 2, 2, 2, 2, 2
173                                 },
174                                 .insert_read_before_invalidate = false,
175                                 .l1_stream_id_reg_offset =
176                                 IPU6_MMU_L1_STREAM_ID_REG_OFFSET,
177                                 .l2_stream_id_reg_offset =
178                                 IPU6_PSYS_MMU1W_L2_STREAM_ID_REG_OFFSET,
179                         },
180                         {
181                                 .offset = IPU6_PSYS_IOMMU1R_OFFSET,
182                                 .info_bits = 0,
183                                 .nr_l1streams = 16,
184                                 .l1_block_sz = {
185                                         1, 4, 4, 4, 4, 16, 8, 4, 32,
186                                         16, 16, 2, 2, 2, 1, 12
187                                 },
188                                 .nr_l2streams = 16,
189                                 .l2_block_sz = {
190                                         2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
191                                         2, 2, 2, 2, 2, 2
192                                 },
193                                 .insert_read_before_invalidate = false,
194                                 .l1_stream_id_reg_offset =
195                                 IPU6_MMU_L1_STREAM_ID_REG_OFFSET,
196                                 .l2_stream_id_reg_offset =
197                                 IPU6_MMU_L2_STREAM_ID_REG_OFFSET,
198                         },
199                         {
200                                 .offset = IPU6_PSYS_IOMMUI_OFFSET,
201                                 .info_bits = 0,
202                                 .nr_l1streams = 0,
203                                 .nr_l2streams = 0,
204                                 .insert_read_before_invalidate = false,
205                         },
206                 },
207                 .dmem_offset = IPU6_PSYS_DMEM_OFFSET,
208         },
209 };
210
211 static const struct ipu6_buttress_ctrl isys_buttress_ctrl = {
212         .ratio = IPU6_IS_FREQ_CTL_DEFAULT_RATIO,
213         .qos_floor = IPU6_IS_FREQ_CTL_DEFAULT_QOS_FLOOR_RATIO,
214         .freq_ctl = IPU6_BUTTRESS_REG_IS_FREQ_CTL,
215         .pwr_sts_shift = IPU6_BUTTRESS_PWR_STATE_IS_PWR_SHIFT,
216         .pwr_sts_mask = IPU6_BUTTRESS_PWR_STATE_IS_PWR_MASK,
217         .pwr_sts_on = IPU6_BUTTRESS_PWR_STATE_UP_DONE,
218         .pwr_sts_off = IPU6_BUTTRESS_PWR_STATE_DN_DONE,
219 };
220
221 static const struct ipu6_buttress_ctrl psys_buttress_ctrl = {
222         .ratio = IPU6_PS_FREQ_CTL_DEFAULT_RATIO,
223         .qos_floor = IPU6_PS_FREQ_CTL_DEFAULT_QOS_FLOOR_RATIO,
224         .freq_ctl = IPU6_BUTTRESS_REG_PS_FREQ_CTL,
225         .pwr_sts_shift = IPU6_BUTTRESS_PWR_STATE_PS_PWR_SHIFT,
226         .pwr_sts_mask = IPU6_BUTTRESS_PWR_STATE_PS_PWR_MASK,
227         .pwr_sts_on = IPU6_BUTTRESS_PWR_STATE_UP_DONE,
228         .pwr_sts_off = IPU6_BUTTRESS_PWR_STATE_DN_DONE,
229 };
230
231 static void
232 ipu6_pkg_dir_configure_spc(struct ipu6_device *isp,
233                            const struct ipu6_hw_variants *hw_variant,
234                            int pkg_dir_idx, void __iomem *base,
235                            u64 *pkg_dir, dma_addr_t pkg_dir_vied_address)
236 {
237         struct ipu6_cell_program *prog;
238         void __iomem *spc_base;
239         u32 server_fw_addr;
240         dma_addr_t dma_addr;
241         u32 pg_offset;
242
243         server_fw_addr = lower_32_bits(*(pkg_dir + (pkg_dir_idx + 1) * 2));
244         if (pkg_dir_idx == IPU6_CPD_PKG_DIR_ISYS_SERVER_IDX)
245                 dma_addr = sg_dma_address(isp->isys->fw_sgt.sgl);
246         else
247                 dma_addr = sg_dma_address(isp->psys->fw_sgt.sgl);
248
249         pg_offset = server_fw_addr - dma_addr;
250         prog = (struct ipu6_cell_program *)((u64)isp->cpd_fw->data + pg_offset);
251         spc_base = base + prog->regs_addr;
252         if (spc_base != (base + hw_variant->spc_offset))
253                 dev_warn(&isp->pdev->dev,
254                          "SPC reg addr %p not matching value from CPD %p\n",
255                          base + hw_variant->spc_offset, spc_base);
256         writel(server_fw_addr + prog->blob_offset +
257                prog->icache_source, spc_base + IPU6_PSYS_REG_SPC_ICACHE_BASE);
258         writel(IPU6_INFO_REQUEST_DESTINATION_IOSF,
259                spc_base + IPU6_REG_PSYS_INFO_SEG_0_CONFIG_ICACHE_MASTER);
260         writel(prog->start[1], spc_base + IPU6_PSYS_REG_SPC_START_PC);
261         writel(pkg_dir_vied_address, base + hw_variant->dmem_offset);
262 }
263
264 void ipu6_configure_spc(struct ipu6_device *isp,
265                         const struct ipu6_hw_variants *hw_variant,
266                         int pkg_dir_idx, void __iomem *base, u64 *pkg_dir,
267                         dma_addr_t pkg_dir_dma_addr)
268 {
269         void __iomem *dmem_base = base + hw_variant->dmem_offset;
270         void __iomem *spc_regs_base = base + hw_variant->spc_offset;
271         u32 val;
272
273         val = readl(spc_regs_base + IPU6_PSYS_REG_SPC_STATUS_CTRL);
274         val |= IPU6_PSYS_SPC_STATUS_CTRL_ICACHE_INVALIDATE;
275         writel(val, spc_regs_base + IPU6_PSYS_REG_SPC_STATUS_CTRL);
276
277         if (isp->secure_mode)
278                 writel(IPU6_PKG_DIR_IMR_OFFSET, dmem_base);
279         else
280                 ipu6_pkg_dir_configure_spc(isp, hw_variant, pkg_dir_idx, base,
281                                            pkg_dir, pkg_dir_dma_addr);
282 }
283 EXPORT_SYMBOL_NS_GPL(ipu6_configure_spc, INTEL_IPU6);
284
285 #define IPU6_ISYS_CSI2_NPORTS           4
286 #define IPU6SE_ISYS_CSI2_NPORTS         4
287 #define IPU6_TGL_ISYS_CSI2_NPORTS       8
288 #define IPU6EP_MTL_ISYS_CSI2_NPORTS     4
289
290 static void ipu6_internal_pdata_init(struct ipu6_device *isp)
291 {
292         u8 hw_ver = isp->hw_ver;
293
294         isys_ipdata.num_parallel_streams = IPU6_ISYS_NUM_STREAMS;
295         isys_ipdata.sram_gran_shift = IPU6_SRAM_GRANULARITY_SHIFT;
296         isys_ipdata.sram_gran_size = IPU6_SRAM_GRANULARITY_SIZE;
297         isys_ipdata.max_sram_size = IPU6_MAX_SRAM_SIZE;
298         isys_ipdata.sensor_type_start = IPU6_FW_ISYS_SENSOR_TYPE_START;
299         isys_ipdata.sensor_type_end = IPU6_FW_ISYS_SENSOR_TYPE_END;
300         isys_ipdata.max_streams = IPU6_ISYS_NUM_STREAMS;
301         isys_ipdata.max_send_queues = IPU6_N_MAX_SEND_QUEUES;
302         isys_ipdata.max_sram_blocks = IPU6_NOF_SRAM_BLOCKS_MAX;
303         isys_ipdata.max_devq_size = IPU6_DEV_SEND_QUEUE_SIZE;
304         isys_ipdata.csi2.nports = IPU6_ISYS_CSI2_NPORTS;
305         isys_ipdata.csi2.irq_mask = IPU6_CSI_RX_ERROR_IRQ_MASK;
306         isys_ipdata.csi2.ctrl0_irq_edge = IPU6_REG_ISYS_CSI_TOP_CTRL0_IRQ_EDGE;
307         isys_ipdata.csi2.ctrl0_irq_clear =
308                 IPU6_REG_ISYS_CSI_TOP_CTRL0_IRQ_CLEAR;
309         isys_ipdata.csi2.ctrl0_irq_mask = IPU6_REG_ISYS_CSI_TOP_CTRL0_IRQ_MASK;
310         isys_ipdata.csi2.ctrl0_irq_enable =
311                 IPU6_REG_ISYS_CSI_TOP_CTRL0_IRQ_ENABLE;
312         isys_ipdata.csi2.ctrl0_irq_status =
313                 IPU6_REG_ISYS_CSI_TOP_CTRL0_IRQ_STATUS;
314         isys_ipdata.csi2.ctrl0_irq_lnp =
315                 IPU6_REG_ISYS_CSI_TOP_CTRL0_IRQ_LEVEL_NOT_PULSE;
316         isys_ipdata.enhanced_iwake = is_ipu6ep_mtl(hw_ver) || is_ipu6ep(hw_ver);
317         psys_ipdata.hw_variant.spc_offset = IPU6_PSYS_SPC_OFFSET;
318         isys_ipdata.csi2.fw_access_port_ofs = CSI_REG_HUB_FW_ACCESS_PORT_OFS;
319
320         if (is_ipu6ep(hw_ver)) {
321                 isys_ipdata.ltr = IPU6EP_LTR_VALUE;
322                 isys_ipdata.memopen_threshold = IPU6EP_MIN_MEMOPEN_TH;
323         }
324
325         if (is_ipu6_tgl(hw_ver))
326                 isys_ipdata.csi2.nports = IPU6_TGL_ISYS_CSI2_NPORTS;
327
328         if (is_ipu6ep_mtl(hw_ver)) {
329                 isys_ipdata.csi2.nports = IPU6EP_MTL_ISYS_CSI2_NPORTS;
330
331                 isys_ipdata.csi2.ctrl0_irq_edge =
332                         IPU6V6_REG_ISYS_CSI_TOP_CTRL0_IRQ_EDGE;
333                 isys_ipdata.csi2.ctrl0_irq_clear =
334                         IPU6V6_REG_ISYS_CSI_TOP_CTRL0_IRQ_CLEAR;
335                 isys_ipdata.csi2.ctrl0_irq_mask =
336                         IPU6V6_REG_ISYS_CSI_TOP_CTRL0_IRQ_MASK;
337                 isys_ipdata.csi2.ctrl0_irq_enable =
338                         IPU6V6_REG_ISYS_CSI_TOP_CTRL0_IRQ_ENABLE;
339                 isys_ipdata.csi2.ctrl0_irq_lnp =
340                         IPU6V6_REG_ISYS_CSI_TOP_CTRL0_IRQ_LEVEL_NOT_PULSE;
341                 isys_ipdata.csi2.ctrl0_irq_status =
342                         IPU6V6_REG_ISYS_CSI_TOP_CTRL0_IRQ_STATUS;
343                 isys_ipdata.csi2.fw_access_port_ofs =
344                         CSI_REG_HUB_FW_ACCESS_PORT_V6OFS;
345                 isys_ipdata.ltr = IPU6EP_MTL_LTR_VALUE;
346                 isys_ipdata.memopen_threshold = IPU6EP_MTL_MIN_MEMOPEN_TH;
347         }
348
349         if (is_ipu6se(hw_ver)) {
350                 isys_ipdata.csi2.nports = IPU6SE_ISYS_CSI2_NPORTS;
351                 isys_ipdata.csi2.irq_mask = IPU6SE_CSI_RX_ERROR_IRQ_MASK;
352                 isys_ipdata.num_parallel_streams = IPU6SE_ISYS_NUM_STREAMS;
353                 isys_ipdata.sram_gran_shift = IPU6SE_SRAM_GRANULARITY_SHIFT;
354                 isys_ipdata.sram_gran_size = IPU6SE_SRAM_GRANULARITY_SIZE;
355                 isys_ipdata.max_sram_size = IPU6SE_MAX_SRAM_SIZE;
356                 isys_ipdata.sensor_type_start =
357                         IPU6SE_FW_ISYS_SENSOR_TYPE_START;
358                 isys_ipdata.sensor_type_end = IPU6SE_FW_ISYS_SENSOR_TYPE_END;
359                 isys_ipdata.max_streams = IPU6SE_ISYS_NUM_STREAMS;
360                 isys_ipdata.max_send_queues = IPU6SE_N_MAX_SEND_QUEUES;
361                 isys_ipdata.max_sram_blocks = IPU6SE_NOF_SRAM_BLOCKS_MAX;
362                 isys_ipdata.max_devq_size = IPU6SE_DEV_SEND_QUEUE_SIZE;
363                 psys_ipdata.hw_variant.spc_offset = IPU6SE_PSYS_SPC_OFFSET;
364         }
365 }
366
367 static struct ipu6_bus_device *
368 ipu6_isys_init(struct pci_dev *pdev, struct device *parent,
369                struct ipu6_buttress_ctrl *ctrl, void __iomem *base,
370                const struct ipu6_isys_internal_pdata *ipdata)
371 {
372         struct device *dev = &pdev->dev;
373         struct ipu6_bus_device *isys_adev;
374         struct ipu6_isys_pdata *pdata;
375         int ret;
376
377         ret = ipu_bridge_init(dev, ipu_bridge_parse_ssdb);
378         if (ret) {
379                 dev_err_probe(dev, ret, "IPU6 bridge init failed\n");
380                 return ERR_PTR(ret);
381         }
382
383         pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
384         if (!pdata)
385                 return ERR_PTR(-ENOMEM);
386
387         pdata->base = base;
388         pdata->ipdata = ipdata;
389
390         isys_adev = ipu6_bus_initialize_device(pdev, parent, pdata, ctrl,
391                                                IPU6_ISYS_NAME);
392         if (IS_ERR(isys_adev)) {
393                 dev_err_probe(dev, PTR_ERR(isys_adev),
394                               "ipu6_bus_initialize_device isys failed\n");
395                 kfree(pdata);
396                 return ERR_CAST(isys_adev);
397         }
398
399         isys_adev->mmu = ipu6_mmu_init(dev, base, ISYS_MMID,
400                                        &ipdata->hw_variant);
401         if (IS_ERR(isys_adev->mmu)) {
402                 dev_err_probe(dev, PTR_ERR(isys_adev->mmu),
403                               "ipu6_mmu_init(isys_adev->mmu) failed\n");
404                 put_device(&isys_adev->auxdev.dev);
405                 kfree(pdata);
406                 return ERR_CAST(isys_adev->mmu);
407         }
408
409         isys_adev->mmu->dev = &isys_adev->auxdev.dev;
410
411         ret = ipu6_bus_add_device(isys_adev);
412         if (ret) {
413                 kfree(pdata);
414                 return ERR_PTR(ret);
415         }
416
417         return isys_adev;
418 }
419
420 static struct ipu6_bus_device *
421 ipu6_psys_init(struct pci_dev *pdev, struct device *parent,
422                struct ipu6_buttress_ctrl *ctrl, void __iomem *base,
423                const struct ipu6_psys_internal_pdata *ipdata)
424 {
425         struct ipu6_bus_device *psys_adev;
426         struct ipu6_psys_pdata *pdata;
427         int ret;
428
429         pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
430         if (!pdata)
431                 return ERR_PTR(-ENOMEM);
432
433         pdata->base = base;
434         pdata->ipdata = ipdata;
435
436         psys_adev = ipu6_bus_initialize_device(pdev, parent, pdata, ctrl,
437                                                IPU6_PSYS_NAME);
438         if (IS_ERR(psys_adev)) {
439                 dev_err_probe(&pdev->dev, PTR_ERR(psys_adev),
440                               "ipu6_bus_initialize_device psys failed\n");
441                 kfree(pdata);
442                 return ERR_CAST(psys_adev);
443         }
444
445         psys_adev->mmu = ipu6_mmu_init(&pdev->dev, base, PSYS_MMID,
446                                        &ipdata->hw_variant);
447         if (IS_ERR(psys_adev->mmu)) {
448                 dev_err_probe(&pdev->dev, PTR_ERR(psys_adev->mmu),
449                               "ipu6_mmu_init(psys_adev->mmu) failed\n");
450                 put_device(&psys_adev->auxdev.dev);
451                 kfree(pdata);
452                 return ERR_CAST(psys_adev->mmu);
453         }
454
455         psys_adev->mmu->dev = &psys_adev->auxdev.dev;
456
457         ret = ipu6_bus_add_device(psys_adev);
458         if (ret) {
459                 kfree(pdata);
460                 return ERR_PTR(ret);
461         }
462
463         return psys_adev;
464 }
465
466 static int ipu6_pci_config_setup(struct pci_dev *dev, u8 hw_ver)
467 {
468         int ret;
469
470         /* disable IPU6 PCI ATS on mtl ES2 */
471         if (is_ipu6ep_mtl(hw_ver) && boot_cpu_data.x86_stepping == 0x2 &&
472             pci_ats_supported(dev))
473                 pci_disable_ats(dev);
474
475         /* No PCI msi capability for IPU6EP */
476         if (is_ipu6ep(hw_ver) || is_ipu6ep_mtl(hw_ver)) {
477                 /* likely do nothing as msi not enabled by default */
478                 pci_disable_msi(dev);
479                 return 0;
480         }
481
482         ret = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_MSI);
483         if (ret < 0)
484                 return dev_err_probe(&dev->dev, ret, "Request msi failed");
485
486         return 0;
487 }
488
489 static void ipu6_configure_vc_mechanism(struct ipu6_device *isp)
490 {
491         u32 val = readl(isp->base + BUTTRESS_REG_BTRS_CTRL);
492
493         if (IPU6_BTRS_ARB_STALL_MODE_VC0 == IPU6_BTRS_ARB_MODE_TYPE_STALL)
494                 val |= BUTTRESS_REG_BTRS_CTRL_STALL_MODE_VC0;
495         else
496                 val &= ~BUTTRESS_REG_BTRS_CTRL_STALL_MODE_VC0;
497
498         if (IPU6_BTRS_ARB_STALL_MODE_VC1 == IPU6_BTRS_ARB_MODE_TYPE_STALL)
499                 val |= BUTTRESS_REG_BTRS_CTRL_STALL_MODE_VC1;
500         else
501                 val &= ~BUTTRESS_REG_BTRS_CTRL_STALL_MODE_VC1;
502
503         writel(val, isp->base + BUTTRESS_REG_BTRS_CTRL);
504 }
505
506 static int ipu6_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
507 {
508         struct ipu6_buttress_ctrl *isys_ctrl = NULL, *psys_ctrl = NULL;
509         struct device *dev = &pdev->dev;
510         void __iomem *isys_base = NULL;
511         void __iomem *psys_base = NULL;
512         struct ipu6_device *isp;
513         phys_addr_t phys;
514         u32 val, version, sku_id;
515         int ret;
516
517         isp = devm_kzalloc(dev, sizeof(*isp), GFP_KERNEL);
518         if (!isp)
519                 return -ENOMEM;
520
521         isp->pdev = pdev;
522         INIT_LIST_HEAD(&isp->devices);
523
524         ret = pcim_enable_device(pdev);
525         if (ret)
526                 return dev_err_probe(dev, ret, "Enable PCI device failed\n");
527
528         phys = pci_resource_start(pdev, IPU6_PCI_BAR);
529         dev_dbg(dev, "IPU6 PCI bar[%u] = %pa\n", IPU6_PCI_BAR, &phys);
530
531         ret = pcim_iomap_regions(pdev, 1 << IPU6_PCI_BAR, pci_name(pdev));
532         if (ret)
533                 return dev_err_probe(dev, ret, "Failed to I/O mem remapping\n");
534
535         isp->base = pcim_iomap_table(pdev)[IPU6_PCI_BAR];
536         pci_set_drvdata(pdev, isp);
537         pci_set_master(pdev);
538
539         isp->cpd_metadata_cmpnt_size = sizeof(struct ipu6_cpd_metadata_cmpnt);
540         switch (id->device) {
541         case PCI_DEVICE_ID_INTEL_IPU6:
542                 isp->hw_ver = IPU6_VER_6;
543                 isp->cpd_fw_name = IPU6_FIRMWARE_NAME;
544                 break;
545         case PCI_DEVICE_ID_INTEL_IPU6SE:
546                 isp->hw_ver = IPU6_VER_6SE;
547                 isp->cpd_fw_name = IPU6SE_FIRMWARE_NAME;
548                 isp->cpd_metadata_cmpnt_size =
549                         sizeof(struct ipu6se_cpd_metadata_cmpnt);
550                 break;
551         case PCI_DEVICE_ID_INTEL_IPU6EP_ADLP:
552         case PCI_DEVICE_ID_INTEL_IPU6EP_RPLP:
553                 isp->hw_ver = IPU6_VER_6EP;
554                 isp->cpd_fw_name = IPU6EP_FIRMWARE_NAME;
555                 break;
556         case PCI_DEVICE_ID_INTEL_IPU6EP_ADLN:
557                 isp->hw_ver = IPU6_VER_6EP;
558                 isp->cpd_fw_name = IPU6EPADLN_FIRMWARE_NAME;
559                 break;
560         case PCI_DEVICE_ID_INTEL_IPU6EP_MTL:
561                 isp->hw_ver = IPU6_VER_6EP_MTL;
562                 isp->cpd_fw_name = IPU6EPMTL_FIRMWARE_NAME;
563                 break;
564         default:
565                 return dev_err_probe(dev, -ENODEV,
566                                      "Unsupported IPU6 device %x\n",
567                                      id->device);
568         }
569
570         ipu6_internal_pdata_init(isp);
571
572         isys_base = isp->base + isys_ipdata.hw_variant.offset;
573         psys_base = isp->base + psys_ipdata.hw_variant.offset;
574
575         ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(39));
576         if (ret)
577                 return dev_err_probe(dev, ret, "Failed to set DMA mask\n");
578
579         ret = dma_set_max_seg_size(dev, UINT_MAX);
580         if (ret)
581                 return dev_err_probe(dev, ret, "Failed to set max_seg_size\n");
582
583         ret = ipu6_pci_config_setup(pdev, isp->hw_ver);
584         if (ret)
585                 return ret;
586
587         ret = ipu6_buttress_init(isp);
588         if (ret)
589                 return ret;
590
591         ret = request_firmware(&isp->cpd_fw, isp->cpd_fw_name, dev);
592         if (ret) {
593                 dev_err_probe(&isp->pdev->dev, ret,
594                               "Requesting signed firmware %s failed\n",
595                               isp->cpd_fw_name);
596                 goto buttress_exit;
597         }
598
599         ret = ipu6_cpd_validate_cpd_file(isp, isp->cpd_fw->data,
600                                          isp->cpd_fw->size);
601         if (ret) {
602                 dev_err_probe(&isp->pdev->dev, ret,
603                               "Failed to validate cpd\n");
604                 goto out_ipu6_bus_del_devices;
605         }
606
607         isys_ctrl = devm_kmemdup(dev, &isys_buttress_ctrl,
608                                  sizeof(isys_buttress_ctrl), GFP_KERNEL);
609         if (!isys_ctrl) {
610                 ret = -ENOMEM;
611                 goto out_ipu6_bus_del_devices;
612         }
613
614         isp->isys = ipu6_isys_init(pdev, dev, isys_ctrl, isys_base,
615                                    &isys_ipdata);
616         if (IS_ERR(isp->isys)) {
617                 ret = PTR_ERR(isp->isys);
618                 goto out_ipu6_bus_del_devices;
619         }
620
621         psys_ctrl = devm_kmemdup(dev, &psys_buttress_ctrl,
622                                  sizeof(psys_buttress_ctrl), GFP_KERNEL);
623         if (!psys_ctrl) {
624                 ret = -ENOMEM;
625                 goto out_ipu6_bus_del_devices;
626         }
627
628         isp->psys = ipu6_psys_init(pdev, &isp->isys->auxdev.dev, psys_ctrl,
629                                    psys_base, &psys_ipdata);
630         if (IS_ERR(isp->psys)) {
631                 ret = PTR_ERR(isp->psys);
632                 goto out_ipu6_bus_del_devices;
633         }
634
635         ret = pm_runtime_resume_and_get(&isp->psys->auxdev.dev);
636         if (ret < 0)
637                 goto out_ipu6_bus_del_devices;
638
639         ret = ipu6_mmu_hw_init(isp->psys->mmu);
640         if (ret) {
641                 dev_err_probe(&isp->pdev->dev, ret,
642                               "Failed to set MMU hardware\n");
643                 goto out_ipu6_bus_del_devices;
644         }
645
646         ret = ipu6_buttress_map_fw_image(isp->psys, isp->cpd_fw,
647                                          &isp->psys->fw_sgt);
648         if (ret) {
649                 dev_err_probe(&isp->pdev->dev, ret, "failed to map fw image\n");
650                 goto out_ipu6_bus_del_devices;
651         }
652
653         ret = ipu6_cpd_create_pkg_dir(isp->psys, isp->cpd_fw->data);
654         if (ret) {
655                 dev_err_probe(&isp->pdev->dev, ret,
656                               "failed to create pkg dir\n");
657                 goto out_ipu6_bus_del_devices;
658         }
659
660         ret = devm_request_threaded_irq(dev, pdev->irq, ipu6_buttress_isr,
661                                         ipu6_buttress_isr_threaded,
662                                         IRQF_SHARED, IPU6_NAME, isp);
663         if (ret) {
664                 dev_err_probe(dev, ret, "Requesting irq failed\n");
665                 goto out_ipu6_bus_del_devices;
666         }
667
668         ret = ipu6_buttress_authenticate(isp);
669         if (ret) {
670                 dev_err_probe(&isp->pdev->dev, ret,
671                               "FW authentication failed\n");
672                 goto out_free_irq;
673         }
674
675         ipu6_mmu_hw_cleanup(isp->psys->mmu);
676         pm_runtime_put(&isp->psys->auxdev.dev);
677
678         /* Configure the arbitration mechanisms for VC requests */
679         ipu6_configure_vc_mechanism(isp);
680
681         val = readl(isp->base + BUTTRESS_REG_SKU);
682         sku_id = FIELD_GET(GENMASK(6, 4), val);
683         version = FIELD_GET(GENMASK(3, 0), val);
684         dev_info(dev, "IPU%u-v%u[%x] hardware version %d\n", version, sku_id,
685                  pdev->device, isp->hw_ver);
686
687         pm_runtime_put_noidle(dev);
688         pm_runtime_allow(dev);
689
690         isp->bus_ready_to_probe = true;
691
692         return 0;
693
694 out_free_irq:
695         devm_free_irq(dev, pdev->irq, isp);
696 out_ipu6_bus_del_devices:
697         if (isp->psys) {
698                 ipu6_cpd_free_pkg_dir(isp->psys);
699                 ipu6_buttress_unmap_fw_image(isp->psys, &isp->psys->fw_sgt);
700         }
701         if (!IS_ERR_OR_NULL(isp->psys) && !IS_ERR_OR_NULL(isp->psys->mmu))
702                 ipu6_mmu_cleanup(isp->psys->mmu);
703         if (!IS_ERR_OR_NULL(isp->isys) && !IS_ERR_OR_NULL(isp->isys->mmu))
704                 ipu6_mmu_cleanup(isp->isys->mmu);
705         ipu6_bus_del_devices(pdev);
706         release_firmware(isp->cpd_fw);
707 buttress_exit:
708         ipu6_buttress_exit(isp);
709
710         return ret;
711 }
712
713 static void ipu6_pci_remove(struct pci_dev *pdev)
714 {
715         struct ipu6_device *isp = pci_get_drvdata(pdev);
716         struct ipu6_mmu *isys_mmu = isp->isys->mmu;
717         struct ipu6_mmu *psys_mmu = isp->psys->mmu;
718
719         devm_free_irq(&pdev->dev, pdev->irq, isp);
720         ipu6_cpd_free_pkg_dir(isp->psys);
721
722         ipu6_buttress_unmap_fw_image(isp->psys, &isp->psys->fw_sgt);
723         ipu6_buttress_exit(isp);
724
725         ipu6_bus_del_devices(pdev);
726
727         pm_runtime_forbid(&pdev->dev);
728         pm_runtime_get_noresume(&pdev->dev);
729
730         release_firmware(isp->cpd_fw);
731
732         ipu6_mmu_cleanup(psys_mmu);
733         ipu6_mmu_cleanup(isys_mmu);
734 }
735
736 static void ipu6_pci_reset_prepare(struct pci_dev *pdev)
737 {
738         struct ipu6_device *isp = pci_get_drvdata(pdev);
739
740         pm_runtime_forbid(&isp->pdev->dev);
741 }
742
743 static void ipu6_pci_reset_done(struct pci_dev *pdev)
744 {
745         struct ipu6_device *isp = pci_get_drvdata(pdev);
746
747         ipu6_buttress_restore(isp);
748         if (isp->secure_mode)
749                 ipu6_buttress_reset_authentication(isp);
750
751         isp->need_ipc_reset = true;
752         pm_runtime_allow(&isp->pdev->dev);
753 }
754
755 /*
756  * PCI base driver code requires driver to provide these to enable
757  * PCI device level PM state transitions (D0<->D3)
758  */
759 static int ipu6_suspend(struct device *dev)
760 {
761         return 0;
762 }
763
764 static int ipu6_resume(struct device *dev)
765 {
766         struct pci_dev *pdev = to_pci_dev(dev);
767         struct ipu6_device *isp = pci_get_drvdata(pdev);
768         struct ipu6_buttress *b = &isp->buttress;
769         int ret;
770
771         /* Configure the arbitration mechanisms for VC requests */
772         ipu6_configure_vc_mechanism(isp);
773
774         isp->secure_mode = ipu6_buttress_get_secure_mode(isp);
775         dev_info(dev, "IPU6 in %s mode\n",
776                  isp->secure_mode ? "secure" : "non-secure");
777
778         ipu6_buttress_restore(isp);
779
780         ret = ipu6_buttress_ipc_reset(isp, &b->cse);
781         if (ret)
782                 dev_err(&isp->pdev->dev, "IPC reset protocol failed!\n");
783
784         ret = pm_runtime_resume_and_get(&isp->psys->auxdev.dev);
785         if (ret < 0) {
786                 dev_err(&isp->psys->auxdev.dev, "Failed to get runtime PM\n");
787                 return 0;
788         }
789
790         ret = ipu6_buttress_authenticate(isp);
791         if (ret)
792                 dev_err(&isp->pdev->dev, "FW authentication failed(%d)\n", ret);
793
794         pm_runtime_put(&isp->psys->auxdev.dev);
795
796         return 0;
797 }
798
799 static int ipu6_runtime_resume(struct device *dev)
800 {
801         struct pci_dev *pdev = to_pci_dev(dev);
802         struct ipu6_device *isp = pci_get_drvdata(pdev);
803         int ret;
804
805         ipu6_configure_vc_mechanism(isp);
806         ipu6_buttress_restore(isp);
807
808         if (isp->need_ipc_reset) {
809                 struct ipu6_buttress *b = &isp->buttress;
810
811                 isp->need_ipc_reset = false;
812                 ret = ipu6_buttress_ipc_reset(isp, &b->cse);
813                 if (ret)
814                         dev_err(&isp->pdev->dev, "IPC reset protocol failed\n");
815         }
816
817         return 0;
818 }
819
820 static const struct dev_pm_ops ipu6_pm_ops = {
821         SYSTEM_SLEEP_PM_OPS(&ipu6_suspend, &ipu6_resume)
822         RUNTIME_PM_OPS(&ipu6_suspend, &ipu6_runtime_resume, NULL)
823 };
824
825 MODULE_DEVICE_TABLE(pci, ipu6_pci_tbl);
826
827 static const struct pci_error_handlers pci_err_handlers = {
828         .reset_prepare = ipu6_pci_reset_prepare,
829         .reset_done = ipu6_pci_reset_done,
830 };
831
832 static struct pci_driver ipu6_pci_driver = {
833         .name = IPU6_NAME,
834         .id_table = ipu6_pci_tbl,
835         .probe = ipu6_pci_probe,
836         .remove = ipu6_pci_remove,
837         .driver = {
838                 .pm = pm_ptr(&ipu6_pm_ops),
839         },
840         .err_handler = &pci_err_handlers,
841 };
842
843 module_pci_driver(ipu6_pci_driver);
844
845 MODULE_IMPORT_NS(INTEL_IPU_BRIDGE);
846 MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>");
847 MODULE_AUTHOR("Tianshu Qiu <tian.shu.qiu@intel.com>");
848 MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>");
849 MODULE_AUTHOR("Qingwu Zhang <qingwu.zhang@intel.com>");
850 MODULE_AUTHOR("Yunliang Ding <yunliang.ding@intel.com>");
851 MODULE_AUTHOR("Hongju Wang <hongju.wang@intel.com>");
852 MODULE_LICENSE("GPL");
853 MODULE_DESCRIPTION("Intel IPU6 PCI driver");