at v6.19 547 lines 13 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2011-2017, The Linux Foundation 4 */ 5 6#include <linux/kernel.h> 7#include <linux/errno.h> 8#include <linux/slab.h> 9#include <linux/init.h> 10#include <linux/idr.h> 11#include <linux/of.h> 12#include <linux/of_device.h> 13#include <linux/pm_runtime.h> 14#include <linux/slimbus.h> 15#include "slimbus.h" 16 17static DEFINE_IDA(ctrl_ida); 18 19static const struct slim_device_id *slim_match(const struct slim_device_id *id, 20 const struct slim_device *sbdev) 21{ 22 while (id->manf_id != 0 || id->prod_code != 0) { 23 if (id->manf_id == sbdev->e_addr.manf_id && 24 id->prod_code == sbdev->e_addr.prod_code && 25 id->dev_index == sbdev->e_addr.dev_index && 26 id->instance == sbdev->e_addr.instance) 27 return id; 28 id++; 29 } 30 return NULL; 31} 32 33static int slim_device_match(struct device *dev, const struct device_driver *drv) 34{ 35 struct slim_device *sbdev = to_slim_device(dev); 36 const struct slim_driver *sbdrv = to_slim_driver(drv); 37 38 /* Attempt an OF style match first */ 39 if (of_driver_match_device(dev, drv)) 40 return 1; 41 42 return !!slim_match(sbdrv->id_table, sbdev); 43} 44 45static void slim_device_update_status(struct slim_device *sbdev, 46 enum slim_device_status status) 47{ 48 struct slim_driver *sbdrv; 49 50 if (sbdev->status == status) 51 return; 52 53 sbdev->status = status; 54 if (!sbdev->dev.driver) 55 return; 56 57 sbdrv = to_slim_driver(sbdev->dev.driver); 58 if (sbdrv->device_status) 59 sbdrv->device_status(sbdev, sbdev->status); 60} 61 62static int slim_device_probe(struct device *dev) 63{ 64 struct slim_device *sbdev = to_slim_device(dev); 65 struct slim_driver *sbdrv = to_slim_driver(dev->driver); 66 int ret; 67 68 ret = sbdrv->probe(sbdev); 69 if (ret) 70 return ret; 71 72 /* try getting the logical address after probe */ 73 ret = slim_get_logical_addr(sbdev); 74 if (!ret) { 75 slim_device_update_status(sbdev, SLIM_DEVICE_STATUS_UP); 76 } else { 77 dev_err(&sbdev->dev, "Failed to get logical address\n"); 78 ret = -EPROBE_DEFER; 79 } 80 81 return ret; 82} 83 84static void slim_device_remove(struct device *dev) 85{ 86 struct slim_device *sbdev = to_slim_device(dev); 87 struct slim_driver *sbdrv; 88 89 if (dev->driver) { 90 sbdrv = to_slim_driver(dev->driver); 91 if (sbdrv->remove) 92 sbdrv->remove(sbdev); 93 } 94} 95 96static int slim_device_uevent(const struct device *dev, struct kobj_uevent_env *env) 97{ 98 const struct slim_device *sbdev = to_slim_device(dev); 99 100 return add_uevent_var(env, "MODALIAS=slim:%s", dev_name(&sbdev->dev)); 101} 102 103const struct bus_type slimbus_bus = { 104 .name = "slimbus", 105 .match = slim_device_match, 106 .probe = slim_device_probe, 107 .remove = slim_device_remove, 108 .uevent = slim_device_uevent, 109}; 110EXPORT_SYMBOL_GPL(slimbus_bus); 111 112/* 113 * __slim_driver_register() - Client driver registration with SLIMbus 114 * 115 * @drv:Client driver to be associated with client-device. 116 * @owner: owning module/driver 117 * 118 * This API will register the client driver with the SLIMbus 119 * It is called from the driver's module-init function. 120 */ 121int __slim_driver_register(struct slim_driver *drv, struct module *owner) 122{ 123 /* ID table and probe are mandatory */ 124 if (!(drv->driver.of_match_table || drv->id_table) || !drv->probe) 125 return -EINVAL; 126 127 drv->driver.bus = &slimbus_bus; 128 drv->driver.owner = owner; 129 130 return driver_register(&drv->driver); 131} 132EXPORT_SYMBOL_GPL(__slim_driver_register); 133 134/* 135 * slim_driver_unregister() - Undo effect of slim_driver_register 136 * 137 * @drv: Client driver to be unregistered 138 */ 139void slim_driver_unregister(struct slim_driver *drv) 140{ 141 driver_unregister(&drv->driver); 142} 143EXPORT_SYMBOL_GPL(slim_driver_unregister); 144 145static void slim_dev_release(struct device *dev) 146{ 147 struct slim_device *sbdev = to_slim_device(dev); 148 149 of_node_put(sbdev->dev.of_node); 150 kfree(sbdev); 151} 152 153static int slim_add_device(struct slim_controller *ctrl, 154 struct slim_device *sbdev, 155 struct device_node *node) 156{ 157 sbdev->dev.bus = &slimbus_bus; 158 sbdev->dev.parent = ctrl->dev; 159 sbdev->dev.release = slim_dev_release; 160 sbdev->dev.driver = NULL; 161 sbdev->ctrl = ctrl; 162 INIT_LIST_HEAD(&sbdev->stream_list); 163 spin_lock_init(&sbdev->stream_list_lock); 164 sbdev->dev.of_node = of_node_get(node); 165 sbdev->dev.fwnode = of_fwnode_handle(node); 166 167 dev_set_name(&sbdev->dev, "%x:%x:%x:%x", 168 sbdev->e_addr.manf_id, 169 sbdev->e_addr.prod_code, 170 sbdev->e_addr.dev_index, 171 sbdev->e_addr.instance); 172 173 return device_register(&sbdev->dev); 174} 175 176static struct slim_device *slim_alloc_device(struct slim_controller *ctrl, 177 struct slim_eaddr *eaddr, 178 struct device_node *node) 179{ 180 struct slim_device *sbdev; 181 int ret; 182 183 sbdev = kzalloc(sizeof(*sbdev), GFP_KERNEL); 184 if (!sbdev) 185 return NULL; 186 187 sbdev->e_addr = *eaddr; 188 ret = slim_add_device(ctrl, sbdev, node); 189 if (ret) { 190 put_device(&sbdev->dev); 191 return NULL; 192 } 193 194 return sbdev; 195} 196 197static void of_register_slim_devices(struct slim_controller *ctrl) 198{ 199 struct device *dev = ctrl->dev; 200 struct device_node *node; 201 202 if (!ctrl->dev->of_node) 203 return; 204 205 for_each_child_of_node(ctrl->dev->of_node, node) { 206 struct slim_device *sbdev; 207 struct slim_eaddr e_addr; 208 const char *compat = NULL; 209 int reg[2], ret; 210 int manf_id, prod_code; 211 212 compat = of_get_property(node, "compatible", NULL); 213 if (!compat) 214 continue; 215 216 ret = sscanf(compat, "slim%x,%x", &manf_id, &prod_code); 217 if (ret != 2) { 218 dev_err(dev, "Manf ID & Product code not found %s\n", 219 compat); 220 continue; 221 } 222 223 ret = of_property_read_u32_array(node, "reg", reg, 2); 224 if (ret) { 225 dev_err(dev, "Device and Instance id not found:%d\n", 226 ret); 227 continue; 228 } 229 230 e_addr.dev_index = reg[0]; 231 e_addr.instance = reg[1]; 232 e_addr.manf_id = manf_id; 233 e_addr.prod_code = prod_code; 234 235 sbdev = slim_alloc_device(ctrl, &e_addr, node); 236 if (!sbdev) 237 continue; 238 } 239} 240 241/* 242 * slim_register_controller() - Controller bring-up and registration. 243 * 244 * @ctrl: Controller to be registered. 245 * 246 * A controller is registered with the framework using this API. 247 * If devices on a controller were registered before controller, 248 * this will make sure that they get probed when controller is up 249 */ 250int slim_register_controller(struct slim_controller *ctrl) 251{ 252 int id; 253 254 id = ida_alloc(&ctrl_ida, GFP_KERNEL); 255 if (id < 0) 256 return id; 257 258 ctrl->id = id; 259 260 if (!ctrl->min_cg) 261 ctrl->min_cg = SLIM_MIN_CLK_GEAR; 262 if (!ctrl->max_cg) 263 ctrl->max_cg = SLIM_MAX_CLK_GEAR; 264 265 ida_init(&ctrl->laddr_ida); 266 idr_init(&ctrl->tid_idr); 267 mutex_init(&ctrl->lock); 268 mutex_init(&ctrl->sched.m_reconf); 269 init_completion(&ctrl->sched.pause_comp); 270 spin_lock_init(&ctrl->txn_lock); 271 272 dev_dbg(ctrl->dev, "Bus [%s] registered:dev:%p\n", 273 ctrl->name, ctrl->dev); 274 275 of_register_slim_devices(ctrl); 276 277 return 0; 278} 279EXPORT_SYMBOL_GPL(slim_register_controller); 280 281/* slim_remove_device: Remove the effect of slim_add_device() */ 282static void slim_remove_device(struct slim_device *sbdev) 283{ 284 device_unregister(&sbdev->dev); 285} 286 287static int slim_ctrl_remove_device(struct device *dev, void *null) 288{ 289 slim_remove_device(to_slim_device(dev)); 290 return 0; 291} 292 293/** 294 * slim_unregister_controller() - Controller tear-down. 295 * 296 * @ctrl: Controller to tear-down. 297 */ 298int slim_unregister_controller(struct slim_controller *ctrl) 299{ 300 /* Remove all clients */ 301 device_for_each_child(ctrl->dev, NULL, slim_ctrl_remove_device); 302 ida_free(&ctrl_ida, ctrl->id); 303 304 return 0; 305} 306EXPORT_SYMBOL_GPL(slim_unregister_controller); 307 308/** 309 * slim_report_absent() - Controller calls this function when a device 310 * reports absent, OR when the device cannot be communicated with 311 * 312 * @sbdev: Device that cannot be reached, or sent report absent 313 */ 314void slim_report_absent(struct slim_device *sbdev) 315{ 316 struct slim_controller *ctrl = sbdev->ctrl; 317 318 if (!ctrl) 319 return; 320 321 /* invalidate logical addresses */ 322 mutex_lock(&ctrl->lock); 323 sbdev->is_laddr_valid = false; 324 mutex_unlock(&ctrl->lock); 325 if (!ctrl->get_laddr) 326 ida_free(&ctrl->laddr_ida, sbdev->laddr); 327 slim_device_update_status(sbdev, SLIM_DEVICE_STATUS_DOWN); 328} 329EXPORT_SYMBOL_GPL(slim_report_absent); 330 331static bool slim_eaddr_equal(const struct slim_eaddr *a, 332 const struct slim_eaddr *b) 333{ 334 return (a->manf_id == b->manf_id && 335 a->prod_code == b->prod_code && 336 a->dev_index == b->dev_index && 337 a->instance == b->instance); 338} 339 340static int slim_match_dev(struct device *dev, const void *data) 341{ 342 const struct slim_eaddr *e_addr = data; 343 struct slim_device *sbdev = to_slim_device(dev); 344 345 return slim_eaddr_equal(&sbdev->e_addr, e_addr); 346} 347 348static struct slim_device *find_slim_device(struct slim_controller *ctrl, 349 struct slim_eaddr *eaddr) 350{ 351 struct slim_device *sbdev; 352 struct device *dev; 353 354 dev = device_find_child(ctrl->dev, eaddr, slim_match_dev); 355 if (dev) { 356 sbdev = to_slim_device(dev); 357 return sbdev; 358 } 359 360 return NULL; 361} 362 363/** 364 * slim_get_device() - get handle to a device. 365 * 366 * @ctrl: Controller on which this device will be added/queried 367 * @e_addr: Enumeration address of the device to be queried 368 * 369 * Takes a reference to the embedded struct device which needs to be dropped 370 * after use. 371 * 372 * Return: pointer to a device if it has already reported. Creates a new 373 * device and returns pointer to it if the device has not yet enumerated. 374 */ 375struct slim_device *slim_get_device(struct slim_controller *ctrl, 376 struct slim_eaddr *e_addr) 377{ 378 struct slim_device *sbdev; 379 380 sbdev = find_slim_device(ctrl, e_addr); 381 if (!sbdev) { 382 sbdev = slim_alloc_device(ctrl, e_addr, NULL); 383 if (!sbdev) 384 return ERR_PTR(-ENOMEM); 385 386 get_device(&sbdev->dev); 387 } 388 389 return sbdev; 390} 391EXPORT_SYMBOL_GPL(slim_get_device); 392 393/** 394 * of_slim_get_device() - get handle to a device using dt node. 395 * 396 * @ctrl: Controller on which this device will be queried 397 * @np: node pointer to device 398 * 399 * Takes a reference to the embedded struct device which needs to be dropped 400 * after use. 401 * 402 * Return: pointer to a device if it has been registered, otherwise NULL. 403 */ 404struct slim_device *of_slim_get_device(struct slim_controller *ctrl, 405 struct device_node *np) 406{ 407 struct slim_device *sbdev; 408 struct device *dev; 409 410 dev = device_find_child(ctrl->dev, np, device_match_of_node); 411 if (dev) { 412 sbdev = to_slim_device(dev); 413 return sbdev; 414 } 415 416 return NULL; 417} 418EXPORT_SYMBOL_GPL(of_slim_get_device); 419 420static int slim_device_alloc_laddr(struct slim_device *sbdev, 421 bool report_present) 422{ 423 struct slim_controller *ctrl = sbdev->ctrl; 424 u8 laddr; 425 int ret; 426 427 mutex_lock(&ctrl->lock); 428 if (ctrl->get_laddr) { 429 ret = ctrl->get_laddr(ctrl, &sbdev->e_addr, &laddr); 430 if (ret < 0) 431 goto err; 432 } else if (report_present) { 433 ret = ida_alloc_max(&ctrl->laddr_ida, 434 SLIM_LA_MANAGER - 1, GFP_KERNEL); 435 if (ret < 0) 436 goto err; 437 438 laddr = ret; 439 } else { 440 ret = -EINVAL; 441 goto err; 442 } 443 444 if (ctrl->set_laddr) { 445 ret = ctrl->set_laddr(ctrl, &sbdev->e_addr, laddr); 446 if (ret) { 447 ret = -EINVAL; 448 goto err; 449 } 450 } 451 452 sbdev->laddr = laddr; 453 sbdev->is_laddr_valid = true; 454 mutex_unlock(&ctrl->lock); 455 456 slim_device_update_status(sbdev, SLIM_DEVICE_STATUS_UP); 457 458 dev_dbg(ctrl->dev, "setting slimbus l-addr:%x, ea:%x,%x,%x,%x\n", 459 laddr, sbdev->e_addr.manf_id, sbdev->e_addr.prod_code, 460 sbdev->e_addr.dev_index, sbdev->e_addr.instance); 461 462 return 0; 463 464err: 465 mutex_unlock(&ctrl->lock); 466 return ret; 467 468} 469 470/** 471 * slim_device_report_present() - Report enumerated device. 472 * 473 * @ctrl: Controller with which device is enumerated. 474 * @e_addr: Enumeration address of the device. 475 * @laddr: Return logical address (if valid flag is false) 476 * 477 * Called by controller in response to REPORT_PRESENT. Framework will assign 478 * a logical address to this enumeration address. 479 * Function returns -EXFULL to indicate that all logical addresses are already 480 * taken. 481 */ 482int slim_device_report_present(struct slim_controller *ctrl, 483 struct slim_eaddr *e_addr, u8 *laddr) 484{ 485 struct slim_device *sbdev; 486 int ret; 487 488 ret = pm_runtime_get_sync(ctrl->dev); 489 490 if (ctrl->sched.clk_state != SLIM_CLK_ACTIVE) { 491 dev_err(ctrl->dev, "slim ctrl not active,state:%d, ret:%d\n", 492 ctrl->sched.clk_state, ret); 493 goto out_put_rpm; 494 } 495 496 sbdev = slim_get_device(ctrl, e_addr); 497 if (IS_ERR(sbdev)) { 498 ret = -ENODEV; 499 goto out_put_rpm; 500 } 501 502 if (sbdev->is_laddr_valid) { 503 *laddr = sbdev->laddr; 504 ret = 0; 505 } else { 506 ret = slim_device_alloc_laddr(sbdev, true); 507 } 508 509 put_device(&sbdev->dev); 510out_put_rpm: 511 pm_runtime_mark_last_busy(ctrl->dev); 512 pm_runtime_put_autosuspend(ctrl->dev); 513 return ret; 514} 515EXPORT_SYMBOL_GPL(slim_device_report_present); 516 517/** 518 * slim_get_logical_addr() - get/allocate logical address of a SLIMbus device. 519 * 520 * @sbdev: client handle requesting the address. 521 * 522 * Return: zero if a logical address is valid or a new logical address 523 * has been assigned. error code in case of error. 524 */ 525int slim_get_logical_addr(struct slim_device *sbdev) 526{ 527 if (!sbdev->is_laddr_valid) 528 return slim_device_alloc_laddr(sbdev, false); 529 530 return 0; 531} 532EXPORT_SYMBOL_GPL(slim_get_logical_addr); 533 534static void __exit slimbus_exit(void) 535{ 536 bus_unregister(&slimbus_bus); 537} 538module_exit(slimbus_exit); 539 540static int __init slimbus_init(void) 541{ 542 return bus_register(&slimbus_bus); 543} 544postcore_initcall(slimbus_init); 545 546MODULE_LICENSE("GPL v2"); 547MODULE_DESCRIPTION("SLIMbus core");