* yaboot mailing lists - new home
From: Paul Nasrat @ 2005-12-20 16:08 UTC (permalink / raw)
To: Ethan Benson, linuxppc-dev; +Cc: linuxppc64-dev
Following the hardware failure on penguinppc.org I've managed to arrange
hosting thanks to the kind administrators at ozlabs
https://ozlabs.org/mailman/listinfo/yaboot-devel
https://ozlabs.org/mailman/listinfo/yaboot-users
I haven't pushed any content there yet, but I think we were aiming at a
test release shortly so having the lists back will help.
Paul
^ permalink raw reply
* Re: [PATCH 3/3] ppc32: Adds MPC885ADS, MPC866ADS and MPC8272ADS-specific platform stuff for fs_enet
From: Kumar Gala @ 2005-12-20 15:02 UTC (permalink / raw)
To: Vitaly Bordug; +Cc: linuxppc-embedded list
In-Reply-To: <43A6B3E3.6030105@ru.mvista.com>
I really dont care for how fs_platform_info is laid out and what we
are passing into the driver vs what it can figure out itself or
maintain itself going forward. I guess we will clean this up when we
move to a flat device tree.
- kumar
On Dec 19, 2005, at 7:21 AM, Vitaly Bordug wrote:
> 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: Vitaly Bordug <vbordug@ru.mvista.com>
>
>
> ---
>
> arch/ppc/Kconfig | 47 ++++
> arch/ppc/platforms/Makefile | 4
> arch/ppc/platforms/fads.h | 2
> arch/ppc/platforms/mpc8272ads_setup.c | 235 ++++++++++++++++++++
> arch/ppc/platforms/mpc866ads_setup.c | 269 +++++++++++++++++++++++
> arch/ppc/platforms/mpc885ads_setup.c | 387 ++++++++++++++++++++++
> +++++++++++
> arch/ppc/platforms/pq2ads.h | 4
> arch/ppc/platforms/pq2ads_pd.h | 114 ++++++++++
> 8 files changed, 1061 insertions(+), 1 deletions(-)
> create mode 100644 arch/ppc/platforms/mpc8272ads_setup.c
> create mode 100644 arch/ppc/platforms/mpc866ads_setup.c
> create mode 100644 arch/ppc/platforms/mpc885ads_setup.c
> create mode 100644 arch/ppc/platforms/pq2ads_pd.h
>
> applies-to: f51b03be0daf16352ec61e3499f61c95adf115e7
> 5406392976524c1e504f2a612f49eac2b41dc16c
> diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
> index cc3f64c..ac32793 100644
> --- a/arch/ppc/Kconfig
> +++ b/arch/ppc/Kconfig
> @@ -506,6 +506,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 || POWER4
> diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
> index 7c5cdab..ee50b0d 100644
> --- a/arch/ppc/platforms/Makefile
> +++ b/arch/ppc/platforms/Makefile
> @@ -22,6 +22,8 @@ ifeq ($(CONFIG_PPC_PMAC),y)
> obj-$(CONFIG_NVRAM) += pmac_nvram.o
> obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o
> endif
> +
> +obj-$(CONFIG_ADS8272) += mpc8272ads_setup.o
> obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o
> obj-$(CONFIG_PREP_RESIDUAL) += residual.o
> obj-$(CONFIG_PQ2ADS) += pq2ads.o
> @@ -45,6 +47,8 @@ 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
>
> ifeq ($(CONFIG_SMP),y)
> obj-$(CONFIG_PPC_PMAC) += pmac_smp.o
> diff --git a/arch/ppc/platforms/fads.h b/arch/ppc/platforms/fads.h
> index a48fb8d..e1c0b1b 100644
> --- a/arch/ppc/platforms/fads.h
> +++ b/arch/ppc/platforms/fads.h
> @@ -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.
> diff --git a/arch/ppc/platforms/mpc8272ads_setup.c b/arch/ppc/
> platforms/mpc8272ads_setup.c
> new file mode 100644
> index 0000000..0f228ad
> --- /dev/null
> +++ b/arch/ppc/platforms/mpc8272ads_setup.c
> @@ -0,0 +1,235 @@
> +/*
> + * 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 <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;
> + }
> + printk("all\n");
> +}
> +
> +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_set_func_all(FUNC_DISABLED);
> + ppc_sys_device_setfunc(MPC82xx_CPM_FCC1, FUNC_ENABLED);
> + ppc_sys_device_setfunc(MPC82xx_CPM_FCC2, FUNC_ENABLED);
> +
> + return 0;
> +}
> +
> +arch_initcall(mpc8272ads_init);
> diff --git a/arch/ppc/platforms/mpc866ads_setup.c b/arch/ppc/
> platforms/mpc866ads_setup.c
> new file mode 100644
> index 0000000..ed1b050
> --- /dev/null
> +++ b/arch/ppc/platforms/mpc866ads_setup.c
> @@ -0,0 +1,269 @@
> +/*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:
> + break;
> + }
> +
> + 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 (strcmp(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 (strcmp(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_set_func_all(FUNC_DISABLED);
> + ppc_sys_device_setfunc(MPC8xx_CPM_SCC1, FUNC_ENABLED);
> + ppc_sys_device_setfunc(MPC8xx_CPM_FEC1, FUNC_ENABLED);
> +
> + return 0;
> +}
> +
> +arch_initcall(mpc866ads_init);
> diff --git a/arch/ppc/platforms/mpc885ads_setup.c b/arch/ppc/
> platforms/mpc885ads_setup.c
> new file mode 100644
> index 0000000..feefa91
> --- /dev/null
> +++ b/arch/ppc/platforms/mpc885ads_setup.c
> @@ -0,0 +1,387 @@
> +/*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>
> +
> +extern unsigned char __res[];
> +
> +static void __init mpc885ads_scc_phy_init(char);
> +
> +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 = {
> +#ifdef CONFIG_SCC_ENET_8xx_FIXED
> + .method = fsmii_fixed,
> +#else
> + .method = fsmii_fec,
> +#endif
> +
> + .id = 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 = 0,
> + .phy_irq = SIU_IRQ7,
> +
> + .bus_info = &fec_mii_bus_info,
> + }, {
> + .rx_ring = 128,
> + .tx_ring = 16,
> + .rx_copybreak = 240,
> +
> + .use_napi = 1,
> + .napi_weight = 17,
> +
> + .phy_addr = 1,
> + .phy_irq = SIU_IRQ7,
> +
> + .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 = 2,
> +#ifdef CONFIG_MPC8xx_SCC_ENET_FIXED
> + .phy_irq = -1,
> +#else
> + .phy_irq = SIU_IRQ7,
> +#endif
> +
> + .bus_info = &scc_mii_bus_info,
> +};
> +
> +void __init board_init(void)
> +{
> + volatile cpm8xx_t *cp = cpmp;
> + unsigned int *bcsr_io;
> +
> +#ifdef CONFIG_FS_ENET
> + immap_t *immap = (immap_t *) IMAP_ADDR;
> +#endif
> + bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
> +
> + if (bcsr_io == NULL) {
> + printk(KERN_CRIT "Could not remap BCSR\n");
> + return;
> + }
> +#ifdef CONFIG_SERIAL_CPM_SMC1
> + cp->cp_simode &= ~(0xe0000000 >> 17); /* brg1 */
> + clrbits32(bcsr_io, BCSR1_RS232EN_1);
> +#else
> + setbits32(bcsr_io,BCSR1_RS232EN_1);
> + 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,BCSR1_RS232EN_2);
> +#else
> + setbits32(bcsr_io,BCSR1_RS232EN_2);
> + cp->cp_smc[1].smc_smcmr = 0;
> + cp->cp_smc[1].smc_smce = 0;
> +#endif
> + iounmap(bcsr_io);
> +
> +#ifdef CONFIG_FS_ENET
> + /* use MDC for MII (common) */
> + setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
> + clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
> +#endif
> +}
> +
> +static void setup_fec1_ioports(void)
> +{
> + immap_t *immap = (immap_t *) IMAP_ADDR;
> +
> + /* configure FEC1 pins */
> + setbits16(&immap->im_ioport.iop_papar, 0xf830);
> + setbits16(&immap->im_ioport.iop_padir, 0x0830);
> + clrbits16(&immap->im_ioport.iop_padir, 0xf000);
> + setbits32(&immap->im_cpm.cp_pbpar, 0x00001001);
> +
> + clrbits32(&immap->im_cpm.cp_pbdir, 0x00001001);
> + setbits16(&immap->im_ioport.iop_pcpar, 0x000c);
> + clrbits16(&immap->im_ioport.iop_pcdir, 0x000c);
> + setbits32(&immap->im_cpm.cp_pepar, 0x00000003);
> +
> + setbits32(&immap->im_cpm.cp_pedir, 0x00000003);
> + clrbits32(&immap->im_cpm.cp_peso, 0x00000003);
> + clrbits32(&immap->im_cpm.cp_cptr, 0x00000100);
> +}
> +
> +static void setup_fec2_ioports(void)
> +{
> + immap_t *immap = (immap_t *) IMAP_ADDR;
> +
> + /* configure FEC2 pins */
> + setbits32(&immap->im_cpm.cp_pepar, 0x0003fffc);
> + setbits32(&immap->im_cpm.cp_pedir, 0x0003fffc);
> + setbits32(&immap->im_cpm.cp_peso, 0x00037800);
> + clrbits32(&immap->im_cpm.cp_peso, 0x000087fc);
> + clrbits32(&immap->im_cpm.cp_cptr, 0x00000080);
> +}
> +
> +static void setup_scc3_ioports(void)
> +{
> + immap_t *immap = (immap_t *) IMAP_ADDR;
> + unsigned *bcsr_io;
> +
> + bcsr_io = ioremap(BCSR_ADDR, BCSR_SIZE);
> +
> + if (bcsr_io == NULL) {
> + printk(KERN_CRIT "Could not remap BCSR\n");
> + return;
> + }
> +
> + /* Enable the PHY.
> + */
> + setbits32(bcsr_io+4, BCSR4_ETH10_RST);
> + /* Configure port A pins for Txd and Rxd.
> + */
> + setbits16(&immap->im_ioport.iop_papar, PA_ENET_RXD | PA_ENET_TXD);
> + clrbits16(&immap->im_ioport.iop_padir, PA_ENET_RXD | 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 E for TCLK and RCLK.
> + */
> + setbits32(&immap->im_cpm.cp_pepar, PE_ENET_TCLK | PE_ENET_RCLK);
> + clrbits32(&immap->im_cpm.cp_pepar, PE_ENET_TENA);
> + clrbits32(&immap->im_cpm.cp_pedir,
> + PE_ENET_TCLK | PE_ENET_RCLK | PE_ENET_TENA);
> + clrbits32(&immap->im_cpm.cp_peso, PE_ENET_TCLK | PE_ENET_RCLK);
> + setbits32(&immap->im_cpm.cp_peso, PE_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);
> +
> + /* Disable Rx and Tx. SMC1 sshould be stopped if SCC3 eternet are
> used.
> + */
> + immap->im_cpm.cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
> + /* On the MPC885ADS SCC ethernet PHY is initialized in the full
> duplex mode
> + * by H/W setting after reset. SCC ethernet controller support
> only half duplex.
> + * This discrepancy of modes causes a lot of carrier lost errors.
> + */
> +
> + /* In the original SCC enet driver the following code is placed at
> + the end of the initialization */
> + setbits32(&immap->im_cpm.cp_pepar, PE_ENET_TENA);
> + clrbits32(&immap->im_cpm.cp_pedir, PE_ENET_TENA);
> + setbits32(&immap->im_cpm.cp_peso, PE_ENET_TENA);
> +
> + setbits32(bcsr_io+1, BCSR1_ETHEN);
> + iounmap(bcsr_io);
> +}
> +
> +static void mpc885ads_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_fec2:
> + fpi = &mpc8xx_fec_pdata[1];
> + fpi->init_ioports = &setup_fec2_ioports;
> + break;
> + case fsid_scc3:
> + fpi = &mpc8xx_scc_pdata;
> + fpi->init_ioports = &setup_scc3_ioports;
> + mpc885ads_scc_phy_init(fpi->phy_addr);
> + break;
> + default:
> + break;
> + }
> +
> + 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 mpc885ads_fixup_fec_enet_pdata(struct platform_device
> *pdev,
> + int idx)
> +{
> + /* This is for FEC devices only */
> + if (!strstr(pdev->name, "fsl-cpm-fec"))
> + return;
> + mpc885ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
> +}
> +
> +static void __init mpc885ads_fixup_scc_enet_pdata(struct
> platform_device *pdev,
> + int idx)
> +{
> + /* This is for SCC devices only */
> + if (!strstr(pdev->name, "fsl-cpm-scc"))
> + return;
> +
> + mpc885ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
> +}
> +
> +/* SCC ethernet controller does not have MII management channel.
> FEC1 MII
> + * channel is used to communicate with the 10Mbit PHY.
> + */
> +
> +#define MII_ECNTRL_PINMUX 0x4
> +#define FEC_ECNTRL_PINMUX 0x00000004
> +#define FEC_RCNTRL_MII_MODE 0x00000004
> +
> +/* Make MII read/write commands.
> + */
> +#define mk_mii_write(REG, VAL, PHY_ADDR) (0x50020000 | (((REG)
> & 0x1f) << 18) | \
> + ((VAL) & 0xffff) | ((PHY_ADDR) << 23))
> +
> +static void mpc885ads_scc_phy_init(char phy_addr)
> +{
> + volatile immap_t *immap;
> + volatile fec_t *fecp;
> + bd_t *bd;
> +
> + bd = (bd_t *) __res;
> + immap = (immap_t *) IMAP_ADDR; /* pointer to internal registers */
> + fecp = &(immap->im_cpm.cp_fec);
> +
> + /* Enable MII pins of the FEC1
> + */
> + setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
> + clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
> + /* Set MII speed to 2.5 MHz
> + */
> + out_be32(&fecp->fec_mii_speed,
> + ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1);
> +
> + /* Enable FEC pin MUX
> + */
> + setbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX);
> + setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
> +
> + out_be32(&fecp->fec_mii_data,
> + mk_mii_write(MII_BMCR, BMCR_ISOLATE, phy_addr));
> + udelay(100);
> + out_be32(&fecp->fec_mii_data,
> + mk_mii_write(MII_ADVERTISE,
> + ADVERTISE_10HALF | ADVERTISE_CSMA, phy_addr));
> + udelay(100);
> +
> + /* Disable FEC MII settings
> + */
> + clrbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX);
> + clrbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
> + out_be32(&fecp->fec_mii_speed, 0);
> +}
> +
> +static int mpc885ads_platform_notify(struct device *dev)
> +{
> +
> + static const struct platform_notify_dev_map dev_map[] = {
> + {
> + .bus_id = "fsl-cpm-fec",
> + .rtn = mpc885ads_fixup_fec_enet_pdata,
> + },
> + {
> + .bus_id = "fsl-cpm-scc",
> + .rtn = mpc885ads_fixup_scc_enet_pdata,
> + },
> + {
> + .bus_id = NULL
> + }
> + };
> +
> + platform_notify_map(dev_map,dev);
> +
> +}
> +
> +int __init mpc885ads_init(void)
> +{
> + printk(KERN_NOTICE "mpc885ads: Init\n");
> +
> + platform_notify = mpc885ads_platform_notify;
> +
> + ppc_sys_device_initfunc();
> + ppc_sys_device_set_func_all(FUNC_DISABLED);
> + ppc_sys_device_setfunc(MPC8xx_CPM_FEC1, FUNC_ENABLED);
> +
> +#ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3
> + ppc_sys_device_setfunc(MPC8xx_CPM_SCC1, FUNC_ENABLED);
> +
> +#endif
> +#ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2
> + ppc_sys_device_setfunc(MPC8xx_CPM_FEC2, FUNC_ENABLED);
> +#endif
> +
> + return 0;
> +}
> +
> +arch_initcall(mpc885ads_init);
> diff --git a/arch/ppc/platforms/pq2ads.h b/arch/ppc/platforms/pq2ads.h
> index 067d9a5..6b26dd3 100644
> --- a/arch/ppc/platforms/pq2ads.h
> +++ b/arch/ppc/platforms/pq2ads.h
> @@ -13,6 +13,10 @@
>
> #include <asm/ppcboot.h>
>
> +#if defined(CONFIG_ADS8272)
> +#define BOARD_CHIP_NAME "8272"
> +#endif
> +
> /* Memory map is configured by the PROM startup.
> * We just map a few things we need. The CSR is actually 4 byte-wide
> * registers that can be accessed as 8-, 16-, or 32-bit values.
> diff --git a/arch/ppc/platforms/pq2ads_pd.h b/arch/ppc/platforms/
> pq2ads_pd.h
> new file mode 100644
> index 0000000..8f14a43
> --- /dev/null
> +++ b/arch/ppc/platforms/pq2ads_pd.h
> @@ -0,0 +1,114 @@
> +#ifndef __PQ2ADS_PD_H
> +#define __PQ2ADS_PD_H
> +/*
> + * arch/ppc/platforms/82xx/pq2ads_pd.h
> + *
> + * Some defines for 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.
> + */
> +
> +/* FCC1 Clock Source Configuration. These can be redefined in the
> board specific file.
> + Can only choose from CLK9-12 */
> +
> +#define F1_RXCLK 11
> +#define F1_TXCLK 10
> +
> +/* FCC2 Clock Source Configuration. These can be redefined in the
> board specific file.
> + Can only choose from CLK13-16 */
> +#define F2_RXCLK 15
> +#define F2_TXCLK 16
> +
> +/* FCC3 Clock Source Configuration. These can be redefined in the
> board specific file.
> + Can only choose from CLK13-16 */
> +#define F3_RXCLK 13
> +#define F3_TXCLK 14
> +
> +/* Automatically generates register configurations */
> +#define PC_CLK(x) ((uint)(1<<(x-1))) /* FCC CLK I/O ports */
> +
> +#define CMXFCR_RF1CS(x) ((uint)((x-5)<<27)) /* FCC1 Receive Clock
> Source */
> +#define CMXFCR_TF1CS(x) ((uint)((x-5)<<24)) /* FCC1 Transmit Clock
> Source */
> +#define CMXFCR_RF2CS(x) ((uint)((x-9)<<19)) /* FCC2 Receive Clock
> Source */
> +#define CMXFCR_TF2CS(x) ((uint)((x-9)<<16)) /* FCC2 Transmit Clock
> Source */
> +#define CMXFCR_RF3CS(x) ((uint)((x-9)<<11)) /* FCC3 Receive Clock
> Source */
> +#define CMXFCR_TF3CS(x) ((uint)((x-9)<<8)) /* FCC3 Transmit Clock
> Source */
> +
> +#define PC_F1RXCLK PC_CLK(F1_RXCLK)
> +#define PC_F1TXCLK PC_CLK(F1_TXCLK)
> +#define CMX1_CLK_ROUTE (CMXFCR_RF1CS(F1_RXCLK) | CMXFCR_TF1CS
> (F1_TXCLK))
> +#define CMX1_CLK_MASK ((uint)0xff000000)
> +
> +#define PC_F2RXCLK PC_CLK(F2_RXCLK)
> +#define PC_F2TXCLK PC_CLK(F2_TXCLK)
> +#define CMX2_CLK_ROUTE (CMXFCR_RF2CS(F2_RXCLK) | CMXFCR_TF2CS
> (F2_TXCLK))
> +#define CMX2_CLK_MASK ((uint)0x00ff0000)
> +
> +#define PC_F3RXCLK PC_CLK(F3_RXCLK)
> +#define PC_F3TXCLK PC_CLK(F3_TXCLK)
> +#define CMX3_CLK_ROUTE (CMXFCR_RF3CS(F3_RXCLK) | CMXFCR_TF3CS
> (F3_TXCLK))
> +#define CMX3_CLK_MASK ((uint)0x0000ff00)
> +
> +/* I/O Pin assignment for FCC1. I don't yet know the best way to
> do this,
> + * but there is little variation among the choices.
> + */
> +#define PA1_COL 0x00000001U
> +#define PA1_CRS 0x00000002U
> +#define PA1_TXER 0x00000004U
> +#define PA1_TXEN 0x00000008U
> +#define PA1_RXDV 0x00000010U
> +#define PA1_RXER 0x00000020U
> +#define PA1_TXDAT 0x00003c00U
> +#define PA1_RXDAT 0x0003c000U
> +#define PA1_PSORA0 (PA1_RXDAT | PA1_TXDAT)
> +#define PA1_PSORA1 (PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
> + PA1_RXDV | PA1_RXER)
> +#define PA1_DIRA0 (PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER |
> PA1_RXDV)
> +#define PA1_DIRA1 (PA1_TXDAT | PA1_TXEN | PA1_TXER)
> +
> +
> +/* I/O Pin assignment for FCC2. I don't yet know the best way to
> do this,
> + * but there is little variation among the choices.
> + */
> +#define PB2_TXER 0x00000001U
> +#define PB2_RXDV 0x00000002U
> +#define PB2_TXEN 0x00000004U
> +#define PB2_RXER 0x00000008U
> +#define PB2_COL 0x00000010U
> +#define PB2_CRS 0x00000020U
> +#define PB2_TXDAT 0x000003c0U
> +#define PB2_RXDAT 0x00003c00U
> +#define PB2_PSORB0 (PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
> + PB2_RXER | PB2_RXDV | PB2_TXER)
> +#define PB2_PSORB1 (PB2_TXEN)
> +#define PB2_DIRB0 (PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER |
> PB2_RXDV)
> +#define PB2_DIRB1 (PB2_TXDAT | PB2_TXEN | PB2_TXER)
> +
> +
> +/* I/O Pin assignment for FCC3. I don't yet know the best way to
> do this,
> + * but there is little variation among the choices.
> + */
> +#define PB3_RXDV 0x00004000U
> +#define PB3_RXER 0x00008000U
> +#define PB3_TXER 0x00010000U
> +#define PB3_TXEN 0x00020000U
> +#define PB3_COL 0x00040000U
> +#define PB3_CRS 0x00080000U
> +#define PB3_TXDAT 0x0f000000U
> +#define PB3_RXDAT 0x00f00000U
> +#define PB3_PSORB0 (PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
> + PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN)
> +#define PB3_PSORB1 0
> +#define PB3_DIRB0 (PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER |
> PB3_RXDV)
> +#define PB3_DIRB1 (PB3_TXDAT | PB3_TXEN | PB3_TXER)
> +
> +#define FCC_MEM_OFFSET(x) (CPM_FCC_SPECIAL_BASE + (x*128))
> +#define FCC1_MEM_OFFSET FCC_MEM_OFFSET(0)
> +#define FCC2_MEM_OFFSET FCC_MEM_OFFSET(1)
> +
> +#endif
> ---
> Sincerely,
> Vitaly
>
^ permalink raw reply
* Re: [PATCH 1/3] ppc32: Make platform devices being able to assign functions (update)
From: Kumar Gala @ 2005-12-20 14:49 UTC (permalink / raw)
To: Vitaly Bordug; +Cc: linuxppc-embedded list
In-Reply-To: <43A77F81.9030102@ru.mvista.com>
On Dec 19, 2005, at 9:50 PM, Vitaly Bordug wrote:
> Implemented by modification of the .name field of the platform
> device,
> when PDs with the
> same names are to be used within different drivers, as
> <device_name> -> <device_name>:<function>
> Corresponding drivers should change the .name in struct
> device_driver to
> reflect upper of course.
>
> Also helper platform_notify_map function added, making assignment of
> board-specific platform_info more consistent and generic.
>
> Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
>
>
> ---
>
> arch/ppc/syslib/ppc_sys.c | 136 ++++++++++++++++++++++++++++++++++
> ++++++++++-
> include/asm-ppc/mpc10x.h | 1
> include/asm-ppc/mpc52xx.h | 1
> include/asm-ppc/mpc8260.h | 1
> include/asm-ppc/mpc83xx.h | 1
> include/asm-ppc/mpc85xx.h | 1
> include/asm-ppc/mpc8xx.h | 1
> include/asm-ppc/ppc_sys.h | 24 ++++++++
> 8 files changed, 164 insertions(+), 2 deletions(-)
>
> applies-to: 4ce1b1890dc687cb1cf77f98e7a95b94c7ef3a93
> a8450a334dc930d7284800c457d91ed55a1a3dd7
> diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c
> index c0b93c4..26d2658 100644
> --- a/arch/ppc/syslib/ppc_sys.c
> +++ b/arch/ppc/syslib/ppc_sys.c
> @@ -15,11 +15,23 @@
> */
>
> #include <linux/string.h>
> +#include <linux/bootmem.h>
> #include <asm/ppc_sys.h>
>
> int (*ppc_sys_device_fixup) (struct platform_device * pdev);
>
> static int ppc_sys_inited;
> +static int ppc_sys_func_inited;
> +
> +static const char *ppc_sys_func_names[] = {
> + [FUNC_ENABLED] = "dummy",
> + [FUNC_ETH] = "eth",
> + [FUNC_UART] = "uart",
> + [FUNC_HLDC] = "hldc",
> + [FUNC_USB] = "usb",
> + [FUNC_IRDA] = "irda",
> + [FUNC_DISABLED] = "off",
> +};
We should probably qualify the enum names a bit further for name
space pollution.
>
> void __init identify_ppc_sys_by_id(u32 id)
> {
> @@ -38,13 +50,13 @@ void __init identify_ppc_sys_by_id(u32 i
> void __init identify_ppc_sys_by_name(char *name)
> {
> unsigned int i = 0;
> - while (ppc_sys_specs[i].ppc_sys_name[0])
> - {
> + while (ppc_sys_specs[i].ppc_sys_name[0]) {
> if (!strcmp(ppc_sys_specs[i].ppc_sys_name, name))
> break;
> i++;
> }
> cur_ppc_sys_spec = &ppc_sys_specs[i];
> +
> return;
> }
>
> @@ -128,6 +140,126 @@ void ppc_sys_device_remove(enum ppc_sys_
> }
> }
>
> +/* Platform-notify mapping
> + * Helper function for BSP code to assign board-specific platfom-
> divice bits
> + */
> +
> +void platform_notify_map(const struct platform_notify_dev_map *map,
> + struct device *dev)
> +{
> + struct platform_device *pdev;
> + int len, idx;
> + const char *s;
> +
> + /* do nothing if no device or no bus_id */
> + if (!dev || !dev->bus_id)
> + return;
> +
> + /* call per device map */
> + while (map->bus_id != NULL) {
> + idx = -1;
> + s = strrchr(dev->bus_id, '.');
> + if (s != NULL)
> + idx = (int)simple_strtol(s + 1, NULL, 10);
> + else
> + s = dev->bus_id;
> +
> + len = s - dev->bus_id;
> +
> + if (!strncmp(dev->bus_id, map->bus_id, len)) {
> + pdev = container_of(dev, struct platform_device, dev);
> + map->rtn(pdev, idx);
> + }
> + map++;
> + }
> +}
> +
> +/*
> + Function assignment stuff.
> + Intended to work as follows:
> + the device name defined in foo_devices.c will be concatenated
> with :"func",
> + where func is string map of respective function from
> platfom_device_func enum
> +
> + The FUNC_ENABLED function is intended to remove all assignments,
> making the device to appear
> + in platform bus with unmodified name.
> + */
> +
> +/*
> + Here we'll replace .name pointers with fixed-lenght strings
Nit: lenght -> length
> + Hereby, this should be called *before* any func stuff triggeded.
> + */
> +void ppc_sys_device_initfunc(void)
> +{
> + int i;
> + const char *name;
> + static char new_names[NUM_PPC_SYS_DEVS][BUS_ID_SIZE];
> + enum ppc_sys_devices cur_dev;
> +
> + /* If inited yet, do nothing */
> + if (ppc_sys_func_inited)
> + return;
> +
> + for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) {
> + if ((cur_dev = cur_ppc_sys_spec->device_list[i]) < 0)
> + continue;
> +
> + if (ppc_sys_platform_devices[cur_dev].name) {
> + /*backup name */
> + name = ppc_sys_platform_devices[cur_dev].name;
> + strlcpy(new_names[i], name, BUS_ID_SIZE);
> + ppc_sys_platform_devices[cur_dev].name = new_names[i];
> + }
> + }
> +
> + ppc_sys_func_inited = 1;
> +}
> +
I really dont like mixing the function "enet, usb, serial, ..." with
the state enable/disabled. We should separate these two items.
> +/*The "engine" of the func stuff. Here we either concat specified
> function string description
> + to the name, or remove it if FUNC_ENABLED parameter is passed here*/
> +void ppc_sys_device_setfunc(enum ppc_sys_devices dev,
> + enum platform_device_func func)
> +{
> + char *s;
> + char *name = (char *)ppc_sys_platform_devices[dev].name;
> + char tmp[BUS_ID_SIZE];
> +
> + if (!ppc_sys_func_inited) {
> + printk(KERN_ERR "Unable to alter function - not inited!\n");
> + return;
> + }
> +
> + if (ppc_sys_inited) {
> + platform_device_unregister(&ppc_sys_platform_devices[dev]);
> + }
> +
> + if ((s = (char *)strchr(name, ':')) != NULL) { /* reassign */
> + /* Either change the name after ':' or remove func modifications */
> + if (func != FUNC_ENABLED)
> + strlcpy(s + 1, ppc_sys_func_names[func], BUS_ID_SIZE);
> + else
> + *s = 0;
> + } else if (func != FUNC_ENABLED) {
> + /* do assignment if it is not just "enable" request */
> + sprintf(tmp, "%s:%s", name, ppc_sys_func_names[func]);
> + strlcpy(name, tmp, BUS_ID_SIZE);
> + }
> +
> + if (ppc_sys_inited) {
> + platform_device_register(&ppc_sys_platform_devices[dev]);
> + }
> +}
> +
> +void ppc_sys_device_set_func_all(enum platform_device_func func)
> +{
> + enum ppc_sys_devices cur_dev;
> + int i;
> +
> + for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) {
> + cur_dev = cur_ppc_sys_spec->device_list[i];
> + ppc_sys_device_setfunc(cur_dev, func);
> + }
> +}
> +
> static int __init ppc_sys_init(void)
> {
> unsigned int i, dev_id, ret = 0;
> diff --git a/include/asm-ppc/mpc10x.h b/include/asm-ppc/mpc10x.h
> index 77b1e09..976ad3d 100644
> --- a/include/asm-ppc/mpc10x.h
> +++ b/include/asm-ppc/mpc10x.h
> @@ -165,6 +165,7 @@ enum ppc_sys_devices {
> MPC10X_DMA1,
> MPC10X_UART0,
> MPC10X_UART1,
> + NUM_PPC_SYS_DEVS,
> };
>
> int mpc10x_bridge_init(struct pci_controller *hose,
> diff --git a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
> index e5f80c2..b2cb44f 100644
> --- a/include/asm-ppc/mpc52xx.h
> +++ b/include/asm-ppc/mpc52xx.h
> @@ -49,6 +49,7 @@ enum ppc_sys_devices {
> MPC52xx_ATA,
> MPC52xx_I2C1,
> MPC52xx_I2C2,
> + NUM_PPC_SYS_DEVS,
> };
>
>
> diff --git a/include/asm-ppc/mpc8260.h b/include/asm-ppc/mpc8260.h
> index 3214526..6ba69a8 100644
> --- a/include/asm-ppc/mpc8260.h
> +++ b/include/asm-ppc/mpc8260.h
> @@ -83,6 +83,7 @@ enum ppc_sys_devices {
> MPC82xx_CPM_SMC2,
> MPC82xx_CPM_USB,
> MPC82xx_SEC1,
> + NUM_PPC_SYS_DEVS,
> };
>
> #ifndef __ASSEMBLY__
> diff --git a/include/asm-ppc/mpc83xx.h b/include/asm-ppc/mpc83xx.h
> index 7cdf60f..3c23fc4 100644
> --- a/include/asm-ppc/mpc83xx.h
> +++ b/include/asm-ppc/mpc83xx.h
> @@ -108,6 +108,7 @@ enum ppc_sys_devices {
> MPC83xx_USB2_DR,
> MPC83xx_USB2_MPH,
> MPC83xx_MDIO,
> + NUM_PPC_SYS_DEVS,
> };
>
> #endif /* CONFIG_83xx */
> diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h
> index 9d14bae..2a77884 100644
> --- a/include/asm-ppc/mpc85xx.h
> +++ b/include/asm-ppc/mpc85xx.h
> @@ -135,6 +135,7 @@ enum ppc_sys_devices {
> MPC85xx_eTSEC4,
> MPC85xx_IIC2,
> MPC85xx_MDIO,
> + NUM_PPC_SYS_DEVS,
> };
>
> /* Internal interrupts are all Level Sensitive, and Positive
> Polarity */
> diff --git a/include/asm-ppc/mpc8xx.h b/include/asm-ppc/mpc8xx.h
> index 46f159c..90e3d59 100644
> --- a/include/asm-ppc/mpc8xx.h
> +++ b/include/asm-ppc/mpc8xx.h
> @@ -111,6 +111,7 @@ enum ppc_sys_devices {
> MPC8xx_CPM_SMC1,
> MPC8xx_CPM_SMC2,
> MPC8xx_CPM_USB,
> + NUM_PPC_SYS_DEVS,
> };
>
> #ifndef BOARD_CHIP_NAME
> diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h
> index 83d8c77..76f259f 100644
> --- a/include/asm-ppc/ppc_sys.h
> +++ b/include/asm-ppc/ppc_sys.h
> @@ -47,6 +47,21 @@ struct ppc_sys_spec {
> enum ppc_sys_devices *device_list;
> };
>
> +struct platform_notify_dev_map {
> + const char *bus_id;
> + void (*rtn)(struct platform_device * pdev, int idx);
> +};
> +
> +enum platform_device_func {
> + FUNC_ENABLED = 0,
> + FUNC_ETH = 1,
> + FUNC_UART = 2,
> + FUNC_HLDC = 3,
> + FUNC_USB = 4,
> + FUNC_IRDA = 5,
> + FUNC_DISABLED = 6,
> +};
> +
> /* describes all specific chips and which devices they have on
> them */
> extern struct ppc_sys_spec ppc_sys_specs[];
> extern struct ppc_sys_spec *cur_ppc_sys_spec;
> @@ -72,5 +87,14 @@ extern void *ppc_sys_get_pdata(enum ppc_
> /* remove a device from the system */
> extern void ppc_sys_device_remove(enum ppc_sys_devices dev);
>
> +/*Function assignment stuff*/
> +void ppc_sys_device_initfunc(void);
> +void ppc_sys_device_setfunc(enum ppc_sys_devices dev,
> + enum platform_device_func func);
> +void ppc_sys_device_set_func_all(enum platform_device_func func);
> +
> +void platform_notify_map(const struct platform_notify_dev_map *map,
> + struct device *dev);
> +
> #endif /* __ASM_PPC_SYS_H */
> #endif /* __KERNEL__ */
> ---
> 0.99.9.GIT
>
^ permalink raw reply
* Re: linux DMA capabilities in MV64460
From: Brian Waite @ 2005-12-20 14:27 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <20051220010136.GA31165@mag.az.mvista.com>
On Monday 19 December 2005 8:01 pm, Mark A. Greer wrote:
> >
> > up the mv64460. One source told me:
> > > In order to do PCI bursts, you'll need to use a DMA engine. The
> > > MV64460 does contain a DMA engine, but you'd need to write a driver
> > > to access it.
>
> That is not correct (assuming the quote is not out of context).
> The bridge supports bursting on the PCI bus as long as the bridge is
> configured correctly and the PCI device is making an appropriate request.
> Note, however, that there are many errata for the Marvell parts including
> some with cache coherency.
There are many many errata regarding cache coherency. Also, the PCI bandwidth
the bridge is capable of with coherency enabled is very small. You will most
likely need to use sw coherency for any real speed.
> If your system is running with coherency on,
> you may have to limit your bursts to 32 bytes (i.e., the size of one
> cache line).
You will have to limit your self to 32 byte bursts with coherency. This is a
requirement not an errata.
> > Is there a summary of what is possible and/or not possible with the 4
> > IDMA channels on the mv64460?
>
> The only real documentation is the bridge's user manual from Marvell.
> Unfortunately, you must sign an NDA to get access to it so I can't share
> mine with you. You will need access to that info to get very far so I
> recommend you contact the people in your company that can make that
> happen, ASAP.
Ask for the errata sheets while your at it. You WILL need them :)
You really do need the chipset docs to do anything intelligent with the IDMA
controllers.
Thanks
Brian
^ permalink raw reply
* Re: RFC: Rev 0.5 Booting the Linux/ppc kernel without Open Firmware
From: Arnd Bergmann @ 2005-12-20 10:18 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc64-dev, linuxppc-dev
In-Reply-To: <Pine.LNX.4.44.0512191446570.4542-100000@gate.crashing.org>
On Maandag 19 Dezember 2005 21:49, Kumar Gala wrote:
> I'm still in favor of just leaving these devices as straight platform
> devices. Unless there is something that is bus specific that each device
> on the bus conforms to I dont see any reason to create a new bus type.
How do platform devices work with module autoloading? What I'm interested
in is to have stuff like the Fedora installer or kernels with modular
drivers 'just work' because they can use the same way to load their
modules that is already used for PCI devices.
AFAICS, that requires at least two things:
- The device needs to be created when the bus is probed, i.e.
of_device_register can not be called from inside the driver
module_init() function.
- The bus type needs to create a modalias file so user space can
do the matching with the of device table in the modules.
Both of these should be a lot easier to implement with a special
bus type that creates entries in sysfs for a subset of the OF
device tree.
The alternative would be to represent all of the device tree
in /sys/devices, but IMHO that should better be part of
/sys/firmware with symlinks to the linux internal device tree
representation.
Arnd <><
^ permalink raw reply
* ppc440 EBC question
From: Peter Fercher @ 2005-12-20 7:52 UTC (permalink / raw)
To: 'linux-ppc-embedded'
[-- Attachment #1: Type: text/plain, Size: 129 bytes --]
does somebody have a hint where to find an example how to
talk to devices attached to the ppc440 external bus controller
thanks
[-- Attachment #2: Type: text/html, Size: 638 bytes --]
^ permalink raw reply
* Re: MPC8272ADS stability issues
From: Dmytro Bablinyuk @ 2005-12-20 5:22 UTC (permalink / raw)
To: Laurie, Ian; +Cc: linuxppc-embedded
In-Reply-To: <F311526ED41F0F449EAFC93A85287CCC02A8F205@USCHD00MX15ASU.APAC.AVNET.COM>
>
> Does anyone have any news regarding any resolution of this issue?
>
We cannot guarantee that this is solution for everybody BUT:
We had similar problems with our MPC8272ADS and this morning we
discovered that core voltage exceeds recommended values - the core
voltage on 8272ADS was 1.6V instead of 1.5V.
Where according to MPC8272EC, Rev. 1.2, 05/2005 page 7
--8<--
Table 4. Recommended Operating Conditions
Caution: These are the recommended and tested operating conditions.
Proper operation outside of these conditions is not guaranteed.
Rating Symbol Value Unit
Core supply voltage VDD 1.425 – 1.575 V
--8<--
We run memory test, as for now, for almost 9 hours and so far without
problems. Though before board was crashing every 1-4 hours. We don't
know whether this is source of the problem - we will keep testing it.
Power supply for MPC8272ADS generates ± 5V, ± 12V, +3.3V - they are all ok.
Core voltage is generated by U45 on the 8272ADS board. There is a
trimmer pot RP1 for adjusting the core voltage - we never checked it
before since we assumed that it should be set properly by factory. But
today we found that U45 gives 1.6V instead of 1.5V, which is outside of
recommended values and datasheet says "Proper operation outside of these
conditions is not guaranteed".
So, check you core voltage (U45) - it might help.
Dmytro
^ permalink raw reply
* [PATCH] MPC8349 MDS USB HOST support
From: Li Yang-r58472 @ 2005-12-20 3:57 UTC (permalink / raw)
To: linux-usb-devel, linuxppc-embedded
Hi,
Here is the patch we have in Freescale released BSP. I post it here in case anyone may need it without the BSP. It's for kernel 2.6.11, and won't have big problem for newer kernel, I think. The patch is not done by myself, and maybe submitted later formally after merge with OTG and clean up. Here goes the patch.
diff -Nur linux/drivers/usb/core/hcd.c linux-8349-2.6/drivers/usb/core/hcd.c
--- linux/drivers/usb/core/hcd.c 2005-03-02 15:38:10.000000000 +0800
+++ linux-8349-2.6/drivers/usb/core/hcd.c 2005-08-15 13:54:13.000000000 +0800
@@ -1116,13 +1116,20 @@
if (hcd->self.controller->dma_mask) {
if (usb_pipecontrol (urb->pipe)
&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+#ifdef CONFIG_FSL_USB20
+ urb->setup_dma = (unsigned long)urb->setup_packet;
+#else
urb->setup_dma = dma_map_single (
hcd->self.controller,
urb->setup_packet,
sizeof (struct usb_ctrlrequest),
DMA_TO_DEVICE);
+#endif
if (urb->transfer_buffer_length != 0
&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+#ifdef CONFIG_FSL_USB20
+ urb->transfer_dma = (unsigned long)urb->transfer_buffer;
+#else
urb->transfer_dma = dma_map_single (
hcd->self.controller,
urb->transfer_buffer,
@@ -1130,6 +1137,7 @@
usb_pipein (urb->pipe)
? DMA_FROM_DEVICE
: DMA_TO_DEVICE);
+#endif
}
status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags);
@@ -1469,6 +1477,8 @@
// It would catch exit/unlink paths for all urbs.
/* lower level hcd code should use *_dma exclusively */
+#ifdef CONFIG_FSL_USB20
+#else
if (hcd->self.controller->dma_mask) {
if (usb_pipecontrol (urb->pipe)
&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
@@ -1484,7 +1494,7 @@
? DMA_FROM_DEVICE
: DMA_TO_DEVICE);
}
-
+#endif
/* pass ownership to the completion handler */
urb->complete (urb, regs);
atomic_dec (&urb->use_count);
diff -Nur linux/drivers/usb/core/hub.c linux-8349-2.6/drivers/usb/core/hub.c
--- linux/drivers/usb/core/hub.c 2005-03-02 15:38:08.000000000 +0800
+++ linux-8349-2.6/drivers/usb/core/hub.c 2005-08-15 13:56:05.000000000 +0800
@@ -2155,7 +2155,11 @@
} else if (udev->speed != USB_SPEED_HIGH
&& hdev->speed == USB_SPEED_HIGH) {
udev->tt = &hub->tt;
+#ifdef CONFIG_FSL_USB20
+ udev->ttport = port1+1;
+#else
udev->ttport = port1;
+#endif
}
/* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way?
diff -Nur linux/drivers/usb/host/ehci.h linux-8349-2.6/drivers/usb/host/ehci.h
--- linux/drivers/usb/host/ehci.h 2005-03-02 15:38:25.000000000 +0800
+++ linux-8349-2.6/drivers/usb/host/ehci.h 2005-08-15 10:25:52.000000000 +0800
@@ -59,6 +59,9 @@
#define DEFAULT_I_TDPS 1024 /* some HCs can do less */
unsigned periodic_size;
__le32 *periodic; /* hw periodic table */
+#ifdef CONFIG_FSL_USB20
+ u32 orig_periodic;
+#endif
dma_addr_t periodic_dma;
unsigned i_thresh; /* uframes HC might cache */
@@ -70,11 +73,17 @@
unsigned long reset_done [EHCI_MAX_ROOT_PORTS];
/* per-HC memory pools (could be per-bus, but ...) */
+#ifdef CONFIG_FSL_USB20
+ t_MemorySegment *qh_pool; /* qh per active urb */
+ t_MemorySegment *qtd_pool; /* one or more per qh */
+ t_MemorySegment *itd_pool; /* itd per iso urb */
+ t_MemorySegment *sitd_pool; /* sitd per split iso urb */
+#else
struct dma_pool *qh_pool; /* qh per active urb */
struct dma_pool *qtd_pool; /* one or more per qh */
struct dma_pool *itd_pool; /* itd per iso urb */
struct dma_pool *sitd_pool; /* sitd per split iso urb */
-
+#endif
struct timer_list watchdog;
struct notifier_block reboot_notifier;
unsigned long actions;
@@ -230,9 +239,26 @@
u32 frame_list; /* points to periodic list */
/* ASYNCLISTADDR: offset 0x18 */
u32 async_next; /* address of next async queue head */
-
+#ifdef CONFIG_FSL_USB20
+ /* ASYNCTTSTS: offset 0x1c */
+ u32 async_tt_status; /* async queue status for embedded TT */
+ /* BURSTSIZE: offset 0x20 */
+ u32 burst_size; /* programmable burst size */
+ /* TXFILLTUNING: offset 0x24 */
+ u32 txfilltuning; /* host transmit pre-buffer packet tuning */
+ /* TXTTFILLTUNING: offset 0x28 */
+ u32 txttfilltuning; /* host TT transmit pre-buffer packet tuning */
+ u32 reserved0;
+ /* ULPIVIEWPORT: offset 0x30 */
+ u32 ulpi_view_port; /* ULPI view port */
+ /* ENDPTNAK: offset 0x34 */
+ u32 endpoint_nack; /* endpoint nack */
+ /* ENDPTNAKEN: offset 0x38 */
+ u32 endpoint_nack_en; /* endpoint nack enable */
+ u32 reserved1;
+#else
u32 reserved [9];
-
+#endif
/* CONFIGFLAG: offset 0x40 */
u32 configured_flag;
#define FLAG_CF (1<<0) /* true: we'll support "high speed" */
diff -Nur linux/drivers/usb/host/ehci-hcd.c linux-8349-2.6/drivers/usb/host/ehci-hcd.c
--- linux/drivers/usb/host/ehci-hcd.c 2005-03-02 15:38:38.000000000 +0800
+++ linux-8349-2.6/drivers/usb/host/ehci-hcd.c 2005-08-15 10:40:35.000000000 +0800
@@ -16,6 +16,13 @@
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#ifdef CONFIG_FSL_USB20
+#ifdef CONFIG_USB_DEBUG
+ #define DEBUG
+#else
+ #undef DEBUG
+#endif
+#else
#include <linux/config.h>
#ifdef CONFIG_USB_DEBUG
@@ -101,8 +108,17 @@
#define DRIVER_AUTHOR "David Brownell"
#define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver"
-static const char hcd_name [] = "ehci_hcd";
+#endif
+#ifdef CONFIG_FSL_USB20
+#if defined (CONFIG_MPH_USB_SUPPORT)
+static const char hcd_name [] = "fsl-usb2-mph";
+#elif defined (CONFIG_DR_USB_SUPPORT)
+static const char hcd_name [] = "fsl-usb2-dr";
+#endif
+#else
+static const char hcd_name [] = "ehci_hcd";
+#endif
#undef EHCI_VERBOSE_DEBUG
#undef EHCI_URB_TRACE
@@ -112,6 +128,7 @@
#endif
/* magic numbers that can affect system performance */
+
#define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */
#define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */
#define EHCI_TUNE_RL_TT 0
@@ -126,13 +143,18 @@
/* Initial IRQ latency: faster than hw default */
static int log2_irq_thresh = 0; // 0 to 6
+#ifdef CONFIG_FSL_USB20
+#else
module_param (log2_irq_thresh, int, S_IRUGO);
MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes");
-
+#endif
/* initial park setting: slower than hw default */
static unsigned park = 0;
+#ifdef CONFIG_FSL_USB20
+#else
module_param (park, uint, S_IRUGO);
MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets");
+#endif
#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
@@ -190,7 +212,27 @@
writel (temp, &ehci->regs->command);
return handshake (&ehci->regs->status, STS_HALT, STS_HALT, 16 * 125);
}
+#ifdef CONFIG_FSL_USB20
+static void mpc8349_usb_reset(void);
+/* reset a non-running (STS_HALT == 1) controller */
+static int ehci_reset (struct ehci_hcd *ehci)
+{
+ int retval;
+ u32 command = readl (&ehci->regs->command);
+ command |= CMD_RESET;
+ dbg_cmd (ehci, "reset", command);
+ writel (command, &ehci->regs->command);
+ ehci_to_hcd(ehci)->state = USB_STATE_HALT;
+ ehci->next_statechange = jiffies;
+ retval = handshake (&ehci->regs->command, CMD_RESET, 0, 250 * 1000);
+
+ if (retval)
+ return retval;
+ mpc8349_usb_reset ();
+ return retval;
+}
+#else
/* reset a non-running (STS_HALT == 1) controller */
static int ehci_reset (struct ehci_hcd *ehci)
{
@@ -203,7 +245,7 @@
ehci->next_statechange = jiffies;
return handshake (&ehci->regs->command, CMD_RESET, 0, 250 * 1000);
}
-
+#endif
/* idle the controller (from running) */
static void ehci_quiesce (struct ehci_hcd *ehci)
{
@@ -276,7 +318,7 @@
spin_unlock_irqrestore (&ehci->lock, flags);
}
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) && !defined(CONFIG_FSL_USB20)
/* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/...
* off the controller (maybe it can boot from highspeed USB disks).
@@ -285,18 +327,22 @@
{
if (cap & (1 << 16)) {
int msec = 5000;
+
struct pci_dev *pdev =
to_pci_dev(ehci_to_hcd(ehci)->self.controller);
/* request handoff to OS */
cap |= 1 << 24;
+
pci_write_config_dword(pdev, where, cap);
/* and wait a while for it to happen */
do {
msleep(10);
msec -= 10;
+
pci_read_config_dword(pdev, where, &cap);
+
} while ((cap & (1 << 16)) && msec);
if (cap & (1 << 16)) {
ehci_err (ehci, "BIOS handoff failed (%d, %04x)\n",
@@ -332,7 +378,10 @@
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
u32 temp;
+#ifdef CONFIG_FSL_USB20
+#else
unsigned count = 256/4;
+#endif
spin_lock_init (&ehci->lock);
@@ -340,8 +389,14 @@
ehci->regs = hcd->regs + HC_LENGTH (readl (&ehci->caps->hc_capbase));
dbg_hcs_params (ehci, "reset");
dbg_hcc_params (ehci, "reset");
+
-#ifdef CONFIG_PCI
+#ifdef CONFIG_FSL_USB20
+ mpc8349_usb_reset ();
+ ehci->is_arc_rh_tt = 1;
+#endif
+
+#if defined(CONFIG_PCI) && !defined(CONFIG_FSL_USB20)
/* EHCI 0.96 and later may have "extended capabilities" */
if (hcd->self.controller->bus == &pci_bus_type) {
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
@@ -395,7 +450,7 @@
HCS_N_PCC(ehci->hcs_params),
HCS_N_PORTS(ehci->hcs_params));
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) && !defined(CONFIG_FSL_USB20)
if (hcd->self.controller->bus == &pci_bus_type) {
struct pci_dev *pdev;
@@ -465,7 +520,7 @@
}
writel (ehci->periodic_dma, &ehci->regs->frame_list);
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) && !defined(CONFIG_FSL_USB20)
if (hcd->self.controller->bus == &pci_bus_type) {
struct pci_dev *pdev;
u16 port_wake;
@@ -829,7 +884,7 @@
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
u32 status;
int bh;
-
+
spin_lock (&ehci->lock);
status = readl (&ehci->regs->status);
@@ -1181,6 +1236,9 @@
/*-------------------------------------------------------------------------*/
/* EHCI 1.0 doesn't require PCI */
+#ifdef CONFIG_FSL_USB20
+
+#else
#ifdef CONFIG_PCI
@@ -1236,3 +1294,4 @@
pci_unregister_driver (&ehci_pci_driver);
}
module_exit (cleanup);
+#endif
diff -Nur linux/drivers/usb/host/ehci-mem.c linux-8349-2.6/drivers/usb/host/ehci-mem.c
--- linux/drivers/usb/host/ehci-mem.c 2005-03-02 15:38:26.000000000 +0800
+++ linux-8349-2.6/drivers/usb/host/ehci-mem.c 2005-08-15 10:46:53.000000000 +0800
@@ -49,8 +49,13 @@
{
struct ehci_qtd *qtd;
dma_addr_t dma;
-
+#ifdef CONFIG_FSL_USB20
+ qtd = MEM_Get( ehci->qtd_pool);
+ dma = virt_to_phys(qtd);
+ memset(qtd, 0, sizeof(*qtd));
+#else
qtd = dma_pool_alloc (ehci->qtd_pool, flags, &dma);
+#endif
if (qtd != NULL) {
ehci_qtd_init (qtd, dma);
}
@@ -59,7 +64,11 @@
static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd)
{
+#ifdef CONFIG_FSL_USB20
+ MEM_Put(ehci->qtd_pool, qtd);
+#else
dma_pool_free (ehci->qtd_pool, qtd, qtd->qtd_dma);
+#endif
}
@@ -75,8 +84,12 @@
}
if (qh->dummy)
ehci_qtd_free (ehci, qh->dummy);
+#ifdef CONFIG_FSL_USB20
+ MEM_Put(ehci->qh_pool, qh);
+#else
usb_put_dev (qh->dev);
dma_pool_free (ehci->qh_pool, qh, qh->qh_dma);
+#endif
}
static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags)
@@ -84,8 +97,14 @@
struct ehci_qh *qh;
dma_addr_t dma;
+#ifdef CONFIG_FSL_USB20
+ qh = (struct ehci_qh *) MEM_Get(ehci->qh_pool);
+ dma = virt_to_phys(qh);
+ memset(qh, 0, sizeof(*qh));
+#else
qh = (struct ehci_qh *)
dma_pool_alloc (ehci->qh_pool, flags, &dma);
+#endif
if (!qh)
return qh;
@@ -100,7 +119,11 @@
qh->dummy = ehci_qtd_alloc (ehci, flags);
if (qh->dummy == NULL) {
ehci_dbg (ehci, "no dummy td\n");
+#ifdef CONFIG_FSL_USB20
+ MEM_Put(ehci->qh_pool, qh);
+#else
dma_pool_free (ehci->qh_pool, qh, qh->qh_dma);
+#endif
qh = NULL;
}
return qh;
@@ -133,26 +156,46 @@
/* DMA consistent memory and pools */
if (ehci->qtd_pool)
+#ifdef CONFIG_FSL_USB20
+ MEM_Free(ehci->qtd_pool);
+#else
dma_pool_destroy (ehci->qtd_pool);
+#endif
ehci->qtd_pool = NULL;
if (ehci->qh_pool) {
+#ifdef CONFIG_FSL_USB20
+ MEM_Free(ehci->qh_pool);
+#else
dma_pool_destroy (ehci->qh_pool);
+#endif
ehci->qh_pool = NULL;
}
if (ehci->itd_pool)
+#ifdef CONFIG_FSL_USB20
+ MEM_Free(ehci->itd_pool);
+#else
dma_pool_destroy (ehci->itd_pool);
+#endif
ehci->itd_pool = NULL;
if (ehci->sitd_pool)
+#ifdef CONFIG_FSL_USB20
+ MEM_Free(ehci->sitd_pool);
+#else
dma_pool_destroy (ehci->sitd_pool);
+#endif
ehci->sitd_pool = NULL;
if (ehci->periodic)
+#ifdef CONFIG_FSL_USB20
+ kfree((void *)ehci->orig_periodic);
+#else
dma_free_coherent (ehci_to_hcd(ehci)->self.controller,
ehci->periodic_size * sizeof (u32),
ehci->periodic, ehci->periodic_dma);
+#endif
ehci->periodic = NULL;
/* shadow periodic table */
@@ -165,23 +208,31 @@
static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
{
int i;
+ int err;
/* QTDs for control/bulk/intr transfers */
+#ifdef CONFIG_FSL_USB20
+ err = MEM_Init("ehci_qtd_pool", (void **)&ehci->qtd_pool, 128, sizeof(struct ehci_qtd), 0, 0, 32);
+#else
ehci->qtd_pool = dma_pool_create ("ehci_qtd",
ehci_to_hcd(ehci)->self.controller,
sizeof (struct ehci_qtd),
32 /* byte alignment (for hw parts) */,
4096 /* can't cross 4K */);
+#endif
if (!ehci->qtd_pool) {
goto fail;
}
-
+#ifdef CONFIG_FSL_USB20
+ err = MEM_Init("ehci_qh_pool", (void **)&ehci->qh_pool, 128, sizeof(struct ehci_qh), 0, 0, 64);
+#else
/* QHs for control/bulk/intr transfers */
ehci->qh_pool = dma_pool_create ("ehci_qh",
ehci_to_hcd(ehci)->self.controller,
sizeof (struct ehci_qh),
32 /* byte alignment (for hw parts) */,
4096 /* can't cross 4K */);
+#endif
if (!ehci->qh_pool) {
goto fail;
}
@@ -191,30 +242,47 @@
}
/* ITD for high speed ISO transfers */
+#ifdef CONFIG_FSL_USB20
+ err = MEM_Init("ehci_itd_pool", (void **)&ehci->itd_pool, 128, sizeof(struct ehci_itd), 0, 0, 32);
+#else
ehci->itd_pool = dma_pool_create ("ehci_itd",
ehci_to_hcd(ehci)->self.controller,
sizeof (struct ehci_itd),
32 /* byte alignment (for hw parts) */,
4096 /* can't cross 4K */);
+#endif
if (!ehci->itd_pool) {
goto fail;
}
/* SITD for full/low speed split ISO transfers */
+#ifdef CONFIG_FSL_USB20
+ err = MEM_Init("ehci_sitd_pool", (void**)&ehci->sitd_pool, 128, sizeof(struct ehci_sitd), 0, 0, 32);
+#else
ehci->sitd_pool = dma_pool_create ("ehci_sitd",
ehci_to_hcd(ehci)->self.controller,
sizeof (struct ehci_sitd),
32 /* byte alignment (for hw parts) */,
4096 /* can't cross 4K */);
+#endif
if (!ehci->sitd_pool) {
goto fail;
}
/* Hardware periodic table */
+#ifdef CONFIG_FSL_USB20
+ ehci->orig_periodic =(u32)kmalloc((int)(ehci->periodic_size * sizeof (u32))+0x1000,GFP_KERNEL);
+ if(ehci->orig_periodic%0x1000)
+ ehci->periodic = (__le32 *)(((ehci->orig_periodic>>12)<<12)+0x1000);
+ else
+ ehci->periodic = (__le32 *)ehci->orig_periodic;
+ ehci->periodic_dma = virt_to_phys(ehci->periodic);
+#else
ehci->periodic = (__le32 *)
dma_alloc_coherent (ehci_to_hcd(ehci)->self.controller,
ehci->periodic_size * sizeof(__le32),
&ehci->periodic_dma, 0);
+#endif
if (ehci->periodic == NULL) {
goto fail;
}
diff -Nur linux/drivers/usb/host/ehci-q.c linux-8349-2.6/drivers/usb/host/ehci-q.c
--- linux/drivers/usb/host/ehci-q.c 2005-03-02 15:38:19.000000000 +0800
+++ linux-8349-2.6/drivers/usb/host/ehci-q.c 2005-08-15 10:50:13.000000000 +0800
@@ -500,7 +500,11 @@
is_input = usb_pipein (urb->pipe);
if (usb_pipecontrol (urb->pipe)) {
/* SETUP pid */
+#ifdef CONFIG_FSL_USB20
+ qtd_fill (qtd, virt_to_phys(urb->setup_packet), sizeof (struct usb_ctrlrequest),
+#else
qtd_fill (qtd, urb->setup_dma, sizeof (struct usb_ctrlrequest),
+#endif
token | (2 /* "setup" */ << 8), 8);
/* ... and always at least one more pid */
@@ -518,7 +522,11 @@
* data transfer stage: buffer setup
*/
if (likely (len > 0))
+#ifdef CONFIG_FSL_USB20
+ buf = virt_to_phys(urb->transfer_buffer);
+#else
buf = urb->transfer_dma;
+#endif
else
buf = 0;
@@ -712,8 +720,11 @@
info1 |= maxp << 16;
info2 |= (EHCI_TUNE_MULT_TT << 30);
+#ifdef CONFIG_FSL_USB20
+ info2 |= (urb->dev->ttport-1) << 23;
+#else
info2 |= urb->dev->ttport << 23;
-
+#endif
/* set the address of the TT; for ARC's integrated
* root hub tt, leave it zeroed.
*/
@@ -863,7 +874,11 @@
dummy = qh->dummy;
dma = dummy->qtd_dma;
+#ifdef CONFIG_FSL_USB20
+ memcpy(dummy,qtd,sizeof(struct ehci_qtd));
+#else
*dummy = *qtd;
+#endif
dummy->qtd_dma = dma;
list_del (&qtd->qtd_list);
@@ -925,6 +940,7 @@
if (likely (qh != NULL)) {
if (likely (qh->qh_state == QH_STATE_IDLE))
qh_link_async (ehci, qh_get (qh));
+
}
spin_unlock_irqrestore (&ehci->lock, flags);
if (unlikely (qh == NULL)) {
diff -Nur linux/drivers/usb/host/ehci-sched.c linux-8349-2.6/drivers/usb/host/ehci-sched.c
--- linux/drivers/usb/host/ehci-sched.c 2005-03-02 15:37:53.000000000 +0800
+++ linux-8349-2.6/drivers/usb/host/ehci-sched.c 2005-08-15 10:53:16.000000000 +0800
@@ -699,8 +699,11 @@
} else {
u32 addr;
-
+#ifdef CONFIG_FSL_USB20
+ addr = (u32)((dev->ttport-1) << 24);
+#else
addr = dev->ttport << 24;
+#endif
addr |= dev->tt->hub->devnum << 16;
addr |= epnum << 8;
addr |= dev->devnum;
@@ -759,15 +762,23 @@
itd = list_entry (entry, struct ehci_itd,
itd_list);
+#ifdef CONFIG_FSL_USB20
+ MEM_Put(ehci->itd_pool, itd);
+#else
dma_pool_free (ehci->itd_pool, itd,
itd->itd_dma);
+#endif
} else {
struct ehci_sitd *sitd;
sitd = list_entry (entry, struct ehci_sitd,
sitd_list);
+#ifdef CONFIG_FSL_USB20
+ MEM_Put(ehci->sitd_pool, sitd);
+#else
dma_pool_free (ehci->sitd_pool, sitd,
sitd->sitd_dma);
+#endif
}
}
@@ -865,8 +876,11 @@
)
{
unsigned i;
+#ifdef CONFIG_FSL_USB20
+ dma_addr_t dma = virt_to_phys(urb->transfer_buffer);
+#else
dma_addr_t dma = urb->transfer_dma;
-
+#endif
/* how many uframes are needed for these transfers */
iso_sched->span = urb->number_of_packets * stream->interval;
@@ -956,8 +970,14 @@
if (!itd) {
spin_unlock_irqrestore (&ehci->lock, flags);
+#ifdef CONFIG_FSL_USB20
+ itd = MEM_Get(ehci->itd_pool);
+ itd_dma = virt_to_phys(itd);
+
+#else
itd = dma_pool_alloc (ehci->itd_pool, mem_flags,
&itd_dma);
+#endif
spin_lock_irqsave (&ehci->lock, flags);
}
@@ -1559,8 +1579,13 @@
if (!sitd) {
spin_unlock_irqrestore (&ehci->lock, flags);
+#ifdef CONFIG_FSL_USB20
+ sitd = MEM_Get (ehci->sitd_pool);
+ sitd_dma = virt_to_phys(sitd);
+#else
sitd = dma_pool_alloc (ehci->sitd_pool, mem_flags,
&sitd_dma);
+#endif
spin_lock_irqsave (&ehci->lock, flags);
}
diff -Nur linux/drivers/usb/host/fsl-usb.c linux-8349-2.6/drivers/usb/host/fsl-usb.c
--- linux/drivers/usb/host/fsl-usb.c 1970-01-01 08:00:00.000000000 +0800
+++ linux-8349-2.6/drivers/usb/host/fsl-usb.c 2005-08-25 11:50:08.000000000 +0800
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2005 freescale semiconductor
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/reboot.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#include <asm/unaligned.h>
+
+#include "../core/hcd.h"
+#include "fsl-usb.h"
+
+#define DRIVER_VERSION "$Revision: 1.11 $"
+#define DRIVER_AUTHOR "Hunter Wu"
+#define DRIVER_DESC "USB 2.0 Freescale EHCI Driver"
+#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
+
+MODULE_DESCRIPTION("MPC8249 USB Host Controller Driver");
+
+#include "ehci-hcd.c"
+
+void mpc8349_board_init(void)
+{
+ volatile unsigned char *bcsr5_p;
+
+ /* if SYS board is plug into PIB board, force to use the PHY on SYS board */
+ bcsr5_p = (volatile unsigned char *)(CFG_BCSR_BASE + 0x00000005);
+ if ( (*bcsr5_p & BCSR5_INT_USB) == 0 )
+ *bcsr5_p = (*bcsr5_p | BCSR5_INT_USB);
+}
+
+void mpc8349_usb_clk_cfg(void)
+{
+ unsigned long sccr;
+ volatile unsigned long *p;
+
+ p = (volatile unsigned long *)(CFG_IMMR_BASE + SCCR_OFFS); /* SCCR */
+ sccr = *p;
+
+#if defined(CONFIG_MPH_USB_SUPPORT)
+ sccr &= ~SCCR_USB_MPHCM_11;
+ sccr |= SCCR_USB_MPHCM_11; /* USB CLK 1:3 CSB CLK */
+ *p = sccr;
+#elif defined(CONFIG_DR_USB_SUPPORT)
+ sccr &= ~SCCR_USB_DRCM_11;
+ sccr |= SCCR_USB_DRCM_11; /* USB CLK 1:3 CSB CLK */
+ *p = sccr;
+#endif
+
+}
+
+void mpc8349_usb_pin_cfg(void)
+{
+ unsigned long sicrl;
+ volatile unsigned long *p;
+
+ p = (volatile unsigned long *)(CFG_IMMR_BASE + SICRL_OFFS); /* SCCR */
+ sicrl = *p;
+
+#if defined(CONFIG_MPH_USB_SUPPORT)
+#ifdef CONFIG_MPH0_USB_ENABLE
+ sicrl &= ~SICRL_USB0;
+ *p = sicrl;
+#endif
+
+#ifdef CONFIG_MPH1_USB_ENABLE
+ sicrl &= ~SICRL_USB1;
+ *p = sicrl;
+#endif
+#elif defined(CONFIG_DR_USB_SUPPORT)
+ sicrl &= ~SICRL_USB0;
+ sicrl |= SICRL_USB1 ;
+ *p = sicrl;
+#if defined(CONFIG_DR_UTMI)
+ sicrl &= ~SICRL_USB0;
+ sicrl |= SICRL_USB0;
+ *p = sicrl;
+#endif
+
+#endif
+}
+
+static void mpc8349_usb_reset(void)
+{
+ u32 portsc;
+
+#if defined(CONFIG_MPH_USB_SUPPORT)
+ t_USB_MPH_MAP *p_MphMemMap;
+ /* Enable PHY interface in the control reg. */
+ p_MphMemMap = (t_USB_MPH_MAP *)MPC83xx_USB_MPH_BASE;
+ p_MphMemMap->control = 0x00000004;
+ p_MphMemMap->snoop1 = 0x0000001b;
+#ifdef CONFIG_MPH0_USB_ENABLE
+ portsc = readl(&p_MphMemMap->port_status[0]);
+ portsc &= ~PORT_TS;
+#if defined(CONFIG_MPH0_ULPI)
+ portsc |= PORT_TS_ULPI;
+#elif defined (CONFIG_MPH0_SERIAL)
+ portsc |= PORT_TS_SERIAL;
+#endif
+ writel(portsc,&p_MphMemMap->port_status[0]);
+#endif
+
+#ifdef CONFIG_MPH1_USB_ENABLE
+ portsc = readl(&p_MphMemMap->port_status[1]);
+ portsc &= ~PORT_TS;
+#if defined(CONFIG_MPH1_ULPI)
+ portsc |= PORT_TS_ULPI;
+#elif defined (CONFIG_MPH1_SERIAL)
+ portsc |= PORT_TS_SERIAL;
+#endif
+ writel(portsc,&p_MphMemMap->port_status[1]);
+#endif
+
+ p_MphMemMap->pri_ctrl = 0x0000000c;
+ p_MphMemMap->age_cnt_thresh = 0x00000040;
+ p_MphMemMap->si_ctrl= 0x00000001;
+
+#elif defined(CONFIG_DR_USB_SUPPORT)
+ t_USB_DR_MAP *p_DrMemMap;
+ p_DrMemMap = (t_USB_DR_MAP *)MPC83xx_USB_DR_BASE;
+ p_DrMemMap->control = 0x00000004;
+ p_DrMemMap->snoop1 = 0x0000001b;
+ portsc = readl(&p_DrMemMap->port_status[0]);
+ portsc &= ~PORT_TS;
+#if defined(CONFIG_DR_ULPI)
+ portsc |= PORT_TS_ULPI;
+#elif defined(CONFIG_DR_SERIAL)
+ portsc |= PORT_TS_SERIAL;
+#elif defined(CONFIG_DR_UTMI)
+ portsc |= PORT_TS_ULPI;
+#endif
+
+ writel(portsc,&p_DrMemMap->port_status[0]);
+ writel(0x00000003,&p_DrMemMap->usbmode);
+ p_DrMemMap->pri_ctrl = 0x0000000c;
+ p_DrMemMap->age_cnt_thresh = 0x00000040;
+ p_DrMemMap->si_ctrl= 0x00000001;
+#endif
+}
+
+
+static int __init
+fsl_usb20_probe(struct device *dev)
+{
+ struct usb_hcd *hcd;
+ struct ehci_hcd *ehci;
+ int retval;
+#if defined (CONFIG_MPH_USB_SUPPORT)
+ t_USB_MPH_MAP *p_MphMemMap;
+#elif defined (CONFIG_DR_USB_SUPPORT)
+ t_USB_DR_MAP *p_DrMemMap;
+#endif
+ mpc8349_board_init();
+ mpc8349_usb_clk_cfg();
+ mpc8349_usb_pin_cfg();
+
+ hcd = usb_create_hcd(&ehci_driver);
+ if (!hcd) {
+ retval = 0;
+ goto err1;
+ }
+
+ ehci = hcd_to_ehci(hcd);
+ dev_set_drvdata(dev, ehci);
+
+#if defined(CONFIG_MPH_USB_SUPPORT)
+ p_MphMemMap = (t_USB_MPH_MAP *)MPC83xx_USB_MPH_BASE;
+
+ hcd->regs = (void *)(&p_MphMemMap->hc_capbase);
+ hcd->irq = MPC83xx_USB_MPH_IVEC;
+
+#elif defined (CONFIG_DR_USB_SUPPORT)
+ /* Enable PHY interface in the control reg. */
+ p_DrMemMap = (t_USB_DR_MAP *)MPC83xx_USB_DR_BASE;
+ hcd->regs = (void *)(&p_DrMemMap->hc_capbase);/* Set the interrupt that is called for this USB. */
+ hcd->irq = MPC83xx_USB_DR_IVEC;
+
+#endif
+
+ hcd->self.controller = dev;
+ hcd->self.bus_name = dev->bus_id;
+ hcd->product_desc ="fsl usb20";
+
+ retval = request_irq(hcd->irq, usb_hcd_irq, SA_INTERRUPT,hcd->driver->description, hcd);
+ if (retval != 0)
+ goto err2;
+ retval = usb_register_bus(&hcd->self);
+ if (retval < 0)
+ goto err3;
+
+ retval=ehci_hc_reset(hcd);
+
+ if (retval < 0)
+ goto err4;
+
+ if ((retval = ehci_start (hcd)) < 0) {
+ goto err4;
+ }
+
+ return 0;
+err4:
+ usb_deregister_bus(&hcd->self);
+err3:
+ free_irq(hcd->irq, hcd);
+err2:
+ usb_put_hcd(hcd);
+err1:
+ printk("init error, %d\n", retval);
+ return retval;
+}
+
+static int __init_or_module
+fsl_usb20_remove(struct device *dev)
+{
+ struct ehci_hcd *ehci = dev_get_drvdata(dev);
+ struct usb_hcd *hcd = ehci_to_hcd(ehci);
+
+
+ if (HCD_IS_RUNNING(hcd->state))
+ hcd->state = USB_STATE_QUIESCING;
+
+ usb_disconnect(&hcd->self.root_hub);
+
+ hcd->driver->stop (hcd);
+
+ usb_deregister_bus(&hcd->self);
+
+ free_irq(hcd->irq, hcd);
+
+ usb_put_hcd(hcd);
+ return 0;
+}
+
+#define fsl_usb20_suspend NULL
+#define fsl_usb20_resume NULL
+
+static struct device_driver fsl_usb20_driver = {
+ .name = (char *) hcd_name,
+ .bus = &platform_bus_type,
+
+ .probe = fsl_usb20_probe,
+ .remove = fsl_usb20_remove,
+
+ .suspend = fsl_usb20_suspend,
+ .resume = fsl_usb20_resume,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init mpc8349_usb_hc_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ printk(KERN_INFO"driver %s, %s\n", hcd_name, DRIVER_VERSION);
+ return driver_register(&fsl_usb20_driver);
+}
+
+
+static void __exit mpc8349_usb_hc_deinit(void)
+{
+ driver_unregister(&fsl_usb20_driver);
+}
+MODULE_DESCRIPTION (DRIVER_INFO);
+MODULE_AUTHOR (DRIVER_AUTHOR);
+MODULE_LICENSE ("GPL");
+module_init(mpc8349_usb_hc_init);
+module_exit(mpc8349_usb_hc_deinit);
diff -Nur linux/drivers/usb/host/fsl-usb.h linux-8349-2.6/drivers/usb/host/fsl-usb.h
--- linux/drivers/usb/host/fsl-usb.h 1970-01-01 08:00:00.000000000 +0800
+++ linux-8349-2.6/drivers/usb/host/fsl-usb.h 2005-08-25 11:49:00.000000000 +0800
@@ -0,0 +1,406 @@
+/* Copyright (c) 2005 freescale semiconductor
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef _MPC8349_USB_EHCI_H
+#define _MPC8349_USB_EHCI_H
+
+/**************************************************************************/
+/*@Description t_USB_MPH_MAP - USB Multi-Port-Host internal memory map.*/
+/***************************************************************************/
+typedef struct{
+ volatile u32 id; /* Identification register */
+ volatile u32 hwgeneral;
+ volatile u32 hwhost;
+ volatile u8 RESERVED01[0x004]; /* Reserved area */
+ volatile u32 hwtxbuf;
+ volatile u32 hwrxbuf;
+ volatile u8 RESERVED02[0x0e8]; /* Reserved area */
+
+ /* Capability Registers */
+ volatile u32 hc_capbase;
+ volatile u32 hcs_params; /* HCSPARAMS - offset 0x4 */
+ volatile u32 hcc_params; /* HCCPARAMS - offset 0x8 */
+ volatile u8 portroute [8]; /* nibbles for routing - offset 0xC */
+ volatile u8 RESERVED03[0x02c]; /* Reserved area */
+
+ /* Operational Registers */
+ volatile u32 command;
+ volatile u32 status;
+ volatile u32 intr_enable;
+ volatile u32 frame_index; /* current microframe number */
+ volatile u32 segment; /* address bits 63:32 if needed */
+ volatile u32 frame_list; /* points to periodic list */
+ volatile u32 async_next; /* address of next async queue head */
+ volatile u32 async_tt_status; /* async queue status for embedded TT */
+ volatile u32 burst_size; /* programmable burst size */
+ volatile u32 txfilltuning; /* host transmit pre-buffer packet tuning */
+ volatile u32 txttfilltuning; /* host TT transmit pre-buffer packet tuning */
+ volatile u8 RESERVED04[4];
+ volatile u32 ulpi_view_port; /* ULPI view port */
+ volatile u32 endpoint_nack; /* endpoint nack */
+ volatile u32 endpoint_nack_en; /* endpoint nack enable */
+ volatile u8 RESERVED05[4];
+ volatile u32 configured_flag;
+ volatile u32 port_status [2]; /* up to N_PORTS */
+
+ volatile u8 RESERVED06[0x01c]; /* Reserved area */
+ volatile u32 usbmode;
+ volatile u8 RESERVED07[0x254]; /* Reserved area */
+ volatile u32 snoop1;
+ volatile u32 snoop2;
+ volatile u32 age_cnt_thresh;
+ volatile u32 si_ctrl;
+ volatile u32 pri_ctrl;
+ volatile u8 RESERVED08[0x0ec]; /* Reserved area */
+ volatile u32 control;
+ volatile u8 RESERVED09[0xaf8]; /* Reserved area */
+} t_USB_MPH_MAP;
+
+/**************************************************************************/
+/** @Description t_USB_DR_MAP - USB Dual-Role internal memory map. */
+/***************************************************************************/
+typedef struct{
+ volatile u32 id; /* Identification register */
+ volatile u32 hwgeneral;
+ volatile u32 hwhost;
+ volatile u32 hwdevice;
+ volatile u32 hwtxbuf;
+ volatile u32 hwrxbuf;
+ volatile u8 RESERVED01[0x0e8]; /* Reserved area */
+
+ /* Capability Registers */
+ volatile u32 hc_capbase;
+ volatile u32 hcs_params; /* HCSPARAMS - offset 0x4 */
+ volatile u32 hcc_params; /* HCCPARAMS - offset 0x8 */
+ volatile u8 portroute [8]; /* nibbles for routing - offset 0xC */
+ volatile u8 RESERVED02[0x00c]; /* Reserved area */
+ volatile u32 dciversion;
+ volatile u32 dccparms;
+ volatile u8 RESERVED03[0x018]; /* Reserved area */
+
+ /* Operational Registers */
+ volatile u32 command;
+ volatile u32 status;
+ volatile u32 intr_enable;
+ volatile u32 frame_index; /* current microframe number */
+ union t_host_slave_regs {
+ struct t_ehci_regs
+ {
+ volatile u32 segment; /* address bits 63:32 if needed */
+ volatile u32 frame_list; /* points to periodic list */
+ volatile u32 async_next; /* address of next async queue head */
+ } host_regs;
+ struct t_slave_regs {
+ volatile u8 RESERVED04 [0x04];
+ volatile u32 deviceaddr;
+ volatile u32 endpoint_list_addr; /* points to periodic list */
+ } slave_regs;
+ } host_slave_regs;
+ volatile u32 async_tt_status; /* async queue status for embedded TT */
+ volatile u32 burst_size; /* programmable burst size */
+ volatile u32 txfilltuning; /* host transmit pre-buffer packet tuning */
+ volatile u32 txttfilltuning; /* host TT transmit pre-buffer packet tuning */
+ volatile u8 RESERVED04[4];
+ volatile u32 ulpi_view_port; /* ULPI view port */
+ volatile u32 endpoint_nack; /* endpoint nack */
+ volatile u32 endpoint_nack_en; /* endpoint nack enable */
+ volatile u8 RESERVED05[4];
+ volatile u32 configured_flag;
+ volatile u32 port_status [1]; /* up to N_PORTS */
+
+ volatile u8 RESERVED06[0x01c]; /* Reserved area */
+ volatile u32 otgsc;
+ volatile u32 usbmode;
+ volatile u32 endptsetupstat;
+ volatile u32 endptprime;
+ volatile u32 endptflush;
+ volatile u32 endptstatus;
+ volatile u32 endptcomplete;
+ volatile u32 endptctrl[6];
+ volatile u8 RESERVED07[0x228]; /* Reserved area */
+ volatile u32 snoop1;
+ volatile u32 snoop2;
+ volatile u32 age_cnt_thresh;
+ volatile u32 si_ctrl;
+ volatile u32 pri_ctrl;
+ volatile u8 RESERVED08[0x0ec]; /* Reserved area */
+ volatile u32 control;
+ volatile u8 RESERVED09[0xaf8]; /* Reserved area */
+} __attribute__ ((packed)) t_USB_DR_MAP, * t_pUSB_DR_MAP;
+
+
+
+#define PORT_OFF 0
+#define PORT_ULPI 1
+#define PORT_UTMI 2
+#define PORT_SERIAL 3
+#define PORT_SERIAL_OTG 4
+
+
+#define PORT_TS 0xc0000000
+#define PORT_TS_UTMI 0x00000000
+#define PORT_TS_ULPI 0x80000000
+#define PORT_TS_SERIAL 0xc0000000
+#define PORT_TW 0x10000000
+#define PORT_SPD 0x0c000000
+#define PORT_FSC 0x01000000
+#define PORT_PP 0x00001000
+
+
+
+#define CFG_IMMR_BASE (0xfe000000)
+#define MPC83xx_USB_MPH_BASE (CFG_IMMR_BASE + 0x22000)
+#define MPC83xx_USB_DR_BASE (CFG_IMMR_BASE + 0x23000)
+#define MPC83xx_USB_DR_IVEC (38)
+#define MPC83xx_USB_MPH_IVEC (39)
+#define CFG_BCSR_BASE (0xfe100000)
+#define BCSR5_INT_USB (0x02)
+
+#define e_USB_MPH 0
+#define e_USB_DR 1
+#define e_ULPI 0
+#define e_UTMI_8BIT 1
+#define e_UTMI_16BIT 2
+#define e_SERIAL 3
+
+#define SCCR_OFFS 0xA08
+#define SCCR_USB_MPHCM_11 0x00c00000
+#define SCCR_USB_MPHCM_01 0x00400000
+#define SCCR_USB_MPHCM_10 0x00800000
+#define SCCR_USB_DRCM_11 0x00300000
+#define SCCR_USB_DRCM_01 0x00100000
+#define SCCR_USB_DRCM_10 0x00200000
+
+#define SICRL_OFFS 0x114
+#define SICRL_USB1 0x40000000
+#define SICRL_USB0 0x20000000
+
+#define SICRH_OFFS 0x118
+#define SICRH_USB_UTMI 0x00020000
+
+#define SPCR_OFFS 0x00000110
+#define SPCR_TBEN 0x00400000
+
+#define POWER_OF_2(n) (!(n & (n-1)))
+
+/*------------------------------------------------------*/
+
+typedef struct
+{
+ char Name[4]; /* this segment's name */
+ spinlock_t lock;
+ u16 Num; /* number of blocks in segment */
+ int Size; /* size of blocks in segment */
+ /* in case of TMP_DEF - */
+ /* only the data */
+ u32 GetFailures; /* number of times get failed */
+ int LocallyAllocated; /* TRUE if memory was allocated */
+ /* at MEM_Init. */
+ u8 *p_Base; /* base address of segment */
+ void **p_First; /* first block in segment */
+ void **p_Last; /* last block in segment */
+ int (*f_MemPut)(void* Handle, void *p_Block );
+ /* a routine for returning a memory block */
+
+ u16 PrefixSize; /* replaces B_OFFSET - how many */
+ /* bytes to reserve before the data */
+ u16 PostfixSize ; /* replaces B_TRAILER - how many */
+ /* bytes to reserve after the data */
+ /* Trailer also includes a pad needed for */
+ /* padding the entire block to 4 byte */
+ /* alignment for faster access to the */
+ /* control field */
+ u16 Alignment; /* requested alignment for the data field */
+ u16 AlignPad; /* pad the offset field so that the data */
+ /* field shall have the proper alignment */
+ u16 EndPad; /* Pad to make entire block size a */
+ /* multiple of Alignment */
+} t_MemorySegment;
+
+#define PAD_ALIGNMENT( align, x ) ( ((x)%(align)) ? ((align)-((x)%(align))) : 0 )
+
+
+void *MEM_Get( void* Handle )
+{
+ unsigned long flags;
+ u8 *p_F;
+ t_MemorySegment *p ;
+
+ p = (t_MemorySegment *)Handle;
+
+ spin_lock_irqsave(&p->lock,flags);
+
+ /* check if the chain is not empty */
+ if( !(*(p->p_First)) )
+ {
+ p->GetFailures++;
+ spin_unlock_irqrestore(p->lock,flags);
+ return 0;
+ }
+ /* advance first pointer and return the old head of chain */
+ p_F = ((u8 *)p->p_First) + ( 4 + p->AlignPad + p->PrefixSize );
+ p->p_First = (void **) *(p->p_First); /* skip the next pointer */
+
+ spin_unlock_irqrestore(&p->lock,flags);
+
+ return (void *)p_F;
+}
+
+
+int MEM_Put_Default( void * Handle, void *p_Block )
+{
+ unsigned long flags;
+ t_MemorySegment *p = (t_MemorySegment *)Handle;
+ u8 *p_B = (u8 *)p_Block;
+
+ /* if handle is NULL, use user's free routine */
+ if( Handle == 0 )
+ {
+ kfree( p_Block );
+ return 0;
+ }
+
+ spin_lock_irqsave(&p->lock,flags);
+
+ /* get the pointer to the start of the memory */
+ p_B -= ( 4 + p->AlignPad + p->PrefixSize ); /* skip back over next pointer */
+ /* chain to end and advance last pointer */
+ *((void **)p_B) = 0;
+ *(p->p_Last) = (void *)p_B;
+ p->p_Last = (void **)p_B;
+
+ spin_unlock_irqrestore(&p->lock,flags);
+ return 0;
+}
+
+int MEM_Init( char Name[],
+ void* *p_Handle,
+ u16 Num,
+ u16 Size ,
+ u16 PrefixSize,
+ u16 PostfixSize,
+ u16 Alignment )
+{
+ t_MemorySegment *p;
+ u8 *p_Blocks;
+ int i ;
+ int blockSize;
+
+ /* always allocate a dummy block at the end */
+ Num++;
+
+ /* make sure size is always a multiple of 4 */
+ if( Size & 3 )
+ {
+ Size &= ~3;
+ Size += 4;
+ }
+
+ if (Alignment < 4 )
+ Alignment = 4;
+
+ /** make sure that the alignment is a power of two */
+ if( !POWER_OF_2(Alignment) )
+ {
+ printk("MEM_Init: requested alignment is not a power of two.\n");
+ return -EINVAL;
+ }
+
+ /* prepare in case of error */
+ *p_Handle = 0;
+
+ /* first allocate the segment descriptor */
+ p = (t_MemorySegment *)kmalloc( sizeof(t_MemorySegment),GFP_KERNEL );
+
+ if( !p )
+ return -ENOMEM;
+ /* calculate blockSize */
+
+ /* store info about this segment */
+ spin_lock_init (&p->lock);
+ p->Num = (u16)(Num - 1);
+ p->Size = Size;
+ p->GetFailures = 0L;
+ p->f_MemPut = MEM_Put_Default;
+ p->LocallyAllocated = 1;
+ p->PrefixSize = PrefixSize;
+ p->Alignment = Alignment;
+ p->AlignPad = (u16)PAD_ALIGNMENT((u16)4, (u16)PrefixSize+4);
+ p->PostfixSize = PostfixSize;
+ /* Make sure the entire size is a multiple of Alignment */
+ p->EndPad = (u16)PAD_ALIGNMENT((u16)Alignment, 4 + p->AlignPad + PrefixSize + Size + PostfixSize);
+
+ blockSize = 4 + p->AlignPad + PrefixSize + Size + PostfixSize + p->EndPad;
+
+ p_Blocks = (u8 *)kmalloc(( Alignment + Num * blockSize ),GFP_KERNEL);
+
+ if( !p_Blocks )
+ {
+ kfree( p );
+ return -ENOMEM;
+ }
+ /* store the memory segment address */
+ p->p_Base = p_Blocks;
+
+ p_Blocks += (PrefixSize+4);
+ p_Blocks += (PAD_ALIGNMENT( Alignment, (u32)p_Blocks));
+ p_Blocks -= (PrefixSize+4+p->AlignPad);
+
+ /* store name */
+ strncpy( p->Name, Name, 4 );
+
+ /* finally, initialize the blocks */
+ p->p_Last = p->p_First = (void **)p_Blocks;
+ for(i = 0; i < (Num-1); i++)
+ {
+ /* get next block */
+ p_Blocks += blockSize;
+
+ /* attach to end of chain */
+ if( p->p_Last )
+ *(p->p_Last) = (void *)p_Blocks;
+
+ /* advance last pointer */
+ p->p_Last = (void **)p_Blocks;
+ }
+
+ /* zero next pointer in last block */
+ *(p->p_Last) = 0;
+
+ /* return handle to caller */
+ *p_Handle = (void *)p;
+
+ return 0;
+}
+
+
+
+void MEM_Free( void* p_Handle)
+{
+ t_MemorySegment *p = (t_MemorySegment*)p_Handle;
+
+ if ( p && p->LocallyAllocated)
+ kfree (p->p_Base);
+ kfree(p);
+}
+
+#define MEM_Put(Handle, p_Block) \
+ ((t_MemorySegment *)Handle)->f_MemPut( Handle, p_Block)
+
+
+
+
+#endif /* __STD_EXT_H */
diff -Nur linux/drivers/usb/host/Kconfig linux-8349-2.6/drivers/usb/host/Kconfig
--- linux/drivers/usb/host/Kconfig 2004-12-25 05:35:29.000000000 +0800
+++ linux-8349-2.6/drivers/usb/host/Kconfig 2005-08-16 14:58:56.000000000 +0800
@@ -5,6 +5,7 @@
boolean
default y if USB_ARCH_HAS_OHCI
default y if ARM # SL-811
+ default y if FSL_USB20 # MPC83xx SYS
default PCI
# many non-PCI hcds implement OHCI
@@ -24,7 +25,7 @@
config USB_EHCI_HCD
tristate "EHCI HCD (USB 2.0) support"
- depends on USB && PCI
+ depends on (USB && PCI) || (USB && FSL_USB20)
---help---
The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0
"high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware.
diff -Nur linux/drivers/usb/host/Makefile linux-8349-2.6/drivers/usb/host/Makefile
--- linux/drivers/usb/host/Makefile 2004-12-25 05:35:39.000000000 +0800
+++ linux-8349-2.6/drivers/usb/host/Makefile 2005-08-15 13:41:35.000000000 +0800
@@ -2,8 +2,11 @@
# Makefile for USB Host Controller Driver
# framework and drivers
#
-
+ifeq ($(CONFIG_FSL_USB20),y)
+obj-$(CONFIG_USB_EHCI_HCD) += fsl-usb.o
+else
obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
+endif
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o
obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o
diff -Nur linux/arch/ppc/platforms/83xx/Kconfig linux-8349-2.6/arch/ppc/platforms/83xx/Kconfig
--- linux/arch/ppc/platforms/83xx/Kconfig 2005-03-03 01:46:54.000000000 +0800
+++ linux-8349-2.6/arch/ppc/platforms/83xx/Kconfig 2005-08-25 11:44:57.000000000 +0800
@@ -27,4 +27,78 @@
depends on 83xx
default y
+config FSL_USB20
+ bool "MPC834x USB20 Host Support"
+ depends on MPC834x_SYS
+
+
+menu "USB20 Host Configuration"
+ depends on FSL_USB20
+
+choice
+ prompt "MPC83xx USB20 host Mode"
+ depends on FSL_USB20
+ default MPH_USB_SUPPORT
+
+config MPH_USB_SUPPORT
+ bool "MPH_MODE"
+
+config DR_USB_SUPPORT
+ bool "DR_MODE"
+
+endchoice
+
+config MPH0_USB_ENABLE
+ bool "MPH0 USB HOST Enable"
+ depends on MPH_USB_SUPPORT
+
+choice
+ prompt "MPH0 PHY Interface Selection"
+ depends on MPH0_USB_ENABLE
+ default MPH0_ULPI
+
+config MPH0_ULPI
+ bool "ULPI"
+
+config MPH0_SERIAL
+ bool "Serial"
+
+endchoice
+
+config MPH1_USB_ENABLE
+ bool "MPH1 USB HOST Enable"
+ depends on MPH_USB_SUPPORT
+
+choice
+ prompt "MPH1 PHY Interface Selection"
+ depends on MPH1_USB_ENABLE
+ default MPH1_ULPI
+
+config MPH1_ULPI
+ bool "ULPI"
+
+config MPH1_SERIAL
+ bool "Serial"
+
+endchoice
+
+
+choice
+ prompt "DR PHY Interface Selection"
+ depends on DR_USB_SUPPORT
+ default DR_ULPI
+
+config DR_ULPI
+ bool "ULPI"
+
+config DR_SERIAL
+ bool "Serial"
+
+config DR_UTMI
+ bool "UTMI"
+
+endchoice
+
+endmenu
+
endmenu
--
Leo Li
Freescale Semiconductor
LeoLi@freescale.com
^ permalink raw reply
* [PATCH]ppc32: Adds PQ2FADS flash SIMM support as physmap device
From: Vitaly Bordug @ 2005-12-20 3:57 UTC (permalink / raw)
To: linuxppc-embedded list
Implemented more correct way to support physmapped flash on PQ2FADS
than map in mtd (which is already removed from the mtd tree).
The areas intended to contain bootloader are protected readonly.
Note that CFI and JEDEC stuff should be configured properly in order
this to work, e.g. for 8272 CFI should support 4-chip flash interleave.
Also fixed compilation warning.
Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
---
commit 3af1e7e029c4fd50236078e48e79f8112a999de8
tree f84ee4fe92d616a0f640e1e86601a003d887b807
parent a8450a334dc930d7284800c457d91ed55a1a3dd7
author Vitaly Bordug <vbordug@ru.mvista.com> Sun, 18 Dec 2005 21:26:13 +0300
committer Vitaly Bordug <vbordug@ru.mvista.com> Sun, 18 Dec 2005 21:26:13 +0300
arch/ppc/syslib/m8260_setup.c | 71 ++++++++++++++++++++++++++++++++++++++++-
1 files changed, 70 insertions(+), 1 deletions(-)
diff --git a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c
index 76a2aa4..693e8dc 100644
--- a/arch/ppc/syslib/m8260_setup.c
+++ b/arch/ppc/syslib/m8260_setup.c
@@ -20,6 +20,13 @@
#include <linux/seq_file.h>
#include <linux/irq.h>
+#if defined(CONFIG_MTD) && defined(CONFIG_MTD_PHYSMAP)
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#endif
+
#include <asm/mmu.h>
#include <asm/io.h>
#include <asm/pgtable.h>
@@ -28,9 +35,58 @@
#include <asm/machdep.h>
#include <asm/bootinfo.h>
#include <asm/time.h>
+#include <asm/ppc_sys.h>
#include "cpm2_pic.h"
+#ifdef CONFIG_MTD_PHYSMAP
+#define PQ2FADS_BANK_WIDTH 4
+#endif
+
+#if defined(CONFIG_MTD_PARTITIONS)
+/*
+ NOTE: bank width and interleave relative to the installed flash
+ should have been chosen within MTD_CFI_GEOMETRY options.
+ */
+
+static struct mtd_partition pq2fads_partitions[] = {
+ {
+#if defined(CONFIG_ADS8272)
+ .name = "HRCW",
+ .size = 0x40000,
+ .offset = 0,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ .name = "User FS",
+ .size = 0x5c0000,
+ .offset = 0x40000,
+#else
+ .name = "User FS",
+ .size = 0x600000,
+ .offset = 0,
+#endif
+ }, {
+ .name = "uImage",
+ .size = 0x100000,
+ .offset = 0x600000,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ .name = "bootloader",
+ .size = 0x40000,
+ .offset = 0x700000,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ .name = "bootloader env",
+ .size = 0x40000,
+ .offset = 0x740000,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }
+};
+
+#define pq2fads_part_num (sizeof (pq2fads_partitions) / sizeof (pq2fads_partitions[0]))
+
+#endif
+
unsigned char __res[sizeof(bd_t)];
extern void pq2_find_bridges(void);
@@ -46,6 +102,9 @@ m82xx_board_setup(void)
static void __init
m8260_setup_arch(void)
{
+#if defined(CONFIG_MTD) && defined(CONFIG_MTD_PHYSMAP)
+ bd_t *binfo = (bd_t *)__res;
+#endif
/* Print out Vendor and Machine info. */
printk(KERN_INFO "%s %s port\n", CPUINFO_VENDOR, CPUINFO_MACHINE);
@@ -64,7 +123,17 @@ m8260_setup_arch(void)
#endif
identify_ppc_sys_by_name_and_id(BOARD_CHIP_NAME,
- in_be32(CPM_MAP_ADDR + CPM_IMMR_OFFSET));
+ in_be32((void*)(CPM_MAP_ADDR + CPM_IMMR_OFFSET)));
+
+#if defined (CONFIG_ADS8272) || defined (CONFIG_PQ2FADS)
+#if defined(CONFIG_MTD_PHYSMAP)
+ physmap_configure(binfo->bi_flashstart, binfo->bi_flashsize,
+ PQ2FADS_BANK_WIDTH, NULL);
+#ifdef CONFIG_MTD_PARTITIONS
+ physmap_set_partitions(pq2fads_partitions, pq2fads_part_num);
+#endif /* CONFIG_MTD_PARTITIONS */
+#endif /* CONFIG_MTD_PHYSMAP */
+#endif
m82xx_board_setup();
}
^ permalink raw reply related
* [PATCH 1/3] ppc32: Make platform devices being able to assign functions (update)
From: Vitaly Bordug @ 2005-12-20 3:50 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-embedded list
Implemented by modification of the .name field of the platform device,
when PDs with the
same names are to be used within different drivers, as
<device_name> -> <device_name>:<function>
Corresponding drivers should change the .name in struct device_driver to
reflect upper of course.
Also helper platform_notify_map function added, making assignment of
board-specific platform_info more consistent and generic.
Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
---
arch/ppc/syslib/ppc_sys.c | 136 ++++++++++++++++++++++++++++++++++++++++++++-
include/asm-ppc/mpc10x.h | 1
include/asm-ppc/mpc52xx.h | 1
include/asm-ppc/mpc8260.h | 1
include/asm-ppc/mpc83xx.h | 1
include/asm-ppc/mpc85xx.h | 1
include/asm-ppc/mpc8xx.h | 1
include/asm-ppc/ppc_sys.h | 24 ++++++++
8 files changed, 164 insertions(+), 2 deletions(-)
applies-to: 4ce1b1890dc687cb1cf77f98e7a95b94c7ef3a93
a8450a334dc930d7284800c457d91ed55a1a3dd7
diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c
index c0b93c4..26d2658 100644
--- a/arch/ppc/syslib/ppc_sys.c
+++ b/arch/ppc/syslib/ppc_sys.c
@@ -15,11 +15,23 @@
*/
#include <linux/string.h>
+#include <linux/bootmem.h>
#include <asm/ppc_sys.h>
int (*ppc_sys_device_fixup) (struct platform_device * pdev);
static int ppc_sys_inited;
+static int ppc_sys_func_inited;
+
+static const char *ppc_sys_func_names[] = {
+ [FUNC_ENABLED] = "dummy",
+ [FUNC_ETH] = "eth",
+ [FUNC_UART] = "uart",
+ [FUNC_HLDC] = "hldc",
+ [FUNC_USB] = "usb",
+ [FUNC_IRDA] = "irda",
+ [FUNC_DISABLED] = "off",
+};
void __init identify_ppc_sys_by_id(u32 id)
{
@@ -38,13 +50,13 @@ void __init identify_ppc_sys_by_id(u32 i
void __init identify_ppc_sys_by_name(char *name)
{
unsigned int i = 0;
- while (ppc_sys_specs[i].ppc_sys_name[0])
- {
+ while (ppc_sys_specs[i].ppc_sys_name[0]) {
if (!strcmp(ppc_sys_specs[i].ppc_sys_name, name))
break;
i++;
}
cur_ppc_sys_spec = &ppc_sys_specs[i];
+
return;
}
@@ -128,6 +140,126 @@ void ppc_sys_device_remove(enum ppc_sys_
}
}
+/* Platform-notify mapping
+ * Helper function for BSP code to assign board-specific platfom-divice bits
+ */
+
+void platform_notify_map(const struct platform_notify_dev_map *map,
+ struct device *dev)
+{
+ struct platform_device *pdev;
+ int len, idx;
+ const char *s;
+
+ /* do nothing if no device or no bus_id */
+ if (!dev || !dev->bus_id)
+ return;
+
+ /* call per device map */
+ while (map->bus_id != NULL) {
+ idx = -1;
+ s = strrchr(dev->bus_id, '.');
+ if (s != NULL)
+ idx = (int)simple_strtol(s + 1, NULL, 10);
+ else
+ s = dev->bus_id;
+
+ len = s - dev->bus_id;
+
+ if (!strncmp(dev->bus_id, map->bus_id, len)) {
+ pdev = container_of(dev, struct platform_device, dev);
+ map->rtn(pdev, idx);
+ }
+ map++;
+ }
+}
+
+/*
+ Function assignment stuff.
+ Intended to work as follows:
+ the device name defined in foo_devices.c will be concatenated with :"func",
+ where func is string map of respective function from platfom_device_func enum
+
+ The FUNC_ENABLED function is intended to remove all assignments, making the device to appear
+ in platform bus with unmodified name.
+ */
+
+/*
+ Here we'll replace .name pointers with fixed-lenght strings
+ Hereby, this should be called *before* any func stuff triggeded.
+ */
+void ppc_sys_device_initfunc(void)
+{
+ int i;
+ const char *name;
+ static char new_names[NUM_PPC_SYS_DEVS][BUS_ID_SIZE];
+ enum ppc_sys_devices cur_dev;
+
+ /* If inited yet, do nothing */
+ if (ppc_sys_func_inited)
+ return;
+
+ for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) {
+ if ((cur_dev = cur_ppc_sys_spec->device_list[i]) < 0)
+ continue;
+
+ if (ppc_sys_platform_devices[cur_dev].name) {
+ /*backup name */
+ name = ppc_sys_platform_devices[cur_dev].name;
+ strlcpy(new_names[i], name, BUS_ID_SIZE);
+ ppc_sys_platform_devices[cur_dev].name = new_names[i];
+ }
+ }
+
+ ppc_sys_func_inited = 1;
+}
+
+/*The "engine" of the func stuff. Here we either concat specified function string description
+ to the name, or remove it if FUNC_ENABLED parameter is passed here*/
+void ppc_sys_device_setfunc(enum ppc_sys_devices dev,
+ enum platform_device_func func)
+{
+ char *s;
+ char *name = (char *)ppc_sys_platform_devices[dev].name;
+ char tmp[BUS_ID_SIZE];
+
+ if (!ppc_sys_func_inited) {
+ printk(KERN_ERR "Unable to alter function - not inited!\n");
+ return;
+ }
+
+ if (ppc_sys_inited) {
+ platform_device_unregister(&ppc_sys_platform_devices[dev]);
+ }
+
+ if ((s = (char *)strchr(name, ':')) != NULL) { /* reassign */
+ /* Either change the name after ':' or remove func modifications */
+ if (func != FUNC_ENABLED)
+ strlcpy(s + 1, ppc_sys_func_names[func], BUS_ID_SIZE);
+ else
+ *s = 0;
+ } else if (func != FUNC_ENABLED) {
+ /* do assignment if it is not just "enable" request */
+ sprintf(tmp, "%s:%s", name, ppc_sys_func_names[func]);
+ strlcpy(name, tmp, BUS_ID_SIZE);
+ }
+
+ if (ppc_sys_inited) {
+ platform_device_register(&ppc_sys_platform_devices[dev]);
+ }
+}
+
+void ppc_sys_device_set_func_all(enum platform_device_func func)
+{
+ enum ppc_sys_devices cur_dev;
+ int i;
+
+ for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) {
+ cur_dev = cur_ppc_sys_spec->device_list[i];
+ ppc_sys_device_setfunc(cur_dev, func);
+ }
+}
+
static int __init ppc_sys_init(void)
{
unsigned int i, dev_id, ret = 0;
diff --git a/include/asm-ppc/mpc10x.h b/include/asm-ppc/mpc10x.h
index 77b1e09..976ad3d 100644
--- a/include/asm-ppc/mpc10x.h
+++ b/include/asm-ppc/mpc10x.h
@@ -165,6 +165,7 @@ enum ppc_sys_devices {
MPC10X_DMA1,
MPC10X_UART0,
MPC10X_UART1,
+ NUM_PPC_SYS_DEVS,
};
int mpc10x_bridge_init(struct pci_controller *hose,
diff --git a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
index e5f80c2..b2cb44f 100644
--- a/include/asm-ppc/mpc52xx.h
+++ b/include/asm-ppc/mpc52xx.h
@@ -49,6 +49,7 @@ enum ppc_sys_devices {
MPC52xx_ATA,
MPC52xx_I2C1,
MPC52xx_I2C2,
+ NUM_PPC_SYS_DEVS,
};
diff --git a/include/asm-ppc/mpc8260.h b/include/asm-ppc/mpc8260.h
index 3214526..6ba69a8 100644
--- a/include/asm-ppc/mpc8260.h
+++ b/include/asm-ppc/mpc8260.h
@@ -83,6 +83,7 @@ enum ppc_sys_devices {
MPC82xx_CPM_SMC2,
MPC82xx_CPM_USB,
MPC82xx_SEC1,
+ NUM_PPC_SYS_DEVS,
};
#ifndef __ASSEMBLY__
diff --git a/include/asm-ppc/mpc83xx.h b/include/asm-ppc/mpc83xx.h
index 7cdf60f..3c23fc4 100644
--- a/include/asm-ppc/mpc83xx.h
+++ b/include/asm-ppc/mpc83xx.h
@@ -108,6 +108,7 @@ enum ppc_sys_devices {
MPC83xx_USB2_DR,
MPC83xx_USB2_MPH,
MPC83xx_MDIO,
+ NUM_PPC_SYS_DEVS,
};
#endif /* CONFIG_83xx */
diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h
index 9d14bae..2a77884 100644
--- a/include/asm-ppc/mpc85xx.h
+++ b/include/asm-ppc/mpc85xx.h
@@ -135,6 +135,7 @@ enum ppc_sys_devices {
MPC85xx_eTSEC4,
MPC85xx_IIC2,
MPC85xx_MDIO,
+ NUM_PPC_SYS_DEVS,
};
/* Internal interrupts are all Level Sensitive, and Positive Polarity */
diff --git a/include/asm-ppc/mpc8xx.h b/include/asm-ppc/mpc8xx.h
index 46f159c..90e3d59 100644
--- a/include/asm-ppc/mpc8xx.h
+++ b/include/asm-ppc/mpc8xx.h
@@ -111,6 +111,7 @@ enum ppc_sys_devices {
MPC8xx_CPM_SMC1,
MPC8xx_CPM_SMC2,
MPC8xx_CPM_USB,
+ NUM_PPC_SYS_DEVS,
};
#ifndef BOARD_CHIP_NAME
diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h
index 83d8c77..76f259f 100644
--- a/include/asm-ppc/ppc_sys.h
+++ b/include/asm-ppc/ppc_sys.h
@@ -47,6 +47,21 @@ struct ppc_sys_spec {
enum ppc_sys_devices *device_list;
};
+struct platform_notify_dev_map {
+ const char *bus_id;
+ void (*rtn)(struct platform_device * pdev, int idx);
+};
+
+enum platform_device_func {
+ FUNC_ENABLED = 0,
+ FUNC_ETH = 1,
+ FUNC_UART = 2,
+ FUNC_HLDC = 3,
+ FUNC_USB = 4,
+ FUNC_IRDA = 5,
+ FUNC_DISABLED = 6,
+};
+
/* describes all specific chips and which devices they have on them */
extern struct ppc_sys_spec ppc_sys_specs[];
extern struct ppc_sys_spec *cur_ppc_sys_spec;
@@ -72,5 +87,14 @@ extern void *ppc_sys_get_pdata(enum ppc_
/* remove a device from the system */
extern void ppc_sys_device_remove(enum ppc_sys_devices dev);
+/*Function assignment stuff*/
+void ppc_sys_device_initfunc(void);
+void ppc_sys_device_setfunc(enum ppc_sys_devices dev,
+ enum platform_device_func func);
+void ppc_sys_device_set_func_all(enum platform_device_func func);
+
+void platform_notify_map(const struct platform_notify_dev_map *map,
+ struct device *dev);
+
#endif /* __ASM_PPC_SYS_H */
#endif /* __KERNEL__ */
---
0.99.9.GIT
^ permalink raw reply related
* ramdisk loading address in U-Boot
From: HappyPhot @ 2005-12-20 1:45 UTC (permalink / raw)
To: linuxppc-embedded
Hi:
I build a ramdisk image and mkimage for U-Boot
by using -a and -e = 4000000.
In U-Boot command line, I type "tftpboot 2000000 ramdisk_image".
After bootm , the ramdisk is loaded to "0fdea000", like:
## initrd at 0x02000040 ... 0x02185BD0 (len=1596305=0x185B91)
Loading Ramdisk to 0fdea000, end 0ff6fb91 ... OK
## Transferring control to Linux ....
Why was the ramdisk loaded into 0fdea000, instead of 4000000 ?
thank you,
/HappyPhot
^ permalink raw reply
* Re: linux DMA capabilities in MV64460
From: Mark A. Greer @ 2005-12-20 1:01 UTC (permalink / raw)
To: Phil Nitschke; +Cc: linuxppc-embedded
In-Reply-To: <kw3bkovcup.fsf@lamorak.int.avalon.com.au>
Hi Phil,
[Note: I'm cc'ing linuxppc-embedded for others to reference and to
add their thoughts.]
---
On Tue, Dec 20, 2005 at 10:49:58AM +1030, Phil Nitschke wrote:
> Hi Mark,
>
> I'm developing a device driver to run in the 2.6.10 kernel. I want to
That's a pretty old kernel. Do you have the option of using a more
recent one like 2.6.14?
> get large amounts of data from a custom peripheral on the PCI bus. The
> software is running on an Artesyn PmPPC7448, which includes a Discovery
> III bridge.
Can you share exact platform you're using?
> The custom device is a digitizer, which runs at over 200 million samples
> per second, so we're looking to use a fair amount of PCI bandwidth to
> get the data into main memory. Burst reads/writes seem like the only
> way.
>
> I have seen that you wrote some code for the mainstream kernel that sets
> up the mv64460. One source told me:
>
> > In order to do PCI bursts, you'll need to use a DMA engine. The
> > MV64460 does contain a DMA engine, but you'd need to write a driver
> > to access it.
That is not correct (assuming the quote is not out of context).
The bridge supports bursting on the PCI bus as long as the bridge is
configured correctly and the PCI device is making an appropriate request.
Note, however, that there are many errata for the Marvell parts including
some with cache coherency. If your system is running with coherency on,
you may have to limit your bursts to 32 bytes (i.e., the size of one
cache line).
You can see how the bursting is set up on the bridge by looking at the
platform file for your board (e.g., <file:arch/ppc/platforms/katana.c> in
the latest linux kernel)--search for 'BURST'.
> Is there a summary of what is possible and/or not possible with the 4
> IDMA channels on the mv64460?
The only real documentation is the bridge's user manual from Marvell.
Unfortunately, you must sign an NDA to get access to it so I can't share
mine with you. You will need access to that info to get very far so I
recommend you contact the people in your company that can make that
happen, ASAP.
> For example, if the device that I'm trying to get data from supported a
> DMA engine capable of initiating bursts on the PCI bus (it currently
> can't do this), does the current kernel code support that?
That's a hardware feature so its not really an issue of kernel support
other than ensuring that the firmware and/or kernel configures the bridge
correctly. IOW, it can be supported by software but its an issue of
whether your hardware supports it (and it actually works).
> Or if I wanted to suck the data into main memory using the mv64460 IDMA
> controller (assuming the device couldn't initiate its own burst writes),
> is there a standard kernel interface to allow me to do this?
Yes. You would make a "dma ctlr driver" for the dma ctlr(s).
I don't know what the best example would be but hopefully someone else
has a suggestion.
> Sorry if the questions are silly or inappropriately directed.
Not at all. Those were good questions.
> At the
> moment I'm still trying to understand some really basic things, like
> what determines the difference between burst reads and ordinary reads,
> and what is the difference between SDMA and IDMA, etc ;-)
You may want to pick up "PCI System Architecture" from Mindshare, Inc.
There are ones for PCI-X and PCI-Express too, I think. Well worth the money.
> Many thanks for any help/suggestions/information you can offer.
>
> --
> Phil
I hope this helps,
Mark
^ permalink raw reply
* [PATCH] powerpc: Fix compile problem in pci.c for ppc32
From: Kumar Gala @ 2005-12-19 21:49 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
pci_address_to_pio is missing a closing curly brace
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
commit a86f866f7b31e01c729ee7498228c547a51d8514
tree 7cc7df7f28735a34618d450cc46bfd3c86d8725b
parent c211d7347a735eb5d5996433f3eef7159c3fe41a
author Kumar Gala <galak@kernel.crashing.org> Mon, 19 Dec 2005 15:52:42 -0600
committer Kumar Gala <galak@kernel.crashing.org> Mon, 19 Dec 2005 15:52:42 -0600
arch/ppc/kernel/pci.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 664af8b..7d4c0e3 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -1823,7 +1823,7 @@ unsigned long pci_address_to_pio(phys_ad
unsigned long base =
(unsigned long)hose->io_base_virt - _IO_BASE;
return base + (address - hose->io_base_phys);
-
+ }
}
return (unsigned int)-1;
}
^ permalink raw reply related
* Re: RFC: Rev 0.5 Booting the Linux/ppc kernel without Open Firmware
From: Kumar Gala @ 2005-12-19 20:49 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Arnd Bergmann, linuxppc64-dev
In-Reply-To: <1134856762.6102.54.camel@gaston>
On Sun, 18 Dec 2005, Benjamin Herrenschmidt wrote:
>
> > - Do we need a way to identify the type of soc bus? There are different
> > standards for this, e.g. PLB4 on PPC440 or the EIB on the Cell BE.
> > My initial idea was to have different device-type properties for these,
> > but I now think that device_type = "soc" makes sense for all of them.
> > Maybe we could add a model or compatible property for them.
>
> That would be a good idea.
>
> Also, it might be useful to ass a "clock-frequency" to it for processors
> where it makes sense. One of the things we are passing from uboot
> currently is the list of clock frequencies for PLB/OPB/PCI/... we need
> to replace this with appropriate nodes and their respective
> "clock-frequency" properties
>
> > - It does not really belong into this document, but is related anyway:
> > how do you want to represent this in Linux? Currently, most of these
> > would be of_platform_device, but I think it would be good to have
> > a new bus_type for it. The advantage would be that you can see the
> > devices in /sys/devices/soc@xxx/ even if the driver is not loaded
> > and the driver can even be autoloaded by udev.
> > Also, which properties should show up in sysfs? All of them or just
> > those specified in this document or a subset of them?
I'm still in favor of just leaving these devices as straight platform
devices. Unless there is something that is bus specific that each device
on the bus conforms to I dont see any reason to create a new bus type.
> If we go that way, we also need to have the SOC type take optionally
> part in the matching. That is, the driver matching infos should be based
> on model & compatible like OF does, thus we could recommend something
> like:
>
> - Define a unique SOC name per SOC bus type/family, for example,
> ppc4xxPLB, etc... This goes into /soc/model.
>
> - Optionally, use compatible for similar busses. For example, if you
> have a new rev of that PLB that is similar but has extensions called
> PLB2, you can have model be ppc4xxPLB2 and compatible containing
> ppc4xxPLB.
>
> - Define that the "model" property of a device under /soc is of the
> form "socname,devicename"... For example, EMAC would be ppc4xxPLB,emac",
> Same rule applies with compatible (this one could be compatible, among
> others, with "ppc4xxPLB,emac" and model "ppc4xxPLB2,emac".
>
> > - What do we do with pci root devices? They are often physically connected
> > to the internal CPU bus, so it would make sense to represent them
> > this way in the device tree. Should we add them to the specification
> > here? Would it even work the expected way in Linux?
- kumar
^ permalink raw reply
* Re: kernel 2.6.15-rc5-latest doesn't work anymore on mpc8540ads
From: Kumar Gala @ 2005-12-19 20:38 UTC (permalink / raw)
To: Clemens Koller; +Cc: linuxppc-embedded
In-Reply-To: <43A6ED1E.20506@anagramm.de>
On Mon, 19 Dec 2005, Clemens Koller wrote:
> Hello!
>
> Here is a little update:
>
> > I am just about to update my kernel from 2.6.13-rc7 which is working
> > fine to linus' 2.6.15-rc5-latest git on my mpc8540ads flavored board.
> > However, the kernel hangs pretty early after
> >
> > openpic: exit
>
> openpic_init() is called by mpc85xx_ads_init_IRQ in ppc/platforms/85xx
>
> ppc_md.init_IRQ=mpc85xx_ads_init_IRQ in ppc/platforms/85xx
>
> ppc_md.init_IRQ() is called from powerpc/kernel/irq.c
>
> init_IRQ() is called from init/main.c:start_kernel()
>
> and that seems to work fine. So, it crashes silently somewhere
> after that point. I try to build 2.6.15-rc6-latest with kgbd support,
> not knowing if it's supposed to work on this platform.
It was a guess :)
> Are there some open issues from the ppc->powerpc migration?
possible, can you use git bisect to find what commit may have caused the
issue?
- kumar
^ permalink raw reply
* Re: kernel 2.6.15-rc5-latest doesn't work anymore on mpc8540ads
From: Clemens Koller @ 2005-12-19 17:25 UTC (permalink / raw)
To: Clemens Koller; +Cc: linuxppc-embedded
In-Reply-To: <43A2E175.9050004@anagramm.de>
Hello!
Here is a little update:
> I am just about to update my kernel from 2.6.13-rc7 which is working
> fine to linus' 2.6.15-rc5-latest git on my mpc8540ads flavored board.
> However, the kernel hangs pretty early after
>
> openpic: exit
openpic_init() is called by mpc85xx_ads_init_IRQ in ppc/platforms/85xx
ppc_md.init_IRQ=mpc85xx_ads_init_IRQ in ppc/platforms/85xx
ppc_md.init_IRQ() is called from powerpc/kernel/irq.c
init_IRQ() is called from init/main.c:start_kernel()
and that seems to work fine. So, it crashes silently somewhere
after that point. I try to build 2.6.15-rc6-latest with kgbd support,
not knowing if it's supposed to work on this platform.
Are there some open issues from the ppc->powerpc migration?
Thanks,
--
Clemens Koller
_______________________________
R&D Imaging Devices
Anagramm GmbH
Rupert-Mayer-Str. 45/1
81379 Muenchen
Germany
http://www.anagramm.de
Phone: +49-89-741518-50
Fax: +49-89-741518-19
^ permalink raw reply
* Re: POSIX High Resolution Timers in LinuxPPC 2.4
From: Egan @ 2005-12-19 15:57 UTC (permalink / raw)
To: linuxppc-embedded, linuxppc-embedded
In-Reply-To: <200512191039.58149.david.jander@protonic.nl>
> Hi Tim,
>
> On Friday 16 December 2005 23:34, Martin, Tim wrote:
> > Could someone give me a brief history lesson on POSIX high resolution
> > timers (e.g. timer_create() function) implemented in the Linux kernel on
> > the PowerPC 405 architecture? Specifically:
> >
> > Confirm they are in the mainline 2.6 kernel now (e.g. kernel.org)?
> >
> > Were they ever a part of the "mainline" 2.4 linuxppc kernel (e.g
> > ppc.bkbits.net)?
> >
> > If no, were they ever available as a patch? The stuff at
> > sourceforge.net/projects/high-res-timers stops at 2.4.20 and looks like it
> > was only ever working for i386, not ppc.
>
> I asked a related question a while back, and got no answer (yet).
> I did find this though, which you might have overlooked:
> http://prdownloads.sourceforge.net/high-res-timers/ppc-hrt-2.6.10.patch?download
>
> I am equally puzzled about whether this has made it into mainstream, is about
> to, or never will. I don't even know if it actually works.
>
> Greetings,
>
> --
>
> David Jander
> Protonic Holland.
>
High resolution timer support has been rewritten for 2.6 by Thomas Gleixner
with help from Ingo Molnar and others and is available at:
http://tglx.de/hrtimers.html. It is also integrated into Ingo's
realtime-preempt patch at: http://people.redhat.com/mingo/realtime-preempt/.
It is not available in the mainline kernel yet. Currently only X86 is
supported, PPC and other architectures are reported to be in progress. If you
monitor the LKML you will see a lot of discussion/development in this area
right now.
Regards,
Tony
^ permalink raw reply
* WG: Problem loading modules
From: Achim Machura @ 2005-12-19 16:41 UTC (permalink / raw)
To: Linuxppc-Embedded (E-Mail)
-----Ursprüngliche Nachricht-----
Von: Achim Machura [mailto:achim.machura@berghof.com]
Gesendet: Montag, 19. Dezember 2005 17:41
An: 'Paula Saameño'
Betreff: AW: Problem loading modules
Hello,
> Yes, I tried with insmod and the error then was: "couldn't find the kernel
version the module was
make sure that the kernel was compiled with the same header as your
kernelmoduls.
best regards
achim
^ permalink raw reply
* Re: Problem loading modules
From: Paula Saameño @ 2005-12-19 16:22 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 624 bytes --]
>>Hi!
>>I'm working with a ml403 board, porting Linux 2.4.devel on it. I got the
OS
>>running, but I cannot load modules.
>>When I try "modprobe /lib/modules/<version>/kernel/net/<module.o>, I
obtain
>>the error messages:
>>Note: /etc/modules.conf is more recent than
>>/lib/modules/<version>/modules.dep
>>modprobe: Can't locate module lib/modules/<version>/kernel/net/<module.o>
>did you try with insmod ?
>then try running depmod.
Yes, I tried with insmod and the error then was: "couldn't find the kernel
version the module was compiled for"
In modules.dep, the references are ok.
Greetings!
[-- Attachment #2: Type: text/html, Size: 788 bytes --]
^ permalink raw reply
* [PATCH][UPDATE] powerpc: CPM2 interrupt handler failure after 100, 000 interrupts
From: Kumar Gala @ 2005-12-19 15:16 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-embedded
From: Edson Seabra <Edson.Seabra@cyclades.com>
The CPM2 interrupt handler does not return success to the IRQ subsystem, which
causes it to kill the IRQ line after 100,000 interrupts.
Signed-off-by: Edson Seabra <Edson.Seabra@cyclades.com>
Signed-off-by: Marcelo Tosatti <marcelo.tosatti@cyclades.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
Paul: We should put this in the merge tree for linus to pick up for
2.6.15. Fixed up return type to be irqreturn_t
commit c211d7347a735eb5d5996433f3eef7159c3fe41a
tree 1c14ca8d89ae7b7d989dac917f8bf87dba40b6c7
parent 1abf7e247b676a84fbfcd47442dc44788526f2f6
author Kumar Gala <galak@kernel.crashing.org> Mon, 19 Dec 2005 09:17:05 -0600
committer Kumar Gala <galak@kernel.crashing.org> Mon, 19 Dec 2005 09:17:05 -0600
arch/ppc/platforms/85xx/mpc85xx_cds_common.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
index d8991b8..5e8cc5e 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -130,10 +130,11 @@ mpc85xx_cds_show_cpuinfo(struct seq_file
}
#ifdef CONFIG_CPM2
-static void cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs)
{
while((irq = cpm2_get_irq(regs)) >= 0)
__do_IRQ(irq, regs);
+ return IRQ_HANDLED;
}
static struct irqaction cpm2_irqaction = {
^ permalink raw reply related
* Re: [PATCH] powerpc: CPM2 interrupt handler failure after 100,000
From: Kumar Gala @ 2005-12-19 15:18 UTC (permalink / raw)
To: Nathael Pajani; +Cc: linuxppc-embedded
In-Reply-To: <20051219085747.5D79425C7AA@smtp-out.completel.net>
On Dec 19, 2005, at 3:00 AM, Nathael Pajani wrote:
> interrupts
> Message-Id: <20051219100059.5a95533f.nathael.pajani@cpe.fr>
> X-Mailer: Sylpheed version 2.0.4 (GTK+ 2.8.9; i486-pc-linux-gnu)
> Mime-Version: 1.0
> Content-Type: text/plain; charset=ISO-8859-1
> Content-Transfer-Encoding: quoted-printable
>
> Hi!
>
> Hum.. in the patch you moved from "void" to "int":
>> -static void cpm2_cascade(int irq, void *dev_id, struct pt_regs
>> *regs)
>> +static int cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs)
>
> But should'nt it be "irqreturn_t" ?
> static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct
> pt_regs *regs)
Yep, should be. I'll fixup the patch and resend.
- kumar
^ permalink raw reply
* mv643xx_eth, sleeping function called from invalid context at mm/slab.c:2472
From: Olaf Hering @ 2005-12-19 13:39 UTC (permalink / raw)
To: Manish_Lachwani, netdev; +Cc: linuxppc-dev
I get this with 2.6.15-rc6 on a pegasos2 board:
MV-643xx 10/100/1000 Ethernet Driver
eth1: port 1 with MAC address 00:2b:2f:de:ad:01
eth1: Scatter Gather Enabled
eth1: TX TCP/IP Checksumming Supported
eth1: RX TCP/UDP Checksum Offload ON
eth1: RX NAPI Enabled
eth1: Using SRAM
Debug: sleeping function called from invalid context at mm/slab.c:2472
in_atomic():0, irqs_disabled():1
Call Trace:
[CB32DCF0] [C000AFCC] show_stack+0x54/0x180 (unreliable)
[CB32DD10] [C0027CD4] __might_sleep+0xbc/0xd0
[CB32DD20] [C005E50C] kmem_cache_alloc+0x34/0x108
[CB32DD40] [C01C5F40] rand_initialize_irq+0x40/0x6c
[CB32DD60] [C0054104] setup_irq+0x5c/0x154
[CB32DD90] [C0054284] request_irq+0x88/0xb8
[CB32DDC0] [D22820A0] mv643xx_eth_open+0x44/0xb4 [mv643xx_eth]
[CB32DDE0] [C0257394] dev_open+0x70/0xd8
[CB32DE00] [C02554F0] dev_change_flags+0x6c/0x13c
[CB32DE20] [C02A2818] devinet_ioctl+0x280/0x708
[CB32DE80] [C02A319C] inet_ioctl+0xb4/0x100
[CB32DE90] [C02C0078] packet_ioctl+0x15c/0x188
[CB32DEB0] [C024B998] sock_ioctl+0x30c/0x334
[CB32DED0] [C00922F4] do_ioctl+0x3c/0x88
[CB32DEE0] [C0092728] vfs_ioctl+0x3e8/0x424
[CB32DF10] [C00927CC] sys_ioctl+0x68/0x98
[CB32DF40] [C000FAEC] ret_from_syscall+0x0/0x4c
--- Exception: c01 at 0x7f6be80
LR = 0x7fec9d0
eth1: no IPv6 routers present
00:00.0 Host bridge: Marvell Technology Group Ltd. MV64360/64361/64362 System Controller (rev 03)
00:01.0 FireWire (IEEE 1394): VIA Technologies, Inc. IEEE 1394 Host Controller (rev 46)
00:0c.0 ISA bridge: VIA Technologies, Inc. VT8231 [PCI-to-ISA Bridge] (rev 10)
00:0c.1 IDE interface: VIA Technologies, Inc. VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (rev 06)
00:0c.2 USB Controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1.1 Controller (rev 1e)
00:0c.3 USB Controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1.1 Controller (rev 1e)
00:0c.4 Bridge: VIA Technologies, Inc. VT8235 ACPI (rev 10)
00:0c.5 Multimedia audio controller: VIA Technologies, Inc. VT82C686 AC97 Audio Controller (rev 40)
00:0c.6 Communication controller: VIA Technologies, Inc. AC'97 Modem Controller (rev 20)
00:0d.0 Ethernet controller: VIA Technologies, Inc. VT6102 [Rhine-II] (rev 51)
0001:01:00.0 Host bridge: Marvell Technology Group Ltd. MV64360/64361/64362 System Controller (rev 03)
0001:01:08.0 VGA compatible controller: ATI Technologies Inc RV280 [Radeon 9200 SE] (rev 01)
0001:01:08.1 Display controller: ATI Technologies Inc RV280 [Radeon 9200 SE] (Secondary) (rev 01)
--
short story of a lazy sysadmin:
alias appserv=wotan
^ permalink raw reply
* [PATCH 3/3] ppc32: Adds MPC885ADS, MPC866ADS and MPC8272ADS-specific platform stuff for fs_enet
From: Vitaly Bordug @ 2005-12-19 13:21 UTC (permalink / raw)
To: Kumar Gala, Marcelo Tosatti, Pantelis Antoniou,
linuxppc-embedded list
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: Vitaly Bordug <vbordug@ru.mvista.com>
---
arch/ppc/Kconfig | 47 ++++
arch/ppc/platforms/Makefile | 4
arch/ppc/platforms/fads.h | 2
arch/ppc/platforms/mpc8272ads_setup.c | 235 ++++++++++++++++++++
arch/ppc/platforms/mpc866ads_setup.c | 269 +++++++++++++++++++++++
arch/ppc/platforms/mpc885ads_setup.c | 387 +++++++++++++++++++++++++++++++++
arch/ppc/platforms/pq2ads.h | 4
arch/ppc/platforms/pq2ads_pd.h | 114 ++++++++++
8 files changed, 1061 insertions(+), 1 deletions(-)
create mode 100644 arch/ppc/platforms/mpc8272ads_setup.c
create mode 100644 arch/ppc/platforms/mpc866ads_setup.c
create mode 100644 arch/ppc/platforms/mpc885ads_setup.c
create mode 100644 arch/ppc/platforms/pq2ads_pd.h
applies-to: f51b03be0daf16352ec61e3499f61c95adf115e7
5406392976524c1e504f2a612f49eac2b41dc16c
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index cc3f64c..ac32793 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -506,6 +506,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 || POWER4
diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
index 7c5cdab..ee50b0d 100644
--- a/arch/ppc/platforms/Makefile
+++ b/arch/ppc/platforms/Makefile
@@ -22,6 +22,8 @@ ifeq ($(CONFIG_PPC_PMAC),y)
obj-$(CONFIG_NVRAM) += pmac_nvram.o
obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o
endif
+
+obj-$(CONFIG_ADS8272) += mpc8272ads_setup.o
obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o
obj-$(CONFIG_PREP_RESIDUAL) += residual.o
obj-$(CONFIG_PQ2ADS) += pq2ads.o
@@ -45,6 +47,8 @@ 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
ifeq ($(CONFIG_SMP),y)
obj-$(CONFIG_PPC_PMAC) += pmac_smp.o
diff --git a/arch/ppc/platforms/fads.h b/arch/ppc/platforms/fads.h
index a48fb8d..e1c0b1b 100644
--- a/arch/ppc/platforms/fads.h
+++ b/arch/ppc/platforms/fads.h
@@ -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.
diff --git a/arch/ppc/platforms/mpc8272ads_setup.c b/arch/ppc/platforms/mpc8272ads_setup.c
new file mode 100644
index 0000000..0f228ad
--- /dev/null
+++ b/arch/ppc/platforms/mpc8272ads_setup.c
@@ -0,0 +1,235 @@
+/*
+ * 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 <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;
+ }
+ printk("all\n");
+}
+
+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_set_func_all(FUNC_DISABLED);
+ ppc_sys_device_setfunc(MPC82xx_CPM_FCC1, FUNC_ENABLED);
+ ppc_sys_device_setfunc(MPC82xx_CPM_FCC2, FUNC_ENABLED);
+
+ return 0;
+}
+
+arch_initcall(mpc8272ads_init);
diff --git a/arch/ppc/platforms/mpc866ads_setup.c b/arch/ppc/platforms/mpc866ads_setup.c
new file mode 100644
index 0000000..ed1b050
--- /dev/null
+++ b/arch/ppc/platforms/mpc866ads_setup.c
@@ -0,0 +1,269 @@
+/*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:
+ break;
+ }
+
+ 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 (strcmp(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 (strcmp(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_set_func_all(FUNC_DISABLED);
+ ppc_sys_device_setfunc(MPC8xx_CPM_SCC1, FUNC_ENABLED);
+ ppc_sys_device_setfunc(MPC8xx_CPM_FEC1, FUNC_ENABLED);
+
+ return 0;
+}
+
+arch_initcall(mpc866ads_init);
diff --git a/arch/ppc/platforms/mpc885ads_setup.c b/arch/ppc/platforms/mpc885ads_setup.c
new file mode 100644
index 0000000..feefa91
--- /dev/null
+++ b/arch/ppc/platforms/mpc885ads_setup.c
@@ -0,0 +1,387 @@
+/*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>
+
+extern unsigned char __res[];
+
+static void __init mpc885ads_scc_phy_init(char);
+
+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 = {
+#ifdef CONFIG_SCC_ENET_8xx_FIXED
+ .method = fsmii_fixed,
+#else
+ .method = fsmii_fec,
+#endif
+
+ .id = 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 = 0,
+ .phy_irq = SIU_IRQ7,
+
+ .bus_info = &fec_mii_bus_info,
+ }, {
+ .rx_ring = 128,
+ .tx_ring = 16,
+ .rx_copybreak = 240,
+
+ .use_napi = 1,
+ .napi_weight = 17,
+
+ .phy_addr = 1,
+ .phy_irq = SIU_IRQ7,
+
+ .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 = 2,
+#ifdef CONFIG_MPC8xx_SCC_ENET_FIXED
+ .phy_irq = -1,
+#else
+ .phy_irq = SIU_IRQ7,
+#endif
+
+ .bus_info = &scc_mii_bus_info,
+};
+
+void __init board_init(void)
+{
+ volatile cpm8xx_t *cp = cpmp;
+ unsigned int *bcsr_io;
+
+#ifdef CONFIG_FS_ENET
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+#endif
+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+ if (bcsr_io == NULL) {
+ printk(KERN_CRIT "Could not remap BCSR\n");
+ return;
+ }
+#ifdef CONFIG_SERIAL_CPM_SMC1
+ cp->cp_simode &= ~(0xe0000000 >> 17); /* brg1 */
+ clrbits32(bcsr_io, BCSR1_RS232EN_1);
+#else
+ setbits32(bcsr_io,BCSR1_RS232EN_1);
+ 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,BCSR1_RS232EN_2);
+#else
+ setbits32(bcsr_io,BCSR1_RS232EN_2);
+ cp->cp_smc[1].smc_smcmr = 0;
+ cp->cp_smc[1].smc_smce = 0;
+#endif
+ iounmap(bcsr_io);
+
+#ifdef CONFIG_FS_ENET
+ /* use MDC for MII (common) */
+ setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
+ clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
+#endif
+}
+
+static void setup_fec1_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+
+ /* configure FEC1 pins */
+ setbits16(&immap->im_ioport.iop_papar, 0xf830);
+ setbits16(&immap->im_ioport.iop_padir, 0x0830);
+ clrbits16(&immap->im_ioport.iop_padir, 0xf000);
+ setbits32(&immap->im_cpm.cp_pbpar, 0x00001001);
+
+ clrbits32(&immap->im_cpm.cp_pbdir, 0x00001001);
+ setbits16(&immap->im_ioport.iop_pcpar, 0x000c);
+ clrbits16(&immap->im_ioport.iop_pcdir, 0x000c);
+ setbits32(&immap->im_cpm.cp_pepar, 0x00000003);
+
+ setbits32(&immap->im_cpm.cp_pedir, 0x00000003);
+ clrbits32(&immap->im_cpm.cp_peso, 0x00000003);
+ clrbits32(&immap->im_cpm.cp_cptr, 0x00000100);
+}
+
+static void setup_fec2_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+
+ /* configure FEC2 pins */
+ setbits32(&immap->im_cpm.cp_pepar, 0x0003fffc);
+ setbits32(&immap->im_cpm.cp_pedir, 0x0003fffc);
+ setbits32(&immap->im_cpm.cp_peso, 0x00037800);
+ clrbits32(&immap->im_cpm.cp_peso, 0x000087fc);
+ clrbits32(&immap->im_cpm.cp_cptr, 0x00000080);
+}
+
+static void setup_scc3_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+ unsigned *bcsr_io;
+
+ bcsr_io = ioremap(BCSR_ADDR, BCSR_SIZE);
+
+ if (bcsr_io == NULL) {
+ printk(KERN_CRIT "Could not remap BCSR\n");
+ return;
+ }
+
+ /* Enable the PHY.
+ */
+ setbits32(bcsr_io+4, BCSR4_ETH10_RST);
+ /* Configure port A pins for Txd and Rxd.
+ */
+ setbits16(&immap->im_ioport.iop_papar, PA_ENET_RXD | PA_ENET_TXD);
+ clrbits16(&immap->im_ioport.iop_padir, PA_ENET_RXD | 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 E for TCLK and RCLK.
+ */
+ setbits32(&immap->im_cpm.cp_pepar, PE_ENET_TCLK | PE_ENET_RCLK);
+ clrbits32(&immap->im_cpm.cp_pepar, PE_ENET_TENA);
+ clrbits32(&immap->im_cpm.cp_pedir,
+ PE_ENET_TCLK | PE_ENET_RCLK | PE_ENET_TENA);
+ clrbits32(&immap->im_cpm.cp_peso, PE_ENET_TCLK | PE_ENET_RCLK);
+ setbits32(&immap->im_cpm.cp_peso, PE_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);
+
+ /* Disable Rx and Tx. SMC1 sshould be stopped if SCC3 eternet are used.
+ */
+ immap->im_cpm.cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+ /* On the MPC885ADS SCC ethernet PHY is initialized in the full duplex mode
+ * by H/W setting after reset. SCC ethernet controller support only half duplex.
+ * This discrepancy of modes causes a lot of carrier lost errors.
+ */
+
+ /* In the original SCC enet driver the following code is placed at
+ the end of the initialization */
+ setbits32(&immap->im_cpm.cp_pepar, PE_ENET_TENA);
+ clrbits32(&immap->im_cpm.cp_pedir, PE_ENET_TENA);
+ setbits32(&immap->im_cpm.cp_peso, PE_ENET_TENA);
+
+ setbits32(bcsr_io+1, BCSR1_ETHEN);
+ iounmap(bcsr_io);
+}
+
+static void mpc885ads_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_fec2:
+ fpi = &mpc8xx_fec_pdata[1];
+ fpi->init_ioports = &setup_fec2_ioports;
+ break;
+ case fsid_scc3:
+ fpi = &mpc8xx_scc_pdata;
+ fpi->init_ioports = &setup_scc3_ioports;
+ mpc885ads_scc_phy_init(fpi->phy_addr);
+ break;
+ default:
+ break;
+ }
+
+ 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 mpc885ads_fixup_fec_enet_pdata(struct platform_device *pdev,
+ int idx)
+{
+ /* This is for FEC devices only */
+ if (!strstr(pdev->name, "fsl-cpm-fec"))
+ return;
+ mpc885ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
+}
+
+static void __init mpc885ads_fixup_scc_enet_pdata(struct platform_device *pdev,
+ int idx)
+{
+ /* This is for SCC devices only */
+ if (!strstr(pdev->name, "fsl-cpm-scc"))
+ return;
+
+ mpc885ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
+}
+
+/* SCC ethernet controller does not have MII management channel. FEC1 MII
+ * channel is used to communicate with the 10Mbit PHY.
+ */
+
+#define MII_ECNTRL_PINMUX 0x4
+#define FEC_ECNTRL_PINMUX 0x00000004
+#define FEC_RCNTRL_MII_MODE 0x00000004
+
+/* Make MII read/write commands.
+ */
+#define mk_mii_write(REG, VAL, PHY_ADDR) (0x50020000 | (((REG) & 0x1f) << 18) | \
+ ((VAL) & 0xffff) | ((PHY_ADDR) << 23))
+
+static void mpc885ads_scc_phy_init(char phy_addr)
+{
+ volatile immap_t *immap;
+ volatile fec_t *fecp;
+ bd_t *bd;
+
+ bd = (bd_t *) __res;
+ immap = (immap_t *) IMAP_ADDR; /* pointer to internal registers */
+ fecp = &(immap->im_cpm.cp_fec);
+
+ /* Enable MII pins of the FEC1
+ */
+ setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
+ clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
+ /* Set MII speed to 2.5 MHz
+ */
+ out_be32(&fecp->fec_mii_speed,
+ ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1);
+
+ /* Enable FEC pin MUX
+ */
+ setbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX);
+ setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
+
+ out_be32(&fecp->fec_mii_data,
+ mk_mii_write(MII_BMCR, BMCR_ISOLATE, phy_addr));
+ udelay(100);
+ out_be32(&fecp->fec_mii_data,
+ mk_mii_write(MII_ADVERTISE,
+ ADVERTISE_10HALF | ADVERTISE_CSMA, phy_addr));
+ udelay(100);
+
+ /* Disable FEC MII settings
+ */
+ clrbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX);
+ clrbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
+ out_be32(&fecp->fec_mii_speed, 0);
+}
+
+static int mpc885ads_platform_notify(struct device *dev)
+{
+
+ static const struct platform_notify_dev_map dev_map[] = {
+ {
+ .bus_id = "fsl-cpm-fec",
+ .rtn = mpc885ads_fixup_fec_enet_pdata,
+ },
+ {
+ .bus_id = "fsl-cpm-scc",
+ .rtn = mpc885ads_fixup_scc_enet_pdata,
+ },
+ {
+ .bus_id = NULL
+ }
+ };
+
+ platform_notify_map(dev_map,dev);
+
+}
+
+int __init mpc885ads_init(void)
+{
+ printk(KERN_NOTICE "mpc885ads: Init\n");
+
+ platform_notify = mpc885ads_platform_notify;
+
+ ppc_sys_device_initfunc();
+ ppc_sys_device_set_func_all(FUNC_DISABLED);
+ ppc_sys_device_setfunc(MPC8xx_CPM_FEC1, FUNC_ENABLED);
+
+#ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3
+ ppc_sys_device_setfunc(MPC8xx_CPM_SCC1, FUNC_ENABLED);
+
+#endif
+#ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2
+ ppc_sys_device_setfunc(MPC8xx_CPM_FEC2, FUNC_ENABLED);
+#endif
+
+ return 0;
+}
+
+arch_initcall(mpc885ads_init);
diff --git a/arch/ppc/platforms/pq2ads.h b/arch/ppc/platforms/pq2ads.h
index 067d9a5..6b26dd3 100644
--- a/arch/ppc/platforms/pq2ads.h
+++ b/arch/ppc/platforms/pq2ads.h
@@ -13,6 +13,10 @@
#include <asm/ppcboot.h>
+#if defined(CONFIG_ADS8272)
+#define BOARD_CHIP_NAME "8272"
+#endif
+
/* Memory map is configured by the PROM startup.
* We just map a few things we need. The CSR is actually 4 byte-wide
* registers that can be accessed as 8-, 16-, or 32-bit values.
diff --git a/arch/ppc/platforms/pq2ads_pd.h b/arch/ppc/platforms/pq2ads_pd.h
new file mode 100644
index 0000000..8f14a43
--- /dev/null
+++ b/arch/ppc/platforms/pq2ads_pd.h
@@ -0,0 +1,114 @@
+#ifndef __PQ2ADS_PD_H
+#define __PQ2ADS_PD_H
+/*
+ * arch/ppc/platforms/82xx/pq2ads_pd.h
+ *
+ * Some defines for 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.
+ */
+
+/* FCC1 Clock Source Configuration. These can be redefined in the board specific file.
+ Can only choose from CLK9-12 */
+
+#define F1_RXCLK 11
+#define F1_TXCLK 10
+
+/* FCC2 Clock Source Configuration. These can be redefined in the board specific file.
+ Can only choose from CLK13-16 */
+#define F2_RXCLK 15
+#define F2_TXCLK 16
+
+/* FCC3 Clock Source Configuration. These can be redefined in the board specific file.
+ Can only choose from CLK13-16 */
+#define F3_RXCLK 13
+#define F3_TXCLK 14
+
+/* Automatically generates register configurations */
+#define PC_CLK(x) ((uint)(1<<(x-1))) /* FCC CLK I/O ports */
+
+#define CMXFCR_RF1CS(x) ((uint)((x-5)<<27)) /* FCC1 Receive Clock Source */
+#define CMXFCR_TF1CS(x) ((uint)((x-5)<<24)) /* FCC1 Transmit Clock Source */
+#define CMXFCR_RF2CS(x) ((uint)((x-9)<<19)) /* FCC2 Receive Clock Source */
+#define CMXFCR_TF2CS(x) ((uint)((x-9)<<16)) /* FCC2 Transmit Clock Source */
+#define CMXFCR_RF3CS(x) ((uint)((x-9)<<11)) /* FCC3 Receive Clock Source */
+#define CMXFCR_TF3CS(x) ((uint)((x-9)<<8)) /* FCC3 Transmit Clock Source */
+
+#define PC_F1RXCLK PC_CLK(F1_RXCLK)
+#define PC_F1TXCLK PC_CLK(F1_TXCLK)
+#define CMX1_CLK_ROUTE (CMXFCR_RF1CS(F1_RXCLK) | CMXFCR_TF1CS(F1_TXCLK))
+#define CMX1_CLK_MASK ((uint)0xff000000)
+
+#define PC_F2RXCLK PC_CLK(F2_RXCLK)
+#define PC_F2TXCLK PC_CLK(F2_TXCLK)
+#define CMX2_CLK_ROUTE (CMXFCR_RF2CS(F2_RXCLK) | CMXFCR_TF2CS(F2_TXCLK))
+#define CMX2_CLK_MASK ((uint)0x00ff0000)
+
+#define PC_F3RXCLK PC_CLK(F3_RXCLK)
+#define PC_F3TXCLK PC_CLK(F3_TXCLK)
+#define CMX3_CLK_ROUTE (CMXFCR_RF3CS(F3_RXCLK) | CMXFCR_TF3CS(F3_TXCLK))
+#define CMX3_CLK_MASK ((uint)0x0000ff00)
+
+/* I/O Pin assignment for FCC1. I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PA1_COL 0x00000001U
+#define PA1_CRS 0x00000002U
+#define PA1_TXER 0x00000004U
+#define PA1_TXEN 0x00000008U
+#define PA1_RXDV 0x00000010U
+#define PA1_RXER 0x00000020U
+#define PA1_TXDAT 0x00003c00U
+#define PA1_RXDAT 0x0003c000U
+#define PA1_PSORA0 (PA1_RXDAT | PA1_TXDAT)
+#define PA1_PSORA1 (PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
+ PA1_RXDV | PA1_RXER)
+#define PA1_DIRA0 (PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV)
+#define PA1_DIRA1 (PA1_TXDAT | PA1_TXEN | PA1_TXER)
+
+
+/* I/O Pin assignment for FCC2. I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PB2_TXER 0x00000001U
+#define PB2_RXDV 0x00000002U
+#define PB2_TXEN 0x00000004U
+#define PB2_RXER 0x00000008U
+#define PB2_COL 0x00000010U
+#define PB2_CRS 0x00000020U
+#define PB2_TXDAT 0x000003c0U
+#define PB2_RXDAT 0x00003c00U
+#define PB2_PSORB0 (PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
+ PB2_RXER | PB2_RXDV | PB2_TXER)
+#define PB2_PSORB1 (PB2_TXEN)
+#define PB2_DIRB0 (PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV)
+#define PB2_DIRB1 (PB2_TXDAT | PB2_TXEN | PB2_TXER)
+
+
+/* I/O Pin assignment for FCC3. I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PB3_RXDV 0x00004000U
+#define PB3_RXER 0x00008000U
+#define PB3_TXER 0x00010000U
+#define PB3_TXEN 0x00020000U
+#define PB3_COL 0x00040000U
+#define PB3_CRS 0x00080000U
+#define PB3_TXDAT 0x0f000000U
+#define PB3_RXDAT 0x00f00000U
+#define PB3_PSORB0 (PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
+ PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN)
+#define PB3_PSORB1 0
+#define PB3_DIRB0 (PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV)
+#define PB3_DIRB1 (PB3_TXDAT | PB3_TXEN | PB3_TXER)
+
+#define FCC_MEM_OFFSET(x) (CPM_FCC_SPECIAL_BASE + (x*128))
+#define FCC1_MEM_OFFSET FCC_MEM_OFFSET(0)
+#define FCC2_MEM_OFFSET FCC_MEM_OFFSET(1)
+
+#endif
---
Sincerely,
Vitaly
^ permalink raw reply related
* [PATCH 2/3] ppc32 8xx: Added setbitsXX/clrbitsXX macro for read-modify-write operations
From: Vitaly Bordug @ 2005-12-19 13:21 UTC (permalink / raw)
To: Kumar Gala, Marcelo Tosatti, Pantelis Antoniou,
linuxppc-embedded list
This adds setbitsXX/clrbitsXX macro for read-modify-write operations
and converts the 8xx core and drivers to use them.
Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
---
arch/ppc/8xx_io/commproc.c | 6 +++---
arch/ppc/syslib/m8xx_setup.c | 12 +++++-------
arch/ppc/syslib/m8xx_wdt.c | 3 +--
include/asm-ppc/io.h | 7 +++++++
4 files changed, 16 insertions(+), 12 deletions(-)
applies-to: 35d67fb06e89218629ae613633a01c7532f45ac0
3420ec0002cc78ecce97921ca4bb9488be6bbdf5
diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c
index 579cd40..12b84ca 100644
--- a/arch/ppc/8xx_io/commproc.c
+++ b/arch/ppc/8xx_io/commproc.c
@@ -73,7 +73,7 @@ cpm_mask_irq(unsigned int irq)
{
int cpm_vec = irq - CPM_IRQ_OFFSET;
- out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr, in_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr) & ~(1 << cpm_vec));
+ clrbits32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr, (1 << cpm_vec));
}
static void
@@ -81,7 +81,7 @@ cpm_unmask_irq(unsigned int irq)
{
int cpm_vec = irq - CPM_IRQ_OFFSET;
- out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr, in_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr) | (1 << cpm_vec));
+ setbits32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr, (1 << cpm_vec));
}
static void
@@ -198,7 +198,7 @@ cpm_interrupt_init(void)
if (setup_irq(CPM_IRQ_OFFSET + CPMVEC_ERROR, &cpm_error_irqaction))
panic("Could not allocate CPM error IRQ!");
- out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr, in_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr) | CICR_IEN);
+ setbits32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr, CICR_IEN);
}
/*
diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c
index 1cc3abe..ad7db45 100644
--- a/arch/ppc/syslib/m8xx_setup.c
+++ b/arch/ppc/syslib/m8xx_setup.c
@@ -149,8 +149,7 @@ void __init m8xx_calibrate_decr(void)
out_be32(&((immap_t *)IMAP_ADDR)->im_clkrstk.cark_sccrk, KAPWR_KEY);
/* Force all 8xx processors to use divide by 16 processor clock. */
- out_be32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_sccr,
- in_be32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_sccr)|0x02000000);
+ setbits32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_sccr, 0x02000000);
/* Processor frequency is MHz.
* The value 'fp' is the number of decrementer ticks per second.
*/
@@ -184,10 +183,9 @@ void __init m8xx_calibrate_decr(void)
out_be32(&((immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk, KAPWR_KEY);
/* Disable the RTC one second and alarm interrupts. */
- out_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, in_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc) & ~(RTCSC_SIE | RTCSC_ALE));
+ clrbits16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, (RTCSC_SIE | RTCSC_ALE));
/* Enable the RTC */
- out_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, in_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc) | (RTCSC_RTF | RTCSC_RTE));
-
+ setbits16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, (RTCSC_RTF | RTCSC_RTE));
/* Enabling the decrementer also enables the timebase interrupts
* (or from the other point of view, to get decrementer interrupts
* we have to enable the timebase). The decrementer interrupt
@@ -232,8 +230,8 @@ m8xx_restart(char *cmd)
__volatile__ unsigned char dummy;
local_irq_disable();
- out_be32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr, in_be32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr) | 0x00000080);
+ setbits32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr, 0x00000080);
/* Clear the ME bit in MSR to cause checkstop on machine check
*/
mtmsr(mfmsr() & ~0x1000);
@@ -303,8 +301,8 @@ m8xx_init_IRQ(void)
i8259_init(0);
/* The i8259 cascade interrupt must be level sensitive. */
- out_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel, in_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel & ~(0x80000000 >> ISA_BRIDGE_INT)));
+ clrbits32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel, (0x80000000 >> ISA_BRIDGE_INT));
if (setup_irq(ISA_BRIDGE_INT, &mbx_i8259_irqaction))
enable_irq(ISA_BRIDGE_INT);
#endif /* CONFIG_PCI */
diff --git a/arch/ppc/syslib/m8xx_wdt.c b/arch/ppc/syslib/m8xx_wdt.c
index a21632d..57f8b9f 100644
--- a/arch/ppc/syslib/m8xx_wdt.c
+++ b/arch/ppc/syslib/m8xx_wdt.c
@@ -40,8 +40,7 @@ static irqreturn_t m8xx_wdt_interrupt(in
m8xx_wdt_reset();
- out_be16(&imap->im_sit.sit_piscr, in_be16(&imap->im_sit.sit_piscr) | PISCR_PS); /* clear irq */
-
+ setbits16(&imap->im_sit.sit_piscr, PISCR_PS);
return IRQ_HANDLED;
}
diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h
index 84ac6e2..9c2e3db 100644
--- a/include/asm-ppc/io.h
+++ b/include/asm-ppc/io.h
@@ -573,4 +573,11 @@ extern void pci_iounmap(struct pci_dev *
*/
#define xlate_dev_kmem_ptr(p) p
+/* access ports */
+#define setbits32(_addr, _v) out_be32((_addr), in_be32(_addr) | (_v))
+#define clrbits32(_addr, _v) out_be32((_addr), in_be32(_addr) & ~(_v))
+
+#define setbits16(_addr, _v) out_be16((_addr), in_be16(_addr) | (_v))
+#define clrbits16(_addr, _v) out_be16((_addr), in_be16(_addr) & ~(_v))
+
#endif /* __KERNEL__ */
---
Sincerely,
Vitaly
^ permalink raw reply related
* [PATCH 1/3] ppc32: Make platform devices being able to assign functions
From: Vitaly Bordug @ 2005-12-19 13:21 UTC (permalink / raw)
To: Kumar Gala, Marcelo Tosatti; +Cc: linuxppc-embedded list
Implemented by modification of the .name field of the platform device,
when PDs with the
same names are to be used within different drivers, as
<device_name> -> <device_name>:<function>
Corresponding drivers should change the .name in struct device_driver to
reflect upper of course.
Also helper platform_notify_map function added, making assignment of
board-specific platform_info more consistent and generic.
Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
---
arch/ppc/syslib/ppc_sys.c | 136 ++++++++++++++++++++++++++++++++++++++++++++-
include/asm-ppc/mpc10x.h | 1
include/asm-ppc/mpc52xx.h | 1
include/asm-ppc/mpc8260.h | 1
include/asm-ppc/mpc83xx.h | 1
include/asm-ppc/mpc85xx.h | 1
include/asm-ppc/mpc8xx.h | 1
include/asm-ppc/ppc_sys.h | 24 ++++++++
8 files changed, 164 insertions(+), 2 deletions(-)
applies-to: 4ce1b1890dc687cb1cf77f98e7a95b94c7ef3a93
a8450a334dc930d7284800c457d91ed55a1a3dd7
diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c
index c0b93c4..26d2658 100644
--- a/arch/ppc/syslib/ppc_sys.c
+++ b/arch/ppc/syslib/ppc_sys.c
@@ -15,11 +15,23 @@
*/
#include <linux/string.h>
+#include <linux/bootmem.h>
#include <asm/ppc_sys.h>
int (*ppc_sys_device_fixup) (struct platform_device * pdev);
static int ppc_sys_inited;
+static int ppc_sys_func_inited;
+
+static const char *ppc_sys_func_names[] = {
+ [FUNC_ENABLED] = "dummy",
+ [FUNC_ETH] = "eth",
+ [FUNC_UART] = "uart",
+ [FUNC_HLDC] = "hldc",
+ [FUNC_USB] = "usb",
+ [FUNC_IRDA] = "irda",
+ [FUNC_DISABLED] = "off",
+};
void __init identify_ppc_sys_by_id(u32 id)
{
@@ -38,13 +50,13 @@ void __init identify_ppc_sys_by_id(u32 i
void __init identify_ppc_sys_by_name(char *name)
{
unsigned int i = 0;
- while (ppc_sys_specs[i].ppc_sys_name[0])
- {
+ while (ppc_sys_specs[i].ppc_sys_name[0]) {
if (!strcmp(ppc_sys_specs[i].ppc_sys_name, name))
break;
i++;
}
cur_ppc_sys_spec = &ppc_sys_specs[i];
+
return;
}
@@ -128,6 +140,126 @@ void ppc_sys_device_remove(enum ppc_sys_
}
}
+/* Platform-notify mapping
+ * Helper function for BSP code to assign board-specific platfom-divice bits
+ */
+
+void platform_notify_map(const struct platform_notify_dev_map *map,
+ struct device *dev)
+{
+ struct platform_device *pdev;
+ int len, idx;
+ const char *s;
+
+ /* do nothing if no device or no bus_id */
+ if (!dev || !dev->bus_id)
+ return;
+
+ /* call per device map */
+ while (map->bus_id != NULL) {
+ idx = -1;
+ s = strrchr(dev->bus_id, '.');
+ if (s != NULL)
+ idx = (int)simple_strtol(s + 1, NULL, 10);
+ else
+ s = dev->bus_id + strlen(s);
+
+ len = s - dev->bus_id;
+
+ if (!strncmp(dev->bus_id, map->bus_id, len)) {
+ pdev = container_of(dev, struct platform_device, dev);
+ map->rtn(pdev, idx);
+ }
+ map++;
+ }
+}
+
+/*
+ Function assignment stuff.
+ Intended to work as follows:
+ the device name defined in foo_devices.c will be concatenated with :"func",
+ where func is string map of respective function from platfom_device_func enum
+
+ The FUNC_ENABLED function is intended to remove all assignments, making the device to appear
+ in platform bus with unmodified name.
+ */
+
+/*
+ Here we'll replace .name pointers with fixed-lenght strings
+ Hereby, this should be called *before* any func stuff triggeded.
+ */
+void ppc_sys_device_initfunc(void)
+{
+ int i;
+ const char *name;
+ static char new_names[NUM_PPC_SYS_DEVS][BUS_ID_SIZE];
+ enum ppc_sys_devices cur_dev;
+
+ /* If inited yet, do nothing */
+ if (ppc_sys_func_inited)
+ return;
+
+ for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) {
+ if ((cur_dev = cur_ppc_sys_spec->device_list[i]) < 0)
+ continue;
+
+ if (ppc_sys_platform_devices[cur_dev].name) {
+ /*backup name */
+ name = ppc_sys_platform_devices[cur_dev].name;
+ strlcpy(new_names[i], name, BUS_ID_SIZE);
+ ppc_sys_platform_devices[cur_dev].name = new_names[i];
+ }
+ }
+
+ ppc_sys_func_inited = 1;
+}
+
+/*The "engine" of the func stuff. Here we either concat specified function string description
+ to the name, or remove it if FUNC_ENABLED parameter is passed here*/
+void ppc_sys_device_setfunc(enum ppc_sys_devices dev,
+ enum platform_device_func func)
+{
+ char *s;
+ char *name = (char *)ppc_sys_platform_devices[dev].name;
+ char tmp[BUS_ID_SIZE];
+
+ if (!ppc_sys_func_inited) {
+ printk(KERN_ERR "Unable to alter function - not inited!\n");
+ return;
+ }
+
+ if (ppc_sys_inited) {
+ platform_device_unregister(&ppc_sys_platform_devices[dev]);
+ }
+
+ if ((s = (char *)strchr(name, ':')) != NULL) { /* reassign */
+ /* Either change the name after ':' or remove func modifications */
+ if (func != FUNC_ENABLED)
+ strlcpy(s + 1, ppc_sys_func_names[func], BUS_ID_SIZE);
+ else
+ *s = 0;
+ } else if (func != FUNC_ENABLED) {
+ /* do assignment if it is not just "enable" request */
+ sprintf(tmp, "%s:%s", name, ppc_sys_func_names[func]);
+ strlcpy(name, tmp, BUS_ID_SIZE);
+ }
+
+ if (ppc_sys_inited) {
+ platform_device_register(&ppc_sys_platform_devices[dev]);
+ }
+}
+
+void ppc_sys_device_set_func_all(enum platform_device_func func)
+{
+ enum ppc_sys_devices cur_dev;
+ int i;
+
+ for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) {
+ cur_dev = cur_ppc_sys_spec->device_list[i];
+ ppc_sys_device_setfunc(cur_dev, func);
+ }
+}
+
static int __init ppc_sys_init(void)
{
unsigned int i, dev_id, ret = 0;
diff --git a/include/asm-ppc/mpc10x.h b/include/asm-ppc/mpc10x.h
index 77b1e09..976ad3d 100644
--- a/include/asm-ppc/mpc10x.h
+++ b/include/asm-ppc/mpc10x.h
@@ -165,6 +165,7 @@ enum ppc_sys_devices {
MPC10X_DMA1,
MPC10X_UART0,
MPC10X_UART1,
+ NUM_PPC_SYS_DEVS,
};
int mpc10x_bridge_init(struct pci_controller *hose,
diff --git a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
index e5f80c2..b2cb44f 100644
--- a/include/asm-ppc/mpc52xx.h
+++ b/include/asm-ppc/mpc52xx.h
@@ -49,6 +49,7 @@ enum ppc_sys_devices {
MPC52xx_ATA,
MPC52xx_I2C1,
MPC52xx_I2C2,
+ NUM_PPC_SYS_DEVS,
};
diff --git a/include/asm-ppc/mpc8260.h b/include/asm-ppc/mpc8260.h
index 3214526..6ba69a8 100644
--- a/include/asm-ppc/mpc8260.h
+++ b/include/asm-ppc/mpc8260.h
@@ -83,6 +83,7 @@ enum ppc_sys_devices {
MPC82xx_CPM_SMC2,
MPC82xx_CPM_USB,
MPC82xx_SEC1,
+ NUM_PPC_SYS_DEVS,
};
#ifndef __ASSEMBLY__
diff --git a/include/asm-ppc/mpc83xx.h b/include/asm-ppc/mpc83xx.h
index 7cdf60f..3c23fc4 100644
--- a/include/asm-ppc/mpc83xx.h
+++ b/include/asm-ppc/mpc83xx.h
@@ -108,6 +108,7 @@ enum ppc_sys_devices {
MPC83xx_USB2_DR,
MPC83xx_USB2_MPH,
MPC83xx_MDIO,
+ NUM_PPC_SYS_DEVS,
};
#endif /* CONFIG_83xx */
diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h
index 9d14bae..2a77884 100644
--- a/include/asm-ppc/mpc85xx.h
+++ b/include/asm-ppc/mpc85xx.h
@@ -135,6 +135,7 @@ enum ppc_sys_devices {
MPC85xx_eTSEC4,
MPC85xx_IIC2,
MPC85xx_MDIO,
+ NUM_PPC_SYS_DEVS,
};
/* Internal interrupts are all Level Sensitive, and Positive Polarity */
diff --git a/include/asm-ppc/mpc8xx.h b/include/asm-ppc/mpc8xx.h
index 46f159c..90e3d59 100644
--- a/include/asm-ppc/mpc8xx.h
+++ b/include/asm-ppc/mpc8xx.h
@@ -111,6 +111,7 @@ enum ppc_sys_devices {
MPC8xx_CPM_SMC1,
MPC8xx_CPM_SMC2,
MPC8xx_CPM_USB,
+ NUM_PPC_SYS_DEVS,
};
#ifndef BOARD_CHIP_NAME
diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h
index 83d8c77..76f259f 100644
--- a/include/asm-ppc/ppc_sys.h
+++ b/include/asm-ppc/ppc_sys.h
@@ -47,6 +47,21 @@ struct ppc_sys_spec {
enum ppc_sys_devices *device_list;
};
+struct platform_notify_dev_map {
+ const char *bus_id;
+ void (*rtn)(struct platform_device * pdev, int idx);
+};
+
+enum platform_device_func {
+ FUNC_ENABLED = 0,
+ FUNC_ETH = 1,
+ FUNC_UART = 2,
+ FUNC_HLDC = 3,
+ FUNC_USB = 4,
+ FUNC_IRDA = 5,
+ FUNC_DISABLED = 6,
+};
+
/* describes all specific chips and which devices they have on them */
extern struct ppc_sys_spec ppc_sys_specs[];
extern struct ppc_sys_spec *cur_ppc_sys_spec;
@@ -72,5 +87,14 @@ extern void *ppc_sys_get_pdata(enum ppc_
/* remove a device from the system */
extern void ppc_sys_device_remove(enum ppc_sys_devices dev);
+/*Function assignment stuff*/
+void ppc_sys_device_initfunc(void);
+void ppc_sys_device_setfunc(enum ppc_sys_devices dev,
+ enum platform_device_func func);
+void ppc_sys_device_set_func_all(enum platform_device_func func);
+
+void platform_notify_map(const struct platform_notify_dev_map *map,
+ struct device *dev);
+
#endif /* __ASM_PPC_SYS_H */
#endif /* __KERNEL__ */
---
Sincerely,
Vitaly
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox