Lines Matching +full:smem +full:- +full:part
1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
16 #include <linux/soc/qcom/smem.h>
38 * (@smem_ptable), that is found 4kB from the end of the main smem region. The
44 * two regions are cached and non-cached memory respectively. Each region
48 * Items in the non-cached region are allocated from the start of the partition
50 * is hence the region between the cached and non-cached offsets. The header of
55 * region with partition type (SMEM_GLOBAL_HOST) and the max smem item count is
59 * be held - currently lock number 3 of the sfpb or tcsr is used for this on all
65 * The version member of the smem header contains an array of versions for the
92 * struct smem_proc_comm - proc_comm communication struct (legacy)
104 * struct smem_global_entry - entry to reference smem items on the heap
120 * struct smem_header - header found in beginning of primary smem region
123 * @initialized: boolean to indicate that smem is initialized
124 * @free_offset: index of the first unallocated byte in smem
140 * struct smem_ptable_entry - one entry in the @smem_ptable list
160 * struct smem_ptable - partition table for the private partitions
178 * struct smem_partition_header - header of the partitions
200 * struct smem_partition - describes smem partition
216 * struct smem_private_entry - header of each item in the private partition
218 * @item: identifying number of the smem item
235 * struct smem_info - smem region info located after the table of contents
237 * @size: size of the smem region
238 * @base_addr: base address of the smem region
253 * struct smem_region - representation of a chunk of memory used for smem
265 * struct qcom_smem - device data for the smem device
296 return p + le32_to_cpu(phdr->offset_free_uncached); in phdr_to_last_uncached_entry()
306 return p + le32_to_cpu(phdr->size) - ALIGN(sizeof(*e), cacheline); in phdr_to_first_cached_entry()
314 return p + le32_to_cpu(phdr->offset_free_cached); in phdr_to_last_cached_entry()
330 return p + sizeof(*e) + le16_to_cpu(e->padding_hdr) + in uncached_entry_next()
331 le32_to_cpu(e->size); in uncached_entry_next()
339 return p - le32_to_cpu(e->size) - ALIGN(sizeof(*e), cacheline); in cached_entry_next()
346 return p + sizeof(*e) + le16_to_cpu(e->padding_hdr); in uncached_entry_to_item()
353 return p - le32_to_cpu(e->size); in cached_entry_to_item()
357 * Pointer to the one and only smem handle.
358 * Init to -EPROBE_DEFER to signal SMEM still has to be probed.
359 * Can be set to -ENODEV if SMEM is not initialized by SBL.
361 static struct qcom_smem *__smem = INIT_ERR_PTR(-EPROBE_DEFER);
366 /* The qcom hwspinlock id is always plus one from the smem host id */
370 * qcom_smem_bust_hwspin_lock_by_host() - bust the smem hwspinlock for a host
373 * Busts the hwspin_lock for the given smem host id. This helper is intended
374 * for remoteproc drivers that manage remoteprocs with an equivalent smem
376 * smem hwspin_lock if the rproc unexpectedly goes into a bad state.
386 return -EINVAL; in qcom_smem_bust_hwspin_lock_by_host()
388 return hwspin_lock_bust(__smem->hwlock, SMEM_HOST_ID_TO_HWSPINLOCK_ID(host)); in qcom_smem_bust_hwspin_lock_by_host()
393 * qcom_smem_is_available() - Check if SMEM is available
395 * Return: true if SMEM is available, false otherwise.
403 static int qcom_smem_alloc_private(struct qcom_smem *smem, in qcom_smem_alloc_private() argument
404 struct smem_partition *part, in qcom_smem_alloc_private() argument
414 phdr = (struct smem_partition_header __force *)part->virt_base; in qcom_smem_alloc_private()
415 p_end = (void *)phdr + part->size; in qcom_smem_alloc_private()
422 return -EINVAL; in qcom_smem_alloc_private()
425 if (hdr->canary != SMEM_PRIVATE_CANARY) in qcom_smem_alloc_private()
427 if (le16_to_cpu(hdr->item) == item) in qcom_smem_alloc_private()
428 return -EEXIST; in qcom_smem_alloc_private()
434 return -EINVAL; in qcom_smem_alloc_private()
439 dev_err(smem->dev, "Out of memory\n"); in qcom_smem_alloc_private()
440 return -ENOSPC; in qcom_smem_alloc_private()
443 hdr->canary = SMEM_PRIVATE_CANARY; in qcom_smem_alloc_private()
444 hdr->item = cpu_to_le16(item); in qcom_smem_alloc_private()
445 hdr->size = cpu_to_le32(ALIGN(size, 8)); in qcom_smem_alloc_private()
446 hdr->padding_data = cpu_to_le16(le32_to_cpu(hdr->size) - size); in qcom_smem_alloc_private()
447 hdr->padding_hdr = 0; in qcom_smem_alloc_private()
455 le32_add_cpu(&phdr->offset_free_uncached, alloc_size); in qcom_smem_alloc_private()
459 dev_err(smem->dev, "Found invalid canary in hosts %hu:%hu partition\n", in qcom_smem_alloc_private()
460 le16_to_cpu(phdr->host0), le16_to_cpu(phdr->host1)); in qcom_smem_alloc_private()
462 return -EINVAL; in qcom_smem_alloc_private()
465 static int qcom_smem_alloc_global(struct qcom_smem *smem, in qcom_smem_alloc_global() argument
472 header = smem->regions[0].virt_base; in qcom_smem_alloc_global()
473 entry = &header->toc[item]; in qcom_smem_alloc_global()
474 if (entry->allocated) in qcom_smem_alloc_global()
475 return -EEXIST; in qcom_smem_alloc_global()
478 if (WARN_ON(size > le32_to_cpu(header->available))) in qcom_smem_alloc_global()
479 return -ENOMEM; in qcom_smem_alloc_global()
481 entry->offset = header->free_offset; in qcom_smem_alloc_global()
482 entry->size = cpu_to_le32(size); in qcom_smem_alloc_global()
490 entry->allocated = cpu_to_le32(1); in qcom_smem_alloc_global()
492 le32_add_cpu(&header->free_offset, size); in qcom_smem_alloc_global()
493 le32_add_cpu(&header->available, -size); in qcom_smem_alloc_global()
499 * qcom_smem_alloc() - allocate space for a smem item
500 * @host: remote processor id, or -1
501 * @item: smem item handle
504 * Allocate space for a given smem item of size @size, given that the item is
511 struct smem_partition *part; in qcom_smem_alloc() local
519 dev_err(__smem->dev, in qcom_smem_alloc()
521 return -EINVAL; in qcom_smem_alloc()
524 if (item >= __smem->item_count) in qcom_smem_alloc()
525 return -EINVAL; in qcom_smem_alloc()
527 ret = hwspin_lock_timeout_irqsave(__smem->hwlock, in qcom_smem_alloc()
533 if (host < SMEM_HOST_COUNT && __smem->partitions[host].virt_base) { in qcom_smem_alloc()
534 part = &__smem->partitions[host]; in qcom_smem_alloc()
535 ret = qcom_smem_alloc_private(__smem, part, item, size); in qcom_smem_alloc()
536 } else if (__smem->global_partition.virt_base) { in qcom_smem_alloc()
537 part = &__smem->global_partition; in qcom_smem_alloc()
538 ret = qcom_smem_alloc_private(__smem, part, item, size); in qcom_smem_alloc()
543 hwspin_unlock_irqrestore(__smem->hwlock, &flags); in qcom_smem_alloc()
549 static void *qcom_smem_get_global(struct qcom_smem *smem, in qcom_smem_get_global() argument
561 header = smem->regions[0].virt_base; in qcom_smem_get_global()
562 entry = &header->toc[item]; in qcom_smem_get_global()
563 if (!entry->allocated) in qcom_smem_get_global()
564 return ERR_PTR(-ENXIO); in qcom_smem_get_global()
566 aux_base = le32_to_cpu(entry->aux_base) & AUX_BASE_MASK; in qcom_smem_get_global()
568 for (i = 0; i < smem->num_regions; i++) { in qcom_smem_get_global()
569 region = &smem->regions[i]; in qcom_smem_get_global()
571 if ((u32)region->aux_base == aux_base || !aux_base) { in qcom_smem_get_global()
572 e_size = le32_to_cpu(entry->size); in qcom_smem_get_global()
573 entry_offset = le32_to_cpu(entry->offset); in qcom_smem_get_global()
575 if (WARN_ON(e_size + entry_offset > region->size)) in qcom_smem_get_global()
576 return ERR_PTR(-EINVAL); in qcom_smem_get_global()
581 return region->virt_base + entry_offset; in qcom_smem_get_global()
585 return ERR_PTR(-ENOENT); in qcom_smem_get_global()
588 static void *qcom_smem_get_private(struct qcom_smem *smem, in qcom_smem_get_private() argument
589 struct smem_partition *part, in qcom_smem_get_private() argument
599 phdr = (struct smem_partition_header __force *)part->virt_base; in qcom_smem_get_private()
600 p_end = (void *)phdr + part->size; in qcom_smem_get_private()
606 if (e->canary != SMEM_PRIVATE_CANARY) in qcom_smem_get_private()
609 if (le16_to_cpu(e->item) == item) { in qcom_smem_get_private()
611 e_size = le32_to_cpu(e->size); in qcom_smem_get_private()
612 padding_data = le16_to_cpu(e->padding_data); in qcom_smem_get_private()
614 if (WARN_ON(e_size > part->size || padding_data > e_size)) in qcom_smem_get_private()
615 return ERR_PTR(-EINVAL); in qcom_smem_get_private()
617 *size = e_size - padding_data; in qcom_smem_get_private()
622 return ERR_PTR(-EINVAL); in qcom_smem_get_private()
631 return ERR_PTR(-EINVAL); in qcom_smem_get_private()
635 e = phdr_to_first_cached_entry(phdr, part->cacheline); in qcom_smem_get_private()
639 return ERR_PTR(-EINVAL); in qcom_smem_get_private()
642 if (e->canary != SMEM_PRIVATE_CANARY) in qcom_smem_get_private()
645 if (le16_to_cpu(e->item) == item) { in qcom_smem_get_private()
647 e_size = le32_to_cpu(e->size); in qcom_smem_get_private()
648 padding_data = le16_to_cpu(e->padding_data); in qcom_smem_get_private()
650 if (WARN_ON(e_size > part->size || padding_data > e_size)) in qcom_smem_get_private()
651 return ERR_PTR(-EINVAL); in qcom_smem_get_private()
653 *size = e_size - padding_data; in qcom_smem_get_private()
658 return ERR_PTR(-EINVAL); in qcom_smem_get_private()
663 e = cached_entry_next(e, part->cacheline); in qcom_smem_get_private()
667 return ERR_PTR(-EINVAL); in qcom_smem_get_private()
669 return ERR_PTR(-ENOENT); in qcom_smem_get_private()
672 dev_err(smem->dev, "Found invalid canary in hosts %hu:%hu partition\n", in qcom_smem_get_private()
673 le16_to_cpu(phdr->host0), le16_to_cpu(phdr->host1)); in qcom_smem_get_private()
675 return ERR_PTR(-EINVAL); in qcom_smem_get_private()
679 * qcom_smem_get() - resolve ptr of size of a smem item
680 * @host: the remote processor, or -1
681 * @item: smem item handle
684 * Looks up smem item and returns pointer to it. Size of smem
687 * Return: a pointer to an SMEM item on success, ERR_PTR() on failure.
691 struct smem_partition *part; in qcom_smem_get() local
697 if (item >= __smem->item_count) in qcom_smem_get()
698 return ERR_PTR(-EINVAL); in qcom_smem_get()
700 if (host < SMEM_HOST_COUNT && __smem->partitions[host].virt_base) { in qcom_smem_get()
701 part = &__smem->partitions[host]; in qcom_smem_get()
702 ptr = qcom_smem_get_private(__smem, part, item, size); in qcom_smem_get()
703 } else if (__smem->global_partition.virt_base) { in qcom_smem_get()
704 part = &__smem->global_partition; in qcom_smem_get()
705 ptr = qcom_smem_get_private(__smem, part, item, size); in qcom_smem_get()
715 * qcom_smem_get_free_space() - retrieve amount of free space in a partition
716 * @host: the remote processor identifying a partition, or -1
718 * To be used by smem clients as a quick way to determine if any new
725 struct smem_partition *part; in qcom_smem_get_free_space() local
733 if (host < SMEM_HOST_COUNT && __smem->partitions[host].virt_base) { in qcom_smem_get_free_space()
734 part = &__smem->partitions[host]; in qcom_smem_get_free_space()
735 phdr = part->virt_base; in qcom_smem_get_free_space()
736 ret = le32_to_cpu(phdr->offset_free_cached) - in qcom_smem_get_free_space()
737 le32_to_cpu(phdr->offset_free_uncached); in qcom_smem_get_free_space()
739 if (ret > le32_to_cpu(part->size)) in qcom_smem_get_free_space()
740 return -EINVAL; in qcom_smem_get_free_space()
741 } else if (__smem->global_partition.virt_base) { in qcom_smem_get_free_space()
742 part = &__smem->global_partition; in qcom_smem_get_free_space()
743 phdr = part->virt_base; in qcom_smem_get_free_space()
744 ret = le32_to_cpu(phdr->offset_free_cached) - in qcom_smem_get_free_space()
745 le32_to_cpu(phdr->offset_free_uncached); in qcom_smem_get_free_space()
747 if (ret > le32_to_cpu(part->size)) in qcom_smem_get_free_space()
748 return -EINVAL; in qcom_smem_get_free_space()
750 header = __smem->regions[0].virt_base; in qcom_smem_get_free_space()
751 ret = le32_to_cpu(header->available); in qcom_smem_get_free_space()
753 if (ret > __smem->regions[0].size) in qcom_smem_get_free_space()
754 return -EINVAL; in qcom_smem_get_free_space()
767 * qcom_smem_virt_to_phys() - return the physical address associated
768 * with an smem item pointer (previously returned by qcom_smem_get()
771 * Return: physical address of the SMEM item (if found), 0 otherwise
775 struct smem_partition *part; in qcom_smem_virt_to_phys() local
781 part = &__smem->partitions[i]; in qcom_smem_virt_to_phys()
783 if (addr_in_range(part->virt_base, part->size, p)) { in qcom_smem_virt_to_phys()
784 offset = p - part->virt_base; in qcom_smem_virt_to_phys()
786 return (phys_addr_t)part->phys_base + offset; in qcom_smem_virt_to_phys()
790 part = &__smem->global_partition; in qcom_smem_virt_to_phys()
792 if (addr_in_range(part->virt_base, part->size, p)) { in qcom_smem_virt_to_phys()
793 offset = p - part->virt_base; in qcom_smem_virt_to_phys()
795 return (phys_addr_t)part->phys_base + offset; in qcom_smem_virt_to_phys()
798 for (i = 0; i < __smem->num_regions; i++) { in qcom_smem_virt_to_phys()
799 area = &__smem->regions[i]; in qcom_smem_virt_to_phys()
801 if (addr_in_range(area->virt_base, area->size, p)) { in qcom_smem_virt_to_phys()
802 offset = p - area->virt_base; in qcom_smem_virt_to_phys()
804 return (phys_addr_t)area->aux_base + offset; in qcom_smem_virt_to_phys()
813 * qcom_smem_get_soc_id() - return the SoC ID
828 *id = __le32_to_cpu(info->id); in qcom_smem_get_soc_id()
835 * qcom_smem_get_feature_code() - return the feature code
838 * Look up the feature code identifier from SMEM and return it.
852 if (__le32_to_cpu(info->fmt) < SOCINFO_VERSION(0, 16)) in qcom_smem_get_feature_code()
853 return -EOPNOTSUPP; in qcom_smem_get_feature_code()
855 raw_code = __le32_to_cpu(info->feature_code); in qcom_smem_get_feature_code()
867 static int qcom_smem_get_sbl_version(struct qcom_smem *smem) in qcom_smem_get_sbl_version() argument
872 header = smem->regions[0].virt_base; in qcom_smem_get_sbl_version()
873 versions = header->version; in qcom_smem_get_sbl_version()
878 static struct smem_ptable *qcom_smem_get_ptable(struct qcom_smem *smem) in qcom_smem_get_ptable() argument
883 ptable = smem->ptable; in qcom_smem_get_ptable()
884 if (memcmp(ptable->magic, SMEM_PTABLE_MAGIC, sizeof(ptable->magic))) in qcom_smem_get_ptable()
885 return ERR_PTR(-ENOENT); in qcom_smem_get_ptable()
887 version = le32_to_cpu(ptable->version); in qcom_smem_get_ptable()
889 dev_err(smem->dev, in qcom_smem_get_ptable()
891 return ERR_PTR(-EINVAL); in qcom_smem_get_ptable()
896 static u32 qcom_smem_get_item_count(struct qcom_smem *smem) in qcom_smem_get_item_count() argument
901 ptable = qcom_smem_get_ptable(smem); in qcom_smem_get_item_count()
905 info = (struct smem_info *)&ptable->entry[le32_to_cpu(ptable->num_entries)]; in qcom_smem_get_item_count()
906 if (memcmp(info->magic, SMEM_INFO_MAGIC, sizeof(info->magic))) in qcom_smem_get_item_count()
909 return le16_to_cpu(info->num_items); in qcom_smem_get_item_count()
918 qcom_smem_partition_header(struct qcom_smem *smem, in qcom_smem_partition_header() argument
925 phys_addr = smem->regions[0].aux_base + le32_to_cpu(entry->offset); in qcom_smem_partition_header()
926 header = devm_ioremap_wc(smem->dev, phys_addr, le32_to_cpu(entry->size)); in qcom_smem_partition_header()
931 if (memcmp(header->magic, SMEM_PART_MAGIC, sizeof(header->magic))) { in qcom_smem_partition_header()
932 dev_err(smem->dev, "bad partition magic %4ph\n", header->magic); in qcom_smem_partition_header()
936 if (host0 != le16_to_cpu(header->host0)) { in qcom_smem_partition_header()
937 dev_err(smem->dev, "bad host0 (%hu != %hu)\n", in qcom_smem_partition_header()
938 host0, le16_to_cpu(header->host0)); in qcom_smem_partition_header()
941 if (host1 != le16_to_cpu(header->host1)) { in qcom_smem_partition_header()
942 dev_err(smem->dev, "bad host1 (%hu != %hu)\n", in qcom_smem_partition_header()
943 host1, le16_to_cpu(header->host1)); in qcom_smem_partition_header()
947 size = le32_to_cpu(header->size); in qcom_smem_partition_header()
948 if (size != le32_to_cpu(entry->size)) { in qcom_smem_partition_header()
949 dev_err(smem->dev, "bad partition size (%u != %u)\n", in qcom_smem_partition_header()
950 size, le32_to_cpu(entry->size)); in qcom_smem_partition_header()
954 if (le32_to_cpu(header->offset_free_uncached) > size) { in qcom_smem_partition_header()
955 dev_err(smem->dev, "bad partition free uncached (%u > %u)\n", in qcom_smem_partition_header()
956 le32_to_cpu(header->offset_free_uncached), size); in qcom_smem_partition_header()
963 static int qcom_smem_set_global_partition(struct qcom_smem *smem) in qcom_smem_set_global_partition() argument
971 if (smem->global_partition.virt_base) { in qcom_smem_set_global_partition()
972 dev_err(smem->dev, "Already found the global partition\n"); in qcom_smem_set_global_partition()
973 return -EINVAL; in qcom_smem_set_global_partition()
976 ptable = qcom_smem_get_ptable(smem); in qcom_smem_set_global_partition()
980 for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) { in qcom_smem_set_global_partition()
981 entry = &ptable->entry[i]; in qcom_smem_set_global_partition()
982 if (!le32_to_cpu(entry->offset)) in qcom_smem_set_global_partition()
984 if (!le32_to_cpu(entry->size)) in qcom_smem_set_global_partition()
987 if (le16_to_cpu(entry->host0) != SMEM_GLOBAL_HOST) in qcom_smem_set_global_partition()
990 if (le16_to_cpu(entry->host1) == SMEM_GLOBAL_HOST) { in qcom_smem_set_global_partition()
997 dev_err(smem->dev, "Missing entry for global partition\n"); in qcom_smem_set_global_partition()
998 return -EINVAL; in qcom_smem_set_global_partition()
1001 header = qcom_smem_partition_header(smem, entry, in qcom_smem_set_global_partition()
1004 return -EINVAL; in qcom_smem_set_global_partition()
1006 smem->global_partition.virt_base = (void __iomem *)header; in qcom_smem_set_global_partition()
1007 smem->global_partition.phys_base = smem->regions[0].aux_base + in qcom_smem_set_global_partition()
1008 le32_to_cpu(entry->offset); in qcom_smem_set_global_partition()
1009 smem->global_partition.size = le32_to_cpu(entry->size); in qcom_smem_set_global_partition()
1010 smem->global_partition.cacheline = le32_to_cpu(entry->cacheline); in qcom_smem_set_global_partition()
1016 qcom_smem_enumerate_partitions(struct qcom_smem *smem, u16 local_host) in qcom_smem_enumerate_partitions() argument
1025 ptable = qcom_smem_get_ptable(smem); in qcom_smem_enumerate_partitions()
1029 for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) { in qcom_smem_enumerate_partitions()
1030 entry = &ptable->entry[i]; in qcom_smem_enumerate_partitions()
1031 if (!le32_to_cpu(entry->offset)) in qcom_smem_enumerate_partitions()
1033 if (!le32_to_cpu(entry->size)) in qcom_smem_enumerate_partitions()
1036 host0 = le16_to_cpu(entry->host0); in qcom_smem_enumerate_partitions()
1037 host1 = le16_to_cpu(entry->host1); in qcom_smem_enumerate_partitions()
1046 dev_err(smem->dev, "bad host %u\n", remote_host); in qcom_smem_enumerate_partitions()
1047 return -EINVAL; in qcom_smem_enumerate_partitions()
1050 if (smem->partitions[remote_host].virt_base) { in qcom_smem_enumerate_partitions()
1051 dev_err(smem->dev, "duplicate host %u\n", remote_host); in qcom_smem_enumerate_partitions()
1052 return -EINVAL; in qcom_smem_enumerate_partitions()
1055 header = qcom_smem_partition_header(smem, entry, host0, host1); in qcom_smem_enumerate_partitions()
1057 return -EINVAL; in qcom_smem_enumerate_partitions()
1059 smem->partitions[remote_host].virt_base = (void __iomem *)header; in qcom_smem_enumerate_partitions()
1060 smem->partitions[remote_host].phys_base = smem->regions[0].aux_base + in qcom_smem_enumerate_partitions()
1061 le32_to_cpu(entry->offset); in qcom_smem_enumerate_partitions()
1062 smem->partitions[remote_host].size = le32_to_cpu(entry->size); in qcom_smem_enumerate_partitions()
1063 smem->partitions[remote_host].cacheline = le32_to_cpu(entry->cacheline); in qcom_smem_enumerate_partitions()
1069 static int qcom_smem_map_toc(struct qcom_smem *smem, struct smem_region *region) in qcom_smem_map_toc() argument
1073 /* map starting 4K for smem header */ in qcom_smem_map_toc()
1074 region->virt_base = devm_ioremap_wc(smem->dev, region->aux_base, SZ_4K); in qcom_smem_map_toc()
1075 ptable_start = region->aux_base + region->size - SZ_4K; in qcom_smem_map_toc()
1077 smem->ptable = devm_ioremap_wc(smem->dev, ptable_start, SZ_4K); in qcom_smem_map_toc()
1079 if (!region->virt_base || !smem->ptable) in qcom_smem_map_toc()
1080 return -ENOMEM; in qcom_smem_map_toc()
1085 static int qcom_smem_map_global(struct qcom_smem *smem, u32 size) in qcom_smem_map_global() argument
1089 phys_addr = smem->regions[0].aux_base; in qcom_smem_map_global()
1091 smem->regions[0].size = size; in qcom_smem_map_global()
1092 smem->regions[0].virt_base = devm_ioremap_wc(smem->dev, phys_addr, size); in qcom_smem_map_global()
1094 if (!smem->regions[0].virt_base) in qcom_smem_map_global()
1095 return -ENOMEM; in qcom_smem_map_global()
1100 static int qcom_smem_resolve_mem(struct qcom_smem *smem, const char *name, in qcom_smem_resolve_mem() argument
1103 struct device *dev = smem->dev; in qcom_smem_resolve_mem()
1108 np = of_parse_phandle(dev->of_node, name, 0); in qcom_smem_resolve_mem()
1111 return -EINVAL; in qcom_smem_resolve_mem()
1119 region->aux_base = r.start; in qcom_smem_resolve_mem()
1120 region->size = resource_size(&r); in qcom_smem_resolve_mem()
1129 struct qcom_smem *smem; in qcom_smem_probe() local
1139 if (of_property_present(pdev->dev.of_node, "qcom,rpm-msg-ram")) in qcom_smem_probe()
1142 smem = devm_kzalloc(&pdev->dev, struct_size(smem, regions, num_regions), in qcom_smem_probe()
1144 if (!smem) in qcom_smem_probe()
1145 return -ENOMEM; in qcom_smem_probe()
1147 smem->dev = &pdev->dev; in qcom_smem_probe()
1148 smem->num_regions = num_regions; in qcom_smem_probe()
1150 rmem = of_reserved_mem_lookup(pdev->dev.of_node); in qcom_smem_probe()
1152 smem->regions[0].aux_base = rmem->base; in qcom_smem_probe()
1153 smem->regions[0].size = rmem->size; in qcom_smem_probe()
1156 * Fall back to the memory-region reference, if we're not a in qcom_smem_probe()
1157 * reserved-memory node. in qcom_smem_probe()
1159 ret = qcom_smem_resolve_mem(smem, "memory-region", &smem->regions[0]); in qcom_smem_probe()
1165 ret = qcom_smem_resolve_mem(smem, "qcom,rpm-msg-ram", &smem->regions[1]); in qcom_smem_probe()
1171 ret = qcom_smem_map_toc(smem, &smem->regions[0]); in qcom_smem_probe()
1176 smem->regions[i].virt_base = devm_ioremap_wc(&pdev->dev, in qcom_smem_probe()
1177 smem->regions[i].aux_base, in qcom_smem_probe()
1178 smem->regions[i].size); in qcom_smem_probe()
1179 if (!smem->regions[i].virt_base) { in qcom_smem_probe()
1180 dev_err(&pdev->dev, "failed to remap %pa\n", &smem->regions[i].aux_base); in qcom_smem_probe()
1181 return -ENOMEM; in qcom_smem_probe()
1185 header = smem->regions[0].virt_base; in qcom_smem_probe()
1186 if (le32_to_cpu(header->initialized) != 1 || in qcom_smem_probe()
1187 le32_to_cpu(header->reserved)) { in qcom_smem_probe()
1188 __smem = ERR_PTR(-ENODEV); in qcom_smem_probe()
1189 return dev_err_probe(&pdev->dev, PTR_ERR(__smem), "SMEM is not initialized by SBL\n"); in qcom_smem_probe()
1192 hwlock_id = of_hwspin_lock_get_id(pdev->dev.of_node, 0); in qcom_smem_probe()
1194 return dev_err_probe(&pdev->dev, hwlock_id, in qcom_smem_probe()
1197 smem->hwlock = devm_hwspin_lock_request_specific(&pdev->dev, hwlock_id); in qcom_smem_probe()
1198 if (!smem->hwlock) in qcom_smem_probe()
1199 return -ENXIO; in qcom_smem_probe()
1201 ret = hwspin_lock_timeout_irqsave(smem->hwlock, HWSPINLOCK_TIMEOUT, &flags); in qcom_smem_probe()
1204 size = readl_relaxed(&header->available) + readl_relaxed(&header->free_offset); in qcom_smem_probe()
1205 hwspin_unlock_irqrestore(smem->hwlock, &flags); in qcom_smem_probe()
1207 version = qcom_smem_get_sbl_version(smem); in qcom_smem_probe()
1209 * smem header mapping is required only in heap version scheme, so unmap in qcom_smem_probe()
1213 devm_iounmap(smem->dev, smem->regions[0].virt_base); in qcom_smem_probe()
1216 ret = qcom_smem_set_global_partition(smem); in qcom_smem_probe()
1219 smem->item_count = qcom_smem_get_item_count(smem); in qcom_smem_probe()
1222 qcom_smem_map_global(smem, size); in qcom_smem_probe()
1223 smem->item_count = SMEM_ITEM_COUNT; in qcom_smem_probe()
1226 dev_err(&pdev->dev, "Unsupported SMEM version 0x%x\n", version); in qcom_smem_probe()
1227 return -EINVAL; in qcom_smem_probe()
1231 ret = qcom_smem_enumerate_partitions(smem, SMEM_HOST_APPS); in qcom_smem_probe()
1232 if (ret < 0 && ret != -ENOENT) in qcom_smem_probe()
1235 __smem = smem; in qcom_smem_probe()
1237 smem->socinfo = platform_device_register_data(&pdev->dev, "qcom-socinfo", in qcom_smem_probe()
1240 if (IS_ERR(smem->socinfo)) in qcom_smem_probe()
1241 dev_dbg(&pdev->dev, "failed to register socinfo device\n"); in qcom_smem_probe()
1248 platform_device_unregister(__smem->socinfo); in qcom_smem_remove()
1254 { .compatible = "qcom,smem" },
1263 .name = "qcom-smem",