Пример #1
0
int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
{
	int dpmemsz, memsz;
	u8 *dp_mem;
	unsigned long dp_offset;
	u8 *mem_addr;
	dma_addr_t dma_addr = 0;

	pr_debug("CPM uart[%d]:allocbuf\n", pinfo->port.line);

	dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos);
	dp_offset = cpm_dpalloc(dpmemsz, 8);
	if (IS_ERR_VALUE(dp_offset)) {
		printk(KERN_ERR
		       "cpm_uart_cpm1.c: could not allocate buffer descriptors\n");
		return -ENOMEM;
	}
	dp_mem = cpm_dpram_addr(dp_offset);

	memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
	    L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
	if (is_con) {
		
		
		mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
		dma_addr = (u32)cpm_dpram_phys(mem_addr);
	} else
		mem_addr = dma_alloc_coherent(pinfo->port.dev, memsz, &dma_addr,
					      GFP_KERNEL);

	if (mem_addr == NULL) {
		cpm_dpfree(dp_offset);
		printk(KERN_ERR
		       "cpm_uart_cpm1.c: could not allocate coherent memory\n");
		return -ENOMEM;
	}

	pinfo->dp_addr = dp_offset;
	pinfo->mem_addr = mem_addr;             
	pinfo->dma_addr = dma_addr;             
	pinfo->mem_size = memsz;

	pinfo->rx_buf = mem_addr;
	pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
						       * pinfo->rx_fifosize);

	pinfo->rx_bd_base = (cbd_t __iomem __force *)dp_mem;
	pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos;

	return 0;
}
Пример #2
0
/*
 * Allocate DP-Ram and memory buffers. We need to allocate a transmit and
 * receive buffer descriptors from dual port ram, and a character
 * buffer area from host mem. If we are allocating for the console we need
 * to do it from bootmem
 */
int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
{
	int dpmemsz, memsz;
	u8 *dp_mem;
	unsigned long dp_offset;
	u8 *mem_addr;
	dma_addr_t dma_addr = 0;

	pr_debug("CPM uart[%d]:allocbuf\n", pinfo->port.line);

	dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos);
	dp_offset = cpm_dpalloc(dpmemsz, 8);
	if (IS_ERR_VALUE(dp_offset)) {
		printk(KERN_ERR
		       "cpm_uart_cpm1.c: could not allocate buffer descriptors\n");
		return -ENOMEM;
	}
	dp_mem = cpm_dpram_addr(dp_offset);

	memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
	    L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
	if (is_con) {
		/* was hostalloc but changed cause it blows away the */
		/* large tlb mapping when pinning the kernel area    */
		mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
		dma_addr = (u32)cpm_dpram_phys(mem_addr);
	} else
		mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
					      GFP_KERNEL);

	if (mem_addr == NULL) {
		cpm_dpfree(dp_offset);
		printk(KERN_ERR
		       "cpm_uart_cpm1.c: could not allocate coherent memory\n");
		return -ENOMEM;
	}

	pinfo->dp_addr = dp_offset;
	pinfo->mem_addr = mem_addr;             /*  virtual address*/
	pinfo->dma_addr = dma_addr;             /*  physical address*/
	pinfo->mem_size = memsz;

	pinfo->rx_buf = mem_addr;
	pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
						       * pinfo->rx_fifosize);

	pinfo->rx_bd_base = (volatile cbd_t *)dp_mem;
	pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos;

	return 0;
}
Пример #3
0
void idma_pci9_init(void)
{
	uint dpram_offset;
	volatile idma_t *pram;
	volatile im_idma_t *idma_reg;
	volatile cpm2_map_t *immap = cpm2_immr;

	/* allocate IDMA dpram */
	dpram_offset = cpm_dpalloc(sizeof(idma_dpram_t), 64);
	idma_dpram = cpm_dpram_addr(dpram_offset); 

	/* initialize the IDMA parameter RAM */
	memset((void *)idma_dpram, 0, sizeof(idma_dpram_t));
	pram = &idma_dpram->pram;
	pram->ibase = dpram_offset + IDMA_BD_OFFSET;
	pram->dpr_buf = dpram_offset + IDMA_XFER_BUF_OFFSET;
	pram->ss_max = 32;
	pram->dts = 32;

	/* initialize the IDMA_BASE pointer to the IDMA parameter RAM */
	*((ushort *) &immap->im_dprambase[PROFF_IDMA]) = dpram_offset;

	/* initialize the IDMA registers */
	idma_reg = (volatile im_idma_t *) &immap->im_sdma.sdma_idsr1;
	idma_reg[IDMA_CHAN].idmr = 0;		/* mask all IDMA interrupts */
	idma_reg[IDMA_CHAN].idsr = 0xff;	/* clear all event flags */

	printk("<4>Using IDMA%d for MPC8260 device erratum PCI 9 workaround\n",
		IDMA_CHAN + 1);

	return;
}
Пример #4
0
/*
 * Allocate DP-Ram and memory buffers. We need to allocate a transmit and 
 * receive buffer descriptors from dual port ram, and a character
 * buffer area from host mem. If we are allocating for the console we need
 * to do it from bootmem
 */
