Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 42dc75c4 authored by Vitaly Bordug's avatar Vitaly Bordug Committed by Paul Mackerras
Browse files

[PATCH] ppc32: MPC885ADS, MPC866ADS and MPC8272ADS-specific platform stuff for fs_enet



Added proper ppc_sys identification and fs_platform_info's for MPC 885ADS,
866ADS and 8272ADS, utilizing function assignment to remove/do not use
platform devices which conflict with PD-incompatible drivers.

Signed-off-by: default avatarVitaly Bordug <vbordug@ru.mvista.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent b9289175
Loading
Loading
Loading
Loading
+47 −0
Original line number Diff line number Diff line
@@ -481,6 +481,53 @@ config WINCEPT

endchoice

menu "Freescale Ethernet driver platform-specific options"
	depends on FS_ENET

	config MPC8xx_SECOND_ETH
	bool "Second Ethernet channel"
	depends on (MPC885ADS || MPC86XADS)
	default y
	help
	  This enables support for second Ethernet on MPC885ADS and MPC86xADS boards.
	  The latter will use SCC1, for 885ADS you can select it below.

	choice
		prompt "Second Ethernet channel"
		depends on MPC8xx_SECOND_ETH
		default MPC8xx_SECOND_ETH_FEC2

		config MPC8xx_SECOND_ETH_FEC2
		bool "FEC2"
		depends on MPC885ADS
		help
		  Enable FEC2 to serve as 2-nd Ethernet channel. Note that SMC2
		  (often 2-nd UART) will not work if this is enabled.

		config MPC8xx_SECOND_ETH_SCC1
		bool "SCC1"
		depends on MPC86XADS
		select MPC8xx_SCC_ENET_FIXED
		help
		  Enable SCC1 to serve as 2-nd Ethernet channel. Note that SMC1
		  (often 1-nd UART) will not work if this is enabled.

		config MPC8xx_SECOND_ETH_SCC3
		bool "SCC3"
		depends on MPC885ADS
		help
		  Enable SCC3 to serve as 2-nd Ethernet channel. Note that SMC1
		  (often 1-nd UART) will not work if this is enabled.

	endchoice

	config MPC8xx_SCC_ENET_FIXED
	depends on MPC8xx_SECOND_ETH_SCC
	default n
	bool "Use fixed MII-less mode for SCC Ethernet"

endmenu

choice
	prompt "Machine Type"
	depends on 6xx || POWER3
+3 −0
Original line number Diff line number Diff line
@@ -37,6 +37,9 @@ obj-$(CONFIG_SBC82xx) += sbc82xx.o
obj-$(CONFIG_SPRUCE)		+= spruce.o
obj-$(CONFIG_LITE5200)		+= lite5200.o
obj-$(CONFIG_EV64360)		+= ev64360.o
obj-$(CONFIG_MPC86XADS)		+= mpc866ads_setup.o
obj-$(CONFIG_MPC885ADS)		+= mpc885ads_setup.o
obj-$(CONFIG_ADS8272)		+= mpc8272ads_setup.o

ifeq ($(CONFIG_SMP),y)
obj-$(CONFIG_PPC_CHRP)		+= chrp_smp.o
+1 −1
Original line number Diff line number Diff line
@@ -112,7 +112,7 @@

/* CPM Ethernet through SCC1 or SCC2 */

#ifdef CONFIG_SCC1_ENET		/* Probably 860 variant */
#if defined(CONFIG_SCC1_ENET) || defined(CONFIG_MPC8xx_SECOND_ETH_SCC1)		/* Probably 860 variant */
/* Bits in parallel I/O port registers that have to be set/cleared
 * to configure the pins for SCC1 use.
 * TCLK - CLK1, RCLK - CLK2.
+236 −0
Original line number Diff line number Diff line
/*
 * arch/ppc/platforms/82xx/pq2ads_pd.c
 *
 * MPC82xx Board-specific PlatformDevice descriptions
 *
 * 2005 (c) MontaVista Software, Inc.
 * Vitaly Bordug <vbordug@ru.mvista.com>
 *
 * This file is licensed under the terms of the GNU General Public License
 * version 2. This program is licensed "as is" without any warranty of any
 * kind, whether express or implied.
 */


