^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)