int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
{
	int dpmemsz, memsz;
	u8 *dp_mem;
	unsigned long dp_offset;
	u8 *mem_addr;
	dma_addr_t dma_addr = 0;

	pr_debug("CPM uart[%d]:allocbuf\n", pinfo->port.line);

	dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos);
	dp_offset = cpm_dpalloc(dpmemsz, 8);
	if (IS_ERR_VALUE(dp_offset)) {
		printk(KERN_ERR
		       "cpm_uart_cpm.c: could not allocate buffer descriptors\n");
		return -ENOMEM;
	}

	dp_mem = cpm_dpram_addr(dp_offset);

	memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
	    L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
	if (is_con) {
		/* KGDB hits this before bootmem is setup */
		if (init_bootmem_done) {
			mem_addr = alloc_bootmem(memsz);
			dma_addr = virt_to_bus(mem_addr);
		} else {
			dma_addr = (dma_addr_t)lmb_alloc(memsz, 8);
			mem_addr = __va(dma_addr);
		}
	}
	else
		mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
					      GFP_KERNEL);

	if (mem_addr == NULL) {
		cpm_dpfree(dp_offset);
		printk(KERN_ERR
		       "cpm_uart_cpm.c: could not allocate coherent memory\n");
		return -ENOMEM;
	}

	pinfo->dp_addr = dp_offset;
	pinfo->mem_addr = mem_addr;
	pinfo->dma_addr = dma_addr;
	pinfo->mem_size = memsz;

	pinfo->rx_buf = mem_addr;
	pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
						       * pinfo->rx_fifosize);

	pinfo->rx_bd_base = (volatile cbd_t *)dp_mem;
	pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos;

	return 0;
}
Пример #5
0
static int allocate_bd(struct net_device *dev)
{
	struct fs_enet_private *fep = netdev_priv(dev);
	const struct fs_platform_info *fpi = fep->fpi;

	fep->ring_mem_addr = cpm_dpalloc((fpi->tx_ring + fpi->rx_ring) *
					 sizeof(cbd_t), 8);
	if (IS_ERR_VALUE(fep->ring_mem_addr))
		return -ENOMEM;

	fep->ring_base = (void __iomem __force*)
		cpm_dpram_addr(fep->ring_mem_addr);

	return 0;
}
Пример #6
0
/*
 * Allocate DP-Ram and memory buffers. We need to allocate a transmit and 
 * receive buffer descriptors from dual port ram, and a character
 * buffer area from host mem. If we are allocating for the console we need
 * to do it from bootmem
 */
int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
{
	int dpmemsz, memsz;
	u8 *dp_mem;
	uint dp_offset;
	u8 *mem_addr;
	dma_addr_t dma_addr = 0;

	pr_debug("CPM uart[%d]:allocbuf\n", pinfo->port.line);

	dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos);
	dp_offset = cpm_dpalloc(dpmemsz, 8);
	if (IS_DPERR(dp_offset)) {
		printk(KERN_ERR
		       "cpm_uart_cpm.c: could not allocate buffer descriptors\n");
		return -ENOMEM;
	}

	dp_mem = cpm_dpram_addr(dp_offset);

	memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
	    L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
	if (is_con)
		mem_addr = alloc_bootmem(memsz);
	else
		mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
					      GFP_KERNEL);

	if (mem_addr == NULL) {
		cpm_dpfree(dp_offset);
		printk(KERN_ERR
		       "cpm_uart_cpm.c: could not allocate coherent memory\n");
		return -ENOMEM;
	}

	pinfo->dp_addr = dp_offset;
	pinfo->mem_addr = mem_addr;
	pinfo->dma_addr = dma_addr;

	pinfo->rx_buf = mem_addr;
	pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
						       * pinfo->rx_fifosize);

	pinfo->rx_bd_base = (volatile cbd_t *)dp_mem;
	pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos;

	return 0;
}
Пример #7
0
/* Initialize the CPM Ethernet on SCC.  If EPPC-Bug loaded us, or performed
 * some other network I/O, a whole bunch of this has already been set up.
 * It is no big deal if we do it again, we just have to disable the
 * transmit and receive to make sure we don't catch the CPM with some
 * inconsistent control information.
 */
static int __init scc_enet_init(void)
{
	struct net_device *dev;
	struct scc_enet_private *cep;
	int i, j, k, err;
	uint dp_offset;
	unsigned char	*eap, *ba;
	dma_addr_t	mem_addr;
	bd_t		*bd;
	volatile	cbd_t		*bdp;
	volatile	cpm8xx_t	*cp;
	volatile	scc_t		*sccp;
	volatile	scc_enet_t	*ep;
	volatile	immap_t		*immap;

	cp = cpmp;	/* Get pointer to Communication Processor */

	immap = (immap_t *)(mfspr(IMMR) & 0xFFFF0000);	/* and to internal registers */

	bd = (bd_t *)__res;

	dev = alloc_etherdev(sizeof(*cep));
	if (!dev)
		return -ENOMEM;

	cep = dev->priv;
	spin_lock_init(&cep->lock);

	/* Get pointer to SCC area in parameter RAM.
	*/
	ep = (scc_enet_t *)(&cp->cp_dparam[PROFF_ENET]);

	/* And another to the SCC register area.
	*/
	sccp = (volatile scc_t *)(&cp->cp_scc[SCC_ENET]);
	cep->sccp = (scc_t *)sccp;		/* Keep the pointer handy */

	/* Disable receive and transmit in case EPPC-Bug started it.
	*/
	sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);

	/* Cookbook style from the MPC860 manual.....
	 * Not all of this is necessary if EPPC-Bug has initialized
	 * the network.
	 * So far we are lucky, all board configurations use the same
	 * pins, or at least the same I/O Port for these functions.....
	 * It can't last though......
	 */

