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