Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * Driver for MPC52xx processor BestComm peripheral controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Copyright (C) 2005      Varma Electronics Oy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *                         ( by Andrey Volkov <avolkov@varma-el.com> )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * Copyright (C) 2003-2004 MontaVista, Software, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *                         ( by Dale Farnsworth <dfarnsworth@mvista.com> )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * This file is licensed under the terms of the GNU General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * version 2. This program is licensed "as is" without any warranty of any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <asm/mpc52xx.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include <linux/fsl/bestcomm/sram.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include <linux/fsl/bestcomm/bestcomm_priv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #include "linux/fsl/bestcomm/bestcomm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define DRIVER_NAME "bestcomm-core"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) /* MPC5200 device tree match tables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) static const struct of_device_id mpc52xx_sram_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	{ .compatible = "fsl,mpc5200-sram", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	{ .compatible = "mpc5200-sram", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	{}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) struct bcom_engine *bcom_eng = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) EXPORT_SYMBOL_GPL(bcom_eng);	/* needed for inline functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) /* ======================================================================== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) /* Public and private API                                                   */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) /* ======================================================================== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) /* Private API */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) struct bcom_task *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) bcom_task_alloc(int bd_count, int bd_size, int priv_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	int i, tasknum = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	struct bcom_task *tsk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	/* Don't try to do anything if bestcomm init failed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	if (!bcom_eng)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	/* Get and reserve a task num */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	spin_lock(&bcom_eng->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	for (i=0; i<BCOM_MAX_TASKS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		if (!bcom_eng->tdt[i].stop) {	/* we use stop as a marker */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 			bcom_eng->tdt[i].stop = 0xfffffffful; /* dummy addr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 			tasknum = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	spin_unlock(&bcom_eng->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	if (tasknum < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	/* Allocate our structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	tsk = kzalloc(sizeof(struct bcom_task) + priv_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	if (!tsk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	tsk->tasknum = tasknum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	if (priv_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		tsk->priv = (void*)tsk + sizeof(struct bcom_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	/* Get IRQ of that task */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	tsk->irq = irq_of_parse_and_map(bcom_eng->ofnode, tsk->tasknum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	if (!tsk->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	/* Init the BDs, if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	if (bd_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		tsk->cookie = kmalloc_array(bd_count, sizeof(void *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 					    GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		if (!tsk->cookie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 			goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		tsk->bd = bcom_sram_alloc(bd_count * bd_size, 4, &tsk->bd_pa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		if (!tsk->bd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 			goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		memset(tsk->bd, 0x00, bd_count * bd_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		tsk->num_bd = bd_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		tsk->bd_size = bd_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	return tsk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	if (tsk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		if (tsk->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 			irq_dispose_mapping(tsk->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		bcom_sram_free(tsk->bd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		kfree(tsk->cookie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		kfree(tsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	bcom_eng->tdt[tasknum].stop = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) EXPORT_SYMBOL_GPL(bcom_task_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) bcom_task_free(struct bcom_task *tsk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	/* Stop the task */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	bcom_disable_task(tsk->tasknum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	/* Clear TDT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	bcom_eng->tdt[tsk->tasknum].start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	bcom_eng->tdt[tsk->tasknum].stop  = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	/* Free everything */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	irq_dispose_mapping(tsk->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	bcom_sram_free(tsk->bd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	kfree(tsk->cookie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	kfree(tsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) EXPORT_SYMBOL_GPL(bcom_task_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) bcom_load_image(int task, u32 *task_image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	struct bcom_task_header *hdr = (struct bcom_task_header *)task_image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	struct bcom_tdt *tdt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	u32 *desc, *var, *inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	u32 *desc_src, *var_src, *inc_src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	/* Safety checks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	if (hdr->magic != BCOM_TASK_MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		printk(KERN_ERR DRIVER_NAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 			": Trying to load invalid microcode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	if ((task < 0) || (task >= BCOM_MAX_TASKS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		printk(KERN_ERR DRIVER_NAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 			": Trying to load invalid task %d\n", task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	/* Initial load or reload */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	tdt = &bcom_eng->tdt[task];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	if (tdt->start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		desc = bcom_task_desc(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		if (hdr->desc_size != bcom_task_num_descs(task)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 			printk(KERN_ERR DRIVER_NAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 				": Trying to reload wrong task image "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 				"(%d size %d/%d)!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 				task,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 				hdr->desc_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 				bcom_task_num_descs(task));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		phys_addr_t start_pa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		desc = bcom_sram_alloc(hdr->desc_size * sizeof(u32), 4, &start_pa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		if (!desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		tdt->start = start_pa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		tdt->stop = start_pa + ((hdr->desc_size-1) * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	var = bcom_task_var(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	inc = bcom_task_inc(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	/* Clear & copy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	memset(var, 0x00, BCOM_VAR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	memset(inc, 0x00, BCOM_INC_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	desc_src = (u32 *)(hdr + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	var_src = desc_src + hdr->desc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	inc_src = var_src + hdr->var_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	memcpy(desc, desc_src, hdr->desc_size * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	memcpy(var + hdr->first_var, var_src, hdr->var_size * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	memcpy(inc, inc_src, hdr->inc_size * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) EXPORT_SYMBOL_GPL(bcom_load_image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) bcom_set_initiator(int task, int initiator)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	int num_descs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	u32 *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	int next_drd_has_initiator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	bcom_set_tcr_initiator(task, initiator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	/* Just setting tcr is apparently not enough due to some problem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	/* with it. So we just go thru all the microcode and replace in  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	/* the DRD directly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	desc = bcom_task_desc(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	next_drd_has_initiator = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	num_descs = bcom_task_num_descs(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	for (i=0; i<num_descs; i++, desc++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		if (!bcom_desc_is_drd(*desc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		if (next_drd_has_initiator)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 			if (bcom_desc_initiator(*desc) != BCOM_INITIATOR_ALWAYS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 				bcom_set_desc_initiator(desc, initiator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		next_drd_has_initiator = !bcom_drd_is_extended(*desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) EXPORT_SYMBOL_GPL(bcom_set_initiator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /* Public API */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) bcom_enable(struct bcom_task *tsk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	bcom_enable_task(tsk->tasknum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) EXPORT_SYMBOL_GPL(bcom_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) bcom_disable(struct bcom_task *tsk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	bcom_disable_task(tsk->tasknum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) EXPORT_SYMBOL_GPL(bcom_disable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /* ======================================================================== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* Engine init/cleanup                                                      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /* ======================================================================== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* Function Descriptor table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* this will need to be updated if Freescale changes their task code FDT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static u32 fdt_ops[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	0xa0045670,	/* FDT[48] - load_acc()	  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	0x80045670,	/* FDT[49] - unload_acc() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	0x21800000,	/* FDT[50] - and()        */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	0x21e00000,	/* FDT[51] - or()         */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	0x21500000,	/* FDT[52] - xor()        */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	0x21400000,	/* FDT[53] - andn()       */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	0x21500000,	/* FDT[54] - not()        */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	0x20400000,	/* FDT[55] - add()        */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	0x20500000,	/* FDT[56] - sub()        */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	0x20800000,	/* FDT[57] - lsh()        */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	0x20a00000,	/* FDT[58] - rsh()        */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	0xc0170000,	/* FDT[59] - crc8()       */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	0xc0145670,	/* FDT[60] - crc16()      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	0xc0345670,	/* FDT[61] - crc32()      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	0xa0076540,	/* FDT[62] - endian32()   */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	0xa0000760,	/* FDT[63] - endian16()   */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static int bcom_engine_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	int task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	phys_addr_t tdt_pa, ctx_pa, var_pa, fdt_pa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	unsigned int tdt_size, ctx_size, var_size, fdt_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	/* Allocate & clear SRAM zones for FDT, TDTs, contexts and vars/incs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	tdt_size = BCOM_MAX_TASKS * sizeof(struct bcom_tdt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	ctx_size = BCOM_MAX_TASKS * BCOM_CTX_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	var_size = BCOM_MAX_TASKS * (BCOM_VAR_SIZE + BCOM_INC_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	fdt_size = BCOM_FDT_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	bcom_eng->tdt = bcom_sram_alloc(tdt_size, sizeof(u32), &tdt_pa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	bcom_eng->ctx = bcom_sram_alloc(ctx_size, BCOM_CTX_ALIGN, &ctx_pa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	bcom_eng->var = bcom_sram_alloc(var_size, BCOM_VAR_ALIGN, &var_pa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	bcom_eng->fdt = bcom_sram_alloc(fdt_size, BCOM_FDT_ALIGN, &fdt_pa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	if (!bcom_eng->tdt || !bcom_eng->ctx || !bcom_eng->var || !bcom_eng->fdt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		printk(KERN_ERR "DMA: SRAM alloc failed in engine init !\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		bcom_sram_free(bcom_eng->tdt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		bcom_sram_free(bcom_eng->ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 		bcom_sram_free(bcom_eng->var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		bcom_sram_free(bcom_eng->fdt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	memset(bcom_eng->tdt, 0x00, tdt_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	memset(bcom_eng->ctx, 0x00, ctx_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	memset(bcom_eng->var, 0x00, var_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	memset(bcom_eng->fdt, 0x00, fdt_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	/* Copy the FDT for the EU#3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	memcpy(&bcom_eng->fdt[48], fdt_ops, sizeof(fdt_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	/* Initialize Task base structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	for (task=0; task<BCOM_MAX_TASKS; task++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		out_be16(&bcom_eng->regs->tcr[task], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 		out_8(&bcom_eng->regs->ipr[task], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		bcom_eng->tdt[task].context	= ctx_pa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		bcom_eng->tdt[task].var	= var_pa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		bcom_eng->tdt[task].fdt	= fdt_pa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		var_pa += BCOM_VAR_SIZE + BCOM_INC_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		ctx_pa += BCOM_CTX_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	out_be32(&bcom_eng->regs->taskBar, tdt_pa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	/* Init 'always' initiator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ALWAYS], BCOM_IPR_ALWAYS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	/* Disable COMM Bus Prefetch on the original 5200; it's broken */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	if ((mfspr(SPRN_SVR) & MPC5200_SVR_MASK) == MPC5200_SVR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		bcom_disable_prefetch();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	/* Init lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	spin_lock_init(&bcom_eng->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) bcom_engine_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	int task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	/* Stop all tasks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	for (task=0; task<BCOM_MAX_TASKS; task++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 		out_be16(&bcom_eng->regs->tcr[task], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		out_8(&bcom_eng->regs->ipr[task], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	out_be32(&bcom_eng->regs->taskBar, 0ul);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	/* Release the SRAM zones */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	bcom_sram_free(bcom_eng->tdt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	bcom_sram_free(bcom_eng->ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	bcom_sram_free(bcom_eng->var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	bcom_sram_free(bcom_eng->fdt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /* ======================================================================== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) /* OF platform driver                                                       */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* ======================================================================== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static int mpc52xx_bcom_probe(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	struct device_node *ofn_sram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	struct resource res_bcom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	/* Inform user we're ok so far */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	printk(KERN_INFO "DMA: MPC52xx BestComm driver\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	/* Get the bestcomm node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	of_node_get(op->dev.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	/* Prepare SRAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	ofn_sram = of_find_matching_node(NULL, mpc52xx_sram_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	if (!ofn_sram) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 		printk(KERN_ERR DRIVER_NAME ": "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 			"No SRAM found in device tree\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 		rv = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 		goto error_ofput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	rv = bcom_sram_init(ofn_sram, DRIVER_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	of_node_put(ofn_sram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	if (rv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 		printk(KERN_ERR DRIVER_NAME ": "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 			"Error in SRAM init\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 		goto error_ofput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	/* Get a clean struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	bcom_eng = kzalloc(sizeof(struct bcom_engine), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	if (!bcom_eng) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 		rv = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 		goto error_sramclean;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	/* Save the node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	bcom_eng->ofnode = op->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	/* Get, reserve & map io */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	if (of_address_to_resource(op->dev.of_node, 0, &res_bcom)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		printk(KERN_ERR DRIVER_NAME ": "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 			"Can't get resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		rv = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 		goto error_sramclean;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	if (!request_mem_region(res_bcom.start, resource_size(&res_bcom),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 				DRIVER_NAME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 		printk(KERN_ERR DRIVER_NAME ": "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 			"Can't request registers region\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 		rv = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 		goto error_sramclean;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	bcom_eng->regs_base = res_bcom.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	bcom_eng->regs = ioremap(res_bcom.start, sizeof(struct mpc52xx_sdma));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	if (!bcom_eng->regs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 		printk(KERN_ERR DRIVER_NAME ": "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 			"Can't map registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 		rv = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 		goto error_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	/* Now, do the real init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	rv = bcom_engine_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	if (rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 		goto error_unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	/* Done ! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	printk(KERN_INFO "DMA: MPC52xx BestComm engine @%08lx ok !\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 		(long)bcom_eng->regs_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	/* Error path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) error_unmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	iounmap(bcom_eng->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) error_release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	release_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) error_sramclean:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	kfree(bcom_eng);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	bcom_sram_cleanup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) error_ofput:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	of_node_put(op->dev.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	printk(KERN_ERR "DMA: MPC52xx BestComm init failed !\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) static int mpc52xx_bcom_remove(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 	/* Clean up the engine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	bcom_engine_cleanup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	/* Cleanup SRAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	bcom_sram_cleanup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	/* Release regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	iounmap(bcom_eng->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	release_mem_region(bcom_eng->regs_base, sizeof(struct mpc52xx_sdma));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 	/* Release the node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	of_node_put(bcom_eng->ofnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	/* Release memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	kfree(bcom_eng);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	bcom_eng = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) static const struct of_device_id mpc52xx_bcom_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	{ .compatible = "fsl,mpc5200-bestcomm", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	{ .compatible = "mpc5200-bestcomm", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	{},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) MODULE_DEVICE_TABLE(of, mpc52xx_bcom_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) static struct platform_driver mpc52xx_bcom_of_platform_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	.probe		= mpc52xx_bcom_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	.remove		= mpc52xx_bcom_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 		.name = DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 		.of_match_table = mpc52xx_bcom_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) /* ======================================================================== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) /* Module                                                                   */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) /* ======================================================================== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static int __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) mpc52xx_bcom_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	return platform_driver_register(&mpc52xx_bcom_of_platform_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static void __exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) mpc52xx_bcom_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	platform_driver_unregister(&mpc52xx_bcom_of_platform_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) /* If we're not a module, we must make sure everything is setup before  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) /* anyone tries to use us ... that's why we use subsys_initcall instead */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) /* of module_init. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) subsys_initcall(mpc52xx_bcom_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) module_exit(mpc52xx_bcom_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) MODULE_DESCRIPTION("Freescale MPC52xx BestComm DMA");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) MODULE_AUTHOR("Andrey Volkov <avolkov@varma-el.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) MODULE_AUTHOR("Dale Farnsworth <dfarnsworth@mvista.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)