| 1 | /* SPDX-License-Identifier: GPL-2.0 | 
|---|
| 2 | * | 
|---|
| 3 | * CDX bus public interface | 
|---|
| 4 | * | 
|---|
| 5 | * Copyright (C) 2022-2023, Advanced Micro Devices, Inc. | 
|---|
| 6 | * | 
|---|
| 7 | */ | 
|---|
| 8 |  | 
|---|
| 9 | #ifndef _CDX_BUS_H_ | 
|---|
| 10 | #define _CDX_BUS_H_ | 
|---|
| 11 |  | 
|---|
| 12 | #include <linux/device.h> | 
|---|
| 13 | #include <linux/list.h> | 
|---|
| 14 | #include <linux/mod_devicetable.h> | 
|---|
| 15 | #include <linux/msi.h> | 
|---|
| 16 |  | 
|---|
| 17 | #define MAX_CDX_DEV_RESOURCES	4 | 
|---|
| 18 | #define CDX_CONTROLLER_ID_SHIFT 4 | 
|---|
| 19 | #define CDX_BUS_NUM_MASK 0xF | 
|---|
| 20 |  | 
|---|
| 21 | /* Forward declaration for CDX controller */ | 
|---|
| 22 | struct cdx_controller; | 
|---|
| 23 |  | 
|---|
| 24 | enum { | 
|---|
| 25 | CDX_DEV_MSI_CONF, | 
|---|
| 26 | CDX_DEV_BUS_MASTER_CONF, | 
|---|
| 27 | CDX_DEV_RESET_CONF, | 
|---|
| 28 | CDX_DEV_MSI_ENABLE, | 
|---|
| 29 | }; | 
|---|
| 30 |  | 
|---|
| 31 | struct cdx_msi_config { | 
|---|
| 32 | u64 addr; | 
|---|
| 33 | u32 data; | 
|---|
| 34 | u16 msi_index; | 
|---|
| 35 | }; | 
|---|
| 36 |  | 
|---|
| 37 | struct cdx_device_config { | 
|---|
| 38 | u8 type; | 
|---|
| 39 | union { | 
|---|
| 40 | struct cdx_msi_config msi; | 
|---|
| 41 | bool bus_master_enable; | 
|---|
| 42 | bool msi_enable; | 
|---|
| 43 | }; | 
|---|
| 44 | }; | 
|---|
| 45 |  | 
|---|
| 46 | typedef int (*cdx_bus_enable_cb)(struct cdx_controller *cdx, u8 bus_num); | 
|---|
| 47 |  | 
|---|
| 48 | typedef int (*cdx_bus_disable_cb)(struct cdx_controller *cdx, u8 bus_num); | 
|---|
| 49 |  | 
|---|
| 50 | typedef int (*cdx_scan_cb)(struct cdx_controller *cdx); | 
|---|
| 51 |  | 
|---|
| 52 | typedef int (*cdx_dev_configure_cb)(struct cdx_controller *cdx, | 
|---|
| 53 | u8 bus_num, u8 dev_num, | 
|---|
| 54 | struct cdx_device_config *dev_config); | 
|---|
| 55 |  | 
|---|
| 56 | /** | 
|---|
| 57 | * CDX_DEVICE - macro used to describe a specific CDX device | 
|---|
| 58 | * @vend: the 16 bit CDX Vendor ID | 
|---|
| 59 | * @dev: the 16 bit CDX Device ID | 
|---|
| 60 | * | 
|---|
| 61 | * This macro is used to create a struct cdx_device_id that matches a | 
|---|
| 62 | * specific device. The subvendor and subdevice fields will be set to | 
|---|
| 63 | * CDX_ANY_ID. | 
|---|
| 64 | */ | 
|---|
| 65 | #define CDX_DEVICE(vend, dev) \ | 
|---|
| 66 | .vendor = (vend), .device = (dev), \ | 
|---|
| 67 | .subvendor = CDX_ANY_ID, .subdevice = CDX_ANY_ID | 
|---|
| 68 |  | 
|---|
| 69 | /** | 
|---|
| 70 | * CDX_DEVICE_DRIVER_OVERRIDE - macro used to describe a CDX device with | 
|---|
| 71 | *                              override_only flags. | 
|---|
| 72 | * @vend: the 16 bit CDX Vendor ID | 
|---|
| 73 | * @dev: the 16 bit CDX Device ID | 
|---|
| 74 | * @driver_override: the 32 bit CDX Device override_only | 
|---|
| 75 | * | 
|---|
| 76 | * This macro is used to create a struct cdx_device_id that matches only a | 
|---|
| 77 | * driver_override device. The subvendor and subdevice fields will be set to | 
|---|
| 78 | * CDX_ANY_ID. | 
|---|
| 79 | */ | 
|---|
| 80 | #define CDX_DEVICE_DRIVER_OVERRIDE(vend, dev, driver_override) \ | 
|---|
| 81 | .vendor = (vend), .device = (dev), .subvendor = CDX_ANY_ID,\ | 
|---|
| 82 | .subdevice = CDX_ANY_ID, .override_only = (driver_override) | 
|---|
| 83 |  | 
|---|
| 84 | /** | 
|---|
| 85 | * struct cdx_ops - Callbacks supported by CDX controller. | 
|---|
| 86 | * @bus_enable: enable bus on the controller | 
|---|
| 87 | * @bus_disable: disable bus on the controller | 
|---|
| 88 | * @scan: scan the devices on the controller | 
|---|
| 89 | * @dev_configure: configuration like reset, master_enable, | 
|---|
| 90 | *		   msi_config etc for a CDX device | 
|---|
| 91 | */ | 
|---|
| 92 | struct cdx_ops { | 
|---|
| 93 | cdx_bus_enable_cb bus_enable; | 
|---|
| 94 | cdx_bus_disable_cb bus_disable; | 
|---|
| 95 | cdx_scan_cb scan; | 
|---|
| 96 | cdx_dev_configure_cb dev_configure; | 
|---|
| 97 | }; | 
|---|
| 98 |  | 
|---|
| 99 | /** | 
|---|
| 100 | * struct cdx_controller: CDX controller object | 
|---|
| 101 | * @dev: Linux device associated with the CDX controller. | 
|---|
| 102 | * @priv: private data | 
|---|
| 103 | * @msi_domain: MSI domain | 
|---|
| 104 | * @id: Controller ID | 
|---|
| 105 | * @controller_registered: controller registered with bus | 
|---|
| 106 | * @ops: CDX controller ops | 
|---|
| 107 | */ | 
|---|
| 108 | struct cdx_controller { | 
|---|
| 109 | struct device *dev; | 
|---|
| 110 | void *priv; | 
|---|
| 111 | struct irq_domain *msi_domain; | 
|---|
| 112 | u32 id; | 
|---|
| 113 | bool controller_registered; | 
|---|
| 114 | struct cdx_ops *ops; | 
|---|
| 115 | }; | 
|---|
| 116 |  | 
|---|
| 117 | /** | 
|---|
| 118 | * struct cdx_device - CDX device object | 
|---|
| 119 | * @dev: Linux driver model device object | 
|---|
| 120 | * @cdx: CDX controller associated with the device | 
|---|
| 121 | * @vendor: Vendor ID for CDX device | 
|---|
| 122 | * @device: Device ID for CDX device | 
|---|
| 123 | * @subsystem_vendor: Subsystem Vendor ID for CDX device | 
|---|
| 124 | * @subsystem_device: Subsystem Device ID for CDX device | 
|---|
| 125 | * @class: Class for the CDX device | 
|---|
| 126 | * @revision: Revision of the CDX device | 
|---|
| 127 | * @bus_num: Bus number for this CDX device | 
|---|
| 128 | * @dev_num: Device number for this device | 
|---|
| 129 | * @res: array of MMIO region entries | 
|---|
| 130 | * @res_attr: resource binary attribute | 
|---|
| 131 | * @debugfs_dir: debugfs directory for this device | 
|---|
| 132 | * @res_count: number of valid MMIO regions | 
|---|
| 133 | * @dma_mask: Default DMA mask | 
|---|
| 134 | * @flags: CDX device flags | 
|---|
| 135 | * @req_id: Requestor ID associated with CDX device | 
|---|
| 136 | * @is_bus: Is this bus device | 
|---|
| 137 | * @enabled: is this bus enabled | 
|---|
| 138 | * @msi_dev_id: MSI Device ID associated with CDX device | 
|---|
| 139 | * @num_msi: Number of MSI's supported by the device | 
|---|
| 140 | * @driver_override: driver name to force a match; do not set directly, | 
|---|
| 141 | *                   because core frees it; use driver_set_override() to | 
|---|
| 142 | *                   set or clear it. | 
|---|
| 143 | * @irqchip_lock: lock to synchronize irq/msi configuration | 
|---|
| 144 | * @msi_write_pending: MSI write pending for this device | 
|---|
| 145 | */ | 
|---|
| 146 | struct cdx_device { | 
|---|
| 147 | struct device dev; | 
|---|
| 148 | struct cdx_controller *cdx; | 
|---|
| 149 | u16 vendor; | 
|---|
| 150 | u16 device; | 
|---|
| 151 | u16 subsystem_vendor; | 
|---|
| 152 | u16 subsystem_device; | 
|---|
| 153 | u32 class; | 
|---|
| 154 | u8 revision; | 
|---|
| 155 | u8 bus_num; | 
|---|
| 156 | u8 dev_num; | 
|---|
| 157 | struct resource res[MAX_CDX_DEV_RESOURCES]; | 
|---|
| 158 | struct bin_attribute *res_attr[MAX_CDX_DEV_RESOURCES]; | 
|---|
| 159 | struct dentry *debugfs_dir; | 
|---|
| 160 | u8 res_count; | 
|---|
| 161 | u64 dma_mask; | 
|---|
| 162 | u16 flags; | 
|---|
| 163 | u32 req_id; | 
|---|
| 164 | bool is_bus; | 
|---|
| 165 | bool enabled; | 
|---|
| 166 | u32 msi_dev_id; | 
|---|
| 167 | u32 num_msi; | 
|---|
| 168 | const char *driver_override; | 
|---|
| 169 | struct mutex irqchip_lock; | 
|---|
| 170 | bool msi_write_pending; | 
|---|
| 171 | }; | 
|---|
| 172 |  | 
|---|
| 173 | #define to_cdx_device(_dev) \ | 
|---|
| 174 | container_of(_dev, struct cdx_device, dev) | 
|---|
| 175 |  | 
|---|
| 176 | #define cdx_resource_start(dev, num)	((dev)->res[(num)].start) | 
|---|
| 177 | #define cdx_resource_end(dev, num)	((dev)->res[(num)].end) | 
|---|
| 178 | #define cdx_resource_flags(dev, num)	((dev)->res[(num)].flags) | 
|---|
| 179 | #define cdx_resource_len(dev, num) \ | 
|---|
| 180 | ((cdx_resource_start((dev), (num)) == 0 &&	\ | 
|---|
| 181 | cdx_resource_end((dev), (num)) ==		\ | 
|---|
| 182 | cdx_resource_start((dev), (num))) ? 0 :	\ | 
|---|
| 183 | (cdx_resource_end((dev), (num)) -		\ | 
|---|
| 184 | cdx_resource_start((dev), (num)) + 1)) | 
|---|
| 185 | /** | 
|---|
| 186 | * struct cdx_driver - CDX device driver | 
|---|
| 187 | * @driver: Generic device driver | 
|---|
| 188 | * @match_id_table: table of supported device matching Ids | 
|---|
| 189 | * @probe: Function called when a device is added | 
|---|
| 190 | * @remove: Function called when a device is removed | 
|---|
| 191 | * @shutdown: Function called at shutdown time to quiesce the device | 
|---|
| 192 | * @reset_prepare: Function called before is reset to notify driver | 
|---|
| 193 | * @reset_done: Function called after reset is complete to notify driver | 
|---|
| 194 | * @driver_managed_dma: Device driver doesn't use kernel DMA API for DMA. | 
|---|
| 195 | *		For most device drivers, no need to care about this flag | 
|---|
| 196 | *		as long as all DMAs are handled through the kernel DMA API. | 
|---|
| 197 | *		For some special ones, for example VFIO drivers, they know | 
|---|
| 198 | *		how to manage the DMA themselves and set this flag so that | 
|---|
| 199 | *		the IOMMU layer will allow them to setup and manage their | 
|---|
| 200 | *		own I/O address space. | 
|---|
| 201 | */ | 
|---|
| 202 | struct cdx_driver { | 
|---|
| 203 | struct device_driver driver; | 
|---|
| 204 | const struct cdx_device_id *match_id_table; | 
|---|
| 205 | int (*probe)(struct cdx_device *dev); | 
|---|
| 206 | int (*remove)(struct cdx_device *dev); | 
|---|
| 207 | void (*shutdown)(struct cdx_device *dev); | 
|---|
| 208 | void (*reset_prepare)(struct cdx_device *dev); | 
|---|
| 209 | void (*reset_done)(struct cdx_device *dev); | 
|---|
| 210 | bool driver_managed_dma; | 
|---|
| 211 | }; | 
|---|
| 212 |  | 
|---|
| 213 | #define to_cdx_driver(_drv) \ | 
|---|
| 214 | container_of_const(_drv, struct cdx_driver, driver) | 
|---|
| 215 |  | 
|---|
| 216 | /* Macro to avoid include chaining to get THIS_MODULE */ | 
|---|
| 217 | #define cdx_driver_register(drv) \ | 
|---|
| 218 | __cdx_driver_register(drv, THIS_MODULE) | 
|---|
| 219 |  | 
|---|
| 220 | /** | 
|---|
| 221 | * __cdx_driver_register - registers a CDX device driver | 
|---|
| 222 | * @cdx_driver: CDX driver to register | 
|---|
| 223 | * @owner: module owner | 
|---|
| 224 | * | 
|---|
| 225 | * Return: -errno on failure, 0 on success. | 
|---|
| 226 | */ | 
|---|
| 227 | int __must_check __cdx_driver_register(struct cdx_driver *cdx_driver, | 
|---|
| 228 | struct module *owner); | 
|---|
| 229 |  | 
|---|
| 230 | /** | 
|---|
| 231 | * cdx_driver_unregister - unregisters a device driver from the | 
|---|
| 232 | * CDX bus. | 
|---|
| 233 | * @cdx_driver: CDX driver to register | 
|---|
| 234 | */ | 
|---|
| 235 | void cdx_driver_unregister(struct cdx_driver *cdx_driver); | 
|---|
| 236 |  | 
|---|
| 237 | extern struct bus_type cdx_bus_type; | 
|---|
| 238 |  | 
|---|
| 239 | /** | 
|---|
| 240 | * cdx_dev_reset - Reset CDX device | 
|---|
| 241 | * @dev: device pointer | 
|---|
| 242 | * | 
|---|
| 243 | * Return: 0 for success, -errno on failure | 
|---|
| 244 | */ | 
|---|
| 245 | int cdx_dev_reset(struct device *dev); | 
|---|
| 246 |  | 
|---|
| 247 | /** | 
|---|
| 248 | * cdx_set_master - enables bus-mastering for CDX device | 
|---|
| 249 | * @cdx_dev: the CDX device to enable | 
|---|
| 250 | * | 
|---|
| 251 | * Return: 0 for success, -errno on failure | 
|---|
| 252 | */ | 
|---|
| 253 | int cdx_set_master(struct cdx_device *cdx_dev); | 
|---|
| 254 |  | 
|---|
| 255 | /** | 
|---|
| 256 | * cdx_clear_master - disables bus-mastering for CDX device | 
|---|
| 257 | * @cdx_dev: the CDX device to disable | 
|---|
| 258 | * | 
|---|
| 259 | * Return: 0 for success, -errno on failure | 
|---|
| 260 | */ | 
|---|
| 261 | int cdx_clear_master(struct cdx_device *cdx_dev); | 
|---|
| 262 |  | 
|---|
| 263 | #ifdef CONFIG_GENERIC_MSI_IRQ | 
|---|
| 264 | /** | 
|---|
| 265 | * cdx_enable_msi - Enable MSI for the CDX device. | 
|---|
| 266 | * @cdx_dev: device pointer | 
|---|
| 267 | * | 
|---|
| 268 | * Return: 0 for success, -errno on failure | 
|---|
| 269 | */ | 
|---|
| 270 | int cdx_enable_msi(struct cdx_device *cdx_dev); | 
|---|
| 271 |  | 
|---|
| 272 | /** | 
|---|
| 273 | * cdx_disable_msi - Disable MSI for the CDX device. | 
|---|
| 274 | * @cdx_dev: device pointer | 
|---|
| 275 | */ | 
|---|
| 276 | void cdx_disable_msi(struct cdx_device *cdx_dev); | 
|---|
| 277 |  | 
|---|
| 278 | #else /* CONFIG_GENERIC_MSI_IRQ */ | 
|---|
| 279 |  | 
|---|
| 280 | static inline int cdx_enable_msi(struct cdx_device *cdx_dev) | 
|---|
| 281 | { | 
|---|
| 282 | return -ENODEV; | 
|---|
| 283 | } | 
|---|
| 284 |  | 
|---|
| 285 | static inline void cdx_disable_msi(struct cdx_device *cdx_dev) | 
|---|
| 286 | { | 
|---|
| 287 | } | 
|---|
| 288 |  | 
|---|
| 289 | #endif /* CONFIG_GENERIC_MSI_IRQ */ | 
|---|
| 290 |  | 
|---|
| 291 | #endif /* _CDX_BUS_H_ */ | 
|---|
| 292 |  | 
|---|