1 /* 2 * linux/arch/arm/common/amba.c 3 * 4 * Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 #include <linux/module.h> 11 #include <linux/init.h> 12 #include <linux/device.h> 13 #include <linux/string.h> 14 #include <linux/slab.h> 15 #include <linux/io.h> 16 #include <linux/pm.h> 17 #include <linux/pm_runtime.h> 18 #include <linux/pm_domain.h> 19 #include <linux/amba/bus.h> 20 #include <linux/sizes.h> 21 22 #include <asm/irq.h> 23 24 #define to_amba_driver(d) container_of(d, struct amba_driver, drv) 25 26 static const struct amba_id * 27 amba_lookup(const struct amba_id *table, struct amba_device *dev) 28 { 29 int ret = 0; 30 31 while (table->mask) { 32 ret = (dev->periphid & table->mask) == table->id; 33 if (ret) 34 break; 35 table++; 36 } 37 38 return ret ? table : NULL; 39 } 40 41 static int amba_match(struct device *dev, struct device_driver *drv) 42 { 43 struct amba_device *pcdev = to_amba_device(dev); 44 struct amba_driver *pcdrv = to_amba_driver(drv); 45 46 return amba_lookup(pcdrv->id_table, pcdev) != NULL; 47 } 48 49 static int amba_uevent(struct device *dev, struct kobj_uevent_env *env) 50 { 51 struct amba_device *pcdev = to_amba_device(dev); 52 int retval = 0; 53 54 retval = add_uevent_var(env, "AMBA_ID=%08x", pcdev->periphid); 55 if (retval) 56 return retval; 57 58 retval = add_uevent_var(env, "MODALIAS=amba:d%08X", pcdev->periphid); 59 return retval; 60 } 61 62 #define amba_attr_func(name,fmt,arg...) \ 63 static ssize_t name##_show(struct device *_dev, \ 64 struct device_attribute *attr, char *buf) \ 65 { \ 66 struct amba_device *dev = to_amba_device(_dev); \ 67 return sprintf(buf, fmt, arg); \ 68 } 69 70 #define amba_attr(name,fmt,arg...) \ 71 amba_attr_func(name,fmt,arg) \ 72 static DEVICE_ATTR(name, S_IRUGO, name##_show, NULL) 73 74 amba_attr_func(id, "%08x\n", dev->periphid); 75 amba_attr(irq0, "%u\n", dev->irq[0]); 76 amba_attr(irq1, "%u\n", dev->irq[1]); 77 amba_attr_func(resource, "\t%016llx\t%016llx\t%016lx\n", 78 (unsigned long long)dev->res.start, (unsigned long long)dev->res.end, 79 dev->res.flags); 80 81 static struct device_attribute amba_dev_attrs[] = { 82 __ATTR_RO(id), 83 __ATTR_RO(resource), 84 __ATTR_NULL, 85 }; 86 87 #ifdef CONFIG_PM 88 /* 89 * Hooks to provide runtime PM of the pclk (bus clock). It is safe to 90 * enable/disable the bus clock at runtime PM suspend/resume as this 91 * does not result in loss of context. 92 */ 93 static int amba_pm_runtime_suspend(struct device *dev) 94 { 95 struct amba_device *pcdev = to_amba_device(dev); 96 int ret = pm_generic_runtime_suspend(dev); 97 98 if (ret == 0 && dev->driver) 99 clk_disable_unprepare(pcdev->pclk); 100 101 return ret; 102 } 103 104 static int amba_pm_runtime_resume(struct device *dev) 105 { 106 struct amba_device *pcdev = to_amba_device(dev); 107 int ret; 108 109 if (dev->driver) { 110 ret = clk_prepare_enable(pcdev->pclk); 111 /* Failure is probably fatal to the system, but... */ 112 if (ret) 113 return ret; 114 } 115 116 return pm_generic_runtime_resume(dev); 117 } 118 #endif 119 120 static const struct dev_pm_ops amba_pm = { 121 .suspend = pm_generic_suspend, 122 .resume = pm_generic_resume, 123 .freeze = pm_generic_freeze, 124 .thaw = pm_generic_thaw, 125 .poweroff = pm_generic_poweroff, 126 .restore = pm_generic_restore, 127 SET_PM_RUNTIME_PM_OPS( 128 amba_pm_runtime_suspend, 129 amba_pm_runtime_resume, 130 NULL 131 ) 132 }; 133 134 /* 135 * Primecells are part of the Advanced Microcontroller Bus Architecture, 136 * so we call the bus "amba". 137 */ 138 struct bus_type amba_bustype = { 139 .name = "amba", 140 .dev_attrs = amba_dev_attrs, 141 .match = amba_match, 142 .uevent = amba_uevent, 143 .pm = &amba_pm, 144 }; 145 146 static int __init amba_init(void) 147 { 148 return bus_register(&amba_bustype); 149 } 150 151 postcore_initcall(amba_init); 152 153 static int amba_get_enable_pclk(struct amba_device *pcdev) 154 { 155 int ret; 156 157 pcdev->pclk = clk_get(&pcdev->dev, "apb_pclk"); 158 if (IS_ERR(pcdev->pclk)) 159 return PTR_ERR(pcdev->pclk); 160 161 ret = clk_prepare_enable(pcdev->pclk); 162 if (ret) 163 clk_put(pcdev->pclk); 164 165 return ret; 166 } 167 168 static void amba_put_disable_pclk(struct amba_device *pcdev) 169 { 170 clk_disable_unprepare(pcdev->pclk); 171 clk_put(pcdev->pclk); 172 } 173 174 /* 175 * These are the device model conversion veneers; they convert the 176 * device model structures to our more specific structures. 177 */ 178 static int amba_probe(struct device *dev) 179 { 180 struct amba_device *pcdev = to_amba_device(dev); 181 struct amba_driver *pcdrv = to_amba_driver(dev->driver); 182 const struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev); 183 int ret; 184 185 do { 186 ret = dev_pm_domain_attach(dev, true); 187 if (ret == -EPROBE_DEFER) 188 break; 189 190 ret = amba_get_enable_pclk(pcdev); 191 if (ret) { 192 dev_pm_domain_detach(dev, true); 193 break; 194 } 195 196 pm_runtime_get_noresume(dev); 197 pm_runtime_set_active(dev); 198 pm_runtime_enable(dev); 199 200 ret = pcdrv->probe(pcdev, id); 201 if (ret == 0) 202 break; 203 204 pm_runtime_disable(dev); 205 pm_runtime_set_suspended(dev); 206 pm_runtime_put_noidle(dev); 207 208 amba_put_disable_pclk(pcdev); 209 dev_pm_domain_detach(dev, true); 210 } while (0); 211 212 return ret; 213 } 214 215 static int amba_remove(struct device *dev) 216 { 217 struct amba_device *pcdev = to_amba_device(dev); 218 struct amba_driver *drv = to_amba_driver(dev->driver); 219 int ret; 220 221 pm_runtime_get_sync(dev); 222 ret = drv->remove(pcdev); 223 pm_runtime_put_noidle(dev); 224 225 /* Undo the runtime PM settings in amba_probe() */ 226 pm_runtime_disable(dev); 227 pm_runtime_set_suspended(dev); 228 pm_runtime_put_noidle(dev); 229 230 amba_put_disable_pclk(pcdev); 231 dev_pm_domain_detach(dev, true); 232 233 return ret; 234 } 235 236 static void amba_shutdown(struct device *dev) 237 { 238 struct amba_driver *drv = to_amba_driver(dev->driver); 239 drv->shutdown(to_amba_device(dev)); 240 } 241 242 /** 243 * amba_driver_register - register an AMBA device driver 244 * @drv: amba device driver structure 245 * 246 * Register an AMBA device driver with the Linux device model 247 * core. If devices pre-exist, the drivers probe function will 248 * be called. 249 */ 250 int amba_driver_register(struct amba_driver *drv) 251 { 252 drv->drv.bus = &amba_bustype; 253 254 #define SETFN(fn) if (drv->fn) drv->drv.fn = amba_##fn 255 SETFN(probe); 256 SETFN(remove); 257 SETFN(shutdown); 258 259 return driver_register(&drv->drv); 260 } 261 262 /** 263 * amba_driver_unregister - remove an AMBA device driver 264 * @drv: AMBA device driver structure to remove 265 * 266 * Unregister an AMBA device driver from the Linux device 267 * model. The device model will call the drivers remove function 268 * for each device the device driver is currently handling. 269 */ 270 void amba_driver_unregister(struct amba_driver *drv) 271 { 272 driver_unregister(&drv->drv); 273 } 274 275 276 static void amba_device_release(struct device *dev) 277 { 278 struct amba_device *d = to_amba_device(dev); 279 280 if (d->res.parent) 281 release_resource(&d->res); 282 kfree(d); 283 } 284 285 /** 286 * amba_device_add - add a previously allocated AMBA device structure 287 * @dev: AMBA device allocated by amba_device_alloc 288 * @parent: resource parent for this devices resources 289 * 290 * Claim the resource, and read the device cell ID if not already 291 * initialized. Register the AMBA device with the Linux device 292 * manager. 293 */ 294 int amba_device_add(struct amba_device *dev, struct resource *parent) 295 { 296 u32 size; 297 void __iomem *tmp; 298 int i, ret; 299 300 WARN_ON(dev->irq[0] == (unsigned int)-1); 301 WARN_ON(dev->irq[1] == (unsigned int)-1); 302 303 ret = request_resource(parent, &dev->res); 304 if (ret) 305 goto err_out; 306 307 /* Hard-coded primecell ID instead of plug-n-play */ 308 if (dev->periphid != 0) 309 goto skip_probe; 310 311 /* 312 * Dynamically calculate the size of the resource 313 * and use this for iomap 314 */ 315 size = resource_size(&dev->res); 316 tmp = ioremap(dev->res.start, size); 317 if (!tmp) { 318 ret = -ENOMEM; 319 goto err_release; 320 } 321 322 ret = amba_get_enable_pclk(dev); 323 if (ret == 0) { 324 u32 pid, cid; 325 326 /* 327 * Read pid and cid based on size of resource 328 * they are located at end of region 329 */ 330 for (pid = 0, i = 0; i < 4; i++) 331 pid |= (readl(tmp + size - 0x20 + 4 * i) & 255) << 332 (i * 8); 333 for (cid = 0, i = 0; i < 4; i++) 334 cid |= (readl(tmp + size - 0x10 + 4 * i) & 255) << 335 (i * 8); 336 337 amba_put_disable_pclk(dev); 338 339 if (cid == AMBA_CID) 340 dev->periphid = pid; 341 342 if (!dev->periphid) 343 ret = -ENODEV; 344 } 345 346 iounmap(tmp); 347 348 if (ret) 349 goto err_release; 350 351 skip_probe: 352 ret = device_add(&dev->dev); 353 if (ret) 354 goto err_release; 355 356 if (dev->irq[0]) 357 ret = device_create_file(&dev->dev, &dev_attr_irq0); 358 if (ret == 0 && dev->irq[1]) 359 ret = device_create_file(&dev->dev, &dev_attr_irq1); 360 if (ret == 0) 361 return ret; 362 363 device_unregister(&dev->dev); 364 365 err_release: 366 release_resource(&dev->res); 367 err_out: 368 return ret; 369 } 370 EXPORT_SYMBOL_GPL(amba_device_add); 371 372 static struct amba_device * 373 amba_aphb_device_add(struct device *parent, const char *name, 374 resource_size_t base, size_t size, int irq1, int irq2, 375 void *pdata, unsigned int periphid, u64 dma_mask, 376 struct resource *resbase) 377 { 378 struct amba_device *dev; 379 int ret; 380 381 dev = amba_device_alloc(name, base, size); 382 if (!dev) 383 return ERR_PTR(-ENOMEM); 384 385 dev->dev.coherent_dma_mask = dma_mask; 386 dev->irq[0] = irq1; 387 dev->irq[1] = irq2; 388 dev->periphid = periphid; 389 dev->dev.platform_data = pdata; 390 dev->dev.parent = parent; 391 392 ret = amba_device_add(dev, resbase); 393 if (ret) { 394 amba_device_put(dev); 395 return ERR_PTR(ret); 396 } 397 398 return dev; 399 } 400 401 struct amba_device * 402 amba_apb_device_add(struct device *parent, const char *name, 403 resource_size_t base, size_t size, int irq1, int irq2, 404 void *pdata, unsigned int periphid) 405 { 406 return amba_aphb_device_add(parent, name, base, size, irq1, irq2, pdata, 407 periphid, 0, &iomem_resource); 408 } 409 EXPORT_SYMBOL_GPL(amba_apb_device_add); 410 411 struct amba_device * 412 amba_ahb_device_add(struct device *parent, const char *name, 413 resource_size_t base, size_t size, int irq1, int irq2, 414 void *pdata, unsigned int periphid) 415 { 416 return amba_aphb_device_add(parent, name, base, size, irq1, irq2, pdata, 417 periphid, ~0ULL, &iomem_resource); 418 } 419 EXPORT_SYMBOL_GPL(amba_ahb_device_add); 420 421 struct amba_device * 422 amba_apb_device_add_res(struct device *parent, const char *name, 423 resource_size_t base, size_t size, int irq1, 424 int irq2, void *pdata, unsigned int periphid, 425 struct resource *resbase) 426 { 427 return amba_aphb_device_add(parent, name, base, size, irq1, irq2, pdata, 428 periphid, 0, resbase); 429 } 430 EXPORT_SYMBOL_GPL(amba_apb_device_add_res); 431 432 struct amba_device * 433 amba_ahb_device_add_res(struct device *parent, const char *name, 434 resource_size_t base, size_t size, int irq1, 435 int irq2, void *pdata, unsigned int periphid, 436 struct resource *resbase) 437 { 438 return amba_aphb_device_add(parent, name, base, size, irq1, irq2, pdata, 439 periphid, ~0ULL, resbase); 440 } 441 EXPORT_SYMBOL_GPL(amba_ahb_device_add_res); 442 443 444 static void amba_device_initialize(struct amba_device *dev, const char *name) 445 { 446 device_initialize(&dev->dev); 447 if (name) 448 dev_set_name(&dev->dev, "%s", name); 449 dev->dev.release = amba_device_release; 450 dev->dev.bus = &amba_bustype; 451 dev->dev.dma_mask = &dev->dev.coherent_dma_mask; 452 dev->res.name = dev_name(&dev->dev); 453 } 454 455 /** 456 * amba_device_alloc - allocate an AMBA device 457 * @name: sysfs name of the AMBA device 458 * @base: base of AMBA device 459 * @size: size of AMBA device 460 * 461 * Allocate and initialize an AMBA device structure. Returns %NULL 462 * on failure. 463 */ 464 struct amba_device *amba_device_alloc(const char *name, resource_size_t base, 465 size_t size) 466 { 467 struct amba_device *dev; 468 469 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 470 if (dev) { 471 amba_device_initialize(dev, name); 472 dev->res.start = base; 473 dev->res.end = base + size - 1; 474 dev->res.flags = IORESOURCE_MEM; 475 } 476 477 return dev; 478 } 479 EXPORT_SYMBOL_GPL(amba_device_alloc); 480 481 /** 482 * amba_device_register - register an AMBA device 483 * @dev: AMBA device to register 484 * @parent: parent memory resource 485 * 486 * Setup the AMBA device, reading the cell ID if present. 487 * Claim the resource, and register the AMBA device with 488 * the Linux device manager. 489 */ 490 int amba_device_register(struct amba_device *dev, struct resource *parent) 491 { 492 amba_device_initialize(dev, dev->dev.init_name); 493 dev->dev.init_name = NULL; 494 495 return amba_device_add(dev, parent); 496 } 497 498 /** 499 * amba_device_put - put an AMBA device 500 * @dev: AMBA device to put 501 */ 502 void amba_device_put(struct amba_device *dev) 503 { 504 put_device(&dev->dev); 505 } 506 EXPORT_SYMBOL_GPL(amba_device_put); 507 508 /** 509 * amba_device_unregister - unregister an AMBA device 510 * @dev: AMBA device to remove 511 * 512 * Remove the specified AMBA device from the Linux device 513 * manager. All files associated with this object will be 514 * destroyed, and device drivers notified that the device has 515 * been removed. The AMBA device's resources including 516 * the amba_device structure will be freed once all 517 * references to it have been dropped. 518 */ 519 void amba_device_unregister(struct amba_device *dev) 520 { 521 device_unregister(&dev->dev); 522 } 523 524 525 struct find_data { 526 struct amba_device *dev; 527 struct device *parent; 528 const char *busid; 529 unsigned int id; 530 unsigned int mask; 531 }; 532 533 static int amba_find_match(struct device *dev, void *data) 534 { 535 struct find_data *d = data; 536 struct amba_device *pcdev = to_amba_device(dev); 537 int r; 538 539 r = (pcdev->periphid & d->mask) == d->id; 540 if (d->parent) 541 r &= d->parent == dev->parent; 542 if (d->busid) 543 r &= strcmp(dev_name(dev), d->busid) == 0; 544 545 if (r) { 546 get_device(dev); 547 d->dev = pcdev; 548 } 549 550 return r; 551 } 552 553 /** 554 * amba_find_device - locate an AMBA device given a bus id 555 * @busid: bus id for device (or NULL) 556 * @parent: parent device (or NULL) 557 * @id: peripheral ID (or 0) 558 * @mask: peripheral ID mask (or 0) 559 * 560 * Return the AMBA device corresponding to the supplied parameters. 561 * If no device matches, returns NULL. 562 * 563 * NOTE: When a valid device is found, its refcount is 564 * incremented, and must be decremented before the returned 565 * reference. 566 */ 567 struct amba_device * 568 amba_find_device(const char *busid, struct device *parent, unsigned int id, 569 unsigned int mask) 570 { 571 struct find_data data; 572 573 data.dev = NULL; 574 data.parent = parent; 575 data.busid = busid; 576 data.id = id; 577 data.mask = mask; 578 579 bus_for_each_dev(&amba_bustype, NULL, &data, amba_find_match); 580 581 return data.dev; 582 } 583 584 /** 585 * amba_request_regions - request all mem regions associated with device 586 * @dev: amba_device structure for device 587 * @name: name, or NULL to use driver name 588 */ 589 int amba_request_regions(struct amba_device *dev, const char *name) 590 { 591 int ret = 0; 592 u32 size; 593 594 if (!name) 595 name = dev->dev.driver->name; 596 597 size = resource_size(&dev->res); 598 599 if (!request_mem_region(dev->res.start, size, name)) 600 ret = -EBUSY; 601 602 return ret; 603 } 604 605 /** 606 * amba_release_regions - release mem regions associated with device 607 * @dev: amba_device structure for device 608 * 609 * Release regions claimed by a successful call to amba_request_regions. 610 */ 611 void amba_release_regions(struct amba_device *dev) 612 { 613 u32 size; 614 615 size = resource_size(&dev->res); 616 release_mem_region(dev->res.start, size); 617 } 618 619 EXPORT_SYMBOL(amba_driver_register); 620 EXPORT_SYMBOL(amba_driver_unregister); 621 EXPORT_SYMBOL(amba_device_register); 622 EXPORT_SYMBOL(amba_device_unregister); 623 EXPORT_SYMBOL(amba_find_device); 624 EXPORT_SYMBOL(amba_request_regions); 625 EXPORT_SYMBOL(amba_release_regions); 626