1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2018 Cadence Design Systems Inc. 4 * 5 * Author: Boris Brezillon <boris.brezillon@bootlin.com> 6 */ 7 8 #include <linux/atomic.h> 9 #include <linux/bug.h> 10 #include <linux/completion.h> 11 #include <linux/device.h> 12 #include <linux/mutex.h> 13 #include <linux/slab.h> 14 15 #include "internals.h" 16 17 /** 18 * i3c_device_do_priv_xfers() - do I3C SDR private transfers directed to a 19 * specific device 20 * 21 * @dev: device with which the transfers should be done 22 * @xfers: array of transfers 23 * @nxfers: number of transfers 24 * 25 * Initiate one or several private SDR transfers with @dev. 26 * 27 * This function can sleep and thus cannot be called in atomic context. 28 * 29 * Return: 0 in case of success, a negative error core otherwise. 30 */ 31 int i3c_device_do_priv_xfers(struct i3c_device *dev, 32 struct i3c_priv_xfer *xfers, 33 int nxfers) 34 { 35 int ret, i; 36 37 if (nxfers < 1) 38 return 0; 39 40 for (i = 0; i < nxfers; i++) { 41 if (!xfers[i].len || !xfers[i].data.in) 42 return -EINVAL; 43 } 44 45 i3c_bus_normaluse_lock(dev->bus); 46 ret = i3c_dev_do_priv_xfers_locked(dev->desc, xfers, nxfers); 47 i3c_bus_normaluse_unlock(dev->bus); 48 49 return ret; 50 } 51 EXPORT_SYMBOL_GPL(i3c_device_do_priv_xfers); 52 53 /** 54 * i3c_device_do_setdasa() - do I3C dynamic address assignement with 55 * static address 56 * 57 * @dev: device with which the DAA should be done 58 * 59 * Return: 0 in case of success, a negative error core otherwise. 60 */ 61 int i3c_device_do_setdasa(struct i3c_device *dev) 62 { 63 int ret; 64 65 i3c_bus_normaluse_lock(dev->bus); 66 ret = i3c_dev_setdasa_locked(dev->desc); 67 i3c_bus_normaluse_unlock(dev->bus); 68 69 return ret; 70 } 71 EXPORT_SYMBOL_GPL(i3c_device_do_setdasa); 72 73 /** 74 * i3c_device_get_info() - get I3C device information 75 * 76 * @dev: device we want information on 77 * @info: the information object to fill in 78 * 79 * Retrieve I3C dev info. 80 */ 81 void i3c_device_get_info(const struct i3c_device *dev, 82 struct i3c_device_info *info) 83 { 84 if (!info) 85 return; 86 87 i3c_bus_normaluse_lock(dev->bus); 88 if (dev->desc) 89 *info = dev->desc->info; 90 i3c_bus_normaluse_unlock(dev->bus); 91 } 92 EXPORT_SYMBOL_GPL(i3c_device_get_info); 93 94 /** 95 * i3c_device_disable_ibi() - Disable IBIs coming from a specific device 96 * @dev: device on which IBIs should be disabled 97 * 98 * This function disable IBIs coming from a specific device and wait for 99 * all pending IBIs to be processed. 100 * 101 * Return: 0 in case of success, a negative error core otherwise. 102 */ 103 int i3c_device_disable_ibi(struct i3c_device *dev) 104 { 105 int ret = -ENOENT; 106 107 i3c_bus_normaluse_lock(dev->bus); 108 if (dev->desc) { 109 mutex_lock(&dev->desc->ibi_lock); 110 ret = i3c_dev_disable_ibi_locked(dev->desc); 111 mutex_unlock(&dev->desc->ibi_lock); 112 } 113 i3c_bus_normaluse_unlock(dev->bus); 114 115 return ret; 116 } 117 EXPORT_SYMBOL_GPL(i3c_device_disable_ibi); 118 119 /** 120 * i3c_device_enable_ibi() - Enable IBIs coming from a specific device 121 * @dev: device on which IBIs should be enabled 122 * 123 * This function enable IBIs coming from a specific device and wait for 124 * all pending IBIs to be processed. This should be called on a device 125 * where i3c_device_request_ibi() has succeeded. 126 * 127 * Note that IBIs from this device might be received before this function 128 * returns to its caller. 129 * 130 * Return: 0 in case of success, a negative error core otherwise. 131 */ 132 int i3c_device_enable_ibi(struct i3c_device *dev) 133 { 134 int ret = -ENOENT; 135 136 i3c_bus_normaluse_lock(dev->bus); 137 if (dev->desc) { 138 mutex_lock(&dev->desc->ibi_lock); 139 ret = i3c_dev_enable_ibi_locked(dev->desc); 140 mutex_unlock(&dev->desc->ibi_lock); 141 } 142 i3c_bus_normaluse_unlock(dev->bus); 143 144 return ret; 145 } 146 EXPORT_SYMBOL_GPL(i3c_device_enable_ibi); 147 148 /** 149 * i3c_device_request_ibi() - Request an IBI 150 * @dev: device for which we should enable IBIs 151 * @req: setup requested for this IBI 152 * 153 * This function is responsible for pre-allocating all resources needed to 154 * process IBIs coming from @dev. When this function returns, the IBI is not 155 * enabled until i3c_device_enable_ibi() is called. 156 * 157 * Return: 0 in case of success, a negative error core otherwise. 158 */ 159 int i3c_device_request_ibi(struct i3c_device *dev, 160 const struct i3c_ibi_setup *req) 161 { 162 int ret = -ENOENT; 163 164 if (!req->handler || !req->num_slots) 165 return -EINVAL; 166 167 i3c_bus_normaluse_lock(dev->bus); 168 if (dev->desc) { 169 mutex_lock(&dev->desc->ibi_lock); 170 ret = i3c_dev_request_ibi_locked(dev->desc, req); 171 mutex_unlock(&dev->desc->ibi_lock); 172 } 173 i3c_bus_normaluse_unlock(dev->bus); 174 175 return ret; 176 } 177 EXPORT_SYMBOL_GPL(i3c_device_request_ibi); 178 179 /** 180 * i3c_device_free_ibi() - Free all resources needed for IBI handling 181 * @dev: device on which you want to release IBI resources 182 * 183 * This function is responsible for de-allocating resources previously 184 * allocated by i3c_device_request_ibi(). It should be called after disabling 185 * IBIs with i3c_device_disable_ibi(). 186 */ 187 void i3c_device_free_ibi(struct i3c_device *dev) 188 { 189 i3c_bus_normaluse_lock(dev->bus); 190 if (dev->desc) { 191 mutex_lock(&dev->desc->ibi_lock); 192 i3c_dev_free_ibi_locked(dev->desc); 193 mutex_unlock(&dev->desc->ibi_lock); 194 } 195 i3c_bus_normaluse_unlock(dev->bus); 196 } 197 EXPORT_SYMBOL_GPL(i3c_device_free_ibi); 198 199 /** 200 * i3cdev_to_dev() - Returns the device embedded in @i3cdev 201 * @i3cdev: I3C device 202 * 203 * Return: a pointer to a device object. 204 */ 205 struct device *i3cdev_to_dev(struct i3c_device *i3cdev) 206 { 207 return &i3cdev->dev; 208 } 209 EXPORT_SYMBOL_GPL(i3cdev_to_dev); 210 211 /** 212 * i3c_device_match_id() - Returns the i3c_device_id entry matching @i3cdev 213 * @i3cdev: I3C device 214 * @id_table: I3C device match table 215 * 216 * Return: a pointer to an i3c_device_id object or NULL if there's no match. 217 */ 218 const struct i3c_device_id * 219 i3c_device_match_id(struct i3c_device *i3cdev, 220 const struct i3c_device_id *id_table) 221 { 222 struct i3c_device_info devinfo; 223 const struct i3c_device_id *id; 224 u16 manuf, part, ext_info; 225 bool rndpid; 226 227 i3c_device_get_info(i3cdev, &devinfo); 228 229 manuf = I3C_PID_MANUF_ID(devinfo.pid); 230 part = I3C_PID_PART_ID(devinfo.pid); 231 ext_info = I3C_PID_EXTRA_INFO(devinfo.pid); 232 rndpid = I3C_PID_RND_LOWER_32BITS(devinfo.pid); 233 234 for (id = id_table; id->match_flags != 0; id++) { 235 if ((id->match_flags & I3C_MATCH_DCR) && 236 id->dcr != devinfo.dcr) 237 continue; 238 239 if ((id->match_flags & I3C_MATCH_MANUF) && 240 id->manuf_id != manuf) 241 continue; 242 243 if ((id->match_flags & I3C_MATCH_PART) && 244 (rndpid || id->part_id != part)) 245 continue; 246 247 if ((id->match_flags & I3C_MATCH_EXTRA_INFO) && 248 (rndpid || id->extra_info != ext_info)) 249 continue; 250 251 return id; 252 } 253 254 return NULL; 255 } 256 EXPORT_SYMBOL_GPL(i3c_device_match_id); 257 258 /** 259 * i3c_driver_register_with_owner() - register an I3C device driver 260 * 261 * @drv: driver to register 262 * @owner: module that owns this driver 263 * 264 * Register @drv to the core. 265 * 266 * Return: 0 in case of success, a negative error core otherwise. 267 */ 268 int i3c_driver_register_with_owner(struct i3c_driver *drv, struct module *owner) 269 { 270 drv->driver.owner = owner; 271 drv->driver.bus = &i3c_bus_type; 272 273 if (!drv->probe) { 274 pr_err("Trying to register an i3c driver without probe callback\n"); 275 return -EINVAL; 276 } 277 278 return driver_register(&drv->driver); 279 } 280 EXPORT_SYMBOL_GPL(i3c_driver_register_with_owner); 281 282 /** 283 * i3c_driver_unregister() - unregister an I3C device driver 284 * 285 * @drv: driver to unregister 286 * 287 * Unregister @drv. 288 */ 289 void i3c_driver_unregister(struct i3c_driver *drv) 290 { 291 driver_unregister(&drv->driver); 292 } 293 EXPORT_SYMBOL_GPL(i3c_driver_unregister); 294