* [PATCH 1/6] ppc32: Remove unnecessary test in MPC52xx reset code
From: Sylvain Munaut @ 2005-03-26 23:45 UTC (permalink / raw)
To: Andrew Morton; +Cc: Sylvain Munaut, ML linuxppc-embedded
In-Reply-To: <0.20050327_004704.tnt@patchsend.246tNt.com>
ppc32: Remove unnecessary test in MPC52xx reset code
That test is part of an old version of the code and
erroneously made it to mainstream.
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Signed-off-by: Kumar Gala <kumar.gala@freescale.com>
---
diff -Nru a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c
--- a/arch/ppc/syslib/mpc52xx_setup.c 2005-03-26 19:55:53 +01:00
+++ b/arch/ppc/syslib/mpc52xx_setup.c 2005-03-26 19:55:53 +01:00
@@ -46,11 +46,8 @@
/* Turn on the watchdog and wait for it to expire. It effectively
does a reset */
- if (gpt0 != NULL) {
- out_be32(&gpt0->count, 0x000000ff);
- out_be32(&gpt0->mode, 0x00009004);
- } else
- printk(KERN_ERR "mpc52xx_restart: Unable to ioremap GPT0 registers, -> looping ...");
+ out_be32(&gpt0->count, 0x000000ff);
+ out_be32(&gpt0->mode, 0x00009004);
while (1);
}
^ permalink raw reply
* [PATCH 0/6] Change MPC52xx to platform bus / ppc_sys model
From: Sylvain Munaut @ 2005-03-26 23:44 UTC (permalink / raw)
To: Andrew Morton; +Cc: Sylvain Munaut, ML linuxppc-embedded
Hi Andrew,
This series of patch changes all the MPC52xx related code
to use platform bus and ppc_sys instead of OCP. It's
divided in several patches that represents "steps" in
the conversion. However the intermediate states might
not be functionnal.
Theses are against a bk clone of this morning since they
depend on some patches that are on bk but not yet in
2.6.12-rc1. I just tested and they also apply/run fine
with -mm3.
Regards,
Sylvain
^ permalink raw reply
* Re: 2.6.11-5 kernel on 8xx -- perhaps i messed up the console port?
From: Robert P. J. Day @ 2005-03-26 17:32 UTC (permalink / raw)
To: Embedded PPC Linux list
In-Reply-To: <Pine.LNX.4.61.0503260953100.12378@localhost.localdomain>
Solved.
On Sat, 26 Mar 2005, Robert P. J. Day wrote:
... snip ...
> has anything changed in the last little while in terms of the
> console port? i tried to reproduce faithfully my earlier config
> options for console port support, but no luck.
rather than "console=ttyS0" as i used to use, it's now
"console=ttyCPM0". and we're off ...
rday
^ permalink raw reply
* 2.6.11-5 kernel on 8xx -- perhaps i messed up the console port?
From: Robert P. J. Day @ 2005-03-26 14:54 UTC (permalink / raw)
To: Embedded PPC Linux list
to make a long story a little shorter, once upon a time, i had a
2.5.xx kernel running on my 8xx-based board. i used the latest bk
checkout from bkbits.net and had at least a minimal operational kernel
that would boot, mount its root filesystem, mount JFFS2 and a bit
more.
finally getting back to that, i grabbed the latest stock (2.6.11-5)
kernel and tried to reproduce that. by hand, i perused my old config
file, duplicated what i could, made (relatively?) intelligent
decisions about new options and tried again. to keep things simple, i
left out absolutely *everything* that wasn't essential for just an
initial boot -- no networking, no MTD, not even an initrd -- i just
wanted to see the kernel boot and would be quite happy for it to get
to trying to mount the root filesystem, only to choke and fall over.
no problem.
however, after (all based on ELDK 3.1 cross-compilation):
$ make ARCH=ppc menuconfig
$ make ARCH=ppc
$ ppc_8xx-objcopy -O binary zImage.elf zImage.bin
download (via planet core boot loader) to 400000 in RAM, and "g
400000", i get:
loaded at: 00400000 00485160
board data at: 00483124 00483140
relocated to: 00405090 004050AC
zimage at: 004058C8 0048275F
avail ram: 00486000 02000000
Linux/PPC load: rw root=/dev/ram0
Uncompressing Linux...done.
Now booting the kernel
... hangs ...
of course, there are an infinite number of ways i could have screwed
up, but one possibility is that i just messed up configuring the
console port. the kernel could very well be loading but, as this is a
bare board with no blinkenlights or anything, there's no way to tell.
has anything changed in the last little while in terms of the
console port? i tried to reproduce faithfully my earlier config
options for console port support, but no luck.
thoughts? the problem could, of course, be elsewhere but i'd like
to check this out first.
rday
^ permalink raw reply
* Re: MPC885 CryptoApi support.
From: Marcelo Tosatti @ 2005-03-24 11:39 UTC (permalink / raw)
To: Bruce Donadt; +Cc: linuxppc-embedded
In-Reply-To: <NEBBIHDFOLIPIPJAKJAMCEDLGEAA.bdonadt@arabellasw.com>
On Mon, Mar 21, 2005 at 03:54:39PM -0500, Bruce Donadt wrote:
> Guillaume:
>
> Arabella Software provides asynchronous 2.6 kernel CryptoApi support for the
> MPC885 as well as the PowerQUICC II devices as part of our commercially
> supported Linux distribution. If you would be interested in a commercial
> open source offering, please feel free to contact me and I can provide
> further detail.
These drivers are not GPL, then?
^ permalink raw reply
* Re: RFC: PHY Abstraction Layer II
From: Andy Fleming @ 2005-03-25 22:56 UTC (permalink / raw)
To: Andy Fleming; +Cc: netdev, linuxppc-embedded, David S. Miller
In-Reply-To: <96c50184a02557c88dee0e6d17f3a539@freescale.com>
[-- Attachment #1: Type: text/plain, Size: 93 bytes --]
And here's the patch which converts the gianfar driver to using the PHY
Abstraction Layer:
[-- Attachment #2: gfar_03252005.patch --]
[-- Type: application/octet-stream, Size: 63119 bytes --]
diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig
--- a/drivers/net/Kconfig 2005-03-25 14:47:22 -06:00
+++ b/drivers/net/Kconfig 2005-03-25 14:47:22 -06:00
@@ -153,6 +153,8 @@
source "drivers/net/arcnet/Kconfig"
endif
+source "drivers/net/phy/Kconfig"
+
#
# Ethernet
#
@@ -2056,6 +2058,8 @@
config GIANFAR
tristate "Gianfar Ethernet"
depends on 85xx || 83xx
+ select PHYLIB
+ select PHYCONTROL
help
This driver supports the Gigabit TSEC on the MPC85xx
family of chips, and the FEC on the 8540
diff -Nru a/drivers/net/Makefile b/drivers/net/Makefile
--- a/drivers/net/Makefile 2005-03-25 14:47:21 -06:00
+++ b/drivers/net/Makefile 2005-03-25 14:47:21 -06:00
@@ -12,7 +12,7 @@
obj-$(CONFIG_BONDING) += bonding/
obj-$(CONFIG_GIANFAR) += gianfar_driver.o
-gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_phy.o
+gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_mii.o
#
# link order important here
@@ -63,6 +63,7 @@
#
obj-$(CONFIG_MII) += mii.o
+obj-$(CONFIG_PHYLIB) += phy/
obj-$(CONFIG_SUNDANCE) += sundance.o
obj-$(CONFIG_HAMACHI) += hamachi.o
diff -Nru a/drivers/net/gianfar.c b/drivers/net/gianfar.c
--- a/drivers/net/gianfar.c 2005-03-25 14:47:21 -06:00
+++ b/drivers/net/gianfar.c 2005-03-25 14:47:21 -06:00
@@ -1,4 +1,4 @@
-/*
+/*
* drivers/net/gianfar.c
*
* Gianfar Ethernet Driver
@@ -24,35 +24,30 @@
* Theory of operation
* This driver is designed for the Triple-speed Ethernet
* controllers on the Freescale 8540/8560 integrated processors,
- * as well as the Fast Ethernet Controller on the 8540.
- *
- * The driver is initialized through platform_device. Structures which
- * define the configuration needed by the board are defined in a
- * board structure in arch/ppc/platforms (though I do not
+ * as well as the Fast Ethernet Controller on the 8540.
+ *
+ * The driver is initialized through platform_device. Structures
+ * which define the configuration needed by the board are defined
+ * in a board structure in arch/ppc/platforms (though I do not
* discount the possibility that other architectures could one
- * day be supported. One assumption the driver currently makes
- * is that the PHY is configured in such a way to advertise all
- * capabilities. This is a sensible default, and on certain
- * PHYs, changing this default encounters substantial errata
- * issues. Future versions may remove this requirement, but for
- * now, it is best for the firmware to ensure this is the case.
+ * day be supported.
*
* The Gianfar Ethernet Controller uses a ring of buffer
* descriptors. The beginning is indicated by a register
- * pointing to the physical address of the start of the ring.
- * The end is determined by a "wrap" bit being set in the
+ * pointing to the physical address of the start of the ring.
+ * The end is determined by a "wrap" bit being set in the
* last descriptor of the ring.
*
* When a packet is received, the RXF bit in the
- * IEVENT register is set, triggering an interrupt when the
+ * IEVENT register is set, triggering an interrupt when the
* corresponding bit in the IMASK register is also set (if
* interrupt coalescing is active, then the interrupt may not
* happen immediately, but will wait until either a set number
- * of frames or amount of time have passed.). In NAPI, the
+ * of frames or amount of time have passed). In NAPI, the
* interrupt handler will signal there is work to be done, and
* exit. Without NAPI, the packet(s) will be handled
* immediately. Both methods will start at the last known empty
- * descriptor, and process every subsequent descriptor until there
+ * descriptor, and process every subsequent descriptor until there
* are none left with data (NAPI will stop after a set number of
* packets to give time to other tasks, but will eventually
* process all the packets). The data arrives inside a
@@ -76,6 +71,7 @@
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/errno.h>
+#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -94,9 +90,11 @@
#include <linux/version.h>
#include <linux/dma-mapping.h>
#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
#include "gianfar.h"
-#include "gianfar_phy.h"
+#include "gianfar_mii.h"
#define TX_TIMEOUT (1*HZ)
#define SKB_ALLOC_TIMEOUT 1000000
@@ -110,9 +108,8 @@
#endif
const char gfar_driver_name[] = "Gianfar Ethernet";
-const char gfar_driver_version[] = "1.1";
+const char gfar_driver_version[] = "1.2";
-int startup_gfar(struct net_device *dev);
static int gfar_enet_open(struct net_device *dev);
static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void gfar_timeout(struct net_device *dev);
@@ -123,17 +120,13 @@
static int gfar_change_mtu(struct net_device *dev, int new_mtu);
static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs);
static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs);
-irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void gfar_phy_change(void *data);
-static void gfar_phy_timer(unsigned long data);
static void adjust_link(struct net_device *dev);
static void init_registers(struct net_device *dev);
static int init_phy(struct net_device *dev);
static int gfar_probe(struct device *device);
static int gfar_remove(struct device *device);
-void free_skb_resources(struct gfar_private *priv);
+static void free_skb_resources(struct gfar_private *priv);
static void gfar_set_multi(struct net_device *dev);
static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
#ifdef CONFIG_GFAR_NAPI
@@ -141,14 +134,13 @@
#endif
static int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
-static void gfar_phy_startup_timer(unsigned long data);
-
-extern struct ethtool_ops gfar_ethtool_ops;
MODULE_AUTHOR("Freescale Semiconductor, Inc");
MODULE_DESCRIPTION("Gianfar Ethernet Driver");
MODULE_LICENSE("GPL");
+/* Set up the ethernet device structure, private data,
+ * and anything else we need before we start */
static int gfar_probe(struct device *device)
{
u32 tempval;
@@ -173,7 +165,7 @@
/* Create an ethernet device instance */
dev = alloc_etherdev(sizeof (*priv));
- if (dev == NULL)
+ if (NULL == dev)
return -ENOMEM;
priv = netdev_priv(dev);
@@ -200,15 +192,6 @@
goto regs_fail;
}
- /* Set the PHY base address */
- priv->phyregs = (struct gfar *)
- ioremap(einfo->phy_reg_addr, sizeof (struct gfar));
-
- if (priv->phyregs == NULL) {
- err = -ENOMEM;
- goto phy_regs_fail;
- }
-
spin_lock_init(&priv->lock);
dev_set_drvdata(device, dev);
@@ -317,14 +300,13 @@
return 0;
register_fail:
- iounmap((void *) priv->phyregs);
-phy_regs_fail:
iounmap((void *) priv->regs);
regs_fail:
free_netdev(dev);
- return -ENOMEM;
+ return err;
}
+
static int gfar_remove(struct device *device)
{
struct net_device *dev = dev_get_drvdata(device);
@@ -333,108 +315,45 @@
dev_set_drvdata(device, NULL);
iounmap((void *) priv->regs);
- iounmap((void *) priv->phyregs);
free_netdev(dev);
return 0;
}
-/* Configure the PHY for dev.
- * returns 0 if success. -1 if failure
+/* Initializes driver's PHY state, and attaches to the PHY.
+ * Returns 0 on success, errno on failure to attach.
*/
static int init_phy(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
- struct phy_info *curphy;
- unsigned int timeout = PHY_INIT_TIMEOUT;
- struct gfar *phyregs = priv->phyregs;
- struct gfar_mii_info *mii_info;
- int err;
+ uint gigabit_support =
+ priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
+ SUPPORTED_1000baseT_Full : 0;
+ struct phy_device *phydev;
priv->oldlink = 0;
priv->oldspeed = 0;
priv->oldduplex = -1;
- mii_info = kmalloc(sizeof(struct gfar_mii_info),
- GFP_KERNEL);
-
- if(NULL == mii_info) {
- printk(KERN_ERR "%s: Could not allocate mii_info\n",
- dev->name);
- return -ENOMEM;
- }
-
- mii_info->speed = SPEED_1000;
- mii_info->duplex = DUPLEX_FULL;
- mii_info->pause = 0;
- mii_info->link = 1;
-
- mii_info->advertising = (ADVERTISED_10baseT_Half |
- ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Half |
- ADVERTISED_100baseT_Full |
- ADVERTISED_1000baseT_Full);
- mii_info->autoneg = 1;
-
- spin_lock_init(&mii_info->mdio_lock);
-
- mii_info->mii_id = priv->einfo->phyid;
-
- mii_info->dev = dev;
-
- mii_info->mdio_read = &read_phy_reg;
- mii_info->mdio_write = &write_phy_reg;
-
- priv->mii_info = mii_info;
+ phydev = phy_connect(dev, priv->einfo->bus_id,
+ &adjust_link);
- /* Reset the management interface */
- gfar_write(&phyregs->miimcfg, MIIMCFG_RESET);
-
- /* Setup the MII Mgmt clock speed */
- gfar_write(&phyregs->miimcfg, MIIMCFG_INIT_VALUE);
-
- /* Wait until the bus is free */
- while ((gfar_read(&phyregs->miimind) & MIIMIND_BUSY) &&
- timeout--)
- cpu_relax();
-
- if(timeout <= 0) {
- printk(KERN_ERR "%s: The MII Bus is stuck!\n",
- dev->name);
- err = -1;
- goto bus_fail;
+ if(NULL == phydev) {
+ printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+ return errno;
}
- /* get info for this PHY */
- curphy = get_phy_info(priv->mii_info);
+ /* Remove any features not supported by the controller */
+ phydev->supported &= (GFAR_SUPPORTED | gigabit_support);
+ phydev->advertising = phydev->supported;
- if (curphy == NULL) {
- printk(KERN_ERR "%s: No PHY found\n", dev->name);
- err = -1;
- goto no_phy;
- }
-
- mii_info->phyinfo = curphy;
-
- /* Run the commands which initialize the PHY */
- if(curphy->init) {
- err = curphy->init(priv->mii_info);
-
- if (err)
- goto phy_init_fail;
- }
+ priv->phydev = phydev;
return 0;
-
-phy_init_fail:
-no_phy:
-bus_fail:
- kfree(mii_info);
-
- return err;
}
+
static void init_registers(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
@@ -504,13 +423,11 @@
unsigned long flags;
u32 tempval;
+ phy_stop(priv->phydev);
+
/* Lock it down */
spin_lock_irqsave(&priv->lock, flags);
- /* Tell the kernel the link is down */
- priv->mii_info->link = 0;
- adjust_link(dev);
-
/* Mask all interrupts */
gfar_write(®s->imask, IMASK_INIT_CLEAR);
@@ -534,30 +451,15 @@
tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN);
gfar_write(®s->maccfg1, tempval);
- if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
- /* Clear any pending interrupts */
- mii_clear_phy_interrupt(priv->mii_info);
-
- /* Disable PHY Interrupts */
- mii_configure_phy_interrupt(priv->mii_info,
- MII_INTERRUPT_DISABLED);
- }
-
spin_unlock_irqrestore(&priv->lock, flags);
/* Free the IRQs */
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
- free_irq(priv->interruptError, dev);
- free_irq(priv->interruptTransmit, dev);
- free_irq(priv->interruptReceive, dev);
+ free_irq(priv->interruptError, dev);
+ free_irq(priv->interruptTransmit, dev);
+ free_irq(priv->interruptReceive, dev);
} else {
- free_irq(priv->interruptTransmit, dev);
- }
-
- if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
- free_irq(priv->einfo->interruptPHY, dev);
- } else {
- del_timer_sync(&priv->phy_info_timer);
+ free_irq(priv->interruptTransmit, dev);
}
free_skb_resources(priv);
@@ -571,7 +473,7 @@
/* If there are any tx skbs or rx skbs still around, free them.
* Then free tx_skbuff and rx_skbuff */
-void free_skb_resources(struct gfar_private *priv)
+static void free_skb_resources(struct gfar_private *priv)
{
struct rxbd8 *rxbdp;
struct txbd8 *txbdp;
@@ -636,7 +538,7 @@
gfar_write(®s->imask, IMASK_INIT_CLEAR);
/* Allocate memory for the buffer descriptors */
- vaddr = (unsigned long) dma_alloc_coherent(NULL,
+ vaddr = (unsigned long) dma_alloc_coherent(NULL,
sizeof (struct txbd8) * priv->tx_ring_size +
sizeof (struct rxbd8) * priv->rx_ring_size,
&addr, GFP_KERNEL);
@@ -726,7 +628,7 @@
/* If the device has multiple interrupts, register for
* them. Otherwise, only register for the one */
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
- /* Install our interrupt handlers for Error,
+ /* Install our interrupt handlers for Error,
* Transmit, and Receive */
if (request_irq(priv->interruptError, gfar_error,
0, "enet_error", dev) < 0) {
@@ -766,13 +668,7 @@
}
}
- /* Set up the PHY change work queue */
- INIT_WORK(&priv->tq, gfar_phy_change, dev);
-
- init_timer(&priv->phy_info_timer);
- priv->phy_info_timer.function = &gfar_phy_startup_timer;
- priv->phy_info_timer.data = (unsigned long) priv->mii_info;
- mod_timer(&priv->phy_info_timer, jiffies + HZ);
+ phy_start(priv->phydev);
/* Configure the coalescing support */
if (priv->txcoalescing)
@@ -826,11 +722,6 @@
priv->tx_bd_base,
gfar_read(®s->tbase));
- if (priv->mii_info->phyinfo->close)
- priv->mii_info->phyinfo->close(priv->mii_info);
-
- kfree(priv->mii_info);
-
return err;
}
@@ -878,7 +769,7 @@
/* Set buffer length and pointer */
txbdp->length = skb->len;
- txbdp->bufPtr = dma_map_single(NULL, skb->data,
+ txbdp->bufPtr = dma_map_single(NULL, skb->data,
skb->len, DMA_TO_DEVICE);
/* Save the skb pointer so we can free it later */
@@ -930,11 +821,9 @@
struct gfar_private *priv = netdev_priv(dev);
stop_gfar(dev);
- /* Shutdown the PHY */
- if (priv->mii_info->phyinfo->close)
- priv->mii_info->phyinfo->close(priv->mii_info);
-
- kfree(priv->mii_info);
+ /* Disconnect from the PHY */
+ phy_disconnect(priv->phydev);
+ priv->phydev = NULL;
netif_stop_queue(dev);
@@ -1120,7 +1009,7 @@
skb->dev = dev;
bdp->bufPtr = dma_map_single(NULL, skb->data,
- priv->rx_buffer_size + RXBUF_ALIGNMENT,
+ priv->rx_buffer_size + RXBUF_ALIGNMENT,
DMA_FROM_DEVICE);
bdp->length = 0;
@@ -1250,7 +1139,7 @@
}
/* gfar_clean_rx_ring() -- Processes each frame in the rx ring
- * until the budget/quota has been reached. Returns the number
+ * until the budget/quota has been reached. Returns the number
* of frames handled
*/
static int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
@@ -1450,129 +1339,9 @@
return IRQ_HANDLED;
}
-static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct net_device *dev = (struct net_device *) dev_id;
- struct gfar_private *priv = netdev_priv(dev);
-
- /* Clear the interrupt */
- mii_clear_phy_interrupt(priv->mii_info);
-
- /* Disable PHY interrupts */
- mii_configure_phy_interrupt(priv->mii_info,
- MII_INTERRUPT_DISABLED);
-
- /* Schedule the phy change */
- schedule_work(&priv->tq);
-
- return IRQ_HANDLED;
-}
-
-/* Scheduled by the phy_interrupt/timer to handle PHY changes */
-static void gfar_phy_change(void *data)
-{
- struct net_device *dev = (struct net_device *) data;
- struct gfar_private *priv = netdev_priv(dev);
- int result = 0;
-
- /* Delay to give the PHY a chance to change the
- * register state */
- msleep(1);
-
- /* Update the link, speed, duplex */
- result = priv->mii_info->phyinfo->read_status(priv->mii_info);
-
- /* Adjust the known status as long as the link
- * isn't still coming up */
- if((0 == result) || (priv->mii_info->link == 0))
- adjust_link(dev);
-
- /* Reenable interrupts, if needed */
- if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR)
- mii_configure_phy_interrupt(priv->mii_info,
- MII_INTERRUPT_ENABLED);
-}
-
-/* Called every so often on systems that don't interrupt
- * the core for PHY changes */
-static void gfar_phy_timer(unsigned long data)
-{
- struct net_device *dev = (struct net_device *) data;
- struct gfar_private *priv = netdev_priv(dev);
-
- schedule_work(&priv->tq);
-
- mod_timer(&priv->phy_info_timer, jiffies +
- GFAR_PHY_CHANGE_TIME * HZ);
-}
-
-/* Keep trying aneg for some time
- * If, after GFAR_AN_TIMEOUT seconds, it has not
- * finished, we switch to forced.
- * Either way, once the process has completed, we either
- * request the interrupt, or switch the timer over to
- * using gfar_phy_timer to check status */
-static void gfar_phy_startup_timer(unsigned long data)
-{
- int result;
- static int secondary = GFAR_AN_TIMEOUT;
- struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data;
- struct gfar_private *priv = netdev_priv(mii_info->dev);
-
- /* Configure the Auto-negotiation */
- result = mii_info->phyinfo->config_aneg(mii_info);
-
- /* If autonegotiation failed to start, and
- * we haven't timed out, reset the timer, and return */
- if (result && secondary--) {
- mod_timer(&priv->phy_info_timer, jiffies + HZ);
- return;
- } else if (result) {
- /* Couldn't start autonegotiation.
- * Try switching to forced */
- mii_info->autoneg = 0;
- result = mii_info->phyinfo->config_aneg(mii_info);
-
- /* Forcing failed! Give up */
- if(result) {
- printk(KERN_ERR "%s: Forcing failed!\n",
- mii_info->dev->name);
- return;
- }
- }
-
- /* Kill the timer so it can be restarted */
- del_timer_sync(&priv->phy_info_timer);
-
- /* Grab the PHY interrupt, if necessary/possible */
- if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
- if (request_irq(priv->einfo->interruptPHY,
- phy_interrupt,
- SA_SHIRQ,
- "phy_interrupt",
- mii_info->dev) < 0) {
- printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n",
- mii_info->dev->name,
- priv->einfo->interruptPHY);
- } else {
- mii_configure_phy_interrupt(priv->mii_info,
- MII_INTERRUPT_ENABLED);
- return;
- }
- }
-
- /* Start the timer again, this time in order to
- * handle a change in status */
- init_timer(&priv->phy_info_timer);
- priv->phy_info_timer.function = &gfar_phy_timer;
- priv->phy_info_timer.data = (unsigned long) mii_info->dev;
- mod_timer(&priv->phy_info_timer, jiffies +
- GFAR_PHY_CHANGE_TIME * HZ);
-}
-
/* Called every time the controller might need to be made
* aware of new link state. The PHY code conveys this
- * information through variables in the priv structure, and this
+ * information through variables in the phydev structure, and this
* function converts those variables into the appropriate
* register values, and can bring down the device if needed.
*/
@@ -1581,33 +1350,32 @@
struct gfar_private *priv = netdev_priv(dev);
struct gfar *regs = priv->regs;
u32 tempval;
- struct gfar_mii_info *mii_info = priv->mii_info;
+ unsigned long flags;
+ struct phy_device *phydev = priv->phydev;
+ int new_state = 0;
- if (mii_info->link) {
+ spin_lock_irqsave(&priv->lock, flags);
+ if (phydev->link) {
/* Now we make sure that we can be in full duplex mode.
* If not, we operate in half-duplex mode. */
- if (mii_info->duplex != priv->oldduplex) {
- if (!(mii_info->duplex)) {
+ if (phydev->duplex != priv->oldduplex) {
+ new_state = 1;
+ if (!(phydev->duplex)) {
tempval = gfar_read(®s->maccfg2);
tempval &= ~(MACCFG2_FULL_DUPLEX);
gfar_write(®s->maccfg2, tempval);
-
- printk(KERN_INFO "%s: Half Duplex\n",
- dev->name);
} else {
tempval = gfar_read(®s->maccfg2);
tempval |= MACCFG2_FULL_DUPLEX;
gfar_write(®s->maccfg2, tempval);
-
- printk(KERN_INFO "%s: Full Duplex\n",
- dev->name);
}
- priv->oldduplex = mii_info->duplex;
+ priv->oldduplex = phydev->duplex;
}
- if (mii_info->speed != priv->oldspeed) {
- switch (mii_info->speed) {
+ if (phydev->speed != priv->oldspeed) {
+ new_state = 1;
+ switch (phydev->speed) {
case 1000:
tempval = gfar_read(®s->maccfg2);
tempval =
@@ -1624,31 +1392,39 @@
default:
printk(KERN_WARNING
"%s: Ack! Speed (%d) is not 10/100/1000!\n",
- dev->name, mii_info->speed);
+ dev->name, phydev->speed);
break;
}
- printk(KERN_INFO "%s: Speed %dBT\n", dev->name,
- mii_info->speed);
-
- priv->oldspeed = mii_info->speed;
+ priv->oldspeed = phydev->speed;
}
if (!priv->oldlink) {
- printk(KERN_INFO "%s: Link is up\n", dev->name);
+ new_state = 1;
priv->oldlink = 1;
- netif_carrier_on(dev);
netif_schedule(dev);
}
} else {
if (priv->oldlink) {
- printk(KERN_INFO "%s: Link is down\n", dev->name);
+ new_state = 1;
priv->oldlink = 0;
priv->oldspeed = 0;
priv->oldduplex = -1;
- netif_carrier_off(dev);
}
}
+
+ if (new_state) {
+ pr_info("%s: Link is %s", dev->name,
+ phydev->link ? "Up" : "Down");
+ if (phydev->link)
+ printk(" - %d/%s", phydev->speed,
+ DUPLEX_FULL == phydev->duplex ?
+ "Full" : "Half");
+
+ printk("\n");
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
}
@@ -1836,14 +1612,24 @@
static int __init gfar_init(void)
{
- return driver_register(&gfar_driver);
+ int err = gfar_mdio_init();
+
+ if (err)
+ return err;
+
+ err = driver_register(&gfar_driver);
+
+ if (err)
+ gfar_mdio_exit();
+
+ return err;
}
static void __exit gfar_exit(void)
{
driver_unregister(&gfar_driver);
+ gfar_mdio_exit();
}
module_init(gfar_init);
module_exit(gfar_exit);
-
diff -Nru a/drivers/net/gianfar.h b/drivers/net/gianfar.h
--- a/drivers/net/gianfar.h 2005-03-25 14:47:22 -06:00
+++ b/drivers/net/gianfar.h 2005-03-25 14:47:22 -06:00
@@ -17,7 +17,6 @@
*
* Still left to do:
* -Add support for module parameters
- * -Add support for ethtool -s
* -Add patch for ethtool phys id
*/
#ifndef __GIANFAR_H
@@ -37,7 +36,8 @@
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
-#include <linux/fsl_devices.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -48,7 +48,8 @@
#include <linux/workqueue.h>
#include <linux/ethtool.h>
#include <linux/netdevice.h>
-#include "gianfar_phy.h"
+#include <linux/fsl_devices.h>
+#include "gianfar_mii.h"
/* The maximum number of packets to be handled in one call of gfar_poll */
#define GFAR_DEV_WEIGHT 64
@@ -67,7 +68,7 @@
#define PHY_INIT_TIMEOUT 100000
#define GFAR_PHY_CHANGE_TIME 2
-#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.1, "
+#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.2, "
#define DRV_NAME "gfar-enet"
extern const char gfar_driver_name[];
extern const char gfar_driver_version[];
@@ -221,24 +222,17 @@
/* Attribute fields */
/* This enables rx snooping for buffers and descriptors */
-#ifdef CONFIG_GFAR_BDSTASH
#define ATTR_BDSTASH 0x00000800
-#else
-#define ATTR_BDSTASH 0x00000000
-#endif
-
-#ifdef CONFIG_GFAR_BUFSTASH
+#define ATTR_BDLOCK 0x00000c00
#define ATTR_BUFSTASH 0x00004000
-#define STASH_LENGTH 64
-#else
-#define ATTR_BUFSTASH 0x00000000
-#endif
-
+#define ATTR_BUFLOCK 0x00006000
#define ATTR_SNOOPING 0x000000c0
-#define ATTR_INIT_SETTINGS (ATTR_SNOOPING \
- | ATTR_BDSTASH | ATTR_BUFSTASH)
+#define ATTR_INIT_SETTINGS (ATTR_SNOOPING)
#define ATTRELI_INIT_SETTINGS 0x0
+#define ATTRELI_MASK 0x3fff
+#define ATTRELI_LENGTH(x) ((x & ATTRELI_MASK) << 16)
+#define ATTRELI_INDEX(x) (x & ATTRELI_MASK)
/* TxBD status field bits */
@@ -369,6 +363,18 @@
u64 rmon[GFAR_RMON_LEN];
};
+/* Variables exposed to the user through ethtool */
+struct gfar_xvals {
+ u32 phytest; /* Enable PHY error injection */
+ u32 ptest_reg; /* Which register will trigger an error */
+ u32 ptest_read; /* Whether read or write will trigger an error */
+ u32 bd_stash; /* on == BDs allocated into L2 */
+ u32 buf_stash; /* number of bytes of buffer to stash in
+ L2 (0 means no allocation is performed) */
+ u32 buf_index; /* Index of first byte to extract to L2 */
+ u32 bd_lock; /* Lock buffer descriptors in the L2 */
+ u32 buf_lock; /* Lock extracted buffers in the L2 */
+};
struct gfar {
u8 res1[16];
@@ -422,12 +428,7 @@
u32 hafdup; /* 0x.50c - Half Duplex Register */
u32 maxfrm; /* 0x.510 - Maximum Frame Length Register */
u8 res18[12];
- u32 miimcfg; /* 0x.520 - MII Management Configuration Register */
- u32 miimcom; /* 0x.524 - MII Management Command Register */
- u32 miimadd; /* 0x.528 - MII Management Address Register */
- u32 miimcon; /* 0x.52c - MII Management Control Register */
- u32 miimstat; /* 0x.530 - MII Management Status Register */
- u32 miimind; /* 0x.534 - MII Management Indicator Register */
+ u8 gfar_mii_regs[24]; /* See gianfar_phy.h */
u8 res19[4];
u32 ifstat; /* 0x.53c - Interface Status Register */
u32 macstnaddr1; /* 0x.540 - Station Address Part 1 Register */
@@ -496,11 +497,9 @@
struct txbd8 *cur_tx; /* Next free ring entry */
struct txbd8 *dirty_tx; /* The Ring entry to be freed. */
struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */
- struct gfar *phyregs;
- struct work_struct tq;
- struct timer_list phy_info_timer;
struct net_device_stats stats; /* linux network statistics */
struct gfar_extra_stats extra_stats;
+ struct gfar_xvals xvals;
spinlock_t lock;
unsigned int rx_buffer_size;
unsigned int rx_stash_size;
@@ -515,7 +514,8 @@
unsigned int interruptError;
struct gianfar_platform_data *einfo;
- struct gfar_mii_info *mii_info;
+ struct phy_device *phydev;
+ struct mii_bus *mii_bus;
int oldspeed;
int oldduplex;
int oldlink;
@@ -534,5 +534,12 @@
}
extern struct ethtool_ops *gfar_op_array[];
+
+extern irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
+extern int startup_gfar(struct net_device *dev);
+extern void stop_gfar(struct net_device *dev);
+extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev,
+ int enable, u32 regnum, u32 read);
+void gfar_setup_stashing(struct net_device *dev);
#endif /* __GIANFAR_H */
diff -Nru a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
--- a/drivers/net/gianfar_ethtool.c 2005-03-25 14:47:22 -06:00
+++ b/drivers/net/gianfar_ethtool.c 2005-03-25 14:47:22 -06:00
@@ -39,14 +39,15 @@
#include <asm/types.h>
#include <asm/uaccess.h>
#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
#include "gianfar.h"
#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
-extern int startup_gfar(struct net_device *dev);
-extern void stop_gfar(struct net_device *dev);
-extern void gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
+#define GFAR_MAX_COAL_USECS 0xffff
+#define GFAR_MAX_COAL_FRAMES 0xff
void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
u64 * buf);
@@ -118,6 +119,7 @@
"tx-fragmented-frames",
};
+
/* Fill in an array of 64-bit statistics from various sources.
* This array will be appended to the end of the ethtool_stats
* structure, and returned to user space
@@ -181,38 +183,31 @@
drvinfo->eedump_len = 0;
}
+
+static int gfar_ssettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct phy_device *phydev = priv->phydev;
+
+ if (NULL == phydev)
+ return -ENODEV;
+
+ return phy_ethtool_sset(phydev, cmd);
+}
+
/* Return the current settings in the ethtool_cmd structure */
int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct gfar_private *priv = netdev_priv(dev);
- uint gigabit_support =
- priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
- SUPPORTED_1000baseT_Full : 0;
- uint gigabit_advert =
- priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
- ADVERTISED_1000baseT_Full: 0;
-
- cmd->supported = (SUPPORTED_10baseT_Half
- | SUPPORTED_100baseT_Half
- | SUPPORTED_100baseT_Full
- | gigabit_support | SUPPORTED_Autoneg);
-
- /* For now, we always advertise everything */
- cmd->advertising = (ADVERTISED_10baseT_Half
- | ADVERTISED_100baseT_Half
- | ADVERTISED_100baseT_Full
- | gigabit_advert | ADVERTISED_Autoneg);
-
- cmd->speed = priv->mii_info->speed;
- cmd->duplex = priv->mii_info->duplex;
- cmd->port = PORT_MII;
- cmd->phy_address = priv->mii_info->mii_id;
- cmd->transceiver = XCVR_EXTERNAL;
- cmd->autoneg = AUTONEG_ENABLE;
+ struct phy_device *phydev = priv->phydev;
+
+ if (NULL == phydev)
+ return -ENODEV;
+
cmd->maxtxpkt = priv->txcount;
cmd->maxrxpkt = priv->rxcount;
- return 0;
+ return phy_ethtool_gset(phydev, cmd);
}
/* Return the length of the register structure */
@@ -247,14 +242,14 @@
unsigned int count;
/* The timer is different, depending on the interface speed */
- switch (priv->mii_info->speed) {
- case 1000:
+ switch (priv->phydev->speed) {
+ case SPEED_1000:
count = GFAR_GBIT_TIME;
break;
- case 100:
+ case SPEED_100:
count = GFAR_100_TIME;
break;
- case 10:
+ case SPEED_10:
default:
count = GFAR_10_TIME;
break;
@@ -271,14 +266,14 @@
unsigned int count;
/* The timer is different, depending on the interface speed */
- switch (priv->mii_info->speed) {
- case 1000:
+ switch (priv->phydev->speed) {
+ case SPEED_1000:
count = GFAR_GBIT_TIME;
break;
- case 100:
+ case SPEED_100:
count = GFAR_100_TIME;
break;
- case 10:
+ case SPEED_10:
default:
count = GFAR_10_TIME;
break;
@@ -295,6 +290,9 @@
{
struct gfar_private *priv = netdev_priv(dev);
+ if (NULL == priv->phydev)
+ return -ENODEV;
+
cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime);
cvals->rx_max_coalesced_frames = priv->rxcount;
@@ -348,6 +346,22 @@
else
priv->rxcoalescing = 1;
+ if (NULL == priv->phydev)
+ return -ENODEV;
+
+ /* Check the bounds of the values */
+ if (cvals->rx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
+ pr_info("Coalescing is limited to %d microseconds\n",
+ GFAR_MAX_COAL_USECS);
+ return -EINVAL;
+ }
+
+ if (cvals->rx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
+ pr_info("Coalescing is limited to %d frames\n",
+ GFAR_MAX_COAL_FRAMES);
+ return -EINVAL;
+ }
+
priv->rxtime = gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs);
priv->rxcount = cvals->rx_max_coalesced_frames;
@@ -358,6 +372,19 @@
else
priv->txcoalescing = 1;
+ /* Check the bounds of the values */
+ if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
+ pr_info("Coalescing is limited to %d microseconds\n",
+ GFAR_MAX_COAL_USECS);
+ return -EINVAL;
+ }
+
+ if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
+ pr_info("Coalescing is limited to %d frames\n",
+ GFAR_MAX_COAL_FRAMES);
+ return -EINVAL;
+ }
+
priv->txtime = gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs);
priv->txcount = cvals->tx_max_coalesced_frames;
@@ -464,6 +491,7 @@
}
struct ethtool_ops gfar_ethtool_ops = {
+ .set_settings = gfar_ssettings,
.get_settings = gfar_gsettings,
.get_drvinfo = gfar_gdrvinfo,
.get_regs_len = gfar_reglen,
@@ -479,6 +507,7 @@
};
struct ethtool_ops gfar_normon_nocoalesce_ethtool_ops = {
+ .set_settings = gfar_ssettings,
.get_settings = gfar_gsettings,
.get_drvinfo = gfar_gdrvinfo,
.get_regs_len = gfar_reglen,
@@ -492,6 +521,7 @@
};
struct ethtool_ops gfar_nocoalesce_ethtool_ops = {
+ .set_settings = gfar_ssettings,
.get_settings = gfar_gsettings,
.get_drvinfo = gfar_gdrvinfo,
.get_regs_len = gfar_reglen,
@@ -505,6 +535,7 @@
};
struct ethtool_ops gfar_normon_ethtool_ops = {
+ .set_settings = gfar_ssettings,
.get_settings = gfar_gsettings,
.get_drvinfo = gfar_gdrvinfo,
.get_regs_len = gfar_reglen,
diff -Nru a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/drivers/net/gianfar_mii.c 2005-03-25 14:47:21 -06:00
@@ -0,0 +1,219 @@
+/*
+ * drivers/net/gianfar_mii.c
+ *
+ * Gianfar Ethernet Driver -- MIIM bus implementation
+ * Provides Bus interface for MIIM regs
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *
+ * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <asm/ocp.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "gianfar.h"
+#include "gianfar_mii.h"
+
+/* Write value to the PHY at mii_id at register regnum,
+ * on the bus, waiting until the write is done before returning.
+ * All PHY configuration is done through the TSEC1 MIIM regs */
+int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
+{
+ struct gfar_mii *regs = bus->priv;
+
+ /* Set the PHY address and the register address we want to write */
+ gfar_write(®s->miimadd, (mii_id << 8) | regnum);
+
+ /* Write out the value we want */
+ gfar_write(®s->miimcon, value);
+
+ /* Wait for the transaction to finish */
+ while (gfar_read(®s->miimind) & MIIMIND_BUSY)
+ cpu_relax();
+
+ return 0;
+}
+
+/* Read the bus for PHY at addr mii_id, register regnum, and
+ * return the value. Clears miimcom first. All PHY
+ * configuration has to be done through the TSEC1 MIIM regs */
+int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+ struct gfar_mii *regs = bus->priv;
+ u16 value;
+
+ /* Set the PHY address and the register address we want to read */
+ gfar_write(®s->miimadd, (mii_id << 8) | regnum);
+
+ /* Clear miimcom, and then initiate a read */
+ gfar_write(®s->miimcom, 0);
+ gfar_write(®s->miimcom, MII_READ_COMMAND);
+
+ /* Wait for the transaction to finish */
+ while (gfar_read(®s->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
+ cpu_relax();
+
+ /* Grab the value of the register from miimstat */
+ value = gfar_read(®s->miimstat);
+
+ return value;
+}
+
+
+/* Reset the MIIM registers, and wait for the bus to free */
+int gfar_mdio_reset(struct mii_bus *bus)
+{
+ struct gfar_mii *regs = bus->priv;
+ unsigned int timeout = PHY_INIT_TIMEOUT;
+
+ spin_lock_bh(&bus->mdio_lock);
+
+ /* Reset the management interface */
+ gfar_write(®s->miimcfg, MIIMCFG_RESET);
+
+ /* Setup the MII Mgmt clock speed */
+ gfar_write(®s->miimcfg, MIIMCFG_INIT_VALUE);
+
+ /* Wait until the bus is free */
+ while ((gfar_read(®s->miimind) & MIIMIND_BUSY) &&
+ timeout--)
+ cpu_relax();
+
+ spin_unlock_bh(&bus->mdio_lock);
+
+ if(timeout <= 0) {
+ printk(KERN_ERR "%s: The MII Bus is stuck!\n",
+ bus->name);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+
+int gfar_mdio_probe(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct gianfar_mdio_data *pdata;
+ struct gfar_mii *regs;
+ struct mii_bus *new_bus;
+ int err = 0;
+
+ if (NULL == dev)
+ return -EINVAL;
+
+ new_bus = kmalloc(sizeof(struct mii_bus), GFP_KERNEL);
+
+ if (NULL == new_bus)
+ return -ENOMEM;
+
+ new_bus->name = "Gianfar MII Bus",
+ new_bus->read = &gfar_mdio_read,
+ new_bus->write = &gfar_mdio_write,
+ new_bus->reset = &gfar_mdio_reset,
+ new_bus->id = pdev->id;
+
+ pdata = (struct gianfar_mdio_data *)pdev->dev.platform_data;
+
+ if (NULL == pdata) {
+ printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id);
+ return -ENODEV;
+ }
+
+ /* Set the PHY base address */
+ regs = (struct gfar_mii *) ioremap(pdata->paddr,
+ sizeof (struct gfar_mii));
+
+ if (NULL == regs) {
+ err = -ENOMEM;
+ goto reg_map_fail;
+ }
+
+ new_bus->priv = regs;
+
+ new_bus->irq = pdata->irq;
+
+ new_bus->dev = dev;
+ dev_set_drvdata(dev, new_bus);
+
+ err = mdiobus_register(new_bus);
+
+ if (0 != err) {
+ printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
+ new_bus->name);
+ goto bus_register_fail;
+ }
+
+ return 0;
+
+bus_register_fail:
+ iounmap((void *) regs);
+reg_map_fail:
+ kfree(new_bus);
+
+ return err;
+}
+
+
+int gfar_mdio_remove(struct device *dev)
+{
+ struct mii_bus *bus = dev_get_drvdata(dev);
+
+ mdiobus_unregister(bus);
+
+ dev_set_drvdata(dev, NULL);
+
+ iounmap((void *) (&bus->priv));
+ bus->priv = NULL;
+ kfree(bus);
+
+ return 0;
+}
+
+static struct device_driver gianfar_mdio_driver = {
+ .name = "fsl-gianfar_mdio",
+ .bus = &platform_bus_type,
+ .probe = gfar_mdio_probe,
+ .remove = gfar_mdio_remove,
+};
+
+int __init gfar_mdio_init(void)
+{
+ return driver_register(&gianfar_mdio_driver);
+}
+
+void __exit gfar_mdio_exit(void)
+{
+ driver_unregister(&gianfar_mdio_driver);
+}
diff -Nru a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/drivers/net/gianfar_mii.h 2005-03-25 14:47:21 -06:00
@@ -0,0 +1,45 @@
+/*
+ * drivers/net/gianfar_mii.h
+ *
+ * Gianfar Ethernet Driver -- MII Management Bus Implementation
+ * Driver for the MDIO bus controller in the Gianfar register space
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *
+ * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ */
+#ifndef __GIANFAR_MII_H
+#define __GIANFAR_MII_H
+
+#define MIIMIND_BUSY 0x00000001
+#define MIIMIND_NOTVALID 0x00000004
+
+#define MII_READ_COMMAND 0x00000001
+
+#define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \
+ | SUPPORTED_100baseT_Half \
+ | SUPPORTED_100baseT_Full \
+ | SUPPORTED_Autoneg \
+ | SUPPORTED_MII)
+
+struct gfar_mii {
+ u32 miimcfg; /* 0x.520 - MII Management Config Register */
+ u32 miimcom; /* 0x.524 - MII Management Command Register */
+ u32 miimadd; /* 0x.528 - MII Management Address Register */
+ u32 miimcon; /* 0x.52c - MII Management Control Register */
+ u32 miimstat; /* 0x.530 - MII Management Status Register */
+ u32 miimind; /* 0x.534 - MII Management Indicator Register */
+};
+
+int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum);
+int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
+int __init gfar_mdio_init(void);
+void __exit gfar_mdio_exit(void);
+#endif /* GIANFAR_PHY_H */
diff -Nru a/drivers/net/gianfar_phy.c b/drivers/net/gianfar_phy.c
--- a/drivers/net/gianfar_phy.c 2005-03-25 14:47:21 -06:00
+++ /dev/null Wed Dec 31 16:00:00 196900
@@ -1,661 +0,0 @@
-/*
- * drivers/net/gianfar_phy.c
- *
- * Gianfar Ethernet Driver -- PHY handling
- * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
- * Based on 8260_io/fcc_enet.c
- *
- * Author: Andy Fleming
- * Maintainer: Kumar Gala (kumar.gala@freescale.com)
- *
- * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
- *
- * 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.
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/mm.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/crc32.h>
-#include <linux/mii.h>
-
-#include "gianfar.h"
-#include "gianfar_phy.h"
-
-static void config_genmii_advert(struct gfar_mii_info *mii_info);
-static void genmii_setup_forced(struct gfar_mii_info *mii_info);
-static void genmii_restart_aneg(struct gfar_mii_info *mii_info);
-static int gbit_config_aneg(struct gfar_mii_info *mii_info);
-static int genmii_config_aneg(struct gfar_mii_info *mii_info);
-static int genmii_update_link(struct gfar_mii_info *mii_info);
-static int genmii_read_status(struct gfar_mii_info *mii_info);
-u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum);
-void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val);
-
-/* Write value to the PHY for this device to the register at regnum, */
-/* waiting until the write is done before it returns. All PHY */
-/* configuration has to be done through the TSEC1 MIIM regs */
-void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value)
-{
- struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regbase = priv->phyregs;
-
- /* Set the PHY address and the register address we want to write */
- gfar_write(®base->miimadd, (mii_id << 8) | regnum);
-
- /* Write out the value we want */
- gfar_write(®base->miimcon, value);
-
- /* Wait for the transaction to finish */
- while (gfar_read(®base->miimind) & MIIMIND_BUSY)
- cpu_relax();
-}
-
-/* Reads from register regnum in the PHY for device dev, */
-/* returning the value. Clears miimcom first. All PHY */
-/* configuration has to be done through the TSEC1 MIIM regs */
-int read_phy_reg(struct net_device *dev, int mii_id, int regnum)
-{
- struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regbase = priv->phyregs;
- u16 value;
-
- /* Set the PHY address and the register address we want to read */
- gfar_write(®base->miimadd, (mii_id << 8) | regnum);
-
- /* Clear miimcom, and then initiate a read */
- gfar_write(®base->miimcom, 0);
- gfar_write(®base->miimcom, MII_READ_COMMAND);
-
- /* Wait for the transaction to finish */
- while (gfar_read(®base->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
- cpu_relax();
-
- /* Grab the value of the register from miimstat */
- value = gfar_read(®base->miimstat);
-
- return value;
-}
-
-void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info)
-{
- if(mii_info->phyinfo->ack_interrupt)
- mii_info->phyinfo->ack_interrupt(mii_info);
-}
-
-
-void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts)
-{
- mii_info->interrupts = interrupts;
- if(mii_info->phyinfo->config_intr)
- mii_info->phyinfo->config_intr(mii_info);
-}
-
-
-/* Writes MII_ADVERTISE with the appropriate values, after
- * sanitizing advertise to make sure only supported features
- * are advertised
- */
-static void config_genmii_advert(struct gfar_mii_info *mii_info)
-{
- u32 advertise;
- u16 adv;
-
- /* Only allow advertising what this PHY supports */
- mii_info->advertising &= mii_info->phyinfo->features;
- advertise = mii_info->advertising;
-
- /* Setup standard advertisement */
- adv = phy_read(mii_info, MII_ADVERTISE);
- adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
- if (advertise & ADVERTISED_10baseT_Half)
- adv |= ADVERTISE_10HALF;
- if (advertise & ADVERTISED_10baseT_Full)
- adv |= ADVERTISE_10FULL;
- if (advertise & ADVERTISED_100baseT_Half)
- adv |= ADVERTISE_100HALF;
- if (advertise & ADVERTISED_100baseT_Full)
- adv |= ADVERTISE_100FULL;
- phy_write(mii_info, MII_ADVERTISE, adv);
-}
-
-static void genmii_setup_forced(struct gfar_mii_info *mii_info)
-{
- u16 ctrl;
- u32 features = mii_info->phyinfo->features;
-
- ctrl = phy_read(mii_info, MII_BMCR);
-
- ctrl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPEED1000|BMCR_ANENABLE);
- ctrl |= BMCR_RESET;
-
- switch(mii_info->speed) {
- case SPEED_1000:
- if(features & (SUPPORTED_1000baseT_Half
- | SUPPORTED_1000baseT_Full)) {
- ctrl |= BMCR_SPEED1000;
- break;
- }
- mii_info->speed = SPEED_100;
- case SPEED_100:
- if (features & (SUPPORTED_100baseT_Half
- | SUPPORTED_100baseT_Full)) {
- ctrl |= BMCR_SPEED100;
- break;
- }
- mii_info->speed = SPEED_10;
- case SPEED_10:
- if (features & (SUPPORTED_10baseT_Half
- | SUPPORTED_10baseT_Full))
- break;
- default: /* Unsupported speed! */
- printk(KERN_ERR "%s: Bad speed!\n",
- mii_info->dev->name);
- break;
- }
-
- phy_write(mii_info, MII_BMCR, ctrl);
-}
-
-
-/* Enable and Restart Autonegotiation */
-static void genmii_restart_aneg(struct gfar_mii_info *mii_info)
-{
- u16 ctl;
-
- ctl = phy_read(mii_info, MII_BMCR);
- ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
- phy_write(mii_info, MII_BMCR, ctl);
-}
-
-
-static int gbit_config_aneg(struct gfar_mii_info *mii_info)
-{
- u16 adv;
- u32 advertise;
-
- if(mii_info->autoneg) {
- /* Configure the ADVERTISE register */
- config_genmii_advert(mii_info);
- advertise = mii_info->advertising;
-
- adv = phy_read(mii_info, MII_1000BASETCONTROL);
- adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
- MII_1000BASETCONTROL_HALFDUPLEXCAP);
- if (advertise & SUPPORTED_1000baseT_Half)
- adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
- if (advertise & SUPPORTED_1000baseT_Full)
- adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
- phy_write(mii_info, MII_1000BASETCONTROL, adv);
-
- /* Start/Restart aneg */
- genmii_restart_aneg(mii_info);
- } else
- genmii_setup_forced(mii_info);
-
- return 0;
-}
-
-static int marvell_config_aneg(struct gfar_mii_info *mii_info)
-{
- /* The Marvell PHY has an errata which requires
- * that certain registers get written in order
- * to restart autonegotiation */
- phy_write(mii_info, MII_BMCR, BMCR_RESET);
-
- phy_write(mii_info, 0x1d, 0x1f);
- phy_write(mii_info, 0x1e, 0x200c);
- phy_write(mii_info, 0x1d, 0x5);
- phy_write(mii_info, 0x1e, 0);
- phy_write(mii_info, 0x1e, 0x100);
-
- gbit_config_aneg(mii_info);
-
- return 0;
-}
-static int genmii_config_aneg(struct gfar_mii_info *mii_info)
-{
- if (mii_info->autoneg) {
- config_genmii_advert(mii_info);
- genmii_restart_aneg(mii_info);
- } else
- genmii_setup_forced(mii_info);
-
- return 0;
-}
-
-
-static int genmii_update_link(struct gfar_mii_info *mii_info)
-{
- u16 status;
-
- /* Do a fake read */
- phy_read(mii_info, MII_BMSR);
-
- /* Read link and autonegotiation status */
- status = phy_read(mii_info, MII_BMSR);
- if ((status & BMSR_LSTATUS) == 0)
- mii_info->link = 0;
- else
- mii_info->link = 1;
-
- /* If we are autonegotiating, and not done,
- * return an error */
- if (mii_info->autoneg && !(status & BMSR_ANEGCOMPLETE))
- return -EAGAIN;
-
- return 0;
-}
-
-static int genmii_read_status(struct gfar_mii_info *mii_info)
-{
- u16 status;
- int err;
-
- /* Update the link, but return if there
- * was an error */
- err = genmii_update_link(mii_info);
- if (err)
- return err;
-
- if (mii_info->autoneg) {
- status = phy_read(mii_info, MII_LPA);
-
- if (status & (LPA_10FULL | LPA_100FULL))
- mii_info->duplex = DUPLEX_FULL;
- else
- mii_info->duplex = DUPLEX_HALF;
- if (status & (LPA_100FULL | LPA_100HALF))
- mii_info->speed = SPEED_100;
- else
- mii_info->speed = SPEED_10;
- mii_info->pause = 0;
- }
- /* On non-aneg, we assume what we put in BMCR is the speed,
- * though magic-aneg shouldn't prevent this case from occurring
- */
-
- return 0;
-}
-static int marvell_read_status(struct gfar_mii_info *mii_info)
-{
- u16 status;
- int err;
-
- /* Update the link, but return if there
- * was an error */
- err = genmii_update_link(mii_info);
- if (err)
- return err;
-
- /* If the link is up, read the speed and duplex */
- /* If we aren't autonegotiating, assume speeds
- * are as set */
- if (mii_info->autoneg && mii_info->link) {
- int speed;
- status = phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
-
-#if 0
- /* If speed and duplex aren't resolved,
- * return an error. Isn't this handled
- * by checking aneg?
- */
- if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
- return -EAGAIN;
-#endif
-
- /* Get the duplexity */
- if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
- mii_info->duplex = DUPLEX_FULL;
- else
- mii_info->duplex = DUPLEX_HALF;
-
- /* Get the speed */
- speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK;
- switch(speed) {
- case MII_M1011_PHY_SPEC_STATUS_1000:
- mii_info->speed = SPEED_1000;
- break;
- case MII_M1011_PHY_SPEC_STATUS_100:
- mii_info->speed = SPEED_100;
- break;
- default:
- mii_info->speed = SPEED_10;
- break;
- }
- mii_info->pause = 0;
- }
-
- return 0;
-}
-
-
-static int cis820x_read_status(struct gfar_mii_info *mii_info)
-{
- u16 status;
- int err;
-
- /* Update the link, but return if there
- * was an error */
- err = genmii_update_link(mii_info);
- if (err)
- return err;
-
- /* If the link is up, read the speed and duplex */
- /* If we aren't autonegotiating, assume speeds
- * are as set */
- if (mii_info->autoneg && mii_info->link) {
- int speed;
-
- status = phy_read(mii_info, MII_CIS8201_AUX_CONSTAT);
- if (status & MII_CIS8201_AUXCONSTAT_DUPLEX)
- mii_info->duplex = DUPLEX_FULL;
- else
- mii_info->duplex = DUPLEX_HALF;
-
- speed = status & MII_CIS8201_AUXCONSTAT_SPEED;
-
- switch (speed) {
- case MII_CIS8201_AUXCONSTAT_GBIT:
- mii_info->speed = SPEED_1000;
- break;
- case MII_CIS8201_AUXCONSTAT_100:
- mii_info->speed = SPEED_100;
- break;
- default:
- mii_info->speed = SPEED_10;
- break;
- }
- }
-
- return 0;
-}
-
-static int marvell_ack_interrupt(struct gfar_mii_info *mii_info)
-{
- /* Clear the interrupts by reading the reg */
- phy_read(mii_info, MII_M1011_IEVENT);
-
- return 0;
-}
-
-static int marvell_config_intr(struct gfar_mii_info *mii_info)
-{
- if(mii_info->interrupts == MII_INTERRUPT_ENABLED)
- phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
- else
- phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
-
- return 0;
-}
-
-static int cis820x_init(struct gfar_mii_info *mii_info)
-{
- phy_write(mii_info, MII_CIS8201_AUX_CONSTAT,
- MII_CIS8201_AUXCONSTAT_INIT);
- phy_write(mii_info, MII_CIS8201_EXT_CON1,
- MII_CIS8201_EXTCON1_INIT);
-
- return 0;
-}
-
-static int cis820x_ack_interrupt(struct gfar_mii_info *mii_info)
-{
- phy_read(mii_info, MII_CIS8201_ISTAT);
-
- return 0;
-}
-
-static int cis820x_config_intr(struct gfar_mii_info *mii_info)
-{
- if(mii_info->interrupts == MII_INTERRUPT_ENABLED)
- phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK);
- else
- phy_write(mii_info, MII_CIS8201_IMASK, 0);
-
- return 0;
-}
-
-#define DM9161_DELAY 10
-
-static int dm9161_read_status(struct gfar_mii_info *mii_info)
-{
- u16 status;
- int err;
-
- /* Update the link, but return if there
- * was an error */
- err = genmii_update_link(mii_info);
- if (err)
- return err;
-
- /* If the link is up, read the speed and duplex */
- /* If we aren't autonegotiating, assume speeds
- * are as set */
- if (mii_info->autoneg && mii_info->link) {
- status = phy_read(mii_info, MII_DM9161_SCSR);
- if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
- mii_info->speed = SPEED_100;
- else
- mii_info->speed = SPEED_10;
-
- if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F))
- mii_info->duplex = DUPLEX_FULL;
- else
- mii_info->duplex = DUPLEX_HALF;
- }
-
- return 0;
-}
-
-
-static int dm9161_config_aneg(struct gfar_mii_info *mii_info)
-{
- struct dm9161_private *priv = mii_info->priv;
-
- if(0 == priv->resetdone)
- return -EAGAIN;
-
- return 0;
-}
-
-static void dm9161_timer(unsigned long data)
-{
- struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data;
- struct dm9161_private *priv = mii_info->priv;
- u16 status = phy_read(mii_info, MII_BMSR);
-
- if (status & BMSR_ANEGCOMPLETE) {
- priv->resetdone = 1;
- } else
- mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
-}
-
-static int dm9161_init(struct gfar_mii_info *mii_info)
-{
- struct dm9161_private *priv;
-
- /* Allocate the private data structure */
- priv = kmalloc(sizeof(struct dm9161_private), GFP_KERNEL);
-
- if (NULL == priv)
- return -ENOMEM;
-
- mii_info->priv = priv;
-
- /* Reset is not done yet */
- priv->resetdone = 0;
-
- /* Isolate the PHY */
- phy_write(mii_info, MII_BMCR, BMCR_ISOLATE);
-
- /* Do not bypass the scrambler/descrambler */
- phy_write(mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
-
- /* Clear 10BTCSR to default */
- phy_write(mii_info, MII_DM9161_10BTCSR, MII_DM9161_10BTCSR_INIT);
-
- /* Reconnect the PHY, and enable Autonegotiation */
- phy_write(mii_info, MII_BMCR, BMCR_ANENABLE);
-
- /* Start a timer for DM9161_DELAY seconds to wait
- * for the PHY to be ready */
- init_timer(&priv->timer);
- priv->timer.function = &dm9161_timer;
- priv->timer.data = (unsigned long) mii_info;
- mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
-
- return 0;
-}
-
-static void dm9161_close(struct gfar_mii_info *mii_info)
-{
- struct dm9161_private *priv = mii_info->priv;
-
- del_timer_sync(&priv->timer);
- kfree(priv);
-}
-
-#if 0
-static int dm9161_ack_interrupt(struct gfar_mii_info *mii_info)
-{
- phy_read(mii_info, MII_DM9161_INTR);
-
- return 0;
-}
-#endif
-
-/* Cicada 820x */
-static struct phy_info phy_info_cis820x = {
- 0x000fc440,
- "Cicada Cis8204",
- 0x000fffc0,
- .features = MII_GBIT_FEATURES,
- .init = &cis820x_init,
- .config_aneg = &gbit_config_aneg,
- .read_status = &cis820x_read_status,
- .ack_interrupt = &cis820x_ack_interrupt,
- .config_intr = &cis820x_config_intr,
-};
-
-static struct phy_info phy_info_dm9161 = {
- .phy_id = 0x0181b880,
- .name = "Davicom DM9161E",
- .phy_id_mask = 0x0ffffff0,
- .init = dm9161_init,
- .config_aneg = dm9161_config_aneg,
- .read_status = dm9161_read_status,
- .close = dm9161_close,
-};
-
-static struct phy_info phy_info_marvell = {
- .phy_id = 0x01410c00,
- .phy_id_mask = 0xffffff00,
- .name = "Marvell 88E1101",
- .features = MII_GBIT_FEATURES,
- .config_aneg = &marvell_config_aneg,
- .read_status = &marvell_read_status,
- .ack_interrupt = &marvell_ack_interrupt,
- .config_intr = &marvell_config_intr,
-};
-
-static struct phy_info phy_info_genmii= {
- .phy_id = 0x00000000,
- .phy_id_mask = 0x00000000,
- .name = "Generic MII",
- .features = MII_BASIC_FEATURES,
- .config_aneg = genmii_config_aneg,
- .read_status = genmii_read_status,
-};
-
-static struct phy_info *phy_info[] = {
- &phy_info_cis820x,
- &phy_info_marvell,
- &phy_info_dm9161,
- &phy_info_genmii,
- NULL
-};
-
-u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum)
-{
- u16 retval;
- unsigned long flags;
-
- spin_lock_irqsave(&mii_info->mdio_lock, flags);
- retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum);
- spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
-
- return retval;
-}
-
-void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&mii_info->mdio_lock, flags);
- mii_info->mdio_write(mii_info->dev,
- mii_info->mii_id,
- regnum, val);
- spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
-}
-
-/* Use the PHY ID registers to determine what type of PHY is attached
- * to device dev. return a struct phy_info structure describing that PHY
- */
-struct phy_info * get_phy_info(struct gfar_mii_info *mii_info)
-{
- u16 phy_reg;
- u32 phy_ID;
- int i;
- struct phy_info *theInfo = NULL;
- struct net_device *dev = mii_info->dev;
-
- /* Grab the bits from PHYIR1, and put them in the upper half */
- phy_reg = phy_read(mii_info, MII_PHYSID1);
- phy_ID = (phy_reg & 0xffff) << 16;
-
- /* Grab the bits from PHYIR2, and put them in the lower half */
- phy_reg = phy_read(mii_info, MII_PHYSID2);
- phy_ID |= (phy_reg & 0xffff);
-
- /* loop through all the known PHY types, and find one that */
- /* matches the ID we read from the PHY. */
- for (i = 0; phy_info[i]; i++)
- if (phy_info[i]->phy_id ==
- (phy_ID & phy_info[i]->phy_id_mask)) {
- theInfo = phy_info[i];
- break;
- }
-
- /* This shouldn't happen, as we have generic PHY support */
- if (theInfo == NULL) {
- printk("%s: PHY id %x is not supported!\n", dev->name, phy_ID);
- return NULL;
- } else {
- printk("%s: PHY is %s (%x)\n", dev->name, theInfo->name,
- phy_ID);
- }
-
- return theInfo;
-}
diff -Nru a/drivers/net/gianfar_phy.h b/drivers/net/gianfar_phy.h
--- a/drivers/net/gianfar_phy.h 2005-03-25 14:47:21 -06:00
+++ /dev/null Wed Dec 31 16:00:00 196900
@@ -1,213 +0,0 @@
-/*
- * drivers/net/gianfar_phy.h
- *
- * Gianfar Ethernet Driver -- PHY handling
- * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
- * Based on 8260_io/fcc_enet.c
- *
- * Author: Andy Fleming
- * Maintainer: Kumar Gala (kumar.gala@freescale.com)
- *
- * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
- *
- * 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.
- *
- */
-#ifndef __GIANFAR_PHY_H
-#define __GIANFAR_PHY_H
-
-#define MII_end ((u32)-2)
-#define MII_read ((u32)-1)
-
-#define MIIMIND_BUSY 0x00000001
-#define MIIMIND_NOTVALID 0x00000004
-
-#define GFAR_AN_TIMEOUT 2000
-
-/* 1000BT control (Marvell & BCM54xx at least) */
-#define MII_1000BASETCONTROL 0x09
-#define MII_1000BASETCONTROL_FULLDUPLEXCAP 0x0200
-#define MII_1000BASETCONTROL_HALFDUPLEXCAP 0x0100
-
-/* Cicada Extended Control Register 1 */
-#define MII_CIS8201_EXT_CON1 0x17
-#define MII_CIS8201_EXTCON1_INIT 0x0000
-
-/* Cicada Interrupt Mask Register */
-#define MII_CIS8201_IMASK 0x19
-#define MII_CIS8201_IMASK_IEN 0x8000
-#define MII_CIS8201_IMASK_SPEED 0x4000
-#define MII_CIS8201_IMASK_LINK 0x2000
-#define MII_CIS8201_IMASK_DUPLEX 0x1000
-#define MII_CIS8201_IMASK_MASK 0xf000
-
-/* Cicada Interrupt Status Register */
-#define MII_CIS8201_ISTAT 0x1a
-#define MII_CIS8201_ISTAT_STATUS 0x8000
-#define MII_CIS8201_ISTAT_SPEED 0x4000
-#define MII_CIS8201_ISTAT_LINK 0x2000
-#define MII_CIS8201_ISTAT_DUPLEX 0x1000
-
-/* Cicada Auxiliary Control/Status Register */
-#define MII_CIS8201_AUX_CONSTAT 0x1c
-#define MII_CIS8201_AUXCONSTAT_INIT 0x0004
-#define MII_CIS8201_AUXCONSTAT_DUPLEX 0x0020
-#define MII_CIS8201_AUXCONSTAT_SPEED 0x0018
-#define MII_CIS8201_AUXCONSTAT_GBIT 0x0010
-#define MII_CIS8201_AUXCONSTAT_100 0x0008
-
-/* 88E1011 PHY Status Register */
-#define MII_M1011_PHY_SPEC_STATUS 0x11
-#define MII_M1011_PHY_SPEC_STATUS_1000 0x8000
-#define MII_M1011_PHY_SPEC_STATUS_100 0x4000
-#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK 0xc000
-#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX 0x2000
-#define MII_M1011_PHY_SPEC_STATUS_RESOLVED 0x0800
-#define MII_M1011_PHY_SPEC_STATUS_LINK 0x0400
-
-#define MII_M1011_IEVENT 0x13
-#define MII_M1011_IEVENT_CLEAR 0x0000
-
-#define MII_M1011_IMASK 0x12
-#define MII_M1011_IMASK_INIT 0x6400
-#define MII_M1011_IMASK_CLEAR 0x0000
-
-#define MII_DM9161_SCR 0x10
-#define MII_DM9161_SCR_INIT 0x0610
-
-/* DM9161 Specified Configuration and Status Register */
-#define MII_DM9161_SCSR 0x11
-#define MII_DM9161_SCSR_100F 0x8000
-#define MII_DM9161_SCSR_100H 0x4000
-#define MII_DM9161_SCSR_10F 0x2000
-#define MII_DM9161_SCSR_10H 0x1000
-
-/* DM9161 Interrupt Register */
-#define MII_DM9161_INTR 0x15
-#define MII_DM9161_INTR_PEND 0x8000
-#define MII_DM9161_INTR_DPLX_MASK 0x0800
-#define MII_DM9161_INTR_SPD_MASK 0x0400
-#define MII_DM9161_INTR_LINK_MASK 0x0200
-#define MII_DM9161_INTR_MASK 0x0100
-#define MII_DM9161_INTR_DPLX_CHANGE 0x0010
-#define MII_DM9161_INTR_SPD_CHANGE 0x0008
-#define MII_DM9161_INTR_LINK_CHANGE 0x0004
-#define MII_DM9161_INTR_INIT 0x0000
-#define MII_DM9161_INTR_STOP \
-(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \
- | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK)
-
-/* DM9161 10BT Configuration/Status */
-#define MII_DM9161_10BTCSR 0x12
-#define MII_DM9161_10BTCSR_INIT 0x7800
-
-#define MII_BASIC_FEATURES (SUPPORTED_10baseT_Half | \
- SUPPORTED_10baseT_Full | \
- SUPPORTED_100baseT_Half | \
- SUPPORTED_100baseT_Full | \
- SUPPORTED_Autoneg | \
- SUPPORTED_TP | \
- SUPPORTED_MII)
-
-#define MII_GBIT_FEATURES (MII_BASIC_FEATURES | \
- SUPPORTED_1000baseT_Half | \
- SUPPORTED_1000baseT_Full)
-
-#define MII_READ_COMMAND 0x00000001
-
-#define MII_INTERRUPT_DISABLED 0x0
-#define MII_INTERRUPT_ENABLED 0x1
-/* Taken from mii_if_info and sungem_phy.h */
-struct gfar_mii_info {
- /* Information about the PHY type */
- /* And management functions */
- struct phy_info *phyinfo;
-
- /* forced speed & duplex (no autoneg)
- * partner speed & duplex & pause (autoneg)
- */
- int speed;
- int duplex;
- int pause;
-
- /* The most recently read link state */
- int link;
-
- /* Enabled Interrupts */
- u32 interrupts;
-
- u32 advertising;
- int autoneg;
- int mii_id;
-
- /* private data pointer */
- /* For use by PHYs to maintain extra state */
- void *priv;
-
- /* Provided by host chip */
- struct net_device *dev;
-
- /* A lock to ensure that only one thing can read/write
- * the MDIO bus at a time */
- spinlock_t mdio_lock;
-
- /* Provided by ethernet driver */
- int (*mdio_read) (struct net_device *dev, int mii_id, int reg);
- void (*mdio_write) (struct net_device *dev, int mii_id, int reg, int val);
-};
-
-/* struct phy_info: a structure which defines attributes for a PHY
- *
- * id will contain a number which represents the PHY. During
- * startup, the driver will poll the PHY to find out what its
- * UID--as defined by registers 2 and 3--is. The 32-bit result
- * gotten from the PHY will be ANDed with phy_id_mask to
- * discard any bits which may change based on revision numbers
- * unimportant to functionality
- *
- * There are 6 commands which take a gfar_mii_info structure.
- * Each PHY must declare config_aneg, and read_status.
- */
-struct phy_info {
- u32 phy_id;
- char *name;
- unsigned int phy_id_mask;
- u32 features;
-
- /* Called to initialize the PHY */
- int (*init)(struct gfar_mii_info *mii_info);
-
- /* Called to suspend the PHY for power */
- int (*suspend)(struct gfar_mii_info *mii_info);
-
- /* Reconfigures autonegotiation (or disables it) */
- int (*config_aneg)(struct gfar_mii_info *mii_info);
-
- /* Determines the negotiated speed and duplex */
- int (*read_status)(struct gfar_mii_info *mii_info);
-
- /* Clears any pending interrupts */
- int (*ack_interrupt)(struct gfar_mii_info *mii_info);
-
- /* Enables or disables interrupts */
- int (*config_intr)(struct gfar_mii_info *mii_info);
-
- /* Clears up any memory if needed */
- void (*close)(struct gfar_mii_info *mii_info);
-};
-
-struct phy_info *get_phy_info(struct gfar_mii_info *mii_info);
-int read_phy_reg(struct net_device *dev, int mii_id, int regnum);
-void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value);
-void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info);
-void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts);
-
-struct dm9161_private {
- struct timer_list timer;
- int resetdone;
-};
-
-#endif /* GIANFAR_PHY_H */
^ permalink raw reply
* why is entire 8xx architecture defined as "broken"?
From: Robert P. J. Day @ 2005-03-25 22:41 UTC (permalink / raw)
To: Embedded PPC Linux list
after i looked at the Kconfig setup for 2.6.11-5, i'm a bit puzzled
-- why is the entire 8xx architecture defined as "BROKEN"? follow the
logic along:
arch/ppc/Kconfig:
config 8xx
depends on BROKEN
bool "8xx"
and what means "BROKEN"?
init/Kconfig:
config BROKEN
bool
depends on !CLEAN_COMPILE
default y
ok, and "CLEAN_COMPILE"? defined just above that:
config CLEAN_COMPILE
bool "Select only drivers expected to compile cleanly" if
EXPERIMENTAL
default y
ok, and "EXPERIMENTAL"?
config EXPERIMENTAL
bool "Prompt for development and/or incomplete code/drivers"
and *that* refers to the top-level menu entry regarding whether you
want to take a chance on "development and/or incomplete code/drivers",
not entire architectures.
the above seems just a tad misleading, no?
rday
^ permalink raw reply
* Re: [PATCH] ppc32/64: Map prefetchable PCI without guarded bit
From: Benjamin Herrenschmidt @ 2005-03-25 22:26 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: Andrew Morton, linuxppc-dev list, Linux Kernel list
In-Reply-To: <6ab08e99eb9f0823f7f7fb12e728e90d@kernel.crashing.org>
On Thu, 2005-03-24 at 19:20 +0100, Segher Boessenkool wrote:
> > While experimenting with framebuffer access performances, we noticed a
> > very significant improvement in write access to it when not setting
> > the "guarded" bit on the MMU mappings. This bit basically says that
> > reads and writes won't have side effects (it allows speculation).
>
> Unless the data is already in cache.
>
> > It appears that it also disables write combining.
>
> When the page is also cache-inhibited, it indeed does.
>
>
> Btw, did you ever get to fix the problem with mapping the last page
> of physical address space via /dev/mem ?
I don't think so, but I'll have to double check.
Ben.
^ permalink raw reply
* Re: [PATCH] ppc32/64: Map prefetchable PCI without guarded bit
From: Benjamin Herrenschmidt @ 2005-03-25 22:23 UTC (permalink / raw)
To: Jesse Barnes; +Cc: Andrew Morton, linuxppc-dev list, Linux Kernel list
In-Reply-To: <200503240854.45741.jbarnes@engr.sgi.com>
On Thu, 2005-03-24 at 08:54 -0800, Jesse Barnes wrote:
> On Wednesday, March 23, 2005 10:24 pm, Benjamin Herrenschmidt wrote:
> > While experimenting with framebuffer access performances, we noticed a
> > very significant improvement in write access to it when not setting
> > the "guarded" bit on the MMU mappings. This bit basically says that
> > reads and writes won't have side effects (it allows speculation). It
> > appears that it also disables write combining.
>
> Doesn't pgprot_writecombine imply non-guarded, so can't you use it instead?
> Either way, you'll probably want to fix fbmem.c as well and turn off
> _PAGE_GUARDED?
I'm not sure we implement pgprot_writecombine. But anyway, that wouldn't
help as X uses /dev/mem which doesn't use that, and sysfs new mmap
interface doesn't have anything for setting writecombine.
The interface I propose could be made generic, that is the whole point.
It's basically a mean for the arch to say "heh, somebody wants to map
this bit of physical address space, what pgprot should I use" :) The
decision of wether to do uncacheable or writecombine, all the
page_in_ram() trickery in /dev/mem or fbmem can be moved to arch
specific routines and cleanup the generic stuff.
> Maybe it's time for a more generic call to support this stuff, both for
> in-kernel mappings and ones that we export to userspace.
Yah, in-kernel mappings aren't covered yet, as my interface supposes a
"struct file" but then, I don't use the struct file argument in my ppc
implementation (I exposed it for the sake of archs that may want it). We
could just define that in-kernel mappings can call this with NULL for
struct file.
Ben.
^ permalink raw reply
* Re: still not clear on which tree to be using these days
From: Robert P. J. Day @ 2005-03-25 22:11 UTC (permalink / raw)
To: Dan Malek; +Cc: Embedded PPC Linux list
In-Reply-To: <3787fed579cbb8849677a0baa10e0ee4@embeddededge.com>
On Fri, 25 Mar 2005, Dan Malek wrote:
>
> On Mar 25, 2005, at 4:19 PM, Robert P. J. Day wrote:
>
> > what is the proper tree to be using these days for a 2.6 kernel
> > on 8xx? for the longest time, i've used the "bk" checkout from
> > bkbits.net, but i see others now working with what looks like the
> > latest stock 2.6.x release.
>
> I just use the latest kernel.org tree for everything. If I'm
> submitting a patch, or working with someone else, I use the bk tree
> just to be that little more up to date.
i just downloaded the 2.6.11-5 kernel source and was a bit nonplussed
to discover that "8xx" wasn't in the list of choices for processor,
until i noticed in the Kconfig file that 8xx depends on "BROKEN". oh,
my. :-) live and learn.
rday
^ permalink raw reply
* Re: still not clear on which tree to be using these days
From: Dan Malek @ 2005-03-25 21:52 UTC (permalink / raw)
To: Robert P. J. Day; +Cc: Embedded PPC Linux list
In-Reply-To: <Pine.LNX.4.61.0503251617100.15647@localhost.localdomain>
On Mar 25, 2005, at 4:19 PM, Robert P. J. Day wrote:
> what is the proper tree to be using these days for a 2.6 kernel on
> 8xx? for the longest time, i've used the "bk" checkout from
> bkbits.net, but i see others now working with what looks like the
> latest stock 2.6.x release.
I just use the latest kernel.org tree for everything. If I'm submitting
a patch, or working with someone else, I use the bk tree just to
be that little more up to date.
-- Dan
^ permalink raw reply
* still not clear on which tree to be using these days
From: Robert P. J. Day @ 2005-03-25 21:19 UTC (permalink / raw)
To: Embedded PPC Linux list
what is the proper tree to be using these days for a 2.6 kernel on
8xx? for the longest time, i've used the "bk" checkout from
bkbits.net, but i see others now working with what looks like the
latest stock 2.6.x release.
what's the status on patches that were submitted against the bk
tree? have they been pushed upstream? etc, etc.
rday
^ permalink raw reply
* Re: Question regarding Interrupt "delivery" to user mode process
From: Eugene Surovegin @ 2005-03-25 20:37 UTC (permalink / raw)
To: Tolunay Orkun; +Cc: linuxppc-embedded
In-Reply-To: <42446F00.90000@orkun.us>
On Fri, Mar 25, 2005 at 02:05:20PM -0600, Tolunay Orkun wrote:
> This would not be a problem for level triggered interrupts if
> enable_irq() cleared the pending IRQ bit before re-enabling the
> interrupt system if that particular interrupt was level triggered.
>
> If there is a valid request still pending (i.e. external IRQ line is
> still asserted at the appropriate level) this would not cause loss of
> interrupt but in case there is no requester (i.e. all interrupts are
> properly acknowledged), the spurious interrupt due to delayed processing
> would be avoided.
Hmm, I think I agree with you. Let me think a little more and I'll
probably add this additional ACK to 4xx PIC code.
Only thing which bothers me is that such hack will be 4xx specific, as
none of PIC handlers I looked at (in arch/ppc) do this. So, I'm not
quite sure it worth adding at all. After all, the way you use
enable_irq/disable_irq isn't quite standard anyway :).
--
Eugene
^ permalink raw reply
* Re: Question regarding Interrupt "delivery" to user mode process
From: Tolunay Orkun @ 2005-03-25 20:05 UTC (permalink / raw)
Cc: linuxppc-embedded
In-Reply-To: <424469C2.2070906@orkun.us>
Eugene,
>> There is a quirk for PPC405 however: Linux (2.4) calls ack_irq()
>> before branching to the IRQ handler. However, if irq is level
>> triggered and external interrupt source has not yet deasserted, the
>> interrupt status bit in interrupt status register will remain set! To
>> avoid spurious interrupt it is necessary to call ack_irq() again
>> before enabling the interrupts again. I had discussed this in the old
>> linuxppc-embedded list while I was doing this driver.
>>
>
>
> This isn't 405 specific. This problem will exist on any system with
> level-sensitive IRQ source which wasn't ACK'ed. ACK'ed here means
> acknowledgment in device itself, not in PIC.
This would not be a problem for level triggered interrupts if
enable_irq() cleared the pending IRQ bit before re-enabling the
interrupt system if that particular interrupt was level triggered.
If there is a valid request still pending (i.e. external IRQ line is
still asserted at the appropriate level) this would not cause loss of
interrupt but in case there is no requester (i.e. all interrupts are
properly acknowledged), the spurious interrupt due to delayed processing
would be avoided.
Tolunay
^ permalink raw reply
* Re: Question regarding Interrupt "delivery" to user mode process
From: Tolunay Orkun @ 2005-03-25 19:42 UTC (permalink / raw)
To: Eugene Surovegin; +Cc: linuxppc-embedded
In-Reply-To: <20050325183126.GA2539@gate.ebshome.net>
Eugene Surovegin wrote:
>On Fri, Mar 25, 2005 at 11:40:16AM -0600, Tolunay Orkun wrote:
>
>[snip]
>
>
>
>>There is a quirk for PPC405 however: Linux (2.4) calls ack_irq() before
>>branching to the IRQ handler. However, if irq is level triggered and
>>external interrupt source has not yet deasserted, the interrupt status
>>bit in interrupt status register will remain set! To avoid spurious
>>interrupt it is necessary to call ack_irq() again before enabling the
>>interrupts again. I had discussed this in the old linuxppc-embedded list
>>while I was doing this driver.
>>
>>
>
>This isn't 405 specific. This problem will exist on any system with
>level-sensitive IRQ source which wasn't ACK'ed. ACK'ed here means
>acknowledgment in device itself, not in PIC.
>
>This is why this user-space IRQ handling is a bad idea, IMHO. You have
>to ACK IRQ (in device itself) in kernel-IRQ handler.
>
>--
>Eugene
>
>
Well, ACK'ing the IRQ in the kernel IRQ handler was impractical for us
because you have to communicate using I2C (sloooow) and multiple devices
of the same types is hooked to the same IRQ so we need to poll them to
see which one has actually generated the the IRQ. That means many Nx I2C
reads and 1x I2C write. Furthermore, N is a variable as I2C devices are
hot plugged or removed from the bus so when nobody claims ownership we
need to probe for new instance of device. Ugly but much better than
purely polled operation...
Best regards,
Tolunay
^ permalink raw reply
* Re: Question regarding Interrupt "delivery" to user mode process
From: Eugene Surovegin @ 2005-03-25 18:31 UTC (permalink / raw)
To: Tolunay Orkun; +Cc: linuxppc-embedded
In-Reply-To: <42444D00.80401@orkun.us>
On Fri, Mar 25, 2005 at 11:40:16AM -0600, Tolunay Orkun wrote:
[snip]
> There is a quirk for PPC405 however: Linux (2.4) calls ack_irq() before
> branching to the IRQ handler. However, if irq is level triggered and
> external interrupt source has not yet deasserted, the interrupt status
> bit in interrupt status register will remain set! To avoid spurious
> interrupt it is necessary to call ack_irq() again before enabling the
> interrupts again. I had discussed this in the old linuxppc-embedded list
> while I was doing this driver.
This isn't 405 specific. This problem will exist on any system with
level-sensitive IRQ source which wasn't ACK'ed. ACK'ed here means
acknowledgment in device itself, not in PIC.
This is why this user-space IRQ handling is a bad idea, IMHO. You have
to ACK IRQ (in device itself) in kernel-IRQ handler.
--
Eugene
^ permalink raw reply
* Re: Question regarding Interrupt "delivery" to user mode process
From: Tolunay Orkun @ 2005-03-25 17:40 UTC (permalink / raw)
To: Caruso, Nick; +Cc: linuxppc-embedded
In-Reply-To: <712A2DEC228C7448978CBD7A7AD5B090012EE448@fever.wardrobe.irobot.com>
Dear Nick,
Caruso, Nick wrote:
> Note that "delivery" is in quotes - I don't mean to actually deliver an
> interrupt, but rather to wake the process when the interrupt occurs.
>
> This is a broad question, but I'm hoping someone out there with real
> experience in this area can comment on a design idea we're kicking
> around.
> If there's a better mailing list for asking this type of question,
> please tell me!
>
> We are building a device with an MPC5200 processor which needs to detect
> incoming pulses at a 13 mSec rate. We've got this incoming pulse wired
> to an IRQ on the MPC5200 and we now need a method for detecting these
> interrupts in a user mode process.
>
> The design we're contemplating is a small character device driver in the
> kernel that will allow a user mode process to perform a blocking read on
> a file descriptor, and return from the read call whenever an interrupt
> occurs.
I have done a similar char device driver in 2.4 kernel on a PPC405GP
board. The driver receives the interrupt but does not enable the
interrupt. However, it releases the user mode application waiting on
"select" call (could be "poll" as well) from the /dev/device. Once the
user application processes the interrupt, it performs an ioctl to the
device driver to re-enable the interrupt.
We do not have hard timing issues like you have. I think 13mSec rate is
pretty problematic for handling the interrupts consistently from a user
mode application like I did. But, you can try. It is pretty easy to do.
There is a quirk for PPC405 however: Linux (2.4) calls ack_irq() before
branching to the IRQ handler. However, if irq is level triggered and
external interrupt source has not yet deasserted, the interrupt status
bit in interrupt status register will remain set! To avoid spurious
interrupt it is necessary to call ack_irq() again before enabling the
interrupts again. I had discussed this in the old linuxppc-embedded list
while I was doing this driver.
> We're not concerned (for the moment) with missing interrupts - we think
> we can service them fast enough (we just need to record a
> chronometer-type timestamp for some other incoming (serial) data).
>
> Does this sound like a workable approach? Does anyone know of a better
> way? My implementation plan is to derive something from the 3rd edition
> Linux Device Drivers book "scull-pipe" device driver.
>
> Any comments or suggestions would be greatly appreciated.
>
> thanks and best regards,
> Nick Caruso
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
^ permalink raw reply
* RE: Question regarding Interrupt "delivery" to user mode process
From: Stephen Warren @ 2005-03-25 17:19 UTC (permalink / raw)
To: Caruso, Nick, linuxppc-embedded
This is certainly do-able.
Take a look at the Gelato project - they actually are able to do whole
user-mode device drivers for PCI. You can probably snag some of their
kernel->user-mode IRQ notification code for what you want.
http://www.gelato.unsw.edu.au/IA64wiki/UserLevelDrivers=20
--=20
Stephen Warren, Software Engineer, NVIDIA, Fort Collins, CO
swarren@nvidia.com http://www.nvidia.com/
swarren@wwwdotorg.org http://www.wwwdotorg.org/pgp.html
^ permalink raw reply
* Question regarding Interrupt "delivery" to user mode process
From: Caruso, Nick @ 2005-03-25 16:58 UTC (permalink / raw)
To: linuxppc-embedded
Note that "delivery" is in quotes - I don't mean to actually deliver an
interrupt, but rather to wake the process when the interrupt occurs.
This is a broad question, but I'm hoping someone out there with real
experience in this area can comment on a design idea we're kicking
around.
If there's a better mailing list for asking this type of question,
please tell me!
We are building a device with an MPC5200 processor which needs to detect
incoming pulses at a 13 mSec rate. We've got this incoming pulse wired
to an IRQ on the MPC5200 and we now need a method for detecting these
interrupts in a user mode process.
The design we're contemplating is a small character device driver in the
kernel that will allow a user mode process to perform a blocking read on
a file descriptor, and return from the read call whenever an interrupt
occurs. =20
We're not concerned (for the moment) with missing interrupts - we think
we can service them fast enough (we just need to record a
chronometer-type timestamp for some other incoming (serial) data).
Does this sound like a workable approach? Does anyone know of a better
way? My implementation plan is to derive something from the 3rd edition
Linux Device Drivers book "scull-pipe" device driver.
Any comments or suggestions would be greatly appreciated.
thanks and best regards,
Nick Caruso
^ permalink raw reply
* RE: MPC5200 IDE DMA and Machine checks due to TEA
From: Stephen Warren @ 2005-03-25 16:35 UTC (permalink / raw)
To: linuxppc-embedded
I wrote:
> Does anyone have IDE DMA really working on the MPC5200...
> ...
> The reason I ask is that we keep on getting machine check
> exceptions with DMA enabled.
Incidentally, if anyone thinks they are able to do consulting on this
with a good chance of finding out the problem (timescale is short:-( )
then we're willing to discuss payment.
--=20
Stephen Warren, Software Engineer, NVIDIA, Fort Collins, CO
swarren@nvidia.com http://www.nvidia.com/
swarren@wwwdotorg.org http://www.wwwdotorg.org/pgp.html
^ permalink raw reply
* Re: [PATCH 4/6] ppc32: Add platform bus / ppc_sys model to Freescale MPC52xx
From: Kumar Gala @ 2005-03-25 15:15 UTC (permalink / raw)
To: Sylvain Munaut; +Cc: ML linuxppc-embedded
In-Reply-To: <4.20050322_000905.tnt@patchsend.246tNt.com>
One question, do you really need #defines for the device offsets in=20
mpc52xx_devices.c ? Are these used anywhere else?
- kumar
On Mar 21, 2005, at 5:08 PM, Sylvain Munaut wrote:
> ppc32: Add platform bus / ppc_sys model to Freescale MPC52xx
>
> This patch makes all platform based around the Freescale MPC52xx use
> the platform bus and more precisly the ppc_sys model put in
> place by Kumar Gala.
>
>
>
> Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
[ snip ]
> diff -Nru a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
> --- a/arch/ppc/syslib/Makefile=A0 2005-03-21 20:10:34 +01:00
> +++ b/arch/ppc/syslib/Makefile=A0 2005-03-21 20:10:34 +01:00
> @@ -106,7 +106,8 @@
> =A0obj-$(CONFIG_PCI)=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 +=3D =
indirect_pci.o pci_auto.o
> =A0endif
> =A0obj-$(CONFIG_MPC8555_CDS)=A0=A0=A0=A0=A0 +=3D todc_time.o
> -obj-$(CONFIG_PPC_MPC52xx)=A0=A0=A0=A0=A0 +=3D mpc52xx_setup.o =
mpc52xx_pic.o
> +obj-$(CONFIG_PPC_MPC52xx)=A0=A0=A0=A0=A0 +=3D mpc52xx_setup.o =
mpc52xx_pic.o \
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 mpc52xx_sys.o=20
> mpc52xx_devices.o ppc_sys.o
> =A0ifeq ($(CONFIG_PPC_MPC52xx),y)
> =A0obj-$(CONFIG_PCI)=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 +=3D =
mpc52xx_pci.o
> =A0endif
> diff -Nru a/arch/ppc/syslib/mpc52xx_devices.c=20
> b/arch/ppc/syslib/mpc52xx_devices.c
> --- /dev/null=A0=A0 Wed Dec 31 16:00:00 196900
> +++ b/arch/ppc/syslib/mpc52xx_devices.c 2005-03-21 20:10:34 +01:00
> @@ -0,0 +1,333 @@
> +/*
> + * arch/ppc/syslib/mpc52xx_devices.c
> + *
> + * Freescale MPC52xx device descriptions
> + *
> + *
> + * Maintainer : Sylvain Munaut <tnt@246tNt.com>
> + *
> + * Copyright (C) 2005 Sylvain Munaut <tnt@246tNt.com>
> + *
> + * This file is licensed under the terms of the GNU General Public=20=
> License
> + * version 2. This program is licensed "as is" without any warranty=20=
> of any
> + * kind, whether express or implied.
> + */
> +
> +#include <linux/fsl_devices.h>
> +#include <linux/resource.h>
> +#include <asm/mpc52xx.h>
> +#include <asm/ppc_sys.h>
> +
> +
> +static u64 mpc52xx_dma_mask =3D 0xffffffffULL;
> +
> +static struct fsl_i2c_platform_data mpc52xx_fsl_i2c_pdata =3D {
> +=A0=A0=A0=A0=A0=A0 .device_flags =3D FSL_I2C_DEV_CLOCK_5200,
> +};
> +
> +
> +/* We use relative offsets for IORESOURCE_MEM to be independent from=20=
> the
> + * MBAR location at compile time
> + */
> +
> +/* TODO Add the BestComm initiator channel to the device =
definitions,
> +=A0=A0 possibly using IORESOURCE_DMA. But that's when BestComm is =
ready=20
> ... */
> +
> +struct platform_device ppc_sys_platform_devices[] =3D {
> +=A0=A0=A0=A0=A0=A0 [MPC52xx_MSCAN1] =3D {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .name=A0=A0 =A0=A0=A0=A0=A0=A0=
=A0 =3D "mpc52xx-mscan",
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .id=A0=A0=A0=A0 =A0=A0=A0=A0=A0=
=A0=A0 =3D 0,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .num_resources=A0 =3D 2,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .resource =3D (struct =
resource[]) {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_MSCAN1_OFFSET,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_MSCAN1_OFFSET +
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
MPC52xx_MSCAN_SIZE -=20
> 1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_MEM,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_MSCAN1_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_MSCAN1_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 [MPC52xx_MSCAN2] =3D {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .name=A0=A0 =A0=A0=A0=A0=A0=A0=
=A0 =3D "mpc52xx-mscan",
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .id=A0=A0=A0=A0 =A0=A0=A0=A0=A0=
=A0=A0 =3D 1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .num_resources=A0 =3D 2,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .resource =3D (struct =
resource[]) {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_MSCAN2_OFFSET,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_MSCAN2_OFFSET +
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
MPC52xx_MSCAN_SIZE -=20
> 1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_MEM,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_MSCAN2_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_MSCAN2_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 [MPC52xx_SPI] =3D {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .name=A0=A0 =A0=A0=A0=A0=A0=A0=
=A0 =3D "mpc52xx-spi",
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .id=A0=A0=A0=A0 =A0=A0=A0=A0=A0=
=A0=A0 =3D -1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .num_resources=A0 =3D 3,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .resource=A0=A0=A0=A0=A0=A0 =
=3D (struct resource[]) {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_SPI_OFFSET,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_SPI_OFFSET +
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
MPC52xx_SPI_SIZE - 1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_MEM,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .name=A0=A0 =3D "modf",
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_SPI_MODF_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_SPI_MODF_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .name=A0=A0 =3D "spif",
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_SPI_SPIF_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_SPI_SPIF_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 [MPC52xx_USB] =3D {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .name=A0=A0 =A0=A0=A0=A0=A0=A0=
=A0 =3D "ppc-soc-ohci",
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .id=A0=A0=A0=A0 =A0=A0=A0=A0=A0=
=A0=A0 =3D -1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .num_resources=A0 =3D 2,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .dev.dma_mask=A0=A0 =3D =
&mpc52xx_dma_mask,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .dev.coherent_dma_mask =3D =
0xffffffffULL,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .resource=A0=A0=A0=A0=A0=A0 =
=3D (struct resource[]) {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_USB_OFFSET,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_USB_OFFSET +
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
MPC52xx_USB_SIZE - 1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_MEM,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_USB_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_USB_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 [MPC52xx_BDLC] =3D {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .name=A0=A0 =A0=A0=A0=A0=A0=A0=
=A0 =3D "mpc52xx-bdlc",
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .id=A0=A0=A0=A0 =A0=A0=A0=A0=A0=
=A0=A0 =3D -1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .num_resources=A0 =3D 2,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .resource=A0=A0=A0=A0=A0=A0 =
=3D (struct resource[]) {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_BDLC_OFFSET,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_BDLC_OFFSET +
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
MPC52xx_BDLC_SIZE - 1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_MEM,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_BDLC_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_BDLC_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 [MPC52xx_PSC1] =3D {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .name=A0=A0 =A0=A0=A0=A0=A0=A0=
=A0 =3D "mpc52xx-psc",
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .id=A0=A0=A0=A0 =A0=A0=A0=A0=A0=
=A0=A0 =3D 0,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .num_resources=A0 =3D 2,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .resource=A0=A0=A0=A0=A0=A0 =
=3D (struct resource[]) {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_PSC1_OFFSET,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_PSC1_OFFSET +
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
MPC52xx_PSC_SIZE - 1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_MEM,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_PSC1_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_PSC1_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 [MPC52xx_PSC2] =3D {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .name=A0=A0 =A0=A0=A0=A0=A0=A0=
=A0 =3D "mpc52xx-psc",
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .id=A0=A0=A0=A0 =A0=A0=A0=A0=A0=
=A0=A0 =3D 1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .num_resources=A0 =3D 2,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .resource=A0=A0=A0=A0=A0=A0 =
=3D (struct resource[]) {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_PSC2_OFFSET,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_PSC2_OFFSET +
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
MPC52xx_PSC_SIZE - 1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_MEM,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_PSC2_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_PSC2_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 [MPC52xx_PSC3] =3D {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .name=A0=A0 =A0=A0=A0=A0=A0=A0=
=A0 =3D "mpc52xx-psc",
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .id=A0=A0=A0=A0 =A0=A0=A0=A0=A0=
=A0=A0 =3D 2,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .num_resources=A0 =3D 2,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .resource=A0=A0=A0=A0=A0=A0 =
=3D (struct resource[]) {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_PSC3_OFFSET,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_PSC3_OFFSET +
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
MPC52xx_PSC_SIZE - 1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_MEM,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_PSC3_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_PSC3_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 [MPC52xx_PSC4] =3D {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .name=A0=A0 =A0=A0=A0=A0=A0=A0=
=A0 =3D "mpc52xx-psc",
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .id=A0=A0=A0=A0 =A0=A0=A0=A0=A0=
=A0=A0 =3D 3,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .num_resources=A0 =3D 2,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .resource=A0=A0=A0=A0=A0=A0 =
=3D (struct resource[]) {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_PSC4_OFFSET,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_PSC4_OFFSET +
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
MPC52xx_PSC_SIZE - 1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_MEM,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_PSC4_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_PSC4_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 [MPC52xx_PSC5] =3D {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .name=A0=A0 =A0=A0=A0=A0=A0=A0=
=A0 =3D "mpc52xx-psc",
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .id=A0=A0=A0=A0 =A0=A0=A0=A0=A0=
=A0=A0 =3D 4,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .num_resources=A0 =3D 2,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .resource=A0=A0=A0=A0=A0=A0 =
=3D (struct resource[]) {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_PSC5_OFFSET,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_PSC5_OFFSET +
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
MPC52xx_PSC_SIZE - 1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_MEM,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_PSC5_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_PSC5_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 [MPC52xx_PSC6] =3D {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .name=A0=A0 =A0=A0=A0=A0=A0=A0=
=A0 =3D "mpc52xx-psc",
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .id=A0=A0=A0=A0 =A0=A0=A0=A0=A0=
=A0=A0 =3D 5,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .num_resources=A0 =3D 2,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .resource=A0=A0=A0=A0=A0=A0 =
=3D (struct resource[]) {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_PSC6_OFFSET,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_PSC6_OFFSET +
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
MPC52xx_PSC_SIZE - 1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_MEM,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_PSC6_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_PSC6_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 [MPC52xx_FEC] =3D {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .name=A0=A0 =A0=A0=A0=A0=A0=A0=
=A0 =3D "mpc52xx-fec",
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .id=A0=A0=A0=A0 =A0=A0=A0=A0=A0=
=A0=A0 =3D -1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .num_resources=A0 =3D 2,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .resource=A0=A0=A0=A0=A0=A0 =
=3D (struct resource[]) {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_FEC_OFFSET,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_FEC_OFFSET +
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
MPC52xx_FEC_SIZE - 1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_MEM,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_FEC_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_FEC_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 [MPC52xx_ATA] =3D {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .name=A0=A0 =A0=A0=A0=A0=A0=A0=
=A0 =3D "mpc52xx-ata",
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .id=A0=A0=A0=A0 =A0=A0=A0=A0=A0=
=A0=A0 =3D -1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .num_resources=A0 =3D 2,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .resource=A0=A0=A0=A0=A0=A0 =
=3D (struct resource[]) {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_ATA_OFFSET,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_ATA_OFFSET +
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
MPC52xx_ATA_SIZE - 1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_MEM,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_ATA_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_ATA_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 [MPC52xx_I2C1] =3D {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .name=A0=A0 =A0=A0=A0=A0=A0=A0=
=A0 =3D "fsl-i2c",
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .id=A0=A0=A0=A0 =A0=A0=A0=A0=A0=
=A0=A0 =3D 0,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .dev.platform_data =3D =
&mpc52xx_fsl_i2c_pdata,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .num_resources=A0 =3D 2,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .resource=A0=A0=A0=A0=A0=A0 =
=3D (struct resource[]) {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_I2C1_OFFSET,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_I2C1_OFFSET +
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
MPC52xx_I2C_SIZE - 1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_MEM,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_I2C1_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_I2C1_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 [MPC52xx_I2C2] =3D {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .name=A0=A0 =A0=A0=A0=A0=A0=A0=
=A0 =3D "fsl-i2c",
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .id=A0=A0=A0=A0 =A0=A0=A0=A0=A0=
=A0=A0 =3D 1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .dev.platform_data =3D =
&mpc52xx_fsl_i2c_pdata,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .num_resources=A0 =3D 2,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 .resource=A0=A0=A0=A0=A0=A0 =
=3D (struct resource[]) {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_I2C2_OFFSET,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_I2C2_OFFSET +
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
MPC52xx_I2C_SIZE - 1,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_MEM,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 {
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .start=A0 =3D MPC52xx_I2C2_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .end=A0=A0=A0 =3D MPC52xx_I2C2_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 .flags=A0 =3D IORESOURCE_IRQ,
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 },
> +=A0=A0=A0=A0=A0=A0 },
> +};
> +
> +
> +static int __init mach_mpc52xx_fixup(struct platform_device *pdev)
> +{
> +=A0=A0=A0=A0=A0=A0 ppc_sys_fixup_mem_resource(pdev, MPC52xx_MBAR);
> +=A0=A0=A0=A0=A0=A0 return 0;
> +}
> +
> +static int __init mach_mpc52xx_init(void)
> +{
> +=A0=A0=A0=A0=A0=A0 ppc_sys_device_fixup =3D mach_mpc52xx_fixup;
> +=A0=A0=A0=A0=A0=A0 return 0;
> +}
> +
> +postcore_initcall(mach_mpc52xx_init);
^ permalink raw reply
* Re: PCI support under 2.6.11.4 on MPC8272ADS ???
From: Andrey Volkov @ 2005-03-25 14:32 UTC (permalink / raw)
To: Vitaly Bordug; +Cc: linuxppc-embedded
In-Reply-To: <42441B13.7080703@ru.mvista.com>
Hi Vitaly
Same bug, as I describe early ( for MPC5200 )
+ /* Enable PCI */
+ immap->im_pci.pci_gcr = cpu_to_le32(PCIGCR_PCI_BUS_EN);
+ {
+ /* give it some time */
+ int i;
+ for(i=0;i<100;i++)
+ udelay(100);
+ }
Delay must be up to 1 sec (if you follow PCI standart :), not 10 msec.
--
Regards
Andrey Volkov
Vitaly Bordug wrote:
> Hi Walt,
>
> Well, the incorrect VendorID almost clearly points to the incompatible
> PCI bus frequency - try to set it to 33Mhz.
> AFAIR, I saw my network card as video adapter in the lspci output.
>
> The 2.4 stuff was tested rather thoroughly. The current 2.6.11 support
> is examined with HPT370 and PDC20268 PCI IDE.
>
> You may also try my latest patch to the stock linux 2.5.
>
> Wimer, Walt wrote:
>
>>Using Vitaly's 2.4-based patch below as a starting point, I've been
>>adding PCI support to 2.6.11.4 for the MPC8272ADS board.
>>
>>The good news is that I think I have PCI interrupts pretty well sorted
>>out, and I see *something* half-way reasonable from "lspci".
>>
>>The bad news is that neither of the ethernet cards that I'm trying will
>>actually work, and I see some very weird behavior with PCI configuration
>>space:
>>
>> Card 1: Some Realtek RTL8139D-based card
>> Card 2: NETGEAR FA311 (National Semi DP83815 chip)
>>
>>With either card installed alone, both U-Boot and my kernel identify the
>>cards correctly in PCI configuration space.
>>
>>With *both* cards installed, both U-Boot and my kernel see the Realtek-
>>based card correctly, but the NETGEAR card has a corrupted Vendor ID
>>(e.g. 0x1000 or 0x1003 instead of the correct 0x100b). This happens
>>regardless of which PCI slots I use for the cards (I've tried virtually
>>every combination). This smells of a power problem or something to me.
>>
>>And again, even with either card alone, the drivers have serious
>>problems talking to the cards. I get various error messages from
>>the drivers and I see badly mangled packets on the wire. It's also
>>not uncommon for the whole system to freeze...
>>
>>Has anyone else seen similar behavior?
>>
>>Has anyone had success with PCI on this board (under any kernel
>>version)?
>>
>>
>>Any ideas / data points are appreciated.
>>
>>
>>Thanks!!!
>>
>>Walt Wimer
>>
>>
>>
>>
>>
>>>This patch adds PCI bridge support for MPC8272 and PQ2FADS to the
>>>current linuxppc-2.4 tree. Actually it has been tested with 8272, but
>>>PQ2 _should_ also work, though it will complain that host bridge ID is
>>>unrecognized.
>>>
>>>Signed-off-by: Vitaly Bordug <vbordug at ru.mvista.com>
>>>
>>>--
>>>Sincerely, Vitaly
>>>
>>>-------------- next part --------------
>>>A non-text attachment was scrubbed...
>>>Name: pq2-pci.patch
>>>Type: text/x-patch
>>>Size: 20111 bytes
>>>Desc: not available
>>>Url : http://ozlabs.org/pipermail/linuxppc-embedded/attachments/20050218/12060ce8/pq2-pci.bin
>>>
>>>
>>
>>
>>
>>
>
> --
> Sincerely,
> Vitaly
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
^ permalink raw reply
* Re: PCI support under 2.6.11.4 on MPC8272ADS ???
From: Vitaly Bordug @ 2005-03-25 14:07 UTC (permalink / raw)
To: Wimer, Walt; +Cc: linuxppc-embedded
In-Reply-To: <1111705036.15834.29.camel@excalibur.timesys.com>
[-- Attachment #1: Type: text/plain, Size: 2483 bytes --]
Hi Walt,
Well, the incorrect VendorID almost clearly points to the incompatible
PCI bus frequency - try to set it to 33Mhz.
AFAIR, I saw my network card as video adapter in the lspci output.
The 2.4 stuff was tested rather thoroughly. The current 2.6.11 support
is examined with HPT370 and PDC20268 PCI IDE.
You may also try my latest patch to the stock linux 2.5.
Wimer, Walt wrote:
>Using Vitaly's 2.4-based patch below as a starting point, I've been
>adding PCI support to 2.6.11.4 for the MPC8272ADS board.
>
>The good news is that I think I have PCI interrupts pretty well sorted
>out, and I see *something* half-way reasonable from "lspci".
>
>The bad news is that neither of the ethernet cards that I'm trying will
>actually work, and I see some very weird behavior with PCI configuration
>space:
>
> Card 1: Some Realtek RTL8139D-based card
> Card 2: NETGEAR FA311 (National Semi DP83815 chip)
>
>With either card installed alone, both U-Boot and my kernel identify the
>cards correctly in PCI configuration space.
>
>With *both* cards installed, both U-Boot and my kernel see the Realtek-
>based card correctly, but the NETGEAR card has a corrupted Vendor ID
>(e.g. 0x1000 or 0x1003 instead of the correct 0x100b). This happens
>regardless of which PCI slots I use for the cards (I've tried virtually
>every combination). This smells of a power problem or something to me.
>
>And again, even with either card alone, the drivers have serious
>problems talking to the cards. I get various error messages from
>the drivers and I see badly mangled packets on the wire. It's also
>not uncommon for the whole system to freeze...
>
>Has anyone else seen similar behavior?
>
>Has anyone had success with PCI on this board (under any kernel
>version)?
>
>
>Any ideas / data points are appreciated.
>
>
>Thanks!!!
>
>Walt Wimer
>
>
>
>
>
>>This patch adds PCI bridge support for MPC8272 and PQ2FADS to the
>>current linuxppc-2.4 tree. Actually it has been tested with 8272, but
>>PQ2 _should_ also work, though it will complain that host bridge ID is
>>unrecognized.
>>
>>Signed-off-by: Vitaly Bordug <vbordug at ru.mvista.com>
>>
>>--
>>Sincerely, Vitaly
>>
>>-------------- next part --------------
>>A non-text attachment was scrubbed...
>>Name: pq2-pci.patch
>>Type: text/x-patch
>>Size: 20111 bytes
>>Desc: not available
>>Url : http://ozlabs.org/pipermail/linuxppc-embedded/attachments/20050218/12060ce8/pq2-pci.bin
>>
>>
>
>
>
>
--
Sincerely,
Vitaly
[-- Attachment #2: Type: text/html, Size: 3062 bytes --]
^ permalink raw reply
* Re: [RFC] MPC5200 Kernel/UBoot PCI problem
From: Sylvain Munaut @ 2005-03-25 14:00 UTC (permalink / raw)
To: Andrey Volkov; +Cc: linuxppc-embedded
In-Reply-To: <424404E2.2030602@varma-el.com>
Hi Andrey,
Andrey Volkov wrote:
>>> Try adding some delays in the pci configuration zone access routines
>>> in mpc52xx_pci.c I remember someone needed those but still don't
>>> know why, the manual don't say anything about that.
>>
>>
>> Board started, after I add udelay(7) in read/write config. Really
>> strange.
>
>
> Sylvain, answer was in PCI2.2 specification, not in manual.
>
Indeed good catch ! Never imagined the delay was so long.
It should be possible to use the sched_clock(void) to know if we're
booting since long enough, because just waiting 1 full second is ... long.
Sylvain
^ permalink raw reply
* [RFC] [PATCH] Freescale 8272ADS PCI bridge support to the stock linux-2.5
From: Vitaly Bordug @ 2005-03-25 13:22 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 949 bytes --]
Hello,
This patch adds support for the 8272ADS PCI bridge to the latest linux-2.5
There is a minor problem in the 2.5 tree, and I'm not completely sure
this solution is the best one. The point is, that the existing PCI code
actually includes two completely different PCI map defines- one is in
platforms/pq2ads.h, the another - syslib/m8260-pci.h. In the added code
I tried to use the first one only, preventing even second include for
the supported board, and implementing alternative setup_pci function,
thus adding extra code . Existing support (I assume was for 8266) lacks
irq stuff at all, and though new stuff _may_ work with other 82xx, I
haven't any to test. So, the replace of existing m8260-pci.c/h seems a
cleaner solution to provide and extend functionality without code bloat,
as keeping several define sets for actually the same thing isn't good, IMO.
Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
--
Sincerely,
Vitaly
[-- Attachment #2: all.patch --]
[-- Type: text/x-patch, Size: 16272 bytes --]
===== arch/ppc/Kconfig 1.105 vs edited =====
--- 1.105/arch/ppc/Kconfig 2005-03-18 23:51:33 +03:00
+++ edited/arch/ppc/Kconfig 2005-03-21 18:45:59 +03:00
@@ -1133,7 +1133,7 @@
config PCI_8260
bool
- depends on PCI && 8260 && !8272
+ depends on PCI && 8260
default y
config 8260_PCI9
===== arch/ppc/platforms/pq2ads.h 1.3 vs edited =====
--- 1.3/arch/ppc/platforms/pq2ads.h 2005-01-16 01:01:51 +03:00
+++ edited/arch/ppc/platforms/pq2ads.h 2005-03-22 19:46:40 +03:00
@@ -71,6 +71,7 @@
/* window for a PCI master to access MPC8266 memory */
#define PCI_SLV_MEM_LOCAL 0x00000000 /* Local base */
#define PCI_SLV_MEM_BUS 0x00000000 /* PCI base */
+#define PCI_SLV_MEM_SIZE 0x10000000 /* 256 Mb */
/* window for the processor to access PCI memory with prefetching */
#define PCI_MSTR_MEM_LOCAL 0x80000000 /* Local base */
@@ -83,9 +84,66 @@
#define PCI_MSTR_MEMIO_SIZE 0x20000000 /* 512MB */
/* window for the processor to access PCI I/O */
+#ifndef CONFIG_ADS8272
+
#define PCI_MSTR_IO_LOCAL 0xF4000000 /* Local base */
#define PCI_MSTR_IO_BUS 0x00000000 /* PCI base */
#define PCI_MSTR_IO_SIZE 0x04000000 /* 64MB */
+
+#else /* CONFIG_ADS8272 */
+
+#define PCI_MSTR_IO_LOCAL 0xF6000000 /* Local base */
+#define PCI_MSTR_IO_BUS 0x00000000 /* PCI base */
+#define PCI_MSTR_IO_SIZE 0x02000000 /* 64MB */
+
+/*-----------------------------------------------------------------------
+ * SIUMCR - SIU Module Configuration Register 4-31
+ */
+#define SIUMCR_BBD 0x80000000 /* Bus Busy Disable */
+#define SIUMCR_ESE 0x40000000 /* External Snoop Enable */
+#define SIUMCR_PBSE 0x20000000 /* Parity Byte Select Enable */
+#define SIUMCR_CDIS 0x10000000 /* Core Disable */
+#define SIUMCR_DPPC00 0x00000000 /* Data Parity Pins Configuration*/
+#define SIUMCR_DPPC01 0x04000000 /* - " - */
+#define SIUMCR_DPPC10 0x08000000 /* - " - */
+#define SIUMCR_DPPC11 0x0c000000 /* - " - */
+#define SIUMCR_L2CPC00 0x00000000 /* L2 Cache Pins Configuration */
+#define SIUMCR_L2CPC01 0x01000000 /* - " - */
+#define SIUMCR_L2CPC10 0x02000000 /* - " - */
+#define SIUMCR_L2CPC11 0x03000000 /* - " - */
+#define SIUMCR_LBPC00 0x00000000 /* Local Bus Pins Configuration */
+#define SIUMCR_LBPC01 0x00400000 /* - " - */
+#define SIUMCR_LBPC10 0x00800000 /* - " - */
+#define SIUMCR_LBPC11 0x00c00000 /* - " - */
+#define SIUMCR_APPC00 0x00000000 /* Address Parity Pins Configuration*/
+#define SIUMCR_APPC01 0x00100000 /* - " - */
+#define SIUMCR_APPC10 0x00200000 /* - " - */
+#define SIUMCR_APPC11 0x00300000 /* - " - */
+#define SIUMCR_CS10PC00 0x00000000 /* CS10 Pin Configuration */
+#define SIUMCR_CS10PC01 0x00040000 /* - " - */
+#define SIUMCR_CS10PC10 0x00080000 /* - " - */
+#define SIUMCR_CS10PC11 0x000c0000 /* - " - */
+#define SIUMCR_BCTLC00 0x00000000 /* Buffer Control Configuration */
+#define SIUMCR_BCTLC01 0x00010000 /* - " - */
+#define SIUMCR_BCTLC10 0x00020000 /* - " - */
+#define SIUMCR_BCTLC11 0x00030000 /* - " - */
+#define SIUMCR_MMR00 0x00000000 /* Mask Masters Requests */
+#define SIUMCR_MMR01 0x00004000 /* - " - */
+#define SIUMCR_MMR10 0x00008000 /* - " - */
+#define SIUMCR_MMR11 0x0000c000 /* - " - */
+#define SIUMCR_LPBSE 0x00002000 /* LocalBus Parity Byte Select Enable*/
+#endif
+
+#if defined(CONFIG_ADS8272)
+#define PCI_INT_TO_SIU SIU_INT_IRQ2
+#elif defined(CONFIG_PQ2FADS)
+#define PCI_INT_TO_SIU SIU_INT_IRQ6
+#else
+#warning PCI Bridge will be without interrupts support
+#endif
+
+#define POTA_ADDR_SHIFT 12
+#define PITA_ADDR_SHIFT 12
#define _IO_BASE PCI_MSTR_IO_LOCAL
#define _ISA_MEM_BASE PCI_MSTR_MEMIO_LOCAL
===== arch/ppc/syslib/Makefile 1.49 vs edited =====
--- 1.49/arch/ppc/syslib/Makefile 2005-03-18 23:51:33 +03:00
+++ edited/arch/ppc/syslib/Makefile 2005-03-22 19:59:08 +03:00
@@ -82,6 +82,9 @@
todc_time.o
obj-$(CONFIG_8260) += m8260_setup.o
obj-$(CONFIG_PCI_8260) += m8260_pci.o indirect_pci.o
+ifeq ($(CONFIG_ADS8272),y)
+obj-$(CONFIG_PCI) += pci_auto.o
+endif
obj-$(CONFIG_8260_PCI9) += m8260_pci_erratum9.o
obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o
ifeq ($(CONFIG_PPC_GEN550),y)
===== arch/ppc/syslib/m8260_pci.c 1.2 vs edited =====
--- 1.2/arch/ppc/syslib/m8260_pci.c 2004-06-17 16:57:15 +04:00
+++ edited/arch/ppc/syslib/m8260_pci.c 2005-03-22 20:16:33 +03:00
@@ -1,4 +1,7 @@
/*
+ * 2005 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
* (C) Copyright 2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
@@ -28,6 +31,8 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <asm/byteorder.h>
#include <asm/io.h>
@@ -38,12 +43,144 @@
#include <asm/immap_cpm2.h>
#include <asm/mpc8260.h>
+#if !defined(CONFIG_ADS8272) || !defined(CONFIG_PQ2FADS)
#include "m8260_pci.h"
+#endif
+
+/*
+ * Interrupt routing
+ */
+
+static inline int
+pq2pci_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ { PIRQA, PIRQB, PIRQC, PIRQD }, /* IDSEL 22 - PCI slot 0 */
+ { PIRQD, PIRQA, PIRQB, PIRQC }, /* IDSEL 23 - PCI slot 1 */
+ { PIRQC, PIRQD, PIRQA, PIRQB }, /* IDSEL 24 - PCI slot 2 */
+ };
+
+ const long min_idsel = 22, max_idsel = 24, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static void
+pq2pci_mask_irq(unsigned int irq)
+{
+ int bit = irq - NR_SIU_INTS;
+
+ *(volatile unsigned long *) PCI_INT_MASK_REG |= (1 << (31 - bit));
+ return;
+}
+
+static void
+pq2pci_unmask_irq(unsigned int irq)
+{
+ int bit = irq - NR_SIU_INTS;
+
+ *(volatile unsigned long *) PCI_INT_MASK_REG &= ~(1 << (31 - bit));
+ return;
+}
+
+static void
+pq2pci_mask_and_ack(unsigned int irq)
+{
+ int bit = irq - NR_SIU_INTS;
+
+ *(volatile unsigned long *) PCI_INT_MASK_REG |= (1 << (31 - bit));
+ return;
+}
+
+static void
+pq2pci_end_irq(unsigned int irq)
+{
+ int bit = irq - NR_SIU_INTS;
+
+ *(volatile unsigned long *) PCI_INT_MASK_REG &= ~(1 << (31 - bit));
+ return;
+}
+
+struct hw_interrupt_type pq2pci_ic = {
+ "PQ2 PCI",
+ NULL,
+ NULL,
+ pq2pci_unmask_irq,
+ pq2pci_mask_irq,
+ pq2pci_mask_and_ack,
+ pq2pci_end_irq,
+ 0
+};
+
+static irqreturn_t
+pq2pci_irq_demux(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned long stat, mask, pend;
+ int bit;
+
+ for(;;) {
+ stat = *(volatile unsigned long *) PCI_INT_STAT_REG;
+ mask = *(volatile unsigned long *) PCI_INT_MASK_REG;
+ pend = stat & ~mask & 0xf0000000;
+ if (!pend)
+ break;
+ for (bit = 0; pend != 0; ++bit, pend <<= 1) {
+ if (pend & 0x80000000)
+ __do_IRQ(NR_SIU_INTS + bit, regs);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction pq2pci_irqaction = {
+ .handler = pq2pci_irq_demux,
+ .flags = SA_INTERRUPT,
+ .mask = CPU_MASK_NONE,
+ .name = "PQ2 PCI cascade",
+};
+
+
+void
+pq2pci_init_irq(void)
+{
+ int irq;
+ volatile cpm2_map_t *immap = cpm2_immr;
+#ifdef CONFIG_ADS8272
+ /* configure chip select for PCI interrupt controller */
+ immap->im_memctl.memc_br3 = PCI_INT_STAT_REG | 0x00001801;
+ immap->im_memctl.memc_or3 = 0xffff8010;
+#endif
+ for (irq = NR_SIU_INTS; irq < NR_SIU_INTS + 4; irq++)
+ irq_desc[irq].handler = &pq2pci_ic;
+
+ /* make PCI IRQ level sensitive */
+ immap->im_intctl.ic_siexr &=
+ ~(1 << (14 - (PCI_INT_TO_SIU - SIU_INT_IRQ1)));
+
+ /* mask all PCI interrupts */
+ *(volatile unsigned long *) PCI_INT_MASK_REG |= 0xfff00000;
+
+ /* install the demultiplexer for the PCI cascade interrupt */
+ setup_irq(PCI_INT_TO_SIU, &pq2pci_irqaction);
+ return;
+}
+
+static int
+pq2pci_exclude_device(u_char bus, u_char devfn)
+{
+ return PCIBIOS_SUCCESSFUL;
+}
/* PCI bus configuration registers.
*/
+#ifndef CONFIG_ADS8272
static void __init m8260_setup_pci(struct pci_controller *hose)
{
volatile cpm2_map_t *immap = cpm2_immr;
@@ -146,10 +283,136 @@
tempShort | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
}
-void __init m8260_find_bridges(void)
+#else /* setup hardware for 8272ADS and PQ2FADS */
+
+static void
+pq2ads_setup_pci(struct pci_controller *hose)
+{
+ __u32 val;
+ volatile cpm2_map_t *immap = cpm2_immr;
+ /* PCI int lowest prio */
+ /* Each 4 bits is a device bus request and the MS 4bits
+ is highest priority */
+ /* Bus 4bit value
+ --- ----------
+ CPM high 0b0000
+ CPM middle 0b0001
+ CPM low 0b0010
+ PCI reguest 0b0011
+ Reserved 0b0100
+ Reserved 0b0101
+ Internal Core 0b0110
+ External Master 1 0b0111
+ External Master 2 0b1000
+ External Master 3 0b1001
+ The rest are reserved
+ */
+ immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x61207893;
+ /* park bus on core */
+ immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_CORE;
+ /*
+ * Set up master windows that allow the CPU to access PCI space. These
+ * windows are set up using the two SIU PCIBR registers.
+ */
+
+ immap->im_memctl.memc_pcimsk0 = ~(PCI_MSTR_IO_SIZE - 1U);
+ immap->im_memctl.memc_pcibr0 = PCI_MSTR_IO_LOCAL | PCIBR_ENABLE;
+
+ immap->im_memctl.memc_pcimsk1 = ~(PCI_MSTR_MEM_SIZE + PCI_MSTR_MEMIO_SIZE - 1U);
+ immap->im_memctl.memc_pcibr1 = PCI_MSTR_MEM_LOCAL | PCIBR_ENABLE;
+#ifdef CONFIG_ADS8272
+ immap->im_siu_conf.siu_82xx.sc_siumcr = (immap->im_siu_conf.siu_82xx.sc_siumcr &
+ ~SIUMCR_BBD &
+ ~SIUMCR_ESE &
+ ~SIUMCR_PBSE &
+ ~SIUMCR_CDIS &
+ ~SIUMCR_DPPC11 &
+ ~SIUMCR_L2CPC11 &
+ ~SIUMCR_LBPC11 &
+ ~SIUMCR_APPC11 &
+ ~SIUMCR_CS10PC11 &
+ ~SIUMCR_BCTLC11 &
+ ~SIUMCR_MMR11)
+ | SIUMCR_DPPC11 | SIUMCR_L2CPC01 | SIUMCR_LBPC00
+ | SIUMCR_APPC10 | SIUMCR_CS10PC00 | SIUMCR_BCTLC00 | SIUMCR_MMR11;
+#elif defined CONFIG_PQ2FADS
+ /*
+ * Setting required to enable IRQ1-IRQ7 (SIUMCR [DPPC]),
+ * and local bus for PCI (SIUMCR [LBPC]).
+ */
+ immap->im_siu_conf.siu_82xx.sc_siumcr = (immap->im_siu_conf.sc_siumcr &
+ ~SIUMCR_LBPC11 &
+ ~SIUMCR_CS10PC11 &
+ ~SIUMCR_LBPC11) |
+ SIUMCR_LBPC01 | SIUMCR_CS10PC01 | SIUMCR_APPC10;
+#endif
+ /* Enable PCI */
+ immap->im_pci.pci_gcr = cpu_to_le32(PCIGCR_PCI_BUS_EN);
+ {
+ /* give it some time */
+ int i;
+ for(i=0;i<100;i++)
+ udelay(100);
+ }
+
+ /* setup ATU registers */
+ immap->im_pci.pci_pocmr0 = cpu_to_le32(POCMR_ENABLE | POCMR_PCI_IO |
+ ((~(PCI_MSTR_IO_SIZE - 1U)) >> POTA_ADDR_SHIFT));
+ immap->im_pci.pci_potar0 = cpu_to_le32(PCI_MSTR_IO_BUS >> POTA_ADDR_SHIFT);
+ immap->im_pci.pci_pobar0 = cpu_to_le32(PCI_MSTR_IO_LOCAL >> POTA_ADDR_SHIFT);
+
+ /* Set-up non-prefetchable window */
+ immap->im_pci.pci_pocmr1 = cpu_to_le32(POCMR_ENABLE | ((~(PCI_MSTR_MEMIO_SIZE-1U)) >> POTA_ADDR_SHIFT));
+ immap->im_pci.pci_potar1 = cpu_to_le32(PCI_MSTR_MEMIO_BUS >> POTA_ADDR_SHIFT);
+ immap->im_pci.pci_pobar1 = cpu_to_le32(PCI_MSTR_MEMIO_LOCAL >> POTA_ADDR_SHIFT);
+
+ /* Set-up prefetchable window */
+ immap->im_pci.pci_pocmr2 = cpu_to_le32(POCMR_ENABLE |POCMR_PREFETCH_EN |
+ (~(PCI_MSTR_MEM_SIZE-1U) >> POTA_ADDR_SHIFT));
+ immap->im_pci.pci_potar2 = cpu_to_le32((PCI_MSTR_MEM_BUS) >> POTA_ADDR_SHIFT);
+ immap->im_pci.pci_pobar2 = cpu_to_le32((PCI_MSTR_MEM_LOCAL) >> POTA_ADDR_SHIFT);
+
+ /* Inbound transactions from PCI memory space */
+ immap->im_pci.pci_picmr0 = cpu_to_le32(PICMR_ENABLE | PICMR_PREFETCH_EN |
+ ((~(PCI_SLV_MEM_SIZE-1U)) >> PITA_ADDR_SHIFT));
+ immap->im_pci.pci_pibar0 = cpu_to_le32(PCI_SLV_MEM_BUS >> PITA_ADDR_SHIFT);
+ immap->im_pci.pci_pitar0 = cpu_to_le32(PCI_SLV_MEM_LOCAL>> PITA_ADDR_SHIFT);
+
+#if defined CONFIG_ADS8272
+ /* PCI int highest prio */
+ immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x01236745;
+#elif defined CONFIG_PQ2FADS
+ immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x03124567;
+#endif
+ /* park bus on PCI */
+ immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_PCI;
+
+ /* Enable bus mastering and inbound memory transactions */
+ early_read_config_dword(hose, hose->first_busno, 0, PCI_COMMAND, &val);
+ val &= 0xffff0000;
+ val |= PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER;
+ early_write_config_dword(hose, hose->first_busno, 0, PCI_COMMAND, val);
+
+}
+
+static void pq2ads_setup_hose(struct pci_controller * hose)
+{
+ hose->io_space.start = MPC826x_PCI_LOWER_IO;
+ hose->io_space.end = MPC826x_PCI_UPPER_IO;
+ hose->mem_space.start = MPC826x_PCI_LOWER_MEM;
+ hose->mem_space.end = MPC826x_PCI_UPPER_MMIO;
+ hose->io_base_virt = (void*)MPC826x_PCI_IO_BASE;
+ isa_io_base = MPC826x_PCI_IO_BASE;
+}
+
+#endif
+
+
+void __init pq2_find_bridges(void)
{
extern int pci_assign_all_busses;
struct pci_controller * hose;
+ int host_bridge;
pci_assign_all_busses = 1;
@@ -164,18 +427,45 @@
hose->bus_offset = 0;
hose->last_busno = 0xff;
+#ifdef CONFIG_ADS8272
+ hose->set_cfg_type = 1;
+#endif
+
setup_m8260_indirect_pci(hose,
(unsigned long)&cpm2_immr->im_pci.pci_cfg_addr,
(unsigned long)&cpm2_immr->im_pci.pci_cfg_data);
+ /* Make sure it is a supported bridge */
+ early_read_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ PCI_VENDOR_ID,
+ &host_bridge);
+ switch (host_bridge) {
+ case PCI_DEVICE_ID_MPC8265:
+ break;
+ case PCI_DEVICE_ID_MPC8272:
+ break;
+ default:
+ printk("Attempting to use unrecognized host bridge ID"
+ " 0x%08x.\n", host_bridge);
+ break;
+ }
+
+#if defined(CONFIG_ADS8272) || defined(CONFIG_PQ2FADS)
+ pq2ads_setup_pci(hose);
+ pq2ads_setup_hose(hose);
+#else
m8260_setup_pci(hose);
+
hose->pci_mem_offset = MPC826x_PCI_MEM_OFFSET;
- isa_io_base =
+ isa_io_base =
(unsigned long) ioremap(MPC826x_PCI_IO_BASE,
MPC826x_PCI_IO_SIZE);
hose->io_base_virt = (void *) isa_io_base;
-
+#endif
+
/* setup resources */
pci_init_resource(&hose->mem_resources[0],
MPC826x_PCI_LOWER_MEM,
@@ -191,4 +481,15 @@
MPC826x_PCI_LOWER_IO,
MPC826x_PCI_UPPER_IO,
IORESOURCE_IO, "PCI I/O");
+
+#if defined(CONFIG_ADS8272) || defined(CONFIG_PQ2FADS)
+ ppc_md.pci_exclude_device = pq2pci_exclude_device;
+ hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+ ppc_md.pci_map_irq = pq2pci_map_irq;
+ ppc_md.pcibios_fixup = NULL;
+ ppc_md.pcibios_fixup_bus = NULL;
+
+#endif
+
}
===== arch/ppc/syslib/m8260_setup.c 1.29 vs edited =====
--- 1.29/arch/ppc/syslib/m8260_setup.c 2005-01-16 01:01:51 +03:00
+++ edited/arch/ppc/syslib/m8260_setup.c 2005-03-23 14:06:40 +03:00
@@ -34,7 +34,8 @@
unsigned char __res[sizeof(bd_t)];
extern void cpm2_reset(void);
-extern void m8260_find_bridges(void);
+extern void pq2_find_bridges(void);
+extern void pq2pci_init_irq(void);
extern void idma_pci9_init(void);
/* Place-holder for board-specific init */
@@ -56,7 +57,11 @@
idma_pci9_init();
#endif
#ifdef CONFIG_PCI_8260
+#if defined(CONFIG_ADS8272) || defined(CONFIG_PQ2FADS)
+ pq2_find_bridges();
+#else
m8260_find_bridges();
+#endif
#endif
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start)
@@ -179,6 +184,10 @@
cpm2_immr->im_intctl.ic_siprr = 0x05309770;
cpm2_immr->im_intctl.ic_scprrh = 0x05309770;
cpm2_immr->im_intctl.ic_scprrl = 0x05309770;
+#if defined(CONFIG_PCI) && (defined(CONFIG_ADS8272) || defined(CONFIG_ADS8272))
+ /* Initialize stuff for the 82xx CPLD IC and install demux */
+ pq2pci_init_irq();
+#endif
}
/*
@@ -201,6 +210,9 @@
m8260_map_io(void)
{
uint addr;
+#if defined(CONFIG_PCI) && (defined(CONFIG_ADS8272) || defined(CONFIG_ADS8272))
+ io_block_mapping(0x80000000,0x80000000,0x10000000, _PAGE_IO);
+#endif
/* Map IMMR region to a 256MB BAT */
addr = (cpm2_immr != NULL) ? (uint)cpm2_immr : CPM_MAP_ADDR;
===== include/asm-ppc/m8260_pci.h 1.1 vs edited =====
--- 1.1/include/asm-ppc/m8260_pci.h 2004-06-17 02:56:05 +04:00
+++ edited/include/asm-ppc/m8260_pci.h 2005-03-22 20:03:03 +03:00
@@ -19,6 +19,7 @@
* Define the vendor/device ID for the MPC8265.
*/
#define PCI_DEVICE_ID_MPC8265 ((0x18C0 << 16) | PCI_VENDOR_ID_MOTOROLA)
+#define PCI_DEVICE_ID_MPC8272 ((0x18C1 << 16) | PCI_VENDOR_ID_MOTOROLA)
#define M8265_PCIBR0 0x101ac
#define M8265_PCIBR1 0x101b0
^ permalink raw reply
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