#if (defined(PA_ENET_RXD) && defined(PA_ENET_TXD))
	/* Configure port A pins for Txd and Rxd.
	*/
	immap->im_ioport.iop_papar |=  (PA_ENET_RXD | PA_ENET_TXD);
	immap->im_ioport.iop_padir &= ~(PA_ENET_RXD | PA_ENET_TXD);
	immap->im_ioport.iop_paodr &=                ~PA_ENET_TXD;
#elif (defined(PB_ENET_RXD) && defined(PB_ENET_TXD))
	/* Configure port B pins for Txd and Rxd.
	*/
	immap->im_cpm.cp_pbpar |=  (PB_ENET_RXD | PB_ENET_TXD);
	immap->im_cpm.cp_pbdir &= ~(PB_ENET_RXD | PB_ENET_TXD);
	immap->im_cpm.cp_pbodr &=		 ~PB_ENET_TXD;
#else
#error Exactly ONE pair of PA_ENET_[RT]XD, PB_ENET_[RT]XD must be defined
#endif

#if defined(PC_ENET_LBK)
	/* Configure port C pins to disable External Loopback
	 */
	immap->im_ioport.iop_pcpar &= ~PC_ENET_LBK;
	immap->im_ioport.iop_pcdir |=  PC_ENET_LBK;
	immap->im_ioport.iop_pcso  &= ~PC_ENET_LBK;
	immap->im_ioport.iop_pcdat &= ~PC_ENET_LBK;	/* Disable Loopback */
#endif	/* PC_ENET_LBK */

#ifdef PE_ENET_TCLK
	/* Configure port E for TCLK and RCLK.
	*/
	cp->cp_pepar |=  (PE_ENET_TCLK | PE_ENET_RCLK);
	cp->cp_pedir &= ~(PE_ENET_TCLK | PE_ENET_RCLK);
	cp->cp_peso  &= ~(PE_ENET_TCLK | PE_ENET_RCLK);
#else
	/* Configure port A for TCLK and RCLK.
	*/
	immap->im_ioport.iop_papar |=  (PA_ENET_TCLK | PA_ENET_RCLK);
	immap->im_ioport.iop_padir &= ~(PA_ENET_TCLK | PA_ENET_RCLK);