#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/ioport.h>
#include <linux/fs_enet_pd.h>
#include <linux/platform_device.h>

#include <asm/io.h>
#include <asm/mpc8260.h>
#include <asm/cpm2.h>
#include <asm/immap_cpm2.h>
#include <asm/irq.h>
#include <asm/ppc_sys.h>
#include <asm/ppcboot.h>

#include "pq2ads_pd.h"

static void init_fcc1_ioports(void);
static void init_fcc2_ioports(void);

static struct fs_mii_bus_info mii_bus_info = {
	.method                 = fsmii_bitbang,
	.id                     = 0,
	.i.bitbang = {
		.mdio_port	= fsiop_portc,
		.mdio_bit	= 18,
		.mdc_port	= fsiop_portc,
		.mdc_bit	= 19,
		.delay		= 1,
	},
};

static struct fs_platform_info mpc82xx_fcc1_pdata = {
	.fs_no		= fsid_fcc1,
	.cp_page	= CPM_CR_FCC1_PAGE,
	.cp_block 	= CPM_CR_FCC1_SBLOCK,
	.clk_trx 	= (PC_F1RXCLK | PC_F1TXCLK),
	.clk_route	= CMX1_CLK_ROUTE,
	.clk_mask	= CMX1_CLK_MASK,
	.init_ioports 	= init_fcc1_ioports,

	.phy_addr	= 0,
#ifdef PHY_INTERRUPT
	.phy_irq	= PHY_INTERRUPT,
#else
	.phy_irq	= -1;
#endif
	.mem_offset	= FCC1_MEM_OFFSET,
	.bus_info	= &mii_bus_info,
	.rx_ring	= 32,
	.tx_ring	= 32,
	.rx_copybreak	= 240,
	.use_napi	= 0,
	.napi_weight	= 17,
};

static struct fs_platform_info mpc82xx_fcc2_pdata = {
	.fs_no		= fsid_fcc2,
	.cp_page	= CPM_CR_FCC2_PAGE,
	.cp_block 	= CPM_CR_FCC2_SBLOCK,
	.clk_trx 	= (PC_F2RXCLK | PC_F2TXCLK),
	.clk_route	= CMX2_CLK_ROUTE,
	.clk_mask	= CMX2_CLK_MASK,
	.init_ioports	= init_fcc2_ioports,

	.phy_addr	= 3,
#ifdef PHY_INTERRUPT
	.phy_irq	= PHY_INTERRUPT,
#else
	.phy_irq	= -1;
#endif
	.mem_offset	= FCC2_MEM_OFFSET,
	.bus_info	= &mii_bus_info,
	.rx_ring	= 32,
	.tx_ring	= 32,
	.rx_copybreak	= 240,
	.use_napi	= 0,
	.napi_weight	= 17,
};

static void init_fcc1_ioports(void)
{
	struct io_port *io;
	u32 tempval;
	cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
	u32 *bcsr = ioremap(BCSR_ADDR+4, sizeof(u32));

	io = &immap->im_ioport;

	/* Enable the PHY */
	clrbits32(bcsr, BCSR1_FETHIEN);
	setbits32(bcsr, BCSR1_FETH_RST);

	/* FCC1 pins are on port A/C. */
	/* Configure port A and C pins for FCC1 Ethernet. */

	tempval = in_be32(&io->iop_pdira);
	tempval &= ~PA1_DIRA0;
	tempval |= PA1_DIRA1;
	out_be32(&io->iop_pdira, tempval);

	tempval = in_be32(&io->iop_psora);
	tempval &= ~PA1_PSORA0;
	tempval |= PA1_PSORA1;
	out_be32(&io->iop_psora, tempval);

	setbits32(&io->iop_ppara,PA1_DIRA0 | PA1_DIRA1);

	/* Alter clocks */
	tempval = PC_F1TXCLK|PC_F1RXCLK;

	clrbits32(&io->iop_psorc, tempval);
	clrbits32(&io->iop_pdirc, tempval);
	setbits32(&io->iop_pparc, tempval);

	clrbits32(&immap->im_cpmux.cmx_fcr, CMX1_CLK_MASK);
	setbits32(&immap->im_cpmux.cmx_fcr, CMX1_CLK_ROUTE);
	iounmap(bcsr);
	iounmap(immap);
}

