-
Notifications
You must be signed in to change notification settings - Fork 943
remoteproc: adi: replace MDMA memcpy with memcpy_toio for LDR load #3268
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: adsp-6.12.0-y
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||
| /* | ||
| * Analog Device SHARC Image Loader for SC5XX processors | ||
|
|
@@ -11,13 +11,12 @@ | |
| */ | ||
|
|
||
| #include <linux/clk.h> | ||
| #include <linux/completion.h> | ||
| #include <linux/dmaengine.h> | ||
| #include <linux/firmware.h> | ||
| #include <linux/elf.h> | ||
| #include <linux/virtio_ids.h> | ||
| #include <linux/virtio_ring.h> | ||
| #include <linux/interrupt.h> | ||
| #include <linux/io.h> | ||
| #include <linux/module.h> | ||
| #include <linux/of.h> | ||
| #include <linux/of_address.h> | ||
|
|
@@ -26,7 +25,6 @@ | |
| #include <linux/platform_device.h> | ||
| #include <linux/remoteproc.h> | ||
| #include <linux/delay.h> | ||
| #include <linux/dma-mapping.h> | ||
|
|
||
| #include <linux/soc/adi/icc.h> | ||
| #include <linux/soc/adi/rcu.h> | ||
|
|
@@ -35,22 +33,17 @@ | |
| /* location of bootrom that loops idle */ | ||
| #define SHARC_IDLE_ADDR (0x00090004) | ||
|
|
||
| #define SPU_MDMA0_SRC_ID 88 | ||
| #define SPU_MDMA0_DST_ID 89 | ||
|
|
||
| #define CORE_INIT_TIMEOUT_MS (2000) | ||
| #define CORE_INIT_TIMEOUT msecs_to_jiffies(CORE_INIT_TIMEOUT_MS) | ||
|
|
||
| #define MEMORY_COUNT 2 | ||
|
|
||
| #define ADI_FW_LDR 0 | ||
| #define ADI_FW_ELF 1 | ||
|
|
||
| #define NUM_TABLE_ENTRIES 1 | ||
| /* Resource table for the given remote */ | ||
|
|
||
| struct bcode_flag_t { | ||
| uint32_t bCode:4, /* 0-3 */ | ||
| u32 bCode:4, /* 0-3 */ | ||
| bFlag_save:1, /* 4 */ | ||
| bFlag_aux:1, /* 5 */ | ||
| bReserved:1, /* 6 */ | ||
|
|
@@ -87,6 +80,7 @@ | |
| struct sharc_resource_table rsc_table; | ||
| } __packed; | ||
|
|
||
|
|
||
|
Check warning on line 83 in drivers/remoteproc/adi_remoteproc.c
|
||
| #define VRING_ALIGN 0x1000 | ||
| #define VRING_DEFAULT_SIZE 0x800 | ||
|
|
||
|
|
@@ -147,9 +141,6 @@ | |
| int core_irq; | ||
| int icc_irq; | ||
| int icc_irq_flags; | ||
| void *mem_virt; | ||
| dma_addr_t mem_handle; | ||
| size_t fw_size; | ||
| unsigned long ldr_load_addr; | ||
| int firmware_format; | ||
| void __iomem *L1_shared_base; | ||
|
|
@@ -189,7 +180,7 @@ | |
|
|
||
| if (rproc_data->adi_rsc_table != NULL) { | ||
| rproc_data->rpmsg_state = ADI_RP_RPMSG_WAITING; | ||
| ret = devm_request_threaded_irq(rproc_data->dev, | ||
|
Check warning on line 183 in drivers/remoteproc/adi_remoteproc.c
|
||
| rproc_data->icc_irq, NULL, | ||
| sharc_virtio_irq_threaded_handler, | ||
| rproc_data->icc_irq_flags, | ||
|
|
@@ -229,114 +220,52 @@ | |
| return hdr->bcode_flag.bFlag_ignore || (hdr->byte_count == 0); | ||
| } | ||
|
|
||
| static void load_callback(void *p) | ||
| { | ||
| struct completion *cmp = p; | ||
|
|
||
| complete(cmp); | ||
| } | ||
|
|
||
| /* @todo this needs to return status */ | ||
| /* @todo the error paths here leak tremendously, this needs further cleanup */ | ||
| static void ldr_load(struct adi_rproc_data *rproc_data) | ||
| static void ldr_load(struct adi_rproc_data *rproc_data, const u8 *fw_data) | ||
| { | ||
| struct ldr_hdr *block_hdr = NULL; | ||
| struct ldr_hdr *next_hdr = NULL; | ||
| u8 *virbuf = (u8 *) rproc_data->mem_virt; | ||
| dma_addr_t phybuf = rproc_data->mem_handle; | ||
| struct ldr_hdr *block_hdr; | ||
| const u8 *virbuf = fw_data; | ||
| void __iomem *target; | ||
| u32 addr; | ||
| int offset; | ||
| // part of verify buffer code | ||
| // int i; | ||
| // uint32_t verfied = 0; | ||
| // uint8_t *pCompareBuffer; | ||
| // uint8_t *pVerifyBuffer; | ||
| struct dma_chan *chan = dma_find_channel(DMA_MEMCPY); | ||
| struct dma_async_tx_descriptor *tx; | ||
| struct completion cmp; | ||
|
|
||
| if (!chan) { | ||
| dev_err(rproc_data->dev, "Could not find dma memcpy channel\n"); | ||
| return; | ||
| } | ||
|
|
||
| init_completion(&cmp); | ||
|
|
||
| do { | ||
| /* read the header */ | ||
| block_hdr = (struct ldr_hdr *) virbuf; | ||
| offset = sizeof(struct ldr_hdr) + (block_hdr->bcode_flag.bFlag_fill ? | ||
| 0 : block_hdr->byte_count); | ||
| next_hdr = (struct ldr_hdr *) (virbuf + offset); | ||
| tx = NULL; | ||
| addr = block_hdr->target_addr; | ||
|
|
||
| /* Overwrite the ldr_load_addr */ | ||
| if (block_hdr->bcode_flag.bFlag_first) | ||
| rproc_data->ldr_load_addr = (unsigned long)block_hdr->target_addr; | ||
| rproc_data->ldr_load_addr = (unsigned long)addr; | ||
|
|
||
| if (!is_empty(block_hdr)) { | ||
| if (block_hdr->bcode_flag.bFlag_fill) { | ||
| tx = dmaengine_prep_dma_memset(chan, | ||
| block_hdr->target_addr, | ||
| block_hdr->argument, | ||
| block_hdr->byte_count, 0); | ||
| } else { | ||
| tx = dmaengine_prep_dma_memcpy(chan, | ||
| block_hdr->target_addr, | ||
| phybuf + sizeof(struct ldr_hdr), | ||
| block_hdr->byte_count, 0); | ||
|
|
||
| // if (rproc_data->verify) { | ||
| // @todo implement verification | ||
| // pCompareBuffer = virbuf + sizeof(struct ldr_hdr); | ||
| // pVerifyBuffer = virbuf + rproc_data->fw_size; | ||
| // | ||
| // dma_memcpy(phybuf + rproc_data->fw_size, | ||
| // block_hdr->target_addr, | ||
| // block_hdr->byte_count); | ||
| // | ||
| // /* check the data */ | ||
| // for (i = 0; i < block_hdr->byte_count; i++) { | ||
| // if (pCompareBuffer[i] != pVerifyBuffer[i]) { | ||
| // dev_err(rproc_data->dev, | ||
| // "dirty data, compare[%d]:0x%x," | ||
| // "verify[%d]:0x%x\n", | ||
| // i, pCompareBuffer[i], i, | ||
| // pVerifyBuffer[i]); | ||
| // verfied++; | ||
| // break; | ||
| // } | ||
| // } | ||
| // } | ||
| } | ||
|
|
||
| if (!tx) { | ||
| dev_err(rproc_data->dev, "Failed to allocate dma transaction\n"); | ||
| if (addr >= rproc_data->l1_da_range[0] && | ||
| addr < rproc_data->l1_da_range[1]) | ||
| target = rproc_data->L1_shared_base + addr; | ||
| else if (addr >= rproc_data->l2_da_range[0] && | ||
| addr < rproc_data->l2_da_range[1]) | ||
| target = rproc_data->L2_shared_base + | ||
| (addr - rproc_data->l2_da_range[0]); | ||
| else { | ||
|
Check warning on line 249 in drivers/remoteproc/adi_remoteproc.c
|
||
| dev_err(rproc_data->dev, | ||
| "Target 0x%08x outside mapped ranges\n", addr); | ||
| return; | ||
| } | ||
|
|
||
| if (is_final(block_hdr) || (is_final(next_hdr) && is_empty(next_hdr))) { | ||
| tx->callback = load_callback; | ||
| tx->callback_param = &cmp; | ||
| } | ||
| dmaengine_submit(tx); | ||
| dma_async_issue_pending(chan); | ||
| if (block_hdr->bcode_flag.bFlag_fill) | ||
| memset_io(target, block_hdr->argument, | ||
| block_hdr->byte_count); | ||
| else | ||
| memcpy_toio(target, | ||
| virbuf + sizeof(struct ldr_hdr), | ||
| block_hdr->byte_count); | ||
| } | ||
|
|
||
| if (is_final(block_hdr)) { | ||
| wait_for_completion(&cmp); | ||
| if (is_final(block_hdr)) | ||
| break; | ||
| } | ||
|
|
||
| virbuf += offset; | ||
| phybuf += offset; | ||
| } while (1); | ||
|
|
||
| // if (rproc_data->verify) { | ||
| // if (verfied == 0) | ||
| // dev_err(rproc_data->dev, "success to verify all the data\n"); | ||
| // else | ||
| // dev_err(rproc_data->dev, "fail to verify all the data %d\n", verfied); | ||
| // } | ||
| } | ||
|
|
||
| static int adi_valid_firmware(struct rproc *rproc, const struct firmware *fw) | ||
|
|
@@ -358,40 +287,10 @@ | |
| return -EINVAL; | ||
| } | ||
|
|
||
| void set_spu_securep_msec(u16 n, bool msec); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In comment section |
||
| static void enable_spu(void) | ||
| { | ||
| set_spu_securep_msec(SPU_MDMA0_SRC_ID, true); | ||
| set_spu_securep_msec(SPU_MDMA0_DST_ID, true); | ||
| } | ||
|
|
||
| static void disable_spu(void) | ||
| { | ||
| set_spu_securep_msec(SPU_MDMA0_SRC_ID, false); | ||
| set_spu_securep_msec(SPU_MDMA0_DST_ID, false); | ||
| } | ||
|
|
||
| static int adi_ldr_load(struct adi_rproc_data *rproc_data, | ||
| const struct firmware *fw) | ||
| { | ||
| rproc_data->fw_size = fw->size; | ||
| if (!rproc_data->mem_virt) { | ||
| rproc_data->mem_virt = dma_alloc_coherent(rproc_data->dev, | ||
| fw->size * MEMORY_COUNT, | ||
| &rproc_data->mem_handle, | ||
| GFP_KERNEL); | ||
| if (rproc_data->mem_virt == NULL) { | ||
| dev_err(rproc_data->dev, "Unable to allocate memory\n"); | ||
| return -ENOMEM; | ||
| } | ||
| } | ||
|
|
||
| memcpy((char *)rproc_data->mem_virt, fw->data, fw->size); | ||
|
|
||
| enable_spu(); | ||
| ldr_load(rproc_data); | ||
| disable_spu(); | ||
|
|
||
| ldr_load(rproc_data, fw->data); | ||
| return 0; | ||
| } | ||
|
|
||
|
|
@@ -468,14 +367,6 @@ | |
| if (ret) | ||
| return ret; | ||
|
|
||
| if (rproc_data->mem_virt) { | ||
| memset(rproc_data->mem_virt, 0, rproc_data->fw_size * MEMORY_COUNT); | ||
| dma_free_coherent(rproc_data->dev, rproc_data->fw_size * MEMORY_COUNT, | ||
| rproc_data->mem_virt, rproc_data->mem_handle); | ||
| rproc_data->mem_virt = NULL; | ||
| rproc_data->fw_size = 0; | ||
| } | ||
|
|
||
| rproc_data->ldr_load_addr = SHARC_IDLE_ADDR; | ||
| rproc_data->loaded_rsc_table = NULL; | ||
| return ret; | ||
|
|
@@ -518,7 +409,7 @@ | |
| struct device *dev = rproc->dev.parent; | ||
| void *va; | ||
|
|
||
| va = ioremap_wc(mem->dma, mem->len); | ||
|
Check warning on line 412 in drivers/remoteproc/adi_remoteproc.c
|
||
| if (!va) { | ||
| dev_err(dev, "Unable to map memory carveout %pa+%zx\n", &mem->dma, mem->len); | ||
| return -ENOMEM; | ||
|
|
@@ -529,7 +420,7 @@ | |
|
|
||
| static int adi_rproc_unmap_carveout(struct rproc *rproc, struct rproc_mem_entry *mem) | ||
| { | ||
| iounmap(mem->va); | ||
|
Check warning on line 423 in drivers/remoteproc/adi_remoteproc.c
|
||
| return 0; | ||
| } | ||
|
|
||
|
|
@@ -786,9 +677,9 @@ | |
| return NULL; | ||
|
|
||
| if (da >= rproc_data->l1_da_range[0] && da < rproc_data->l1_da_range[1]) | ||
| ret = L1_shared_base + da; | ||
|
Check warning on line 680 in drivers/remoteproc/adi_remoteproc.c
|
||
| else if (da >= rproc_data->l2_da_range[0] && da < rproc_data->l2_da_range[1]) | ||
| ret = L2_shared_base + (da - rproc_data->l2_da_range[0]); | ||
|
Check warning on line 682 in drivers/remoteproc/adi_remoteproc.c
|
||
|
|
||
| return ret; | ||
| } | ||
|
|
@@ -894,7 +785,7 @@ | |
| goto free_adi_rcu; | ||
| } | ||
|
|
||
| rproc_data->adi_rsc_table = devm_ioremap_wc(dev, | ||
|
Check warning on line 788 in drivers/remoteproc/adi_remoteproc.c
|
||
| rmem->base, | ||
| rmem->size); | ||
| if (IS_ERR(rproc_data->adi_rsc_table)) { | ||
|
|
@@ -905,7 +796,7 @@ | |
|
|
||
| rproc_data->icc_irq = platform_get_irq(pdev, 0); | ||
| if (rproc_data->icc_irq <= 0) { | ||
| dev_err(dev, "No ICC IRQ specified\n"); | ||
|
Check warning on line 799 in drivers/remoteproc/adi_remoteproc.c
|
||
| ret = -ENOENT; | ||
| goto free_adi_rcu; | ||
| } | ||
|
|
@@ -971,8 +862,6 @@ | |
| rproc_data->tru = adi_tru; | ||
| rproc_data->rproc = rproc; | ||
| rproc_data->firmware_name = name; | ||
| rproc_data->mem_virt = NULL; | ||
| rproc_data->fw_size = 0; | ||
| rproc_data->ldr_load_addr = SHARC_IDLE_ADDR; | ||
| rproc_data->rpmsg_state = ADI_RP_RPMSG_TIMED_OUT; | ||
|
|
||
|
|
@@ -982,8 +871,6 @@ | |
| goto free_workqueue; | ||
| } | ||
|
|
||
| dmaengine_get(); | ||
|
|
||
| return 0; | ||
|
|
||
| free_workqueue: | ||
|
|
@@ -1005,7 +892,6 @@ | |
| { | ||
| struct adi_rproc_data *rproc_data = platform_get_drvdata(pdev); | ||
|
|
||
| dmaengine_put(); | ||
| put_adi_tru(rproc_data->tru); | ||
| put_adi_rcu(rproc_data->rcu); | ||
| rproc_del(rproc_data->rproc); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where this ranges comes from L2 only for vring's or L3. Firmware is loaded to L3