brintos

brintos / linux-shallow public Read only

0
0
Text · 9.2 KiB · 8a24a5c Raw
351 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Driver for MPC52xx processor BestComm General Buffer Descriptor4 *5 * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>6 * Copyright (C) 2006 AppSpec Computer Technologies Corp.7 *                    Jeff Gibbons <jeff.gibbons@appspec.com>8 */9 10#include <linux/module.h>11#include <linux/kernel.h>12#include <linux/string.h>13#include <linux/types.h>14#include <asm/errno.h>15#include <asm/io.h>16 17#include <asm/mpc52xx.h>18#include <asm/mpc52xx_psc.h>19 20#include <linux/fsl/bestcomm/bestcomm.h>21#include <linux/fsl/bestcomm/bestcomm_priv.h>22#include <linux/fsl/bestcomm/gen_bd.h>23 24 25/* ======================================================================== */26/* Task image/var/inc                                                       */27/* ======================================================================== */28 29/* gen_bd tasks images */30extern u32 bcom_gen_bd_rx_task[];31extern u32 bcom_gen_bd_tx_task[];32 33/* rx task vars that need to be set before enabling the task */34struct bcom_gen_bd_rx_var {35	u32 enable;		/* (u16*) address of task's control register */36	u32 fifo;		/* (u32*) address of gen_bd's fifo */37	u32 bd_base;		/* (struct bcom_bd*) beginning of ring buffer */38	u32 bd_last;		/* (struct bcom_bd*) end of ring buffer */39	u32 bd_start;		/* (struct bcom_bd*) current bd */40	u32 buffer_size;	/* size of receive buffer */41};42 43/* rx task incs that need to be set before enabling the task */44struct bcom_gen_bd_rx_inc {45	u16 pad0;46	s16 incr_bytes;47	u16 pad1;48	s16 incr_dst;49};50 51/* tx task vars that need to be set before enabling the task */52struct bcom_gen_bd_tx_var {53	u32 fifo;		/* (u32*) address of gen_bd's fifo */54	u32 enable;		/* (u16*) address of task's control register */55	u32 bd_base;		/* (struct bcom_bd*) beginning of ring buffer */56	u32 bd_last;		/* (struct bcom_bd*) end of ring buffer */57	u32 bd_start;		/* (struct bcom_bd*) current bd */58	u32 buffer_size;	/* set by uCode for each packet */59};60 61/* tx task incs that need to be set before enabling the task */62struct bcom_gen_bd_tx_inc {63	u16 pad0;64	s16 incr_bytes;65	u16 pad1;66	s16 incr_src;67	u16 pad2;68	s16 incr_src_ma;69};70 71/* private structure */72struct bcom_gen_bd_priv {73	phys_addr_t	fifo;74	int		initiator;75	int		ipr;76	int		maxbufsize;77};78 79 80/* ======================================================================== */81/* Task support code                                                        */82/* ======================================================================== */83 84struct bcom_task *85bcom_gen_bd_rx_init(int queue_len, phys_addr_t fifo,86			int initiator, int ipr, int maxbufsize)87{88	struct bcom_task *tsk;89	struct bcom_gen_bd_priv *priv;90 91	tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),92			sizeof(struct bcom_gen_bd_priv));93	if (!tsk)94		return NULL;95 96	tsk->flags = BCOM_FLAGS_NONE;97 98	priv = tsk->priv;99	priv->fifo	= fifo;100	priv->initiator	= initiator;101	priv->ipr	= ipr;102	priv->maxbufsize = maxbufsize;103 104	if (bcom_gen_bd_rx_reset(tsk)) {105		bcom_task_free(tsk);106		return NULL;107	}108 109	return tsk;110}111EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_init);112 113int114bcom_gen_bd_rx_reset(struct bcom_task *tsk)115{116	struct bcom_gen_bd_priv *priv = tsk->priv;117	struct bcom_gen_bd_rx_var *var;118	struct bcom_gen_bd_rx_inc *inc;119 120	/* Shutdown the task */121	bcom_disable_task(tsk->tasknum);122 123	/* Reset the microcode */124	var = (struct bcom_gen_bd_rx_var *) bcom_task_var(tsk->tasknum);125	inc = (struct bcom_gen_bd_rx_inc *) bcom_task_inc(tsk->tasknum);126 127	if (bcom_load_image(tsk->tasknum, bcom_gen_bd_rx_task))128		return -1;129 130	var->enable	= bcom_eng->regs_base +131				offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);132	var->fifo	= (u32) priv->fifo;133	var->bd_base	= tsk->bd_pa;134	var->bd_last	= tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);135	var->bd_start	= tsk->bd_pa;136	var->buffer_size = priv->maxbufsize;137 138	inc->incr_bytes	= -(s16)sizeof(u32);139	inc->incr_dst	= sizeof(u32);140 141	/* Reset the BDs */142	tsk->index = 0;143	tsk->outdex = 0;144 145	memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);146 147	/* Configure some stuff */148	bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_RX_BD_PRAGMA);149	bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);150 151	out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);152	bcom_set_initiator(tsk->tasknum, priv->initiator);153 154	out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum);	/* Clear ints */155 156	return 0;157}158EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_reset);159 160void161bcom_gen_bd_rx_release(struct bcom_task *tsk)162{163	/* Nothing special for the GenBD tasks */164	bcom_task_free(tsk);165}166EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_release);167 168 169extern struct bcom_task *170bcom_gen_bd_tx_init(int queue_len, phys_addr_t fifo,171			int initiator, int ipr)172{173	struct bcom_task *tsk;174	struct bcom_gen_bd_priv *priv;175 176	tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),177			sizeof(struct bcom_gen_bd_priv));178	if (!tsk)179		return NULL;180 181	tsk->flags = BCOM_FLAGS_NONE;182 183	priv = tsk->priv;184	priv->fifo	= fifo;185	priv->initiator	= initiator;186	priv->ipr	= ipr;187 188	if (bcom_gen_bd_tx_reset(tsk)) {189		bcom_task_free(tsk);190		return NULL;191	}192 193	return tsk;194}195EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_init);196 197int198bcom_gen_bd_tx_reset(struct bcom_task *tsk)199{200	struct bcom_gen_bd_priv *priv = tsk->priv;201	struct bcom_gen_bd_tx_var *var;202	struct bcom_gen_bd_tx_inc *inc;203 204	/* Shutdown the task */205	bcom_disable_task(tsk->tasknum);206 207	/* Reset the microcode */208	var = (struct bcom_gen_bd_tx_var *) bcom_task_var(tsk->tasknum);209	inc = (struct bcom_gen_bd_tx_inc *) bcom_task_inc(tsk->tasknum);210 211	if (bcom_load_image(tsk->tasknum, bcom_gen_bd_tx_task))212		return -1;213 214	var->enable	= bcom_eng->regs_base +215				offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);216	var->fifo	= (u32) priv->fifo;217	var->bd_base	= tsk->bd_pa;218	var->bd_last	= tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);219	var->bd_start	= tsk->bd_pa;220 221	inc->incr_bytes	= -(s16)sizeof(u32);222	inc->incr_src	= sizeof(u32);223	inc->incr_src_ma = sizeof(u8);224 225	/* Reset the BDs */226	tsk->index = 0;227	tsk->outdex = 0;228 229	memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);230 231	/* Configure some stuff */232	bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_TX_BD_PRAGMA);233	bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);234 235	out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);236	bcom_set_initiator(tsk->tasknum, priv->initiator);237 238	out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum);	/* Clear ints */239 240	return 0;241}242EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_reset);243 244void245bcom_gen_bd_tx_release(struct bcom_task *tsk)246{247	/* Nothing special for the GenBD tasks */248	bcom_task_free(tsk);249}250EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_release);251 252/* ---------------------------------------------------------------------253 * PSC support code254 */255 256/**257 * bcom_psc_parameters - Bestcomm initialization value table for PSC devices258 *259 * This structure is only used internally.  It is a lookup table for PSC260 * specific parameters to bestcomm tasks.261 */262static struct bcom_psc_params {263	int rx_initiator;264	int rx_ipr;265	int tx_initiator;266	int tx_ipr;267} bcom_psc_params[] = {268	[0] = {269		.rx_initiator = BCOM_INITIATOR_PSC1_RX,270		.rx_ipr = BCOM_IPR_PSC1_RX,271		.tx_initiator = BCOM_INITIATOR_PSC1_TX,272		.tx_ipr = BCOM_IPR_PSC1_TX,273	},274	[1] = {275		.rx_initiator = BCOM_INITIATOR_PSC2_RX,276		.rx_ipr = BCOM_IPR_PSC2_RX,277		.tx_initiator = BCOM_INITIATOR_PSC2_TX,278		.tx_ipr = BCOM_IPR_PSC2_TX,279	},280	[2] = {281		.rx_initiator = BCOM_INITIATOR_PSC3_RX,282		.rx_ipr = BCOM_IPR_PSC3_RX,283		.tx_initiator = BCOM_INITIATOR_PSC3_TX,284		.tx_ipr = BCOM_IPR_PSC3_TX,285	},286	[3] = {287		.rx_initiator = BCOM_INITIATOR_PSC4_RX,288		.rx_ipr = BCOM_IPR_PSC4_RX,289		.tx_initiator = BCOM_INITIATOR_PSC4_TX,290		.tx_ipr = BCOM_IPR_PSC4_TX,291	},292	[4] = {293		.rx_initiator = BCOM_INITIATOR_PSC5_RX,294		.rx_ipr = BCOM_IPR_PSC5_RX,295		.tx_initiator = BCOM_INITIATOR_PSC5_TX,296		.tx_ipr = BCOM_IPR_PSC5_TX,297	},298	[5] = {299		.rx_initiator = BCOM_INITIATOR_PSC6_RX,300		.rx_ipr = BCOM_IPR_PSC6_RX,301		.tx_initiator = BCOM_INITIATOR_PSC6_TX,302		.tx_ipr = BCOM_IPR_PSC6_TX,303	},304};305 306/**307 * bcom_psc_gen_bd_rx_init - Allocate a receive bcom_task for a PSC port308 * @psc_num:	Number of the PSC to allocate a task for309 * @queue_len:	number of buffer descriptors to allocate for the task310 * @fifo:	physical address of FIFO register311 * @maxbufsize:	Maximum receive data size in bytes.312 *313 * Allocate a bestcomm task structure for receiving data from a PSC.314 */315struct bcom_task * bcom_psc_gen_bd_rx_init(unsigned psc_num, int queue_len,316					   phys_addr_t fifo, int maxbufsize)317{318	if (psc_num >= MPC52xx_PSC_MAXNUM)319		return NULL;320 321	return bcom_gen_bd_rx_init(queue_len, fifo,322				   bcom_psc_params[psc_num].rx_initiator,323				   bcom_psc_params[psc_num].rx_ipr,324				   maxbufsize);325}326EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_rx_init);327 328/**329 * bcom_psc_gen_bd_tx_init - Allocate a transmit bcom_task for a PSC port330 * @psc_num:	Number of the PSC to allocate a task for331 * @queue_len:	number of buffer descriptors to allocate for the task332 * @fifo:	physical address of FIFO register333 *334 * Allocate a bestcomm task structure for transmitting data to a PSC.335 */336struct bcom_task *337bcom_psc_gen_bd_tx_init(unsigned psc_num, int queue_len, phys_addr_t fifo)338{339	struct psc;340	return bcom_gen_bd_tx_init(queue_len, fifo,341				   bcom_psc_params[psc_num].tx_initiator,342				   bcom_psc_params[psc_num].tx_ipr);343}344EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_tx_init);345 346 347MODULE_DESCRIPTION("BestComm General Buffer Descriptor tasks driver");348MODULE_AUTHOR("Jeff Gibbons <jeff.gibbons@appspec.com>");349MODULE_LICENSE("GPL v2");350 351