Skip to content

Commit 7e51a9e

Browse files
ajitkupandeybroonie
authored andcommitted
ASoC: SOF: amd: Add fw loader and renoir dsp ops to load firmware
Add acp-loader module with ops callback to load and run firmware on ACP DSP block on Renoir platform. Signed-off-by: Ajit Kumar Pandey <[email protected]> Reviewed-by: Bard Liao <[email protected]> Reviewed-by: Kai Vehmanen <[email protected]> Signed-off-by: Daniel Baluta <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 0e44572 commit 7e51a9e

File tree

5 files changed

+245
-1
lines changed

5 files changed

+245
-1
lines changed

sound/soc/sof/amd/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#
55
# Copyright(c) 2021 Advanced Micro Devices, Inc. All rights reserved.
66

7-
snd-sof-amd-acp-objs := acp.o
7+
snd-sof-amd-acp-objs := acp.o acp-loader.o
88
snd-sof-amd-renoir-objs := renoir.o
99

1010
obj-$(CONFIG_SND_SOC_SOF_AMD_COMMON) += snd-sof-amd-acp.o

sound/soc/sof/amd/acp-dsp-offset.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
#define ACP_DMA_CH_GROUP 0xEC
2525
#define ACP_DMA_CH_RST_STS 0xF0
2626

27+
/* Registers from ACP_DSP_0 block */
28+
#define ACP_DSP0_RUNSTALL 0x414
29+
2730
/* Registers from ACP_AXI2AXIATU block */
2831
#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1 0xC00
2932
#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_1 0xC04

