Add support for MPC512x to fs_enet driver MPC5121 has an FEC core that is nearly identical to the FEC in 8xx. The only problem is that the registers locations have been shuffled. Because of this shuffling of registers, one needs a different structure to describe the 5121 FEC. This is not a huge problem since CPM2 and FEC are mutually exclusive, and therefore we can use CONFIG_CPM1 to distinguish between 5121 and 8xx.
arch/powerpc/boot/dts/mpc5121ads.dts Fix a typo in the file header and add ethernet and mdio nodes. drivers/net/fs_enet/Kconfig Add PPC_MPC512x to FS_ENET and FS_ENET_HAS_FEC depends. Also cleaned up the logic based on input from Scott Wood and Sam Ravnborg. drivers/net/fs_enet/fec_mpc5121.h This contains a struct fec with the appropriate order of fields for 5121. drivers/net/fs_enet/fs_enet-main.c Add a routine for conditionally copying TX skb's that are not aligned. Only do this if fep->fpi->align_tx_packets is set. In fs_enet_probe set fpi->align_tx_packets to the value of fsl,align-tx-packets property in the device node. Add a new entry to match table with compatible set to "fsl,mpc5121-fec". drivers/net/fs_enet/fs_enet.h Include fec_mpc5121.h. drivers/net/fs_enet/mac-fec.c Any code that is differnet between old 8xx fec and 512x fec is ifdef'd with CONFIG_CPM1. The file already had CONFIG_CPM1's in it so this isn't any more evil than what is already there. drivers/net/fs_enet/mii-fec.c Add a new entry to match table with compatible set to "fsl,mpc5121-fec-mdio". include/linux/fs_enet_pd.h Add an new field called align_tx_packets to struct fs_platform_info which is used in fs_enet_main.c as described above. Signed-off-by: John Rigby <[EMAIL PROTECTED]> --- arch/powerpc/boot/dts/mpc5121ads.dts | 24 ++++++++++++- drivers/net/fs_enet/Kconfig | 30 +++++++-------- drivers/net/fs_enet/fec_mpc5121.h | 64 ++++++++++++++++++++++++++++++++++ drivers/net/fs_enet/fs_enet-main.c | 41 +++++++++++++++++++++ drivers/net/fs_enet/fs_enet.h | 7 +++- drivers/net/fs_enet/mac-fec.c | 22 ++++++++++- drivers/net/fs_enet/mii-fec.c | 7 ++++ include/linux/fs_enet_pd.h | 2 + 8 files changed, 177 insertions(+), 20 deletions(-) create mode 100644 drivers/net/fs_enet/fec_mpc5121.h diff --git a/arch/powerpc/boot/dts/mpc5121ads.dts b/arch/powerpc/boot/dts/mpc5121ads.dts index 94ad7b2..bc9629e 100644 --- a/arch/powerpc/boot/dts/mpc5121ads.dts +++ b/arch/powerpc/boot/dts/mpc5121ads.dts @@ -1,5 +1,5 @@ /* - * MPC5121E MDS Device Tree Source + * MPC5121E ADS Device Tree Source * * Copyright 2007 Freescale Semiconductor Inc. * @@ -85,6 +85,28 @@ reg = <0xc00 0x100>; }; + [EMAIL PROTECTED] { + compatible = "fsl,mpc5121-fec-mdio"; + reg = <0x2800 0x800>; + #address-cells = <1>; + #size-cells = <0>; + phy: [EMAIL PROTECTED] { + reg = <1>; + device_type = "ethernet-phy"; + }; + }; + + [EMAIL PROTECTED] { + device_type = "network"; + compatible = "fsl,mpc5121-fec"; + reg = <0x2800 0x800>; + local-mac-address = [ 00 00 00 00 00 00 ]; + interrupts = <4 0x8>; + interrupt-parent = < &ipic >; + phy-handle = < &phy >; + fsl,align-tx-packets = <4>; + }; + // 512x PSCs are not 52xx PSCs compatible // PSC3 serial port A aka ttyPSC0 [EMAIL PROTECTED] { diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig index 562ea68..5806cea 100644 --- a/drivers/net/fs_enet/Kconfig +++ b/drivers/net/fs_enet/Kconfig @@ -1,30 +1,28 @@ config FS_ENET - tristate "Freescale Ethernet Driver" - depends on CPM1 || CPM2 + bool select MII select PHYLIB config FS_ENET_HAS_SCC - bool "Chip has an SCC usable for ethernet" - depends on FS_ENET && (CPM1 || CPM2) - default y + bool "Freescale CPM SCC Ethernet" + depends on CPM1 || CPM2 + select FS_ENET config FS_ENET_HAS_FCC - bool "Chip has an FCC usable for ethernet" - depends on FS_ENET && CPM2 - default y + bool "Freescale CPM FCC Ethernet" + depends on CPM2 + select FS_ENET config FS_ENET_HAS_FEC - bool "Chip has an FEC usable for ethernet" - depends on FS_ENET && CPM1 - select FS_ENET_MDIO_FEC - default y + bool "Freescale Fast Ethernet Controller" + depends on CPM1 || PPC_MPC512x + select FS_ENET config FS_ENET_MDIO_FEC - tristate "MDIO driver for FEC" - depends on FS_ENET && CPM1 + bool "Freescale FEC MDIO" + depends on FS_ENET_HAS_FEC config FS_ENET_MDIO_FCC - tristate "MDIO driver for FCC" - depends on FS_ENET && CPM2 + bool "Freescale CPM Bitbanged MDIO" + depends on CPM2 select MDIO_BITBANG diff --git a/drivers/net/fs_enet/fec_mpc5121.h b/drivers/net/fs_enet/fec_mpc5121.h new file mode 100644 index 0000000..e28c783 --- /dev/null +++ b/drivers/net/fs_enet/fec_mpc5121.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved. + * + * Author: John Rigby, <[EMAIL PROTECTED]> + * + * Modified version of drivers/net/fec.h: + * + * fec.h -- Fast Ethernet Controller for Motorola ColdFire SoC + * processors. + * + * (C) Copyright 2000-2005, Greg Ungerer ([EMAIL PROTECTED]) + * (C) Copyright 2000-2001, Lineo (www.lineo.com) + * + * This 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. + */ +#ifndef FEC_MPC5121_H +#define FEC_MPC5121_H + +#include <linux/types.h> +#include <asm/cpm.h> + +struct fec { + u32 fec_reserved0; + u32 fec_ievent; /* Interrupt event reg */ + u32 fec_imask; /* Interrupt mask reg */ + u32 fec_reserved1; + u32 fec_r_des_active; /* Receive descriptor reg */ + u32 fec_x_des_active; /* Transmit descriptor reg */ + u32 fec_reserved2[3]; + u32 fec_ecntrl; /* Ethernet control reg */ + u32 fec_reserved3[6]; + u32 fec_mii_data; /* MII manage frame reg */ + u32 fec_mii_speed; /* MII speed control reg */ + u32 fec_reserved4[7]; + u32 fec_mib_ctrlstat; /* MIB control/status reg */ + u32 fec_reserved5[7]; + u32 fec_r_cntrl; /* Receive control reg */ + u32 fec_reserved6[15]; + u32 fec_x_cntrl; /* Transmit Control reg */ + u32 fec_reserved7[7]; + u32 fec_addr_low; /* Low 32bits MAC address */ + u32 fec_addr_high; /* High 16bits MAC address */ + u32 fec_opd; /* Opcode + Pause duration */ + u32 fec_reserved8[10]; + u32 fec_hash_table_high; /* High 32bits hash table */ + u32 fec_hash_table_low; /* Low 32bits hash table */ + u32 fec_grp_hash_table_high;/* High 32bits hash table */ + u32 fec_grp_hash_table_low; /* Low 32bits hash table */ + u32 fec_reserved9[7]; + u32 fec_x_wmrk; /* FIFO transmit water mark */ + u32 fec_reserved10; + u32 fec_r_bound; /* FIFO receive bound reg */ + u32 fec_r_fstart; /* FIFO receive start reg */ + u32 fec_reserved11[11]; + u32 fec_r_des_start; /* Receive descriptor ring */ + u32 fec_x_des_start; /* Transmit descriptor ring */ + u32 fec_r_buff_size; /* Maximum receive buff size */ + u32 fec_dma_control; /* DMA Endian and other ctrl */ +}; + +#endif /* FEC_MPC5121_H */ diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index 8ebf388..f3c3c8e 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -597,6 +597,37 @@ void fs_cleanup_bds(struct net_device *dev) /*******************************************************************************/ +/* + * The 5121 FEC doc says transmit buffers must have 4 byte alignment. + * We get alignement from the device tree in case this changes on future + * platforms. + */ +static struct sk_buff *align_tx_skb(struct net_device *dev, struct sk_buff *skb, + int align) +{ + struct sk_buff *skbn; + + if ((((unsigned long)skb->data) & (align-1)) == 0) + return skb; + + skbn = dev_alloc_skb(ENET_RX_FRSIZE+align); + if (skbn) + skb_align(skbn, align); + + if (!skbn) { + printk(KERN_WARNING DRV_MODULE_NAME + ": %s Memory squeeze, dropping tx packet.\n", + dev->name); + dev_kfree_skb_any(skb); + return NULL; + } + + skb_copy_from_linear_data(skb, skbn->data, skb->len); + skb_put(skbn, skb->len); + dev_kfree_skb_any(skb); + return skbn; +} + static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); @@ -605,6 +636,8 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) u16 sc; unsigned long flags; + if (fep->fpi->align_tx_packets) + skb = align_tx_skb(dev, skb, fep->fpi->align_tx_packets); spin_lock_irqsave(&fep->tx_lock, flags); /* @@ -1057,6 +1090,10 @@ static int __devinit fs_enet_probe(struct of_device *ofdev, fpi->cp_command = *data; } + data = of_get_property(ofdev->node, "fsl,align-tx-packets", &len); + if (data && len == 4) + fpi->align_tx_packets = *data; + fpi->rx_ring = 32; fpi->tx_ring = 32; fpi->rx_copybreak = 240; @@ -1184,6 +1221,10 @@ static struct of_device_id fs_enet_match[] = { .compatible = "fsl,pq1-fec-enet", .data = (void *)&fs_fec_ops, }, + { + .compatible = "fsl,mpc5121-fec", + .data = (void *)&fs_fec_ops, + }, #endif {} }; diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h index 7bf779a..ea70938 100644 --- a/drivers/net/fs_enet/fs_enet.h +++ b/drivers/net/fs_enet/fs_enet.h @@ -10,12 +10,17 @@ #include <linux/fs_enet_pd.h> #include <asm/fs_pd.h> +#ifdef CONFIG_PPC_MPC512x +#include "fec_mpc5121.h" +#endif #ifdef CONFIG_CPM1 #include <asm/cpm1.h> +#endif +#if defined(CONFIG_FS_ENET_HAS_FEC) struct fec_info { - fec_t __iomem *fecp; + struct fec __iomem *fecp; u32 mii_speed; }; #endif diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c index cac51b1..e2ea216 100644 --- a/drivers/net/fs_enet/mac-fec.c +++ b/drivers/net/fs_enet/mac-fec.c @@ -43,6 +43,9 @@ #include <asm/mpc8xx.h> #include <asm/cpm1.h> #endif +#ifdef CONFIG_PPC_MPC512x +#include "fec_mpc5121.h" +#endif #include "fs_enet.h" #include "fec.h" @@ -285,7 +288,9 @@ static void restart(struct net_device *dev) * Set maximum receive buffer size. */ FW(fecp, r_buff_size, PKT_MAXBLR_SIZE); +#ifdef CONFIG_CPM1 FW(fecp, r_hash, PKT_MAXBUF_SIZE); +#endif /* get physical address */ rx_bd_base_phys = fep->ring_mem_addr; @@ -299,10 +304,17 @@ static void restart(struct net_device *dev) fs_init_bds(dev); +#ifdef CONFIG_CPM1 /* * Enable big endian and don't care about SDMA FC. */ FW(fecp, fun_code, 0x78000000); +#else + /* + * Set DATA_BO and DESC_BO and leave the rest unchanged + */ + FS(fecp, dma_control, 0xc0000000); +#endif /* * Set MII speed. @@ -313,11 +325,13 @@ static void restart(struct net_device *dev) * Clear any outstanding interrupt. */ FW(fecp, ievent, 0xffc0); +#ifdef CONFIG_CPM1 #ifndef CONFIG_PPC_MERGE FW(fecp, ivec, (fep->interrupt / 2) << 29); #else FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29); #endif +#endif /* * adjust to speed (only for DUET & RMII) @@ -347,9 +361,13 @@ static void restart(struct net_device *dev) out_be32(&immap->im_cpm.cp_cptr, cptr); } #endif - - +#ifdef CONFIG_CPM1 FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ +#else + FW(fecp, r_cntrl, PKT_MAXBUF_SIZE<<16); /* max frame size */ + FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ +#endif + /* * adjust to duplex mode */ diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c index 5079dcf..a1bca5f 100644 --- a/drivers/net/fs_enet/mii-fec.c +++ b/drivers/net/fs_enet/mii-fec.c @@ -214,9 +214,16 @@ static int fs_enet_mdio_remove(struct of_device *ofdev) } static struct of_device_id fs_enet_mdio_fec_match[] = { +#ifdef CONFIG_CPM1 { .compatible = "fsl,pq1-fec-mdio", }, +#endif +#ifdef CONFIG_PPC_MPC512x + { + .compatible = "fsl,mpc5121-fec-mdio", + }, +#endif {}, }; diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h index 0ba21ee..28df8d1 100644 --- a/include/linux/fs_enet_pd.h +++ b/include/linux/fs_enet_pd.h @@ -148,6 +148,8 @@ struct fs_platform_info { int use_rmii; /* use RMII mode */ int has_phy; /* if the network is phy container as well...*/ + + int align_tx_packets; /* align transmit skb's */ }; struct fs_mii_fec_platform_info { u32 irq[32]; -- 1.5.6.rc0.46.gd2b3 _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev