1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2013 - 2024 Intel Corporation
6 #include <linux/auxiliary_bus.h>
7 #include <linux/device.h>
8 #include <linux/dma-mapping.h>
10 #include <linux/list.h>
11 #include <linux/mutex.h>
12 #include <linux/pci.h>
13 #include <linux/pm_domain.h>
14 #include <linux/pm_runtime.h>
15 #include <linux/slab.h>
19 #include "ipu6-buttress.h"
22 static int bus_pm_runtime_suspend(struct device
*dev
)
24 struct ipu6_bus_device
*adev
= to_ipu6_bus_device(dev
);
27 ret
= pm_generic_runtime_suspend(dev
);
31 ret
= ipu6_buttress_power(dev
, adev
->ctrl
, false);
35 dev_err(dev
, "power down failed!\n");
37 /* Powering down failed, attempt to resume device now */
38 ret
= pm_generic_runtime_resume(dev
);
45 static int bus_pm_runtime_resume(struct device
*dev
)
47 struct ipu6_bus_device
*adev
= to_ipu6_bus_device(dev
);
50 ret
= ipu6_buttress_power(dev
, adev
->ctrl
, true);
54 ret
= pm_generic_runtime_resume(dev
);
61 ipu6_buttress_power(dev
, adev
->ctrl
, false);
66 static struct dev_pm_domain ipu6_bus_pm_domain
= {
68 .runtime_suspend
= bus_pm_runtime_suspend
,
69 .runtime_resume
= bus_pm_runtime_resume
,
73 static DEFINE_MUTEX(ipu6_bus_mutex
);
75 static void ipu6_bus_release(struct device
*dev
)
77 struct ipu6_bus_device
*adev
= to_ipu6_bus_device(dev
);
83 struct ipu6_bus_device
*
84 ipu6_bus_initialize_device(struct pci_dev
*pdev
, struct device
*parent
,
85 void *pdata
, struct ipu6_buttress_ctrl
*ctrl
,
88 struct auxiliary_device
*auxdev
;
89 struct ipu6_bus_device
*adev
;
90 struct ipu6_device
*isp
= pci_get_drvdata(pdev
);
93 adev
= kzalloc(sizeof(*adev
), GFP_KERNEL
);
95 return ERR_PTR(-ENOMEM
);
100 auxdev
= &adev
->auxdev
;
102 auxdev
->id
= (pci_domain_nr(pdev
->bus
) << 16) |
103 PCI_DEVID(pdev
->bus
->number
, pdev
->devfn
);
105 auxdev
->dev
.parent
= parent
;
106 auxdev
->dev
.release
= ipu6_bus_release
;
108 ret
= auxiliary_device_init(auxdev
);
110 dev_err(&isp
->pdev
->dev
, "auxiliary device init failed (%d)\n",
116 dev_pm_domain_set(&auxdev
->dev
, &ipu6_bus_pm_domain
);
118 pm_runtime_forbid(&adev
->auxdev
.dev
);
119 pm_runtime_enable(&adev
->auxdev
.dev
);
124 int ipu6_bus_add_device(struct ipu6_bus_device
*adev
)
126 struct auxiliary_device
*auxdev
= &adev
->auxdev
;
129 ret
= auxiliary_device_add(auxdev
);
131 auxiliary_device_uninit(auxdev
);
135 mutex_lock(&ipu6_bus_mutex
);
136 list_add(&adev
->list
, &adev
->isp
->devices
);
137 mutex_unlock(&ipu6_bus_mutex
);
139 pm_runtime_allow(&auxdev
->dev
);
144 void ipu6_bus_del_devices(struct pci_dev
*pdev
)
146 struct ipu6_device
*isp
= pci_get_drvdata(pdev
);
147 struct ipu6_bus_device
*adev
, *save
;
149 mutex_lock(&ipu6_bus_mutex
);
151 list_for_each_entry_safe(adev
, save
, &isp
->devices
, list
) {
152 pm_runtime_disable(&adev
->auxdev
.dev
);
153 list_del(&adev
->list
);
154 auxiliary_device_delete(&adev
->auxdev
);
155 auxiliary_device_uninit(&adev
->auxdev
);
158 mutex_unlock(&ipu6_bus_mutex
);