| 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 const 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 | |