#endif

	/* Configure port C pins to enable CLSN and RENA.
	*/
	immap->im_ioport.iop_pcpar &= ~(PC_ENET_CLSN | PC_ENET_RENA);
	immap->im_ioport.iop_pcdir &= ~(PC_ENET_CLSN | PC_ENET_RENA);
	immap->im_ioport.iop_pcso  |=  (PC_ENET_CLSN | PC_ENET_RENA);

	/* Configure Serial Interface clock routing.
	 * First, clear all SCC bits to zero, then set the ones we want.
	 */
	cp->cp_sicr &= ~SICR_ENET_MASK;
	cp->cp_sicr |=  SICR_ENET_CLKRT;

	/* Manual says set SDDR, but I can't find anything with that
	 * name.  I think it is a misprint, and should be SDCR.  This
	 * has already been set by the communication processor initialization.
	 */

	/* Allocate space for the buffer descriptors in the DP ram.
	 * These are relative offsets in the DP ram address space.
	 * Initialize base addresses for the buffer descriptors.
	 */
	dp_offset = cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
	ep->sen_genscc.scc_rbase = dp_offset;
	cep->rx_bd_base = cpm_dpram_addr(dp_offset);

	dp_offset = cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
	ep->sen_genscc.scc_tbase = dp_offset;
	cep->tx_bd_base = cpm_dpram_addr(dp_offset);

	cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
	cep->cur_rx = cep->rx_bd_base;

	/* Issue init Rx BD command for SCC.
	 * Manual says to perform an Init Rx parameters here.  We have
	 * to perform both Rx and Tx because the SCC may have been
	 * already running.
	 * In addition, we have to do it later because we don't yet have
	 * all of the BD control/status set properly.
	cp->cp_cpcr = mk_cr_cmd(CPM_CR_ENET, CPM_CR_INIT_RX) | CPM_CR_FLG;
	while (cp->cp_cpcr & CPM_CR_FLG);
	 */

	/* Initialize function code registers for big-endian.
	*/
	ep->sen_genscc.scc_rfcr = SCC_EB;
	ep->sen_genscc.scc_tfcr = SCC_EB;

	/* Set maximum bytes per receive buffer.
	 * This appears to be an Ethernet frame size, not the buffer
	 * fragment size.  It must be a multiple of four.
	 */
	ep->sen_genscc.scc_mrblr = PKT_MAXBLR_SIZE;

	/* Set CRC preset and mask.
	*/
	ep->sen_cpres = 0xffffffff;
	ep->sen_cmask = 0xdebb20e3;

	ep->sen_crcec = 0;	/* CRC Error counter */
	ep->sen_alec = 0;	/* alignment error counter */
	ep->sen_disfc = 0;	/* discard frame counter */

	ep->sen_pads = 0x8888;	/* Tx short frame pad character */
	ep->sen_retlim = 15;	/* Retry limit threshold */

	ep->sen_maxflr = PKT_MAXBUF_SIZE;   /* maximum frame length register */
	ep->sen_minflr = PKT_MINBUF_SIZE;  /* minimum frame length register */

	ep->sen_maxd1 = PKT_MAXBLR_SIZE;	/* maximum DMA1 length */
	ep->sen_maxd2 = PKT_MAXBLR_SIZE;	/* maximum DMA2 length */

	/* Clear hash tables.
	*/
	ep->sen_gaddr1 = 0;
	ep->sen_gaddr2 = 0;
	ep->sen_gaddr3 = 0;
	ep->sen_gaddr4 = 0;
	ep->sen_iaddr1 = 0;
	ep->sen_iaddr2 = 0;
	ep->sen_iaddr3 = 0;
	ep->sen_iaddr4 = 0;

	/* Set Ethernet station address.
	 */
	eap = (unsigned char *)&(ep->sen_paddrh);
	for (i=5; i>=0; i--)
		*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];

	ep->sen_pper = 0;	/* 'cause the book says so */
	ep->sen_taddrl = 0;	/* temp address (LSB) */
	ep->sen_taddrm = 0;
	ep->sen_taddrh = 0;	/* temp address (MSB) */

	/* Now allocate the host memory pages and initialize the
	 * buffer descriptors.
	 */
	bdp = cep->tx_bd_base;
	for (i=0; i<TX_RING_SIZE; i++) {

		/* Initialize the BD for every fragment in the page.
		*/
		bdp->cbd_sc = 0;
		bdp->cbd_bufaddr = 0;
		bdp++;
	}

	/* Set the last buffer to wrap.
	*/
	bdp--;
	bdp->cbd_sc |= BD_SC_WRAP;

	bdp = cep->rx_bd_base;
	k = 0;
	for (i=0; i<CPM_ENET_RX_PAGES; i++) {

		/* Allocate a page.
		*/
		ba = (unsigned char *)dma_alloc_coherent(NULL, PAGE_SIZE,
				&mem_addr, GFP_KERNEL);
		/* BUG: no check for failure */

		/* Initialize the BD for every fragment in the page.
		*/
		for (j=0; j<CPM_ENET_RX_FRPPG; j++) {
			bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
			bdp->cbd_bufaddr = mem_addr;
			cep->rx_vaddr[k++] = ba;
			mem_addr += CPM_ENET_RX_FRSIZE;
			ba += CPM_ENET_RX_FRSIZE;
			bdp++;
		}
	}

	/* Set the last buffer to wrap.
	*/
	bdp--;
	bdp->cbd_sc |= BD_SC_WRAP;

	/* Let's re-initialize the channel now.  We have to do it later
	 * than the manual describes because we have just now finished
	 * the BD initialization.
	 */
	cp->cp_cpcr = mk_cr_cmd(CPM_CR_ENET, CPM_CR_INIT_TRX) | CPM_CR_FLG;
	while (cp->cp_cpcr & CPM_CR_FLG);

	cep->skb_cur = cep->skb_dirty = 0;

	sccp->scc_scce = 0xffff;	/* Clear any pending events */

	/* Enable interrupts for transmit error, complete frame
	 * received, and any transmit buffer we have also set the
	 * interrupt flag.
	 */
	sccp->scc_sccm = (SCCE_ENET_TXE | SCCE_ENET_RXF | SCCE_ENET_TXB);

	/* Install our interrupt handler.
	*/
	cpm_install_handler(CPMVEC_ENET, scc_enet_interrupt, dev);

	/* Set GSMR_H to enable all normal operating modes.
	 * Set GSMR_L to enable Ethernet to MC68160.
	 */
	sccp->scc_gsmrh = 0;
	sccp->scc_gsmrl = (SCC_GSMRL_TCI | SCC_GSMRL_TPL_48 | SCC_GSMRL_TPP_10 | SCC_GSMRL_MODE_ENET);

	/* Set sync/delimiters.
	*/
	sccp->scc_dsr = 0xd555;

	/* Set processing mode.  Use Ethernet CRC, catch broadcast, and
	 * start frame search 22 bit times after RENA.
	 */
	sccp->scc_psmr = (SCC_PSMR_ENCRC | SCC_PSMR_NIB22);

	/* It is now OK to enable the Ethernet transmitter.
	 * Unfortunately, there are board implementation differences here.
	 */
