1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * UWB Multi-interface Controller support. 4 * 5 * Copyright (C) 2007 Cambridge Silicon Radio Ltd. 6 * 7 * UMC (UWB Multi-interface Controller) capabilities (e.g., radio 8 * controller, host controller) are presented as devices on the "umc" 9 * bus. 10 * 11 * The radio controller is not strictly a UMC capability but it's 12 * useful to present it as such. 13 * 14 * References: 15 * 16 * [WHCI] Wireless Host Controller Interface Specification for 17 * Certified Wireless Universal Serial Bus, revision 0.95. 18 * 19 * How this works is kind of convoluted but simple. The whci.ko driver 20 * loads when WHCI devices are detected. These WHCI devices expose 21 * many devices in the same PCI function (they couldn't have reused 22 * functions, no), so for each PCI function that exposes these many 23 * devices, whci ceates a umc_dev [whci_probe() -> whci_add_cap()] 24 * with umc_device_create() and adds it to the bus with 25 * umc_device_register(). 26 * 27 * umc_device_register() calls device_register() which will push the 28 * bus management code to load your UMC driver's somehting_probe() 29 * that you have registered for that capability code. 30 * 31 * Now when the WHCI device is removed, whci_remove() will go over 32 * each umc_dev assigned to each of the PCI function's capabilities 33 * and through whci_del_cap() call umc_device_unregister() each 34 * created umc_dev. Of course, if you are bound to the device, your 35 * driver's something_remove() will be called. 36 */ 37 38 #ifndef _LINUX_UWB_UMC_H_ 39 #define _LINUX_UWB_UMC_H_ 40 41 #include <linux/device.h> 42 #include <linux/pci.h> 43 44 /* 45 * UMC capability IDs. 46 * 47 * 0x00 is reserved so use it for the radio controller device. 48 * 49 * [WHCI] table 2-8 50 */ 51 #define UMC_CAP_ID_WHCI_RC 0x00 /* radio controller */ 52 #define UMC_CAP_ID_WHCI_WUSB_HC 0x01 /* WUSB host controller */ 53 54 /** 55 * struct umc_dev - UMC capability device 56 * 57 * @version: version of the specification this capability conforms to. 58 * @cap_id: capability ID. 59 * @bar: PCI Bar (64 bit) where the resource lies 60 * @resource: register space resource. 61 * @irq: interrupt line. 62 */ 63 struct umc_dev { 64 u16 version; 65 u8 cap_id; 66 u8 bar; 67 struct resource resource; 68 unsigned irq; 69 struct device dev; 70 }; 71 72 #define to_umc_dev(d) container_of(d, struct umc_dev, dev) 73 74 /** 75 * struct umc_driver - UMC capability driver 76 * @cap_id: supported capability ID. 77 * @match: driver specific capability matching function. 78 * @match_data: driver specific data for match() (e.g., a 79 * table of pci_device_id's if umc_match_pci_id() is used). 80 */ 81 struct umc_driver { 82 char *name; 83 u8 cap_id; 84 int (*match)(struct umc_driver *, struct umc_dev *); 85 const void *match_data; 86 87 int (*probe)(struct umc_dev *); 88 void (*remove)(struct umc_dev *); 89 int (*pre_reset)(struct umc_dev *); 90 int (*post_reset)(struct umc_dev *); 91 92 struct device_driver driver; 93 }; 94 95 #define to_umc_driver(d) container_of(d, struct umc_driver, driver) 96 97 extern struct bus_type umc_bus_type; 98 99 struct umc_dev *umc_device_create(struct device *parent, int n); 100 int __must_check umc_device_register(struct umc_dev *umc); 101 void umc_device_unregister(struct umc_dev *umc); 102 103 int __must_check __umc_driver_register(struct umc_driver *umc_drv, 104 struct module *mod, 105 const char *mod_name); 106 107 /** 108 * umc_driver_register - register a UMC capabiltity driver. 109 * @umc_drv: pointer to the driver. 110 */ 111 #define umc_driver_register(umc_drv) \ 112 __umc_driver_register(umc_drv, THIS_MODULE, KBUILD_MODNAME) 113 114 void umc_driver_unregister(struct umc_driver *umc_drv); 115 116 /* 117 * Utility function you can use to match (umc_driver->match) against a 118 * null-terminated array of 'struct pci_device_id' in 119 * umc_driver->match_data. 120 */ 121 int umc_match_pci_id(struct umc_driver *umc_drv, struct umc_dev *umc); 122 123 /** 124 * umc_parent_pci_dev - return the UMC's parent PCI device or NULL if none 125 * @umc_dev: UMC device whose parent PCI device we are looking for 126 * 127 * DIRTY!!! DON'T RELY ON THIS 128 * 129 * FIXME: This is as dirty as it gets, but we need some way to check 130 * the correct type of umc_dev->parent (so that for example, we can 131 * cast to pci_dev). Casting to pci_dev is necessary because at some 132 * point we need to request resources from the device. Mapping is 133 * easily over come (ioremap and stuff are bus agnostic), but hooking 134 * up to some error handlers (such as pci error handlers) might need 135 * this. 136 * 137 * THIS might (probably will) be removed in the future, so don't count 138 * on it. 139 */ 140 static inline struct pci_dev *umc_parent_pci_dev(struct umc_dev *umc_dev) 141 { 142 struct pci_dev *pci_dev = NULL; 143 if (dev_is_pci(umc_dev->dev.parent)) 144 pci_dev = to_pci_dev(umc_dev->dev.parent); 145 return pci_dev; 146 } 147 148 /** 149 * umc_dev_get() - reference a UMC device. 150 * @umc_dev: Pointer to UMC device. 151 * 152 * NOTE: we are assuming in this whole scheme that the parent device 153 * is referenced at _probe() time and unreferenced at _remove() 154 * time by the parent's subsystem. 155 */ 156 static inline struct umc_dev *umc_dev_get(struct umc_dev *umc_dev) 157 { 158 get_device(&umc_dev->dev); 159 return umc_dev; 160 } 161 162 /** 163 * umc_dev_put() - unreference a UMC device. 164 * @umc_dev: Pointer to UMC device. 165 */ 166 static inline void umc_dev_put(struct umc_dev *umc_dev) 167 { 168 put_device(&umc_dev->dev); 169 } 170 171 /** 172 * umc_set_drvdata - set UMC device's driver data. 173 * @umc_dev: Pointer to UMC device. 174 * @data: Data to set. 175 */ 176 static inline void umc_set_drvdata(struct umc_dev *umc_dev, void *data) 177 { 178 dev_set_drvdata(&umc_dev->dev, data); 179 } 180 181 /** 182 * umc_get_drvdata - recover UMC device's driver data. 183 * @umc_dev: Pointer to UMC device. 184 */ 185 static inline void *umc_get_drvdata(struct umc_dev *umc_dev) 186 { 187 return dev_get_drvdata(&umc_dev->dev); 188 } 189 190 int umc_controller_reset(struct umc_dev *umc); 191 192 #endif /* #ifndef _LINUX_UWB_UMC_H_ */