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