Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Driver for MPC52xx processor BestComm General Buffer Descriptor
0004  *
0005  * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>
0006  * Copyright (C) 2006 AppSpec Computer Technologies Corp.
0007  *                    Jeff Gibbons <jeff.gibbons@appspec.com>
0008  */
0009 
0010 #include <linux/module.h>
0011 #include <linux/kernel.h>
0012 #include <linux/string.h>
0013 #include <linux/types.h>
0014 #include <asm/errno.h>
0015 #include <asm/io.h>
0016 
0017 #include <asm/mpc52xx.h>
0018 #include <asm/mpc52xx_psc.h>
0019 
0020 #include <linux/fsl/bestcomm/bestcomm.h>
0021 #include <linux/fsl/bestcomm/bestcomm_priv.h>
0022 #include <linux/fsl/bestcomm/gen_bd.h>
0023 
0024 
0025 /* ======================================================================== */
0026 /* Task image/var/inc                                                       */
0027 /* ======================================================================== */
0028 
0029 /* gen_bd tasks images */
0030 extern u32 bcom_gen_bd_rx_task[];
0031 extern u32 bcom_gen_bd_tx_task[];
0032 
0033 /* rx task vars that need to be set before enabling the task */
0034 struct bcom_gen_bd_rx_var {
0035     u32 enable;     /* (u16*) address of task's control register */
0036     u32 fifo;       /* (u32*) address of gen_bd's fifo */
0037     u32 bd_base;        /* (struct bcom_bd*) beginning of ring buffer */
0038     u32 bd_last;        /* (struct bcom_bd*) end of ring buffer */
0039     u32 bd_start;       /* (struct bcom_bd*) current bd */
0040     u32 buffer_size;    /* size of receive buffer */
0041 };
0042 
0043 /* rx task incs that need to be set before enabling the task */
0044 struct bcom_gen_bd_rx_inc {
0045     u16 pad0;
0046     s16 incr_bytes;
0047     u16 pad1;
0048     s16 incr_dst;
0049 };
0050 
0051 /* tx task vars that need to be set before enabling the task */
0052 struct bcom_gen_bd_tx_var {
0053     u32 fifo;       /* (u32*) address of gen_bd's fifo */
0054     u32 enable;     /* (u16*) address of task's control register */
0055     u32 bd_base;        /* (struct bcom_bd*) beginning of ring buffer */
0056     u32 bd_last;        /* (struct bcom_bd*) end of ring buffer */
0057     u32 bd_start;       /* (struct bcom_bd*) current bd */
0058     u32 buffer_size;    /* set by uCode for each packet */
0059 };
0060 
0061 /* tx task incs that need to be set before enabling the task */
0062 struct bcom_gen_bd_tx_inc {
0063     u16 pad0;
0064     s16 incr_bytes;
0065     u16 pad1;
0066     s16 incr_src;
0067     u16 pad2;
0068     s16 incr_src_ma;
0069 };
0070 
0071 /* private structure */
0072 struct bcom_gen_bd_priv {
0073     phys_addr_t fifo;
0074     int     initiator;
0075     int     ipr;
0076     int     maxbufsize;
0077 };
0078 
0079 
0080 /* ======================================================================== */
0081 /* Task support code                                                        */
0082 /* ======================================================================== */
0083 
0084 struct bcom_task *
0085 bcom_gen_bd_rx_init(int queue_len, phys_addr_t fifo,
0086             int initiator, int ipr, int maxbufsize)
0087 {
0088     struct bcom_task *tsk;
0089     struct bcom_gen_bd_priv *priv;
0090 
0091     tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),
0092             sizeof(struct bcom_gen_bd_priv));
0093     if (!tsk)
0094         return NULL;
0095 
0096     tsk->flags = BCOM_FLAGS_NONE;
0097 
0098     priv = tsk->priv;
0099     priv->fifo  = fifo;
0100     priv->initiator = initiator;
0101     priv->ipr   = ipr;
0102     priv->maxbufsize = maxbufsize;
0103 
0104     if (bcom_gen_bd_rx_reset(tsk)) {
0105         bcom_task_free(tsk);
0106         return NULL;
0107     }
0108 
0109     return tsk;
0110 }
0111 EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_init);
0112 
0113 int
0114 bcom_gen_bd_rx_reset(struct bcom_task *tsk)
0115 {
0116     struct bcom_gen_bd_priv *priv = tsk->priv;
0117     struct bcom_gen_bd_rx_var *var;
0118     struct bcom_gen_bd_rx_inc *inc;
0119 
0120     /* Shutdown the task */
0121     bcom_disable_task(tsk->tasknum);
0122 
0123     /* Reset the microcode */
0124     var = (struct bcom_gen_bd_rx_var *) bcom_task_var(tsk->tasknum);
0125     inc = (struct bcom_gen_bd_rx_inc *) bcom_task_inc(tsk->tasknum);
0126 
0127     if (bcom_load_image(tsk->tasknum, bcom_gen_bd_rx_task))
0128         return -1;
0129 
0130     var->enable = bcom_eng->regs_base +
0131                 offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
0132     var->fifo   = (u32) priv->fifo;
0133     var->bd_base    = tsk->bd_pa;
0134     var->bd_last    = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
0135     var->bd_start   = tsk->bd_pa;
0136     var->buffer_size = priv->maxbufsize;
0137 
0138     inc->incr_bytes = -(s16)sizeof(u32);
0139     inc->incr_dst   = sizeof(u32);
0140 
0141     /* Reset the BDs */
0142     tsk->index = 0;
0143     tsk->outdex = 0;
0144 
0145     memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
0146 
0147     /* Configure some stuff */
0148     bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_RX_BD_PRAGMA);
0149     bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
0150 
0151     out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);
0152     bcom_set_initiator(tsk->tasknum, priv->initiator);
0153 
0154     out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum);    /* Clear ints */
0155 
0156     return 0;
0157 }
0158 EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_reset);
0159 
0160 void
0161 bcom_gen_bd_rx_release(struct bcom_task *tsk)
0162 {
0163     /* Nothing special for the GenBD tasks */
0164     bcom_task_free(tsk);
0165 }
0166 EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_release);
0167 
0168 
0169 extern struct bcom_task *
0170 bcom_gen_bd_tx_init(int queue_len, phys_addr_t fifo,
0171             int initiator, int ipr)
0172 {
0173     struct bcom_task *tsk;
0174     struct bcom_gen_bd_priv *priv;
0175 
0176     tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),
0177             sizeof(struct bcom_gen_bd_priv));
0178     if (!tsk)
0179         return NULL;
0180 
0181     tsk->flags = BCOM_FLAGS_NONE;
0182 
0183     priv = tsk->priv;
0184     priv->fifo  = fifo;
0185     priv->initiator = initiator;
0186     priv->ipr   = ipr;
0187 
0188     if (bcom_gen_bd_tx_reset(tsk)) {
0189         bcom_task_free(tsk);
0190         return NULL;
0191     }
0192 
0193     return tsk;
0194 }
0195 EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_init);
0196 
0197 int
0198 bcom_gen_bd_tx_reset(struct bcom_task *tsk)
0199 {
0200     struct bcom_gen_bd_priv *priv = tsk->priv;
0201     struct bcom_gen_bd_tx_var *var;
0202     struct bcom_gen_bd_tx_inc *inc;
0203 
0204     /* Shutdown the task */
0205     bcom_disable_task(tsk->tasknum);
0206 
0207     /* Reset the microcode */
0208     var = (struct bcom_gen_bd_tx_var *) bcom_task_var(tsk->tasknum);
0209     inc = (struct bcom_gen_bd_tx_inc *) bcom_task_inc(tsk->tasknum);
0210 
0211     if (bcom_load_image(tsk->tasknum, bcom_gen_bd_tx_task))
0212         return -1;
0213 
0214     var->enable = bcom_eng->regs_base +
0215                 offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
0216     var->fifo   = (u32) priv->fifo;
0217     var->bd_base    = tsk->bd_pa;
0218     var->bd_last    = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
0219     var->bd_start   = tsk->bd_pa;
0220 
0221     inc->incr_bytes = -(s16)sizeof(u32);
0222     inc->incr_src   = sizeof(u32);
0223     inc->incr_src_ma = sizeof(u8);
0224 
0225     /* Reset the BDs */
0226     tsk->index = 0;
0227     tsk->outdex = 0;
0228 
0229     memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
0230 
0231     /* Configure some stuff */
0232     bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_TX_BD_PRAGMA);
0233     bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
0234 
0235     out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);
0236     bcom_set_initiator(tsk->tasknum, priv->initiator);
0237 
0238     out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum);    /* Clear ints */
0239 
0240     return 0;
0241 }
0242 EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_reset);
0243 
0244 void
0245 bcom_gen_bd_tx_release(struct bcom_task *tsk)
0246 {
0247     /* Nothing special for the GenBD tasks */
0248     bcom_task_free(tsk);
0249 }
0250 EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_release);
0251 
0252 /* ---------------------------------------------------------------------
0253  * PSC support code
0254  */
0255 
0256 /**
0257  * bcom_psc_parameters - Bestcomm initialization value table for PSC devices
0258  *
0259  * This structure is only used internally.  It is a lookup table for PSC
0260  * specific parameters to bestcomm tasks.
0261  */
0262 static struct bcom_psc_params {
0263     int rx_initiator;
0264     int rx_ipr;
0265     int tx_initiator;
0266     int tx_ipr;
0267 } bcom_psc_params[] = {
0268     [0] = {
0269         .rx_initiator = BCOM_INITIATOR_PSC1_RX,
0270         .rx_ipr = BCOM_IPR_PSC1_RX,
0271         .tx_initiator = BCOM_INITIATOR_PSC1_TX,
0272         .tx_ipr = BCOM_IPR_PSC1_TX,
0273     },
0274     [1] = {
0275         .rx_initiator = BCOM_INITIATOR_PSC2_RX,
0276         .rx_ipr = BCOM_IPR_PSC2_RX,
0277         .tx_initiator = BCOM_INITIATOR_PSC2_TX,
0278         .tx_ipr = BCOM_IPR_PSC2_TX,
0279     },
0280     [2] = {
0281         .rx_initiator = BCOM_INITIATOR_PSC3_RX,
0282         .rx_ipr = BCOM_IPR_PSC3_RX,
0283         .tx_initiator = BCOM_INITIATOR_PSC3_TX,
0284         .tx_ipr = BCOM_IPR_PSC3_TX,
0285     },
0286     [3] = {
0287         .rx_initiator = BCOM_INITIATOR_PSC4_RX,
0288         .rx_ipr = BCOM_IPR_PSC4_RX,
0289         .tx_initiator = BCOM_INITIATOR_PSC4_TX,
0290         .tx_ipr = BCOM_IPR_PSC4_TX,
0291     },
0292     [4] = {
0293         .rx_initiator = BCOM_INITIATOR_PSC5_RX,
0294         .rx_ipr = BCOM_IPR_PSC5_RX,
0295         .tx_initiator = BCOM_INITIATOR_PSC5_TX,
0296         .tx_ipr = BCOM_IPR_PSC5_TX,
0297     },
0298     [5] = {
0299         .rx_initiator = BCOM_INITIATOR_PSC6_RX,
0300         .rx_ipr = BCOM_IPR_PSC6_RX,
0301         .tx_initiator = BCOM_INITIATOR_PSC6_TX,
0302         .tx_ipr = BCOM_IPR_PSC6_TX,
0303     },
0304 };
0305 
0306 /**
0307  * bcom_psc_gen_bd_rx_init - Allocate a receive bcom_task for a PSC port
0308  * @psc_num:    Number of the PSC to allocate a task for
0309  * @queue_len:  number of buffer descriptors to allocate for the task
0310  * @fifo:   physical address of FIFO register
0311  * @maxbufsize: Maximum receive data size in bytes.
0312  *
0313  * Allocate a bestcomm task structure for receiving data from a PSC.
0314  */
0315 struct bcom_task * bcom_psc_gen_bd_rx_init(unsigned psc_num, int queue_len,
0316                        phys_addr_t fifo, int maxbufsize)
0317 {
0318     if (psc_num >= MPC52xx_PSC_MAXNUM)
0319         return NULL;
0320 
0321     return bcom_gen_bd_rx_init(queue_len, fifo,
0322                    bcom_psc_params[psc_num].rx_initiator,
0323                    bcom_psc_params[psc_num].rx_ipr,
0324                    maxbufsize);
0325 }
0326 EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_rx_init);
0327 
0328 /**
0329  * bcom_psc_gen_bd_tx_init - Allocate a transmit bcom_task for a PSC port
0330  * @psc_num:    Number of the PSC to allocate a task for
0331  * @queue_len:  number of buffer descriptors to allocate for the task
0332  * @fifo:   physical address of FIFO register
0333  *
0334  * Allocate a bestcomm task structure for transmitting data to a PSC.
0335  */
0336 struct bcom_task *
0337 bcom_psc_gen_bd_tx_init(unsigned psc_num, int queue_len, phys_addr_t fifo)
0338 {
0339     struct psc;
0340     return bcom_gen_bd_tx_init(queue_len, fifo,
0341                    bcom_psc_params[psc_num].tx_initiator,
0342                    bcom_psc_params[psc_num].tx_ipr);
0343 }
0344 EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_tx_init);
0345 
0346 
0347 MODULE_DESCRIPTION("BestComm General Buffer Descriptor tasks driver");
0348 MODULE_AUTHOR("Jeff Gibbons <jeff.gibbons@appspec.com>");
0349 MODULE_LICENSE("GPL v2");
0350