#if   (!defined (PB_ENET_TENA) &&  defined (PC_ENET_TENA) && !defined (PE_ENET_TENA))
	immap->im_ioport.iop_pcpar |=  PC_ENET_TENA;
	immap->im_ioport.iop_pcdir &= ~PC_ENET_TENA;
#elif ( defined (PB_ENET_TENA) && !defined (PC_ENET_TENA) && !defined (PE_ENET_TENA))
	cp->cp_pbpar |= PB_ENET_TENA;
	cp->cp_pbdir |= PB_ENET_TENA;
#elif ( !defined (PB_ENET_TENA) && !defined (PC_ENET_TENA) && defined (PE_ENET_TENA))
	cp->cp_pepar |=  PE_ENET_TENA;
	cp->cp_pedir &= ~PE_ENET_TENA;
	cp->cp_peso  |=  PE_ENET_TENA;
#else
#error Configuration Error: define exactly ONE of PB_ENET_TENA, PC_ENET_TENA, PE_ENET_TENA
#endif

#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
	/* And while we are here, set the configuration to enable ethernet.
	*/
	*((volatile uint *)RPX_CSR_ADDR) &= ~BCSR0_ETHLPBK;
	*((volatile uint *)RPX_CSR_ADDR) |=
			(BCSR0_ETHEN | BCSR0_COLTESTDIS | BCSR0_FULLDPLXDIS);
#endif

#ifdef CONFIG_BSEIP
	/* BSE uses port B and C for PHY control.
	*/
	cp->cp_pbpar &= ~(PB_BSE_POWERUP | PB_BSE_FDXDIS);
	cp->cp_pbdir |= (PB_BSE_POWERUP | PB_BSE_FDXDIS);
	cp->cp_pbdat |= (PB_BSE_POWERUP | PB_BSE_FDXDIS);

	immap->im_ioport.iop_pcpar &= ~PC_BSE_LOOPBACK;
	immap->im_ioport.iop_pcdir |= PC_BSE_LOOPBACK;
	immap->im_ioport.iop_pcso &= ~PC_BSE_LOOPBACK;
	immap->im_ioport.iop_pcdat &= ~PC_BSE_LOOPBACK;
#endif

#ifdef CONFIG_FADS
	cp->cp_pbpar |= PB_ENET_TENA;
	cp->cp_pbdir |= PB_ENET_TENA;

	/* Enable the EEST PHY.
	*/
	*((volatile uint *)BCSR1) &= ~BCSR1_ETHEN;
#endif

#ifdef CONFIG_MPC885ADS

	/* Deassert PHY reset and enable the PHY.
	 */
	{
		volatile uint __iomem *bcsr = ioremap(BCSR_ADDR, BCSR_SIZE);
		uint tmp;

		tmp = in_be32(bcsr + 1 /* BCSR1 */);
		tmp |= BCSR1_ETHEN;
		out_be32(bcsr + 1, tmp);
		tmp = in_be32(bcsr + 4 /* BCSR4 */);
		tmp |= BCSR4_ETH10_RST;
		out_be32(bcsr + 4, tmp);
		iounmap(bcsr);
	}

	/* On MPC885ADS SCC ethernet PHY defaults to the full duplex mode
	 * upon reset. SCC is set to half duplex by default. So this
	 * inconsistency should be better fixed by the software.
	 */
#endif

	dev->base_addr = (unsigned long)ep;
#if 0
	dev->name = "CPM_ENET";
#endif

	/* The CPM Ethernet specific entries in the device structure. */
	dev->open = scc_enet_open;
	dev->hard_start_xmit = scc_enet_start_xmit;
	dev->tx_timeout = scc_enet_timeout;
	dev->watchdog_timeo = TX_TIMEOUT;
	dev->stop = scc_enet_close;
	dev->get_stats = scc_enet_get_stats;
	dev->set_multicast_list = set_multicast_list;

	err = register_netdev(dev);
	if (err) {
		free_netdev(dev);
		return err;
	}

	/* And last, enable the transmit and receive processing.
	*/
	sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);

	printk("%s: CPM ENET Version 0.2 on SCC%d, ", dev->name, SCC_ENET+1);
	for (i=0; i<5; i++)
		printk("%02x:", dev->dev_addr[i]);
	printk("%02x\n", dev->dev_addr[5]);

	return 0;
}
Пример #8
0
/* Initialize the CPM Ethernet on SCC.
 */