static void init_fcc2_ioports(void)
{
	cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
	u32 *bcsr = ioremap(BCSR_ADDR+12, sizeof(u32));

	struct io_port *io;
	u32 tempval;

	immap = cpm2_immr;

	io = &immap->im_ioport;

	/* Enable the PHY */
	clrbits32(bcsr, BCSR3_FETHIEN2);
	setbits32(bcsr, BCSR3_FETH2_RST);

	/* FCC2 are port B/C. */
	/* Configure port A and C pins for FCC2 Ethernet. */

	tempval = in_be32(&io->iop_pdirb);
	tempval &= ~PB2_DIRB0;
	tempval |= PB2_DIRB1;
	out_be32(&io->iop_pdirb, tempval);

	tempval = in_be32(&io->iop_psorb);
	tempval &= ~PB2_PSORB0;
	tempval |= PB2_PSORB1;
	out_be32(&io->iop_psorb, tempval);

	setbits32(&io->iop_pparb,PB2_DIRB0 | PB2_DIRB1);

	tempval = PC_F2RXCLK|PC_F2TXCLK;

	/* Alter clocks */
	clrbits32(&io->iop_psorc,tempval);
	clrbits32(&io->iop_pdirc,tempval);
	setbits32(&io->iop_pparc,tempval);

	clrbits32(&immap->im_cpmux.cmx_fcr, CMX2_CLK_MASK);
	setbits32(&immap->im_cpmux.cmx_fcr, CMX2_CLK_ROUTE);

	iounmap(bcsr);
	iounmap(immap);
}


static void __init mpc8272ads_fixup_enet_pdata(struct platform_device *pdev,
					      int idx)
{
	bd_t* bi = (void*)__res;
	int fs_no = fsid_fcc1+pdev->id-1;

	mpc82xx_fcc1_pdata.dpram_offset = mpc82xx_fcc2_pdata.dpram_offset = (u32)cpm2_immr->im_dprambase;
	mpc82xx_fcc1_pdata.fcc_regs_c = mpc82xx_fcc2_pdata.fcc_regs_c = (u32)cpm2_immr->im_fcc_c;

	switch(fs_no) {
		case fsid_fcc1:
			memcpy(&mpc82xx_fcc1_pdata.macaddr,bi->bi_enetaddr,6);
			pdev->dev.platform_data = &mpc82xx_fcc1_pdata;
		break;
		case fsid_fcc2:
			memcpy(&mpc82xx_fcc2_pdata.macaddr,bi->bi_enetaddr,6);
			mpc82xx_fcc2_pdata.macaddr[5] ^= 1;
			pdev->dev.platform_data = &mpc82xx_fcc2_pdata;
		break;
	}
}

static int mpc8272ads_platform_notify(struct device *dev)
{
	static const struct platform_notify_dev_map dev_map[] = {
		{
			.bus_id = "fsl-cpm-fcc",
			.rtn = mpc8272ads_fixup_enet_pdata
		},
		{
			.bus_id = NULL
		}
	};
	platform_notify_map(dev_map,dev);

	return 0;

}

int __init mpc8272ads_init(void)
{
	printk(KERN_NOTICE "mpc8272ads: Init\n");

	platform_notify = mpc8272ads_platform_notify;

	ppc_sys_device_initfunc();

	ppc_sys_device_disable_all();
	ppc_sys_device_enable(MPC82xx_CPM_FCC1);
	ppc_sys_device_enable(MPC82xx_CPM_FCC2);

	return 0;
}

arch_initcall(mpc8272ads_init);
+273 −0
Original line number Diff line number Diff line
/*arch/ppc/platforms/mpc885ads-setup.c
 *
 * Platform setup for the Freescale mpc885ads board
 *
 * Vitaly Bordug <vbordug@ru.mvista.com>
 *
 * Copyright 2005 MontaVista Software Inc.
 *
 * This file is licensed under the terms of the GNU General Public License
 * version 2. This program is licensed "as is" without any warranty of any
 * kind, whether express or implied.
 */

