xref: /openbmc/linux/drivers/gpu/drm/nouveau/nvkm/falcon/base.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
131214108SAlexandre Courbot /*
231214108SAlexandre Courbot  * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
331214108SAlexandre Courbot  *
431214108SAlexandre Courbot  * Permission is hereby granted, free of charge, to any person obtaining a
531214108SAlexandre Courbot  * copy of this software and associated documentation files (the "Software"),
631214108SAlexandre Courbot  * to deal in the Software without restriction, including without limitation
731214108SAlexandre Courbot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
831214108SAlexandre Courbot  * and/or sell copies of the Software, and to permit persons to whom the
931214108SAlexandre Courbot  * Software is furnished to do so, subject to the following conditions:
1031214108SAlexandre Courbot  *
1131214108SAlexandre Courbot  * The above copyright notice and this permission notice shall be included in
1231214108SAlexandre Courbot  * all copies or substantial portions of the Software.
1331214108SAlexandre Courbot  *
1431214108SAlexandre Courbot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1531214108SAlexandre Courbot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1631214108SAlexandre Courbot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1731214108SAlexandre Courbot  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1831214108SAlexandre Courbot  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1931214108SAlexandre Courbot  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2031214108SAlexandre Courbot  * DEALINGS IN THE SOFTWARE.
2131214108SAlexandre Courbot  */
2231214108SAlexandre Courbot #include "priv.h"
2331214108SAlexandre Courbot 
2431214108SAlexandre Courbot #include <subdev/mc.h>
252541626cSBen Skeggs #include <subdev/timer.h>
26de048192SBen Skeggs #include <subdev/top.h>
2731214108SAlexandre Courbot 
28*a51c69eeSBen Skeggs static const struct nvkm_falcon_func_dma *
nvkm_falcon_dma(struct nvkm_falcon * falcon,enum nvkm_falcon_mem * mem_type,u32 * mem_base)29*a51c69eeSBen Skeggs nvkm_falcon_dma(struct nvkm_falcon *falcon, enum nvkm_falcon_mem *mem_type, u32 *mem_base)
30*a51c69eeSBen Skeggs {
31*a51c69eeSBen Skeggs 	switch (*mem_type) {
32*a51c69eeSBen Skeggs 	case IMEM: return falcon->func->imem_dma;
33*a51c69eeSBen Skeggs 	case DMEM: return falcon->func->dmem_dma;
34*a51c69eeSBen Skeggs 	default:
35*a51c69eeSBen Skeggs 		return NULL;
36*a51c69eeSBen Skeggs 	}
37*a51c69eeSBen Skeggs }
38*a51c69eeSBen Skeggs 
39*a51c69eeSBen Skeggs int
nvkm_falcon_dma_wr(struct nvkm_falcon * falcon,const u8 * img,u64 dma_addr,u32 dma_base,enum nvkm_falcon_mem mem_type,u32 mem_base,int len,bool sec)40*a51c69eeSBen Skeggs nvkm_falcon_dma_wr(struct nvkm_falcon *falcon, const u8 *img, u64 dma_addr, u32 dma_base,
41*a51c69eeSBen Skeggs 		   enum nvkm_falcon_mem mem_type, u32 mem_base, int len, bool sec)
42*a51c69eeSBen Skeggs {
43*a51c69eeSBen Skeggs 	const struct nvkm_falcon_func_dma *dma = nvkm_falcon_dma(falcon, &mem_type, &mem_base);
44*a51c69eeSBen Skeggs 	const char *type = nvkm_falcon_mem(mem_type);
45*a51c69eeSBen Skeggs 	const int dmalen = 256;
46*a51c69eeSBen Skeggs 	u32 dma_start = 0;
47*a51c69eeSBen Skeggs 	u32 dst, src, cmd;
48*a51c69eeSBen Skeggs 	int ret, i;
49*a51c69eeSBen Skeggs 
50*a51c69eeSBen Skeggs 	if (WARN_ON(!dma->xfer))
51*a51c69eeSBen Skeggs 		return -EINVAL;
52*a51c69eeSBen Skeggs 
53*a51c69eeSBen Skeggs 	if (mem_type == DMEM) {
54*a51c69eeSBen Skeggs 		dma_start = dma_base;
55*a51c69eeSBen Skeggs 		dma_addr += dma_base;
56*a51c69eeSBen Skeggs 	}
57*a51c69eeSBen Skeggs 
58*a51c69eeSBen Skeggs 	FLCN_DBG(falcon, "%s %08x <- %08x bytes at %08x (%010llx %08x)",
59*a51c69eeSBen Skeggs 		 type, mem_base, len, dma_base, dma_addr - dma_base, dma_start);
60*a51c69eeSBen Skeggs 	if (WARN_ON(!len || (len & (dmalen - 1))))
61*a51c69eeSBen Skeggs 		return -EINVAL;
62*a51c69eeSBen Skeggs 
63*a51c69eeSBen Skeggs 	ret = dma->init(falcon, dma_addr, dmalen, mem_type, sec, &cmd);
64*a51c69eeSBen Skeggs 	if (ret)
65*a51c69eeSBen Skeggs 		return ret;
66*a51c69eeSBen Skeggs 
67*a51c69eeSBen Skeggs 	dst = mem_base;
68*a51c69eeSBen Skeggs 	src = dma_base;
69*a51c69eeSBen Skeggs 	if (len) {
70*a51c69eeSBen Skeggs 		while (len >= dmalen) {
71*a51c69eeSBen Skeggs 			dma->xfer(falcon, dst, src - dma_start, cmd);
72*a51c69eeSBen Skeggs 
73*a51c69eeSBen Skeggs 			if (img && nvkm_printk_ok(falcon->owner, falcon->user, NV_DBG_TRACE)) {
74*a51c69eeSBen Skeggs 				for (i = 0; i < dmalen; i += 4, mem_base += 4) {
75*a51c69eeSBen Skeggs 					const int w = 8, x = (i / 4) % w;
76*a51c69eeSBen Skeggs 
77*a51c69eeSBen Skeggs 					if (x == 0)
78*a51c69eeSBen Skeggs 						printk(KERN_INFO "%s %08x <-", type, mem_base);
79*a51c69eeSBen Skeggs 					printk(KERN_CONT " %08x", *(u32 *)(img + src + i));
80*a51c69eeSBen Skeggs 					if (x == (w - 1) || ((i + 4) == dmalen))
81*a51c69eeSBen Skeggs 						printk(KERN_CONT " <- %08x+%08x", dma_base,
82*a51c69eeSBen Skeggs 						       src + i - dma_base - (x * 4));
83*a51c69eeSBen Skeggs 					if (i == (7 * 4))
84*a51c69eeSBen Skeggs 						printk(KERN_CONT " *");
85*a51c69eeSBen Skeggs 				}
86*a51c69eeSBen Skeggs 			}
87*a51c69eeSBen Skeggs 
88*a51c69eeSBen Skeggs 			if (nvkm_msec(falcon->owner->device, 2000,
89*a51c69eeSBen Skeggs 				if (dma->done(falcon))
90*a51c69eeSBen Skeggs 					break;
91*a51c69eeSBen Skeggs 			) < 0)
92*a51c69eeSBen Skeggs 				return -ETIMEDOUT;
93*a51c69eeSBen Skeggs 
94*a51c69eeSBen Skeggs 			src += dmalen;
95*a51c69eeSBen Skeggs 			dst += dmalen;
96*a51c69eeSBen Skeggs 			len -= dmalen;
97*a51c69eeSBen Skeggs 		}
98*a51c69eeSBen Skeggs 		WARN_ON(len);
99*a51c69eeSBen Skeggs 	}
100*a51c69eeSBen Skeggs 
101*a51c69eeSBen Skeggs 	return 0;
102*a51c69eeSBen Skeggs }
103*a51c69eeSBen Skeggs 
1040e44c217SBen Skeggs static const struct nvkm_falcon_func_pio *
nvkm_falcon_pio(struct nvkm_falcon * falcon,enum nvkm_falcon_mem * mem_type,u32 * mem_base)1050e44c217SBen Skeggs nvkm_falcon_pio(struct nvkm_falcon *falcon, enum nvkm_falcon_mem *mem_type, u32 *mem_base)
1060e44c217SBen Skeggs {
1070e44c217SBen Skeggs 	switch (*mem_type) {
1080e44c217SBen Skeggs 	case IMEM:
1090e44c217SBen Skeggs 		return falcon->func->imem_pio;
1100e44c217SBen Skeggs 	case DMEM:
1110e44c217SBen Skeggs 		if (!falcon->func->emem_addr || *mem_base < falcon->func->emem_addr)
1120e44c217SBen Skeggs 			return falcon->func->dmem_pio;
1130e44c217SBen Skeggs 
1140e44c217SBen Skeggs 		*mem_base -= falcon->func->emem_addr;
1150e44c217SBen Skeggs 		fallthrough;
1162541626cSBen Skeggs 	case EMEM:
1172541626cSBen Skeggs 		return falcon->func->emem_pio;
1180e44c217SBen Skeggs 	default:
1190e44c217SBen Skeggs 		return NULL;
1200e44c217SBen Skeggs 	}
1210e44c217SBen Skeggs }
1220e44c217SBen Skeggs 
1230e44c217SBen Skeggs int
nvkm_falcon_pio_rd(struct nvkm_falcon * falcon,u8 port,enum nvkm_falcon_mem mem_type,u32 mem_base,const u8 * img,u32 img_base,int len)1242541626cSBen Skeggs nvkm_falcon_pio_rd(struct nvkm_falcon *falcon, u8 port, enum nvkm_falcon_mem mem_type, u32 mem_base,
1252541626cSBen Skeggs 		   const u8 *img, u32 img_base, int len)
1262541626cSBen Skeggs {
1272541626cSBen Skeggs 	const struct nvkm_falcon_func_pio *pio = nvkm_falcon_pio(falcon, &mem_type, &mem_base);
1282541626cSBen Skeggs 	const char *type = nvkm_falcon_mem(mem_type);
1292541626cSBen Skeggs 	int xfer_len;
1302541626cSBen Skeggs 
1312541626cSBen Skeggs 	if (WARN_ON(!pio || !pio->rd))
1322541626cSBen Skeggs 		return -EINVAL;
1332541626cSBen Skeggs 
1342541626cSBen Skeggs 	FLCN_DBG(falcon, "%s %08x -> %08x bytes at %08x", type, mem_base, len, img_base);
1352541626cSBen Skeggs 	if (WARN_ON(!len || (len & (pio->min - 1))))
1362541626cSBen Skeggs 		return -EINVAL;
1372541626cSBen Skeggs 
1382541626cSBen Skeggs 	pio->rd_init(falcon, port, mem_base);
1392541626cSBen Skeggs 	do {
1402541626cSBen Skeggs 		xfer_len = min(len, pio->max);
1412541626cSBen Skeggs 		pio->rd(falcon, port, img, xfer_len);
1422541626cSBen Skeggs 
1432541626cSBen Skeggs 		if (nvkm_printk_ok(falcon->owner, falcon->user, NV_DBG_TRACE)) {
1442541626cSBen Skeggs 			for (img_base = 0; img_base < xfer_len; img_base += 4, mem_base += 4) {
1452541626cSBen Skeggs 				if (((img_base / 4) % 8) == 0)
1462541626cSBen Skeggs 					printk(KERN_INFO "%s %08x ->", type, mem_base);
1472541626cSBen Skeggs 				printk(KERN_CONT " %08x", *(u32 *)(img + img_base));
1482541626cSBen Skeggs 			}
1492541626cSBen Skeggs 		}
1502541626cSBen Skeggs 
1512541626cSBen Skeggs 		img += xfer_len;
1522541626cSBen Skeggs 		len -= xfer_len;
1532541626cSBen Skeggs 	} while (len);
1542541626cSBen Skeggs 
1552541626cSBen Skeggs 	return 0;
1562541626cSBen Skeggs }
1572541626cSBen Skeggs 
1582541626cSBen Skeggs int
nvkm_falcon_pio_wr(struct nvkm_falcon * falcon,const u8 * img,u32 img_base,u8 port,enum nvkm_falcon_mem mem_type,u32 mem_base,int len,u16 tag,bool sec)1590e44c217SBen Skeggs nvkm_falcon_pio_wr(struct nvkm_falcon *falcon, const u8 *img, u32 img_base, u8 port,
1600e44c217SBen Skeggs 		   enum nvkm_falcon_mem mem_type, u32 mem_base, int len, u16 tag, bool sec)
1610e44c217SBen Skeggs {
1620e44c217SBen Skeggs 	const struct nvkm_falcon_func_pio *pio = nvkm_falcon_pio(falcon, &mem_type, &mem_base);
1630e44c217SBen Skeggs 	const char *type = nvkm_falcon_mem(mem_type);
1640e44c217SBen Skeggs 	int xfer_len;
1650e44c217SBen Skeggs 
1660e44c217SBen Skeggs 	if (WARN_ON(!pio || !pio->wr))
1670e44c217SBen Skeggs 		return -EINVAL;
1680e44c217SBen Skeggs 
1690e44c217SBen Skeggs 	FLCN_DBG(falcon, "%s %08x <- %08x bytes at %08x", type, mem_base, len, img_base);
1700e44c217SBen Skeggs 	if (WARN_ON(!len || (len & (pio->min - 1))))
1710e44c217SBen Skeggs 		return -EINVAL;
1720e44c217SBen Skeggs 
1730e44c217SBen Skeggs 	pio->wr_init(falcon, port, sec, mem_base);
1740e44c217SBen Skeggs 	do {
1750e44c217SBen Skeggs 		xfer_len = min(len, pio->max);
1760e44c217SBen Skeggs 		pio->wr(falcon, port, img, xfer_len, tag++);
1770e44c217SBen Skeggs 
1780e44c217SBen Skeggs 		if (nvkm_printk_ok(falcon->owner, falcon->user, NV_DBG_TRACE)) {
1790e44c217SBen Skeggs 			for (img_base = 0; img_base < xfer_len; img_base += 4, mem_base += 4) {
1800e44c217SBen Skeggs 				if (((img_base / 4) % 8) == 0)
1810e44c217SBen Skeggs 					printk(KERN_INFO "%s %08x <-", type, mem_base);
1820e44c217SBen Skeggs 				printk(KERN_CONT " %08x", *(u32 *)(img + img_base));
1830e44c217SBen Skeggs 				if ((img_base / 4) == 7 && mem_type == IMEM)
1840e44c217SBen Skeggs 					printk(KERN_CONT " %04x", tag - 1);
1850e44c217SBen Skeggs 			}
1860e44c217SBen Skeggs 		}
1870e44c217SBen Skeggs 
1880e44c217SBen Skeggs 		img += xfer_len;
1890e44c217SBen Skeggs 		len -= xfer_len;
1900e44c217SBen Skeggs 	} while (len);
1910e44c217SBen Skeggs 
1920e44c217SBen Skeggs 	return 0;
1930e44c217SBen Skeggs }
1940e44c217SBen Skeggs 
19531214108SAlexandre Courbot void
nvkm_falcon_load_imem(struct nvkm_falcon * falcon,void * data,u32 start,u32 size,u16 tag,u8 port,bool secure)19631214108SAlexandre Courbot nvkm_falcon_load_imem(struct nvkm_falcon *falcon, void *data, u32 start,
19731214108SAlexandre Courbot 		      u32 size, u16 tag, u8 port, bool secure)
19831214108SAlexandre Courbot {
19931214108SAlexandre Courbot 	if (secure && !falcon->secret) {
20031214108SAlexandre Courbot 		nvkm_warn(falcon->user,
20131214108SAlexandre Courbot 			  "writing with secure tag on a non-secure falcon!\n");
20231214108SAlexandre Courbot 		return;
20331214108SAlexandre Courbot 	}
20431214108SAlexandre Courbot 
20531214108SAlexandre Courbot 	falcon->func->load_imem(falcon, data, start, size, tag, port,
20631214108SAlexandre Courbot 				secure);
20731214108SAlexandre Courbot }
20831214108SAlexandre Courbot 
20931214108SAlexandre Courbot void
nvkm_falcon_load_dmem(struct nvkm_falcon * falcon,void * data,u32 start,u32 size,u8 port)21031214108SAlexandre Courbot nvkm_falcon_load_dmem(struct nvkm_falcon *falcon, void *data, u32 start,
21131214108SAlexandre Courbot 		      u32 size, u8 port)
21231214108SAlexandre Courbot {
213e444de56SAlexandre Courbot 	mutex_lock(&falcon->dmem_mutex);
214e444de56SAlexandre Courbot 
21531214108SAlexandre Courbot 	falcon->func->load_dmem(falcon, data, start, size, port);
216e444de56SAlexandre Courbot 
217e444de56SAlexandre Courbot 	mutex_unlock(&falcon->dmem_mutex);
21831214108SAlexandre Courbot }
21931214108SAlexandre Courbot 
22031214108SAlexandre Courbot void
nvkm_falcon_start(struct nvkm_falcon * falcon)22131214108SAlexandre Courbot nvkm_falcon_start(struct nvkm_falcon *falcon)
22231214108SAlexandre Courbot {
22331214108SAlexandre Courbot 	falcon->func->start(falcon);
22431214108SAlexandre Courbot }
22531214108SAlexandre Courbot 
22631214108SAlexandre Courbot int
nvkm_falcon_reset(struct nvkm_falcon * falcon)22731214108SAlexandre Courbot nvkm_falcon_reset(struct nvkm_falcon *falcon)
22831214108SAlexandre Courbot {
229f15cde64SBen Skeggs 	int ret;
23031214108SAlexandre Courbot 
231f15cde64SBen Skeggs 	ret = falcon->func->disable(falcon);
232f15cde64SBen Skeggs 	if (WARN_ON(ret))
233f15cde64SBen Skeggs 		return ret;
234f15cde64SBen Skeggs 
235f15cde64SBen Skeggs 	return nvkm_falcon_enable(falcon);
2364cdd2450SBen Skeggs }
2374cdd2450SBen Skeggs 
2385a4b98cdSBen Skeggs static int
nvkm_falcon_oneinit(struct nvkm_falcon * falcon)2395a4b98cdSBen Skeggs nvkm_falcon_oneinit(struct nvkm_falcon *falcon)
24031214108SAlexandre Courbot {
241e938c4e7SBen Skeggs 	const struct nvkm_falcon_func *func = falcon->func;
2425a4b98cdSBen Skeggs 	const struct nvkm_subdev *subdev = falcon->owner;
24331214108SAlexandre Courbot 	u32 reg;
24431214108SAlexandre Courbot 
245de048192SBen Skeggs 	if (!falcon->addr) {
246b7da823aSBen Skeggs 		falcon->addr = nvkm_top_addr(subdev->device, subdev->type, subdev->inst);
247de048192SBen Skeggs 		if (WARN_ON(!falcon->addr))
248de048192SBen Skeggs 			return -ENODEV;
249de048192SBen Skeggs 	}
250de048192SBen Skeggs 
25131214108SAlexandre Courbot 	reg = nvkm_falcon_rd32(falcon, 0x12c);
25231214108SAlexandre Courbot 	falcon->version = reg & 0xf;
25331214108SAlexandre Courbot 	falcon->secret = (reg >> 4) & 0x3;
25431214108SAlexandre Courbot 	falcon->code.ports = (reg >> 8) & 0xf;
25531214108SAlexandre Courbot 	falcon->data.ports = (reg >> 12) & 0xf;
25631214108SAlexandre Courbot 
25731214108SAlexandre Courbot 	reg = nvkm_falcon_rd32(falcon, 0x108);
25831214108SAlexandre Courbot 	falcon->code.limit = (reg & 0x1ff) << 8;
25931214108SAlexandre Courbot 	falcon->data.limit = (reg & 0x3fe00) >> 1;
26031214108SAlexandre Courbot 
261e938c4e7SBen Skeggs 	if (func->debug) {
262e938c4e7SBen Skeggs 		u32 val = nvkm_falcon_rd32(falcon, func->debug);
263ad147b7fSAlexandre Courbot 		falcon->debug = (val >> 20) & 0x1;
264ad147b7fSAlexandre Courbot 	}
2655a4b98cdSBen Skeggs 
2665a4b98cdSBen Skeggs 	return 0;
2675a4b98cdSBen Skeggs }
2685a4b98cdSBen Skeggs 
2695a4b98cdSBen Skeggs void
nvkm_falcon_put(struct nvkm_falcon * falcon,struct nvkm_subdev * user)270a9d90860SBen Skeggs nvkm_falcon_put(struct nvkm_falcon *falcon, struct nvkm_subdev *user)
2715a4b98cdSBen Skeggs {
2725a4b98cdSBen Skeggs 	if (unlikely(!falcon))
2735a4b98cdSBen Skeggs 		return;
2745a4b98cdSBen Skeggs 
2755a4b98cdSBen Skeggs 	mutex_lock(&falcon->mutex);
2765a4b98cdSBen Skeggs 	if (falcon->user == user) {
2775a4b98cdSBen Skeggs 		nvkm_debug(falcon->user, "released %s falcon\n", falcon->name);
2785a4b98cdSBen Skeggs 		falcon->user = NULL;
2795a4b98cdSBen Skeggs 	}
2805a4b98cdSBen Skeggs 	mutex_unlock(&falcon->mutex);
2815a4b98cdSBen Skeggs }
2825a4b98cdSBen Skeggs 
2835a4b98cdSBen Skeggs int
nvkm_falcon_get(struct nvkm_falcon * falcon,struct nvkm_subdev * user)284a9d90860SBen Skeggs nvkm_falcon_get(struct nvkm_falcon *falcon, struct nvkm_subdev *user)
2855a4b98cdSBen Skeggs {
2865a4b98cdSBen Skeggs 	int ret = 0;
2875a4b98cdSBen Skeggs 
2885a4b98cdSBen Skeggs 	mutex_lock(&falcon->mutex);
2895a4b98cdSBen Skeggs 	if (falcon->user) {
2905a4b98cdSBen Skeggs 		nvkm_error(user, "%s falcon already acquired by %s!\n",
2919c28abb7SBen Skeggs 			   falcon->name, falcon->user->name);
2925a4b98cdSBen Skeggs 		mutex_unlock(&falcon->mutex);
2935a4b98cdSBen Skeggs 		return -EBUSY;
2945a4b98cdSBen Skeggs 	}
2955a4b98cdSBen Skeggs 
2965a4b98cdSBen Skeggs 	nvkm_debug(user, "acquired %s falcon\n", falcon->name);
2975a4b98cdSBen Skeggs 	if (!falcon->oneinit)
2985a4b98cdSBen Skeggs 		ret = nvkm_falcon_oneinit(falcon);
2995a4b98cdSBen Skeggs 	falcon->user = user;
3005a4b98cdSBen Skeggs 	mutex_unlock(&falcon->mutex);
3015a4b98cdSBen Skeggs 	return ret;
3025a4b98cdSBen Skeggs }
3035a4b98cdSBen Skeggs 
3045a4b98cdSBen Skeggs void
nvkm_falcon_dtor(struct nvkm_falcon * falcon)305a128bbfaSBen Skeggs nvkm_falcon_dtor(struct nvkm_falcon *falcon)
306a128bbfaSBen Skeggs {
307a128bbfaSBen Skeggs }
308a128bbfaSBen Skeggs 
309a128bbfaSBen Skeggs int
nvkm_falcon_ctor(const struct nvkm_falcon_func * func,struct nvkm_subdev * subdev,const char * name,u32 addr,struct nvkm_falcon * falcon)3105a4b98cdSBen Skeggs nvkm_falcon_ctor(const struct nvkm_falcon_func *func,
3115a4b98cdSBen Skeggs 		 struct nvkm_subdev *subdev, const char *name, u32 addr,
3125a4b98cdSBen Skeggs 		 struct nvkm_falcon *falcon)
3135a4b98cdSBen Skeggs {
3145a4b98cdSBen Skeggs 	falcon->func = func;
3155a4b98cdSBen Skeggs 	falcon->owner = subdev;
3165a4b98cdSBen Skeggs 	falcon->name = name;
3175a4b98cdSBen Skeggs 	falcon->addr = addr;
318*a51c69eeSBen Skeggs 	falcon->addr2 = func->addr2;
3195a4b98cdSBen Skeggs 	mutex_init(&falcon->mutex);
3205a4b98cdSBen Skeggs 	mutex_init(&falcon->dmem_mutex);
321a128bbfaSBen Skeggs 	return 0;
32231214108SAlexandre Courbot }
323