* [PATCH 2/9] fs_enet: Include linux/string.h from linux/fs_enet_pd.h
From: Scott Wood @ 2007-09-20 22:01 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20070920220043.GA28769@loki.buserror.net>
It is needed for strstr().
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
include/linux/fs_enet_pd.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h
index 543cd3c..815c6f9 100644
--- a/include/linux/fs_enet_pd.h
+++ b/include/linux/fs_enet_pd.h
@@ -16,6 +16,7 @@
#ifndef FS_ENET_PD_H
#define FS_ENET_PD_H
+#include <linux/string.h>
#include <asm/types.h>
#define FS_ENET_NAME "fs_enet"
--
1.5.3.1
^ permalink raw reply related
* [PATCH 3/9] fs_enet: Don't share the interrupt.
From: Scott Wood @ 2007-09-20 22:01 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20070920220043.GA28769@loki.buserror.net>
This driver can't handle an interrupt immediately after request_irq
(making it fail with CONFIG_DEBUG_SHIRQ), and has unshared interrupts
on all hardware I'm aware of.
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
drivers/net/fs_enet/fs_enet-main.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index f261b90..da79a45 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -667,7 +667,7 @@ static int fs_request_irq(struct net_device *dev, int irq, const char *name,
struct fs_enet_private *fep = netdev_priv(dev);
(*fep->ops->pre_request_irq)(dev, irq);
- return request_irq(irq, irqf, IRQF_SHARED, name, dev);
+ return request_irq(irq, irqf, 0, name, dev);
}
static void fs_free_irq(struct net_device *dev, int irq)
--
1.5.3.1
^ permalink raw reply related
* [PATCH 4/9] fs_enet: mac-fcc: Eliminate __fcc-* macros.
From: Scott Wood @ 2007-09-20 22:01 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20070920220043.GA28769@loki.buserror.net>
These macros accomplish nothing other than defeating type checking.
This patch also fixes one instance of the wrong register size being
used that was revealed by enabling type checking.
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
drivers/net/fs_enet/mac-fcc.c | 25 ++++++++-----------------
1 files changed, 8 insertions(+), 17 deletions(-)
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index ad3c5fa..8b30361 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -48,28 +48,19 @@
/* FCC access macros */
-#define __fcc_out32(addr, x) out_be32((unsigned *)addr, x)
-#define __fcc_out16(addr, x) out_be16((unsigned short *)addr, x)
-#define __fcc_out8(addr, x) out_8((unsigned char *)addr, x)
-#define __fcc_in32(addr) in_be32((unsigned *)addr)
-#define __fcc_in16(addr) in_be16((unsigned short *)addr)
-#define __fcc_in8(addr) in_8((unsigned char *)addr)
-
-/* parameter space */
-
/* write, read, set bits, clear bits */
-#define W32(_p, _m, _v) __fcc_out32(&(_p)->_m, (_v))
-#define R32(_p, _m) __fcc_in32(&(_p)->_m)
+#define W32(_p, _m, _v) out_be32(&(_p)->_m, (_v))
+#define R32(_p, _m) in_be32(&(_p)->_m)
#define S32(_p, _m, _v) W32(_p, _m, R32(_p, _m) | (_v))
#define C32(_p, _m, _v) W32(_p, _m, R32(_p, _m) & ~(_v))
-#define W16(_p, _m, _v) __fcc_out16(&(_p)->_m, (_v))
-#define R16(_p, _m) __fcc_in16(&(_p)->_m)
+#define W16(_p, _m, _v) out_be16(&(_p)->_m, (_v))
+#define R16(_p, _m) in_be16(&(_p)->_m)
#define S16(_p, _m, _v) W16(_p, _m, R16(_p, _m) | (_v))
#define C16(_p, _m, _v) W16(_p, _m, R16(_p, _m) & ~(_v))
-#define W8(_p, _m, _v) __fcc_out8(&(_p)->_m, (_v))
-#define R8(_p, _m) __fcc_in8(&(_p)->_m)
+#define W8(_p, _m, _v) out_8(&(_p)->_m, (_v))
+#define R8(_p, _m) in_8(&(_p)->_m)
#define S8(_p, _m, _v) W8(_p, _m, R8(_p, _m) | (_v))
#define C8(_p, _m, _v) W8(_p, _m, R8(_p, _m) & ~(_v))
@@ -290,7 +281,7 @@ static void restart(struct net_device *dev)
/* clear everything (slow & steady does it) */
for (i = 0; i < sizeof(*ep); i++)
- __fcc_out8((char *)ep + i, 0);
+ out_8((char *)ep + i, 0);
/* get physical address */
rx_bd_base_phys = fep->ring_mem_addr;
@@ -495,7 +486,7 @@ static void tx_kickstart(struct net_device *dev)
struct fs_enet_private *fep = netdev_priv(dev);
fcc_t *fccp = fep->fcc.fccp;
- S32(fccp, fcc_ftodr, 0x80);
+ S16(fccp, fcc_ftodr, 0x8000);
}
static u32 get_int_events(struct net_device *dev)
--
1.5.3.1
^ permalink raw reply related
* [PATCH 5/9] fs_enet: Align receive buffers.
From: Scott Wood @ 2007-09-20 22:01 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20070920220043.GA28769@loki.buserror.net>
At least some hardware driven by this driver needs receive buffers
to be aligned on a 16-byte boundary. This usually happens by chance,
but it breaks if slab debugging is enabled.
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
drivers/net/fs_enet/fs_enet-main.c | 21 +++++++++++++++++++--
drivers/net/fs_enet/fs_enet.h | 3 ++-
2 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index da79a45..a4b76cd 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -69,6 +69,14 @@ static void fs_set_multicast_list(struct net_device *dev)
(*fep->ops->set_multicast_list)(dev);
}
+static void skb_align(struct sk_buff *skb, int align)
+{
+ int off = ((unsigned long)skb->data) & (align - 1);
+
+ if (off)
+ skb_reserve(skb, align - off);
+}
+
/* NAPI receive function */
static int fs_enet_rx_napi(struct net_device *dev, int *budget)
{
@@ -166,9 +174,13 @@ static int fs_enet_rx_napi(struct net_device *dev, int *budget)
skb = skbn;
skbn = skbt;
}
- } else
+ } else {
skbn = dev_alloc_skb(ENET_RX_FRSIZE);
+ if (skbn)
+ skb_align(skbn, ENET_RX_ALIGN);
+ }
+
if (skbn != NULL) {
skb_put(skb, pkt_len); /* Make room */
skb->protocol = eth_type_trans(skb, dev);
@@ -300,9 +312,13 @@ static int fs_enet_rx_non_napi(struct net_device *dev)
skb = skbn;
skbn = skbt;
}
- } else
+ } else {
skbn = dev_alloc_skb(ENET_RX_FRSIZE);
+ if (skbn)
+ skb_align(skbn, ENET_RX_ALIGN);
+ }
+
if (skbn != NULL) {
skb_put(skb, pkt_len); /* Make room */
skb->protocol = eth_type_trans(skb, dev);
@@ -512,6 +528,7 @@ void fs_init_bds(struct net_device *dev)
dev->name);
break;
}
+ skb_align(skb, ENET_RX_ALIGN);
fep->rx_skbuff[i] = skb;
CBDW_BUFADDR(bdp,
dma_map_single(fep->dev, skb->data,
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
index 72a61e9..f8c7ee8 100644
--- a/drivers/net/fs_enet/fs_enet.h
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -82,7 +82,8 @@ struct phy_info {
/* Must be a multiple of 32 (to cover both FEC & FCC) */
#define PKT_MAXBLR_SIZE ((PKT_MAXBUF_SIZE + 31) & ~31)
/* This is needed so that invalidate_xxx wont invalidate too much */
-#define ENET_RX_FRSIZE L1_CACHE_ALIGN(PKT_MAXBUF_SIZE)
+#define ENET_RX_ALIGN 16
+#define ENET_RX_FRSIZE L1_CACHE_ALIGN(PKT_MAXBUF_SIZE + ENET_RX_ALIGN - 1)
struct fs_enet_mii_bus {
struct list_head list;
--
1.5.3.1
^ permalink raw reply related
* [PATCH 7/9] Generic bitbanged MDIO library
From: Scott Wood @ 2007-09-20 22:01 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20070920220043.GA28769@loki.buserror.net>
Previously, bitbanged MDIO was only supported in individual
hardware-specific drivers. This code factors out the higher level
protocol implementation, reducing the hardware-specific portion to
functions setting direction, data, and clock.
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
drivers/net/phy/Kconfig | 9 ++
drivers/net/phy/Makefile | 1 +
drivers/net/phy/mdio-bitbang.c | 187 ++++++++++++++++++++++++++++++++++++++++
include/linux/mdio-bitbang.h | 42 +++++++++
4 files changed, 239 insertions(+), 0 deletions(-)
create mode 100644 drivers/net/phy/mdio-bitbang.c
create mode 100644 include/linux/mdio-bitbang.h
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index dd09011..72a98dd 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -76,4 +76,13 @@ config FIXED_MII_100_FDX
bool "Emulation for 100M Fdx fixed PHY behavior"
depends on FIXED_PHY
+config MDIO_BITBANG
+ tristate "Support for bitbanged MDIO buses"
+ help
+ This module implements the MDIO bus protocol in software,
+ for use by low level drivers that export the ability to
+ drive the relevant pins.
+
+ If in doubt, say N.
+
endif # PHYLIB
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 8885650..3d6cc7b 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_VITESSE_PHY) += vitesse.o
obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
obj-$(CONFIG_ICPLUS_PHY) += icplus.o
obj-$(CONFIG_FIXED_PHY) += fixed.o
+obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c
new file mode 100644
index 0000000..8cd243d
--- /dev/null
+++ b/drivers/net/phy/mdio-bitbang.c
@@ -0,0 +1,187 @@
+/*
+ * Bitbanged MDIO support.
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ * Copyright (c) 2007 Freescale Semiconductor
+ *
+ * Based on CPM2 MDIO code which is:
+ *
+ * Copyright (c) 2003 Intracom S.A.
+ * by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * 2005 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/mdio-bitbang.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+
+#define MDIO_READ 1
+#define MDIO_WRITE 0
+
+#define MDIO_SETUP_TIME 10
+#define MDIO_HOLD_TIME 10
+
+/* Minimum MDC period is 400 ns, plus some margin for error. MDIO_DELAY
+ * is done twice per period.
+ */
+#define MDIO_DELAY 250
+
+/* The PHY may take up to 300 ns to produce data, plus some margin
+ * for error.
+ */
+#define MDIO_READ_DELAY 350
+
+/* MDIO must already be configured as output. */
+static void mdiobb_send_bit(struct mdiobb_ctrl *ctrl, int val)
+{
+ const struct mdiobb_ops *ops = ctrl->ops;
+
+ ops->set_mdio_data(ctrl, val);
+ ndelay(MDIO_DELAY);
+ ops->set_mdc(ctrl, 1);
+ ndelay(MDIO_DELAY);
+ ops->set_mdc(ctrl, 0);
+}
+
+/* MDIO must already be configured as input. */
+static int mdiobb_get_bit(struct mdiobb_ctrl *ctrl)
+{
+ const struct mdiobb_ops *ops = ctrl->ops;
+
+ ndelay(MDIO_DELAY);
+ ops->set_mdc(ctrl, 1);
+ ndelay(MDIO_READ_DELAY);
+ ops->set_mdc(ctrl, 0);
+
+ return ops->get_mdio_data(ctrl);
+}
+
+/* MDIO must already be configured as output. */
+static void mdiobb_send_num(struct mdiobb_ctrl *ctrl, u16 val, int bits)
+{
+ int i;
+
+ for (i = bits - 1; i >= 0; i--)
+ mdiobb_send_bit(ctrl, (val >> i) & 1);
+}
+
+/* MDIO must already be configured as input. */
+static u16 mdiobb_get_num(struct mdiobb_ctrl *ctrl, int bits)
+{
+ int i;
+ u16 ret = 0;
+
+ for (i = bits - 1; i >= 0; i--) {
+ ret <<= 1;
+ ret |= mdiobb_get_bit(ctrl);
+ }
+
+ return ret;
+}
+
+/* Utility to send the preamble, address, and
+ * register (common to read and write).
+ */
+static void mdiobb_cmd(struct mdiobb_ctrl *ctrl, int read, u8 phy, u8 reg)
+{
+ const struct mdiobb_ops *ops = ctrl->ops;
+ int i;
+
+ ops->set_mdio_dir(ctrl, 1);
+
+ /*
+ * Send a 32 bit preamble ('1's) with an extra '1' bit for good
+ * measure. The IEEE spec says this is a PHY optional
+ * requirement. The AMD 79C874 requires one after power up and
+ * one after a MII communications error. This means that we are
+ * doing more preambles than we need, but it is safer and will be
+ * much more robust.
+ */
+
+ for (i = 0; i < 32; i++)
+ mdiobb_send_bit(ctrl, 1);
+
+ /* send the start bit (01) and the read opcode (10) or write (10) */
+ mdiobb_send_bit(ctrl, 0);
+ mdiobb_send_bit(ctrl, 1);
+ mdiobb_send_bit(ctrl, read);
+ mdiobb_send_bit(ctrl, !read);
+
+ mdiobb_send_num(ctrl, phy, 5);
+ mdiobb_send_num(ctrl, reg, 5);
+}
+
+
+static int mdiobb_read(struct mii_bus *bus, int phy, int reg)
+{
+ struct mdiobb_ctrl *ctrl = bus->priv;
+ int ret, i;
+
+ mdiobb_cmd(ctrl, MDIO_READ, phy, reg);
+ ctrl->ops->set_mdio_dir(ctrl, 0);
+
+ /* check the turnaround bit: the PHY should be driving it to zero */
+ if (mdiobb_get_bit(ctrl) != 0) {
+ /* PHY didn't drive TA low -- flush any bits it
+ * may be trying to send.
+ */
+ for (i = 0; i < 32; i++)
+ mdiobb_get_bit(ctrl);
+
+ return 0xffff;
+ }
+
+ ret = mdiobb_get_num(ctrl, 16);
+ mdiobb_get_bit(ctrl);
+ return ret;
+}
+
+static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val)
+{
+ struct mdiobb_ctrl *ctrl = bus->priv;
+
+ mdiobb_cmd(ctrl, MDIO_WRITE, phy, reg);
+
+ /* send the turnaround (10) */
+ mdiobb_send_bit(ctrl, 1);
+ mdiobb_send_bit(ctrl, 0);
+
+ mdiobb_send_num(ctrl, val, 16);
+
+ ctrl->ops->set_mdio_dir(ctrl, 0);
+ mdiobb_get_bit(ctrl);
+ return 0;
+}
+
+struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl)
+{
+ struct mii_bus *bus;
+
+ bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+ if (!bus)
+ return NULL;
+
+ __module_get(ctrl->ops->owner);
+
+ bus->read = mdiobb_read;
+ bus->write = mdiobb_write;
+ bus->priv = ctrl;
+
+ return bus;
+}
+
+void free_mdio_bitbang(struct mii_bus *bus)
+{
+ struct mdiobb_ctrl *ctrl = bus->priv;
+
+ module_put(ctrl->ops->owner);
+ kfree(bus);
+}
diff --git a/include/linux/mdio-bitbang.h b/include/linux/mdio-bitbang.h
new file mode 100644
index 0000000..8ea9a42
--- /dev/null
+++ b/include/linux/mdio-bitbang.h
@@ -0,0 +1,42 @@
+#ifndef __LINUX_MDIO_BITBANG_H
+#define __LINUX_MDIO_BITBANG_H
+
+#include <linux/phy.h>
+#include <linux/module.h>
+
+struct mdiobb_ctrl;
+
+struct mdiobb_ops {
+ struct module *owner;
+
+ /* Set the Management Data Clock high if level is one,
+ * low if level is zero.
+ */
+ void (*set_mdc)(struct mdiobb_ctrl *ctrl, int level);
+
+ /* Configure the Management Data I/O pin as an input if
+ * "output" is zero, or an output if "output" is one.
+ */
+ void (*set_mdio_dir)(struct mdiobb_ctrl *ctrl, int output);
+
+ /* Set the Management Data I/O pin high if value is one,
+ * low if "value" is zero. This may only be called
+ * when the MDIO pin is configured as an output.
+ */
+ void (*set_mdio_data)(struct mdiobb_ctrl *ctrl, int value);
+
+ /* Retrieve the state Management Data I/O pin. */
+ int (*get_mdio_data)(struct mdiobb_ctrl *ctrl);
+};
+
+struct mdiobb_ctrl {
+ const struct mdiobb_ops *ops;
+};
+
+/* The returned bus is not yet registered with the phy layer. */
+struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl);
+
+/* The bus must already have been unregistered. */
+void free_mdio_bitbang(struct mii_bus *bus);
+
+#endif
--
1.5.3.1
^ permalink raw reply related
* [PATCH 8/9] fs_enet: Convert mii-bitbang to use the generic bitbang MDIO code.
From: Scott Wood @ 2007-09-20 22:01 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20070920220043.GA28769@loki.buserror.net>
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
drivers/net/fs_enet/mii-bitbang.c | 270 ++++++++-----------------------------
1 files changed, 54 insertions(+), 216 deletions(-)
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index 2b9c44c..5732890 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -15,15 +15,13 @@
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/slab.h>
-#include <linux/interrupt.h>
#include <linux/init.h>
-#include <linux/delay.h>
+#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/mii.h>
-#include <linux/ethtool.h>
-#include <linux/bitops.h>
#include <linux/platform_device.h>
+#include <linux/mdio-bitbang.h>
#ifdef CONFIG_PPC_CPM_NEW_BINDING
#include <linux/of_platform.h>
@@ -32,11 +30,11 @@
#include "fs_enet.h"
struct bb_info {
+ struct mdiobb_ctrl ctrl;
__be32 __iomem *dir;
__be32 __iomem *dat;
u32 mdio_msk;
u32 mdc_msk;
- int delay;
};
/* FIXME: If any other users of GPIO crop up, then these will have to
@@ -59,212 +57,58 @@ static inline int bb_read(u32 __iomem *p, u32 m)
return (in_be32(p) & m) != 0;
}
-static inline void mdio_active(struct bb_info *bitbang)
+static inline void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
{
- bb_set(bitbang->dir, bitbang->mdio_msk);
-}
+ struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
-static inline void mdio_tristate(struct bb_info *bitbang)
-{
- bb_clr(bitbang->dir, bitbang->mdio_msk);
+ if (dir)
+ bb_set(bitbang->dir, bitbang->mdio_msk);
+ else
+ bb_clr(bitbang->dir, bitbang->mdio_msk);
+
+ /* Read back to flush the write. */
+ in_be32(bitbang->dir);
}
-static inline int mdio_read(struct bb_info *bitbang)
+static inline int mdio_read(struct mdiobb_ctrl *ctrl)
{
+ struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
return bb_read(bitbang->dat, bitbang->mdio_msk);
}
-static inline void mdio(struct bb_info *bitbang, int what)
+static inline void mdio(struct mdiobb_ctrl *ctrl, int what)
{
+ struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
+
if (what)
bb_set(bitbang->dat, bitbang->mdio_msk);
else
bb_clr(bitbang->dat, bitbang->mdio_msk);
+
+ /* Read back to flush the write. */
+ in_be32(bitbang->dat);
}
-static inline void mdc(struct bb_info *bitbang, int what)
+static inline void mdc(struct mdiobb_ctrl *ctrl, int what)
{
+ struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
+
if (what)
bb_set(bitbang->dat, bitbang->mdc_msk);
else
bb_clr(bitbang->dat, bitbang->mdc_msk);
-}
-
-static inline void mii_delay(struct bb_info *bitbang)
-{
- udelay(bitbang->delay);
-}
-
-/* Utility to send the preamble, address, and register (common to read and write). */
-static void bitbang_pre(struct bb_info *bitbang , int read, u8 addr, u8 reg)
-{
- int j;
-
- /*
- * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure.
- * The IEEE spec says this is a PHY optional requirement. The AMD
- * 79C874 requires one after power up and one after a MII communications
- * error. This means that we are doing more preambles than we need,
- * but it is safer and will be much more robust.
- */
-
- mdio_active(bitbang);
- mdio(bitbang, 1);
- for (j = 0; j < 32; j++) {
- mdc(bitbang, 0);
- mii_delay(bitbang);
- mdc(bitbang, 1);
- mii_delay(bitbang);
- }
-
- /* send the start bit (01) and the read opcode (10) or write (10) */
- mdc(bitbang, 0);
- mdio(bitbang, 0);
- mii_delay(bitbang);
- mdc(bitbang, 1);
- mii_delay(bitbang);
- mdc(bitbang, 0);
- mdio(bitbang, 1);
- mii_delay(bitbang);
- mdc(bitbang, 1);
- mii_delay(bitbang);
- mdc(bitbang, 0);
- mdio(bitbang, read);
- mii_delay(bitbang);
- mdc(bitbang, 1);
- mii_delay(bitbang);
- mdc(bitbang, 0);
- mdio(bitbang, !read);
- mii_delay(bitbang);
- mdc(bitbang, 1);
- mii_delay(bitbang);
-
- /* send the PHY address */
- for (j = 0; j < 5; j++) {
- mdc(bitbang, 0);
- mdio(bitbang, (addr & 0x10) != 0);
- mii_delay(bitbang);
- mdc(bitbang, 1);
- mii_delay(bitbang);
- addr <<= 1;
- }
- /* send the register address */
- for (j = 0; j < 5; j++) {
- mdc(bitbang, 0);
- mdio(bitbang, (reg & 0x10) != 0);
- mii_delay(bitbang);
- mdc(bitbang, 1);
- mii_delay(bitbang);
- reg <<= 1;
- }
+ /* Read back to flush the write. */
+ in_be32(bitbang->dat);
}
-static int fs_enet_mii_bb_read(struct mii_bus *bus , int phy_id, int location)
-{
- u16 rdreg;
- int ret, j;
- u8 addr = phy_id & 0xff;
- u8 reg = location & 0xff;
- struct bb_info* bitbang = bus->priv;
-
- bitbang_pre(bitbang, 1, addr, reg);
-
- /* tri-state our MDIO I/O pin so we can read */
- mdc(bitbang, 0);
- mdio_tristate(bitbang);
- mii_delay(bitbang);
- mdc(bitbang, 1);
- mii_delay(bitbang);
-
- /* check the turnaround bit: the PHY should be driving it to zero */
- if (mdio_read(bitbang) != 0) {
- /* PHY didn't drive TA low */
- for (j = 0; j < 32; j++) {
- mdc(bitbang, 0);
- mii_delay(bitbang);
- mdc(bitbang, 1);
- mii_delay(bitbang);
- }
- ret = -1;
- goto out;
- }
-
- mdc(bitbang, 0);
- mii_delay(bitbang);
-
- /* read 16 bits of register data, MSB first */
- rdreg = 0;
- for (j = 0; j < 16; j++) {
- mdc(bitbang, 1);
- mii_delay(bitbang);
- rdreg <<= 1;
- rdreg |= mdio_read(bitbang);
- mdc(bitbang, 0);
- mii_delay(bitbang);
- }
-
- mdc(bitbang, 1);
- mii_delay(bitbang);
- mdc(bitbang, 0);
- mii_delay(bitbang);
- mdc(bitbang, 1);
- mii_delay(bitbang);
-
- ret = rdreg;
-out:
- return ret;
-}
-
-static int fs_enet_mii_bb_write(struct mii_bus *bus, int phy_id, int location, u16 val)
-{
- int j;
- struct bb_info* bitbang = bus->priv;
-
- u8 addr = phy_id & 0xff;
- u8 reg = location & 0xff;
- u16 value = val & 0xffff;
-
- bitbang_pre(bitbang, 0, addr, reg);
-
- /* send the turnaround (10) */
- mdc(bitbang, 0);
- mdio(bitbang, 1);
- mii_delay(bitbang);
- mdc(bitbang, 1);
- mii_delay(bitbang);
- mdc(bitbang, 0);
- mdio(bitbang, 0);
- mii_delay(bitbang);
- mdc(bitbang, 1);
- mii_delay(bitbang);
-
- /* write 16 bits of register data, MSB first */
- for (j = 0; j < 16; j++) {
- mdc(bitbang, 0);
- mdio(bitbang, (value & 0x8000) != 0);
- mii_delay(bitbang);
- mdc(bitbang, 1);
- mii_delay(bitbang);
- value <<= 1;
- }
-
- /*
- * Tri-state the MDIO line.
- */
- mdio_tristate(bitbang);
- mdc(bitbang, 0);
- mii_delay(bitbang);
- mdc(bitbang, 1);
- mii_delay(bitbang);
- return 0;
-}
-
-static int fs_enet_mii_bb_reset(struct mii_bus *bus)
-{
- /*nothing here - dunno how to reset it*/
- return 0;
-}
+static struct mdiobb_ops bb_ops = {
+ .owner = THIS_MODULE,
+ .set_mdc = mdc,
+ .set_mdio_dir = mdio_dir,
+ .set_mdio_data = mdio,
+ .get_mdio_data = mdio_read,
+};
#ifdef CONFIG_PPC_CPM_NEW_BINDING
static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
@@ -305,7 +149,6 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
bitbang->dat = bitbang->dir + 4;
bitbang->mdio_msk = 1 << (31 - mdio_pin);
bitbang->mdc_msk = 1 << (31 - mdc_pin);
- bitbang->delay = 1; /* 1 us between operations */
return 0;
}
@@ -336,23 +179,21 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
int ret = -ENOMEM;
int i;
- new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
- if (!new_bus)
- goto out;
-
bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
if (!bitbang)
- goto out_free_bus;
+ goto out;
+
+ bitbang->ctrl.ops = &bb_ops;
+
+ new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
+ if (!new_bus)
+ goto out_free_priv;
- new_bus->priv = bitbang;
new_bus->name = "CPM2 Bitbanged MII",
- new_bus->read = &fs_enet_mii_bb_read,
- new_bus->write = &fs_enet_mii_bb_write,
- new_bus->reset = &fs_enet_mii_bb_reset,
ret = fs_mii_bitbang_init(new_bus, ofdev->node);
if (ret)
- goto out_free_bitbang;
+ goto out_free_bus;
new_bus->phy_mask = ~0;
new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
@@ -380,10 +221,10 @@ out_free_irqs:
kfree(new_bus->irq);
out_unmap_regs:
iounmap(bitbang->dir);
-out_free_bitbang:
- kfree(bitbang);
out_free_bus:
kfree(new_bus);
+out_free_priv:
+ free_mdio_bitbang(new_bus);
out:
return ret;
}
@@ -394,6 +235,7 @@ static int fs_enet_mdio_remove(struct of_device *ofdev)
struct bb_info *bitbang = bus->priv;
mdiobus_unregister(bus);
+ free_mdio_bitbang(bus);
dev_set_drvdata(&ofdev->dev, NULL);
kfree(bus->irq);
iounmap(bitbang->dir);
@@ -417,12 +259,12 @@ static struct of_platform_driver fs_enet_bb_mdio_driver = {
.remove = fs_enet_mdio_remove,
};
-int fs_enet_mdio_bb_init(void)
+static int fs_enet_mdio_bb_init(void)
{
return of_register_platform_driver(&fs_enet_bb_mdio_driver);
}
-void fs_enet_mdio_bb_exit(void)
+static void fs_enet_mdio_bb_exit(void)
{
of_unregister_platform_driver(&fs_enet_bb_mdio_driver);
}
@@ -437,7 +279,6 @@ static int __devinit fs_mii_bitbang_init(struct bb_info *bitbang,
bitbang->dat = (u32 __iomem *)fmpi->mdio_dat.offset;
bitbang->mdio_msk = 1U << (31 - fmpi->mdio_dat.bit);
bitbang->mdc_msk = 1U << (31 - fmpi->mdc_dat.bit);
- bitbang->delay = fmpi->delay;
return 0;
}
@@ -453,20 +294,19 @@ static int __devinit fs_enet_mdio_probe(struct device *dev)
if (NULL == dev)
return -EINVAL;
- new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+ bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
- if (NULL == new_bus)
+ if (NULL == bitbang)
return -ENOMEM;
- bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
+ bitbang->ctrl.ops = &bb_ops;
- if (NULL == bitbang)
+ new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
+
+ if (NULL == new_bus)
return -ENOMEM;
new_bus->name = "BB MII Bus",
- new_bus->read = &fs_enet_mii_bb_read,
- new_bus->write = &fs_enet_mii_bb_write,
- new_bus->reset = &fs_enet_mii_bb_reset,
new_bus->id = pdev->id;
new_bus->phy_mask = ~0x9;
@@ -498,8 +338,8 @@ static int __devinit fs_enet_mdio_probe(struct device *dev)
return 0;
bus_register_fail:
+ free_mdio_bitbang(new_bus);
kfree(bitbang);
- kfree(new_bus);
return err;
}
@@ -512,9 +352,7 @@ static int fs_enet_mdio_remove(struct device *dev)
dev_set_drvdata(dev, NULL);
- iounmap((void *) (&bus->priv));
- bus->priv = NULL;
- kfree(bus);
+ free_mdio_bitbang(bus);
return 0;
}
@@ -535,4 +373,4 @@ void fs_enet_mdio_bb_exit(void)
{
driver_unregister(&fs_enet_bb_mdio_driver);
}
-
+#endif
--
1.5.3.1
^ permalink raw reply related
* [PATCH 6/9] fs_enet: Be an of_platform device when CONFIG_PPC_CPM_NEW_BINDING is set.
From: Scott Wood @ 2007-09-20 22:01 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20070920220043.GA28769@loki.buserror.net>
The existing OF glue code was crufty and broken. Rather than fix it, it
will be removed, and the ethernet driver now talks to the device tree
directly.
The old, non-CONFIG_PPC_CPM_NEW_BINDING code can go away once CPM
platforms are dropped from arch/ppc (which will hopefully be soon), and
existing arch/powerpc boards that I wasn't able to test on for this
patchset get converted (which should be even sooner).
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
drivers/net/fs_enet/Kconfig | 1 +
drivers/net/fs_enet/fs_enet-main.c | 259 ++++++++++++++++++++++++++++++++---
drivers/net/fs_enet/fs_enet.h | 55 +-------
drivers/net/fs_enet/mac-fcc.c | 89 +++++++++----
drivers/net/fs_enet/mac-fec.c | 19 +++-
drivers/net/fs_enet/mac-scc.c | 53 +++++--
drivers/net/fs_enet/mii-bitbang.c | 269 +++++++++++++++++++++++++++---------
drivers/net/fs_enet/mii-fec.c | 143 +++++++++++++++++++-
include/linux/fs_enet_pd.h | 5 +
9 files changed, 714 insertions(+), 179 deletions(-)
diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig
index e27ee21..2765e49 100644
--- a/drivers/net/fs_enet/Kconfig
+++ b/drivers/net/fs_enet/Kconfig
@@ -11,6 +11,7 @@ config FS_ENET_HAS_SCC
config FS_ENET_HAS_FCC
bool "Chip has an FCC usable for ethernet"
depends on FS_ENET && CPM2
+ select MDIO_BITBANG
default y
config FS_ENET_HAS_FEC
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index a4b76cd..281b7d7 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -44,12 +44,18 @@
#include <asm/irq.h>
#include <asm/uaccess.h>
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+#include <asm/of_platform.h>
+#endif
+
#include "fs_enet.h"
/*************************************************/
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
static char version[] __devinitdata =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")" "\n";
+#endif
MODULE_AUTHOR("Pantelis Antoniou <panto@intracom.gr>");
MODULE_DESCRIPTION("Freescale Ethernet Driver");
@@ -953,6 +959,7 @@ static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
extern int fs_mii_connect(struct net_device *dev);
extern void fs_mii_disconnect(struct net_device *dev);
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
static struct net_device *fs_init_instance(struct device *dev,
struct fs_platform_info *fpi)
{
@@ -1132,6 +1139,7 @@ static int fs_cleanup_instance(struct net_device *ndev)
return 0;
}
+#endif
/**************************************************************************************/
@@ -1140,35 +1148,250 @@ void *fs_enet_immap = NULL;
static int setup_immap(void)
{
- phys_addr_t paddr = 0;
- unsigned long size = 0;
-
#ifdef CONFIG_CPM1
- paddr = IMAP_ADDR;
- size = 0x10000; /* map 64K */
-#endif
-
-#ifdef CONFIG_CPM2
- paddr = CPM_MAP_ADDR;
- size = 0x40000; /* map 256 K */
+ fs_enet_immap = ioremap(IMAP_ADDR, 0x4000);
+ WARN_ON(!fs_enet_immap);
+#elif defined(CONFIG_CPM2)
+ fs_enet_immap = cpm2_immr;
#endif
- fs_enet_immap = ioremap(paddr, size);
- if (fs_enet_immap == NULL)
- return -EBADF; /* XXX ahem; maybe just BUG_ON? */
return 0;
}
static void cleanup_immap(void)
{
- if (fs_enet_immap != NULL) {
- iounmap(fs_enet_immap);
- fs_enet_immap = NULL;
- }
+#if defined(CONFIG_CPM1)
+ iounmap(fs_enet_immap);
+#endif
}
/**************************************************************************************/
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+static int __devinit find_phy(struct device_node *np,
+ struct fs_platform_info *fpi)
+{
+ struct device_node *phynode, *mdionode;
+ struct resource res;
+ int ret = 0, len;
+
+ const u32 *data = of_get_property(np, "phy-handle", &len);
+ if (!data || len != 4)
+ return -EINVAL;
+
+ phynode = of_find_node_by_phandle(*data);
+ if (!phynode)
+ return -EINVAL;
+
+ mdionode = of_get_parent(phynode);
+ if (!phynode)
+ goto out_put_phy;
+
+ ret = of_address_to_resource(mdionode, 0, &res);
+ if (ret)
+ goto out_put_mdio;
+
+ data = of_get_property(phynode, "reg", &len);
+ if (!data || len != 4)
+ goto out_put_mdio;
+
+ snprintf(fpi->bus_id, 16, PHY_ID_FMT, res.start, *data);
+
+out_put_mdio:
+ of_node_put(mdionode);
+out_put_phy:
+ of_node_put(phynode);
+ return ret;
+}
+
+#ifdef CONFIG_FS_ENET_HAS_FEC
+#define IS_FEC(match) ((match)->data == &fs_fec_ops)
+#else
+#define IS_FEC(match) 0
+#endif
+
+static int __devinit fs_enet_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ struct net_device *ndev;
+ struct fs_enet_private *fep;
+ struct fs_platform_info *fpi;
+ const u32 *data;
+ const u8 *mac_addr;
+ int privsize, len, ret = -ENODEV;
+
+ fpi = kzalloc(sizeof(*fpi), GFP_KERNEL);
+ if (!fpi)
+ return -ENOMEM;
+
+ if (!IS_FEC(match)) {
+ data = of_get_property(ofdev->node, "fsl,cpm-command", &len);
+ if (!data || len != 4)
+ goto out_free_fpi;
+
+ fpi->cp_command = *data;
+ }
+
+ fpi->rx_ring = 32;
+ fpi->tx_ring = 32;
+ fpi->rx_copybreak = 240;
+ fpi->use_napi = 0;
+ fpi->napi_weight = 17;
+
+ ret = find_phy(ofdev->node, fpi);
+ if (ret)
+ goto out_free_fpi;
+
+ privsize = sizeof(*fep) +
+ sizeof(struct sk_buff **) *
+ (fpi->rx_ring + fpi->tx_ring);
+
+ ndev = alloc_etherdev(privsize);
+ if (!ndev) {
+ ret = -ENOMEM;
+ goto out_free_fpi;
+ }
+
+ SET_MODULE_OWNER(ndev);
+ dev_set_drvdata(&ofdev->dev, ndev);
+
+ fep = netdev_priv(ndev);
+ fep->dev = &ofdev->dev;
+ fep->fpi = fpi;
+ fep->ops = match->data;
+
+ ret = fep->ops->setup_data(ndev);
+ if (ret)
+ goto out_free_dev;
+
+ fep->rx_skbuff = (struct sk_buff **)&fep[1];
+ fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring;
+
+ spin_lock_init(&fep->lock);
+ spin_lock_init(&fep->tx_lock);
+
+ mac_addr = of_get_mac_address(ofdev->node);
+ if (mac_addr)
+ memcpy(ndev->dev_addr, mac_addr, 6);
+
+ ret = fep->ops->allocate_bd(ndev);
+ if (ret)
+ goto out_cleanup_data;
+
+ fep->rx_bd_base = fep->ring_base;
+ fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring;
+
+ fep->tx_ring = fpi->tx_ring;
+ fep->rx_ring = fpi->rx_ring;
+
+ ndev->open = fs_enet_open;
+ ndev->hard_start_xmit = fs_enet_start_xmit;
+ ndev->tx_timeout = fs_timeout;
+ ndev->watchdog_timeo = 2 * HZ;
+ ndev->stop = fs_enet_close;
+ ndev->get_stats = fs_enet_get_stats;
+ ndev->set_multicast_list = fs_set_multicast_list;
+ if (fpi->use_napi) {
+ ndev->poll = fs_enet_rx_napi;
+ ndev->weight = fpi->napi_weight;
+ }
+ ndev->ethtool_ops = &fs_ethtool_ops;
+ ndev->do_ioctl = fs_ioctl;
+
+ init_timer(&fep->phy_timer_list);
+
+ netif_carrier_off(ndev);
+
+ ret = register_netdev(ndev);
+ if (ret)
+ goto out_free_bd;
+
+ printk(KERN_INFO "%s: fs_enet: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ ndev->name,
+ ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
+ ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
+
+ return 0;
+
+out_free_bd:
+ fep->ops->free_bd(ndev);
+out_cleanup_data:
+ fep->ops->cleanup_data(ndev);
+out_free_dev:
+ free_netdev(ndev);
+ dev_set_drvdata(&ofdev->dev, NULL);
+out_free_fpi:
+ kfree(fpi);
+ return ret;
+}
+
+static int fs_enet_remove(struct of_device *ofdev)
+{
+ struct net_device *ndev = dev_get_drvdata(&ofdev->dev);
+ struct fs_enet_private *fep = netdev_priv(ndev);
+
+ unregister_netdev(ndev);
+
+ fep->ops->free_bd(ndev);
+ fep->ops->cleanup_data(ndev);
+ dev_set_drvdata(fep->dev, NULL);
+
+ free_netdev(ndev);
+ return 0;
+}
+
+static struct of_device_id fs_enet_match[] = {
+#ifdef CONFIG_FS_ENET_HAS_SCC
+ {
+ .compatible = "fsl,cpm1-scc-enet",
+ .data = (void *)&fs_scc_ops,
+ },
+#endif
+#ifdef CONFIG_FS_ENET_HAS_FCC
+ {
+ .compatible = "fsl,cpm2-fcc-enet",
+ .data = (void *)&fs_fcc_ops,
+ },
+#endif
+#ifdef CONFIG_FS_ENET_HAS_FEC
+ {
+ .compatible = "fsl,pq1-fec-enet",
+ .data = (void *)&fs_fec_ops,
+ },
+#endif
+ {}
+};
+
+static struct of_platform_driver fs_enet_driver = {
+ .name = "fs_enet",
+ .match_table = fs_enet_match,
+ .probe = fs_enet_probe,
+ .remove = fs_enet_remove,
+};
+
+static int __init fs_init(void)
+{
+ int r = setup_immap();
+ if (r != 0)
+ return r;
+
+ r = of_register_platform_driver(&fs_enet_driver);
+ if (r != 0)
+ goto out;
+
+ return 0;
+
+out:
+ cleanup_immap();
+ return r;
+}
+
+static void __exit fs_cleanup(void)
+{
+ of_unregister_platform_driver(&fs_enet_driver);
+ cleanup_immap();
+}
+#else
static int __devinit fs_enet_probe(struct device *dev)
{
struct net_device *ndev;
@@ -1282,7 +1505,7 @@ static void __exit fs_cleanup(void)
driver_unregister(&fs_enet_scc_driver);
cleanup_immap();
}
-
+#endif
/**************************************************************************************/
module_init(fs_init);
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
index f8c7ee8..14ebba8 100644
--- a/drivers/net/fs_enet/fs_enet.h
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -24,19 +24,6 @@ struct fec_info {
#include <asm/cpm2.h>
#endif
-/* This is used to operate with pins.
- Note that the actual port size may
- be different; cpm(s) handle it OK */
-struct bb_info {
- u8 mdio_dat_msk;
- u8 mdio_dir_msk;
- u8 *mdio_dir;
- u8 *mdio_dat;
- u8 mdc_msk;
- u8 *mdc_dat;
- int delay;
-};
-
/* hw driver ops */
struct fs_ops {
int (*setup_data)(struct net_device *dev);
@@ -85,47 +72,11 @@ struct phy_info {
#define ENET_RX_ALIGN 16
#define ENET_RX_FRSIZE L1_CACHE_ALIGN(PKT_MAXBUF_SIZE + ENET_RX_ALIGN - 1)
-struct fs_enet_mii_bus {
- struct list_head list;
- spinlock_t mii_lock;
- const struct fs_mii_bus_info *bus_info;
- int refs;
- u32 usage_map;
-
- int (*mii_read)(struct fs_enet_mii_bus *bus,
- int phy_id, int location);
-
- void (*mii_write)(struct fs_enet_mii_bus *bus,
- int phy_id, int location, int value);
-
- union {
- struct {
- unsigned int mii_speed;
- void *fecp;
- } fec;
-
- struct {
- /* note that the actual port size may */
- /* be different; cpm(s) handle it OK */
- u8 mdio_msk;
- u8 *mdio_dir;
- u8 *mdio_dat;
- u8 mdc_msk;
- u8 *mdc_dir;
- u8 *mdc_dat;
- } bitbang;
-
- struct {
- u16 lpa;
- } fixed;
- };
-};
-
struct fs_enet_private {
struct device *dev; /* pointer back to the device (must be initialized first) */
spinlock_t lock; /* during all ops except TX pckt processing */
spinlock_t tx_lock; /* during fs_start_xmit and fs_tx */
- const struct fs_platform_info *fpi;
+ struct fs_platform_info *fpi;
const struct fs_ops *ops;
int rx_ring, tx_ring;
dma_addr_t ring_mem_addr;
@@ -144,7 +95,6 @@ struct fs_enet_private {
u32 msg_enable;
struct mii_if_info mii_if;
unsigned int last_mii_status;
- struct fs_enet_mii_bus *mii_bus;
int interrupt;
struct phy_device *phydev;
@@ -186,9 +136,10 @@ struct fs_enet_private {
};
/***************************************************************************/
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
int fs_enet_mdio_bb_init(void);
-int fs_mii_fixed_init(struct fs_enet_mii_bus *bus);
int fs_enet_mdio_fec_init(void);
+#endif
void fs_init_bds(struct net_device *dev);
void fs_cleanup_bds(struct net_device *dev);
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index 8b30361..10e2a2b 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -42,6 +42,10 @@
#include <asm/irq.h>
#include <asm/uaccess.h>
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+#include <asm/of_device.h>
+#endif
+
#include "fs_enet.h"
/*************************************************/
@@ -74,33 +78,64 @@
#define MAX_CR_CMD_LOOPS 10000
-static inline int fcc_cr_cmd(struct fs_enet_private *fep, u32 mcn, u32 op)
+static inline int fcc_cr_cmd(struct fs_enet_private *fep, u32 op)
{
const struct fs_platform_info *fpi = fep->fpi;
cpm2_map_t *immap = fs_enet_immap;
cpm_cpm2_t *cpmp = &immap->im_cpm;
- u32 v;
int i;
- /* Currently I don't know what feature call will look like. But
- I guess there'd be something like do_cpm_cmd() which will require page & sblock */
- v = mk_cr_cmd(fpi->cp_page, fpi->cp_block, mcn, op);
- W32(cpmp, cp_cpcr, v | CPM_CR_FLG);
+ W32(cpmp, cp_cpcr, fpi->cp_command | op | CPM_CR_FLG);
for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
if ((R32(cpmp, cp_cpcr) & CPM_CR_FLG) == 0)
- break;
-
- if (i >= MAX_CR_CMD_LOOPS) {
- printk(KERN_ERR "%s(): Not able to issue CPM command\n",
- __FUNCTION__);
- return 1;
- }
+ return 0;
- return 0;
+ printk(KERN_ERR "%s(): Not able to issue CPM command\n",
+ __FUNCTION__);
+ return 1;
}
static int do_pd_setup(struct fs_enet_private *fep)
{
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+ struct of_device *ofdev = to_of_device(fep->dev);
+ struct fs_platform_info *fpi = fep->fpi;
+ int ret = -EINVAL;
+
+ fep->interrupt = of_irq_to_resource(ofdev->node, 0, NULL);
+ if (fep->interrupt == NO_IRQ)
+ goto out;
+
+ fep->fcc.fccp = of_iomap(ofdev->node, 0);
+ if (!fep->fcc.fccp)
+ goto out;
+
+ fep->fcc.ep = of_iomap(ofdev->node, 1);
+ if (!fep->fcc.ep)
+ goto out_fccp;
+
+ fep->fcc.fcccp = of_iomap(ofdev->node, 2);
+ if (!fep->fcc.fcccp)
+ goto out_ep;
+
+ fep->fcc.mem = (void *)cpm_dpalloc(128, 8);
+ fpi->dpram_offset = (u32)cpm2_immr;
+ if (IS_ERR_VALUE(fpi->dpram_offset)) {
+ ret = fpi->dpram_offset;
+ goto out_fcccp;
+ }
+
+ return 0;
+
+out_fcccp:
+ iounmap(fep->fcc.fcccp);
+out_ep:
+ iounmap(fep->fcc.ep);
+out_fccp:
+ iounmap(fep->fcc.fccp);
+out:
+ return ret;
+#else
struct platform_device *pdev = to_platform_device(fep->dev);
struct resource *r;
@@ -138,6 +173,7 @@ static int do_pd_setup(struct fs_enet_private *fep)
return -EINVAL;
return 0;
+#endif
}
#define FCC_NAPI_RX_EVENT_MSK (FCC_ENET_RXF | FCC_ENET_RXB)
@@ -148,11 +184,17 @@ static int do_pd_setup(struct fs_enet_private *fep)
static int setup_data(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- const struct fs_platform_info *fpi = fep->fpi;
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
+ struct fs_platform_info *fpi = fep->fpi;
+
+ fpi->cp_command = (fpi->cp_page << 26) |
+ (fpi->cp_block << 21) |
+ (12 << 6);
fep->fcc.idx = fs_get_fcc_index(fpi->fs_no);
if ((unsigned int)fep->fcc.idx >= 3) /* max 3 FCCs */
return -EINVAL;
+#endif
if (do_pd_setup(fep) != 0)
return -EINVAL;
@@ -226,7 +268,7 @@ static void set_multicast_one(struct net_device *dev, const u8 *mac)
W16(ep, fen_taddrh, taddrh);
W16(ep, fen_taddrm, taddrm);
W16(ep, fen_taddrl, taddrl);
- fcc_cr_cmd(fep, 0x0C, CPM_CR_SET_GADDR);
+ fcc_cr_cmd(fep, CPM_CR_SET_GADDR);
}
static void set_multicast_finish(struct net_device *dev)
@@ -281,7 +323,7 @@ static void restart(struct net_device *dev)
/* clear everything (slow & steady does it) */
for (i = 0; i < sizeof(*ep); i++)
- out_8((char *)ep + i, 0);
+ out_8((u8 __iomem *)ep + i, 0);
/* get physical address */
rx_bd_base_phys = fep->ring_mem_addr;
@@ -397,7 +439,7 @@ static void restart(struct net_device *dev)
S8(fcccp, fcc_gfemr, 0x20);
}
- fcc_cr_cmd(fep, 0x0c, CPM_CR_INIT_TRX);
+ fcc_cr_cmd(fep, CPM_CR_INIT_TRX);
/* clear events */
W16(fccp, fcc_fcce, 0xffff);
@@ -515,23 +557,22 @@ int get_regs(struct net_device *dev, void *p, int *sizep)
{
struct fs_enet_private *fep = netdev_priv(dev);
- if (*sizep < sizeof(fcc_t) + sizeof(fcc_c_t) + sizeof(fcc_enet_t))
+ if (*sizep < sizeof(fcc_t) + sizeof(fcc_enet_t) + 1)
return -EINVAL;
memcpy_fromio(p, fep->fcc.fccp, sizeof(fcc_t));
p = (char *)p + sizeof(fcc_t);
- memcpy_fromio(p, fep->fcc.fcccp, sizeof(fcc_c_t));
- p = (char *)p + sizeof(fcc_c_t);
-
memcpy_fromio(p, fep->fcc.ep, sizeof(fcc_enet_t));
+ p = (char *)p + sizeof(fcc_enet_t);
+ memcpy_fromio(p, fep->fcc.fcccp, 1);
return 0;
}
int get_regs_len(struct net_device *dev)
{
- return sizeof(fcc_t) + sizeof(fcc_c_t) + sizeof(fcc_enet_t);
+ return sizeof(fcc_t) + sizeof(fcc_enet_t) + 1;
}
/* Some transmit errors cause the transmitter to shut
@@ -551,7 +592,7 @@ void tx_restart(struct net_device *dev)
udelay(10);
S32(fccp, fcc_gfmr, FCC_GFMR_ENT);
- fcc_cr_cmd(fep, 0x0C, CPM_CR_RESTART_TX);
+ fcc_cr_cmd(fep, CPM_CR_RESTART_TX);
}
/*************************************************************************/
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index 04b4f80..9a02312 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -43,6 +43,10 @@
#include <asm/commproc.h>
#endif
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+#include <asm/of_device.h>
+#endif
+
#include "fs_enet.h"
#include "fec.h"
@@ -95,6 +99,19 @@ static int whack_reset(fec_t * fecp)
static int do_pd_setup(struct fs_enet_private *fep)
{
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+ struct of_device *ofdev = to_of_device(fep->dev);
+
+ fep->interrupt = of_irq_to_resource(ofdev->node, 0, NULL);
+ if (fep->interrupt == NO_IRQ)
+ return -EINVAL;
+
+ fep->fec.fecp = of_iomap(ofdev->node, 0);
+ if (!fep->fcc.fccp)
+ return -EINVAL;
+
+ return 0;
+#else
struct platform_device *pdev = to_platform_device(fep->dev);
struct resource *r;
@@ -110,7 +127,7 @@ static int do_pd_setup(struct fs_enet_private *fep)
return -EINVAL;
return 0;
-
+#endif
}
#define FEC_NAPI_RX_EVENT_MSK (FEC_ENET_RXF | FEC_ENET_RXB)
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index 7540966..7352c61 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -43,6 +43,10 @@
#include <asm/commproc.h>
#endif
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+#include <asm/of_platform.h>
+#endif
+
#include "fs_enet.h"
/*************************************************/
@@ -89,27 +93,38 @@
static inline int scc_cr_cmd(struct fs_enet_private *fep, u32 op)
{
- cpm8xx_t *cpmp = &((immap_t *)fs_enet_immap)->im_cpm;
- u32 v, ch;
- int i = 0;
+ const struct fs_platform_info *fpi = fep->fpi;
+ int i;
- ch = fep->scc.idx << 2;
- v = mk_cr_cmd(ch, op);
- W16(cpmp, cp_cpcr, v | CPM_CR_FLG);
+ W16(cpmp, cp_cpcr, fpi->cp_command | CPM_CR_FLG | (op << 8));
for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
if ((R16(cpmp, cp_cpcr) & CPM_CR_FLG) == 0)
- break;
+ return 0;
- if (i >= MAX_CR_CMD_LOOPS) {
- printk(KERN_ERR "%s(): Not able to issue CPM command\n",
- __FUNCTION__);
- return 1;
- }
- return 0;
+ printk(KERN_ERR "%s(): Not able to issue CPM command\n",
+ __FUNCTION__);
+ return 1;
}
static int do_pd_setup(struct fs_enet_private *fep)
{
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+ struct of_device *ofdev = to_of_device(fep->dev);
+
+ fep->interrupt = of_irq_to_resource(ofdev->node, 0, NULL);
+ if (fep->interrupt == NO_IRQ)
+ return -EINVAL;
+
+ fep->scc.sccp = of_iomap(ofdev->node, 0);
+ if (!fep->scc.sccp)
+ return -EINVAL;
+
+ fep->scc.ep = of_iomap(ofdev->node, 1);
+ if (!fep->scc.ep) {
+ iounmap(fep->scc.sccp);
+ return -EINVAL;
+ }
+#else
struct platform_device *pdev = to_platform_device(fep->dev);
struct resource *r;
@@ -129,6 +144,7 @@ static int do_pd_setup(struct fs_enet_private *fep)
if (fep->scc.ep == NULL)
return -EINVAL;
+#endif
return 0;
}
@@ -141,12 +157,17 @@ static int do_pd_setup(struct fs_enet_private *fep)
static int setup_data(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- const struct fs_platform_info *fpi = fep->fpi;
+
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+ struct fs_platform_info *fpi = fep->fpi;
fep->scc.idx = fs_get_scc_index(fpi->fs_no);
- if ((unsigned int)fep->fcc.idx > 4) /* max 4 SCCs */
+ if ((unsigned int)fep->fcc.idx >= 4) /* max 4 SCCs */
return -EINVAL;
+ fpi->cp_command = fep->fcc.idx << 6;
+#endif
+
do_pd_setup(fep);
fep->scc.hthi = 0;
@@ -154,7 +175,7 @@ static int setup_data(struct net_device *dev)
fep->ev_napi_rx = SCC_NAPI_RX_EVENT_MSK;
fep->ev_rx = SCC_RX_EVENT;
- fep->ev_tx = SCC_TX_EVENT;
+ fep->ev_tx = SCC_TX_EVENT | SCCE_ENET_TXE;
fep->ev_err = SCC_ERR_EVENT_MSK;
return 0;
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index 8f766a5..2b9c44c 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -13,11 +13,6 @@
*/
#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ptrace.h>
-#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
@@ -25,86 +20,77 @@
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/bitops.h>
#include <linux/platform_device.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+#include <linux/of_platform.h>
+#endif
#include "fs_enet.h"
-static int bitbang_prep_bit(u8 **datp, u8 *mskp,
- struct fs_mii_bit *mii_bit)
-{
- void *dat;
- int adv;
- u8 msk;
-
- dat = (void*) mii_bit->offset;
-
- adv = mii_bit->bit >> 3;
- dat = (char *)dat + adv;
-
- msk = 1 << (7 - (mii_bit->bit & 7));
-
- *datp = dat;
- *mskp = msk;
-
- return 0;
-}
+struct bb_info {
+ __be32 __iomem *dir;
+ __be32 __iomem *dat;
+ u32 mdio_msk;
+ u32 mdc_msk;
+ int delay;
+};
-static inline void bb_set(u8 *p, u8 m)
+/* FIXME: If any other users of GPIO crop up, then these will have to
+ * have some sort of global synchronization to avoid races with other
+ * pins on the same port. The ideal solution would probably be to
+ * bind the ports to a GPIO driver, and have this be a client of it.
+ */
+static inline void bb_set(u32 __iomem *p, u32 m)
{
- out_8(p, in_8(p) | m);
+ out_be32(p, in_be32(p) | m);
}
-static inline void bb_clr(u8 *p, u8 m)
+static inline void bb_clr(u32 __iomem *p, u32 m)
{
- out_8(p, in_8(p) & ~m);
+ out_be32(p, in_be32(p) & ~m);
}
-static inline int bb_read(u8 *p, u8 m)
+static inline int bb_read(u32 __iomem *p, u32 m)
{
- return (in_8(p) & m) != 0;
+ return (in_be32(p) & m) != 0;
}
static inline void mdio_active(struct bb_info *bitbang)
{
- bb_set(bitbang->mdio_dir, bitbang->mdio_dir_msk);
+ bb_set(bitbang->dir, bitbang->mdio_msk);
}
-static inline void mdio_tristate(struct bb_info *bitbang )
+static inline void mdio_tristate(struct bb_info *bitbang)
{
- bb_clr(bitbang->mdio_dir, bitbang->mdio_dir_msk);
+ bb_clr(bitbang->dir, bitbang->mdio_msk);
}
-static inline int mdio_read(struct bb_info *bitbang )
+static inline int mdio_read(struct bb_info *bitbang)
{
- return bb_read(bitbang->mdio_dat, bitbang->mdio_dat_msk);
+ return bb_read(bitbang->dat, bitbang->mdio_msk);
}
-static inline void mdio(struct bb_info *bitbang , int what)
+static inline void mdio(struct bb_info *bitbang, int what)
{
if (what)
- bb_set(bitbang->mdio_dat, bitbang->mdio_dat_msk);
+ bb_set(bitbang->dat, bitbang->mdio_msk);
else
- bb_clr(bitbang->mdio_dat, bitbang->mdio_dat_msk);
+ bb_clr(bitbang->dat, bitbang->mdio_msk);
}
-static inline void mdc(struct bb_info *bitbang , int what)
+static inline void mdc(struct bb_info *bitbang, int what)
{
if (what)
- bb_set(bitbang->mdc_dat, bitbang->mdc_msk);
+ bb_set(bitbang->dat, bitbang->mdc_msk);
else
- bb_clr(bitbang->mdc_dat, bitbang->mdc_msk);
+ bb_clr(bitbang->dat, bitbang->mdc_msk);
}
-static inline void mii_delay(struct bb_info *bitbang )
+static inline void mii_delay(struct bb_info *bitbang)
{
udelay(bitbang->delay);
}
@@ -280,29 +266,178 @@ static int fs_enet_mii_bb_reset(struct mii_bus *bus)
return 0;
}
-static int fs_mii_bitbang_init(struct bb_info *bitbang, struct fs_mii_bb_platform_info* fmpi)
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
+ struct device_node *np)
{
- int r;
+ struct resource res;
+ const u32 *data;
+ int mdio_pin, mdc_pin, len;
+ struct bb_info *bitbang = bus->priv;
- bitbang->delay = fmpi->delay;
+ int ret = of_address_to_resource(np, 0, &res);
+ if (ret)
+ return ret;
+
+ if (res.end - res.start < 13)
+ return -ENODEV;
+
+ /* This should really encode the pin number as well, but all
+ * we get is an int, and the odds of multiple bitbang mdio buses
+ * is low enough that it's not worth going too crazy.
+ */
+ bus->id = res.start;
+
+ data = of_get_property(np, "fsl,mdio-pin", &len);
+ if (!data || len != 4)
+ return -ENODEV;
+ mdio_pin = *data;
+
+ data = of_get_property(np, "fsl,mdc-pin", &len);
+ if (!data || len != 4)
+ return -ENODEV;
+ mdc_pin = *data;
+
+ bitbang->dir = ioremap(res.start, res.end - res.start + 1);
+ if (!bitbang->dir)
+ return -ENOMEM;
+
+ bitbang->dat = bitbang->dir + 4;
+ bitbang->mdio_msk = 1 << (31 - mdio_pin);
+ bitbang->mdc_msk = 1 << (31 - mdc_pin);
+ bitbang->delay = 1; /* 1 us between operations */
- r = bitbang_prep_bit(&bitbang->mdio_dir,
- &bitbang->mdio_dir_msk,
- &fmpi->mdio_dir);
- if (r != 0)
- return r;
-
- r = bitbang_prep_bit(&bitbang->mdio_dat,
- &bitbang->mdio_dat_msk,
- &fmpi->mdio_dat);
- if (r != 0)
- return r;
-
- r = bitbang_prep_bit(&bitbang->mdc_dat,
- &bitbang->mdc_msk,
- &fmpi->mdc_dat);
- if (r != 0)
- return r;
+ return 0;
+}
+
+static void __devinit add_phy(struct mii_bus *bus, struct device_node *np)
+{
+ const u32 *data;
+ int len, id, irq;
+
+ data = of_get_property(np, "reg", &len);
+ if (!data || len != 4)
+ return;
+
+ id = *data;
+ bus->phy_mask &= ~(1 << id);
+
+ irq = of_irq_to_resource(np, 0, NULL);
+ if (irq != NO_IRQ)
+ bus->irq[id] = irq;
+}
+
+static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ struct device_node *np = NULL;
+ struct mii_bus *new_bus;
+ struct bb_info *bitbang;
+ int ret = -ENOMEM;
+ int i;
+
+ new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+ if (!new_bus)
+ goto out;
+
+ bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
+ if (!bitbang)
+ goto out_free_bus;
+
+ new_bus->priv = bitbang;
+ new_bus->name = "CPM2 Bitbanged MII",
+ new_bus->read = &fs_enet_mii_bb_read,
+ new_bus->write = &fs_enet_mii_bb_write,
+ new_bus->reset = &fs_enet_mii_bb_reset,
+
+ ret = fs_mii_bitbang_init(new_bus, ofdev->node);
+ if (ret)
+ goto out_free_bitbang;
+
+ new_bus->phy_mask = ~0;
+ new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+ if (!new_bus->irq)
+ goto out_unmap_regs;
+
+ for (i = 0; i < PHY_MAX_ADDR; i++)
+ new_bus->irq[i] = -1;
+
+ while ((np = of_get_next_child(ofdev->node, np)))
+ if (!strcmp(np->type, "ethernet-phy"))
+ add_phy(new_bus, np);
+
+ new_bus->dev = &ofdev->dev;
+ dev_set_drvdata(&ofdev->dev, new_bus);
+
+ ret = mdiobus_register(new_bus);
+ if (ret)
+ goto out_free_irqs;
+
+ return 0;
+
+out_free_irqs:
+ dev_set_drvdata(&ofdev->dev, NULL);
+ kfree(new_bus->irq);
+out_unmap_regs:
+ iounmap(bitbang->dir);
+out_free_bitbang:
+ kfree(bitbang);
+out_free_bus:
+ kfree(new_bus);
+out:
+ return ret;
+}
+
+static int fs_enet_mdio_remove(struct of_device *ofdev)
+{
+ struct mii_bus *bus = dev_get_drvdata(&ofdev->dev);
+ struct bb_info *bitbang = bus->priv;
+
+ mdiobus_unregister(bus);
+ dev_set_drvdata(&ofdev->dev, NULL);
+ kfree(bus->irq);
+ iounmap(bitbang->dir);
+ kfree(bitbang);
+ kfree(bus);
+
+ return 0;
+}
+
+static struct of_device_id fs_enet_mdio_bb_match[] = {
+ {
+ .compatible = "fsl,cpm2-mdio-bitbang",
+ },
+ {},
+};
+
+static struct of_platform_driver fs_enet_bb_mdio_driver = {
+ .name = "fsl-bb-mdio",
+ .match_table = fs_enet_mdio_bb_match,
+ .probe = fs_enet_mdio_probe,
+ .remove = fs_enet_mdio_remove,
+};
+
+int fs_enet_mdio_bb_init(void)
+{
+ return of_register_platform_driver(&fs_enet_bb_mdio_driver);
+}
+
+void fs_enet_mdio_bb_exit(void)
+{
+ of_unregister_platform_driver(&fs_enet_bb_mdio_driver);
+}
+
+module_init(fs_enet_mdio_bb_init);
+module_exit(fs_enet_mdio_bb_exit);
+#else
+static int __devinit fs_mii_bitbang_init(struct bb_info *bitbang,
+ struct fs_mii_bb_platform_info *fmpi)
+{
+ bitbang->dir = (u32 __iomem *)fmpi->mdio_dir.offset;
+ bitbang->dat = (u32 __iomem *)fmpi->mdio_dat.offset;
+ bitbang->mdio_msk = 1U << (31 - fmpi->mdio_dat.bit);
+ bitbang->mdc_msk = 1U << (31 - fmpi->mdc_dat.bit);
+ bitbang->delay = fmpi->delay;
return 0;
}
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
index 53db696..f91c38d 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -36,6 +36,10 @@
#include <asm/irq.h>
#include <asm/uaccess.h>
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+#include <asm/of_platform.h>
+#endif
+
#include "fs_enet.h"
#include "fec.h"
@@ -47,6 +51,7 @@
#define FEC_MII_LOOPS 10000
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
static int match_has_phy (struct device *dev, void* data)
{
struct platform_device* pdev = container_of(dev, struct platform_device, dev);
@@ -90,6 +95,7 @@ static int fs_mii_fec_init(struct fec_info* fec, struct fs_mii_fec_platform_info
return 0;
}
+#endif
static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location)
{
@@ -145,6 +151,141 @@ static int fs_enet_fec_mii_reset(struct mii_bus *bus)
return 0;
}
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+static void __devinit add_phy(struct mii_bus *bus, struct device_node *np)
+{
+ const u32 *data;
+ int len, id, irq;
+
+ data = of_get_property(np, "reg", &len);
+ if (!data || len != 4)
+ return;
+
+ id = *data;
+ bus->phy_mask &= ~(1 << id);
+
+ irq = of_irq_to_resource(np, 0, NULL);
+ if (irq != NO_IRQ)
+ bus->irq[id] = irq;
+}
+
+static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ struct device_node *np = NULL;
+ struct resource res;
+ struct mii_bus *new_bus;
+ struct fec_info *fec;
+ int ret = -ENOMEM, i;
+
+ new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+ if (!new_bus)
+ goto out;
+
+ fec = kzalloc(sizeof(struct fec_info), GFP_KERNEL);
+ if (!fec)
+ goto out_mii;
+
+ new_bus->priv = fec;
+ new_bus->name = "FEC MII Bus";
+ new_bus->read = &fs_enet_fec_mii_read;
+ new_bus->write = &fs_enet_fec_mii_write;
+ new_bus->reset = &fs_enet_fec_mii_reset;
+
+ ret = of_address_to_resource(ofdev->node, 0, &res);
+ if (ret)
+ return ret;
+
+ new_bus->id = res.start;
+
+ fec->fecp = ioremap(res.start, res.end - res.start + 1);
+ if (!fec->fecp)
+ goto out_fec;
+
+ fec->mii_speed = ((ppc_proc_freq + 4999999) / 5000000) << 1;
+
+ setbits32(&fec->fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
+ setbits32(&fec->fecp->fec_ecntrl, FEC_ECNTRL_PINMUX |
+ FEC_ECNTRL_ETHER_EN);
+ out_be32(&fec->fecp->fec_ievent, FEC_ENET_MII);
+ out_be32(&fec->fecp->fec_mii_speed, fec->mii_speed);
+
+ new_bus->phy_mask = ~0;
+ new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+ if (!new_bus->irq)
+ goto out_unmap_regs;
+
+ for (i = 0; i < PHY_MAX_ADDR; i++)
+ new_bus->irq[i] = -1;
+
+ while ((np = of_get_next_child(ofdev->node, np)))
+ if (!strcmp(np->type, "ethernet-phy"))
+ add_phy(new_bus, np);
+
+ new_bus->dev = &ofdev->dev;
+ dev_set_drvdata(&ofdev->dev, new_bus);
+
+ ret = mdiobus_register(new_bus);
+ if (ret)
+ goto out_free_irqs;
+
+ return 0;
+
+out_free_irqs:
+ dev_set_drvdata(&ofdev->dev, NULL);
+ kfree(new_bus->irq);
+out_unmap_regs:
+ iounmap(fec->fecp);
+out_fec:
+ kfree(fec);
+out_mii:
+ kfree(new_bus);
+out:
+ return ret;
+}
+
+static int fs_enet_mdio_remove(struct of_device *ofdev)
+{
+ struct mii_bus *bus = dev_get_drvdata(&ofdev->dev);
+ struct fec_info *fec = bus->priv;
+
+ mdiobus_unregister(bus);
+ dev_set_drvdata(&ofdev->dev, NULL);
+ kfree(bus->irq);
+ iounmap(fec->fecp);
+ kfree(fec);
+ kfree(bus);
+
+ return 0;
+}
+
+static struct of_device_id fs_enet_mdio_fec_match[] = {
+ {
+ .compatible = "fsl,pq1-fec-mdio",
+ },
+ {},
+};
+
+static struct of_platform_driver fs_enet_fec_mdio_driver = {
+ .name = "fsl-fec-mdio",
+ .match_table = fs_enet_mdio_fec_match,
+ .probe = fs_enet_mdio_probe,
+ .remove = fs_enet_mdio_remove,
+};
+
+static int fs_enet_mdio_fec_init(void)
+{
+ return of_register_platform_driver(&fs_enet_fec_mdio_driver);
+}
+
+static void fs_enet_mdio_fec_exit(void)
+{
+ of_unregister_platform_driver(&fs_enet_fec_mdio_driver);
+}
+
+module_init(fs_enet_mdio_fec_init);
+module_exit(fs_enet_mdio_fec_exit);
+#else
static int __devinit fs_enet_fec_mdio_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -235,4 +376,4 @@ void fs_enet_mdio_fec_exit(void)
{
driver_unregister(&fs_enet_fec_mdio_driver);
}
-
+#endif
diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h
index 815c6f9..9bc045b 100644
--- a/include/linux/fs_enet_pd.h
+++ b/include/linux/fs_enet_pd.h
@@ -120,6 +120,7 @@ struct fs_platform_info {
u32 cp_page; /* CPM page */
u32 cp_block; /* CPM sblock */
+ u32 cp_command; /* CPM page/sblock/mcn */
u32 clk_trx; /* some stuff for pins & mux configuration*/
u32 clk_rx;
@@ -134,7 +135,11 @@ struct fs_platform_info {
u32 device_flags;
int phy_addr; /* the phy address (-1 no phy) */
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+ char bus_id[16];
+#else
const char* bus_id;
+#endif
int phy_irq; /* the phy irq (if it exists) */
const struct fs_mii_bus_info *bus_info;
--
1.5.3.1
^ permalink raw reply related
* [PATCH 9/9] fs_enet: sparse fixes
From: Scott Wood @ 2007-09-20 22:01 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20070920220043.GA28769@loki.buserror.net>
Mostly a bunch of __iomem annotations.
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
drivers/net/fs_enet/fs_enet-main.c | 16 +++++-----
drivers/net/fs_enet/fs_enet.h | 30 +++++++++---------
drivers/net/fs_enet/mac-fcc.c | 60 ++++++++++++++++++++---------------
drivers/net/fs_enet/mac-fec.c | 34 ++++++++++----------
drivers/net/fs_enet/mac-scc.c | 37 +++++++++++-----------
drivers/net/fs_enet/mii-fec.c | 6 ++--
6 files changed, 96 insertions(+), 87 deletions(-)
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 281b7d7..876de8c 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -62,7 +62,7 @@ MODULE_DESCRIPTION("Freescale Ethernet Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
-int fs_enet_debug = -1; /* -1 == use FS_ENET_DEF_MSG_ENABLE as value */
+static int fs_enet_debug = -1; /* -1 == use FS_ENET_DEF_MSG_ENABLE as value */
module_param(fs_enet_debug, int, 0);
MODULE_PARM_DESC(fs_enet_debug,
"Freescale bitmapped debugging message enable value");
@@ -88,7 +88,7 @@ static int fs_enet_rx_napi(struct net_device *dev, int *budget)
{
struct fs_enet_private *fep = netdev_priv(dev);
const struct fs_platform_info *fpi = fep->fpi;
- cbd_t *bdp;
+ cbd_t __iomem *bdp;
struct sk_buff *skb, *skbn, *skbt;
int received = 0;
u16 pkt_len, sc;
@@ -240,7 +240,7 @@ static int fs_enet_rx_non_napi(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
const struct fs_platform_info *fpi = fep->fpi;
- cbd_t *bdp;
+ cbd_t __iomem *bdp;
struct sk_buff *skb, *skbn, *skbt;
int received = 0;
u16 pkt_len, sc;
@@ -365,7 +365,7 @@ static int fs_enet_rx_non_napi(struct net_device *dev)
static void fs_enet_tx(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- cbd_t *bdp;
+ cbd_t __iomem *bdp;
struct sk_buff *skb;
int dirtyidx, do_wake, do_restart;
u16 sc;
@@ -513,7 +513,7 @@ fs_enet_interrupt(int irq, void *dev_id)
void fs_init_bds(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- cbd_t *bdp;
+ cbd_t __iomem *bdp;
struct sk_buff *skb;
int i;
@@ -567,7 +567,7 @@ void fs_cleanup_bds(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
struct sk_buff *skb;
- cbd_t *bdp;
+ cbd_t __iomem *bdp;
int i;
/*
@@ -608,7 +608,7 @@ void fs_cleanup_bds(struct net_device *dev)
static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- cbd_t *bdp;
+ cbd_t __iomem *bdp;
int curidx;
u16 sc;
unsigned long flags;
@@ -1144,7 +1144,7 @@ static int fs_cleanup_instance(struct net_device *ndev)
/**************************************************************************************/
/* handy pointer to the immap */
-void *fs_enet_immap = NULL;
+void __iomem *fs_enet_immap = NULL;
static int setup_immap(void)
{
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
index 14ebba8..4a8a101 100644
--- a/drivers/net/fs_enet/fs_enet.h
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -15,7 +15,7 @@
#include <asm/commproc.h>
struct fec_info {
- fec_t *fecp;
+ fec_t __iomem *fecp;
u32 mii_speed;
};
#endif
@@ -80,14 +80,14 @@ struct fs_enet_private {
const struct fs_ops *ops;
int rx_ring, tx_ring;
dma_addr_t ring_mem_addr;
- void *ring_base;
+ void __iomem *ring_base;
struct sk_buff **rx_skbuff;
struct sk_buff **tx_skbuff;
- cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */
- cbd_t *tx_bd_base;
- cbd_t *dirty_tx; /* ring entries to be free()ed. */
- cbd_t *cur_rx;
- cbd_t *cur_tx;
+ cbd_t __iomem *rx_bd_base; /* Address of Rx and Tx buffers. */
+ cbd_t __iomem *tx_bd_base;
+ cbd_t __iomem *dirty_tx; /* ring entries to be free()ed. */
+ cbd_t __iomem *cur_rx;
+ cbd_t __iomem *cur_tx;
int tx_free;
struct net_device_stats stats;
struct timer_list phy_timer_list;
@@ -112,23 +112,23 @@ struct fs_enet_private {
union {
struct {
int idx; /* FEC1 = 0, FEC2 = 1 */
- void *fecp; /* hw registers */
+ void __iomem *fecp; /* hw registers */
u32 hthi, htlo; /* state for multicast */
} fec;
struct {
int idx; /* FCC1-3 = 0-2 */
- void *fccp; /* hw registers */
- void *ep; /* parameter ram */
- void *fcccp; /* hw registers cont. */
- void *mem; /* FCC DPRAM */
+ void __iomem *fccp; /* hw registers */
+ void __iomem *ep; /* parameter ram */
+ void __iomem *fcccp; /* hw registers cont. */
+ void __iomem *mem; /* FCC DPRAM */
u32 gaddrh, gaddrl; /* group address */
} fcc;
struct {
int idx; /* FEC1 = 0, FEC2 = 1 */
- void *sccp; /* hw registers */
- void *ep; /* parameter ram */
+ void __iomem *sccp; /* hw registers */
+ void __iomem *ep; /* parameter ram */
u32 hthi, htlo; /* state for multicast */
} scc;
@@ -199,7 +199,7 @@ extern const struct fs_ops fs_scc_ops;
/*******************************************************************/
/* handy pointer to the immap */
-extern void *fs_enet_immap;
+extern void __iomem *fs_enet_immap;
/*******************************************************************/
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index 10e2a2b..fe3e4c3 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -81,8 +81,6 @@
static inline int fcc_cr_cmd(struct fs_enet_private *fep, u32 op)
{
const struct fs_platform_info *fpi = fep->fpi;
- cpm2_map_t *immap = fs_enet_immap;
- cpm_cpm2_t *cpmp = &immap->im_cpm;
int i;
W32(cpmp, cp_cpcr, fpi->cp_command | op | CPM_CR_FLG);
@@ -118,8 +116,8 @@ static int do_pd_setup(struct fs_enet_private *fep)
if (!fep->fcc.fcccp)
goto out_ep;
- fep->fcc.mem = (void *)cpm_dpalloc(128, 8);
- fpi->dpram_offset = (u32)cpm2_immr;
+ fep->fcc.mem = (void __iomem *)cpm2_immr;
+ fpi->dpram_offset = cpm_dpalloc(128, 8);
if (IS_ERR_VALUE(fpi->dpram_offset)) {
ret = fpi->dpram_offset;
goto out_fcccp;
@@ -212,7 +210,7 @@ static int allocate_bd(struct net_device *dev)
struct fs_enet_private *fep = netdev_priv(dev);
const struct fs_platform_info *fpi = fep->fpi;
- fep->ring_base = dma_alloc_coherent(fep->dev,
+ fep->ring_base = (void __iomem __force *)dma_alloc_coherent(fep->dev,
(fpi->tx_ring + fpi->rx_ring) *
sizeof(cbd_t), &fep->ring_mem_addr,
GFP_KERNEL);
@@ -230,7 +228,7 @@ static void free_bd(struct net_device *dev)
if (fep->ring_base)
dma_free_coherent(fep->dev,
(fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t),
- fep->ring_base, fep->ring_mem_addr);
+ (void __force *)fep->ring_base, fep->ring_mem_addr);
}
static void cleanup_data(struct net_device *dev)
@@ -241,7 +239,7 @@ static void cleanup_data(struct net_device *dev)
static void set_promiscuous_mode(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fcc_t *fccp = fep->fcc.fccp;
+ fcc_t __iomem *fccp = fep->fcc.fccp;
S32(fccp, fcc_fpsmr, FCC_PSMR_PRO);
}
@@ -249,7 +247,7 @@ static void set_promiscuous_mode(struct net_device *dev)
static void set_multicast_start(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fcc_enet_t *ep = fep->fcc.ep;
+ fcc_enet_t __iomem *ep = fep->fcc.ep;
W32(ep, fen_gaddrh, 0);
W32(ep, fen_gaddrl, 0);
@@ -258,7 +256,7 @@ static void set_multicast_start(struct net_device *dev)
static void set_multicast_one(struct net_device *dev, const u8 *mac)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fcc_enet_t *ep = fep->fcc.ep;
+ fcc_enet_t __iomem *ep = fep->fcc.ep;
u16 taddrh, taddrm, taddrl;
taddrh = ((u16)mac[5] << 8) | mac[4];
@@ -274,8 +272,8 @@ static void set_multicast_one(struct net_device *dev, const u8 *mac)
static void set_multicast_finish(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fcc_t *fccp = fep->fcc.fccp;
- fcc_enet_t *ep = fep->fcc.ep;
+ fcc_t __iomem *fccp = fep->fcc.fccp;
+ fcc_enet_t __iomem *ep = fep->fcc.ep;
/* clear promiscuous always */
C32(fccp, fcc_fpsmr, FCC_PSMR_PRO);
@@ -310,12 +308,14 @@ static void restart(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
const struct fs_platform_info *fpi = fep->fpi;
- fcc_t *fccp = fep->fcc.fccp;
- fcc_c_t *fcccp = fep->fcc.fcccp;
- fcc_enet_t *ep = fep->fcc.ep;
+ fcc_t __iomem *fccp = fep->fcc.fccp;
+ fcc_c_t __iomem *fcccp = fep->fcc.fcccp;
+ fcc_enet_t __iomem *ep = fep->fcc.ep;
dma_addr_t rx_bd_base_phys, tx_bd_base_phys;
u16 paddrh, paddrm, paddrl;
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
u16 mem_addr;
+#endif
const unsigned char *mac;
int i;
@@ -347,14 +347,22 @@ static void restart(struct net_device *dev)
* this area.
*/
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+ W16(ep, fen_genfcc.fcc_riptr, fpi->dpram_offset);
+ W16(ep, fen_genfcc.fcc_tiptr, fpi->dpram_offset + 32);
+
+ W16(ep, fen_padptr, fpi->dpram_offset + 64);
+#else
mem_addr = (u32) fep->fcc.mem; /* de-fixup dpram offset */
W16(ep, fen_genfcc.fcc_riptr, (mem_addr & 0xffff));
W16(ep, fen_genfcc.fcc_tiptr, ((mem_addr + 32) & 0xffff));
+
W16(ep, fen_padptr, mem_addr + 64);
+#endif
/* fill with special symbol... */
- memset(fep->fcc.mem + fpi->dpram_offset + 64, 0x88, 32);
+ memset_io(fep->fcc.mem + fpi->dpram_offset + 64, 0x88, 32);
W32(ep, fen_genfcc.fcc_rbptr, 0);
W32(ep, fen_genfcc.fcc_tbptr, 0);
@@ -470,7 +478,7 @@ static void restart(struct net_device *dev)
static void stop(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fcc_t *fccp = fep->fcc.fccp;
+ fcc_t __iomem *fccp = fep->fcc.fccp;
/* stop ethernet */
C32(fccp, fcc_gfmr, FCC_GFMR_ENR | FCC_GFMR_ENT);
@@ -497,7 +505,7 @@ static void post_free_irq(struct net_device *dev, int irq)
static void napi_clear_rx_event(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fcc_t *fccp = fep->fcc.fccp;
+ fcc_t __iomem *fccp = fep->fcc.fccp;
W16(fccp, fcc_fcce, FCC_NAPI_RX_EVENT_MSK);
}
@@ -505,7 +513,7 @@ static void napi_clear_rx_event(struct net_device *dev)
static void napi_enable_rx(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fcc_t *fccp = fep->fcc.fccp;
+ fcc_t __iomem *fccp = fep->fcc.fccp;
S16(fccp, fcc_fccm, FCC_NAPI_RX_EVENT_MSK);
}
@@ -513,7 +521,7 @@ static void napi_enable_rx(struct net_device *dev)
static void napi_disable_rx(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fcc_t *fccp = fep->fcc.fccp;
+ fcc_t __iomem *fccp = fep->fcc.fccp;
C16(fccp, fcc_fccm, FCC_NAPI_RX_EVENT_MSK);
}
@@ -526,7 +534,7 @@ static void rx_bd_done(struct net_device *dev)
static void tx_kickstart(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fcc_t *fccp = fep->fcc.fccp;
+ fcc_t __iomem *fccp = fep->fcc.fccp;
S16(fccp, fcc_ftodr, 0x8000);
}
@@ -534,7 +542,7 @@ static void tx_kickstart(struct net_device *dev)
static u32 get_int_events(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fcc_t *fccp = fep->fcc.fccp;
+ fcc_t __iomem *fccp = fep->fcc.fccp;
return (u32)R16(fccp, fcc_fcce);
}
@@ -542,7 +550,7 @@ static u32 get_int_events(struct net_device *dev)
static void clear_int_events(struct net_device *dev, u32 int_events)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fcc_t *fccp = fep->fcc.fccp;
+ fcc_t __iomem *fccp = fep->fcc.fccp;
W16(fccp, fcc_fcce, int_events & 0xffff);
}
@@ -553,7 +561,7 @@ static void ev_error(struct net_device *dev, u32 int_events)
": %s FS_ENET ERROR(s) 0x%x\n", dev->name, int_events);
}
-int get_regs(struct net_device *dev, void *p, int *sizep)
+static int get_regs(struct net_device *dev, void *p, int *sizep)
{
struct fs_enet_private *fep = netdev_priv(dev);
@@ -570,7 +578,7 @@ int get_regs(struct net_device *dev, void *p, int *sizep)
return 0;
}
-int get_regs_len(struct net_device *dev)
+static int get_regs_len(struct net_device *dev)
{
return sizeof(fcc_t) + sizeof(fcc_enet_t) + 1;
}
@@ -583,10 +591,10 @@ int get_regs_len(struct net_device *dev)
* CPM37, we must disable and then re-enable the transmitter
* following a Late Collision, Underrun, or Retry Limit error.
*/
-void tx_restart(struct net_device *dev)
+static void tx_restart(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fcc_t *fccp = fep->fcc.fccp;
+ fcc_t __iomem *fccp = fep->fcc.fccp;
C32(fccp, fcc_gfmr, FCC_GFMR_ENT);
udelay(10);
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index 9a02312..4af6858 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -83,7 +83,7 @@
*/
#define FEC_RESET_DELAY 50
-static int whack_reset(fec_t * fecp)
+static int whack_reset(fec_t __iomem *fecp)
{
int i;
@@ -159,7 +159,7 @@ static int allocate_bd(struct net_device *dev)
struct fs_enet_private *fep = netdev_priv(dev);
const struct fs_platform_info *fpi = fep->fpi;
- fep->ring_base = dma_alloc_coherent(fep->dev,
+ fep->ring_base = (void __force __iomem *)dma_alloc_coherent(fep->dev,
(fpi->tx_ring + fpi->rx_ring) *
sizeof(cbd_t), &fep->ring_mem_addr,
GFP_KERNEL);
@@ -177,7 +177,7 @@ static void free_bd(struct net_device *dev)
if(fep->ring_base)
dma_free_coherent(fep->dev, (fpi->tx_ring + fpi->rx_ring)
* sizeof(cbd_t),
- fep->ring_base,
+ (void __force *)fep->ring_base,
fep->ring_mem_addr);
}
@@ -189,7 +189,7 @@ static void cleanup_data(struct net_device *dev)
static void set_promiscuous_mode(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fec_t *fecp = fep->fec.fecp;
+ fec_t __iomem *fecp = fep->fec.fecp;
FS(fecp, r_cntrl, FEC_RCNTRL_PROM);
}
@@ -237,7 +237,7 @@ static void set_multicast_one(struct net_device *dev, const u8 *mac)
static void set_multicast_finish(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fec_t *fecp = fep->fec.fecp;
+ fec_t __iomem *fecp = fep->fec.fecp;
/* if all multi or too many multicasts; just enable all */
if ((dev->flags & IFF_ALLMULTI) != 0 ||
@@ -271,7 +271,7 @@ static void restart(struct net_device *dev)
u32 cptr;
#endif
struct fs_enet_private *fep = netdev_priv(dev);
- fec_t *fecp = fep->fec.fecp;
+ fec_t __iomem *fecp = fep->fec.fecp;
const struct fs_platform_info *fpi = fep->fpi;
dma_addr_t rx_bd_base_phys, tx_bd_base_phys;
int r;
@@ -399,7 +399,7 @@ static void stop(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
const struct fs_platform_info *fpi = fep->fpi;
- fec_t *fecp = fep->fec.fecp;
+ fec_t __iomem *fecp = fep->fec.fecp;
struct fec_info* feci= fep->phydev->bus->priv;
@@ -461,7 +461,7 @@ static void post_free_irq(struct net_device *dev, int irq)
static void napi_clear_rx_event(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fec_t *fecp = fep->fec.fecp;
+ fec_t __iomem *fecp = fep->fec.fecp;
FW(fecp, ievent, FEC_NAPI_RX_EVENT_MSK);
}
@@ -469,7 +469,7 @@ static void napi_clear_rx_event(struct net_device *dev)
static void napi_enable_rx(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fec_t *fecp = fep->fec.fecp;
+ fec_t __iomem *fecp = fep->fec.fecp;
FS(fecp, imask, FEC_NAPI_RX_EVENT_MSK);
}
@@ -477,7 +477,7 @@ static void napi_enable_rx(struct net_device *dev)
static void napi_disable_rx(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fec_t *fecp = fep->fec.fecp;
+ fec_t __iomem *fecp = fep->fec.fecp;
FC(fecp, imask, FEC_NAPI_RX_EVENT_MSK);
}
@@ -485,7 +485,7 @@ static void napi_disable_rx(struct net_device *dev)
static void rx_bd_done(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fec_t *fecp = fep->fec.fecp;
+ fec_t __iomem *fecp = fep->fec.fecp;
FW(fecp, r_des_active, 0x01000000);
}
@@ -493,7 +493,7 @@ static void rx_bd_done(struct net_device *dev)
static void tx_kickstart(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fec_t *fecp = fep->fec.fecp;
+ fec_t __iomem *fecp = fep->fec.fecp;
FW(fecp, x_des_active, 0x01000000);
}
@@ -501,7 +501,7 @@ static void tx_kickstart(struct net_device *dev)
static u32 get_int_events(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fec_t *fecp = fep->fec.fecp;
+ fec_t __iomem *fecp = fep->fec.fecp;
return FR(fecp, ievent) & FR(fecp, imask);
}
@@ -509,7 +509,7 @@ static u32 get_int_events(struct net_device *dev)
static void clear_int_events(struct net_device *dev, u32 int_events)
{
struct fs_enet_private *fep = netdev_priv(dev);
- fec_t *fecp = fep->fec.fecp;
+ fec_t __iomem *fecp = fep->fec.fecp;
FW(fecp, ievent, int_events);
}
@@ -520,7 +520,7 @@ static void ev_error(struct net_device *dev, u32 int_events)
": %s FEC ERROR(s) 0x%x\n", dev->name, int_events);
}
-int get_regs(struct net_device *dev, void *p, int *sizep)
+static int get_regs(struct net_device *dev, void *p, int *sizep)
{
struct fs_enet_private *fep = netdev_priv(dev);
@@ -532,12 +532,12 @@ int get_regs(struct net_device *dev, void *p, int *sizep)
return 0;
}
-int get_regs_len(struct net_device *dev)
+static int get_regs_len(struct net_device *dev)
{
return sizeof(fec_t);
}
-void tx_restart(struct net_device *dev)
+static void tx_restart(struct net_device *dev)
{
/* nothing */
}
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index 7352c61..880471f 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -191,7 +191,8 @@ static int allocate_bd(struct net_device *dev)
if (IS_ERR_VALUE(fep->ring_mem_addr))
return -ENOMEM;
- fep->ring_base = cpm_dpram_addr(fep->ring_mem_addr);
+ fep->ring_base = (void __iomem __force*)
+ cpm_dpram_addr(fep->ring_mem_addr);
return 0;
}
@@ -212,7 +213,7 @@ static void cleanup_data(struct net_device *dev)
static void set_promiscuous_mode(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- scc_t *sccp = fep->scc.sccp;
+ scc_t __iomem *sccp = fep->scc.sccp;
S16(sccp, scc_psmr, SCC_PSMR_PRO);
}
@@ -220,7 +221,7 @@ static void set_promiscuous_mode(struct net_device *dev)
static void set_multicast_start(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- scc_enet_t *ep = fep->scc.ep;
+ scc_enet_t __iomem *ep = fep->scc.ep;
W16(ep, sen_gaddr1, 0);
W16(ep, sen_gaddr2, 0);
@@ -231,7 +232,7 @@ static void set_multicast_start(struct net_device *dev)
static void set_multicast_one(struct net_device *dev, const u8 * mac)
{
struct fs_enet_private *fep = netdev_priv(dev);
- scc_enet_t *ep = fep->scc.ep;
+ scc_enet_t __iomem *ep = fep->scc.ep;
u16 taddrh, taddrm, taddrl;
taddrh = ((u16) mac[5] << 8) | mac[4];
@@ -247,8 +248,8 @@ static void set_multicast_one(struct net_device *dev, const u8 * mac)
static void set_multicast_finish(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- scc_t *sccp = fep->scc.sccp;
- scc_enet_t *ep = fep->scc.ep;
+ scc_t __iomem *sccp = fep->scc.sccp;
+ scc_enet_t __iomem *ep = fep->scc.ep;
/* clear promiscuous always */
C16(sccp, scc_psmr, SCC_PSMR_PRO);
@@ -285,8 +286,8 @@ static void set_multicast_list(struct net_device *dev)
static void restart(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- scc_t *sccp = fep->scc.sccp;
- scc_enet_t *ep = fep->scc.ep;
+ scc_t __iomem *sccp = fep->scc.sccp;
+ scc_enet_t __iomem *ep = fep->scc.ep;
const struct fs_platform_info *fpi = fep->fpi;
u16 paddrh, paddrm, paddrl;
const unsigned char *mac;
@@ -296,7 +297,7 @@ static void restart(struct net_device *dev)
/* clear everything (slow & steady does it) */
for (i = 0; i < sizeof(*ep); i++)
- __fs_out8((char *)ep + i, 0);
+ __fs_out8((u8 __iomem *)ep + i, 0);
/* point to bds */
W16(ep, sen_genscc.scc_rbase, fep->ring_mem_addr);
@@ -397,7 +398,7 @@ static void restart(struct net_device *dev)
static void stop(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- scc_t *sccp = fep->scc.sccp;
+ scc_t __iomem *sccp = fep->scc.sccp;
int i;
for (i = 0; (R16(sccp, scc_sccm) == 0) && i < SCC_RESET_DELAY; i++)
@@ -441,7 +442,7 @@ static void post_free_irq(struct net_device *dev, int irq)
static void napi_clear_rx_event(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- scc_t *sccp = fep->scc.sccp;
+ scc_t __iomem *sccp = fep->scc.sccp;
W16(sccp, scc_scce, SCC_NAPI_RX_EVENT_MSK);
}
@@ -449,7 +450,7 @@ static void napi_clear_rx_event(struct net_device *dev)
static void napi_enable_rx(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- scc_t *sccp = fep->scc.sccp;
+ scc_t __iomem *sccp = fep->scc.sccp;
S16(sccp, scc_sccm, SCC_NAPI_RX_EVENT_MSK);
}
@@ -457,7 +458,7 @@ static void napi_enable_rx(struct net_device *dev)
static void napi_disable_rx(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- scc_t *sccp = fep->scc.sccp;
+ scc_t __iomem *sccp = fep->scc.sccp;
C16(sccp, scc_sccm, SCC_NAPI_RX_EVENT_MSK);
}
@@ -475,7 +476,7 @@ static void tx_kickstart(struct net_device *dev)
static u32 get_int_events(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
- scc_t *sccp = fep->scc.sccp;
+ scc_t __iomem *sccp = fep->scc.sccp;
return (u32) R16(sccp, scc_scce);
}
@@ -483,7 +484,7 @@ static u32 get_int_events(struct net_device *dev)
static void clear_int_events(struct net_device *dev, u32 int_events)
{
struct fs_enet_private *fep = netdev_priv(dev);
- scc_t *sccp = fep->scc.sccp;
+ scc_t __iomem *sccp = fep->scc.sccp;
W16(sccp, scc_scce, int_events & 0xffff);
}
@@ -498,20 +499,20 @@ static int get_regs(struct net_device *dev, void *p, int *sizep)
{
struct fs_enet_private *fep = netdev_priv(dev);
- if (*sizep < sizeof(scc_t) + sizeof(scc_enet_t))
+ if (*sizep < sizeof(scc_t) + sizeof(scc_enet_t __iomem *))
return -EINVAL;
memcpy_fromio(p, fep->scc.sccp, sizeof(scc_t));
p = (char *)p + sizeof(scc_t);
- memcpy_fromio(p, fep->scc.ep, sizeof(scc_enet_t));
+ memcpy_fromio(p, fep->scc.ep, sizeof(scc_enet_t __iomem *));
return 0;
}
static int get_regs_len(struct net_device *dev)
{
- return sizeof(scc_t) + sizeof(scc_enet_t);
+ return sizeof(scc_t) + sizeof(scc_enet_t __iomem *);
}
static void tx_restart(struct net_device *dev)
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
index f91c38d..c46ca8f 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -70,7 +70,7 @@ static int match_has_phy (struct device *dev, void* data)
static int fs_mii_fec_init(struct fec_info* fec, struct fs_mii_fec_platform_info *fmpi)
{
struct resource *r;
- fec_t *fecp;
+ fec_t __iomem *fecp;
char* name = "fsl-cpm-fec";
/* we need fec in order to be useful */
@@ -100,7 +100,7 @@ static int fs_mii_fec_init(struct fec_info* fec, struct fs_mii_fec_platform_info
static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location)
{
struct fec_info* fec = bus->priv;
- fec_t *fecp = fec->fecp;
+ fec_t __iomem *fecp = fec->fecp;
int i, ret = -1;
if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
@@ -124,7 +124,7 @@ static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location)
static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val)
{
struct fec_info* fec = bus->priv;
- fec_t *fecp = fec->fecp;
+ fec_t __iomem *fecp = fec->fecp;
int i;
/* this must never happen */
--
1.5.3.1
^ permalink raw reply related
* [PATCH 1/2] bootwrapper: Factor out dt_set_mac_address().
From: Scott Wood @ 2007-09-20 22:06 UTC (permalink / raw)
To: galak; +Cc: linuxppc-dev
This allows callers to set addresses one at a time when that would be more
convenient.
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
arch/powerpc/boot/devtree.c | 31 +++++++++++++++++--------------
arch/powerpc/boot/ops.h | 1 +
2 files changed, 18 insertions(+), 14 deletions(-)
diff --git a/arch/powerpc/boot/devtree.c b/arch/powerpc/boot/devtree.c
index 549463b..d78e8b4 100644
--- a/arch/powerpc/boot/devtree.c
+++ b/arch/powerpc/boot/devtree.c
@@ -88,29 +88,32 @@ void dt_fixup_clock(const char *path, u32 freq)
}
}
+void dt_set_mac_address(u32 index, const u8 *addr)
+{
+ void *devp = find_node_by_prop_value(NULL, "linux,network-index",
+ (void*)&index, sizeof(index));
+
+ if (devp) {
+ printf("ENET%d: local-mac-address <-"
+ " %02x:%02x:%02x:%02x:%02x:%02x\n\r", index,
+ addr[0], addr[1], addr[2],
+ addr[3], addr[4], addr[5]);
+
+ setprop(devp, "local-mac-address", addr, 6);
+ }
+}
+
void __dt_fixup_mac_addresses(u32 startindex, ...)
{
va_list ap;
u32 index = startindex;
- void *devp;
const u8 *addr;
va_start(ap, startindex);
- while ((addr = va_arg(ap, const u8 *))) {
- devp = find_node_by_prop_value(NULL, "linux,network-index",
- (void*)&index, sizeof(index));
- if (devp) {
- printf("ENET%d: local-mac-address <-"
- " %02x:%02x:%02x:%02x:%02x:%02x\n\r", index,
- addr[0], addr[1], addr[2],
- addr[3], addr[4], addr[5]);
+ while ((addr = va_arg(ap, const u8 *)))
+ dt_set_mac_address(index++, addr);
- setprop(devp, "local-mac-address", addr, 6);
- }
-
- index++;
- }
va_end(ap);
}
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
index 703255b..d7a9a28 100644
--- a/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -160,6 +160,7 @@ static inline void *find_node_by_devtype(const void *prev,
void dt_fixup_memory(u64 start, u64 size);
void dt_fixup_cpu_clocks(u32 cpufreq, u32 tbfreq, u32 busfreq);
void dt_fixup_clock(const char *path, u32 freq);
+void dt_set_mac_address(u32 index, const u8 *addr);
void __dt_fixup_mac_addresses(u32 startindex, ...);
#define dt_fixup_mac_addresses(...) \
__dt_fixup_mac_addresses(0, __VA_ARGS__, NULL)
--
1.5.3.1
^ permalink raw reply related
* [PATCH 2/2] bootwrapper: Add PlanetCore firmware support.
From: Scott Wood @ 2007-09-20 22:07 UTC (permalink / raw)
To: galak; +Cc: linuxppc-dev
This is a library that board code can use to extract information from the
PlanetCore configuration keys. PlanetCore is used on various boards from
Embedded Planet.
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
This replaces the previous "Add PlanetCore firmware support" patch.
Besides using dt_set_mac_address(), it fixes a bug with MAC address
generation -- it previously assumed that the mac address in the environment
was of the first ethernet port, when it's actually of the currently
configured ethernet port.
arch/powerpc/boot/Makefile | 2 +-
arch/powerpc/boot/planetcore.c | 166 ++++++++++++++++++++++++++++++++++++++++
arch/powerpc/boot/planetcore.h | 49 ++++++++++++
3 files changed, 216 insertions(+), 1 deletions(-)
create mode 100644 arch/powerpc/boot/planetcore.c
create mode 100644 arch/powerpc/boot/planetcore.h
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index cffef14..9ec785c 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -45,7 +45,7 @@ src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
ns16550.c serial.c simple_alloc.c div64.S util.S \
gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
- cpm-serial.c stdlib.c
+ cpm-serial.c stdlib.c planetcore.c
src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
cuboot-ebony.c treeboot-ebony.c prpmc2800.c \
ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \
diff --git a/arch/powerpc/boot/planetcore.c b/arch/powerpc/boot/planetcore.c
new file mode 100644
index 0000000..203f296
--- /dev/null
+++ b/arch/powerpc/boot/planetcore.c
@@ -0,0 +1,166 @@
+/*
+ * PlanetCore configuration data support functions
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ *
+ * Copyright (c) 2007 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 version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "stdio.h"
+#include "stdlib.h"
+#include "ops.h"
+#include "planetcore.h"
+#include "io.h"
+
+/* PlanetCore passes information to the OS in the form of
+ * a table of key=value strings, separated by newlines.
+ *
+ * The list is terminated by an empty string (i.e. two
+ * consecutive newlines).
+ *
+ * To make it easier to parse, we first convert all the
+ * newlines into null bytes.
+ */
+
+void planetcore_prepare_table(char *table)
+{
+ do {
+ if (*table == '\n')
+ *table = 0;
+
+ table++;
+ } while (*(table - 1) || *table != '\n');
+
+ *table = 0;
+}
+
+const char *planetcore_get_key(const char *table, const char *key)
+{
+ int keylen = strlen(key);
+
+ do {
+ if (!strncmp(table, key, keylen) && table[keylen] == '=')
+ return table + keylen + 1;
+
+ table += strlen(table) + 1;
+ } while (strlen(table) != 0);
+
+ return NULL;
+}
+
+int planetcore_get_decimal(const char *table, const char *key, u64 *val)
+{
+ const char *str = planetcore_get_key(table, key);
+ if (!str)
+ return 0;
+
+ *val = strtoull(str, NULL, 10);
+ return 1;
+}
+
+int planetcore_get_hex(const char *table, const char *key, u64 *val)
+{
+ const char *str = planetcore_get_key(table, key);
+ if (!str)
+ return 0;
+
+ *val = strtoull(str, NULL, 16);
+ return 1;
+}
+
+static u64 mac_table[4] = {
+ 0x000000000000,
+ 0x000000800000,
+ 0x000000400000,
+ 0x000000c00000,
+};
+
+void planetcore_set_mac_addrs(const char *table)
+{
+ u8 addr[4][6];
+ u64 int_addr;
+ u32 i;
+ int j;
+
+ if (!planetcore_get_hex(table, PLANETCORE_KEY_MAC_ADDR, &int_addr))
+ return;
+
+ for (i = 0; i < 4; i++) {
+ u64 this_dev_addr = (int_addr & ~0x000000c00000) |
+ mac_table[i];
+
+ for (j = 5; j >= 0; j--) {
+ addr[i][j] = this_dev_addr & 0xff;
+ this_dev_addr >>= 8;
+ }
+
+ dt_set_mac_address(i, addr[i]);
+ }
+}
+
+static char prop_buf[MAX_PROP_LEN];
+
+void planetcore_set_stdout_path(const char *table)
+{
+ char *path;
+ const char *label;
+ void *node, *chosen;
+
+ label = planetcore_get_key(table, PLANETCORE_KEY_SERIAL_PORT);
+ if (!label)
+ return;
+
+ node = find_node_by_prop_value_str(NULL, "linux,planetcore-label",
+ label);
+ if (!node)
+ return;
+
+ path = get_path(node, prop_buf, MAX_PROP_LEN);
+ if (!path)
+ return;
+
+ chosen = finddevice("/chosen");
+ if (!chosen)
+ chosen = create_node(NULL, "chosen");
+ if (!chosen)
+ return;
+
+ setprop_str(chosen, "linux,stdout-path", path);
+}
+
+void planetcore_set_serial_speed(const char *table)
+{
+ void *chosen, *stdout;
+ u64 baud;
+ u32 baud32;
+ int len;
+
+ chosen = finddevice("/chosen");
+ if (!chosen)
+ return;
+
+ len = getprop(chosen, "linux,stdout-path", prop_buf, MAX_PROP_LEN);
+ if (len <= 0)
+ return;
+
+ stdout = finddevice(prop_buf);
+ if (!stdout) {
+ printf("planetcore_set_serial_speed: "
+ "Bad /chosen/linux,stdout-path.\r\n");
+
+ return;
+ }
+
+ if (!planetcore_get_decimal(table, PLANETCORE_KEY_SERIAL_BAUD,
+ &baud)) {
+ printf("planetcore_set_serial_speed: No SB tag.\r\n");
+ return;
+ }
+
+ baud32 = baud;
+ setprop(stdout, "current-speed", &baud32, 4);
+}
diff --git a/arch/powerpc/boot/planetcore.h b/arch/powerpc/boot/planetcore.h
new file mode 100644
index 0000000..0d4094f
--- /dev/null
+++ b/arch/powerpc/boot/planetcore.h
@@ -0,0 +1,49 @@
+#ifndef _PPC_BOOT_PLANETCORE_H_
+#define _PPC_BOOT_PLANETCORE_H_
+
+#include "types.h"
+
+#define PLANETCORE_KEY_BOARD_TYPE "BO"
+#define PLANETCORE_KEY_BOARD_REV "BR"
+#define PLANETCORE_KEY_MB_RAM "D1"
+#define PLANETCORE_KEY_MAC_ADDR "EA"
+#define PLANETCORE_KEY_FLASH_SPEED "FS"
+#define PLANETCORE_KEY_IP_ADDR "IP"
+#define PLANETCORE_KEY_KB_NVRAM "NV"
+#define PLANETCORE_KEY_PROCESSOR "PR"
+#define PLANETCORE_KEY_PROC_VARIANT "PV"
+#define PLANETCORE_KEY_SERIAL_BAUD "SB"
+#define PLANETCORE_KEY_SERIAL_PORT "SP"
+#define PLANETCORE_KEY_SWITCH "SW"
+#define PLANETCORE_KEY_TEMP_OFFSET "TC"
+#define PLANETCORE_KEY_TARGET_IP "TIP"
+#define PLANETCORE_KEY_CRYSTAL_HZ "XT"
+
+/* Prepare the table for processing, by turning all newlines
+ * into NULL bytes.
+ */
+void planetcore_prepare_table(char *table);
+
+/* Return the value associated with a given key in text,
+ * decimal, or hex format.
+ *
+ * Returns zero/NULL on failure, non-zero on success.
+ */
+const char *planetcore_get_key(const char *table, const char *key);
+int planetcore_get_decimal(const char *table, const char *key, u64 *val);
+int planetcore_get_hex(const char *table, const char *key, u64 *val);
+
+/* Updates the device tree local-mac-address properties based
+ * on the EA tag.
+ */
+void planetcore_set_mac_addrs(const char *table);
+
+/* Sets the linux,stdout-path in the /chosen node. This requires the
+ * linux,planetcore-label property in each serial node.
+ */
+void planetcore_set_stdout_path(const char *table);
+
+/* Sets the current-speed property in the serial node. */
+void planetcore_set_serial_speed(const char *table);
+
+#endif
--
1.5.3.1
^ permalink raw reply related
* Re: 4xx git tree moved
From: Josh Boyer @ 2007-09-20 3:28 UTC (permalink / raw)
To: Vitaly Bordug; +Cc: linuxppc-dev
In-Reply-To: <20070921013930.409a9f8b@localhost.localdomain>
On Fri, 2007-09-21 at 01:39 +0400, Vitaly Bordug wrote:
> Hello Josh,
>
> On Thu, 20 Sep 2007 07:42:36 -0500
> Josh Boyer wrote:
>
> > For those interested in 4xx, I've moved my git tree to kernel.org. You
> > can find it here:
> >
> > git://git.kernel.org/pub/scm/linux/kernel/git/jwboyer/powerpc.git
> >
> Can you call it something like 4xx-powerpc.git, or powerpc-4xx.git? Number of powerpc.git stuff tend to grow :)
Sure. powerpc-4xx.git would be fine. After Paul does my latest pull
request I'll rename it.
josh
^ permalink raw reply
* Re: [PATCH 2/5] Implement generic time of day clocksource for powerpc machines.
From: Tony Breeds @ 2007-09-20 23:46 UTC (permalink / raw)
To: john stultz
Cc: Daniel Walker, Thomas Gleixner, Paul Mackerras, Realtime Kernel,
linuxppc-dev
In-Reply-To: <1190306110.14264.7.camel@localhost>
On Thu, Sep 20, 2007 at 09:35:10AM -0700, john stultz wrote:
> I think what Daniel is pointing out is that the clocksource read
> function isn't the place for the __USE_RTC() conditional.
>
> It would likely be better instead of the timebase clocksource managing
> multiple type of hardware (timebase and RTC), to have a separate simple
> RTC clocksource, and then conditionally register one or the other at
> init time.
I'll create a seperate clocksource for the RTC case and use that as
appropriate. I'll resend the patch series after I've booted it :)
Yours Tony
linux.conf.au http://linux.conf.au/ || http://lca2008.linux.org.au/
Jan 28 - Feb 02 2008 The Australian Linux Technical Conference!
^ permalink raw reply
* Re: [PATCH 6/9] fs_enet: Be an of_platform device when CONFIG_PPC_CPM_NEW_BINDING is set.
From: Stephen Rothwell @ 2007-09-21 0:08 UTC (permalink / raw)
To: Scott Wood; +Cc: netdev, jgarzik, linuxppc-dev
In-Reply-To: <20070920220121.GF28784@loki.buserror.net>
[-- Attachment #1: Type: text/plain, Size: 1316 bytes --]
On Thu, 20 Sep 2007 17:01:21 -0500 Scott Wood <scottwood@freescale.com> wrote:
>
> +++ b/drivers/net/fs_enet/fs_enet-main.c
> @@ -44,12 +44,18 @@
> #include <asm/irq.h>
> #include <asm/uaccess.h>
>
> +#ifdef CONFIG_PPC_CPM_NEW_BINDING
> +#include <asm/of_platform.h>
Hmm, didn't I already ask you to change this to linux/of_platform.h?
> +++ b/drivers/net/fs_enet/mac-fcc.c
> @@ -42,6 +42,10 @@
> #include <asm/irq.h>
> #include <asm/uaccess.h>
>
> +#ifdef CONFIG_PPC_CPM_NEW_BINDING
> +#include <asm/of_device.h>
And this to linux/of_device.h
> +++ b/drivers/net/fs_enet/mac-fec.c
> @@ -43,6 +43,10 @@
> #include <asm/commproc.h>
> #endif
>
> +#ifdef CONFIG_PPC_CPM_NEW_BINDING
> +#include <asm/of_device.h>
And this?
> +++ b/drivers/net/fs_enet/mac-scc.c
> @@ -43,6 +43,10 @@
> #include <asm/commproc.h>
> #endif
>
> +#ifdef CONFIG_PPC_CPM_NEW_BINDING
> +#include <asm/of_platform.h>
And this
> +++ b/drivers/net/fs_enet/mii-fec.c
> @@ -36,6 +36,10 @@
> #include <asm/irq.h>
> #include <asm/uaccess.h>
>
> +#ifdef CONFIG_PPC_CPM_NEW_BINDING
> +#include <asm/of_platform.h>
And here
Sorry if I missed these last time around.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH] [POWERPC] Create and use CONFIG_WORD_SIZE
From: Stephen Rothwell @ 2007-09-21 0:16 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
In-Reply-To: <20070920180825.39aca4d7.sfr@canb.auug.org.au>
Linus made this suggestion for the x86 merge and this starts the process
for powerpc. We assume that CONFIG_PPC64 implies CONFIG_PPC_MERGE and
CONFIG_PPC_STD_MMU_32 implies CONFIG_PPC_STD_MMU.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/Kconfig | 5 +++++
arch/powerpc/Makefile | 21 ++++++++++++---------
arch/powerpc/kernel/Makefile | 30 +++++++++++++-----------------
arch/powerpc/lib/Makefile | 7 ++++---
arch/powerpc/mm/Makefile | 13 ++++++++-----
arch/ppc/Kconfig | 4 ++++
6 files changed, 46 insertions(+), 34 deletions(-)
I got some strange warnings from allmodconfig and this version makes them
go away. It appears that sometimes we don't include the config when
using the top level arch Makefile.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 66a3295..de886ec 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -14,6 +14,11 @@ config 64BIT
bool
default y if PPC64
+config WORD_SIZE
+ int
+ default 64 if PPC64
+ default 32 if !PPC64
+
config PPC_MERGE
def_bool y
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 6015a92..4fda65e 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -39,7 +39,6 @@ KBUILD_DEFCONFIG := $(shell uname -m)_defconfig
ifeq ($(CONFIG_PPC64),y)
OLDARCH := ppc64
-SZ := 64
new_nm := $(shell if $(NM) --help 2>&1 | grep -- '--synthetic' > /dev/null; then echo y; else echo n; fi)
@@ -49,16 +48,21 @@ endif
else
OLDARCH := ppc
-SZ := 32
+endif
+
+# It seems there are times we use this Makefile without
+# including the config file, but this replicates the old behaviour
+ifeq ($(CONFIG_WORD_SIZE),)
+CONFIG_WORD_SIZE := 32
endif
UTS_MACHINE := $(OLDARCH)
ifeq ($(HAS_BIARCH),y)
-override AS += -a$(SZ)
-override LD += -m elf$(SZ)ppc
-override CC += -m$(SZ)
-override AR := GNUTARGET=elf$(SZ)-powerpc $(AR)
+override AS += -a$(CONFIG_WORD_SIZE)
+override LD += -m elf$(CONFIG_WORD_SIZE)ppc
+override CC += -m$(CONFIG_WORD_SIZE)
+override AR := GNUTARGET=elf$(CONFIG_WORD_SIZE)-powerpc $(AR)
endif
LDFLAGS_vmlinux := -Bstatic
@@ -72,7 +76,7 @@ AFLAGS += $(AFLAGS-y)
CFLAGS += -msoft-float -pipe $(CFLAGS-y)
CPP = $(CC) -E $(CFLAGS)
-CHECKFLAGS += -m$(SZ) -D__powerpc__ -D__powerpc$(SZ)__
+CHECKFLAGS += -m$(CONFIG_WORD_SIZE) -D__powerpc__ -D__powerpc$(CONFIG_WORD_SIZE)__
ifeq ($(CONFIG_PPC64),y)
GCC_BROKEN_VEC := $(shell if [ $(call cc-version) -lt 0400 ] ; then echo "y"; fi)
@@ -116,8 +120,7 @@ cpu-as-$(CONFIG_E200) += -Wa,-me200
AFLAGS += $(cpu-as-y)
CFLAGS += $(cpu-as-y)
-head-y := arch/powerpc/kernel/head_32.o
-head-$(CONFIG_PPC64) := arch/powerpc/kernel/head_64.o
+head-y := arch/powerpc/kernel/head_$(CONFIG_WORD_SIZE).o
head-$(CONFIG_8xx) := arch/powerpc/kernel/head_8xx.o
head-$(CONFIG_40x) := arch/powerpc/kernel/head_40x.o
head-$(CONFIG_44x) := arch/powerpc/kernel/head_44x.o
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 967afc5..ef3633f 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -37,10 +37,10 @@ obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
obj-$(CONFIG_TAU) += tau_6xx.o
-obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o
-obj32-$(CONFIG_HIBERNATION) += swsusp_32.o
-obj64-$(CONFIG_HIBERNATION) += swsusp_64.o swsusp_asm64.o
-obj32-$(CONFIG_MODULES) += module_32.o
+obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o \
+ swsusp_$(CONFIG_WORD_SIZE).o
+obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o
+obj-$(CONFIG_MODULES) += module_$(CONFIG_WORD_SIZE).o
ifeq ($(CONFIG_PPC_MERGE),y)
@@ -53,9 +53,10 @@ extra-$(CONFIG_8xx) := head_8xx.o
extra-y += vmlinux.lds
obj-y += time.o prom.o traps.o setup-common.o \
- udbg.o misc.o io.o
-obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o
-obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o
+ udbg.o misc.o io.o \
+ misc_$(CONFIG_WORD_SIZE).o
+obj-$(CONFIG_PPC32) += entry_32.o setup_32.o
+obj-$(CONFIG_PPC64) += dma_64.o iommu.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o
obj-$(CONFIG_MODULES) += ppc_ksyms.o
obj-$(CONFIG_BOOTX_TEXT) += btext.o
@@ -63,16 +64,12 @@ obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o
-module-$(CONFIG_PPC64) += module_64.o
-obj-$(CONFIG_MODULES) += $(module-y)
-
-pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o isa-bridge.o
-pci32-$(CONFIG_PPC32) := pci_32.o
-obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) pci-common.o
+pci64-$(CONFIG_PPC64) += pci_dn.o isa-bridge.o
+obj-$(CONFIG_PCI) += pci_$(CONFIG_WORD_SIZE).o $(pci64-y) \
+ pci-common.o
obj-$(CONFIG_PCI_MSI) += msi.o
-kexec-$(CONFIG_PPC64) := machine_kexec_64.o
-kexec-$(CONFIG_PPC32) := machine_kexec_32.o
-obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o $(kexec-y)
+obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o \
+ machine_kexec_$(CONFIG_WORD_SIZE).o
obj-$(CONFIG_AUDIT) += audit.o
obj64-$(CONFIG_AUDIT) += compat_audit.o
@@ -86,7 +83,6 @@ smpobj-$(CONFIG_SMP) += smp.o
endif
-obj-$(CONFIG_PPC32) += $(obj32-y)
obj-$(CONFIG_PPC64) += $(obj64-y)
extra-$(CONFIG_PPC_FPU) += fpu.o
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 23bbb1e..65d492e 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -7,11 +7,12 @@ EXTRA_CFLAGS += -mno-minimal-toc
endif
ifeq ($(CONFIG_PPC_MERGE),y)
-obj-y := string.o alloc.o
-obj-$(CONFIG_PPC32) += div64.o copy_32.o checksum_32.o
+obj-y := string.o alloc.o \
+ checksum_$(CONFIG_WORD_SIZE).o
+obj-$(CONFIG_PPC32) += div64.o copy_32.o
endif
-obj-$(CONFIG_PPC64) += checksum_64.o copypage_64.o copyuser_64.o \
+obj-$(CONFIG_PPC64) += copypage_64.o copyuser_64.o \
memcpy_64.o usercopy_64.o mem_64.o string.o
obj-$(CONFIG_QUICC_ENGINE) += rheap.o
obj-$(CONFIG_XMON) += sstep.o
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
index bf20fa6..20629ae 100644
--- a/arch/powerpc/mm/Makefile
+++ b/arch/powerpc/mm/Makefile
@@ -6,13 +6,16 @@ ifeq ($(CONFIG_PPC64),y)
EXTRA_CFLAGS += -mno-minimal-toc
endif
-obj-y := fault.o mem.o lmb.o
-obj-$(CONFIG_PPC32) += init_32.o pgtable_32.o mmu_context_32.o
+obj-y := fault.o mem.o lmb.o \
+ init_$(CONFIG_WORD_SIZE).o \
+ pgtable_$(CONFIG_WORD_SIZE).o \
+ mmu_context_$(CONFIG_WORD_SIZE).o
hash-$(CONFIG_PPC_NATIVE) := hash_native_64.o
-obj-$(CONFIG_PPC64) += init_64.o pgtable_64.o mmu_context_64.o \
- hash_utils_64.o hash_low_64.o tlb_64.o \
+obj-$(CONFIG_PPC64) += hash_utils_64.o \
slb_low.o slb.o stab.o mmap.o $(hash-y)
-obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o hash_low_32.o tlb_32.o
+obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o
+obj-$(CONFIG_PPC_STD_MMU) += hash_low_$(CONFIG_WORD_SIZE).o \
+ tlb_$(CONFIG_WORD_SIZE).o
obj-$(CONFIG_40x) += 40x_mmu.o
obj-$(CONFIG_44x) += 44x_mmu.o
obj-$(CONFIG_FSL_BOOKE) += fsl_booke_mmu.o
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index c1b34eb..c2087f6 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -4,6 +4,10 @@
mainmenu "Linux/PowerPC Kernel Configuration"
+config WORD_SIZE
+ int
+ default 32
+
config MMU
bool
default y
--
1.5.3.1
^ permalink raw reply related
* Re: [PATCH 6/9] fs_enet: Be an of_platform device when CONFIG_PPC_CPM_NEW_BINDING is set.
From: Scott Wood @ 2007-09-21 0:44 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: netdev, jgarzik, linuxppc-dev
In-Reply-To: <20070921100841.6904f2bc.sfr@canb.auug.org.au>
On Fri, Sep 21, 2007 at 10:08:41AM +1000, Stephen Rothwell wrote:
> On Thu, 20 Sep 2007 17:01:21 -0500 Scott Wood <scottwood@freescale.com> wrote:
> >
> > +++ b/drivers/net/fs_enet/fs_enet-main.c
> > @@ -44,12 +44,18 @@
> > #include <asm/irq.h>
> > #include <asm/uaccess.h>
> >
> > +#ifdef CONFIG_PPC_CPM_NEW_BINDING
> > +#include <asm/of_platform.h>
>
> Hmm, didn't I already ask you to change this to linux/of_platform.h?
Grrr, I thought I'd gotten them all.
-Scott
^ permalink raw reply
* Re: [PATCH 1/2] bootwrapper: Factor out dt_set_mac_address().
From: David Gibson @ 2007-09-21 0:49 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <20070920220615.GA28860@loki.buserror.net>
On Thu, Sep 20, 2007 at 05:06:15PM -0500, Scott Wood wrote:
> This allows callers to set addresses one at a time when that would be more
> convenient.
>
> Signed-off-by: Scott Wood <scottwood@freescale.com>
Um... I feel bad whinging about such a tiny nit, but...
> +void dt_set_mac_address(u32 index, const u8 *addr)
.. I'd prefer it was called dt_fixup_mac_address() to match the other
functions.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: Cleanups for physmap_of.c (v2)
From: David Gibson @ 2007-09-21 1:00 UTC (permalink / raw)
To: Segher Boessenkool
Cc: David Woodhouse, Vitaly Wool, Paul Mackerras, linuxppc-dev
In-Reply-To: <93451aaa11582c2db3be55961514cce9@kernel.crashing.org>
On Thu, Sep 20, 2007 at 07:11:59PM +0200, Segher Boessenkool wrote:
> > - (the big one) Despite the name, this driver really has
> > nothing to do with drivers/mtd/physmap.c. The fact that the flash
> > chips must be physically direct mapped is a constrant, but doesn't
> > really say anything about the actual purpose of this driver, which is
> > to instantiate MTD devices based on information from the device tree.
> > Therefore the physmap name is replaced everywhere within the file with
> > "of_flash".
>
> Do you think this code will handle NAND flash later, too? If not,
> maybe "of_norflash" is better?
Uh.. maybe? I guess we can either extend it or rename it in the
future sometime.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: Printing device tree on running system
From: Josh Boyer @ 2007-09-20 4:57 UTC (permalink / raw)
To: Jon Smirl; +Cc: linuxppc-embedded
In-Reply-To: <9e4733910709200921u3ffd6a37pe0ef268a2a171973@mail.gmail.com>
On Thu, 2007-09-20 at 12:21 -0400, Jon Smirl wrote:
> On 9/20/07, Scott Wood <scottwood@freescale.com> wrote:
> > On Thu, Sep 20, 2007 at 11:55:10AM -0400, Jon Smirl wrote:
> > > Is there a command for printing the device tree on a running system? I
> > > want to see what changes the various device drivers made to the DTC I
> > > started with.
> >
> > It's exported in /proc/device-tree, if support is built into the kernel.
>
> That worked, didn't know the option existed.
>
> >
> > It might be interesting to make dtc support turning that into a dts...
dtc does support that. Pass /proc/device-tree/ to dtc like this:
dtc -I fs -o device-tree.dts -O dts /proc/device-tree
josh
^ permalink raw reply
* Re: [PATCH] PowerPC: add setup_cpu for 44x for processor-specific init
From: Paul Mackerras @ 2007-09-21 1:34 UTC (permalink / raw)
To: Valentine Barshak; +Cc: linuxppc-dev, miltonm, david
In-Reply-To: <20070920175558.GA3191@ru.mvista.com>
Valentine Barshak writes:
> +_GLOBAL(__setup_cpu_440epx)
> + mflr r4
> + bl __init_fpu_44x
> +_GLOBAL(__setup_cpu_440grx)
> + bl __plb_disable_wrp
> + mtlr r4
> + blr
If we enter at __setup_cpu_440grx we'll return to some bogus
address...
Paul.
^ permalink raw reply
* [PATCH] Disable power management for arch/ppc
From: Paul Mackerras @ 2007-09-21 1:52 UTC (permalink / raw)
To: linuxppc-dev
Currently the prep_defconfig in arch/ppc won't build due to swsusp
being broken. This patch avoids the problem by essentially disabling
all power management on those platforms left in arch/ppc.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
Does anyone have an objection to this?
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index c1b34eb..1360f17 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -1012,7 +1012,7 @@ config CMDLINE
some command-line options at build time by entering them here. In
most cases you will need to specify the root device here.
-if !44x || BROKEN
+if BROKEN
source kernel/power/Kconfig
endif
^ permalink raw reply related
* Re: Please pull from 'for-2.6.24' branch of 4xx tree
From: Paul Mackerras @ 2007-09-21 1:53 UTC (permalink / raw)
To: Josh Boyer; +Cc: linuxppc-dev
In-Reply-To: <20070920074128.6a90ebc2@weaponx.rchland.ibm.com>
Josh Boyer writes:
> Please pull from
>
> master.kernel.org:/pub/scm/linux/kernel/git/jwboyer/powerpc.git for-2.6.24
Pulled and pushed out.
Paul.
^ permalink raw reply
* [PATCH V2] powerpc mm init_32 gdb regions
From: Ed Swarthout @ 2007-09-21 2:53 UTC (permalink / raw)
To: galak, linuxppc-dev; +Cc: Ed Swarthout
In-Reply-To: <1190270195801-git-send-email-Ed.Swarthout@freescale.com>
Add memory regions to the kcore list for 32-bit machines.
The entries are only 32-bit, so restrict the virtual address to stay
below 0xffff_ffff. With KERNELBASE set to 0xc000_0000, this in effect
restricts access to the first 1GB of real memory.
Make setup_kcore conditional on CONFIG_PROC_KCORE for both 32/64.
Signed-off-by: Ed Swarthout <Ed.Swarthout@freescale.com>
---
arch/powerpc/mm/init_32.c | 37 +++++++++++++++++++++++++++++++++++++
arch/powerpc/mm/init_64.c | 2 ++
2 files changed, 39 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index d65995a..27c234f 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -255,3 +255,40 @@ void free_initrd_mem(unsigned long start, unsigned long end)
}
}
#endif
+
+#ifdef CONFIG_PROC_KCORE
+static struct kcore_list kcore_vmem;
+
+static int __init setup_kcore(void)
+{
+ int i;
+
+ for (i = 0; i < lmb.memory.cnt; i++) {
+ unsigned long base;
+ unsigned long size;
+ struct kcore_list *kcore_mem;
+
+ base = lmb.memory.region[i].base;
+ size = lmb.memory.region[i].size;
+
+ kcore_mem = kmalloc(sizeof(struct kcore_list), GFP_ATOMIC);
+ if (!kcore_mem)
+ panic("%s: kmalloc failed\n", __FUNCTION__);
+
+ /* must stay under 32 bits */
+ if ( 0xfffffffful - (unsigned long)__va(base) < size) {
+ size = 0xfffffffful - (unsigned long)(__va(base));
+ printk(KERN_DEBUG "setup_kcore: restrict size=%lx\n",
+ size);
+ }
+
+ kclist_add(kcore_mem, __va(base), size);
+ }
+
+ kclist_add(&kcore_vmem, (void *)VMALLOC_START,
+ VMALLOC_END-VMALLOC_START);
+
+ return 0;
+}
+module_init(setup_kcore);
+#endif
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 9f27bb5..fa90f65 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -113,6 +113,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
}
#endif
+#ifdef CONFIG_PROC_KCORE
static struct kcore_list kcore_vmem;
static int __init setup_kcore(void)
@@ -139,6 +140,7 @@ static int __init setup_kcore(void)
return 0;
}
module_init(setup_kcore);
+#endif
static void zero_ctor(void *addr, struct kmem_cache *cache, unsigned long flags)
{
--
1.5.3.1.65.g47184
^ permalink raw reply related
* [PATCH v2 1/4] Implement {read,update}_persistent_clock.
From: Tony Breeds @ 2007-09-21 3:26 UTC (permalink / raw)
To: linuxppc-dev, Paul Mackerras; +Cc: Thomas Gleixner, Realtime Kernel
With these functions implemented we cooperate better with the generic
timekeeping code. This obsoletes the need for the timer sysdev as a bonus.
Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
Patch set updated to powerpc/for-2.6.24
* Compile tested for arch/powerpc/configs/*_defconfig
* Booted on pSeries, iSeries, Cell and PS3
arch/powerpc/Kconfig | 3 +
arch/powerpc/kernel/time.c | 85 ++++++++++-------------------------
arch/powerpc/sysdev/Makefile | 5 --
arch/powerpc/sysdev/timer.c | 81 ---------------------------------
4 files changed, 29 insertions(+), 145 deletions(-)
Index: working/arch/powerpc/Kconfig
===================================================================
--- working.orig/arch/powerpc/Kconfig
+++ working/arch/powerpc/Kconfig
@@ -21,6 +21,9 @@ config MMU
bool
default y
+config GENERIC_CMOS_UPDATE
+ def_bool y
+
config GENERIC_HARDIRQS
bool
default y
Index: working/arch/powerpc/kernel/time.c
===================================================================
--- working.orig/arch/powerpc/kernel/time.c
+++ working/arch/powerpc/kernel/time.c
@@ -73,16 +73,11 @@
#include <asm/iseries/hv_call_xm.h>
#endif
-/* keep track of when we need to update the rtc */
-time_t last_rtc_update;
#ifdef CONFIG_PPC_ISERIES
static unsigned long __initdata iSeries_recal_titan;
static signed long __initdata iSeries_recal_tb;
#endif
-/* The decrementer counts down by 128 every 128ns on a 601. */
-#define DECREMENTER_COUNT_601 (1000000000 / HZ)
-
#define XSEC_PER_SEC (1024*1024)
#ifdef CONFIG_PPC64
@@ -348,39 +343,6 @@ void udelay(unsigned long usecs)
}
EXPORT_SYMBOL(udelay);
-static __inline__ void timer_check_rtc(void)
-{
- /*
- * update the rtc when needed, this should be performed on the
- * right fraction of a second. Half or full second ?
- * Full second works on mk48t59 clocks, others need testing.
- * Note that this update is basically only used through
- * the adjtimex system calls. Setting the HW clock in
- * any other way is a /dev/rtc and userland business.
- * This is still wrong by -0.5/+1.5 jiffies because of the
- * timer interrupt resolution and possible delay, but here we
- * hit a quantization limit which can only be solved by higher
- * resolution timers and decoupling time management from timer
- * interrupts. This is also wrong on the clocks
- * which require being written at the half second boundary.
- * We should have an rtc call that only sets the minutes and
- * seconds like on Intel to avoid problems with non UTC clocks.
- */
- if (ppc_md.set_rtc_time && ntp_synced() &&
- xtime.tv_sec - last_rtc_update >= 659 &&
- abs((xtime.tv_nsec/1000) - (1000000-1000000/HZ)) < 500000/HZ) {
- struct rtc_time tm;
- to_tm(xtime.tv_sec + 1 + timezone_offset, &tm);
- tm.tm_year -= 1900;
- tm.tm_mon -= 1;
- if (ppc_md.set_rtc_time(&tm) == 0)
- last_rtc_update = xtime.tv_sec + 1;
- else
- /* Try again one minute later */
- last_rtc_update += 60;
- }
-}
-
/*
* This version of gettimeofday has microsecond resolution.
*/
@@ -689,7 +651,6 @@ void timer_interrupt(struct pt_regs * re
tb_last_jiffy = tb_next_jiffy;
do_timer(1);
timer_recalc_offset(tb_last_jiffy);
- timer_check_rtc();
}
write_sequnlock(&xtime_lock);
}
@@ -801,11 +762,6 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, new_sec, new_nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- /* In case of a large backwards jump in time with NTP, we want the
- * clock to be updated as soon as the PLL is again in lock.
- */
- last_rtc_update = new_sec - 658;
-
ntp_clear();
new_xsec = xtime.tv_nsec;
@@ -881,12 +837,35 @@ void __init generic_calibrate_decr(void)
#endif
}
-unsigned long get_boot_time(void)
+int update_persistent_clock(struct timespec now)
{
struct rtc_time tm;
- if (ppc_md.get_boot_time)
- return ppc_md.get_boot_time();
+ if (!ppc_md.set_rtc_time)
+ return 0;
+
+ to_tm(now.tv_sec + 1 + timezone_offset, &tm);
+ tm.tm_year -= 1900;
+ tm.tm_mon -= 1;
+
+ return ppc_md.set_rtc_time(&tm);
+}
+
+unsigned long read_persistent_clock(void)
+{
+ struct rtc_time tm;
+ static int first = 1;
+
+ /* XXX this is a litle fragile but will work okay in the short term */
+ if (first) {
+ first = 0;
+ if (ppc_md.time_init)
+ timezone_offset = ppc_md.time_init();
+
+ /* get_boot_time() isn't guaranteed to be safe to call late */
+ if (ppc_md.get_boot_time)
+ return ppc_md.get_boot_time() -timezone_offset;
+ }
if (!ppc_md.get_rtc_time)
return 0;
ppc_md.get_rtc_time(&tm);
@@ -898,14 +877,10 @@ unsigned long get_boot_time(void)
void __init time_init(void)
{
unsigned long flags;
- unsigned long tm = 0;
struct div_result res;
u64 scale, x;
unsigned shift;
- if (ppc_md.time_init != NULL)
- timezone_offset = ppc_md.time_init();
-
if (__USE_RTC()) {
/* 601 processor: dec counts down by 128 every 128ns */
ppc_tb_freq = 1000000000;
@@ -980,19 +955,14 @@ void __init time_init(void)
/* Save the current timebase to pretty up CONFIG_PRINTK_TIME */
boot_tb = get_tb_or_rtc();
- tm = get_boot_time();
-
write_seqlock_irqsave(&xtime_lock, flags);
/* If platform provided a timezone (pmac), we correct the time */
if (timezone_offset) {
sys_tz.tz_minuteswest = -timezone_offset / 60;
sys_tz.tz_dsttime = 0;
- tm -= timezone_offset;
}
- xtime.tv_sec = tm;
- xtime.tv_nsec = 0;
do_gtod.varp = &do_gtod.vars[0];
do_gtod.var_idx = 0;
do_gtod.varp->tb_orig_stamp = tb_last_jiffy;
@@ -1010,9 +980,6 @@ void __init time_init(void)
time_freq = 0;
- last_rtc_update = xtime.tv_sec;
- set_normalized_timespec(&wall_to_monotonic,
- -xtime.tv_sec, -xtime.tv_nsec);
write_sequnlock_irqrestore(&xtime_lock, flags);
/* Not exact, but the timer interrupt takes care of this */
Index: working/arch/powerpc/sysdev/Makefile
===================================================================
--- working.orig/arch/powerpc/sysdev/Makefile
+++ working/arch/powerpc/sysdev/Makefile
@@ -20,11 +20,6 @@ obj-$(CONFIG_MV64X60) += $(mv64x60-y) m
obj-$(CONFIG_RTC_DRV_CMOS) += rtc_cmos_setup.o
obj-$(CONFIG_AXON_RAM) += axonram.o
-# contains only the suspend handler for time
-ifeq ($(CONFIG_RTC_CLASS),)
-obj-$(CONFIG_PM) += timer.o
-endif
-
ifeq ($(CONFIG_PPC_MERGE),y)
obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
obj-$(CONFIG_PPC_I8259) += i8259.o
Index: working/arch/powerpc/sysdev/timer.c
===================================================================
--- working.orig/arch/powerpc/sysdev/timer.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Common code to keep time when machine suspends.
- *
- * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
- *
- * GPLv2
- */
-
-#include <linux/time.h>
-#include <linux/sysdev.h>
-#include <asm/rtc.h>
-
-static unsigned long suspend_rtc_time;
-
-/*
- * Reset the time after a sleep.
- */
-static int timer_resume(struct sys_device *dev)
-{
- struct timeval tv;
- struct timespec ts;
- struct rtc_time cur_rtc_tm;
- unsigned long cur_rtc_time, diff;
-
- /* get current RTC time and convert to seconds */
- get_rtc_time(&cur_rtc_tm);
- cur_rtc_time = mktime(cur_rtc_tm.tm_year + 1900,
- cur_rtc_tm.tm_mon + 1,
- cur_rtc_tm.tm_mday,
- cur_rtc_tm.tm_hour,
- cur_rtc_tm.tm_min,
- cur_rtc_tm.tm_sec);
-
- diff = cur_rtc_time - suspend_rtc_time;
-
- /* adjust time of day by seconds that elapsed while
- * we were suspended */
- do_gettimeofday(&tv);
- ts.tv_sec = tv.tv_sec + diff;
- ts.tv_nsec = tv.tv_usec * NSEC_PER_USEC;
- do_settimeofday(&ts);
-
- return 0;
-}
-
-static int timer_suspend(struct sys_device *dev, pm_message_t state)
-{
- struct rtc_time suspend_rtc_tm;
- WARN_ON(!ppc_md.get_rtc_time);
-
- get_rtc_time(&suspend_rtc_tm);
- suspend_rtc_time = mktime(suspend_rtc_tm.tm_year + 1900,
- suspend_rtc_tm.tm_mon + 1,
- suspend_rtc_tm.tm_mday,
- suspend_rtc_tm.tm_hour,
- suspend_rtc_tm.tm_min,
- suspend_rtc_tm.tm_sec);
-
- return 0;
-}
-
-static struct sysdev_class timer_sysclass = {
- .resume = timer_resume,
- .suspend = timer_suspend,
- set_kset_name("timer"),
-};
-
-static struct sys_device device_timer = {
- .id = 0,
- .cls = &timer_sysclass,
-};
-
-static int time_init_device(void)
-{
- int error = sysdev_class_register(&timer_sysclass);
- if (!error)
- error = sysdev_register(&device_timer);
- return error;
-}
-
-device_initcall(time_init_device);
^ permalink raw reply
* [PATCH v2 2/4] Implement generic time of day clocksource for powerpc machines.
From: Tony Breeds @ 2007-09-21 3:26 UTC (permalink / raw)
To: linuxppc-dev, Paul Mackerras; +Cc: Thomas Gleixner, Realtime Kernel
In-Reply-To: <1190345162.620000.305760830507.qpush@thor>
Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
Updated to create a clocksource driver specific to the 601
arch/powerpc/Kconfig | 6
arch/powerpc/kernel/time.c | 255 ++++++++++++-------------------------
2 files changed, 91 insertions(+), 170 deletions(-)
Index: working/arch/powerpc/Kconfig
===================================================================
--- working.orig/arch/powerpc/Kconfig
+++ working/arch/powerpc/Kconfig
@@ -24,6 +24,12 @@ config MMU
config GENERIC_CMOS_UPDATE
def_bool y
+config GENERIC_TIME
+ def_bool y
+
+config GENERIC_TIME_VSYSCALL
+ def_bool y
+
config GENERIC_HARDIRQS
bool
default y
Index: working/arch/powerpc/kernel/time.c
===================================================================
--- working.orig/arch/powerpc/kernel/time.c
+++ working/arch/powerpc/kernel/time.c
@@ -73,9 +73,38 @@
#include <asm/iseries/hv_call_xm.h>
#endif
+/* powerpc clocksource/clockevent code */
+
+#include <linux/clocksource.h>
+
+static cycle_t rtc_read(void);
+static struct clocksource clocksource_rtc = {
+ .name = "rtc",
+ .rating = 400,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .mask = CLOCKSOURCE_MASK(64),
+ .shift = 22,
+ .mult = 0, /* To be filled in */
+ .read = rtc_read,
+};
+
+static cycle_t timebase_read(void);
+static struct clocksource clocksource_timebase = {
+ .name = "timebase",
+ .rating = 400,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .mask = CLOCKSOURCE_MASK(64),
+ .shift = 22,
+ .mult = 0, /* To be filled in */
+ .read = timebase_read,
+};
+
#ifdef CONFIG_PPC_ISERIES
static unsigned long __initdata iSeries_recal_titan;
static signed long __initdata iSeries_recal_tb;
+
+/* Forward declaration is only needed for iSereis compiles */
+void __init clocksource_init(void);
#endif
#define XSEC_PER_SEC (1024*1024)
@@ -343,65 +372,6 @@ void udelay(unsigned long usecs)
}
EXPORT_SYMBOL(udelay);
-/*
- * This version of gettimeofday has microsecond resolution.
- */
-static inline void __do_gettimeofday(struct timeval *tv)
-{
- unsigned long sec, usec;
- u64 tb_ticks, xsec;
- struct gettimeofday_vars *temp_varp;
- u64 temp_tb_to_xs, temp_stamp_xsec;
-
- /*
- * These calculations are faster (gets rid of divides)
- * if done in units of 1/2^20 rather than microseconds.
- * The conversion to microseconds at the end is done
- * without a divide (and in fact, without a multiply)
- */
- temp_varp = do_gtod.varp;
-
- /* Sampling the time base must be done after loading
- * do_gtod.varp in order to avoid racing with update_gtod.
- */
- data_barrier(temp_varp);
- tb_ticks = get_tb() - temp_varp->tb_orig_stamp;
- temp_tb_to_xs = temp_varp->tb_to_xs;
- temp_stamp_xsec = temp_varp->stamp_xsec;
- xsec = temp_stamp_xsec + mulhdu(tb_ticks, temp_tb_to_xs);
- sec = xsec / XSEC_PER_SEC;
- usec = (unsigned long)xsec & (XSEC_PER_SEC - 1);
- usec = SCALE_XSEC(usec, 1000000);
-
- tv->tv_sec = sec;
- tv->tv_usec = usec;
-}
-
-void do_gettimeofday(struct timeval *tv)
-{
- if (__USE_RTC()) {
- /* do this the old way */
- unsigned long flags, seq;
- unsigned int sec, nsec, usec;
-
- do {
- seq = read_seqbegin_irqsave(&xtime_lock, flags);
- sec = xtime.tv_sec;
- nsec = xtime.tv_nsec + tb_ticks_since(tb_last_jiffy);
- } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
- usec = nsec / 1000;
- while (usec >= 1000000) {
- usec -= 1000000;
- ++sec;
- }
- tv->tv_sec = sec;
- tv->tv_usec = usec;
- return;
- }
- __do_gettimeofday(tv);
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
/*
* There are two copies of tb_to_xs and stamp_xsec so that no
@@ -447,56 +417,6 @@ static inline void update_gtod(u64 new_t
++(vdso_data->tb_update_count);
}
-/*
- * When the timebase - tb_orig_stamp gets too big, we do a manipulation
- * between tb_orig_stamp and stamp_xsec. The goal here is to keep the
- * difference tb - tb_orig_stamp small enough to always fit inside a
- * 32 bits number. This is a requirement of our fast 32 bits userland
- * implementation in the vdso. If we "miss" a call to this function
- * (interrupt latency, CPU locked in a spinlock, ...) and we end up
- * with a too big difference, then the vdso will fallback to calling
- * the syscall
- */
-static __inline__ void timer_recalc_offset(u64 cur_tb)
-{
- unsigned long offset;
- u64 new_stamp_xsec;
- u64 tlen, t2x;
- u64 tb, xsec_old, xsec_new;
- struct gettimeofday_vars *varp;
-
- if (__USE_RTC())
- return;
- tlen = current_tick_length();
- offset = cur_tb - do_gtod.varp->tb_orig_stamp;
- if (tlen == last_tick_len && offset < 0x80000000u)
- return;
- if (tlen != last_tick_len) {
- t2x = mulhdu(tlen << TICKLEN_SHIFT, ticklen_to_xs);
- last_tick_len = tlen;
- } else
- t2x = do_gtod.varp->tb_to_xs;
- new_stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC;
- do_div(new_stamp_xsec, 1000000000);
- new_stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC;
-
- ++vdso_data->tb_update_count;
- smp_mb();
-
- /*
- * Make sure time doesn't go backwards for userspace gettimeofday.
- */
- tb = get_tb();
- varp = do_gtod.varp;
- xsec_old = mulhdu(tb - varp->tb_orig_stamp, varp->tb_to_xs)
- + varp->stamp_xsec;
- xsec_new = mulhdu(tb - cur_tb, t2x) + new_stamp_xsec;
- if (xsec_new < xsec_old)
- new_stamp_xsec += xsec_old - xsec_new;
-
- update_gtod(cur_tb, new_stamp_xsec, t2x);
-}
-
#ifdef CONFIG_SMP
unsigned long profile_pc(struct pt_regs *regs)
{
@@ -568,6 +488,8 @@ static int __init iSeries_tb_recal(void)
iSeries_recal_titan = titan;
iSeries_recal_tb = tb;
+ /* Called here as now we know accurate values for the timebase */
+ clocksource_init();
return 0;
}
late_initcall(iSeries_tb_recal);
@@ -650,7 +572,6 @@ void timer_interrupt(struct pt_regs * re
if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) {
tb_last_jiffy = tb_next_jiffy;
do_timer(1);
- timer_recalc_offset(tb_last_jiffy);
}
write_sequnlock(&xtime_lock);
}
@@ -722,66 +643,6 @@ unsigned long long sched_clock(void)
return mulhdu(get_tb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift;
}
-int do_settimeofday(struct timespec *tv)
-{
- time_t wtm_sec, new_sec = tv->tv_sec;
- long wtm_nsec, new_nsec = tv->tv_nsec;
- unsigned long flags;
- u64 new_xsec;
- unsigned long tb_delta;
-
- if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
- return -EINVAL;
-
- write_seqlock_irqsave(&xtime_lock, flags);
-
- /*
- * Updating the RTC is not the job of this code. If the time is
- * stepped under NTP, the RTC will be updated after STA_UNSYNC
- * is cleared. Tools like clock/hwclock either copy the RTC
- * to the system time, in which case there is no point in writing
- * to the RTC again, or write to the RTC but then they don't call
- * settimeofday to perform this operation.
- */
-
- /* Make userspace gettimeofday spin until we're done. */
- ++vdso_data->tb_update_count;
- smp_mb();
-
- /*
- * Subtract off the number of nanoseconds since the
- * beginning of the last tick.
- */
- tb_delta = tb_ticks_since(tb_last_jiffy);
- tb_delta = mulhdu(tb_delta, do_gtod.varp->tb_to_xs); /* in xsec */
- new_nsec -= SCALE_XSEC(tb_delta, 1000000000);
-
- wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec);
- wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec);
-
- set_normalized_timespec(&xtime, new_sec, new_nsec);
- set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
- ntp_clear();
-
- new_xsec = xtime.tv_nsec;
- if (new_xsec != 0) {
- new_xsec *= XSEC_PER_SEC;
- do_div(new_xsec, NSEC_PER_SEC);
- }
- new_xsec += (u64)xtime.tv_sec * XSEC_PER_SEC;
- update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs);
-
- vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
- vdso_data->tz_dsttime = sys_tz.tz_dsttime;
-
- write_sequnlock_irqrestore(&xtime_lock, flags);
- clock_was_set();
- return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
-
static int __init get_freq(char *name, int cells, unsigned long *val)
{
struct device_node *cpu;
@@ -873,6 +734,69 @@ unsigned long read_persistent_clock(void
tm.tm_hour, tm.tm_min, tm.tm_sec);
}
+/* clocksource code */
+static cycle_t rtc_read(void)
+{
+ return (cycle_t)get_rtc();
+}
+
+static cycle_t timebase_read(void)
+{
+ return (cycle_t)get_tb();
+}
+
+void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
+{
+ u64 t2x, stamp_xsec;
+
+ if (__USE_RTC() || clock != &clocksource_timebase)
+ return;
+
+ /* Make userspace gettimeofday spin until we're done. */
+ ++vdso_data->tb_update_count;
+ smp_mb();
+
+ /* XXX this assumes clock->shift == 22 */
+ /* 4611686018 ~= 2^(20+64-22) / 1e9 */
+ t2x = (u64) clock->mult * 4611686018ULL;
+ stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC;
+ do_div(stamp_xsec, 1000000000);
+ stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC;
+ update_gtod(clock->cycle_last, stamp_xsec, t2x);
+}
+
+void update_vsyscall_tz(void)
+{
+ /* Make userspace gettimeofday spin until we're done. */
+ ++vdso_data->tb_update_count;
+ smp_mb();
+ vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
+ vdso_data->tz_dsttime = sys_tz.tz_dsttime;
+ smp_mb();
+ ++vdso_data->tb_update_count;
+}
+
+void __init clocksource_init(void)
+{
+ struct clocksource *clock;
+
+ if (__USE_RTC())
+ clock = &clocksource_rtc;
+ else
+ clock = &clocksource_timebase;
+
+ clock->mult = clocksource_hz2mult(tb_ticks_per_sec, clock->shift);
+
+ if (clocksource_register(clock)) {
+ printk(KERN_ERR "clocksource: %s is already registered\n",
+ clock->name);
+ return;
+ }
+
+ printk(KERN_INFO "clocksource: %s mult[%x] shift[%d] registered\n",
+ clock->name, clock->mult, clock->shift);
+}
+
/* This function is only called on the boot processor */
void __init time_init(void)
{
@@ -982,6 +906,12 @@ void __init time_init(void)
write_sequnlock_irqrestore(&xtime_lock, flags);
+ /* Register the clocksource, if we're not running on iSeries */
+#ifdef CONFIG_ISERIES
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+#endif
+ clocksource_init();
+
/* Not exact, but the timer interrupt takes care of this */
set_dec(tb_ticks_per_jiffy);
}
^ permalink raw reply
* [PATCH v2 4/4] Enable tickless idle and high res timers for powerpc
From: Tony Breeds @ 2007-09-21 3:26 UTC (permalink / raw)
To: linuxppc-dev, Paul Mackerras; +Cc: Thomas Gleixner, Realtime Kernel
In-Reply-To: <1190345162.620000.305760830507.qpush@thor>
Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
Updated to remove the need for patching generic code to include hrtimer.h
arch/powerpc/Kconfig | 1 +
arch/powerpc/kernel/idle.c | 3 +++
arch/powerpc/platforms/iseries/setup.c | 5 +++++
3 files changed, 9 insertions(+)
Index: working/arch/powerpc/Kconfig
===================================================================
--- working.orig/arch/powerpc/Kconfig
+++ working/arch/powerpc/Kconfig
@@ -168,6 +168,7 @@ config HIGHMEM
bool "High memory support"
depends on PPC32
+source kernel/time/Kconfig
source kernel/Kconfig.hz
source kernel/Kconfig.preempt
source "fs/Kconfig.binfmt"
Index: working/arch/powerpc/kernel/idle.c
===================================================================
--- working.orig/arch/powerpc/kernel/idle.c
+++ working/arch/powerpc/kernel/idle.c
@@ -24,6 +24,7 @@
#include <linux/smp.h>
#include <linux/cpu.h>
#include <linux/sysctl.h>
+#include <linux/tick.h>
#include <asm/system.h>
#include <asm/processor.h>
@@ -59,6 +60,7 @@ void cpu_idle(void)
set_thread_flag(TIF_POLLING_NRFLAG);
while (1) {
+ tick_nohz_stop_sched_tick();
while (!need_resched() && !cpu_should_die()) {
ppc64_runlatch_off();
@@ -90,6 +92,7 @@ void cpu_idle(void)
HMT_medium();
ppc64_runlatch_on();
+ tick_nohz_restart_sched_tick();
if (cpu_should_die())
cpu_die();
preempt_enable_no_resched();
Index: working/arch/powerpc/platforms/iseries/setup.c
===================================================================
--- working.orig/arch/powerpc/platforms/iseries/setup.c
+++ working/arch/powerpc/platforms/iseries/setup.c
@@ -26,6 +26,8 @@
#include <linux/major.h>
#include <linux/root_dev.h>
#include <linux/kernel.h>
+#include <linux/hrtimer.h>
+#include <linux/tick.h>
#include <asm/processor.h>
#include <asm/machdep.h>
@@ -561,6 +563,7 @@ static void yield_shared_processor(void)
static void iseries_shared_idle(void)
{
while (1) {
+ tick_nohz_stop_sched_tick();
while (!need_resched() && !hvlpevent_is_pending()) {
local_irq_disable();
ppc64_runlatch_off();
@@ -574,6 +577,7 @@ static void iseries_shared_idle(void)
}
ppc64_runlatch_on();
+ tick_nohz_restart_sched_tick();
if (hvlpevent_is_pending())
process_iSeries_events();
@@ -589,6 +593,7 @@ static void iseries_dedicated_idle(void)
set_thread_flag(TIF_POLLING_NRFLAG);
while (1) {
+ tick_nohz_stop_sched_tick();
if (!need_resched()) {
while (!need_resched()) {
ppc64_runlatch_off();
@@ -605,6 +610,7 @@ static void iseries_dedicated_idle(void)
}
ppc64_runlatch_on();
+ tick_nohz_restart_sched_tick();
preempt_enable_no_resched();
schedule();
preempt_disable();
^ 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