sound/soc/sof/amd/acp-loader.c

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2+
//
3+
// This file is provided under a dual BSD/GPLv2 license. When using or
4+
// redistributing this file, you may do so under either license.
5+
//
6+
// Copyright(c) 2021 Advanced Micro Devices, Inc.
7+
//
8+
// Authors: Ajit Kumar Pandey <[email protected]>
9+
10+
/*
11+
* Hardware interface for ACP DSP Firmware binaries loader
12+
*/
13+
14+
#include <linux/firmware.h>
15+
#include <linux/module.h>
16+
#include <linux/pci.h>
17+
18+
#include "../ops.h"
19+
#include "acp-dsp-offset.h"
20+
#include "acp.h"
21+
22+
#define FW_BIN 0
23+
#define FW_DATA_BIN 1
24+
25+
#define FW_BIN_PTE_OFFSET 0x00
26+
#define FW_DATA_BIN_PTE_OFFSET 0x08
27+
28+
#define ACP_DSP_RUN 0x00
29+
30+
int acp_dsp_block_read(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_type,
31+
u32 offset, void *dest, size_t size)
32+
{
33+
switch (blk_type) {
34+
case SOF_FW_BLK_TYPE_SRAM:
35+
offset = offset - ACP_SCRATCH_MEMORY_ADDRESS;
36+
memcpy_from_scratch(sdev, offset, dest, size);
37+
break;
38+
default:
39+
dev_err(sdev->dev, "bad blk type 0x%x\n", blk_type);
40+
return -EINVAL;
41+
}
42+
43+
return 0;
44+
}
45+
EXPORT_SYMBOL_NS(acp_dsp_block_read, SND_SOC_SOF_AMD_COMMON);
46+
47+
int acp_dsp_block_write(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_type,
48+
u32 offset, void *src, size_t size)
49+
{
50+
struct snd_sof_pdata *plat_data = sdev->pdata;
51+
struct pci_dev *pci = to_pci_dev(sdev->dev);
52+
struct acp_dev_data *adata;
53+
void *dest;
54+
u32 dma_size, page_count;
55+
unsigned int size_fw;
56+
57+
adata = sdev->pdata->hw_pdata;
58+
59+
switch (blk_type) {
60+
case SOF_FW_BLK_TYPE_IRAM:
61+
if (!adata->bin_buf) {
62+
size_fw = plat_data->fw->size;
63+
page_count = PAGE_ALIGN(size_fw) >> PAGE_SHIFT;
64+
dma_size = page_count * ACP_PAGE_SIZE;
65+
adata->bin_buf = dma_alloc_coherent(&pci->dev, dma_size,
66+
&adata->sha_dma_addr,
67+
GFP_ATOMIC);
68+
if (!adata->bin_buf)
69+
return -ENOMEM;
70+
}
71+
adata->fw_bin_size = size + offset;
72+
dest = adata->bin_buf + offset;
73+
break;
74+
case SOF_FW_BLK_TYPE_DRAM:
75+
if (!adata->data_buf) {
76+
adata->data_buf = dma_alloc_coherent(&pci->dev,
77+
ACP_DEFAULT_DRAM_LENGTH,
78+
&adata->dma_addr,
79+
GFP_ATOMIC);
80+
if (!adata->data_buf)
81+
return -ENOMEM;
82+
}
83+
dest = adata->data_buf + offset;
84+
adata->fw_data_bin_size = size + offset;
85+
break;
86+
case SOF_FW_BLK_TYPE_SRAM:
87+
offset = offset - ACP_SCRATCH_MEMORY_ADDRESS;
88+
memcpy_to_scratch(sdev, offset, src, size);
89+
return 0;
90+
default:
91+
dev_err(sdev->dev, "bad blk type 0x%x\n", blk_type);
92+
return -EINVAL;
93+
}
94+
95+
memcpy(dest, src, size);
96+
return 0;
97+
}
98+
EXPORT_SYMBOL_NS(acp_dsp_block_write, SND_SOC_SOF_AMD_COMMON);
99+
100+
int acp_get_bar_index(struct snd_sof_dev *sdev, u32 type)
101+
{
102+
return type;
103+
}
104+
EXPORT_SYMBOL_NS(acp_get_bar_index, SND_SOC_SOF_AMD_COMMON);
105+
106+
static void configure_pte_for_fw_loading(int type, int num_pages, struct acp_dev_data *adata)
107+
{
108+
struct snd_sof_dev *sdev;
109+
unsigned int low, high;
110+
dma_addr_t addr;
111+
u16 page_idx;
112+
u32 offset;
113+
114+
sdev = adata->dev;
115+
116+
switch (type) {
117+
case FW_BIN:
118+
offset = FW_BIN_PTE_OFFSET;
119+
addr = adata->sha_dma_addr;
120+
break;
121+
case FW_DATA_BIN:
122+
offset = adata->fw_bin_page_count * 8;
123+
addr = adata->dma_addr;
124+
break;
125+
default:
126+
dev_err(sdev->dev, "Invalid data type %x\n", type);
127+
return;
128+
}
129+
130+
for (page_idx = 0; page_idx < num_pages; page_idx++) {
131+
low = lower_32_bits(addr);
132+
high = upper_32_bits(addr);
133+
snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + offset, low);
134+
high |= BIT(31);
135+
snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + offset + 4, high);
136+
offset += 8;
137+
addr += PAGE_SIZE;
138+
}
139+
}
140+
141+
/* pre fw run operations */
142+
int acp_dsp_pre_fw_run(struct snd_sof_dev *sdev)
143+
{
144+
struct pci_dev *pci = to_pci_dev(sdev->dev);
145+
struct snd_sof_pdata *plat_data = sdev->pdata;
146+
struct acp_dev_data *adata;
147+
unsigned int src_addr, size_fw;
148+
u32 page_count, dma_size;
149+
int ret;
150+
151+
adata = sdev->pdata->hw_pdata;
152+
size_fw = adata->fw_bin_size;
153+
154+
page_count = PAGE_ALIGN(size_fw) >> PAGE_SHIFT;
155+
adata->fw_bin_page_count = page_count;
156+
157+
configure_pte_for_fw_loading(FW_BIN, page_count, adata);
158+
ret = configure_and_run_sha_dma(adata, adata->bin_buf, ACP_SYSTEM_MEMORY_WINDOW,
159+
ACP_IRAM_BASE_ADDRESS, size_fw);
160+
if (ret < 0) {
161+
dev_err(sdev->dev, "SHA DMA transfer failed status: %d\n", ret);
162+
return ret;
163+
}
164+
configure_pte_for_fw_loading(FW_DATA_BIN, ACP_DRAM_PAGE_COUNT, adata);
165+
166+
src_addr = ACP_SYSTEM_MEMORY_WINDOW + page_count * ACP_PAGE_SIZE;
167+
ret = configure_and_run_dma(adata, src_addr, ACP_DATA_RAM_BASE_ADDRESS,
168+
adata->fw_data_bin_size);
169+
if (ret < 0) {
170+
dev_err(sdev->dev, "acp dma configuration failed: %d\n", ret);
171+
return ret;
172+
}
173+
174+
ret = acp_dma_status(adata, 0);
175+
if (ret < 0)
176+
dev_err(sdev->dev, "acp dma transfer status: %d\n", ret);
177+
178+
/* Free memory once DMA is complete */
179+
dma_size = (PAGE_ALIGN(plat_data->fw->size) >> PAGE_SHIFT) * ACP_PAGE_SIZE;
180+
dma_free_coherent(&pci->dev, dma_size, adata->bin_buf, adata->sha_dma_addr);
181+
dma_free_coherent(&pci->dev, ACP_DEFAULT_DRAM_LENGTH, adata->data_buf, adata->dma_addr);
182+
adata->bin_buf = NULL;
183+
adata->data_buf = NULL;
184+
185+
return ret;
186+
}
187+
EXPORT_SYMBOL_NS(acp_dsp_pre_fw_run, SND_SOC_SOF_AMD_COMMON);
188+
189+
int acp_sof_dsp_run(struct snd_sof_dev *sdev)
190+
{
191+
int val;
192+
193+
snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_DSP0_RUNSTALL, ACP_DSP_RUN);
194+
val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_DSP0_RUNSTALL);
195+
dev_dbg(sdev->dev, "ACP_DSP0_RUNSTALL : 0x%0x\n", val);
196+
197+
return 0;
198+
}
199+
EXPORT_SYMBOL_NS(acp_sof_dsp_run, SND_SOC_SOF_AMD_COMMON);