#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/param.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/device.h>

#include <linux/fs_enet_pd.h>
#include <linux/mii.h>

#include <asm/delay.h>
#include <asm/io.h>
#include <asm/machdep.h>
#include <asm/page.h>
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/time.h>
#include <asm/ppcboot.h>
#include <asm/8xx_immap.h>
#include <asm/commproc.h>
#include <asm/ppc_sys.h>
#include <asm/mpc8xx.h>

extern unsigned char __res[];

static struct fs_mii_bus_info fec_mii_bus_info = {
	.method = fsmii_fec,
	.id = 0,
};

static struct fs_mii_bus_info scc_mii_bus_info = {
	.method = fsmii_fixed,
	.id = 0,
	.i.fixed.speed = 10,
	.i.fixed.duplex = 0,
};

static struct fs_platform_info mpc8xx_fec_pdata[] = {
	{
	 .rx_ring = 128,
	 .tx_ring = 16,
	 .rx_copybreak = 240,

	 .use_napi = 1,
	 .napi_weight = 17,

	 .phy_addr = 15,
	 .phy_irq = -1,

	 .use_rmii = 0,

	 .bus_info = &fec_mii_bus_info,
	 }
};

static struct fs_platform_info mpc8xx_scc_pdata = {
	.rx_ring = 64,
	.tx_ring = 8,
	.rx_copybreak = 240,

	.use_napi = 1,
	.napi_weight = 17,

	.phy_addr = -1,
	.phy_irq = -1,

	.bus_info = &scc_mii_bus_info,
};

void __init board_init(void)
{
	volatile cpm8xx_t *cp = cpmp;
	unsigned *bcsr_io;

	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));

	if (bcsr_io == NULL) {
		printk(KERN_CRIT "Could not remap BCSR1\n");
		return;
	}
#ifdef CONFIG_SERIAL_CPM_SMC1
	cp->cp_simode &= ~(0xe0000000 >> 17);	/* brg1 */
	clrbits32(bcsr_io,(0x80000000 >> 7));
#else
	setbits32(bcsr_io,(0x80000000 >> 7));

	cp->cp_pbpar &= ~(0x000000c0);
	cp->cp_pbdir |= 0x000000c0;
	cp->cp_smc[0].smc_smcmr = 0;
	cp->cp_smc[0].smc_smce = 0;
#endif

#ifdef CONFIG_SERIAL_CPM_SMC2
	cp->cp_simode &= ~(0xe0000000 >> 1);
	cp->cp_simode |= (0x20000000 >> 1);	/* brg2 */
	clrbits32(bcsr_io,(0x80000000 >> 13));
#else
	clrbits32(bcsr_io,(0x80000000 >> 13));
	cp->cp_pbpar &= ~(0x00000c00);
	cp->cp_pbdir |= 0x00000c00;
	cp->cp_smc[1].smc_smcmr = 0;
	cp->cp_smc[1].smc_smce = 0;
#endif
	iounmap(bcsr_io);
}

static void setup_fec1_ioports(void)
{
	immap_t *immap = (immap_t *) IMAP_ADDR;

	setbits16(&immap->im_ioport.iop_pdpar, 0x1fff);
	setbits16(&immap->im_ioport.iop_pddir, 0x1fff);
}

