1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2015, Sony Mobile Communications AB. 4 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. 5 */ 6 7 #include <linux/hwspinlock.h> 8 #include <linux/io.h> 9 #include <linux/module.h> 10 #include <linux/of.h> 11 #include <linux/of_address.h> 12 #include <linux/of_reserved_mem.h> 13 #include <linux/platform_device.h> 14 #include <linux/sizes.h> 15 #include <linux/slab.h> 16 #include <linux/soc/qcom/smem.h> 17 #include <linux/soc/qcom/socinfo.h> 18 19 /* 20 * The Qualcomm shared memory system is a allocate only heap structure that 21 * consists of one of more memory areas that can be accessed by the processors 22 * in the SoC. 23 * 24 * All systems contains a global heap, accessible by all processors in the SoC, 25 * with a table of contents data structure (@smem_header) at the beginning of 26 * the main shared memory block. 27 * 28 * The global header contains meta data for allocations as well as a fixed list 29 * of 512 entries (@smem_global_entry) that can be initialized to reference 30 * parts of the shared memory space. 31 * 32 * 33 * In addition to this global heap a set of "private" heaps can be set up at 34 * boot time with access restrictions so that only certain processor pairs can 35 * access the data. 36 * 37 * These partitions are referenced from an optional partition table 38 * (@smem_ptable), that is found 4kB from the end of the main smem region. The 39 * partition table entries (@smem_ptable_entry) lists the involved processors 40 * (or hosts) and their location in the main shared memory region. 41 * 42 * Each partition starts with a header (@smem_partition_header) that identifies 43 * the partition and holds properties for the two internal memory regions. The 44 * two regions are cached and non-cached memory respectively. Each region 45 * contain a link list of allocation headers (@smem_private_entry) followed by 46 * their data. 47 * 48 * Items in the non-cached region are allocated from the start of the partition 49 * while items in the cached region are allocated from the end. The free area 50 * is hence the region between the cached and non-cached offsets. The header of 51 * cached items comes after the data. 52 * 53 * Version 12 (SMEM_GLOBAL_PART_VERSION) changes the item alloc/get procedure 54 * for the global heap. A new global partition is created from the global heap 55 * region with partition type (SMEM_GLOBAL_HOST) and the max smem item count is 56 * set by the bootloader. 57 * 58 * To synchronize allocations in the shared memory heaps a remote spinlock must 59 * be held - currently lock number 3 of the sfpb or tcsr is used for this on all 60 * platforms. 61 * 62 */ 63 64 /* 65 * The version member of the smem header contains an array of versions for the 66 * various software components in the SoC. We verify that the boot loader 67 * version is a valid version as a sanity check. 68 */ 69 #define SMEM_MASTER_SBL_VERSION_INDEX 7 70 #define SMEM_GLOBAL_HEAP_VERSION 11 71 #define SMEM_GLOBAL_PART_VERSION 12 72 73 /* 74 * The first 8 items are only to be allocated by the boot loader while 75 * initializing the heap. 76 */ 77 #define SMEM_ITEM_LAST_FIXED 8 78 79 /* Highest accepted item number, for both global and private heaps */ 80 #define SMEM_ITEM_COUNT 512 81 82 /* Processor/host identifier for the application processor */ 83 #define SMEM_HOST_APPS 0 84 85 /* Processor/host identifier for the global partition */ 86 #define SMEM_GLOBAL_HOST 0xfffe 87 88 /** 89 * struct smem_proc_comm - proc_comm communication struct (legacy) 90 * @command: current command to be executed 91 * @status: status of the currently requested command 92 * @params: parameters to the command 93 */ 94 struct smem_proc_comm { 95 __le32 command; 96 __le32 status; 97 __le32 params[2]; 98 }; 99 100 /** 101 * struct smem_global_entry - entry to reference smem items on the heap 102 * @allocated: boolean to indicate if this entry is used 103 * @offset: offset to the allocated space 104 * @size: size of the allocated space, 8 byte aligned 105 * @aux_base: base address for the memory region used by this unit, or 0 for 106 * the default region. bits 0,1 are reserved 107 */ 108 struct smem_global_entry { 109 __le32 allocated; 110 __le32 offset; 111 __le32 size; 112 __le32 aux_base; /* bits 1:0 reserved */ 113 }; 114 #define AUX_BASE_MASK 0xfffffffc 115 116 /** 117 * struct smem_header - header found in beginning of primary smem region 118 * @proc_comm: proc_comm communication interface (legacy) 119 * @version: array of versions for the various subsystems 120 * @initialized: boolean to indicate that smem is initialized 121 * @free_offset: index of the first unallocated byte in smem 122 * @available: number of bytes available for allocation 123 * @reserved: reserved field, must be 0 124 * @toc: array of references to items 125 */ 126 struct smem_header { 127 struct smem_proc_comm proc_comm[4]; 128 __le32 version[32]; 129 __le32 initialized; 130 __le32 free_offset; 131 __le32 available; 132 __le32 reserved; 133 struct smem_global_entry toc[SMEM_ITEM_COUNT]; 134 }; 135 136 /** 137 * struct smem_ptable_entry - one entry in the @smem_ptable list 138 * @offset: offset, within the main shared memory region, of the partition 139 * @size: size of the partition 140 * @flags: flags for the partition (currently unused) 141 * @host0: first processor/host with access to this partition 142 * @host1: second processor/host with access to this partition 143 * @cacheline: alignment for "cached" entries 144 * @reserved: reserved entries for later use 145 */ 146 struct smem_ptable_entry { 147 __le32 offset; 148 __le32 size; 149 __le32 flags; 150 __le16 host0; 151 __le16 host1; 152 __le32 cacheline; 153 __le32 reserved[7]; 154 }; 155 156 /** 157 * struct smem_ptable - partition table for the private partitions 158 * @magic: magic number, must be SMEM_PTABLE_MAGIC 159 * @version: version of the partition table 160 * @num_entries: number of partitions in the table 161 * @reserved: for now reserved entries 162 * @entry: list of @smem_ptable_entry for the @num_entries partitions 163 */ 164 struct smem_ptable { 165 u8 magic[4]; 166 __le32 version; 167 __le32 num_entries; 168 __le32 reserved[5]; 169 struct smem_ptable_entry entry[]; 170 }; 171 172 static const u8 SMEM_PTABLE_MAGIC[] = { 0x24, 0x54, 0x4f, 0x43 }; /* "$TOC" */ 173 174 /** 175 * struct smem_partition_header - header of the partitions 176 * @magic: magic number, must be SMEM_PART_MAGIC 177 * @host0: first processor/host with access to this partition 178 * @host1: second processor/host with access to this partition 179 * @size: size of the partition 180 * @offset_free_uncached: offset to the first free byte of uncached memory in 181 * this partition 182 * @offset_free_cached: offset to the first free byte of cached memory in this 183 * partition 184 * @reserved: for now reserved entries 185 */ 186 struct smem_partition_header { 187 u8 magic[4]; 188 __le16 host0; 189 __le16 host1; 190 __le32 size; 191 __le32 offset_free_uncached; 192 __le32 offset_free_cached; 193 __le32 reserved[3]; 194 }; 195 196 /** 197 * struct smem_partition - describes smem partition 198 * @virt_base: starting virtual address of partition 199 * @phys_base: starting physical address of partition 200 * @cacheline: alignment for "cached" entries 201 * @size: size of partition 202 */ 203 struct smem_partition { 204 void __iomem *virt_base; 205 phys_addr_t phys_base; 206 size_t cacheline; 207 size_t size; 208 }; 209 210 static const u8 SMEM_PART_MAGIC[] = { 0x24, 0x50, 0x52, 0x54 }; 211 212 /** 213 * struct smem_private_entry - header of each item in the private partition 214 * @canary: magic number, must be SMEM_PRIVATE_CANARY 215 * @item: identifying number of the smem item 216 * @size: size of the data, including padding bytes 217 * @padding_data: number of bytes of padding of data 218 * @padding_hdr: number of bytes of padding between the header and the data 219 * @reserved: for now reserved entry 220 */ 221 struct smem_private_entry { 222 u16 canary; /* bytes are the same so no swapping needed */ 223 __le16 item; 224 __le32 size; /* includes padding bytes */ 225 __le16 padding_data; 226 __le16 padding_hdr; 227 __le32 reserved; 228 }; 229 #define SMEM_PRIVATE_CANARY 0xa5a5 230 231 /** 232 * struct smem_info - smem region info located after the table of contents 233 * @magic: magic number, must be SMEM_INFO_MAGIC 234 * @size: size of the smem region 235 * @base_addr: base address of the smem region 236 * @reserved: for now reserved entry 237 * @num_items: highest accepted item number 238 */ 239 struct smem_info { 240 u8 magic[4]; 241 __le32 size; 242 __le32 base_addr; 243 __le32 reserved; 244 __le16 num_items; 245 }; 246 247 static const u8 SMEM_INFO_MAGIC[] = { 0x53, 0x49, 0x49, 0x49 }; /* SIII */ 248 249 /** 250 * struct smem_region - representation of a chunk of memory used for smem 251 * @aux_base: identifier of aux_mem base 252 * @virt_base: virtual base address of memory with this aux_mem identifier 253 * @size: size of the memory region 254 */ 255 struct smem_region { 256 phys_addr_t aux_base; 257 void __iomem *virt_base; 258 size_t size; 259 }; 260 261 /** 262 * struct qcom_smem - device data for the smem device 263 * @dev: device pointer 264 * @hwlock: reference to a hwspinlock 265 * @ptable: virtual base of partition table 266 * @global_partition: describes for global partition when in use 267 * @partitions: list of partitions of current processor/host 268 * @item_count: max accepted item number 269 * @socinfo: platform device pointer 270 * @num_regions: number of @regions 271 * @regions: list of the memory regions defining the shared memory 272 */ 273 struct qcom_smem { 274 struct device *dev; 275 276 struct hwspinlock *hwlock; 277 278 u32 item_count; 279 struct platform_device *socinfo; 280 struct smem_ptable *ptable; 281 struct smem_partition global_partition; 282 struct xarray partitions; 283 284 unsigned num_regions; 285 struct smem_region regions[] __counted_by(num_regions); 286 }; 287 288 static void * 289 phdr_to_last_uncached_entry(struct smem_partition_header *phdr) 290 { 291 void *p = phdr; 292 293 return p + le32_to_cpu(phdr->offset_free_uncached); 294 } 295 296 static struct smem_private_entry * 297 phdr_to_first_cached_entry(struct smem_partition_header *phdr, 298 size_t cacheline) 299 { 300 void *p = phdr; 301 struct smem_private_entry *e; 302 303 return p + le32_to_cpu(phdr->size) - ALIGN(sizeof(*e), cacheline); 304 } 305 306 static void * 307 phdr_to_last_cached_entry(struct smem_partition_header *phdr) 308 { 309 void *p = phdr; 310 311 return p + le32_to_cpu(phdr->offset_free_cached); 312 } 313 314 static struct smem_private_entry * 315 phdr_to_first_uncached_entry(struct smem_partition_header *phdr) 316 { 317 void *p = phdr; 318 319 return p + sizeof(*phdr); 320 } 321 322 static struct smem_private_entry * 323 uncached_entry_next(struct smem_private_entry *e) 324 { 325 void *p = e; 326 327 return p + sizeof(*e) + le16_to_cpu(e->padding_hdr) + 328 le32_to_cpu(e->size); 329 } 330 331 static struct smem_private_entry * 332 cached_entry_next(struct smem_private_entry *e, size_t cacheline) 333 { 334 void *p = e; 335 336 return p - le32_to_cpu(e->size) - ALIGN(sizeof(*e), cacheline); 337 } 338 339 static void *uncached_entry_to_item(struct smem_private_entry *e) 340 { 341 void *p = e; 342 343 return p + sizeof(*e) + le16_to_cpu(e->padding_hdr); 344 } 345 346 static void *cached_entry_to_item(struct smem_private_entry *e) 347 { 348 void *p = e; 349 350 return p - le32_to_cpu(e->size); 351 } 352 353 /* 354 * Pointer to the one and only smem handle. 355 * Init to -EPROBE_DEFER to signal SMEM still has to be probed. 356 * Can be set to -ENODEV if SMEM is not initialized by SBL. 357 */ 358 static struct qcom_smem *__smem = INIT_ERR_PTR(-EPROBE_DEFER); 359 360 /* Timeout (ms) for the trylock of remote spinlocks */ 361 #define HWSPINLOCK_TIMEOUT 1000 362 363 /* The qcom hwspinlock id is always plus one from the smem host id */ 364 #define SMEM_HOST_ID_TO_HWSPINLOCK_ID(__x) ((__x) + 1) 365 366 /** 367 * qcom_smem_bust_hwspin_lock_by_host() - bust the smem hwspinlock for a host 368 * @host: remote processor id 369 * 370 * Busts the hwspin_lock for the given smem host id. This helper is intended 371 * for remoteproc drivers that manage remoteprocs with an equivalent smem 372 * driver instance in the remote firmware. Drivers can force a release of the 373 * smem hwspin_lock if the rproc unexpectedly goes into a bad state. 374 * 375 * Context: Process context. 376 * 377 * Returns: 0 on success, otherwise negative errno. 378 */ 379 int qcom_smem_bust_hwspin_lock_by_host(unsigned int host) 380 { 381 /* This function is for remote procs, so ignore SMEM_HOST_APPS */ 382 if (host == SMEM_HOST_APPS || !xa_load(&__smem->partitions, host)) 383 return -EINVAL; 384 385 return hwspin_lock_bust(__smem->hwlock, SMEM_HOST_ID_TO_HWSPINLOCK_ID(host)); 386 } 387 EXPORT_SYMBOL_GPL(qcom_smem_bust_hwspin_lock_by_host); 388 389 /** 390 * qcom_smem_is_available() - Check if SMEM is available 391 * 392 * Return: true if SMEM is available, false otherwise. 393 */ 394 bool qcom_smem_is_available(void) 395 { 396 return !IS_ERR(__smem); 397 } 398 EXPORT_SYMBOL_GPL(qcom_smem_is_available); 399 400 static int qcom_smem_alloc_private(struct qcom_smem *smem, 401 struct smem_partition *part, 402 unsigned item, 403 size_t size) 404 { 405 struct smem_private_entry *hdr, *end; 406 struct smem_partition_header *phdr; 407 size_t alloc_size; 408 void *cached; 409 void *p_end; 410 411 phdr = (struct smem_partition_header __force *)part->virt_base; 412 p_end = (void *)phdr + part->size; 413 414 hdr = phdr_to_first_uncached_entry(phdr); 415 end = phdr_to_last_uncached_entry(phdr); 416 cached = phdr_to_last_cached_entry(phdr); 417 418 if (WARN_ON((void *)end > p_end || cached > p_end)) 419 return -EINVAL; 420 421 while (hdr < end) { 422 if (hdr->canary != SMEM_PRIVATE_CANARY) 423 goto bad_canary; 424 if (le16_to_cpu(hdr->item) == item) 425 return -EEXIST; 426 427 hdr = uncached_entry_next(hdr); 428 } 429 430 if (WARN_ON((void *)hdr > p_end)) 431 return -EINVAL; 432 433 /* Check that we don't grow into the cached region */ 434 alloc_size = sizeof(*hdr) + ALIGN(size, 8); 435 if ((void *)hdr + alloc_size > cached) { 436 dev_err(smem->dev, "Out of memory\n"); 437 return -ENOSPC; 438 } 439 440 hdr->canary = SMEM_PRIVATE_CANARY; 441 hdr->item = cpu_to_le16(item); 442 hdr->size = cpu_to_le32(ALIGN(size, 8)); 443 hdr->padding_data = cpu_to_le16(le32_to_cpu(hdr->size) - size); 444 hdr->padding_hdr = 0; 445 446 /* 447 * Ensure the header is written before we advance the free offset, so 448 * that remote processors that does not take the remote spinlock still 449 * gets a consistent view of the linked list. 450 */ 451 wmb(); 452 le32_add_cpu(&phdr->offset_free_uncached, alloc_size); 453 454 return 0; 455 bad_canary: 456 dev_err(smem->dev, "Found invalid canary in hosts %hu:%hu partition\n", 457 le16_to_cpu(phdr->host0), le16_to_cpu(phdr->host1)); 458 459 return -EINVAL; 460 } 461 462 static int qcom_smem_alloc_global(struct qcom_smem *smem, 463 unsigned item, 464 size_t size) 465 { 466 struct smem_global_entry *entry; 467 struct smem_header *header; 468 469 header = smem->regions[0].virt_base; 470 entry = &header->toc[item]; 471 if (entry->allocated) 472 return -EEXIST; 473 474 size = ALIGN(size, 8); 475 if (WARN_ON(size > le32_to_cpu(header->available))) 476 return -ENOMEM; 477 478 entry->offset = header->free_offset; 479 entry->size = cpu_to_le32(size); 480 481 /* 482 * Ensure the header is consistent before we mark the item allocated, 483 * so that remote processors will get a consistent view of the item 484 * even though they do not take the spinlock on read. 485 */ 486 wmb(); 487 entry->allocated = cpu_to_le32(1); 488 489 le32_add_cpu(&header->free_offset, size); 490 le32_add_cpu(&header->available, -size); 491 492 return 0; 493 } 494 495 /** 496 * qcom_smem_alloc() - allocate space for a smem item 497 * @host: remote processor id, or -1 498 * @item: smem item handle 499 * @size: number of bytes to be allocated 500 * 501 * Allocate space for a given smem item of size @size, given that the item is 502 * not yet allocated. 503 * 504 * Return: 0 on success, negative errno on failure. 505 */ 506 int qcom_smem_alloc(unsigned host, unsigned item, size_t size) 507 { 508 struct smem_partition *part; 509 unsigned long flags; 510 int ret; 511 512 if (IS_ERR(__smem)) 513 return PTR_ERR(__smem); 514 515 if (item < SMEM_ITEM_LAST_FIXED) { 516 dev_err(__smem->dev, 517 "Rejecting allocation of static entry %d\n", item); 518 return -EINVAL; 519 } 520 521 if (item >= __smem->item_count) 522 return -EINVAL; 523 524 ret = hwspin_lock_timeout_irqsave(__smem->hwlock, 525 HWSPINLOCK_TIMEOUT, 526 &flags); 527 if (ret) 528 return ret; 529 530 part = xa_load(&__smem->partitions, host); 531 if (part) { 532 ret = qcom_smem_alloc_private(__smem, part, item, size); 533 } else if (__smem->global_partition.virt_base) { 534 part = &__smem->global_partition; 535 ret = qcom_smem_alloc_private(__smem, part, item, size); 536 } else { 537 ret = qcom_smem_alloc_global(__smem, item, size); 538 } 539 540 hwspin_unlock_irqrestore(__smem->hwlock, &flags); 541 542 return ret; 543 } 544 EXPORT_SYMBOL_GPL(qcom_smem_alloc); 545 546 static void *qcom_smem_get_global(struct qcom_smem *smem, 547 unsigned item, 548 size_t *size) 549 { 550 struct smem_header *header; 551 struct smem_region *region; 552 struct smem_global_entry *entry; 553 u64 entry_offset; 554 u32 e_size; 555 u32 aux_base; 556 unsigned i; 557 558 header = smem->regions[0].virt_base; 559 entry = &header->toc[item]; 560 if (!entry->allocated) 561 return ERR_PTR(-ENXIO); 562 563 aux_base = le32_to_cpu(entry->aux_base) & AUX_BASE_MASK; 564 565 for (i = 0; i < smem->num_regions; i++) { 566 region = &smem->regions[i]; 567 568 if ((u32)region->aux_base == aux_base || !aux_base) { 569 e_size = le32_to_cpu(entry->size); 570 entry_offset = le32_to_cpu(entry->offset); 571 572 if (WARN_ON(e_size + entry_offset > region->size)) 573 return ERR_PTR(-EINVAL); 574 575 if (size != NULL) 576 *size = e_size; 577 578 return region->virt_base + entry_offset; 579 } 580 } 581 582 return ERR_PTR(-ENOENT); 583 } 584 585 static void *qcom_smem_get_private(struct qcom_smem *smem, 586 struct smem_partition *part, 587 unsigned item, 588 size_t *size) 589 { 590 struct smem_private_entry *e, *end; 591 struct smem_partition_header *phdr; 592 void *item_ptr, *p_end; 593 u32 padding_data; 594 u32 e_size; 595 596 phdr = (struct smem_partition_header __force *)part->virt_base; 597 p_end = (void *)phdr + part->size; 598 599 e = phdr_to_first_uncached_entry(phdr); 600 end = phdr_to_last_uncached_entry(phdr); 601 602 while (e < end) { 603 if (e->canary != SMEM_PRIVATE_CANARY) 604 goto invalid_canary; 605 606 if (le16_to_cpu(e->item) == item) { 607 if (size != NULL) { 608 e_size = le32_to_cpu(e->size); 609 padding_data = le16_to_cpu(e->padding_data); 610 611 if (WARN_ON(e_size > part->size || padding_data > e_size)) 612 return ERR_PTR(-EINVAL); 613 614 *size = e_size - padding_data; 615 } 616 617 item_ptr = uncached_entry_to_item(e); 618 if (WARN_ON(item_ptr > p_end)) 619 return ERR_PTR(-EINVAL); 620 621 return item_ptr; 622 } 623 624 e = uncached_entry_next(e); 625 } 626 627 if (WARN_ON((void *)e > p_end)) 628 return ERR_PTR(-EINVAL); 629 630 /* Item was not found in the uncached list, search the cached list */ 631 632 e = phdr_to_first_cached_entry(phdr, part->cacheline); 633 end = phdr_to_last_cached_entry(phdr); 634 635 if (WARN_ON((void *)e < (void *)phdr || (void *)end > p_end)) 636 return ERR_PTR(-EINVAL); 637 638 while (e > end) { 639 if (e->canary != SMEM_PRIVATE_CANARY) 640 goto invalid_canary; 641 642 if (le16_to_cpu(e->item) == item) { 643 if (size != NULL) { 644 e_size = le32_to_cpu(e->size); 645 padding_data = le16_to_cpu(e->padding_data); 646 647 if (WARN_ON(e_size > part->size || padding_data > e_size)) 648 return ERR_PTR(-EINVAL); 649 650 *size = e_size - padding_data; 651 } 652 653 item_ptr = cached_entry_to_item(e); 654 if (WARN_ON(item_ptr < (void *)phdr)) 655 return ERR_PTR(-EINVAL); 656 657 return item_ptr; 658 } 659 660 e = cached_entry_next(e, part->cacheline); 661 } 662 663 if (WARN_ON((void *)e < (void *)phdr)) 664 return ERR_PTR(-EINVAL); 665 666 return ERR_PTR(-ENOENT); 667 668 invalid_canary: 669 dev_err(smem->dev, "Found invalid canary in hosts %hu:%hu partition\n", 670 le16_to_cpu(phdr->host0), le16_to_cpu(phdr->host1)); 671 672 return ERR_PTR(-EINVAL); 673 } 674 675 /** 676 * qcom_smem_get() - resolve ptr of size of a smem item 677 * @host: the remote processor, or -1 678 * @item: smem item handle 679 * @size: pointer to be filled out with size of the item 680 * 681 * Looks up smem item and returns pointer to it. Size of smem 682 * item is returned in @size. 683 * 684 * Return: a pointer to an SMEM item on success, ERR_PTR() on failure. 685 */ 686 void *qcom_smem_get(unsigned host, unsigned item, size_t *size) 687 { 688 struct smem_partition *part; 689 void *ptr; 690 691 if (IS_ERR(__smem)) 692 return __smem; 693 694 if (item >= __smem->item_count) 695 return ERR_PTR(-EINVAL); 696 697 part = xa_load(&__smem->partitions, host); 698 if (part) { 699 ptr = qcom_smem_get_private(__smem, part, item, size); 700 } else if (__smem->global_partition.virt_base) { 701 part = &__smem->global_partition; 702 ptr = qcom_smem_get_private(__smem, part, item, size); 703 } else { 704 ptr = qcom_smem_get_global(__smem, item, size); 705 } 706 707 return ptr; 708 } 709 EXPORT_SYMBOL_GPL(qcom_smem_get); 710 711 /** 712 * qcom_smem_get_free_space() - retrieve amount of free space in a partition 713 * @host: the remote processor identifying a partition, or -1 714 * 715 * To be used by smem clients as a quick way to determine if any new 716 * allocations has been made. 717 * 718 * Return: number of available bytes on success, negative errno on failure. 719 */ 720 int qcom_smem_get_free_space(unsigned host) 721 { 722 struct smem_partition *part; 723 struct smem_partition_header *phdr; 724 struct smem_header *header; 725 unsigned ret; 726 727 if (IS_ERR(__smem)) 728 return PTR_ERR(__smem); 729 730 part = xa_load(&__smem->partitions, host); 731 if (part) { 732 phdr = part->virt_base; 733 ret = le32_to_cpu(phdr->offset_free_cached) - 734 le32_to_cpu(phdr->offset_free_uncached); 735 736 if (ret > le32_to_cpu(part->size)) 737 return -EINVAL; 738 } else if (__smem->global_partition.virt_base) { 739 part = &__smem->global_partition; 740 phdr = part->virt_base; 741 ret = le32_to_cpu(phdr->offset_free_cached) - 742 le32_to_cpu(phdr->offset_free_uncached); 743 744 if (ret > le32_to_cpu(part->size)) 745 return -EINVAL; 746 } else { 747 header = __smem->regions[0].virt_base; 748 ret = le32_to_cpu(header->available); 749 750 if (ret > __smem->regions[0].size) 751 return -EINVAL; 752 } 753 754 return ret; 755 } 756 EXPORT_SYMBOL_GPL(qcom_smem_get_free_space); 757 758 static bool addr_in_range(void __iomem *base, size_t size, void *addr) 759 { 760 return base && ((void __iomem *)addr >= base && (void __iomem *)addr < base + size); 761 } 762 763 /** 764 * qcom_smem_virt_to_phys() - return the physical address associated 765 * with an smem item pointer (previously returned by qcom_smem_get() 766 * @p: the virtual address to convert 767 * 768 * Return: physical address of the SMEM item (if found), 0 otherwise 769 */ 770 phys_addr_t qcom_smem_virt_to_phys(void *p) 771 { 772 struct smem_partition *part; 773 struct smem_region *area; 774 unsigned long index; 775 u64 offset; 776 u32 i; 777 778 xa_for_each(&__smem->partitions, index, part) { 779 if (addr_in_range(part->virt_base, part->size, p)) { 780 offset = p - part->virt_base; 781 782 return (phys_addr_t)part->phys_base + offset; 783 } 784 } 785 786 part = &__smem->global_partition; 787 788 if (addr_in_range(part->virt_base, part->size, p)) { 789 offset = p - part->virt_base; 790 791 return (phys_addr_t)part->phys_base + offset; 792 } 793 794 for (i = 0; i < __smem->num_regions; i++) { 795 area = &__smem->regions[i]; 796 797 if (addr_in_range(area->virt_base, area->size, p)) { 798 offset = p - area->virt_base; 799 800 return (phys_addr_t)area->aux_base + offset; 801 } 802 } 803 804 return 0; 805 } 806 EXPORT_SYMBOL_GPL(qcom_smem_virt_to_phys); 807 808 /** 809 * qcom_smem_get_soc_id() - return the SoC ID 810 * @id: On success, we return the SoC ID here. 811 * 812 * Look up SoC ID from HW/SW build ID and return it. 813 * 814 * Return: 0 on success, negative errno on failure. 815 */ 816 int qcom_smem_get_soc_id(u32 *id) 817 { 818 struct socinfo *info; 819 820 info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, NULL); 821 if (IS_ERR(info)) 822 return PTR_ERR(info); 823 824 *id = __le32_to_cpu(info->id); 825 826 return 0; 827 } 828 EXPORT_SYMBOL_GPL(qcom_smem_get_soc_id); 829 830 /** 831 * qcom_smem_get_feature_code() - return the feature code 832 * @code: On success, return the feature code here. 833 * 834 * Look up the feature code identifier from SMEM and return it. 835 * 836 * Return: 0 on success, negative errno on failure. 837 */ 838 int qcom_smem_get_feature_code(u32 *code) 839 { 840 struct socinfo *info; 841 u32 raw_code; 842 843 info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, NULL); 844 if (IS_ERR(info)) 845 return PTR_ERR(info); 846 847 /* This only makes sense for socinfo >= 16 */ 848 if (__le32_to_cpu(info->fmt) < SOCINFO_VERSION(0, 16)) 849 return -EOPNOTSUPP; 850 851 raw_code = __le32_to_cpu(info->feature_code); 852 853 /* Ensure the value makes sense */ 854 if (raw_code > SOCINFO_FC_INT_MAX) 855 raw_code = SOCINFO_FC_UNKNOWN; 856 857 *code = raw_code; 858 859 return 0; 860 } 861 EXPORT_SYMBOL_GPL(qcom_smem_get_feature_code); 862 863 static int qcom_smem_get_sbl_version(struct qcom_smem *smem) 864 { 865 struct smem_header *header; 866 __le32 *versions; 867 868 header = smem->regions[0].virt_base; 869 versions = header->version; 870 871 return le32_to_cpu(versions[SMEM_MASTER_SBL_VERSION_INDEX]); 872 } 873 874 static struct smem_ptable *qcom_smem_get_ptable(struct qcom_smem *smem) 875 { 876 struct smem_ptable *ptable; 877 u32 version; 878 879 ptable = smem->ptable; 880 if (memcmp(ptable->magic, SMEM_PTABLE_MAGIC, sizeof(ptable->magic))) 881 return ERR_PTR(-ENOENT); 882 883 version = le32_to_cpu(ptable->version); 884 if (version != 1) { 885 dev_err(smem->dev, 886 "Unsupported partition header version %d\n", version); 887 return ERR_PTR(-EINVAL); 888 } 889 return ptable; 890 } 891 892 static u32 qcom_smem_get_item_count(struct qcom_smem *smem) 893 { 894 struct smem_ptable *ptable; 895 struct smem_info *info; 896 897 ptable = qcom_smem_get_ptable(smem); 898 if (IS_ERR_OR_NULL(ptable)) 899 return SMEM_ITEM_COUNT; 900 901 info = (struct smem_info *)&ptable->entry[le32_to_cpu(ptable->num_entries)]; 902 if (memcmp(info->magic, SMEM_INFO_MAGIC, sizeof(info->magic))) 903 return SMEM_ITEM_COUNT; 904 905 return le16_to_cpu(info->num_items); 906 } 907 908 /* 909 * Validate the partition header for a partition whose partition 910 * table entry is supplied. Returns a pointer to its header if 911 * valid, or a null pointer otherwise. 912 */ 913 static struct smem_partition_header * 914 qcom_smem_partition_header(struct qcom_smem *smem, 915 struct smem_ptable_entry *entry, u16 host0, u16 host1) 916 { 917 struct smem_partition_header *header; 918 u32 phys_addr; 919 u32 size; 920 921 phys_addr = smem->regions[0].aux_base + le32_to_cpu(entry->offset); 922 header = devm_ioremap_wc(smem->dev, phys_addr, le32_to_cpu(entry->size)); 923 924 if (!header) 925 return NULL; 926 927 if (memcmp(header->magic, SMEM_PART_MAGIC, sizeof(header->magic))) { 928 dev_err(smem->dev, "bad partition magic %4ph\n", header->magic); 929 return NULL; 930 } 931 932 if (host0 != le16_to_cpu(header->host0)) { 933 dev_err(smem->dev, "bad host0 (%hu != %hu)\n", 934 host0, le16_to_cpu(header->host0)); 935 return NULL; 936 } 937 if (host1 != le16_to_cpu(header->host1)) { 938 dev_err(smem->dev, "bad host1 (%hu != %hu)\n", 939 host1, le16_to_cpu(header->host1)); 940 return NULL; 941 } 942 943 size = le32_to_cpu(header->size); 944 if (size != le32_to_cpu(entry->size)) { 945 dev_err(smem->dev, "bad partition size (%u != %u)\n", 946 size, le32_to_cpu(entry->size)); 947 return NULL; 948 } 949 950 if (le32_to_cpu(header->offset_free_uncached) > size) { 951 dev_err(smem->dev, "bad partition free uncached (%u > %u)\n", 952 le32_to_cpu(header->offset_free_uncached), size); 953 return NULL; 954 } 955 956 return header; 957 } 958 959 static int qcom_smem_set_global_partition(struct qcom_smem *smem) 960 { 961 struct smem_partition_header *header; 962 struct smem_ptable_entry *entry; 963 struct smem_ptable *ptable; 964 bool found = false; 965 int i; 966 967 if (smem->global_partition.virt_base) { 968 dev_err(smem->dev, "Already found the global partition\n"); 969 return -EINVAL; 970 } 971 972 ptable = qcom_smem_get_ptable(smem); 973 if (IS_ERR(ptable)) 974 return PTR_ERR(ptable); 975 976 for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) { 977 entry = &ptable->entry[i]; 978 if (!le32_to_cpu(entry->offset)) 979 continue; 980 if (!le32_to_cpu(entry->size)) 981 continue; 982 983 if (le16_to_cpu(entry->host0) != SMEM_GLOBAL_HOST) 984 continue; 985 986 if (le16_to_cpu(entry->host1) == SMEM_GLOBAL_HOST) { 987 found = true; 988 break; 989 } 990 } 991 992 if (!found) { 993 dev_err(smem->dev, "Missing entry for global partition\n"); 994 return -EINVAL; 995 } 996 997 header = qcom_smem_partition_header(smem, entry, 998 SMEM_GLOBAL_HOST, SMEM_GLOBAL_HOST); 999 if (!header) 1000 return -EINVAL; 1001 1002 smem->global_partition.virt_base = (void __iomem *)header; 1003 smem->global_partition.phys_base = smem->regions[0].aux_base + 1004 le32_to_cpu(entry->offset); 1005 smem->global_partition.size = le32_to_cpu(entry->size); 1006 smem->global_partition.cacheline = le32_to_cpu(entry->cacheline); 1007 1008 return 0; 1009 } 1010 1011 static int 1012 qcom_smem_enumerate_partitions(struct qcom_smem *smem, u16 local_host) 1013 { 1014 struct smem_partition_header *header; 1015 struct smem_partition *part; 1016 struct smem_ptable_entry *entry; 1017 struct smem_ptable *ptable; 1018 u16 remote_host; 1019 u16 host0, host1; 1020 int ret; 1021 int i; 1022 1023 ptable = qcom_smem_get_ptable(smem); 1024 if (IS_ERR(ptable)) 1025 return PTR_ERR(ptable); 1026 1027 xa_init(&smem->partitions); 1028 1029 for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) { 1030 entry = &ptable->entry[i]; 1031 if (!le32_to_cpu(entry->offset)) 1032 continue; 1033 if (!le32_to_cpu(entry->size)) 1034 continue; 1035 1036 host0 = le16_to_cpu(entry->host0); 1037 host1 = le16_to_cpu(entry->host1); 1038 if (host0 == local_host) 1039 remote_host = host1; 1040 else if (host1 == local_host) 1041 remote_host = host0; 1042 else 1043 continue; 1044 1045 if (xa_load(&smem->partitions, remote_host)) { 1046 dev_err(smem->dev, "duplicate host %u\n", remote_host); 1047 return -EINVAL; 1048 } 1049 1050 header = qcom_smem_partition_header(smem, entry, host0, host1); 1051 if (!header) 1052 return -EINVAL; 1053 1054 part = devm_kzalloc(smem->dev, sizeof(struct smem_partition), GFP_KERNEL); 1055 if (!part) 1056 return -ENOMEM; 1057 1058 part->virt_base = (void __iomem *)header; 1059 part->phys_base = smem->regions[0].aux_base + le32_to_cpu(entry->offset); 1060 part->size = le32_to_cpu(entry->size); 1061 part->cacheline = le32_to_cpu(entry->cacheline); 1062 1063 ret = xa_insert(&smem->partitions, remote_host, part, GFP_KERNEL); 1064 if (ret) { 1065 dev_err(smem->dev, "fail to insert host %u\n", remote_host); 1066 return ret; 1067 } 1068 } 1069 1070 return 0; 1071 } 1072 1073 static int qcom_smem_map_toc(struct qcom_smem *smem, struct smem_region *region) 1074 { 1075 u32 ptable_start; 1076 1077 /* map starting 4K for smem header */ 1078 region->virt_base = devm_ioremap_wc(smem->dev, region->aux_base, SZ_4K); 1079 ptable_start = region->aux_base + region->size - SZ_4K; 1080 /* map last 4k for toc */ 1081 smem->ptable = devm_ioremap_wc(smem->dev, ptable_start, SZ_4K); 1082 1083 if (!region->virt_base || !smem->ptable) 1084 return -ENOMEM; 1085 1086 return 0; 1087 } 1088 1089 static int qcom_smem_map_global(struct qcom_smem *smem, u32 size) 1090 { 1091 u32 phys_addr; 1092 1093 phys_addr = smem->regions[0].aux_base; 1094 1095 smem->regions[0].size = size; 1096 smem->regions[0].virt_base = devm_ioremap_wc(smem->dev, phys_addr, size); 1097 1098 if (!smem->regions[0].virt_base) 1099 return -ENOMEM; 1100 1101 return 0; 1102 } 1103 1104 static int qcom_smem_resolve_mem(struct qcom_smem *smem, const char *name, 1105 struct smem_region *region) 1106 { 1107 struct device *dev = smem->dev; 1108 struct device_node *np; 1109 struct resource r; 1110 int ret; 1111 1112 np = of_parse_phandle(dev->of_node, name, 0); 1113 if (!np) { 1114 dev_err(dev, "No %s specified\n", name); 1115 return -EINVAL; 1116 } 1117 1118 ret = of_address_to_resource(np, 0, &r); 1119 of_node_put(np); 1120 if (ret) 1121 return ret; 1122 1123 region->aux_base = r.start; 1124 region->size = resource_size(&r); 1125 1126 return 0; 1127 } 1128 1129 static int qcom_smem_probe(struct platform_device *pdev) 1130 { 1131 struct smem_header *header; 1132 struct reserved_mem *rmem; 1133 struct qcom_smem *smem; 1134 unsigned long flags; 1135 int num_regions; 1136 int hwlock_id; 1137 u32 version; 1138 u32 size; 1139 int ret; 1140 int i; 1141 1142 num_regions = 1; 1143 if (of_property_present(pdev->dev.of_node, "qcom,rpm-msg-ram")) 1144 num_regions++; 1145 1146 smem = devm_kzalloc(&pdev->dev, struct_size(smem, regions, num_regions), 1147 GFP_KERNEL); 1148 if (!smem) 1149 return -ENOMEM; 1150 1151 smem->dev = &pdev->dev; 1152 smem->num_regions = num_regions; 1153 1154 rmem = of_reserved_mem_lookup(pdev->dev.of_node); 1155 if (rmem) { 1156 smem->regions[0].aux_base = rmem->base; 1157 smem->regions[0].size = rmem->size; 1158 } else { 1159 /* 1160 * Fall back to the memory-region reference, if we're not a 1161 * reserved-memory node. 1162 */ 1163 ret = qcom_smem_resolve_mem(smem, "memory-region", &smem->regions[0]); 1164 if (ret) 1165 return ret; 1166 } 1167 1168 if (num_regions > 1) { 1169 ret = qcom_smem_resolve_mem(smem, "qcom,rpm-msg-ram", &smem->regions[1]); 1170 if (ret) 1171 return ret; 1172 } 1173 1174 1175 ret = qcom_smem_map_toc(smem, &smem->regions[0]); 1176 if (ret) 1177 return ret; 1178 1179 for (i = 1; i < num_regions; i++) { 1180 smem->regions[i].virt_base = devm_ioremap_wc(&pdev->dev, 1181 smem->regions[i].aux_base, 1182 smem->regions[i].size); 1183 if (!smem->regions[i].virt_base) { 1184 dev_err(&pdev->dev, "failed to remap %pa\n", &smem->regions[i].aux_base); 1185 return -ENOMEM; 1186 } 1187 } 1188 1189 header = smem->regions[0].virt_base; 1190 if (le32_to_cpu(header->initialized) != 1 || 1191 le32_to_cpu(header->reserved)) { 1192 __smem = ERR_PTR(-ENODEV); 1193 return dev_err_probe(&pdev->dev, PTR_ERR(__smem), "SMEM is not initialized by SBL\n"); 1194 } 1195 1196 hwlock_id = of_hwspin_lock_get_id(pdev->dev.of_node, 0); 1197 if (hwlock_id < 0) 1198 return dev_err_probe(&pdev->dev, hwlock_id, 1199 "failed to retrieve hwlock\n"); 1200 1201 smem->hwlock = devm_hwspin_lock_request_specific(&pdev->dev, hwlock_id); 1202 if (!smem->hwlock) 1203 return -ENXIO; 1204 1205 ret = hwspin_lock_timeout_irqsave(smem->hwlock, HWSPINLOCK_TIMEOUT, &flags); 1206 if (ret) 1207 return ret; 1208 size = readl_relaxed(&header->available) + readl_relaxed(&header->free_offset); 1209 hwspin_unlock_irqrestore(smem->hwlock, &flags); 1210 1211 version = qcom_smem_get_sbl_version(smem); 1212 /* 1213 * smem header mapping is required only in heap version scheme, so unmap 1214 * it here. It will be remapped in qcom_smem_map_global() when whole 1215 * partition is mapped again. 1216 */ 1217 devm_iounmap(smem->dev, smem->regions[0].virt_base); 1218 switch (version >> 16) { 1219 case SMEM_GLOBAL_PART_VERSION: 1220 ret = qcom_smem_set_global_partition(smem); 1221 if (ret < 0) 1222 return ret; 1223 smem->item_count = qcom_smem_get_item_count(smem); 1224 break; 1225 case SMEM_GLOBAL_HEAP_VERSION: 1226 ret = qcom_smem_map_global(smem, size); 1227 if (ret < 0) 1228 return ret; 1229 smem->item_count = SMEM_ITEM_COUNT; 1230 break; 1231 default: 1232 dev_err(&pdev->dev, "Unsupported SMEM version 0x%x\n", version); 1233 return -EINVAL; 1234 } 1235 1236 ret = qcom_smem_enumerate_partitions(smem, SMEM_HOST_APPS); 1237 if (ret < 0 && ret != -ENOENT) 1238 return ret; 1239 1240 __smem = smem; 1241 1242 smem->socinfo = platform_device_register_data(&pdev->dev, "qcom-socinfo", 1243 PLATFORM_DEVID_NONE, NULL, 1244 0); 1245 if (IS_ERR(smem->socinfo)) 1246 dev_dbg(&pdev->dev, "failed to register socinfo device\n"); 1247 1248 return 0; 1249 } 1250 1251 static void qcom_smem_remove(struct platform_device *pdev) 1252 { 1253 platform_device_unregister(__smem->socinfo); 1254 1255 xa_destroy(&__smem->partitions); 1256 /* Set to -EPROBE_DEFER to signal unprobed state */ 1257 __smem = ERR_PTR(-EPROBE_DEFER); 1258 } 1259 1260 static const struct of_device_id qcom_smem_of_match[] = { 1261 { .compatible = "qcom,smem" }, 1262 {} 1263 }; 1264 MODULE_DEVICE_TABLE(of, qcom_smem_of_match); 1265 1266 static struct platform_driver qcom_smem_driver = { 1267 .probe = qcom_smem_probe, 1268 .remove = qcom_smem_remove, 1269 .driver = { 1270 .name = "qcom-smem", 1271 .of_match_table = qcom_smem_of_match, 1272 .suppress_bind_attrs = true, 1273 }, 1274 }; 1275 1276 static int __init qcom_smem_init(void) 1277 { 1278 return platform_driver_register(&qcom_smem_driver); 1279 } 1280 arch_initcall(qcom_smem_init); 1281 1282 static void __exit qcom_smem_exit(void) 1283 { 1284 platform_driver_unregister(&qcom_smem_driver); 1285 } 1286 module_exit(qcom_smem_exit) 1287 1288 MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>"); 1289 MODULE_DESCRIPTION("Qualcomm Shared Memory Manager"); 1290 MODULE_LICENSE("GPL v2"); 1291