sound/soc/sof/amd/acp.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#ifndef __SOF_AMD_ACP_H
1212
#define __SOF_AMD_ACP_H
1313

14+
#include "../sof-priv.h"
15+
1416
#define ACP_DSP_BAR 0
1517

1618
#define ACP_REG_POLL_INTERVAL 500
@@ -39,6 +41,13 @@
3941
#define ACP_MAX_DESC 128
4042
#define ACPBUS_REG_BASE_OFFSET ACP_DMA_CNTL_0
4143

44+
#define ACP_DEFAULT_DRAM_LENGTH 0x00080000
45+
#define ACP_SCRATCH_MEMORY_ADDRESS 0x02050000
46+
#define ACP_SYSTEM_MEMORY_WINDOW 0x4000000
47+
#define ACP_IRAM_BASE_ADDRESS 0x000000
48+
#define ACP_DATA_RAM_BASE_ADDRESS 0x01000000
49+
#define ACP_DRAM_PAGE_COUNT 128
50+
4251
struct acp_atu_grp_pte {
4352
u32 low;
4453
u32 high;
@@ -106,6 +115,13 @@ struct scratch_reg_conf {
106115
/* Common device data struct for ACP devices */
107116
struct acp_dev_data {
108117
struct snd_sof_dev *dev;
118+
unsigned int fw_bin_size;
119+
unsigned int fw_data_bin_size;
120+
u32 fw_bin_page_count;
121+
dma_addr_t sha_dma_addr;
122+
u8 *bin_buf;
123+
dma_addr_t dma_addr;
124+
u8 *data_buf;
109125
struct dma_descriptor dscr_info[ACP_MAX_DESC];
110126
};
111127

@@ -123,5 +139,16 @@ int configure_and_run_sha_dma(struct acp_dev_data *adata, void *image_addr,
123139
int amd_sof_acp_probe(struct snd_sof_dev *sdev);
124140
int amd_sof_acp_remove(struct snd_sof_dev *sdev);
125141

142+
/* DSP Loader callbacks */
143+
int acp_sof_dsp_run(struct snd_sof_dev *sdev);
144+
int acp_dsp_pre_fw_run(struct snd_sof_dev *sdev);
145+
int acp_get_bar_index(struct snd_sof_dev *sdev, u32 type);
146+
147+
/* Block IO callbacks */
148+
int acp_dsp_block_write(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_type,
149+
u32 offset, void *src, size_t size);
150+
int acp_dsp_block_read(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_type,
151+
u32 offset, void *dest, size_t size);
152+
126153
extern const struct snd_sof_dsp_ops sof_renoir_ops;
127154
#endif

sound/soc/sof/amd/renoir.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,21 @@ const struct snd_sof_dsp_ops sof_renoir_ops = {
2626
/* Register IO */
2727
.write = sof_io_write,
2828
.read = sof_io_read,
29+
30+
/* Block IO */
31+
.block_read = acp_dsp_block_read,
32+
.block_write = acp_dsp_block_write,
33+
34+
/* Module loading */
35+
.load_module = snd_sof_parse_module_memcpy,
36+
37+
/*Firmware loading */
38+
.load_firmware = snd_sof_load_firmware_memcpy,
39+
.pre_fw_run = acp_dsp_pre_fw_run,
40+
.get_bar_index = acp_get_bar_index,
41+
42+
/* DSP core boot */
43+
.run = acp_sof_dsp_run,
2944
};
3045
EXPORT_SYMBOL(sof_renoir_ops);
3146

0 commit comments

Comments
 (0)