static void setup_scc1_ioports(void)
{
	immap_t *immap = (immap_t *) IMAP_ADDR;
	unsigned *bcsr_io;

	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));

	if (bcsr_io == NULL) {
		printk(KERN_CRIT "Could not remap BCSR1\n");
		return;
	}

	/* Enable the PHY.
	 */
	clrbits32(bcsr_io,BCSR1_ETHEN);

	/* Configure port A pins for Txd and Rxd.
	 */
	/* Disable receive and transmit in case EPPC-Bug started it.
	 */
	setbits16(&immap->im_ioport.iop_papar, PA_ENET_RXD | PA_ENET_TXD);
	clrbits16(&immap->im_ioport.iop_padir, PA_ENET_RXD | PA_ENET_TXD);
	clrbits16(&immap->im_ioport.iop_paodr, PA_ENET_TXD);

	/* Configure port C pins to enable CLSN and RENA.
	 */
	clrbits16(&immap->im_ioport.iop_pcpar, PC_ENET_CLSN | PC_ENET_RENA);
	clrbits16(&immap->im_ioport.iop_pcdir, PC_ENET_CLSN | PC_ENET_RENA);
	setbits16(&immap->im_ioport.iop_pcso, PC_ENET_CLSN | PC_ENET_RENA);
	/* Configure port A for TCLK and RCLK.
	 */
	setbits16(&immap->im_ioport.iop_papar, PA_ENET_TCLK | PA_ENET_RCLK);
	clrbits16(&immap->im_ioport.iop_padir, PA_ENET_TCLK | PA_ENET_RCLK);
	clrbits32(&immap->im_cpm.cp_pbpar, PB_ENET_TENA);
	clrbits32(&immap->im_cpm.cp_pbdir, PB_ENET_TENA);

	/* Configure Serial Interface clock routing.
	 * First, clear all SCC bits to zero, then set the ones we want.
	 */
	clrbits32(&immap->im_cpm.cp_sicr, SICR_ENET_MASK);
	setbits32(&immap->im_cpm.cp_sicr, SICR_ENET_CLKRT);

	/* In the original SCC enet driver the following code is placed at
	the end of the initialization */
	setbits32(&immap->im_cpm.cp_pbpar, PB_ENET_TENA);
	setbits32(&immap->im_cpm.cp_pbdir, PB_ENET_TENA);

}

static void mpc866ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
{
	struct fs_platform_info *fpi = pdev->dev.platform_data;

	volatile cpm8xx_t *cp;
	bd_t *bd = (bd_t *) __res;
	char *e;
	int i;

	/* Get pointer to Communication Processor */
	cp = cpmp;
	switch (fs_no) {
	case fsid_fec1:
		fpi = &mpc8xx_fec_pdata[0];
		fpi->init_ioports = &setup_fec1_ioports;

		break;
	case fsid_scc1:
		fpi = &mpc8xx_scc_pdata;
		fpi->init_ioports = &setup_scc1_ioports;

		break;
	default:
		printk(KERN_WARNING"Device %s is not supported!\n", pdev->name);
		return;
	}

	pdev->dev.platform_data = fpi;
	fpi->fs_no = fs_no;

	e = (unsigned char *)&bd->bi_enetaddr;
	for (i = 0; i < 6; i++)
		fpi->macaddr[i] = *e++;

	fpi->macaddr[5 - pdev->id]++;

}

static void mpc866ads_fixup_fec_enet_pdata(struct platform_device *pdev,
					   int idx)
{
	/* This is for FEC devices only */
	if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec")))
		return;
	mpc866ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
}

static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev,
					   int idx)
{
	/* This is for SCC devices only */
	if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc")))
		return;

	mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
}

static int mpc866ads_platform_notify(struct device *dev)
{
	static const struct platform_notify_dev_map dev_map[] = {
		{
			.bus_id = "fsl-cpm-fec",
			.rtn = mpc866ads_fixup_fec_enet_pdata,
		},
		{
			.bus_id = "fsl-cpm-scc",
			.rtn = mpc866ads_fixup_scc_enet_pdata,
		},
		{
			.bus_id = NULL
		}
	};

	platform_notify_map(dev_map,dev);

	return 0;
}

int __init mpc866ads_init(void)
{
	printk(KERN_NOTICE "mpc866ads: Init\n");

	platform_notify = mpc866ads_platform_notify;

	ppc_sys_device_initfunc();
	ppc_sys_device_disable_all();

#ifdef MPC8xx_SECOND_ETH_SCC1
	ppc_sys_device_enable(MPC8xx_CPM_SCC1);
#endif
	ppc_sys_device_enable(MPC8xx_CPM_FEC1);

	return 0;
}

arch_initcall(mpc866ads_init);
Loading