Lines Matching +full:rpm +full:- +full:msg +full:- +full:ram

1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
42 * two regions are cached and non-cached memory respectively. Each region
46 * Items in the non-cached region are allocated from the start of the partition
48 * is hence the region between the cached and non-cached offsets. The header of
57 * be held - currently lock number 3 of the sfpb or tcsr is used for this on all
90 * struct smem_proc_comm - proc_comm communication struct (legacy)
102 * struct smem_global_entry - entry to reference smem items on the heap
118 * struct smem_header - header found in beginning of primary smem region
138 * struct smem_ptable_entry - one entry in the @smem_ptable list
158 * struct smem_ptable - partition table for the private partitions
176 * struct smem_partition_header - header of the partitions
200 * struct smem_private_entry - header of each item in the private partition
219 * struct smem_info - smem region info located after the table of contents
237 * struct smem_region - representation of a chunk of memory used for smem
249 * struct qcom_smem - device data for the smem device
282 return p + le32_to_cpu(phdr->offset_free_uncached); in phdr_to_last_uncached_entry()
292 return p + le32_to_cpu(phdr->size) - ALIGN(sizeof(*e), cacheline); in phdr_to_first_cached_entry()
300 return p + le32_to_cpu(phdr->offset_free_cached); in phdr_to_last_cached_entry()
316 return p + sizeof(*e) + le16_to_cpu(e->padding_hdr) + in uncached_entry_next()
317 le32_to_cpu(e->size); in uncached_entry_next()
325 return p - le32_to_cpu(e->size) - ALIGN(sizeof(*e), cacheline); in cached_entry_next()
332 return p + sizeof(*e) + le16_to_cpu(e->padding_hdr); in uncached_entry_to_item()
339 return p - le32_to_cpu(e->size); in cached_entry_to_item()
362 if (hdr->canary != SMEM_PRIVATE_CANARY) in qcom_smem_alloc_private()
364 if (le16_to_cpu(hdr->item) == item) in qcom_smem_alloc_private()
365 return -EEXIST; in qcom_smem_alloc_private()
373 dev_err(smem->dev, "Out of memory\n"); in qcom_smem_alloc_private()
374 return -ENOSPC; in qcom_smem_alloc_private()
377 hdr->canary = SMEM_PRIVATE_CANARY; in qcom_smem_alloc_private()
378 hdr->item = cpu_to_le16(item); in qcom_smem_alloc_private()
379 hdr->size = cpu_to_le32(ALIGN(size, 8)); in qcom_smem_alloc_private()
380 hdr->padding_data = cpu_to_le16(le32_to_cpu(hdr->size) - size); in qcom_smem_alloc_private()
381 hdr->padding_hdr = 0; in qcom_smem_alloc_private()
389 le32_add_cpu(&phdr->offset_free_uncached, alloc_size); in qcom_smem_alloc_private()
393 dev_err(smem->dev, "Found invalid canary in hosts %hu:%hu partition\n", in qcom_smem_alloc_private()
394 le16_to_cpu(phdr->host0), le16_to_cpu(phdr->host1)); in qcom_smem_alloc_private()
396 return -EINVAL; in qcom_smem_alloc_private()
406 header = smem->regions[0].virt_base; in qcom_smem_alloc_global()
407 entry = &header->toc[item]; in qcom_smem_alloc_global()
408 if (entry->allocated) in qcom_smem_alloc_global()
409 return -EEXIST; in qcom_smem_alloc_global()
412 if (WARN_ON(size > le32_to_cpu(header->available))) in qcom_smem_alloc_global()
413 return -ENOMEM; in qcom_smem_alloc_global()
415 entry->offset = header->free_offset; in qcom_smem_alloc_global()
416 entry->size = cpu_to_le32(size); in qcom_smem_alloc_global()
424 entry->allocated = cpu_to_le32(1); in qcom_smem_alloc_global()
426 le32_add_cpu(&header->free_offset, size); in qcom_smem_alloc_global()
427 le32_add_cpu(&header->available, -size); in qcom_smem_alloc_global()
433 * qcom_smem_alloc() - allocate space for a smem item
434 * @host: remote processor id, or -1
448 return -EPROBE_DEFER; in qcom_smem_alloc()
451 dev_err(__smem->dev, in qcom_smem_alloc()
453 return -EINVAL; in qcom_smem_alloc()
456 if (WARN_ON(item >= __smem->item_count)) in qcom_smem_alloc()
457 return -EINVAL; in qcom_smem_alloc()
459 ret = hwspin_lock_timeout_irqsave(__smem->hwlock, in qcom_smem_alloc()
465 if (host < SMEM_HOST_COUNT && __smem->partitions[host]) { in qcom_smem_alloc()
466 phdr = __smem->partitions[host]; in qcom_smem_alloc()
468 } else if (__smem->global_partition) { in qcom_smem_alloc()
469 phdr = __smem->global_partition; in qcom_smem_alloc()
475 hwspin_unlock_irqrestore(__smem->hwlock, &flags); in qcom_smem_alloc()
491 header = smem->regions[0].virt_base; in qcom_smem_get_global()
492 entry = &header->toc[item]; in qcom_smem_get_global()
493 if (!entry->allocated) in qcom_smem_get_global()
494 return ERR_PTR(-ENXIO); in qcom_smem_get_global()
496 aux_base = le32_to_cpu(entry->aux_base) & AUX_BASE_MASK; in qcom_smem_get_global()
498 for (i = 0; i < smem->num_regions; i++) { in qcom_smem_get_global()
499 region = &smem->regions[i]; in qcom_smem_get_global()
501 if (region->aux_base == aux_base || !aux_base) { in qcom_smem_get_global()
503 *size = le32_to_cpu(entry->size); in qcom_smem_get_global()
504 return region->virt_base + le32_to_cpu(entry->offset); in qcom_smem_get_global()
508 return ERR_PTR(-ENOENT); in qcom_smem_get_global()
523 if (e->canary != SMEM_PRIVATE_CANARY) in qcom_smem_get_private()
526 if (le16_to_cpu(e->item) == item) { in qcom_smem_get_private()
528 *size = le32_to_cpu(e->size) - in qcom_smem_get_private()
529 le16_to_cpu(e->padding_data); in qcom_smem_get_private()
543 if (e->canary != SMEM_PRIVATE_CANARY) in qcom_smem_get_private()
546 if (le16_to_cpu(e->item) == item) { in qcom_smem_get_private()
548 *size = le32_to_cpu(e->size) - in qcom_smem_get_private()
549 le16_to_cpu(e->padding_data); in qcom_smem_get_private()
557 return ERR_PTR(-ENOENT); in qcom_smem_get_private()
560 dev_err(smem->dev, "Found invalid canary in hosts %hu:%hu partition\n", in qcom_smem_get_private()
561 le16_to_cpu(phdr->host0), le16_to_cpu(phdr->host1)); in qcom_smem_get_private()
563 return ERR_PTR(-EINVAL); in qcom_smem_get_private()
567 * qcom_smem_get() - resolve ptr of size of a smem item
568 * @host: the remote processor, or -1
581 void *ptr = ERR_PTR(-EPROBE_DEFER); in qcom_smem_get()
586 if (WARN_ON(item >= __smem->item_count)) in qcom_smem_get()
587 return ERR_PTR(-EINVAL); in qcom_smem_get()
589 ret = hwspin_lock_timeout_irqsave(__smem->hwlock, in qcom_smem_get()
595 if (host < SMEM_HOST_COUNT && __smem->partitions[host]) { in qcom_smem_get()
596 phdr = __smem->partitions[host]; in qcom_smem_get()
597 cacheln = __smem->cacheline[host]; in qcom_smem_get()
599 } else if (__smem->global_partition) { in qcom_smem_get()
600 phdr = __smem->global_partition; in qcom_smem_get()
601 cacheln = __smem->global_cacheline; in qcom_smem_get()
607 hwspin_unlock_irqrestore(__smem->hwlock, &flags); in qcom_smem_get()
615 * qcom_smem_get_free_space() - retrieve amount of free space in a partition
616 * @host: the remote processor identifying a partition, or -1
628 return -EPROBE_DEFER; in qcom_smem_get_free_space()
630 if (host < SMEM_HOST_COUNT && __smem->partitions[host]) { in qcom_smem_get_free_space()
631 phdr = __smem->partitions[host]; in qcom_smem_get_free_space()
632 ret = le32_to_cpu(phdr->offset_free_cached) - in qcom_smem_get_free_space()
633 le32_to_cpu(phdr->offset_free_uncached); in qcom_smem_get_free_space()
634 } else if (__smem->global_partition) { in qcom_smem_get_free_space()
635 phdr = __smem->global_partition; in qcom_smem_get_free_space()
636 ret = le32_to_cpu(phdr->offset_free_cached) - in qcom_smem_get_free_space()
637 le32_to_cpu(phdr->offset_free_uncached); in qcom_smem_get_free_space()
639 header = __smem->regions[0].virt_base; in qcom_smem_get_free_space()
640 ret = le32_to_cpu(header->available); in qcom_smem_get_free_space()
648 * qcom_smem_virt_to_phys() - return the physical address associated
658 for (i = 0; i < __smem->num_regions; i++) { in qcom_smem_virt_to_phys()
659 struct smem_region *region = &__smem->regions[i]; in qcom_smem_virt_to_phys()
661 if (p < region->virt_base) in qcom_smem_virt_to_phys()
663 if (p < region->virt_base + region->size) { in qcom_smem_virt_to_phys()
664 u64 offset = p - region->virt_base; in qcom_smem_virt_to_phys()
666 return (phys_addr_t)region->aux_base + offset; in qcom_smem_virt_to_phys()
679 header = smem->regions[0].virt_base; in qcom_smem_get_sbl_version()
680 versions = header->version; in qcom_smem_get_sbl_version()
690 ptable = smem->regions[0].virt_base + smem->regions[0].size - SZ_4K; in qcom_smem_get_ptable()
691 if (memcmp(ptable->magic, SMEM_PTABLE_MAGIC, sizeof(ptable->magic))) in qcom_smem_get_ptable()
692 return ERR_PTR(-ENOENT); in qcom_smem_get_ptable()
694 version = le32_to_cpu(ptable->version); in qcom_smem_get_ptable()
696 dev_err(smem->dev, in qcom_smem_get_ptable()
698 return ERR_PTR(-EINVAL); in qcom_smem_get_ptable()
712 info = (struct smem_info *)&ptable->entry[ptable->num_entries]; in qcom_smem_get_item_count()
713 if (memcmp(info->magic, SMEM_INFO_MAGIC, sizeof(info->magic))) in qcom_smem_get_item_count()
716 return le16_to_cpu(info->num_items); in qcom_smem_get_item_count()
731 header = smem->regions[0].virt_base + le32_to_cpu(entry->offset); in qcom_smem_partition_header()
733 if (memcmp(header->magic, SMEM_PART_MAGIC, sizeof(header->magic))) { in qcom_smem_partition_header()
734 dev_err(smem->dev, "bad partition magic %02x %02x %02x %02x\n", in qcom_smem_partition_header()
735 header->magic[0], header->magic[1], in qcom_smem_partition_header()
736 header->magic[2], header->magic[3]); in qcom_smem_partition_header()
740 if (host0 != le16_to_cpu(header->host0)) { in qcom_smem_partition_header()
741 dev_err(smem->dev, "bad host0 (%hu != %hu)\n", in qcom_smem_partition_header()
742 host0, le16_to_cpu(header->host0)); in qcom_smem_partition_header()
745 if (host1 != le16_to_cpu(header->host1)) { in qcom_smem_partition_header()
746 dev_err(smem->dev, "bad host1 (%hu != %hu)\n", in qcom_smem_partition_header()
747 host1, le16_to_cpu(header->host1)); in qcom_smem_partition_header()
751 size = le32_to_cpu(header->size); in qcom_smem_partition_header()
752 if (size != le32_to_cpu(entry->size)) { in qcom_smem_partition_header()
753 dev_err(smem->dev, "bad partition size (%u != %u)\n", in qcom_smem_partition_header()
754 size, le32_to_cpu(entry->size)); in qcom_smem_partition_header()
758 if (le32_to_cpu(header->offset_free_uncached) > size) { in qcom_smem_partition_header()
759 dev_err(smem->dev, "bad partition free uncached (%u > %u)\n", in qcom_smem_partition_header()
760 le32_to_cpu(header->offset_free_uncached), size); in qcom_smem_partition_header()
775 if (smem->global_partition) { in qcom_smem_set_global_partition()
776 dev_err(smem->dev, "Already found the global partition\n"); in qcom_smem_set_global_partition()
777 return -EINVAL; in qcom_smem_set_global_partition()
784 for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) { in qcom_smem_set_global_partition()
785 entry = &ptable->entry[i]; in qcom_smem_set_global_partition()
786 if (!le32_to_cpu(entry->offset)) in qcom_smem_set_global_partition()
788 if (!le32_to_cpu(entry->size)) in qcom_smem_set_global_partition()
791 if (le16_to_cpu(entry->host0) != SMEM_GLOBAL_HOST) in qcom_smem_set_global_partition()
794 if (le16_to_cpu(entry->host1) == SMEM_GLOBAL_HOST) { in qcom_smem_set_global_partition()
801 dev_err(smem->dev, "Missing entry for global partition\n"); in qcom_smem_set_global_partition()
802 return -EINVAL; in qcom_smem_set_global_partition()
808 return -EINVAL; in qcom_smem_set_global_partition()
810 smem->global_partition = header; in qcom_smem_set_global_partition()
811 smem->global_cacheline = le32_to_cpu(entry->cacheline); in qcom_smem_set_global_partition()
830 for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) { in qcom_smem_enumerate_partitions()
831 entry = &ptable->entry[i]; in qcom_smem_enumerate_partitions()
832 if (!le32_to_cpu(entry->offset)) in qcom_smem_enumerate_partitions()
834 if (!le32_to_cpu(entry->size)) in qcom_smem_enumerate_partitions()
837 host0 = le16_to_cpu(entry->host0); in qcom_smem_enumerate_partitions()
838 host1 = le16_to_cpu(entry->host1); in qcom_smem_enumerate_partitions()
847 dev_err(smem->dev, "bad host %hu\n", remote_host); in qcom_smem_enumerate_partitions()
848 return -EINVAL; in qcom_smem_enumerate_partitions()
851 if (smem->partitions[remote_host]) { in qcom_smem_enumerate_partitions()
852 dev_err(smem->dev, "duplicate host %hu\n", remote_host); in qcom_smem_enumerate_partitions()
853 return -EINVAL; in qcom_smem_enumerate_partitions()
858 return -EINVAL; in qcom_smem_enumerate_partitions()
860 smem->partitions[remote_host] = header; in qcom_smem_enumerate_partitions()
861 smem->cacheline[remote_host] = le32_to_cpu(entry->cacheline); in qcom_smem_enumerate_partitions()
875 np = of_parse_phandle(dev->of_node, name, 0); in qcom_smem_map_memory()
878 return -EINVAL; in qcom_smem_map_memory()
887 smem->regions[i].virt_base = devm_ioremap_wc(dev, r.start, size); in qcom_smem_map_memory()
888 if (!smem->regions[i].virt_base) in qcom_smem_map_memory()
889 return -ENOMEM; in qcom_smem_map_memory()
890 smem->regions[i].aux_base = (u32)r.start; in qcom_smem_map_memory()
891 smem->regions[i].size = size; in qcom_smem_map_memory()
907 if (of_find_property(pdev->dev.of_node, "qcom,rpm-msg-ram", NULL)) in qcom_smem_probe()
911 smem = devm_kzalloc(&pdev->dev, sizeof(*smem) + array_size, GFP_KERNEL); in qcom_smem_probe()
913 return -ENOMEM; in qcom_smem_probe()
915 smem->dev = &pdev->dev; in qcom_smem_probe()
916 smem->num_regions = num_regions; in qcom_smem_probe()
918 ret = qcom_smem_map_memory(smem, &pdev->dev, "memory-region", 0); in qcom_smem_probe()
922 if (num_regions > 1 && (ret = qcom_smem_map_memory(smem, &pdev->dev, in qcom_smem_probe()
923 "qcom,rpm-msg-ram", 1))) in qcom_smem_probe()
926 header = smem->regions[0].virt_base; in qcom_smem_probe()
927 if (le32_to_cpu(header->initialized) != 1 || in qcom_smem_probe()
928 le32_to_cpu(header->reserved)) { in qcom_smem_probe()
929 dev_err(&pdev->dev, "SMEM is not initialized by SBL\n"); in qcom_smem_probe()
930 return -EINVAL; in qcom_smem_probe()
939 smem->item_count = qcom_smem_get_item_count(smem); in qcom_smem_probe()
942 smem->item_count = SMEM_ITEM_COUNT; in qcom_smem_probe()
945 dev_err(&pdev->dev, "Unsupported SMEM version 0x%x\n", version); in qcom_smem_probe()
946 return -EINVAL; in qcom_smem_probe()
951 if (ret < 0 && ret != -ENOENT) in qcom_smem_probe()
954 hwlock_id = of_hwspin_lock_get_id(pdev->dev.of_node, 0); in qcom_smem_probe()
956 if (hwlock_id != -EPROBE_DEFER) in qcom_smem_probe()
957 dev_err(&pdev->dev, "failed to retrieve hwlock\n"); in qcom_smem_probe()
961 smem->hwlock = hwspin_lock_request_specific(hwlock_id); in qcom_smem_probe()
962 if (!smem->hwlock) in qcom_smem_probe()
963 return -ENXIO; in qcom_smem_probe()
967 smem->socinfo = platform_device_register_data(&pdev->dev, "qcom-socinfo", in qcom_smem_probe()
970 if (IS_ERR(smem->socinfo)) in qcom_smem_probe()
971 dev_dbg(&pdev->dev, "failed to register socinfo device\n"); in qcom_smem_probe()
978 platform_device_unregister(__smem->socinfo); in qcom_smem_remove()
980 hwspin_lock_free(__smem->hwlock); in qcom_smem_remove()
996 .name = "qcom-smem",