Skip to content

Commit 5b28aa3

Browse files
committed
dmaengine i.MX SDMA: Allow to run without firmware
The SDMA firmware consists of a ROM part and a RAM part. The ROM part is always present in the SDMA engine and is sufficient for many cases. This patch allows to pass in platform data containing the script addresses in ROM, so loading a firmware is optional now. Signed-off-by: Sascha Hauer <[email protected]> Acked-by: Dan Williams <[email protected]>
1 parent 9ab4650 commit 5b28aa3

File tree

2 files changed

+124
-96
lines changed

2 files changed

+124
-96
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,63 @@
11
#ifndef __MACH_MXC_SDMA_H__
22
#define __MACH_MXC_SDMA_H__
33

4+
/**
5+
* struct sdma_script_start_addrs - SDMA script start pointers
6+
*
7+
* start addresses of the different functions in the physical
8+
* address space of the SDMA engine.
9+
*/
10+
struct sdma_script_start_addrs {
11+
s32 ap_2_ap_addr;
12+
s32 ap_2_bp_addr;
13+
s32 ap_2_ap_fixed_addr;
14+
s32 bp_2_ap_addr;
15+
s32 loopback_on_dsp_side_addr;
16+
s32 mcu_interrupt_only_addr;
17+
s32 firi_2_per_addr;
18+
s32 firi_2_mcu_addr;
19+
s32 per_2_firi_addr;
20+
s32 mcu_2_firi_addr;
21+
s32 uart_2_per_addr;
22+
s32 uart_2_mcu_addr;
23+
s32 per_2_app_addr;
24+
s32 mcu_2_app_addr;
25+
s32 per_2_per_addr;
26+
s32 uartsh_2_per_addr;
27+
s32 uartsh_2_mcu_addr;
28+
s32 per_2_shp_addr;
29+
s32 mcu_2_shp_addr;
30+
s32 ata_2_mcu_addr;
31+
s32 mcu_2_ata_addr;
32+
s32 app_2_per_addr;
33+
s32 app_2_mcu_addr;
34+
s32 shp_2_per_addr;
35+
s32 shp_2_mcu_addr;
36+
s32 mshc_2_mcu_addr;
37+
s32 mcu_2_mshc_addr;
38+
s32 spdif_2_mcu_addr;
39+
s32 mcu_2_spdif_addr;
40+
s32 asrc_2_mcu_addr;
41+
s32 ext_mem_2_ipu_addr;
42+
s32 descrambler_addr;
43+
s32 dptc_dvfs_addr;
44+
s32 utra_addr;
45+
s32 ram_code_start_addr;
46+
};
47+
448
/**
549
* struct sdma_platform_data - platform specific data for SDMA engine
650
*
751
* @sdma_version The version of this SDMA engine
852
* @cpu_name used to generate the firmware name
953
* @to_version CPU Tape out version
54+
* @script_addrs SDMA scripts addresses in SDMA ROM
1055
*/
1156
struct sdma_platform_data {
1257
int sdma_version;
1358
char *cpu_name;
1459
int to_version;
60+
struct sdma_script_start_addrs *script_addrs;
1561
};
1662

1763
#endif /* __MACH_MXC_SDMA_H__ */

drivers/dma/imx-sdma.c

Lines changed: 78 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -273,50 +273,6 @@ struct sdma_channel {
273273
#define MXC_SDMA_MIN_PRIORITY 1
274274
#define MXC_SDMA_MAX_PRIORITY 7
275275

276-
/**
277-
* struct sdma_script_start_addrs - SDMA script start pointers
278-
*
279-
* start addresses of the different functions in the physical
280-
* address space of the SDMA engine.
281-
*/
282-
struct sdma_script_start_addrs {
283-
u32 ap_2_ap_addr;
284-
u32 ap_2_bp_addr;
285-
u32 ap_2_ap_fixed_addr;
286-
u32 bp_2_ap_addr;
287-
u32 loopback_on_dsp_side_addr;
288-
u32 mcu_interrupt_only_addr;
289-
u32 firi_2_per_addr;
290-
u32 firi_2_mcu_addr;
291-
u32 per_2_firi_addr;
292-
u32 mcu_2_firi_addr;
293-
u32 uart_2_per_addr;
294-
u32 uart_2_mcu_addr;
295-
u32 per_2_app_addr;
296-
u32 mcu_2_app_addr;
297-
u32 per_2_per_addr;
298-
u32 uartsh_2_per_addr;
299-
u32 uartsh_2_mcu_addr;
300-
u32 per_2_shp_addr;
301-
u32 mcu_2_shp_addr;
302-
u32 ata_2_mcu_addr;
303-
u32 mcu_2_ata_addr;
304-
u32 app_2_per_addr;
305-
u32 app_2_mcu_addr;
306-
u32 shp_2_per_addr;
307-
u32 shp_2_mcu_addr;
308-
u32 mshc_2_mcu_addr;
309-
u32 mcu_2_mshc_addr;
310-
u32 spdif_2_mcu_addr;
311-
u32 mcu_2_spdif_addr;
312-
u32 asrc_2_mcu_addr;
313-
u32 ext_mem_2_ipu_addr;
314-
u32 descrambler_addr;
315-
u32 dptc_dvfs_addr;
316-
u32 utra_addr;
317-
u32 ram_code_start_addr;
318-
};
319-
320276
#define SDMA_FIRMWARE_MAGIC 0x414d4453
321277

322278
/**
@@ -1127,8 +1083,74 @@ static void sdma_issue_pending(struct dma_chan *chan)
11271083
*/
11281084
}
11291085