static int __init scc_enet_init(void)
{
    struct net_device *dev;
    struct scc_enet_private *cep;
    int i, j, err;
    uint dp_offset;
    unsigned char	*eap;
    unsigned long	mem_addr;
    bd_t		*bd;
    volatile	cbd_t		*bdp;
    volatile	cpm_cpm2_t	*cp;
    volatile	scc_t		*sccp;
    volatile	scc_enet_t	*ep;
    volatile	cpm2_map_t		*immap;
    volatile	iop_cpm2_t	*io;

    cp = cpmp;	/* Get pointer to Communication Processor */

    immap = (cpm2_map_t *)CPM_MAP_ADDR;	/* and to internal registers */
    io = &immap->im_ioport;

    bd = (bd_t *)__res;

    /* Create an Ethernet device instance.
    */
    dev = alloc_etherdev(sizeof(*cep));
    if (!dev)
        return -ENOMEM;

    cep = dev->priv;
    spin_lock_init(&cep->lock);

    /* Get pointer to SCC area in parameter RAM.
    */
    ep = (scc_enet_t *)(&immap->im_dprambase[PROFF_ENET]);

    /* And another to the SCC register area.
    */
    sccp = (volatile scc_t *)(&immap->im_scc[SCC_ENET]);
    cep->sccp = (scc_t *)sccp;		/* Keep the pointer handy */

    /* Disable receive and transmit in case someone left it running.
    */
    sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);

    /* Configure port C and D pins for SCC Ethernet.  This
     * won't work for all SCC possibilities....it will be
     * board/port specific.
     */
    io->iop_pparc |=
        (PC_ENET_RENA | PC_ENET_CLSN | PC_ENET_TXCLK | PC_ENET_RXCLK);
    io->iop_pdirc &=
        ~(PC_ENET_RENA | PC_ENET_CLSN | PC_ENET_TXCLK | PC_ENET_RXCLK);
    io->iop_psorc &=
        ~(PC_ENET_RENA | PC_ENET_TXCLK | PC_ENET_RXCLK);
    io->iop_psorc |= PC_ENET_CLSN;

    io->iop_ppard |= (PD_ENET_RXD | PD_ENET_TXD | PD_ENET_TENA);
    io->iop_pdird |= (PD_ENET_TXD | PD_ENET_TENA);
    io->iop_pdird &= ~PD_ENET_RXD;
    io->iop_psord |= PD_ENET_TXD;
    io->iop_psord &= ~(PD_ENET_RXD | PD_ENET_TENA);

    /* Configure Serial Interface clock routing.
     * First, clear all SCC bits to zero, then set the ones we want.
     */
    immap->im_cpmux.cmx_scr &= ~CMX_CLK_MASK;
    immap->im_cpmux.cmx_scr |= CMX_CLK_ROUTE;

    /* Allocate space for the buffer descriptors in the DP ram.
     * These are relative offsets in the DP ram address space.
     * Initialize base addresses for the buffer descriptors.
     */
    dp_offset = cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
    ep->sen_genscc.scc_rbase = dp_offset;
    cep->rx_bd_base = (cbd_t *)cpm_dpram_addr(dp_offset);

    dp_offset = cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
    ep->sen_genscc.scc_tbase = dp_offset;
    cep->tx_bd_base = (cbd_t *)cpm_dpram_addr(dp_offset);

    cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
    cep->cur_rx = cep->rx_bd_base;

    ep->sen_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
    ep->sen_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;

    /* Set maximum bytes per receive buffer.
     * This appears to be an Ethernet frame size, not the buffer
     * fragment size.  It must be a multiple of four.
     */
    ep->sen_genscc.scc_mrblr = PKT_MAXBLR_SIZE;

    /* Set CRC preset and mask.
    */
    ep->sen_cpres = 0xffffffff;
    ep->sen_cmask = 0xdebb20e3;

    ep->sen_crcec = 0;	/* CRC Error counter */
    ep->sen_alec = 0;	/* alignment error counter */
    ep->sen_disfc = 0;	/* discard frame counter */

    ep->sen_pads = 0x8888;	/* Tx short frame pad character */
    ep->sen_retlim = 15;	/* Retry limit threshold */

    ep->sen_maxflr = PKT_MAXBUF_SIZE;   /* maximum frame length register */
    ep->sen_minflr = PKT_MINBUF_SIZE;  /* minimum frame length register */

    ep->sen_maxd1 = PKT_MAXBLR_SIZE;	/* maximum DMA1 length */
    ep->sen_maxd2 = PKT_MAXBLR_SIZE;	/* maximum DMA2 length */

    /* Clear hash tables.
    */
    ep->sen_gaddr1 = 0;
    ep->sen_gaddr2 = 0;
    ep->sen_gaddr3 = 0;
    ep->sen_gaddr4 = 0;
    ep->sen_iaddr1 = 0;
    ep->sen_iaddr2 = 0;
    ep->sen_iaddr3 = 0;
    ep->sen_iaddr4 = 0;

    /* Set Ethernet station address.
     *
     * This is supplied in the board information structure, so we
     * copy that into the controller.
     */
    eap = (unsigned char *)&(ep->sen_paddrh);
    for (i=5; i>=0; i--)
        *eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];

    ep->sen_pper = 0;	/* 'cause the book says so */
    ep->sen_taddrl = 0;	/* temp address (LSB) */
    ep->sen_taddrm = 0;
    ep->sen_taddrh = 0;	/* temp address (MSB) */

    /* Now allocate the host memory pages and initialize the
     * buffer descriptors.
     */
    bdp = cep->tx_bd_base;
    for (i=0; i<TX_RING_SIZE; i++) {

        /* Initialize the BD for every fragment in the page.
        */
        bdp->cbd_sc = 0;
        bdp->cbd_bufaddr = 0;
        bdp++;
    }

    /* Set the last buffer to wrap.
    */
    bdp--;
    bdp->cbd_sc |= BD_SC_WRAP;

    bdp = cep->rx_bd_base;
    for (i=0; i<CPM_ENET_RX_PAGES; i++) {

        /* Allocate a page.
        */
        mem_addr = __get_free_page(GFP_KERNEL);
        /* BUG: no check for failure */

        /* Initialize the BD for every fragment in the page.
        */
        for (j=0; j<CPM_ENET_RX_FRPPG; j++) {
            bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
            bdp->cbd_bufaddr = __pa(mem_addr);
            mem_addr += CPM_ENET_RX_FRSIZE;
            bdp++;
        }
    }

    /* Set the last buffer to wrap.
    */
    bdp--;
    bdp->cbd_sc |= BD_SC_WRAP;

    /* Let's re-initialize the channel now.  We have to do it later
     * than the manual describes because we have just now finished
     * the BD initialization.
     */
    cpmp->cp_cpcr = mk_cr_cmd(CPM_ENET_PAGE, CPM_ENET_BLOCK, 0,
                              CPM_CR_INIT_TRX) | CPM_CR_FLG;
    while (cp->cp_cpcr & CPM_CR_FLG);

    cep->skb_cur = cep->skb_dirty = 0;

    sccp->scc_scce = 0xffff;	/* Clear any pending events */

    /* Enable interrupts for transmit error, complete frame
     * received, and any transmit buffer we have also set the
     * interrupt flag.
     */
    sccp->scc_sccm = (SCCE_ENET_TXE | SCCE_ENET_RXF | SCCE_ENET_TXB);

    /* Install our interrupt handler.
    */
    request_irq(SIU_INT_ENET, scc_enet_interrupt, 0, "enet", dev);
    /* BUG: no check for failure */

    /* Set GSMR_H to enable all normal operating modes.
     * Set GSMR_L to enable Ethernet to MC68160.
     */
    sccp->scc_gsmrh = 0;
    sccp->scc_gsmrl = (SCC_GSMRL_TCI | SCC_GSMRL_TPL_48 | SCC_GSMRL_TPP_10 | SCC_GSMRL_MODE_ENET);

    /* Set sync/delimiters.
    */
    sccp->scc_dsr = 0xd555;

    /* Set processing mode.  Use Ethernet CRC, catch broadcast, and
     * start frame search 22 bit times after RENA.
     */
    sccp->scc_psmr = (SCC_PSMR_ENCRC | SCC_PSMR_NIB22);

    /* It is now OK to enable the Ethernet transmitter.
     * Unfortunately, there are board implementation differences here.
     */
    io->iop_pparc &= ~(PC_EST8260_ENET_LOOPBACK |
                       PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
    io->iop_psorc &= ~(PC_EST8260_ENET_LOOPBACK |
                       PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
    io->iop_pdirc |= (PC_EST8260_ENET_LOOPBACK |
                      PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
    io->iop_pdatc &= ~(PC_EST8260_ENET_LOOPBACK | PC_EST8260_ENET_SQE);
    io->iop_pdatc |= PC_EST8260_ENET_NOTFD;

    dev->base_addr = (unsigned long)ep;

    /* The CPM Ethernet specific entries in the device structure. */
    dev->open = scc_enet_open;
    dev->hard_start_xmit = scc_enet_start_xmit;
    dev->tx_timeout = scc_enet_timeout;
    dev->watchdog_timeo = TX_TIMEOUT;
    dev->stop = scc_enet_close;
    dev->get_stats = scc_enet_get_stats;
    dev->set_multicast_list = set_multicast_list;

    /* And last, enable the transmit and receive processing.
    */
    sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);

    err = register_netdev(dev);
    if (err) {
        free_netdev(dev);
        return err;
    }

    printk("%s: SCC ENET Version 0.1, ", dev->name);
    for (i=0; i<5; i++)
        printk("%02x:", dev->dev_addr[i]);
    printk("%02x\n", dev->dev_addr[5]);

    return 0;
}
Пример #9
0
static int __init fs_enet_of_init(void)
{
	struct device_node *np;
	unsigned int i;
	struct platform_device *fs_enet_dev;
	struct resource res;
	int ret;

	for (np = NULL, i = 0;
	     (np = of_find_compatible_node(np, "network", "fs_enet")) != NULL;
	     i++) {
		struct resource r[4];
		struct device_node *phy, *mdio;
		struct fs_platform_info fs_enet_data;
		const unsigned int *id, *phy_addr, *phy_irq;
		const void *mac_addr;
		const phandle *ph;
		const char *model;

		memset(r, 0, sizeof(r));
		memset(&fs_enet_data, 0, sizeof(fs_enet_data));

		ret = of_address_to_resource(np, 0, &r[0]);
		if (ret)
			goto err;
		r[0].name = fcc_regs;

		ret = of_address_to_resource(np, 1, &r[1]);
		if (ret)
			goto err;
		r[1].name = fcc_pram;

		ret = of_address_to_resource(np, 2, &r[2]);
		if (ret)
			goto err;
		r[2].name = fcc_regs_c;
		fs_enet_data.fcc_regs_c = r[2].start;

		of_irq_to_resource(np, 0, &r[3]);

		fs_enet_dev =
		    platform_device_register_simple("fsl-cpm-fcc", i, &r[0], 4);

		if (IS_ERR(fs_enet_dev)) {
			ret = PTR_ERR(fs_enet_dev);
			goto err;
		}

		model = of_get_property(np, "model", NULL);
		if (model == NULL) {
			ret = -ENODEV;
			goto unreg;
		}

		mac_addr = of_get_mac_address(np);
		if (mac_addr)
			memcpy(fs_enet_data.macaddr, mac_addr, 6);

		ph = of_get_property(np, "phy-handle", NULL);
		phy = of_find_node_by_phandle(*ph);

		if (phy == NULL) {
			ret = -ENODEV;
			goto unreg;
		}

		phy_addr = of_get_property(phy, "reg", NULL);
		fs_enet_data.phy_addr = *phy_addr;

		phy_irq = of_get_property(phy, "interrupts", NULL);

		id = of_get_property(np, "device-id", NULL);
		fs_enet_data.fs_no = *id;
		strcpy(fs_enet_data.fs_type, model);

		mdio = of_get_parent(phy);
                ret = of_address_to_resource(mdio, 0, &res);
                if (ret) {
                        of_node_put(phy);
                        of_node_put(mdio);
                        goto unreg;
                }

		fs_enet_data.clk_rx = *((u32 *)of_get_property(np,
						"rx-clock", NULL));
		fs_enet_data.clk_tx = *((u32 *)of_get_property(np,
						"tx-clock", NULL));

		if (strstr(model, "FCC")) {
			int fcc_index = *id - 1;
			const unsigned char *mdio_bb_prop;

			fs_enet_data.dpram_offset = (u32)cpm_dpram_addr(0);
			fs_enet_data.rx_ring = 32;
			fs_enet_data.tx_ring = 32;
			fs_enet_data.rx_copybreak = 240;
			fs_enet_data.use_napi = 0;
			fs_enet_data.napi_weight = 17;
			fs_enet_data.mem_offset = FCC_MEM_OFFSET(fcc_index);
			fs_enet_data.cp_page = CPM_CR_FCC_PAGE(fcc_index);
			fs_enet_data.cp_block = CPM_CR_FCC_SBLOCK(fcc_index);

			snprintf((char*)&bus_id[(*id)], BUS_ID_SIZE, "%x:%02x",
							(u32)res.start, fs_enet_data.phy_addr);
			fs_enet_data.bus_id = (char*)&bus_id[(*id)];
			fs_enet_data.init_ioports = init_fcc_ioports;

			mdio_bb_prop = of_get_property(phy, "bitbang", NULL);
			if (mdio_bb_prop) {
				struct platform_device *fs_enet_mdio_bb_dev;
				struct fs_mii_bb_platform_info fs_enet_mdio_bb_data;

				fs_enet_mdio_bb_dev =
					platform_device_register_simple("fsl-bb-mdio",
							i, NULL, 0);
				memset(&fs_enet_mdio_bb_data, 0,
						sizeof(struct fs_mii_bb_platform_info));
				fs_enet_mdio_bb_data.mdio_dat.bit =
					mdio_bb_prop[0];
				fs_enet_mdio_bb_data.mdio_dir.bit =
					mdio_bb_prop[1];
				fs_enet_mdio_bb_data.mdc_dat.bit =
					mdio_bb_prop[2];
				fs_enet_mdio_bb_data.mdio_port =
					mdio_bb_prop[3];
				fs_enet_mdio_bb_data.mdc_port =
					mdio_bb_prop[4];
				fs_enet_mdio_bb_data.delay =
					mdio_bb_prop[5];

				fs_enet_mdio_bb_data.irq[0] = phy_irq[0];
				fs_enet_mdio_bb_data.irq[1] = -1;
				fs_enet_mdio_bb_data.irq[2] = -1;
				fs_enet_mdio_bb_data.irq[3] = phy_irq[0];
				fs_enet_mdio_bb_data.irq[31] = -1;

				fs_enet_mdio_bb_data.mdio_dat.offset =
					(u32)&cpm2_immr->im_ioport.iop_pdatc;
				fs_enet_mdio_bb_data.mdio_dir.offset =
					(u32)&cpm2_immr->im_ioport.iop_pdirc;
				fs_enet_mdio_bb_data.mdc_dat.offset =
					(u32)&cpm2_immr->im_ioport.iop_pdatc;

				ret = platform_device_add_data(
						fs_enet_mdio_bb_dev,
						&fs_enet_mdio_bb_data,
						sizeof(struct fs_mii_bb_platform_info));
				if (ret)
					goto unreg;
			}

			of_node_put(phy);
			of_node_put(mdio);

			ret = platform_device_add_data(fs_enet_dev, &fs_enet_data,
						     sizeof(struct
							    fs_platform_info));
			if (ret)
				goto unreg;
		}
	}
	return 0;

unreg:
	platform_device_unregister(fs_enet_dev);
err:
	return ret;
}