Subject: powerpc: Axon: add device tree support to ibm_emac This patch adds of_platform probing and basic dt support to ibm_emac. Signed-off-by: Shaun Wetzstein Signed-off-by: Arnd Bergmann Index: linux-2.6/drivers/net/ibm_emac/ibm_emac_mal.c =================================================================== --- linux-2.6.orig/drivers/net/ibm_emac/ibm_emac_mal.c +++ linux-2.6/drivers/net/ibm_emac/ibm_emac_mal.c @@ -27,8 +27,6 @@ #include #include -#include - #include "ibm_emac_core.h" #include "ibm_emac_mal.h" #include "ibm_emac_debug.h" @@ -400,18 +398,19 @@ void *mal_dump_regs(struct ibm_ocp_mal * return regs + 1; } -static int __init mal_probe(struct ocp_device *ocpdev) +#ifdef CONFIG_IBM_EMAC_OCP +static int __init mal_probe(struct bus_device *dev) { struct ibm_ocp_mal *mal; struct ocp_func_mal_data *maldata; int err = 0, i, bd_size; - MAL_DBG("%d: probe" NL, ocpdev->def->index); + MAL_DBG("%d: probe" NL, dev->def->index); - maldata = ocpdev->def->additions; + maldata = dev->def->additions; if (maldata == NULL) { printk(KERN_ERR "mal%d: missing additional data!\n", - ocpdev->def->index); + dev->def->index); return -ENODEV; } @@ -419,11 +418,88 @@ static int __init mal_probe(struct ocp_d if (!mal) { printk(KERN_ERR "mal%d: out of memory allocating MAL structure!\n", - ocpdev->def->index); + dev->def->index); return -ENOMEM; } mal->dcrbase = maldata->dcr_base; - mal->def = ocpdev->def; + mal->def = dev->def; +#else +static int __init mal_probe(struct bus_device *dev, + const struct of_device_id *match) +{ + struct ibm_ocp_mal *mal; + struct ocp_func_mal_data *maldata; + int err = 0, i, bd_size; + + static int index = 0; + u32 *data; + + MAL_DBG("%d: probe" NL, index); + + mal = kzalloc(sizeof(struct ibm_ocp_mal) + + sizeof(struct ocp_def) + + sizeof(struct ocp_func_mal_data), GFP_KERNEL); + if (!mal) { + printk(KERN_ERR + "mal%d: out of memory allocating MAL structure!\n", + index); + return -ENOMEM; + } + mal->def = (struct ocp_def *)(mal + 1); + mal->def->additions = (void *)(mal->def + 1); + mal->def->index = index++; + maldata = mal->def->additions; + + data = (u32 *)get_property(dev->node, "dcr-reg", NULL); + if (data == NULL) { + of_node_put(dev->node); + printk(KERN_ERR + "mal%d: can't find MAL dcr-reg property!\n", + mal->def->index); + err = -ENODEV; + goto fail; + } + maldata->dcr_base = data[0]; + + data = (u32 *)get_property(dev->node, "num-tx-chans", NULL); + if (data == NULL) { + of_node_put(dev->node); + printk(KERN_ERR + "mal%d: can't find MAL num-tx-chans property!\n", + mal->def->index); + err = -ENODEV; + goto fail; + } + maldata->num_tx_chans = data[0]; + + data = (u32 *)get_property(dev->node, "num-rx-chans", NULL); + if (data == NULL) { + of_node_put(dev->node); + printk(KERN_ERR + "emac%d: can't find MAL num-rx-chans property!\n", + mal->def->index); + err = -ENODEV; + goto fail; + } + maldata->num_rx_chans = data[0]; + + mal->dcr_ctlr = dcr_find_controller(dev->node); + if (mal->dcr_ctlr == NULL) { + printk(KERN_ERR + "emac%d: can't find DCR controller!\n", + mal->def->index); + err = -ENODEV; + goto fail; + } + + mal->dcrbase = maldata->dcr_base; + + maldata->txeob_irq = irq_of_parse_and_map(dev->node, 2); + maldata->rxeob_irq = irq_of_parse_and_map(dev->node, 3); + maldata->serr_irq = irq_of_parse_and_map(dev->node, 4); + maldata->txde_irq = irq_of_parse_and_map(dev->node, 5); + maldata->rxde_irq = irq_of_parse_and_map(dev->node, 6); +#endif INIT_LIST_HEAD(&mal->poll_list); set_bit(__LINK_STATE_START, &mal->poll_dev.state); @@ -450,7 +526,7 @@ static int __init mal_probe(struct ocp_d (NUM_TX_BUFF * maldata->num_tx_chans + NUM_RX_BUFF * maldata->num_rx_chans); mal->bd_virt = - dma_alloc_coherent(&ocpdev->dev, bd_size, &mal->bd_dma, GFP_KERNEL); + dma_alloc_coherent(&dev->dev, bd_size, &mal->bd_dma, GFP_KERNEL); if (!mal->bd_virt) { printk(KERN_ERR @@ -471,19 +547,19 @@ static int __init mal_probe(struct ocp_d sizeof(struct mal_descriptor) * mal_rx_bd_offset(mal, i)); - err = request_irq(maldata->serr_irq, mal_serr, 0, "MAL SERR", mal); + err = request_irq(maldata->serr_irq, mal_serr, IRQF_PROBE_SHARED|IRQF_SHARED, "MAL SERR", mal); if (err) goto fail2; - err = request_irq(maldata->txde_irq, mal_txde, 0, "MAL TX DE", mal); + err = request_irq(maldata->txde_irq, mal_txde, IRQF_PROBE_SHARED|IRQF_SHARED, "MAL TX DE", mal); if (err) goto fail3; - err = request_irq(maldata->txeob_irq, mal_txeob, 0, "MAL TX EOB", mal); + err = request_irq(maldata->txeob_irq, mal_txeob, IRQF_PROBE_SHARED|IRQF_SHARED, "MAL TX EOB", mal); if (err) goto fail4; - err = request_irq(maldata->rxde_irq, mal_rxde, 0, "MAL RX DE", mal); + err = request_irq(maldata->rxde_irq, mal_rxde, IRQF_PROBE_SHARED|IRQF_SHARED, "MAL RX DE", mal); if (err) goto fail5; - err = request_irq(maldata->rxeob_irq, mal_rxeob, 0, "MAL RX EOB", mal); + err = request_irq(maldata->rxeob_irq, mal_rxeob, IRQF_PROBE_SHARED|IRQF_SHARED, "MAL RX EOB", mal); if (err) goto fail6; @@ -491,7 +567,7 @@ static int __init mal_probe(struct ocp_d set_mal_dcrn(mal, MAL_IER, MAL_IER_EVENTS); /* Advertise this instance to the rest of the world */ - ocp_set_drvdata(ocpdev, mal); + bus_set_drvdata(dev, mal); mal_dbg_register(mal->def->index, mal); @@ -508,15 +584,15 @@ static int __init mal_probe(struct ocp_d fail3: free_irq(maldata->serr_irq, mal); fail2: - dma_free_coherent(&ocpdev->dev, bd_size, mal->bd_virt, mal->bd_dma); + dma_free_coherent(&dev->dev, bd_size, mal->bd_virt, mal->bd_dma); fail: kfree(mal); return err; } -static void __exit mal_remove(struct ocp_device *ocpdev) +static int __exit mal_remove(struct bus_device *dev) { - struct ibm_ocp_mal *mal = ocp_get_drvdata(ocpdev); + struct ibm_ocp_mal *mal = bus_get_drvdata(dev); struct ocp_func_mal_data *maldata = mal->def->additions; MAL_DBG("%d: remove" NL, mal->def->index); @@ -534,7 +610,7 @@ static void __exit mal_remove(struct ocp mal->def->index); } - ocp_set_drvdata(ocpdev, NULL); + bus_set_drvdata(dev, NULL); free_irq(maldata->serr_irq, mal); free_irq(maldata->txde_irq, mal); @@ -546,15 +622,20 @@ static void __exit mal_remove(struct ocp mal_dbg_register(mal->def->index, NULL); - dma_free_coherent(&ocpdev->dev, + dma_free_coherent(&dev->dev, sizeof(struct mal_descriptor) * (NUM_TX_BUFF * maldata->num_tx_chans + NUM_RX_BUFF * maldata->num_rx_chans), mal->bd_virt, mal->bd_dma); kfree(mal); + +#ifndef CONFIG_IBM_EMAC_OCP + return 0; +#endif } +#ifdef CONFIG_IBM_EMAC_OCP /* Structure for a device driver */ static struct ocp_device_id mal_ids[] = { { .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_MAL }, @@ -568,15 +649,46 @@ static struct ocp_driver mal_driver = { .probe = mal_probe, .remove = mal_remove, }; +#else +static struct of_device_id mal_platform_match[] = +{ + { + .type = "mal", + }, + {}, +}; + +static struct of_platform_driver mal_of_driver = { + .name = "mal", + .match_table = mal_platform_match, + + .probe = mal_probe, + .remove = mal_remove, +}; +#endif int __init mal_init(void) { + int rc; + MAL_DBG(": init" NL); - return ocp_register_driver(&mal_driver); + +#ifdef CONFIG_IBM_EMAC_OCP + rc = ocp_register_driver(&mal_driver); + if (rc) return rc; +#else + of_register_driver(&mal_of_driver); + rc = 0; +#endif + return rc; } void __exit mal_exit(void) { MAL_DBG(": exit" NL); +#ifdef CONFIG_IBM_EMAC_OCP ocp_unregister_driver(&mal_driver); +#else + of_unregister_driver(&mal_of_driver); +#endif } Index: linux-2.6/drivers/net/ibm_emac/ibm_emac_mal.h =================================================================== --- linux-2.6.orig/drivers/net/ibm_emac/ibm_emac_mal.h +++ linux-2.6/drivers/net/ibm_emac/ibm_emac_mal.h @@ -24,7 +24,13 @@ #include #include +#include +#ifndef CONFIG_IBM_EMAC_OCP +#include "ibm_emac_compat.h" +#endif + +/* XXX FIXME */ /* * These MAL "versions" probably aren't the real versions IBM uses for these * MAL cores, I assigned them just to make #ifdefs in this file nicer and @@ -34,7 +40,7 @@ defined(CONFIG_440EP) || defined(CONFIG_440GR) || defined(CONFIG_NP405H) #define MAL_VERSION 1 #elif defined(CONFIG_440GP) || defined(CONFIG_440GX) || defined(CONFIG_440SP) || \ - defined(CONFIG_440SPE) + defined(CONFIG_440SPE) || defined(CONFIG_PPC_CELL) #define MAL_VERSION 2 #else #error "Unknown SoC, please check chip manual and choose MAL 'version'" @@ -190,6 +196,9 @@ struct mal_commac { }; struct ibm_ocp_mal { +#ifndef CONFIG_IBM_EMAC_OCP + void * dcr_ctlr; +#endif int dcrbase; struct list_head poll_list; @@ -207,12 +216,12 @@ struct ibm_ocp_mal { static inline u32 get_mal_dcrn(struct ibm_ocp_mal *mal, int reg) { - return mfdcr(mal->dcrbase + reg); + return dcr_read(mal->dcr_ctlr, mal->dcrbase + reg); } static inline void set_mal_dcrn(struct ibm_ocp_mal *mal, int reg, u32 val) { - mtdcr(mal->dcrbase + reg, val); + dcr_write(mal->dcr_ctlr, mal->dcrbase + reg, val); } /* Register MAL devices */ Index: linux-2.6/drivers/net/Kconfig =================================================================== --- linux-2.6.orig/drivers/net/Kconfig +++ linux-2.6/drivers/net/Kconfig @@ -1212,11 +1212,19 @@ config SYSTEMSIM_NET config IBM_EMAC tristate "PowerPC 4xx on-chip Ethernet support" - depends on 4xx + depends on NET_ETHERNET && PPC_DCR help This driver supports the PowerPC 4xx EMAC family of on-chip Ethernet controllers. +config IBM_EMAC_OCP + bool "On-Chip Peripheral bus support (PPC32 only)" + depends on IBM_EMAC && 4xx && !PPC_MERGE + default y + help + Adds support for OCP bus probing. Selecting 'No' here + causes the driver to use OF platform bus probing. + config IBM_EMAC_RXB int "Number of receive buffers" depends on IBM_EMAC @@ -1267,14 +1275,14 @@ config IBM_EMAC_DEBUG config IBM_EMAC_ZMII bool - depends on IBM_EMAC && (NP405H || NP405L || 44x) + depends on IBM_EMAC && (NP405H || NP405L || 44x || PPC_CELL) default y config IBM_EMAC_RGMII bool - depends on IBM_EMAC && 440GX + depends on IBM_EMAC && (440GX || PPC_CELL) default y - + config IBM_EMAC_TAH bool depends on IBM_EMAC && 440GX Index: linux-2.6/drivers/net/ibm_emac/ibm_emac.h =================================================================== --- linux-2.6.orig/drivers/net/ibm_emac/ibm_emac.h +++ linux-2.6/drivers/net/ibm_emac/ibm_emac.h @@ -22,14 +22,6 @@ #include -/* This is a simple check to prevent use of this driver on non-tested SoCs */ -#if !defined(CONFIG_405GP) && !defined(CONFIG_405GPR) && !defined(CONFIG_405EP) && \ - !defined(CONFIG_440GP) && !defined(CONFIG_440GX) && !defined(CONFIG_440SP) && \ - !defined(CONFIG_440EP) && !defined(CONFIG_NP405H) && !defined(CONFIG_440SPE) && \ - !defined(CONFIG_440GR) -#error "Unknown SoC. Please, check chip user manual and make sure EMAC defines are OK" -#endif - /* EMAC registers Write Access rules */ struct emac_regs { u32 mr0; /* special */ @@ -112,10 +104,16 @@ struct emac_regs { #define EMAC_MR1_MWSW_001 0x00000000 #define EMAC_MR1_BASE(opb) (EMAC_MR1_TFS_2K | EMAC_MR1_TR0_MULT) #else +#define EMAC_MR1_RFS_2K 0x00100000 #define EMAC_MR1_RFS_4K 0x00180000 #define EMAC_MR1_RFS_16K 0x00280000 +#if defined(CONFIG_PPC_CELL) +#define EMAC_RX_FIFO_SIZE(gige) 2048 +#else #define EMAC_RX_FIFO_SIZE(gige) ((gige) ? 16384 : 4096) +#endif #define EMAC_MR1_TFS_2K 0x00020000 +#define EMAC_MR1_TFS_4K 0x00030000 #define EMAC_MR1_TR 0x00008000 #define EMAC_MR1_MWSW_001 0x00001000 #define EMAC_MR1_JPSM 0x00000800 @@ -129,9 +127,14 @@ struct emac_regs { (freq) <= 66 ? EMAC_MR1_OBCI_66 : \ (freq) <= 83 ? EMAC_MR1_OBCI_83 : \ (freq) <= 100 ? EMAC_MR1_OBCI_100 : EMAC_MR1_OBCI_100P) +#if defined(CONFIG_PPC_CELL) +#define EMAC_MR1_BASE(opb) (EMAC_MR1_TFS_4K | EMAC_MR1_TR | \ + EMAC_MR1_OBCI(opb)) +#else #define EMAC_MR1_BASE(opb) (EMAC_MR1_TFS_2K | EMAC_MR1_TR | \ EMAC_MR1_OBCI(opb)) #endif +#endif /* EMACx_TMR0 */ #define EMAC_TMR0_GNP 0x80000000 @@ -227,9 +230,17 @@ struct emac_regs { #define EMAC_STACR_PHYD_SHIFT 16 #define EMAC_STACR_OC 0x00008000 #define EMAC_STACR_PHYE 0x00004000 -#define EMAC_STACR_STAC_MASK 0x00003000 #define EMAC_STACR_STAC_READ 0x00001000 + +/* XXX FIXME */ +#if defined(CONFIG_PPC_CELL) +#define EMAC_STACR_STAC_MASK 0x00001800 +#define EMAC_STACR_STAC_WRITE 0x00000800 +#else +#define EMAC_STACR_STAC_MASK 0x00003000 #define EMAC_STACR_STAC_WRITE 0x00002000 +#endif + #if !defined(CONFIG_IBM_EMAC4) #define EMAC_STACR_OPBC_MASK 0x00000C00 #define EMAC_STACR_OPBC_50 0x00000000 @@ -250,8 +261,9 @@ struct emac_regs { /* * For the 440SPe, AMCC inexplicably changed the polarity of * the "operation complete" bit in the MII control register. + * XXX FIXME */ -#if defined(CONFIG_440SPE) +#if defined(CONFIG_440SPE) || defined(CONFIG_PPC_CELL) static inline int emac_phy_done(u32 stacr) { return !(stacr & EMAC_STACR_OC); Index: linux-2.6/drivers/net/ibm_emac/ibm_emac_core.h =================================================================== --- linux-2.6.orig/drivers/net/ibm_emac/ibm_emac_core.h +++ linux-2.6/drivers/net/ibm_emac/ibm_emac_core.h @@ -22,7 +22,6 @@ #include #include -#include #include "ibm_emac.h" #include "ibm_emac_phy.h" @@ -30,6 +29,10 @@ #include "ibm_emac_rgmii.h" #include "ibm_emac_mal.h" #include "ibm_emac_tah.h" +#include "ibm_emac_busdev.h" +#ifndef CONFIG_IBM_EMAC_OCP +#include "ibm_emac_compat.h" +#endif #define NUM_TX_BUFF CONFIG_IBM_EMAC_TXB #define NUM_RX_BUFF CONFIG_IBM_EMAC_RXB @@ -168,7 +171,7 @@ struct ocp_enet_private { int rx_sync_size; struct ibm_emac_stats stats; - struct ocp_device *tah_dev; + struct bus_device *tah_dev; struct ibm_ocp_mal *mal; struct mal_commac commac; @@ -176,10 +179,11 @@ struct ocp_enet_private { struct sk_buff *tx_skb[NUM_TX_BUFF]; struct sk_buff *rx_skb[NUM_RX_BUFF]; - struct ocp_device *zmii_dev; + struct bus_device *zmii_dev; int zmii_input; struct ocp_enet_private *mdio_dev; - struct ocp_device *rgmii_dev; + + struct bus_device *rgmii_dev; int rgmii_input; struct ocp_def *def; Index: linux-2.6/drivers/net/ibm_emac/ibm_emac_zmii.h =================================================================== --- linux-2.6.orig/drivers/net/ibm_emac/ibm_emac_zmii.h +++ linux-2.6/drivers/net/ibm_emac/ibm_emac_zmii.h @@ -20,7 +20,8 @@ #define _IBM_EMAC_ZMII_H_ #include -#include + +#include "ibm_emac_busdev.h" /* ZMII bridge registers */ struct zmii_regs { @@ -40,35 +41,35 @@ struct ibm_ocp_zmii { #ifdef CONFIG_IBM_EMAC_ZMII int zmii_attach(void *emac) __init; -void __zmii_fini(struct ocp_device *ocpdev, int input) __exit; -static inline void zmii_fini(struct ocp_device *ocpdev, int input) +void __zmii_fini(struct bus_device *dev, int input) __exit; +static inline void zmii_fini(struct bus_device *dev, int input) { - if (ocpdev) - __zmii_fini(ocpdev, input); + if (dev) + __zmii_fini(dev, input); } -void __zmii_enable_mdio(struct ocp_device *ocpdev, int input); -static inline void zmii_enable_mdio(struct ocp_device *ocpdev, int input) +void __zmii_enable_mdio(struct bus_device *dev, int input); +static inline void zmii_enable_mdio(struct bus_device *dev, int input) { - if (ocpdev) - __zmii_enable_mdio(ocpdev, input); + if (dev) + __zmii_enable_mdio(dev, input); } -void __zmii_set_speed(struct ocp_device *ocpdev, int input, int speed); -static inline void zmii_set_speed(struct ocp_device *ocpdev, int input, +void __zmii_set_speed(struct bus_device *dev, int input, int speed); +static inline void zmii_set_speed(struct bus_device *dev, int input, int speed) { - if (ocpdev) - __zmii_set_speed(ocpdev, input, speed); + if (dev) + __zmii_set_speed(dev, input, speed); } -int __zmii_get_regs_len(struct ocp_device *ocpdev); -static inline int zmii_get_regs_len(struct ocp_device *ocpdev) +int __zmii_get_regs_len(struct bus_device *dev); +static inline int zmii_get_regs_len(struct bus_device *dev) { - return ocpdev ? __zmii_get_regs_len(ocpdev) : 0; + return dev ? __zmii_get_regs_len(dev) : 0; } -void *zmii_dump_regs(struct ocp_device *ocpdev, void *buf); +void *zmii_dump_regs(struct bus_device *dev, void *buf); #else # define zmii_attach(x) 0 Index: linux-2.6/drivers/net/ibm_emac/ibm_emac_tah.h =================================================================== --- linux-2.6.orig/drivers/net/ibm_emac/ibm_emac_tah.h +++ linux-2.6/drivers/net/ibm_emac/ibm_emac_tah.h @@ -18,7 +18,6 @@ #define _IBM_EMAC_TAH_H #include -#include /* TAH */ struct tah_regs { Index: linux-2.6/drivers/net/ibm_emac/ibm_emac_core.c =================================================================== --- linux-2.6.orig/drivers/net/ibm_emac/ibm_emac_core.c +++ linux-2.6/drivers/net/ibm_emac/ibm_emac_core.c @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include "ibm_emac_core.h" #include "ibm_emac_debug.h" @@ -72,6 +72,10 @@ MODULE_AUTHOR ("Eugene Surovegin or "); MODULE_LICENSE("GPL"); +#ifdef CONFIG_PPC64 +#define cacheable_memcpy(d,s,n) memcpy((d),(s),(n)) +#endif + /* minimum number of free TX descriptors required to wake up TX process */ #define EMAC_TX_WAKEUP_THRESH (NUM_TX_BUFF / 4) @@ -386,7 +390,11 @@ static inline u32 emac_iff2rmr(struct ne static inline int emac_opb_mhz(void) { +#ifdef FIX_ME return (ocp_sys_info.opb_bus_freq + 500000) / 1000000; +#else + return 133; +#endif } /* BHs disabled */ @@ -421,7 +429,12 @@ static int emac_configure(struct ocp_ene out_be32(&p->ipcr, 0xdeadbeef); } else r |= EMAC_MR1_MF_1000; + +#if defined(CONFIG_PPC_CELL) + r |= EMAC_MR1_RFS_2K; +#else r |= EMAC_MR1_RFS_16K; +#endif gige = 1; if (dev->ndev->mtu > ETH_DATA_LEN) { @@ -435,7 +448,11 @@ static int emac_configure(struct ocp_ene dev->stop_timeout = STOP_TIMEOUT_100; /* Fall through */ default: +#if defined(CONFIG_PPC_CELL) + r |= EMAC_MR1_RFS_2K; +#else r |= EMAC_MR1_RFS_4K; +#endif gige = 0; break; } @@ -552,6 +569,16 @@ static void emac_full_tx_reset(struct ne netif_wake_queue(ndev); } +static void mii_enable_mdio(struct ocp_enet_private *dev) +{ + if (dev) { + if (dev->zmii_dev) + zmii_enable_mdio(dev->zmii_dev, dev->zmii_input); + else + rgmii_enable_mdio(dev->rgmii_dev, dev->rgmii_input); + } +} + static int __emac_mdio_read(struct ocp_enet_private *dev, u8 id, u8 reg) { struct emac_regs __iomem *p = dev->emacp; @@ -561,7 +588,7 @@ static int __emac_mdio_read(struct ocp_e DBG2("%d: mdio_read(%02x,%02x)" NL, dev->def->index, id, reg); /* Enable proper MDIO port */ - zmii_enable_mdio(dev->zmii_dev, dev->zmii_input); + mii_enable_mdio(dev); /* Wait for management interface to become idle */ n = 10; @@ -610,7 +637,7 @@ static void __emac_mdio_write(struct ocp val); /* Enable proper MDIO port */ - zmii_enable_mdio(dev->zmii_dev, dev->zmii_input); + mii_enable_mdio(dev); /* Wait for management interface to be idle */ n = 10; @@ -1240,6 +1267,7 @@ static void emac_parse_tx_error(struct o static void emac_poll_tx(void *param) { struct ocp_enet_private *dev = param; + DBG2("%d: poll_tx, %d %d" NL, dev->def->index, dev->tx_cnt, dev->ack_slot); @@ -1612,24 +1640,28 @@ static struct net_device_stats *emac_sta return nst; } -static void emac_remove(struct ocp_device *ocpdev) +static int emac_remove(struct bus_device *dev) { - struct ocp_enet_private *dev = ocp_get_drvdata(ocpdev); + struct ocp_enet_private *edev = bus_get_drvdata(dev); + + DBG("%d: remove" NL, edev->def->index); - DBG("%d: remove" NL, dev->def->index); + bus_set_drvdata(dev, 0); + unregister_netdev(edev->ndev); - ocp_set_drvdata(ocpdev, NULL); - unregister_netdev(dev->ndev); + tah_fini(dev->tah_dev); + rgmii_fini(edev->rgmii_dev, edev->rgmii_input); + zmii_fini(edev->zmii_dev, edev->zmii_input); - tah_fini(dev->tah_dev); - rgmii_fini(dev->rgmii_dev, dev->rgmii_input); - zmii_fini(dev->zmii_dev, dev->zmii_input); + emac_dbg_register(edev->def->index, 0); - emac_dbg_register(dev->def->index, NULL); + mal_unregister_commac(edev->mal, &edev->commac); + iounmap((void *)edev->emacp); + kfree(edev->ndev); - mal_unregister_commac(dev->mal, &dev->commac); - iounmap(dev->emacp); - kfree(dev->ndev); +#ifndef CONFIG_IBM_EMAC_OCP + return 0; +#endif } static struct mal_commac_ops emac_commac_ops = { @@ -1938,19 +1970,20 @@ static int emac_ioctl(struct net_device } } -static int __init emac_probe(struct ocp_device *ocpdev) +#ifdef CONFIG_IBM_EMAC_OCP +static int __init emac_probe(struct ocp_device *dev) { - struct ocp_func_emac_data *emacdata = ocpdev->def->additions; + struct ocp_func_emac_data *emacdata = dev->def->additions; + struct bus_device *maldev; struct net_device *ndev; - struct ocp_device *maldev; - struct ocp_enet_private *dev; + struct ocp_enet_private *edev; int err, i; - DBG("%d: probe" NL, ocpdev->def->index); + DBG("%d: probe" NL, dev->def->index); if (!emacdata) { printk(KERN_ERR "emac%d: Missing additional data!\n", - ocpdev->def->index); + dev->def->index); return -ENODEV; } @@ -1966,91 +1999,224 @@ static int __init emac_probe(struct ocp_ dev->ldev = &ocpdev->dev; dev->def = ocpdev->def; SET_MODULE_OWNER(ndev); +#else +static unsigned int * ibm_emac_get_property(int dev_nr, + struct device_node * node, + const char * name) +{ + unsigned int * ret = (unsigned int *)get_property(node, name, NULL); + if (!ret) { + of_node_put(node); + printk(KERN_ERR + "emac%d: can't find EMAC %s property!\n", + dev_nr, name); + } + return ret; +} - /* Find MAL device we are connected to */ +static int __init emac_probe(struct of_device *dev, + const struct of_device_id *match) +{ + struct ocp_func_emac_data *emacdata; + struct bus_device *maldev; + struct net_device *ndev; + struct ocp_enet_private *edev; + int err = -ENODEV, i; + + struct device_node *malnode; + static int index = 0; + u32 *phy_dev, *phy_port, *data; + struct resource r; + + emacdata = kzalloc(sizeof(struct ocp_func_emac_data) + + sizeof(struct ocp_def), GFP_KERNEL); + if (!emacdata) { + printk(KERN_ERR + "emac%d: could not allocate EMAC data structure!\n", + index); + return -ENOMEM; + } + + emacdata->rgmii_idx = -1; + emacdata->zmii_idx = -1; + emacdata->mdio_idx = -1; + emacdata->mal_idx = -1; + emacdata->tah_idx = -1; + + data = ibm_emac_get_property(index, dev->node, "phy-map"); + if (!data) goto out1; + emacdata->phy_map = *data; + + data = ibm_emac_get_property(index, dev->node, "phy-mode"); + if (!data) goto out1; + emacdata->phy_mode = *data; + + phy_dev = ibm_emac_get_property(index, dev->node, "phy-device"); + if (!phy_dev) goto out1; + phy_port = ibm_emac_get_property(index, dev->node, "phy-port"); + if (!phy_port) goto out1; + + switch (emacdata->phy_mode) { + case PHY_MODE_RGMII : + case PHY_MODE_GMII : + case PHY_MODE_TBI : + case PHY_MODE_RTBI : + emacdata->rgmii_idx = *phy_dev; + emacdata->rgmii_mux = *phy_port; + break; + case PHY_MODE_MII : + case PHY_MODE_RMII : + case PHY_MODE_SMII : + case PHY_MODE_NA : + emacdata->zmii_idx = *phy_dev; + emacdata->zmii_mux = *phy_port; + default : + printk(KERN_ERR + "emac%d: invalid EMAC phy-mode value %d!\n", + index, emacdata->phy_mode); + goto out1; + } + + data = ibm_emac_get_property(index, dev->node, "mal-device"); + if (!data) goto out1; + emacdata->mal_idx = *data; + + data = ibm_emac_get_property(index, dev->node, "mal-rx-channel"); + if (!data) goto out1; + emacdata->mal_rx_chan = *data; + + data = ibm_emac_get_property(index, dev->node, "mal-tx-channel"); + if (!data) goto out1; + emacdata->mal_tx_chan = *data; + + data = ibm_emac_get_property(index, dev->node, "local-mac-address"); + if (!data) goto out1; + memcpy(emacdata->mac_addr, (u8 *)data, sizeof emacdata->mac_addr); + + if (of_address_to_resource(dev->node, 0, &r)) { + of_node_put(dev->node); + printk(KERN_ERR + "emac%d: can't find EMAC register property!\n", + index); + goto out1; + } + + /* Allocate our net_device structure */ + ndev = alloc_etherdev(sizeof(struct ocp_enet_private)); + if (!ndev) { + printk(KERN_ERR + "emac%d: could not allocate ethernet device!\n", + index); + kfree(emacdata); + err = -ENOMEM; + goto out; + } + edev = ndev->priv; + edev->ndev = ndev; + edev->ldev = &dev->dev; + edev->def = (struct ocp_def *)(emacdata + 1); + edev->def->additions = emacdata; + edev->def->index = index++; + edev->def->paddr = r.start; + edev->def->irq = irq_of_parse_and_map(dev->node, 0); + SET_MODULE_OWNER(ndev); +#endif + /* Find MAL device we are connected to */ +#ifdef CONFIG_IBM_EMAC_OCP maldev = ocp_find_device(OCP_VENDOR_IBM, OCP_FUNC_MAL, emacdata->mal_idx); +#else + malnode = of_find_node_by_type(NULL, "mal"); + if (!malnode) { + printk(KERN_ERR "emac%d: mal%d hasn't been initialized yet!\n", + edev->def->index, emacdata->mal_idx); + goto out; + } + + maldev = (struct of_device *)malnode->data; +#endif if (!maldev) { printk(KERN_ERR "emac%d: unknown mal%d device!\n", - dev->def->index, emacdata->mal_idx); + edev->def->index, emacdata->mal_idx); err = -ENODEV; goto out; } - dev->mal = ocp_get_drvdata(maldev); - if (!dev->mal) { + edev->mal = bus_get_drvdata(maldev); + if (!edev->mal) { printk(KERN_ERR "emac%d: mal%d hasn't been initialized yet!\n", - dev->def->index, emacdata->mal_idx); + edev->def->index, emacdata->mal_idx); err = -ENODEV; goto out; } /* Register with MAL */ - dev->commac.ops = &emac_commac_ops; - dev->commac.dev = dev; - dev->commac.tx_chan_mask = MAL_CHAN_MASK(emacdata->mal_tx_chan); - dev->commac.rx_chan_mask = MAL_CHAN_MASK(emacdata->mal_rx_chan); - err = mal_register_commac(dev->mal, &dev->commac); + edev->commac.ops = &emac_commac_ops; + edev->commac.dev = edev; + edev->commac.tx_chan_mask = MAL_CHAN_MASK(emacdata->mal_tx_chan); + edev->commac.rx_chan_mask = MAL_CHAN_MASK(emacdata->mal_rx_chan); + err = mal_register_commac(edev->mal, &edev->commac); if (err) { printk(KERN_ERR "emac%d: failed to register with mal%d!\n", - dev->def->index, emacdata->mal_idx); + edev->def->index, emacdata->mal_idx); goto out; } - dev->rx_skb_size = emac_rx_skb_size(ndev->mtu); - dev->rx_sync_size = emac_rx_sync_size(ndev->mtu); + edev->rx_skb_size = emac_rx_skb_size(ndev->mtu); + edev->rx_sync_size = emac_rx_sync_size(ndev->mtu); /* Get pointers to BD rings */ - dev->tx_desc = - dev->mal->bd_virt + mal_tx_bd_offset(dev->mal, + edev->tx_desc = + edev->mal->bd_virt + mal_tx_bd_offset(edev->mal, emacdata->mal_tx_chan); - dev->rx_desc = - dev->mal->bd_virt + mal_rx_bd_offset(dev->mal, + edev->rx_desc = + edev->mal->bd_virt + mal_rx_bd_offset(edev->mal, emacdata->mal_rx_chan); - DBG("%d: tx_desc %p" NL, ocpdev->def->index, dev->tx_desc); - DBG("%d: rx_desc %p" NL, ocpdev->def->index, dev->rx_desc); + DBG("%d: tx_desc %p" NL, edev->def->index, edev->tx_desc); + DBG("%d: rx_desc %p" NL, edev->def->index, edev->rx_desc); /* Clean rings */ - memset(dev->tx_desc, 0, NUM_TX_BUFF * sizeof(struct mal_descriptor)); - memset(dev->rx_desc, 0, NUM_RX_BUFF * sizeof(struct mal_descriptor)); + memset(edev->tx_desc, 0, NUM_TX_BUFF * sizeof(struct mal_descriptor)); + memset(edev->rx_desc, 0, NUM_RX_BUFF * sizeof(struct mal_descriptor)); +#ifdef CONFIG_IBM_EMAC_OCP /* If we depend on another EMAC for MDIO, check whether it was probed already */ - if (emacdata->mdio_idx >= 0 && emacdata->mdio_idx != ocpdev->def->index) { + if (emacdata->mdio_idx >= 0 && emacdata->mdio_idx != edev->def->index) { struct ocp_device *mdiodev = ocp_find_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, emacdata->mdio_idx); if (!mdiodev) { printk(KERN_ERR "emac%d: unknown emac%d device!\n", - dev->def->index, emacdata->mdio_idx); + edev->def->index, emacdata->mdio_idx); err = -ENODEV; goto out2; } - dev->mdio_dev = ocp_get_drvdata(mdiodev); - if (!dev->mdio_dev) { + edev->mdio_dev = bus_get_drvdata(mdiodev); + if (!edev->mdio_dev) { printk(KERN_ERR "emac%d: emac%d hasn't been initialized yet!\n", - dev->def->index, emacdata->mdio_idx); + edev->def->index, emacdata->mdio_idx); err = -ENODEV; goto out2; } } - +#endif /* Attach to ZMII, if needed */ - if ((err = zmii_attach(dev)) != 0) + if ((err = zmii_attach(edev)) != 0) goto out2; /* Attach to RGMII, if needed */ - if ((err = rgmii_attach(dev)) != 0) + if ((err = rgmii_attach(edev)) != 0) goto out3; /* Attach to TAH, if needed */ - if ((err = tah_attach(dev)) != 0) + if ((err = tah_attach(edev)) != 0) goto out4; /* Map EMAC regs */ - dev->emacp = ioremap(dev->def->paddr, sizeof(struct emac_regs)); - if (!dev->emacp) { + edev->emacp = ioremap(edev->def->paddr, sizeof(struct emac_regs)); + if (!edev->emacp) { printk(KERN_ERR "emac%d: could not ioremap device registers!\n", - dev->def->index); + edev->def->index); err = -ENOMEM; goto out5; } @@ -2060,43 +2226,43 @@ static int __init emac_probe(struct ocp_ ndev->dev_addr[i] = emacdata->mac_addr[i]; /* Set some link defaults before we can find out real parameters */ - dev->phy.speed = SPEED_100; - dev->phy.duplex = DUPLEX_FULL; - dev->phy.autoneg = AUTONEG_DISABLE; - dev->phy.pause = dev->phy.asym_pause = 0; - dev->stop_timeout = STOP_TIMEOUT_100; - init_timer(&dev->link_timer); - dev->link_timer.function = emac_link_timer; - dev->link_timer.data = (unsigned long)dev; + edev->phy.speed = SPEED_100; + edev->phy.duplex = DUPLEX_FULL; + edev->phy.autoneg = AUTONEG_DISABLE; + edev->phy.pause = edev->phy.asym_pause = 0; + edev->stop_timeout = STOP_TIMEOUT_100; + init_timer(&edev->link_timer); + edev->link_timer.function = emac_link_timer; + edev->link_timer.data = (unsigned long)edev; /* Find PHY if any */ - dev->phy.dev = ndev; - dev->phy.mode = emacdata->phy_mode; + edev->phy.dev = ndev; + edev->phy.mode = emacdata->phy_mode; if (emacdata->phy_map != 0xffffffff) { u32 phy_map = emacdata->phy_map | busy_phy_map; u32 adv; - DBG("%d: PHY maps %08x %08x" NL, dev->def->index, + DBG("%d: PHY maps %08x %08x" NL, edev->def->index, emacdata->phy_map, busy_phy_map); - EMAC_RX_CLK_TX(dev->def->index); + EMAC_RX_CLK_TX(edev->def->index); - dev->phy.mdio_read = emac_mdio_read; - dev->phy.mdio_write = emac_mdio_write; + edev->phy.mdio_read = emac_mdio_read; + edev->phy.mdio_write = emac_mdio_write; /* Configure EMAC with defaults so we can at least use MDIO * This is needed mostly for 440GX */ - if (emac_phy_gpcs(dev->phy.mode)) { + if (emac_phy_gpcs(edev->phy.mode)) { /* XXX * Make GPCS PHY address equal to EMAC index. * We probably should take into account busy_phy_map * and/or phy_map here. */ - dev->phy.address = dev->def->index; + edev->phy.address = edev->def->index; } - emac_configure(dev); + emac_configure(edev); for (i = 0; i < 0x20; phy_map >>= 1, ++i) if (!(phy_map & 1)) { @@ -2104,35 +2270,35 @@ static int __init emac_probe(struct ocp_ busy_phy_map |= 1 << i; /* Quick check if there is a PHY at the address */ - r = emac_mdio_read(dev->ndev, i, MII_BMCR); + r = emac_mdio_read(edev->ndev, i, MII_BMCR); if (r == 0xffff || r < 0) continue; - if (!mii_phy_probe(&dev->phy, i)) + if (!mii_phy_probe(&edev->phy, i)) break; } if (i == 0x20) { printk(KERN_WARNING "emac%d: can't find PHY!\n", - dev->def->index); + edev->def->index); goto out6; } /* Init PHY */ - if (dev->phy.def->ops->init) - dev->phy.def->ops->init(&dev->phy); + if (edev->phy.def->ops->init) + edev->phy.def->ops->init(&edev->phy); /* Disable any PHY features not supported by the platform */ - dev->phy.def->features &= ~emacdata->phy_feat_exc; + edev->phy.def->features &= ~emacdata->phy_feat_exc; /* Setup initial link parameters */ - if (dev->phy.features & SUPPORTED_Autoneg) { - adv = dev->phy.features; + if (edev->phy.features & SUPPORTED_Autoneg) { + adv = edev->phy.features; #if !defined(CONFIG_40x) adv |= ADVERTISED_Pause | ADVERTISED_Asym_Pause; #endif /* Restart autonegotiation */ - dev->phy.def->ops->setup_aneg(&dev->phy, adv); + edev->phy.def->ops->setup_aneg(&edev->phy, adv); } else { - u32 f = dev->phy.def->features; + u32 f = edev->phy.def->features; int speed = SPEED_10, fd = DUPLEX_HALF; /* Select highest supported speed/duplex */ @@ -2150,22 +2316,22 @@ static int __init emac_probe(struct ocp_ fd = DUPLEX_FULL; /* Force link parameters */ - dev->phy.def->ops->setup_forced(&dev->phy, speed, fd); + edev->phy.def->ops->setup_forced(&edev->phy, speed, fd); } } else { - emac_reset(dev); + emac_reset(edev); /* PHY-less configuration. * XXX I probably should move these settings to emacdata */ - dev->phy.address = -1; - dev->phy.features = SUPPORTED_100baseT_Full | SUPPORTED_MII; - dev->phy.pause = 1; + edev->phy.address = -1; + edev->phy.features = SUPPORTED_100baseT_Full | SUPPORTED_MII; + edev->phy.pause = 1; } /* Fill in the driver function table */ ndev->open = &emac_open; - if (dev->tah_dev) { + if (edev->tah_dev) { ndev->hard_start_xmit = &emac_start_xmit_sg; ndev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; } else @@ -2178,7 +2344,7 @@ static int __init emac_probe(struct ocp_ ndev->do_ioctl = &emac_ioctl; if (emac_phy_supports_gige(emacdata->phy_mode)) { ndev->change_mtu = &emac_change_mtu; - dev->commac.ops = &emac_commac_sg_ops; + edev->commac.ops = &emac_commac_sg_ops; } SET_ETHTOOL_OPS(ndev, &emac_ethtool_ops); @@ -2188,39 +2354,44 @@ static int __init emac_probe(struct ocp_ err = register_netdev(ndev); if (err) { printk(KERN_ERR "emac%d: failed to register net device (%d)!\n", - dev->def->index, err); + edev->def->index, err); goto out6; } - ocp_set_drvdata(ocpdev, dev); + bus_set_drvdata(dev, edev); printk("%s: emac%d, MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - ndev->name, dev->def->index, + ndev->name, edev->def->index, ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2], ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]); - if (dev->phy.address >= 0) + if (edev->phy.address >= 0) printk("%s: found %s PHY (0x%02x)\n", ndev->name, - dev->phy.def->name, dev->phy.address); + edev->phy.def->name, edev->phy.address); - emac_dbg_register(dev->def->index, dev); + emac_dbg_register(edev->def->index, edev); return 0; out6: - iounmap(dev->emacp); + iounmap(edev->emacp); out5: - tah_fini(dev->tah_dev); + tah_fini(edev->tah_dev); out4: - rgmii_fini(dev->rgmii_dev, dev->rgmii_input); + rgmii_fini(edev->rgmii_dev, edev->rgmii_input); out3: - zmii_fini(dev->zmii_dev, dev->zmii_input); + zmii_fini(edev->zmii_dev, edev->zmii_input); out2: - mal_unregister_commac(dev->mal, &dev->commac); + mal_unregister_commac(edev->mal, &edev->commac); out: kfree(ndev); +#ifndef CONFIG_IBM_EMAC_OCP + out1: + kfree(emacdata); +#endif return err; } +#ifdef CONFIG_IBM_EMAC_OCP static struct ocp_device_id emac_ids[] = { { .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_EMAC }, { .vendor = OCP_VENDOR_INVALID} @@ -2232,6 +2403,24 @@ static struct ocp_driver emac_driver = { .probe = emac_probe, .remove = emac_remove, }; +#else +static struct of_device_id emac_platform_match[] = +{ + { + .name = "ethernet", + .type = "network", + }, + {}, +}; + +static struct of_platform_driver emac_driver = { + .name = "emac", + .match_table = emac_platform_match, + + .probe = emac_probe, + .remove = emac_remove, +}; +#endif static int __init emac_init(void) { @@ -2243,12 +2432,16 @@ static int __init emac_init(void) return -ENODEV; EMAC_CLK_INTERNAL; +#ifdef CONFIG_IBM_EMAC_OCP if (ocp_register_driver(&emac_driver)) { EMAC_CLK_EXTERNAL; ocp_unregister_driver(&emac_driver); mal_exit(); return -ENODEV; } +#else + of_register_driver(&emac_driver); +#endif EMAC_CLK_EXTERNAL; emac_init_debug(); @@ -2258,7 +2451,11 @@ static int __init emac_init(void) static void __exit emac_exit(void) { DBG(": exit" NL); +#ifdef CONFIG_IBM_EMAC_OCP ocp_unregister_driver(&emac_driver); +#else + of_unregister_driver(&emac_driver); +#endif mal_exit(); emac_fini_debug(); } Index: linux-2.6/drivers/net/ibm_emac/ibm_emac_rgmii.c =================================================================== --- linux-2.6.orig/drivers/net/ibm_emac/ibm_emac_rgmii.c +++ linux-2.6/drivers/net/ibm_emac/ibm_emac_rgmii.c @@ -20,10 +20,16 @@ #include #include +#include "ibm_emac_busdev.h" #include "ibm_emac_core.h" #include "ibm_emac_debug.h" -/* RGMIIx_FER */ +/* RGMIIx_FER XXXX */ +#if defined(CONFIG_PPC_CELL) +#define RGMII_FER_MDI(idx) (0x80000000 >> ((idx) + 12)) +#define RGMII_FER_MDI_ALL (RGMII_FER_MDI(0) | RGMII_FER_MDI(1) | \ + RGMII_FER_MDI(2) | RGMII_FER_MDI(3)) +#endif #define RGMII_FER_MASK(idx) (0x7 << ((idx) * 4)) #define RGMII_FER_RTBI(idx) (0x4 << ((idx) * 4)) #define RGMII_FER_RGMII(idx) (0x5 << ((idx) * 4)) @@ -58,6 +64,8 @@ static inline const char *rgmii_mode_nam default: BUG(); } + + return NULL; } static inline u32 rgmii_mode_mask(int mode, int input) @@ -74,49 +82,62 @@ static inline u32 rgmii_mode_mask(int mo default: BUG(); } + + return 0; } -static int __init rgmii_init(struct ocp_device *ocpdev, int input, int mode) +static int __init rgmii_init(struct bus_device *dev, int input, int mode) { - struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev); + struct ibm_ocp_rgmii *rdev = bus_get_drvdata(dev); struct rgmii_regs *p; + struct resource r; - RGMII_DBG("%d: init(%d, %d)" NL, ocpdev->def->index, input, mode); + RGMII_DBG(": init(%d, %d)" NL, input, mode); - if (!dev) { - dev = kzalloc(sizeof(struct ibm_ocp_rgmii), GFP_KERNEL); - if (!dev) { + if (!rdev) { + rdev = kzalloc(sizeof(struct ibm_ocp_rgmii), GFP_KERNEL); + if (!rdev) { printk(KERN_ERR - "rgmii%d: couldn't allocate device structure!\n", - ocpdev->def->index); + "rgmii: couldn't allocate device structure!\n"); return -ENOMEM; } - p = (struct rgmii_regs *)ioremap(ocpdev->def->paddr, +#ifdef CONFIG_IBM_EMAC_OCP + p = (struct rgmii_regs *)ioremap(dev->def->paddr, sizeof(struct rgmii_regs)); +#else + if (of_address_to_resource(dev->node, 0, &r)) { + of_node_put(dev->node); + printk(KERN_ERR + "rgmii: can't find RGMII register property!\n"); + kfree(rdev); + return -EINVAL; + } + p = (struct rgmii_regs *)ioremap(r.start, sizeof *p); +#endif if (!p) { printk(KERN_ERR - "rgmii%d: could not ioremap device registers!\n", - ocpdev->def->index); - kfree(dev); + "rgmii: could not ioremap device registers!\n"); + kfree(rdev); return -ENOMEM; } - dev->base = p; - ocp_set_drvdata(ocpdev, dev); + rdev->base = p; + + bus_set_drvdata(dev, rdev); /* Disable all inputs by default */ out_be32(&p->fer, 0); } else - p = dev->base; + p = rdev->base; /* Enable this input */ out_be32(&p->fer, in_be32(&p->fer) | rgmii_mode_mask(mode, input)); - printk(KERN_NOTICE "rgmii%d: input %d in %s mode\n", - ocpdev->def->index, input, rgmii_mode_name(mode)); + printk(KERN_NOTICE "rgmii: input %d in %s mode\n", + input, rgmii_mode_name(mode)); - ++dev->users; + ++rdev->users; return 0; } @@ -127,74 +148,102 @@ int __init rgmii_attach(void *emac) /* Check if we need to attach to a RGMII */ if (emacdata->rgmii_idx >= 0 && rgmii_valid_mode(emacdata->phy_mode)) { - dev->rgmii_input = emacdata->rgmii_mux; +#ifdef CONFIG_IBM_EMAC_OCP dev->rgmii_dev = ocp_find_device(OCP_VENDOR_IBM, OCP_FUNC_RGMII, emacdata->rgmii_idx); +#else + struct device_node * node = + of_find_node_by_phandle(emacdata->rgmii_idx); + if (!node) { + printk(KERN_ERR + "emac%d: rgmii%d can't find PHY device node!\n", + dev->def->index, emacdata->rgmii_idx); + return -ENODEV; + } + dev->rgmii_dev = (struct of_device *)node->data; +#endif + dev->rgmii_input = emacdata->rgmii_mux; + if (!dev->rgmii_dev) { printk(KERN_ERR "emac%d: unknown rgmii%d!\n", dev->def->index, emacdata->rgmii_idx); return -ENODEV; } + if (rgmii_init (dev->rgmii_dev, dev->rgmii_input, emacdata->phy_mode)) { printk(KERN_ERR - "emac%d: rgmii%d initialization failed!\n", - dev->def->index, emacdata->rgmii_idx); + "emac: rgmii%d initialization failed!\n", + emacdata->rgmii_idx); return -ENODEV; } } return 0; } -void rgmii_set_speed(struct ocp_device *ocpdev, int input, int speed) +void rgmii_enable_mdio(struct bus_device *dev, int input) +{ + struct ibm_ocp_rgmii *rdev = bus_get_drvdata(dev); + u32 fer = in_be32(&rdev->base->fer) & ~RGMII_FER_MDI_ALL; + + RGMII_DBG2(": mdio(%d)" NL, input); + + out_be32(&rdev->base->fer, fer | RGMII_FER_MDI(input)); +} + +void rgmii_set_speed(struct bus_device *dev, int input, int speed) { - struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev); - u32 ssr = in_be32(&dev->base->ssr) & ~RGMII_SSR_MASK(input); + struct ibm_ocp_rgmii *rdev = bus_get_drvdata(dev); + u32 ssr = in_be32(&rdev->base->ssr) & ~RGMII_SSR_MASK(input); - RGMII_DBG("%d: speed(%d, %d)" NL, ocpdev->def->index, input, speed); + RGMII_DBG(": speed(%d, %d)" NL, input, speed); if (speed == SPEED_1000) ssr |= RGMII_SSR_1000(input); else if (speed == SPEED_100) ssr |= RGMII_SSR_100(input); - out_be32(&dev->base->ssr, ssr); + out_be32(&rdev->base->ssr, ssr); } -void __exit __rgmii_fini(struct ocp_device *ocpdev, int input) +void __exit __rgmii_fini(struct bus_device *dev, int input) { - struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev); - BUG_ON(!dev || dev->users == 0); + struct ibm_ocp_rgmii *rdev = bus_get_drvdata(dev); + BUG_ON(!rdev || rdev->users == 0); - RGMII_DBG("%d: fini(%d)" NL, ocpdev->def->index, input); + RGMII_DBG(": fini(%d)" NL, input); /* Disable this input */ - out_be32(&dev->base->fer, - in_be32(&dev->base->fer) & ~RGMII_FER_MASK(input)); + out_be32(&rdev->base->fer, + in_be32(&rdev->base->fer) & ~RGMII_FER_MASK(input)); - if (!--dev->users) { + if (!--rdev->users) { /* Free everything if this is the last user */ - ocp_set_drvdata(ocpdev, NULL); - iounmap((void *)dev->base); - kfree(dev); + bus_set_drvdata(dev, NULL); + iounmap((void *)rdev->base); + kfree(rdev); } } -int __rgmii_get_regs_len(struct ocp_device *ocpdev) +int __rgmii_get_regs_len(struct bus_device *dev) { return sizeof(struct emac_ethtool_regs_subhdr) + sizeof(struct rgmii_regs); } -void *rgmii_dump_regs(struct ocp_device *ocpdev, void *buf) +void *rgmii_dump_regs(struct bus_device *dev, void *buf) { - struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev); + struct ibm_ocp_rgmii *rdev = bus_get_drvdata(dev); struct emac_ethtool_regs_subhdr *hdr = buf; struct rgmii_regs *regs = (struct rgmii_regs *)(hdr + 1); hdr->version = 0; - hdr->index = ocpdev->def->index; - memcpy_fromio(regs, dev->base, sizeof(struct rgmii_regs)); +#ifdef CONFIG_IBM_EMAC_OCP + hdr->index = pdev->def->index; +#else + hdr->index = 0; +#endif + memcpy_fromio(regs, rdev->base, sizeof(struct rgmii_regs)); return regs + 1; } Index: linux-2.6/drivers/net/ibm_emac/ibm_emac_rgmii.h =================================================================== --- linux-2.6.orig/drivers/net/ibm_emac/ibm_emac_rgmii.h +++ linux-2.6/drivers/net/ibm_emac/ibm_emac_rgmii.h @@ -21,6 +21,7 @@ #ifndef _IBM_EMAC_RGMII_H_ #define _IBM_EMAC_RGMII_H_ +#include "ibm_emac_busdev.h" /* RGMII bridge */ struct rgmii_regs { @@ -37,22 +38,23 @@ struct ibm_ocp_rgmii { #ifdef CONFIG_IBM_EMAC_RGMII int rgmii_attach(void *emac) __init; -void __rgmii_fini(struct ocp_device *ocpdev, int input) __exit; -static inline void rgmii_fini(struct ocp_device *ocpdev, int input) +void __rgmii_fini(struct bus_device *dev, int input) __exit; +static inline void rgmii_fini(struct bus_device *dev, int input) { - if (ocpdev) - __rgmii_fini(ocpdev, input); + if (dev) + __rgmii_fini(dev, input); } -void rgmii_set_speed(struct ocp_device *ocpdev, int input, int speed); - -int __rgmii_get_regs_len(struct ocp_device *ocpdev); -static inline int rgmii_get_regs_len(struct ocp_device *ocpdev) +int __rgmii_get_regs_len(struct bus_device *dev); +static inline int rgmii_get_regs_len(struct bus_device *dev) { - return ocpdev ? __rgmii_get_regs_len(ocpdev) : 0; + return dev ? __rgmii_get_regs_len(dev) : 0; } -void *rgmii_dump_regs(struct ocp_device *ocpdev, void *buf); +void rgmii_set_speed(struct bus_device *dev, int input, int speed); +void rgmii_enable_mdio(struct bus_device *dev, int input); +void *rgmii_dump_regs(struct bus_device *dev, void *buf); + #else # define rgmii_attach(x) 0 # define rgmii_fini(x,y) ((void)0) Index: linux-2.6/drivers/net/ibm_emac/ibm_emac_zmii.c =================================================================== --- linux-2.6.orig/drivers/net/ibm_emac/ibm_emac_zmii.c +++ linux-2.6/drivers/net/ibm_emac/ibm_emac_zmii.c @@ -60,6 +60,8 @@ static inline const char *zmii_mode_name default: BUG(); } + + return NULL; } static inline u32 zmii_mode_mask(int mode, int input) @@ -76,41 +78,53 @@ static inline u32 zmii_mode_mask(int mod } } -static int __init zmii_init(struct ocp_device *ocpdev, int input, int *mode) +static int __init zmii_init(struct bus_device *dev, int input, int *mode) { - struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev); + struct ibm_ocp_zmii *zdev = bus_get_drvdata(dev); struct zmii_regs __iomem *p; + unsigned long *reg; - ZMII_DBG("%d: init(%d, %d)" NL, ocpdev->def->index, input, *mode); + ZMII_DBG(": init(%d, %d)" NL, input, *mode); - if (!dev) { - dev = kzalloc(sizeof(struct ibm_ocp_zmii), GFP_KERNEL); - if (!dev) { + if (!zdev) { + zdev = kzalloc(sizeof(struct ibm_ocp_zmii), GFP_KERNEL); + if (!zdev) { printk(KERN_ERR - "zmii%d: couldn't allocate device structure!\n", - ocpdev->def->index); + "zmii: couldn't allocate device structure!\n"); return -ENOMEM; } - dev->mode = PHY_MODE_NA; + zdev->mode = PHY_MODE_NA; +#ifdef CONFIG_IBM_EMAC_OCP p = ioremap(ocpdev->def->paddr, sizeof(struct zmii_regs)); +#else + reg = (unsigned long *)get_property(dev->node, "reg", NULL); + if (reg == NULL) { + of_node_put(dev->node); + printk(KERN_ERR + "rgmii: can't find ZMII register property!\n"); + kfree(zdev); + return -EINVAL; + } + + p = (struct zmii_regs *)ioremap(reg[0], reg[1]); +#endif if (!p) { printk(KERN_ERR - "zmii%d: could not ioremap device registers!\n", - ocpdev->def->index); - kfree(dev); + "zmii: could not ioremap device registers!\n"); + kfree(zdev); return -ENOMEM; } - dev->base = p; - ocp_set_drvdata(ocpdev, dev); + zdev->base = p; + bus_set_drvdata(dev, dev); /* We may need FER value for autodetection later */ - dev->fer_save = in_be32(&p->fer); + zdev->fer_save = in_be32(&p->fer); /* Disable all inputs by default */ out_be32(&p->fer, 0); } else - p = dev->base; + p = zdev->base; if (!zmii_valid_mode(*mode)) { /* Probably an EMAC connected to RGMII, @@ -124,30 +138,29 @@ static int __init zmii_init(struct ocp_d * Please, always specify PHY mode in your board port to avoid * any surprises. */ - if (dev->mode == PHY_MODE_NA) { + if (zdev->mode == PHY_MODE_NA) { if (*mode == PHY_MODE_NA) { - u32 r = dev->fer_save; + u32 r = zdev->fer_save; - ZMII_DBG("%d: autodetecting mode, FER = 0x%08x" NL, - ocpdev->def->index, r); + ZMII_DBG(": autodetecting mode, FER = 0x%08x" NL, r); if (r & (ZMII_FER_MII(0) | ZMII_FER_MII(1))) - dev->mode = PHY_MODE_MII; + zdev->mode = PHY_MODE_MII; else if (r & (ZMII_FER_RMII(0) | ZMII_FER_RMII(1))) - dev->mode = PHY_MODE_RMII; + zdev->mode = PHY_MODE_RMII; else - dev->mode = PHY_MODE_SMII; + zdev->mode = PHY_MODE_SMII; } else - dev->mode = *mode; + zdev->mode = *mode; - printk(KERN_NOTICE "zmii%d: bridge in %s mode\n", - ocpdev->def->index, zmii_mode_name(dev->mode)); + printk(KERN_NOTICE "zmii: bridge in %s mode\n", + zmii_mode_name(zdev->mode)); } else { /* All inputs must use the same mode */ - if (*mode != PHY_MODE_NA && *mode != dev->mode) { + if (*mode != PHY_MODE_NA && *mode != zdev->mode) { printk(KERN_ERR - "zmii%d: invalid mode %d specified for input %d\n", - ocpdev->def->index, *mode, input); + "zmii: invalid mode %d specified for input %d\n", + *mode, input); return -EINVAL; } } @@ -155,12 +168,12 @@ static int __init zmii_init(struct ocp_d /* Report back correct PHY mode, * it may be used during PHY initialization. */ - *mode = dev->mode; + *mode = zdev->mode; /* Enable this input */ - out_be32(&p->fer, in_be32(&p->fer) | zmii_mode_mask(dev->mode, input)); + out_be32(&p->fer, in_be32(&p->fer) | zmii_mode_mask(zdev->mode, input)); out: - ++dev->users; + ++zdev->users; return 0; } @@ -170,10 +183,24 @@ int __init zmii_attach(void *emac) struct ocp_func_emac_data *emacdata = dev->def->additions; if (emacdata->zmii_idx >= 0) { - dev->zmii_input = emacdata->zmii_mux; +#ifdef CONFIG_IBM_EMAC_OCP dev->zmii_dev = ocp_find_device(OCP_VENDOR_IBM, OCP_FUNC_ZMII, emacdata->zmii_idx); +#else + struct device_node * node = + of_find_node_by_phandle(emacdata->zmii_idx); + if (!node || strcmp(node->type, "zmii")) { + printk(KERN_ERR + "emac: zmii%d can't find PHY device node!\n", + emacdata->zmii_idx); + return -ENODEV; + } + + dev->zmii_dev = (struct of_device *)node->data; +#endif + dev->zmii_input = emacdata->zmii_mux; + if (!dev->zmii_dev) { printk(KERN_ERR "emac%d: unknown zmii%d!\n", dev->def->index, emacdata->zmii_idx); @@ -190,64 +217,68 @@ int __init zmii_attach(void *emac) return 0; } -void __zmii_enable_mdio(struct ocp_device *ocpdev, int input) +void __zmii_enable_mdio(struct bus_device *dev, int input) { - struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev); - u32 fer = in_be32(&dev->base->fer) & ~ZMII_FER_MDI_ALL; + struct ibm_ocp_zmii *zdev = bus_get_drvdata(dev); + u32 fer = in_be32(&zdev->base->fer) & ~ZMII_FER_MDI_ALL; - ZMII_DBG2("%d: mdio(%d)" NL, ocpdev->def->index, input); + ZMII_DBG2(": mdio(%d)" NL, input); - out_be32(&dev->base->fer, fer | ZMII_FER_MDI(input)); + out_be32(&zdev->base->fer, fer | ZMII_FER_MDI(input)); } -void __zmii_set_speed(struct ocp_device *ocpdev, int input, int speed) +void __zmii_set_speed(struct bus_device *dev, int input, int speed) { - struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev); - u32 ssr = in_be32(&dev->base->ssr); + struct ibm_ocp_zmii *zdev = bus_get_drvdata(dev); + u32 ssr = in_be32(&zdev->base->ssr); - ZMII_DBG("%d: speed(%d, %d)" NL, ocpdev->def->index, input, speed); + ZMII_DBG(": speed(%d, %d)" NL, input, speed); if (speed == SPEED_100) ssr |= ZMII_SSR_SP(input); else ssr &= ~ZMII_SSR_SP(input); - out_be32(&dev->base->ssr, ssr); + out_be32(&zdev->base->ssr, ssr); } -void __exit __zmii_fini(struct ocp_device *ocpdev, int input) +void __exit __zmii_fini(struct bus_device *dev, int input) { - struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev); - BUG_ON(!dev || dev->users == 0); + struct ibm_ocp_zmii *zdev = bus_get_drvdata(dev); + BUG_ON(!zdev || zdev->users == 0); - ZMII_DBG("%d: fini(%d)" NL, ocpdev->def->index, input); + ZMII_DBG(": fini(%d)" NL, input); /* Disable this input */ - out_be32(&dev->base->fer, - in_be32(&dev->base->fer) & ~zmii_mode_mask(dev->mode, input)); + out_be32(&zdev->base->fer, + in_be32(&zdev->base->fer) & ~zmii_mode_mask(zdev->mode, input)); - if (!--dev->users) { + if (!--zdev->users) { /* Free everything if this is the last user */ - ocp_set_drvdata(ocpdev, NULL); - iounmap(dev->base); - kfree(dev); + bus_set_drvdata(dev, NULL); + iounmap(zdev->base); + kfree(zdev); } } -int __zmii_get_regs_len(struct ocp_device *ocpdev) +int __zmii_get_regs_len(struct bus_device *dev) { return sizeof(struct emac_ethtool_regs_subhdr) + sizeof(struct zmii_regs); } -void *zmii_dump_regs(struct ocp_device *ocpdev, void *buf) +void *zmii_dump_regs(struct bus_device *dev, void *buf) { - struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev); + struct ibm_ocp_zmii *zdev = bus_get_drvdata(dev); struct emac_ethtool_regs_subhdr *hdr = buf; struct zmii_regs *regs = (struct zmii_regs *)(hdr + 1); hdr->version = 0; - hdr->index = ocpdev->def->index; - memcpy_fromio(regs, dev->base, sizeof(struct zmii_regs)); +#ifdef CONFIG_IBM_EMAC_OCP + hdr->index = dev->def->index; +#else + hdr->index = 0; +#endif + memcpy_fromio(regs, zdev->base, sizeof(struct zmii_regs)); return regs + 1; } Index: linux-2.6/drivers/net/ibm_emac/ibm_emac_phy.c =================================================================== --- linux-2.6.orig/drivers/net/ibm_emac/ibm_emac_phy.c +++ linux-2.6/drivers/net/ibm_emac/ibm_emac_phy.c @@ -20,7 +20,11 @@ #include #include +#ifdef CONFIG_IBM_EMAC_OCP #include +#else +#include "ibm_emac_compat.h" +#endif #include "ibm_emac_phy.h" Index: linux-2.6/drivers/net/ibm_emac/ibm_emac_compat.h =================================================================== --- /dev/null +++ linux-2.6/drivers/net/ibm_emac/ibm_emac_compat.h @@ -0,0 +1,73 @@ +#ifndef __IBM_EMAC_COMPAT_H_ +#define __IBM_EMAC_COMPAT_H_ + +#include +#include + +/* + * Definitions in this file are used for compatability when compiling + * the driver without the OCP bus type. Once arch/ppc merges with + * arch/powerpc, the OCP residue could be removed. -swetz + */ + +/* + * OCP device definition. + * + * Minimal definition needed to compile without ocp.h + * + */ +struct ocp_def { + int index; + phys_addr_t paddr; + int irq; + void *additions; +}; + +/* + * Additional MAL platform data obtained from the device-tree. + */ +struct ocp_func_mal_data { + int num_tx_chans; /* Number of TX channels */ + int num_rx_chans; /* Number of RX channels */ + int txeob_irq; /* TX End Of Buffer IRQ */ + int rxeob_irq; /* RX End Of Buffer IRQ */ + int txde_irq; /* TX Descriptor Error IRQ */ + int rxde_irq; /* RX Descriptor Error IRQ */ + int serr_irq; /* MAL System Error IRQ */ + int dcr_base; /* MALx_CFG DCR number */ +}; + +/* + * Additional EMAC platform data obtained from the device-tree. + */ +struct ocp_func_emac_data { + int rgmii_idx; /* RGMII device index or -1 */ + int rgmii_mux; /* RGMII input of this EMAC */ + int zmii_idx; /* ZMII device index or -1 */ + int zmii_mux; /* ZMII input of this EMAC */ + int mal_idx; /* MAL device index */ + int mal_rx_chan; /* MAL rx channel number */ + int mal_tx_chan; /* MAL tx channel number */ + int wol_irq; /* WOL interrupt */ + int mdio_idx; /* EMAC idx of MDIO master or -1 */ + int tah_idx; /* TAH device index or -1 */ + int phy_mode; /* PHY type or configurable mode */ + u8 mac_addr[6]; /* EMAC mac address */ + u32 phy_map; /* EMAC phy map */ + u32 phy_feat_exc; /* Excluded PHY features */ +}; + +/* + * PHY mode settings (EMAC <-> ZMII/RGMII bridge <-> PHY) + */ +#define PHY_MODE_NA 0 +#define PHY_MODE_MII 1 +#define PHY_MODE_RMII 2 +#define PHY_MODE_SMII 3 +#define PHY_MODE_RGMII 4 +#define PHY_MODE_TBI 5 +#define PHY_MODE_GMII 6 +#define PHY_MODE_RTBI 7 +#define PHY_MODE_SGMII 8 + +#endif /* __IBM_EMAC_COMPAT_H_ */ Index: linux-2.6/drivers/net/ibm_emac/ibm_emac_busdev.h =================================================================== --- /dev/null +++ linux-2.6/drivers/net/ibm_emac/ibm_emac_busdev.h @@ -0,0 +1,38 @@ +#ifndef __IBM_EMAC_BUSDEV_H_ +#define __IBM_EMAC_BUSDEV_H_ + +#include +#include + +#ifdef CONFIG_IBM_EMAC_OCP +#include + +#define bus_device ocp_device + +static inline void * bus_get_drvdata (struct bus_device *dev) +{ + return ocp_get_drvdata(dev); +} + +static inline void bus_set_drvdata (struct bus_device *dev, void *data) +{ + ocp_set_drvdata(dev, data); +} +#else +#include + +#define bus_device of_device + +static inline void * bus_get_drvdata (struct bus_device *dev) +{ + return dev_get_drvdata(&dev->dev); +} + +static inline void bus_set_drvdata (struct bus_device *dev, void *data) +{ + dev_set_drvdata(&dev->dev, data); +} +#endif + +#endif /* __IBM_EMAC_BUSDEV_H_ */ + Index: linux-2.6/arch/powerpc/Kconfig =================================================================== --- linux-2.6.orig/arch/powerpc/Kconfig +++ linux-2.6/arch/powerpc/Kconfig @@ -450,6 +450,7 @@ config PPC_CELL_NATIVE select PPC_DCR select MPIC select MPIC_WEIRD + select IBM_EMAC4 default n config PPC_IBM_CELL_BLADE Index: linux-2.6/arch/powerpc/configs/cell_defconfig =================================================================== --- linux-2.6.orig/arch/powerpc/configs/cell_defconfig +++ linux-2.6/arch/powerpc/configs/cell_defconfig @@ -153,6 +153,7 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y # CONFIG_CPU_FREQ_PMAC64 is not set # CONFIG_WANT_EARLY_SERIAL is not set +CONFIG_IBM_EMAC4=y CONFIG_MPIC=y # @@ -552,6 +553,15 @@ CONFIG_MII=y # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set CONFIG_SYSTEMSIM_NET=y +CONFIG_IBM_EMAC=y +CONFIG_IBM_EMAC_RXB=128 +CONFIG_IBM_EMAC_TXB=64 +CONFIG_IBM_EMAC_POLL_WEIGHT=32 +CONFIG_IBM_EMAC_RX_COPY_THRESHOLD=256 +CONFIG_IBM_EMAC_RX_SKB_HEADROOM=0 +# CONFIG_IBM_EMAC_DEBUG is not set +CONFIG_IBM_EMAC_ZMII=y +CONFIG_IBM_EMAC_RGMII=y # CONFIG_NET_PCI is not set #