1130-
static int __init sdma_init(struct sdma_engine *sdma,
1131-
void *ram_code, int ram_code_size)
1086+
#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1 34
1087+
1088+
static void sdma_add_scripts(struct sdma_engine *sdma,
1089+
const struct sdma_script_start_addrs *addr)
1090+
{
1091+
s32 *addr_arr = (u32 *)addr;
1092+
s32 *saddr_arr = (u32 *)sdma->script_addrs;
1093+
int i;
1094+
1095+
for (i = 0; i < SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; i++)
1096+
if (addr_arr[i] > 0)
1097+
saddr_arr[i] = addr_arr[i];
1098+
}
1099+
1100+
static int __init sdma_get_firmware(struct sdma_engine *sdma,
1101+
const char *cpu_name, int to_version)
1102+
{
1103+
const struct firmware *fw;
1104+
char *fwname;
1105+
const struct sdma_firmware_header *header;
1106+
int ret;
1107+
const struct sdma_script_start_addrs *addr;
1108+
unsigned short *ram_code;
1109+
1110+
fwname = kasprintf(GFP_KERNEL, "sdma-%s-to%d.bin", cpu_name, to_version);
1111+
if (!fwname)
1112+
return -ENOMEM;
1113+
1114+
ret = request_firmware(&fw, fwname, sdma->dev);
1115+
if (ret) {
1116+
kfree(fwname);
1117+
return ret;
1118+
}
1119+
kfree(fwname);
1120+
1121+
if (fw->size < sizeof(*header))
1122+
goto err_firmware;
1123+
1124+
header = (struct sdma_firmware_header *)fw->data;
1125+
1126+
if (header->magic != SDMA_FIRMWARE_MAGIC)
1127+
goto err_firmware;
1128+
if (header->ram_code_start + header->ram_code_size > fw->size)
1129+
goto err_firmware;
1130+
1131+
addr = (void *)header + header->script_addrs_start;
1132+
ram_code = (void *)header + header->ram_code_start;
1133+
1134+
clk_enable(sdma->clk);
1135+
/* download the RAM image for SDMA */
1136+
sdma_load_script(sdma, ram_code,
1137+
header->ram_code_size,
1138+
sdma->script_addrs->ram_code_start_addr);
1139+
clk_disable(sdma->clk);
1140+
1141+
sdma_add_scripts(sdma, addr);
1142+
1143+
dev_info(sdma->dev, "loaded firmware %d.%d\n",
1144+
header->version_major,
1145+
header->version_minor);
1146+
1147+
err_firmware:
1148+
release_firmware(fw);
1149+
1150+
return ret;
1151+
}
1152+
1153+
static int __init sdma_init(struct sdma_engine *sdma)
11321154
{
11331155
int i, ret;
11341156
dma_addr_t ccb_phys;
@@ -1192,11 +1214,6 @@ static int __init sdma_init(struct sdma_engine *sdma,
11921214

11931215
__raw_writel(ccb_phys, sdma->regs + SDMA_H_C0PTR);
11941216

1195-
/* download the RAM image for SDMA */
1196-
sdma_load_script(sdma, ram_code,
1197-
ram_code_size,
1198-
sdma->script_addrs->ram_code_start_addr);
1199-
12001217
/* Set bits of CONFIG register with given context switching mode */
12011218
__raw_writel(SDMA_H_CONFIG_CSM, sdma->regs + SDMA_H_CONFIG);
12021219

@@ -1216,14 +1233,9 @@ static int __init sdma_init(struct sdma_engine *sdma,
12161233
static int __init sdma_probe(struct platform_device *pdev)
12171234
{
12181235
int ret;
1219-
const struct firmware *fw;
1220-
const struct sdma_firmware_header *header;
1221-
const struct sdma_script_start_addrs *addr;
12221236
int irq;
1223-
unsigned short *ram_code;
12241237
struct resource *iores;
12251238
struct sdma_platform_data *pdata = pdev->dev.platform_data;
1226-
char *fwname;
12271239
int i;
12281240
dma_cap_mask_t mask;
12291241
struct sdma_engine *sdma;
@@ -1262,38 +1274,9 @@ static int __init sdma_probe(struct platform_device *pdev)
12621274
if (ret)
12631275
goto err_request_irq;
12641276

1265-
fwname = kasprintf(GFP_KERNEL, "sdma-%s-to%d.bin",
1266-
pdata->cpu_name, pdata->to_version);
1267-
if (!fwname) {
1268-
ret = -ENOMEM;
1269-
goto err_cputype;
1270-
}
1271-
1272-
ret = request_firmware(&fw, fwname, &pdev->dev);
1273-
if (ret) {
1274-
dev_err(&pdev->dev, "request firmware \"%s\" failed with %d\n",
1275-
fwname, ret);
1276-
kfree(fwname);
1277-
goto err_cputype;
1278-
}
1279-
kfree(fwname);
1280-
1281-
if (fw->size < sizeof(*header))
1282-
goto err_firmware;
1283-
1284-
header = (struct sdma_firmware_header *)fw->data;
1285-
1286-
if (header->magic != SDMA_FIRMWARE_MAGIC)
1287-
goto err_firmware;
1288-
if (header->ram_code_start + header->ram_code_size > fw->size)
1289-
goto err_firmware;
1290-
1291-
addr = (void *)header + header->script_addrs_start;
1292-
ram_code = (void *)header + header->ram_code_start;
1293-
sdma->script_addrs = kmalloc(sizeof(*addr), GFP_KERNEL);
1277+
sdma->script_addrs = kzalloc(sizeof(*sdma->script_addrs), GFP_KERNEL);
12941278
if (!sdma->script_addrs)
1295-
goto err_firmware;
1296-
memcpy(sdma->script_addrs, addr, sizeof(*addr));
1279+
goto err_alloc;
12971280

12981281
sdma->version = pdata->sdma_version;
12991282

@@ -1316,10 +1299,15 @@ static int __init sdma_probe(struct platform_device *pdev)
13161299
list_add_tail(&sdmac->chan.device_node, &sdma->dma_device.channels);
13171300
}
13181301

1319-
ret = sdma_init(sdma, ram_code, header->ram_code_size);
1302+
ret = sdma_init(sdma);
13201303
if (ret)
13211304
goto err_init;
13221305

1306+
if (pdata->script_addrs)
1307+
sdma_add_scripts(sdma, pdata->script_addrs);
1308+
1309+
sdma_get_firmware(sdma, pdata->cpu_name, pdata->to_version);
1310+
13231311
sdma->dma_device.dev = &pdev->dev;
13241312

13251313
sdma->dma_device.device_alloc_chan_resources = sdma_alloc_chan_resources;
@@ -1336,26 +1324,20 @@ static int __init sdma_probe(struct platform_device *pdev)
13361324
goto err_init;
13371325
}
13381326

1339-
dev_info(&pdev->dev, "initialized (firmware %d.%d)\n",
1340-
header->version_major,
1341-
header->version_minor);
1342-
13431327
/* request channel 0. This is an internal control channel
13441328
* to the SDMA engine and not available to clients.
13451329
*/
13461330
dma_cap_zero(mask);
13471331
dma_cap_set(DMA_SLAVE, mask);
13481332
dma_request_channel(mask, NULL, NULL);
13491333

1350-
release_firmware(fw);
1334+
dev_info(sdma->dev, "initialized\n");
13511335

13521336
return 0;
13531337

13541338
err_init:
13551339
kfree(sdma->script_addrs);
1356-
err_firmware:
1357-
release_firmware(fw);
1358-
err_cputype:
1340+
err_alloc:
13591341
free_irq(irq, sdma);
13601342
err_request_irq:
13611343
iounmap(sdma->regs);

0 commit comments

Comments
 (0)