* [Qemu-devel] [PATCH 0/3] Generalize bitbang MDIO and use for versatile-pb
@ 2013-01-19 22:28 Grant Likely
2013-01-19 22:28 ` [Qemu-devel] [PATCH 1/3] net/bitbang_mdio: Generalize etraxfs MDIO bitbanging emulation Grant Likely
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Grant Likely @ 2013-01-19 22:28 UTC (permalink / raw)
To: qemu-devel
This series extracts the MDIO bitbang code from the etraxfs driver and
makes it usable on targets using the smc91111 Ethernet controller. I've
tested this using u-boot on the versatile-pb model.
net/bitbang_mdio: Generalize etraxfs MDIO bitbanging emulation
net/bitbang_mdio: Never set PHY RST and ANEG_RST bits on register write
net/bitbang_mdio: Use bitbang core for smc91c111 network device
hw/Makefile.objs | 2 +-
hw/bitbang_mdio.c | 271 ++++++++++++++++++++++++++++++++++++++++++++++++
hw/bitbang_mdio.h | 72 +++++++++++++
hw/cris/Makefile.objs | 1 +
hw/etraxfs_eth.c | 273 +------------------------------------------------
hw/smc91c111.c | 29 +++++-
6 files changed, 371 insertions(+), 277 deletions(-)
create mode 100644 hw/bitbang_mdio.c
create mode 100644 hw/bitbang_mdio.h
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 1/3] net/bitbang_mdio: Generalize etraxfs MDIO bitbanging emulation
2013-01-19 22:28 [Qemu-devel] [PATCH 0/3] Generalize bitbang MDIO and use for versatile-pb Grant Likely
@ 2013-01-19 22:28 ` Grant Likely
2013-01-20 17:29 ` Andreas Färber
2013-01-21 12:51 ` Edgar E. Iglesias
2013-01-19 22:28 ` [Qemu-devel] [PATCH 2/3] net/bitbang_mdio: Never set PHY RST and ANEG_RST bits on register write Grant Likely
` (2 subsequent siblings)
3 siblings, 2 replies; 9+ messages in thread
From: Grant Likely @ 2013-01-19 22:28 UTC (permalink / raw)
To: qemu-devel
Cc: Grant Likely, Peter Maydell, Anthony Liguori, Paul Brook,
Edgar E. Iglesias
The etraxfs Ethernet model implements quite a nice bitbanging core. The
change splits it out into a separate .c file. There are no functional
changes here, just movement of code and reformatting to match qemu
coding standards.
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Paul Brook <paul@codesourcery.com>
Cc: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Cc: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
hw/bitbang_mdio.c | 263 +++++++++++++++++++++++++++++++++++++++++++++++
hw/bitbang_mdio.h | 72 +++++++++++++
hw/cris/Makefile.objs | 1 +
hw/etraxfs_eth.c | 273 +------------------------------------------------
4 files changed, 337 insertions(+), 272 deletions(-)
create mode 100644 hw/bitbang_mdio.c
create mode 100644 hw/bitbang_mdio.h
diff --git a/hw/bitbang_mdio.c b/hw/bitbang_mdio.c
new file mode 100644
index 0000000..f0ee6af
--- /dev/null
+++ b/hw/bitbang_mdio.c
@@ -0,0 +1,263 @@
+/*
+ * QEMU Bitbang Ethernet MDIO bus & PHY controllers.
+ *
+ * Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include "qemu-common.h"
+#include "qemu/log.h"
+#include "bitbang_mdio.h"
+
+#define D(x)
+
+/* Advertisement control register. */
+#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
+#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
+#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
+#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
+
+/*
+ * The MDIO extensions in the TDK PHY model were reversed engineered from the
+ * linux driver (PHYID and Diagnostics reg).
+ * TODO: Add friendly names for the register nums.
+ */
+static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req)
+{
+ int regnum;
+ unsigned r = 0;
+
+ regnum = req & 0x1f;
+
+ switch (regnum) {
+ case 1:
+ if (!phy->link) {
+ break;
+ }
+ /* MR1. */
+ /* Speeds and modes. */
+ r |= (1 << 13) | (1 << 14);
+ r |= (1 << 11) | (1 << 12);
+ r |= (1 << 5); /* Autoneg complete. */
+ r |= (1 << 3); /* Autoneg able. */
+ r |= (1 << 2); /* link. */
+ break;
+ case 5:
+ /* Link partner ability.
+ We are kind; always agree with whatever best mode
+ the guest advertises. */
+ r = 1 << 14; /* Success. */
+ /* Copy advertised modes. */
+ r |= phy->regs[4] & (15 << 5);
+ /* Autoneg support. */
+ r |= 1;
+ break;
+ case 18:
+ {
+ /* Diagnostics reg. */
+ int duplex = 0;
+ int speed_100 = 0;
+
+ if (!phy->link) {
+ break;
+ }
+
+ /* Are we advertising 100 half or 100 duplex ? */
+ speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF);
+ speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL);
+
+ /* Are we advertising 10 duplex or 100 duplex ? */
+ duplex = !!(phy->regs[4] & ADVERTISE_100FULL);
+ duplex |= !!(phy->regs[4] & ADVERTISE_10FULL);
+ r = (speed_100 << 10) | (duplex << 11);
+ }
+ break;
+
+ default:
+ r = phy->regs[regnum];
+ break;
+ }
+ D(printf("\n%s %x = reg[%d]\n", __func__, r, regnum));
+ return r;
+}
+
+static void tdk_write(struct qemu_phy *phy, unsigned int req, unsigned int data)
+{
+ int regnum;
+
+ regnum = req & 0x1f;
+ D(printf("%s reg[%d] = %x\n", __func__, regnum, data));
+ switch (regnum) {
+ default:
+ phy->regs[regnum] = data;
+ break;
+ }
+}
+
+void tdk_init(struct qemu_phy *phy)
+{
+ phy->regs[0] = 0x3100;
+ /* PHY Id. */
+ phy->regs[2] = 0x0300;
+ phy->regs[3] = 0xe400;
+ /* Autonegotiation advertisement reg. */
+ phy->regs[4] = 0x01e1;
+ phy->link = 1;
+
+ phy->read = tdk_read;
+ phy->write = tdk_write;
+}
+
+void mdio_attach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr)
+{
+ bus->devs[addr & 0x1f] = phy;
+}
+
+#ifdef USE_THIS_DEAD_CODE
+void mdio_detach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr)
+{
+ bus->devs[addr & 0x1f] = NULL;
+}
+#endif
+
+void mdio_read_req(struct qemu_mdio *bus)
+{
+ struct qemu_phy *phy;
+
+ phy = bus->devs[bus->addr];
+ if (phy && phy->read) {
+ bus->data = phy->read(phy, bus->req);
+ } else {
+ bus->data = 0xffff;
+ }
+ D(qemu_log("%s addr=%d reg=%d data=%x\n", __func__,
+ bus->addr, bus->req, bus->data));
+}
+
+void mdio_write_req(struct qemu_mdio *bus)
+{
+ struct qemu_phy *phy;
+
+ phy = bus->devs[bus->addr];
+ if (phy && phy->write) {
+ phy->write(phy, bus->req, bus->data);
+ }
+}
+
+void mdio_cycle(struct qemu_mdio *bus)
+{
+ bus->cnt++;
+
+ D(printf("mdc=%d mdio=%d state=%d cnt=%d drv=%d\n",
+ bus->mdc, bus->mdio, bus->state, bus->cnt, bus->drive));
+ switch (bus->state) {
+ case PREAMBLE:
+ if (bus->mdc) {
+ if (bus->cnt >= (32 * 2) && !bus->mdio) {
+ bus->cnt = 0;
+ bus->state = SOF;
+ bus->data = 0;
+ }
+ }
+ break;
+ case SOF:
+ if (bus->mdc) {
+ if (bus->mdio != 1) {
+ printf("WARNING: no SOF\n");
+ }
+ if (bus->cnt == 1*2) {
+ bus->cnt = 0;
+ bus->opc = 0;
+ bus->state = OPC;
+ }
+ }
+ break;
+ case OPC:
+ if (bus->mdc) {
+ bus->opc <<= 1;
+ bus->opc |= bus->mdio & 1;
+ if (bus->cnt == 2*2) {
+ bus->cnt = 0;
+ bus->addr = 0;
+ bus->state = ADDR;
+ }
+ }
+ break;
+ case ADDR:
+ if (bus->mdc) {
+ bus->addr <<= 1;
+ bus->addr |= bus->mdio & 1;
+
+ if (bus->cnt == 5*2) {
+ bus->cnt = 0;
+ bus->req = 0;
+ bus->state = REQ;
+ }
+ }
+ break;
+ case REQ:
+ if (bus->mdc) {
+ bus->req <<= 1;
+ bus->req |= bus->mdio & 1;
+ if (bus->cnt == 5*2) {
+ bus->cnt = 0;
+ bus->state = TURNAROUND;
+ }
+ }
+ break;
+ case TURNAROUND:
+ if (bus->mdc && bus->cnt == 2*2) {
+ bus->mdio = 0;
+ bus->cnt = 0;
+
+ if (bus->opc == 2) {
+ bus->drive = 1;
+ mdio_read_req(bus);
+ bus->mdio = bus->data & 1;
+ }
+ bus->state = DATA;
+ }
+ break;
+ case DATA:
+ if (!bus->mdc) {
+ if (bus->drive) {
+ bus->mdio = !!(bus->data & (1 << 15));
+ bus->data <<= 1;
+ }
+ } else {
+ if (!bus->drive) {
+ bus->data <<= 1;
+ bus->data |= bus->mdio;
+ }
+ if (bus->cnt == 16 * 2) {
+ bus->cnt = 0;
+ bus->state = PREAMBLE;
+ if (!bus->drive) {
+ mdio_write_req(bus);
+ }
+ bus->drive = 0;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
diff --git a/hw/bitbang_mdio.h b/hw/bitbang_mdio.h
new file mode 100644
index 0000000..3484aba
--- /dev/null
+++ b/hw/bitbang_mdio.h
@@ -0,0 +1,72 @@
+#ifndef BITBANG_MDIO_H
+#define BITBANG_MDIO_H
+
+/*
+ * QEMU Bitbang Ethernet MDIO bus & PHY controllers.
+ *
+ * Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+struct qemu_phy {
+ uint32_t regs[32];
+
+ int link;
+
+ unsigned int (*read)(struct qemu_phy *phy, unsigned int req);
+ void (*write)(struct qemu_phy *phy, unsigned int req, unsigned int data);
+};
+
+struct qemu_mdio {
+ /* bus. */
+ int mdc;
+ int mdio;
+
+ /* decoder. */
+ enum {
+ PREAMBLE,
+ SOF,
+ OPC,
+ ADDR,
+ REQ,
+ TURNAROUND,
+ DATA
+ } state;
+ unsigned int drive;
+
+ unsigned int cnt;
+ unsigned int addr;
+ unsigned int opc;
+ unsigned int req;
+ unsigned int data;
+
+ struct qemu_phy *devs[32];
+};
+
+void tdk_init(struct qemu_phy *phy);
+void mdio_attach(struct qemu_mdio *bus, struct qemu_phy *phy,
+ unsigned int addr);
+void mdio_read_req(struct qemu_mdio *bus);
+void mdio_write_req(struct qemu_mdio *bus);
+void mdio_cycle(struct qemu_mdio *bus);
+
+#endif
diff --git a/hw/cris/Makefile.objs b/hw/cris/Makefile.objs
index aa9298a..86759a3 100644
--- a/hw/cris/Makefile.objs
+++ b/hw/cris/Makefile.objs
@@ -9,5 +9,6 @@ obj-y += etraxfs_pic.o
obj-y += etraxfs_eth.o
obj-y += etraxfs_timer.o
obj-y += etraxfs_ser.o
+obj-y += bitbang_mdio.o
obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c
index ec23fa6..67b4797 100644
--- a/hw/etraxfs_eth.c
+++ b/hw/etraxfs_eth.c
@@ -26,281 +26,10 @@
#include "sysbus.h"
#include "net/net.h"
#include "etraxfs.h"
+#include "bitbang_mdio.h"
#define D(x)
-/* Advertisement control register. */
-#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
-#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
-#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
-#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
-
-/*
- * The MDIO extensions in the TDK PHY model were reversed engineered from the
- * linux driver (PHYID and Diagnostics reg).
- * TODO: Add friendly names for the register nums.
- */
-struct qemu_phy
-{
- uint32_t regs[32];
-
- int link;
-
- unsigned int (*read)(struct qemu_phy *phy, unsigned int req);
- void (*write)(struct qemu_phy *phy, unsigned int req,
- unsigned int data);
-};
-
-static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req)
-{
- int regnum;
- unsigned r = 0;
-
- regnum = req & 0x1f;
-
- switch (regnum) {
- case 1:
- if (!phy->link)
- break;
- /* MR1. */
- /* Speeds and modes. */
- r |= (1 << 13) | (1 << 14);
- r |= (1 << 11) | (1 << 12);
- r |= (1 << 5); /* Autoneg complete. */
- r |= (1 << 3); /* Autoneg able. */
- r |= (1 << 2); /* link. */
- break;
- case 5:
- /* Link partner ability.
- We are kind; always agree with whatever best mode
- the guest advertises. */
- r = 1 << 14; /* Success. */
- /* Copy advertised modes. */
- r |= phy->regs[4] & (15 << 5);
- /* Autoneg support. */
- r |= 1;
- break;
- case 18:
- {
- /* Diagnostics reg. */
- int duplex = 0;
- int speed_100 = 0;
-
- if (!phy->link)
- break;
-
- /* Are we advertising 100 half or 100 duplex ? */
- speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF);
- speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL);
-
- /* Are we advertising 10 duplex or 100 duplex ? */
- duplex = !!(phy->regs[4] & ADVERTISE_100FULL);
- duplex |= !!(phy->regs[4] & ADVERTISE_10FULL);
- r = (speed_100 << 10) | (duplex << 11);
- }
- break;
-
- default:
- r = phy->regs[regnum];
- break;
- }
- D(printf("\n%s %x = reg[%d]\n", __func__, r, regnum));
- return r;
-}
-
-static void
-tdk_write(struct qemu_phy *phy, unsigned int req, unsigned int data)
-{
- int regnum;
-
- regnum = req & 0x1f;
- D(printf("%s reg[%d] = %x\n", __func__, regnum, data));
- switch (regnum) {
- default:
- phy->regs[regnum] = data;
- break;
- }
-}
-
-static void
-tdk_init(struct qemu_phy *phy)
-{
- phy->regs[0] = 0x3100;
- /* PHY Id. */
- phy->regs[2] = 0x0300;
- phy->regs[3] = 0xe400;
- /* Autonegotiation advertisement reg. */
- phy->regs[4] = 0x01E1;
- phy->link = 1;
-
- phy->read = tdk_read;
- phy->write = tdk_write;
-}
-
-struct qemu_mdio
-{
- /* bus. */
- int mdc;
- int mdio;
-
- /* decoder. */
- enum {
- PREAMBLE,
- SOF,
- OPC,
- ADDR,
- REQ,
- TURNAROUND,
- DATA
- } state;
- unsigned int drive;
-
- unsigned int cnt;
- unsigned int addr;
- unsigned int opc;
- unsigned int req;
- unsigned int data;
-
- struct qemu_phy *devs[32];
-};
-
-static void
-mdio_attach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr)
-{
- bus->devs[addr & 0x1f] = phy;
-}
-
-#ifdef USE_THIS_DEAD_CODE
-static void
-mdio_detach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr)
-{
- bus->devs[addr & 0x1f] = NULL;
-}
-#endif
-
-static void mdio_read_req(struct qemu_mdio *bus)
-{
- struct qemu_phy *phy;
-
- phy = bus->devs[bus->addr];
- if (phy && phy->read)
- bus->data = phy->read(phy, bus->req);
- else
- bus->data = 0xffff;
-}
-
-static void mdio_write_req(struct qemu_mdio *bus)
-{
- struct qemu_phy *phy;
-
- phy = bus->devs[bus->addr];
- if (phy && phy->write)
- phy->write(phy, bus->req, bus->data);
-}
-
-static void mdio_cycle(struct qemu_mdio *bus)
-{
- bus->cnt++;
-
- D(printf("mdc=%d mdio=%d state=%d cnt=%d drv=%d\n",
- bus->mdc, bus->mdio, bus->state, bus->cnt, bus->drive));
-#if 0
- if (bus->mdc)
- printf("%d", bus->mdio);
-#endif
- switch (bus->state)
- {
- case PREAMBLE:
- if (bus->mdc) {
- if (bus->cnt >= (32 * 2) && !bus->mdio) {
- bus->cnt = 0;
- bus->state = SOF;
- bus->data = 0;
- }
- }
- break;
- case SOF:
- if (bus->mdc) {
- if (bus->mdio != 1)
- printf("WARNING: no SOF\n");
- if (bus->cnt == 1*2) {
- bus->cnt = 0;
- bus->opc = 0;
- bus->state = OPC;
- }
- }
- break;
- case OPC:
- if (bus->mdc) {
- bus->opc <<= 1;
- bus->opc |= bus->mdio & 1;
- if (bus->cnt == 2*2) {
- bus->cnt = 0;
- bus->addr = 0;
- bus->state = ADDR;
- }
- }
- break;
- case ADDR:
- if (bus->mdc) {
- bus->addr <<= 1;
- bus->addr |= bus->mdio & 1;
-
- if (bus->cnt == 5*2) {
- bus->cnt = 0;
- bus->req = 0;
- bus->state = REQ;
- }
- }
- break;
- case REQ:
- if (bus->mdc) {
- bus->req <<= 1;
- bus->req |= bus->mdio & 1;
- if (bus->cnt == 5*2) {
- bus->cnt = 0;
- bus->state = TURNAROUND;
- }
- }
- break;
- case TURNAROUND:
- if (bus->mdc && bus->cnt == 2*2) {
- bus->mdio = 0;
- bus->cnt = 0;
-
- if (bus->opc == 2) {
- bus->drive = 1;
- mdio_read_req(bus);
- bus->mdio = bus->data & 1;
- }
- bus->state = DATA;
- }
- break;
- case DATA:
- if (!bus->mdc) {
- if (bus->drive) {
- bus->mdio = !!(bus->data & (1 << 15));
- bus->data <<= 1;
- }
- } else {
- if (!bus->drive) {
- bus->data <<= 1;
- bus->data |= bus->mdio;
- }
- if (bus->cnt == 16 * 2) {
- bus->cnt = 0;
- bus->state = PREAMBLE;
- if (!bus->drive)
- mdio_write_req(bus);
- bus->drive = 0;
- }
- }
- break;
- default:
- break;
- }
-}
-
/* ETRAX-FS Ethernet MAC block starts here. */
#define RW_MA0_LO 0x00
--
1.7.10.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 2/3] net/bitbang_mdio: Never set PHY RST and ANEG_RST bits on register write
2013-01-19 22:28 [Qemu-devel] [PATCH 0/3] Generalize bitbang MDIO and use for versatile-pb Grant Likely
2013-01-19 22:28 ` [Qemu-devel] [PATCH 1/3] net/bitbang_mdio: Generalize etraxfs MDIO bitbanging emulation Grant Likely
@ 2013-01-19 22:28 ` Grant Likely
2013-01-19 22:28 ` [Qemu-devel] [PATCH 3/3] net/bitbang_mdio: Use bitbang core for smc91c111 network device Grant Likely
2013-01-20 17:26 ` [Qemu-devel] [PATCH 0/3] Generalize bitbang MDIO and use for versatile-pb Andreas Färber
3 siblings, 0 replies; 9+ messages in thread
From: Grant Likely @ 2013-01-19 22:28 UTC (permalink / raw)
To: qemu-devel
Cc: Grant Likely, Peter Maydell, Anthony Liguori, Paul Brook,
Edgar E. Iglesias
The RST and ANEG_RST bits are commands, not settings. An operating
system will get confused (or at least u-boot does) if those bits remain
set after writing to them. Therefore, mask them out on write.
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Paul Brook <paul@codesourcery.com>
Cc: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Cc: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
hw/bitbang_mdio.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/hw/bitbang_mdio.c b/hw/bitbang_mdio.c
index f0ee6af..28ac695 100644
--- a/hw/bitbang_mdio.c
+++ b/hw/bitbang_mdio.c
@@ -30,6 +30,10 @@
#define D(x)
/* Advertisement control register. */
+#define PHY_CNTL_REG 0
+#define PHY_CNTL_RST 0x8000 /* PHY reset command */
+#define PHY_CNTL_ANEG_RST 0x0200 /* Autonegotiation reset command */
+
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
@@ -106,6 +110,10 @@ static void tdk_write(struct qemu_phy *phy, unsigned int req, unsigned int data)
regnum = req & 0x1f;
D(printf("%s reg[%d] = %x\n", __func__, regnum, data));
switch (regnum) {
+ case PHY_CNTL_REG:
+ /* Don't ever store the RST or ANEG_RST bits; they are commands */
+ phy->regs[regnum] = data & ~(PHY_CNTL_RST | PHY_CNTL_ANEG_RST);
+ break;
default:
phy->regs[regnum] = data;
break;
@@ -114,7 +122,7 @@ static void tdk_write(struct qemu_phy *phy, unsigned int req, unsigned int data)
void tdk_init(struct qemu_phy *phy)
{
- phy->regs[0] = 0x3100;
+ phy->regs[PHY_CNTL_REG] = 0x3100;
/* PHY Id. */
phy->regs[2] = 0x0300;
phy->regs[3] = 0xe400;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 3/3] net/bitbang_mdio: Use bitbang core for smc91c111 network device
2013-01-19 22:28 [Qemu-devel] [PATCH 0/3] Generalize bitbang MDIO and use for versatile-pb Grant Likely
2013-01-19 22:28 ` [Qemu-devel] [PATCH 1/3] net/bitbang_mdio: Generalize etraxfs MDIO bitbanging emulation Grant Likely
2013-01-19 22:28 ` [Qemu-devel] [PATCH 2/3] net/bitbang_mdio: Never set PHY RST and ANEG_RST bits on register write Grant Likely
@ 2013-01-19 22:28 ` Grant Likely
2013-01-20 11:29 ` Peter Maydell
2013-01-20 17:26 ` [Qemu-devel] [PATCH 0/3] Generalize bitbang MDIO and use for versatile-pb Andreas Färber
3 siblings, 1 reply; 9+ messages in thread
From: Grant Likely @ 2013-01-19 22:28 UTC (permalink / raw)
To: qemu-devel
Cc: Grant Likely, Peter Maydell, Anthony Liguori, Paul Brook,
Edgar E. Iglesias
The smc91c111 device has bitbanged MDIO access, but the model doesn't
yet implement it. This patch uses the generalized bitbang MDIO support
pulled out of etraxfs Ethernet driver.
The MDIO state machine is driven by changes in state to the clock
control bit in the management register. The PHY model emulated is
currently trivial (being whatever was done for the etraxfs driver), but
it is enough to get an OS to recognize a PHY as being present.
Tested with the versatilepb model with U-Boot and the Linux Kernel as
client software.
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Paul Brook <paul@codesourcery.com>
Cc: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Cc: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
hw/Makefile.objs | 2 +-
hw/smc91c111.c | 29 +++++++++++++++++++++++++----
2 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 74b07a7..0104fd4 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -117,7 +117,7 @@ common-obj-$(CONFIG_PCNET_COMMON) += pcnet.o
common-obj-$(CONFIG_E1000_PCI) += e1000.o
common-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o
-common-obj-$(CONFIG_SMC91C111) += smc91c111.o
+common-obj-$(CONFIG_SMC91C111) += smc91c111.o bitbang_mdio.o
common-obj-$(CONFIG_LAN9118) += lan9118.o
common-obj-$(CONFIG_NE2000_ISA) += ne2000-isa.o
common-obj-$(CONFIG_OPENCORES_ETH) += opencores_eth.o
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index a34698f..715422d 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -10,6 +10,7 @@
#include "sysbus.h"
#include "net/net.h"
#include "devices.h"
+#include "bitbang_mdio.h"
/* For crc32 */
#include <zlib.h>
@@ -44,6 +45,13 @@ typedef struct {
uint8_t int_level;
uint8_t int_mask;
MemoryRegion mmio;
+
+ /* MDIO bus. */
+ struct qemu_mdio mdio_bus;
+ unsigned int phyaddr;
+
+ /* PHY. */
+ struct qemu_phy phy;
} smc91c111_state;
static const VMStateDescription vmstate_smc91c111 = {
@@ -437,8 +445,19 @@ static void smc91c111_writeb(void *opaque, hwaddr offset,
/* Multicast table. */
/* Not implemented. */
return;
- case 8: case 9: /* Management Interface. */
- /* Not implemented. */
+ case 8: /* Management Interface. */
+ /* Update MDIO data line status; but only if output is enabled */
+ if (value & 8) {
+ s->mdio_bus.mdio = !!(value & 1);
+ }
+ /* Process the clock */
+ if (s->mdio_bus.mdc != (value & 4)) {
+ mdio_cycle(&s->mdio_bus);
+ s->mdio_bus.mdc = !!(value & 4);
+ }
+ return;
+ case 9: /* Management Interface. */
+ /* Not implemented */
return;
case 12: /* Early receive. */
s->ercv = value & 0x1f;
@@ -576,8 +595,7 @@ static uint32_t smc91c111_readb(void *opaque, hwaddr offset)
/* Not implemented. */
return 0;
case 8: /* Management Interface. */
- /* Not implemented. */
- return 0x30;
+ return 0x30 | (s->mdio_bus.mdio ? 2 : 0);
case 9:
return 0x33;
case 10: /* Revision. */
@@ -754,6 +772,9 @@ static int smc91c111_init1(SysBusDevice *dev)
s->nic = qemu_new_nic(&net_smc91c111_info, &s->conf,
object_get_typename(OBJECT(dev)), dev->qdev.id, s);
qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
+
+ tdk_init(&s->phy);
+ mdio_attach(&s->mdio_bus, &s->phy, 0);
/* ??? Save/restore. */
return 0;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH 3/3] net/bitbang_mdio: Use bitbang core for smc91c111 network device
2013-01-19 22:28 ` [Qemu-devel] [PATCH 3/3] net/bitbang_mdio: Use bitbang core for smc91c111 network device Grant Likely
@ 2013-01-20 11:29 ` Peter Maydell
2013-01-21 13:12 ` Grant Likely
0 siblings, 1 reply; 9+ messages in thread
From: Peter Maydell @ 2013-01-20 11:29 UTC (permalink / raw)
To: Grant Likely; +Cc: Edgar E. Iglesias, Anthony Liguori, qemu-devel, Paul Brook
On 19 January 2013 22:28, Grant Likely <grant.likely@secretlab.ca> wrote:
> The smc91c111 device has bitbanged MDIO access, but the model doesn't
> yet implement it. This patch uses the generalized bitbang MDIO support
> pulled out of etraxfs Ethernet driver.
> @@ -44,6 +45,13 @@ typedef struct {
> uint8_t int_level;
> uint8_t int_mask;
> MemoryRegion mmio;
> +
> + /* MDIO bus. */
> + struct qemu_mdio mdio_bus;
> + unsigned int phyaddr;
> +
> + /* PHY. */
> + struct qemu_phy phy;
> } smc91c111_state;
This surely needs VMState additions so the extra state can be passed
across migrations. It looks like the MDIO/PHY stuff from the etraxfs code
doesn't have any kind of state save/restore support, so you probably need
to first implement that in your new mdio/phy source file, and then refer
to it here.
-- PMM
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH 0/3] Generalize bitbang MDIO and use for versatile-pb
2013-01-19 22:28 [Qemu-devel] [PATCH 0/3] Generalize bitbang MDIO and use for versatile-pb Grant Likely
` (2 preceding siblings ...)
2013-01-19 22:28 ` [Qemu-devel] [PATCH 3/3] net/bitbang_mdio: Use bitbang core for smc91c111 network device Grant Likely
@ 2013-01-20 17:26 ` Andreas Färber
3 siblings, 0 replies; 9+ messages in thread
From: Andreas Färber @ 2013-01-20 17:26 UTC (permalink / raw)
To: Grant Likely
Cc: Edgar E. Iglesias, qemu-devel, Stefan Hajnoczi, Peter Maydell
Am 19.01.2013 23:28, schrieb Grant Likely:
> This series extracts the MDIO bitbang code from the etraxfs driver and
> makes it usable on targets using the smc91111 Ethernet controller. I've
> tested this using u-boot on the versatile-pb model.
>
> net/bitbang_mdio: Generalize etraxfs MDIO bitbanging emulation
> net/bitbang_mdio: Never set PHY RST and ANEG_RST bits on register write
> net/bitbang_mdio: Use bitbang core for smc91c111 network device
>
> hw/Makefile.objs | 2 +-
> hw/bitbang_mdio.c | 271 ++++++++++++++++++++++++++++++++++++++++++++++++
> hw/bitbang_mdio.h | 72 +++++++++++++
> hw/cris/Makefile.objs | 1 +
> hw/etraxfs_eth.c | 273 +------------------------------------------------
> hw/smc91c111.c | 29 +++++-
> 6 files changed, 371 insertions(+), 277 deletions(-)
> create mode 100644 hw/bitbang_mdio.c
> create mode 100644 hw/bitbang_mdio.h
Neither of these files is actually in net/, so please fix that or name
the subject less misleading "bitbang_mdio: ..." if you resend.
Andreas
--
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH 1/3] net/bitbang_mdio: Generalize etraxfs MDIO bitbanging emulation
2013-01-19 22:28 ` [Qemu-devel] [PATCH 1/3] net/bitbang_mdio: Generalize etraxfs MDIO bitbanging emulation Grant Likely
@ 2013-01-20 17:29 ` Andreas Färber
2013-01-21 12:51 ` Edgar E. Iglesias
1 sibling, 0 replies; 9+ messages in thread
From: Andreas Färber @ 2013-01-20 17:29 UTC (permalink / raw)
To: Grant Likely
Cc: Peter Maydell, Anthony Liguori, Edgar E. Iglesias, qemu-devel,
Paul Brook
Am 19.01.2013 23:28, schrieb Grant Likely:
> The etraxfs Ethernet model implements quite a nice bitbanging core. The
> change splits it out into a separate .c file. There are no functional
> changes here, just movement of code and reformatting to match qemu
> coding standards.
>
> Cc: Peter Maydell <peter.maydell@linaro.org>
> Cc: Paul Brook <paul@codesourcery.com>
> Cc: Edgar E. Iglesias <edgar.iglesias@gmail.com>
> Cc: Anthony Liguori <aliguori@us.ibm.com>
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> ---
> hw/bitbang_mdio.c | 263 +++++++++++++++++++++++++++++++++++++++++++++++
> hw/bitbang_mdio.h | 72 +++++++++++++
> hw/cris/Makefile.objs | 1 +
> hw/etraxfs_eth.c | 273 +------------------------------------------------
> 4 files changed, 337 insertions(+), 272 deletions(-)
> create mode 100644 hw/bitbang_mdio.c
> create mode 100644 hw/bitbang_mdio.h
If you fix coding style issues in the original file first this helps
git's copy detection. Looks like either you have it disabled for patches
or it's not detecting it at all... I would expect some "similarity N%"
notice.
Cheers,
Andreas
--
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH 1/3] net/bitbang_mdio: Generalize etraxfs MDIO bitbanging emulation
2013-01-19 22:28 ` [Qemu-devel] [PATCH 1/3] net/bitbang_mdio: Generalize etraxfs MDIO bitbanging emulation Grant Likely
2013-01-20 17:29 ` Andreas Färber
@ 2013-01-21 12:51 ` Edgar E. Iglesias
1 sibling, 0 replies; 9+ messages in thread
From: Edgar E. Iglesias @ 2013-01-21 12:51 UTC (permalink / raw)
To: Grant Likely; +Cc: Peter Maydell, Anthony Liguori, qemu-devel, Paul Brook
On Sat, Jan 19, 2013 at 06:28:10PM -0400, Grant Likely wrote:
> The etraxfs Ethernet model implements quite a nice bitbanging core. The
> change splits it out into a separate .c file. There are no functional
> changes here, just movement of code and reformatting to match qemu
> coding standards.
Hi Grant!
It makes sense to move it out.
A few comments:
* Maybe we could separate the phy models from the bus model/infrastructure.
I.e, the qemu_mdio parts into one file and the qemu_phy into another one.
That way we can add other phy models and keep things separated.
* Not sure bitbang_ makes sense in the naming, the abstraction supports
both the bit twiddeling model with MDIO cycles but also a higher level
transactional version (mdio_write_req etc) that bypass the cycle accuracy.
The latter is useful for modeling NICs that have MDIO support in hw, e.g
like the hw/xilinx_axienet.c while beeing able to reuse the PHY models.
I realize I should have done this split when doing the axienet model, sorry..
Best regards,
Edgar
>
> Cc: Peter Maydell <peter.maydell@linaro.org>
> Cc: Paul Brook <paul@codesourcery.com>
> Cc: Edgar E. Iglesias <edgar.iglesias@gmail.com>
> Cc: Anthony Liguori <aliguori@us.ibm.com>
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> ---
> hw/bitbang_mdio.c | 263 +++++++++++++++++++++++++++++++++++++++++++++++
> hw/bitbang_mdio.h | 72 +++++++++++++
> hw/cris/Makefile.objs | 1 +
> hw/etraxfs_eth.c | 273 +------------------------------------------------
> 4 files changed, 337 insertions(+), 272 deletions(-)
> create mode 100644 hw/bitbang_mdio.c
> create mode 100644 hw/bitbang_mdio.h
>
> diff --git a/hw/bitbang_mdio.c b/hw/bitbang_mdio.c
> new file mode 100644
> index 0000000..f0ee6af
> --- /dev/null
> +++ b/hw/bitbang_mdio.c
> @@ -0,0 +1,263 @@
> +/*
> + * QEMU Bitbang Ethernet MDIO bus & PHY controllers.
> + *
> + * Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include <stdio.h>
> +#include "qemu-common.h"
> +#include "qemu/log.h"
> +#include "bitbang_mdio.h"
> +
> +#define D(x)
> +
> +/* Advertisement control register. */
> +#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
> +#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
> +#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
> +#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
> +
> +/*
> + * The MDIO extensions in the TDK PHY model were reversed engineered from the
> + * linux driver (PHYID and Diagnostics reg).
> + * TODO: Add friendly names for the register nums.
> + */
> +static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req)
> +{
> + int regnum;
> + unsigned r = 0;
> +
> + regnum = req & 0x1f;
> +
> + switch (regnum) {
> + case 1:
> + if (!phy->link) {
> + break;
> + }
> + /* MR1. */
> + /* Speeds and modes. */
> + r |= (1 << 13) | (1 << 14);
> + r |= (1 << 11) | (1 << 12);
> + r |= (1 << 5); /* Autoneg complete. */
> + r |= (1 << 3); /* Autoneg able. */
> + r |= (1 << 2); /* link. */
> + break;
> + case 5:
> + /* Link partner ability.
> + We are kind; always agree with whatever best mode
> + the guest advertises. */
> + r = 1 << 14; /* Success. */
> + /* Copy advertised modes. */
> + r |= phy->regs[4] & (15 << 5);
> + /* Autoneg support. */
> + r |= 1;
> + break;
> + case 18:
> + {
> + /* Diagnostics reg. */
> + int duplex = 0;
> + int speed_100 = 0;
> +
> + if (!phy->link) {
> + break;
> + }
> +
> + /* Are we advertising 100 half or 100 duplex ? */
> + speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF);
> + speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL);
> +
> + /* Are we advertising 10 duplex or 100 duplex ? */
> + duplex = !!(phy->regs[4] & ADVERTISE_100FULL);
> + duplex |= !!(phy->regs[4] & ADVERTISE_10FULL);
> + r = (speed_100 << 10) | (duplex << 11);
> + }
> + break;
> +
> + default:
> + r = phy->regs[regnum];
> + break;
> + }
> + D(printf("\n%s %x = reg[%d]\n", __func__, r, regnum));
> + return r;
> +}
> +
> +static void tdk_write(struct qemu_phy *phy, unsigned int req, unsigned int data)
> +{
> + int regnum;
> +
> + regnum = req & 0x1f;
> + D(printf("%s reg[%d] = %x\n", __func__, regnum, data));
> + switch (regnum) {
> + default:
> + phy->regs[regnum] = data;
> + break;
> + }
> +}
> +
> +void tdk_init(struct qemu_phy *phy)
> +{
> + phy->regs[0] = 0x3100;
> + /* PHY Id. */
> + phy->regs[2] = 0x0300;
> + phy->regs[3] = 0xe400;
> + /* Autonegotiation advertisement reg. */
> + phy->regs[4] = 0x01e1;
> + phy->link = 1;
> +
> + phy->read = tdk_read;
> + phy->write = tdk_write;
> +}
> +
> +void mdio_attach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr)
> +{
> + bus->devs[addr & 0x1f] = phy;
> +}
> +
> +#ifdef USE_THIS_DEAD_CODE
> +void mdio_detach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr)
> +{
> + bus->devs[addr & 0x1f] = NULL;
> +}
> +#endif
> +
> +void mdio_read_req(struct qemu_mdio *bus)
> +{
> + struct qemu_phy *phy;
> +
> + phy = bus->devs[bus->addr];
> + if (phy && phy->read) {
> + bus->data = phy->read(phy, bus->req);
> + } else {
> + bus->data = 0xffff;
> + }
> + D(qemu_log("%s addr=%d reg=%d data=%x\n", __func__,
> + bus->addr, bus->req, bus->data));
> +}
> +
> +void mdio_write_req(struct qemu_mdio *bus)
> +{
> + struct qemu_phy *phy;
> +
> + phy = bus->devs[bus->addr];
> + if (phy && phy->write) {
> + phy->write(phy, bus->req, bus->data);
> + }
> +}
> +
> +void mdio_cycle(struct qemu_mdio *bus)
> +{
> + bus->cnt++;
> +
> + D(printf("mdc=%d mdio=%d state=%d cnt=%d drv=%d\n",
> + bus->mdc, bus->mdio, bus->state, bus->cnt, bus->drive));
> + switch (bus->state) {
> + case PREAMBLE:
> + if (bus->mdc) {
> + if (bus->cnt >= (32 * 2) && !bus->mdio) {
> + bus->cnt = 0;
> + bus->state = SOF;
> + bus->data = 0;
> + }
> + }
> + break;
> + case SOF:
> + if (bus->mdc) {
> + if (bus->mdio != 1) {
> + printf("WARNING: no SOF\n");
> + }
> + if (bus->cnt == 1*2) {
> + bus->cnt = 0;
> + bus->opc = 0;
> + bus->state = OPC;
> + }
> + }
> + break;
> + case OPC:
> + if (bus->mdc) {
> + bus->opc <<= 1;
> + bus->opc |= bus->mdio & 1;
> + if (bus->cnt == 2*2) {
> + bus->cnt = 0;
> + bus->addr = 0;
> + bus->state = ADDR;
> + }
> + }
> + break;
> + case ADDR:
> + if (bus->mdc) {
> + bus->addr <<= 1;
> + bus->addr |= bus->mdio & 1;
> +
> + if (bus->cnt == 5*2) {
> + bus->cnt = 0;
> + bus->req = 0;
> + bus->state = REQ;
> + }
> + }
> + break;
> + case REQ:
> + if (bus->mdc) {
> + bus->req <<= 1;
> + bus->req |= bus->mdio & 1;
> + if (bus->cnt == 5*2) {
> + bus->cnt = 0;
> + bus->state = TURNAROUND;
> + }
> + }
> + break;
> + case TURNAROUND:
> + if (bus->mdc && bus->cnt == 2*2) {
> + bus->mdio = 0;
> + bus->cnt = 0;
> +
> + if (bus->opc == 2) {
> + bus->drive = 1;
> + mdio_read_req(bus);
> + bus->mdio = bus->data & 1;
> + }
> + bus->state = DATA;
> + }
> + break;
> + case DATA:
> + if (!bus->mdc) {
> + if (bus->drive) {
> + bus->mdio = !!(bus->data & (1 << 15));
> + bus->data <<= 1;
> + }
> + } else {
> + if (!bus->drive) {
> + bus->data <<= 1;
> + bus->data |= bus->mdio;
> + }
> + if (bus->cnt == 16 * 2) {
> + bus->cnt = 0;
> + bus->state = PREAMBLE;
> + if (!bus->drive) {
> + mdio_write_req(bus);
> + }
> + bus->drive = 0;
> + }
> + }
> + break;
> + default:
> + break;
> + }
> +}
> diff --git a/hw/bitbang_mdio.h b/hw/bitbang_mdio.h
> new file mode 100644
> index 0000000..3484aba
> --- /dev/null
> +++ b/hw/bitbang_mdio.h
> @@ -0,0 +1,72 @@
> +#ifndef BITBANG_MDIO_H
> +#define BITBANG_MDIO_H
> +
> +/*
> + * QEMU Bitbang Ethernet MDIO bus & PHY controllers.
> + *
> + * Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include <stdint.h>
> +
> +struct qemu_phy {
> + uint32_t regs[32];
> +
> + int link;
> +
> + unsigned int (*read)(struct qemu_phy *phy, unsigned int req);
> + void (*write)(struct qemu_phy *phy, unsigned int req, unsigned int data);
> +};
> +
> +struct qemu_mdio {
> + /* bus. */
> + int mdc;
> + int mdio;
> +
> + /* decoder. */
> + enum {
> + PREAMBLE,
> + SOF,
> + OPC,
> + ADDR,
> + REQ,
> + TURNAROUND,
> + DATA
> + } state;
> + unsigned int drive;
> +
> + unsigned int cnt;
> + unsigned int addr;
> + unsigned int opc;
> + unsigned int req;
> + unsigned int data;
> +
> + struct qemu_phy *devs[32];
> +};
> +
> +void tdk_init(struct qemu_phy *phy);
> +void mdio_attach(struct qemu_mdio *bus, struct qemu_phy *phy,
> + unsigned int addr);
> +void mdio_read_req(struct qemu_mdio *bus);
> +void mdio_write_req(struct qemu_mdio *bus);
> +void mdio_cycle(struct qemu_mdio *bus);
> +
> +#endif
> diff --git a/hw/cris/Makefile.objs b/hw/cris/Makefile.objs
> index aa9298a..86759a3 100644
> --- a/hw/cris/Makefile.objs
> +++ b/hw/cris/Makefile.objs
> @@ -9,5 +9,6 @@ obj-y += etraxfs_pic.o
> obj-y += etraxfs_eth.o
> obj-y += etraxfs_timer.o
> obj-y += etraxfs_ser.o
> +obj-y += bitbang_mdio.o
>
> obj-y := $(addprefix ../,$(obj-y))
> diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c
> index ec23fa6..67b4797 100644
> --- a/hw/etraxfs_eth.c
> +++ b/hw/etraxfs_eth.c
> @@ -26,281 +26,10 @@
> #include "sysbus.h"
> #include "net/net.h"
> #include "etraxfs.h"
> +#include "bitbang_mdio.h"
>
> #define D(x)
>
> -/* Advertisement control register. */
> -#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
> -#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
> -#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
> -#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
> -
> -/*
> - * The MDIO extensions in the TDK PHY model were reversed engineered from the
> - * linux driver (PHYID and Diagnostics reg).
> - * TODO: Add friendly names for the register nums.
> - */
> -struct qemu_phy
> -{
> - uint32_t regs[32];
> -
> - int link;
> -
> - unsigned int (*read)(struct qemu_phy *phy, unsigned int req);
> - void (*write)(struct qemu_phy *phy, unsigned int req,
> - unsigned int data);
> -};
> -
> -static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req)
> -{
> - int regnum;
> - unsigned r = 0;
> -
> - regnum = req & 0x1f;
> -
> - switch (regnum) {
> - case 1:
> - if (!phy->link)
> - break;
> - /* MR1. */
> - /* Speeds and modes. */
> - r |= (1 << 13) | (1 << 14);
> - r |= (1 << 11) | (1 << 12);
> - r |= (1 << 5); /* Autoneg complete. */
> - r |= (1 << 3); /* Autoneg able. */
> - r |= (1 << 2); /* link. */
> - break;
> - case 5:
> - /* Link partner ability.
> - We are kind; always agree with whatever best mode
> - the guest advertises. */
> - r = 1 << 14; /* Success. */
> - /* Copy advertised modes. */
> - r |= phy->regs[4] & (15 << 5);
> - /* Autoneg support. */
> - r |= 1;
> - break;
> - case 18:
> - {
> - /* Diagnostics reg. */
> - int duplex = 0;
> - int speed_100 = 0;
> -
> - if (!phy->link)
> - break;
> -
> - /* Are we advertising 100 half or 100 duplex ? */
> - speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF);
> - speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL);
> -
> - /* Are we advertising 10 duplex or 100 duplex ? */
> - duplex = !!(phy->regs[4] & ADVERTISE_100FULL);
> - duplex |= !!(phy->regs[4] & ADVERTISE_10FULL);
> - r = (speed_100 << 10) | (duplex << 11);
> - }
> - break;
> -
> - default:
> - r = phy->regs[regnum];
> - break;
> - }
> - D(printf("\n%s %x = reg[%d]\n", __func__, r, regnum));
> - return r;
> -}
> -
> -static void
> -tdk_write(struct qemu_phy *phy, unsigned int req, unsigned int data)
> -{
> - int regnum;
> -
> - regnum = req & 0x1f;
> - D(printf("%s reg[%d] = %x\n", __func__, regnum, data));
> - switch (regnum) {
> - default:
> - phy->regs[regnum] = data;
> - break;
> - }
> -}
> -
> -static void
> -tdk_init(struct qemu_phy *phy)
> -{
> - phy->regs[0] = 0x3100;
> - /* PHY Id. */
> - phy->regs[2] = 0x0300;
> - phy->regs[3] = 0xe400;
> - /* Autonegotiation advertisement reg. */
> - phy->regs[4] = 0x01E1;
> - phy->link = 1;
> -
> - phy->read = tdk_read;
> - phy->write = tdk_write;
> -}
> -
> -struct qemu_mdio
> -{
> - /* bus. */
> - int mdc;
> - int mdio;
> -
> - /* decoder. */
> - enum {
> - PREAMBLE,
> - SOF,
> - OPC,
> - ADDR,
> - REQ,
> - TURNAROUND,
> - DATA
> - } state;
> - unsigned int drive;
> -
> - unsigned int cnt;
> - unsigned int addr;
> - unsigned int opc;
> - unsigned int req;
> - unsigned int data;
> -
> - struct qemu_phy *devs[32];
> -};
> -
> -static void
> -mdio_attach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr)
> -{
> - bus->devs[addr & 0x1f] = phy;
> -}
> -
> -#ifdef USE_THIS_DEAD_CODE
> -static void
> -mdio_detach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr)
> -{
> - bus->devs[addr & 0x1f] = NULL;
> -}
> -#endif
> -
> -static void mdio_read_req(struct qemu_mdio *bus)
> -{
> - struct qemu_phy *phy;
> -
> - phy = bus->devs[bus->addr];
> - if (phy && phy->read)
> - bus->data = phy->read(phy, bus->req);
> - else
> - bus->data = 0xffff;
> -}
> -
> -static void mdio_write_req(struct qemu_mdio *bus)
> -{
> - struct qemu_phy *phy;
> -
> - phy = bus->devs[bus->addr];
> - if (phy && phy->write)
> - phy->write(phy, bus->req, bus->data);
> -}
> -
> -static void mdio_cycle(struct qemu_mdio *bus)
> -{
> - bus->cnt++;
> -
> - D(printf("mdc=%d mdio=%d state=%d cnt=%d drv=%d\n",
> - bus->mdc, bus->mdio, bus->state, bus->cnt, bus->drive));
> -#if 0
> - if (bus->mdc)
> - printf("%d", bus->mdio);
> -#endif
> - switch (bus->state)
> - {
> - case PREAMBLE:
> - if (bus->mdc) {
> - if (bus->cnt >= (32 * 2) && !bus->mdio) {
> - bus->cnt = 0;
> - bus->state = SOF;
> - bus->data = 0;
> - }
> - }
> - break;
> - case SOF:
> - if (bus->mdc) {
> - if (bus->mdio != 1)
> - printf("WARNING: no SOF\n");
> - if (bus->cnt == 1*2) {
> - bus->cnt = 0;
> - bus->opc = 0;
> - bus->state = OPC;
> - }
> - }
> - break;
> - case OPC:
> - if (bus->mdc) {
> - bus->opc <<= 1;
> - bus->opc |= bus->mdio & 1;
> - if (bus->cnt == 2*2) {
> - bus->cnt = 0;
> - bus->addr = 0;
> - bus->state = ADDR;
> - }
> - }
> - break;
> - case ADDR:
> - if (bus->mdc) {
> - bus->addr <<= 1;
> - bus->addr |= bus->mdio & 1;
> -
> - if (bus->cnt == 5*2) {
> - bus->cnt = 0;
> - bus->req = 0;
> - bus->state = REQ;
> - }
> - }
> - break;
> - case REQ:
> - if (bus->mdc) {
> - bus->req <<= 1;
> - bus->req |= bus->mdio & 1;
> - if (bus->cnt == 5*2) {
> - bus->cnt = 0;
> - bus->state = TURNAROUND;
> - }
> - }
> - break;
> - case TURNAROUND:
> - if (bus->mdc && bus->cnt == 2*2) {
> - bus->mdio = 0;
> - bus->cnt = 0;
> -
> - if (bus->opc == 2) {
> - bus->drive = 1;
> - mdio_read_req(bus);
> - bus->mdio = bus->data & 1;
> - }
> - bus->state = DATA;
> - }
> - break;
> - case DATA:
> - if (!bus->mdc) {
> - if (bus->drive) {
> - bus->mdio = !!(bus->data & (1 << 15));
> - bus->data <<= 1;
> - }
> - } else {
> - if (!bus->drive) {
> - bus->data <<= 1;
> - bus->data |= bus->mdio;
> - }
> - if (bus->cnt == 16 * 2) {
> - bus->cnt = 0;
> - bus->state = PREAMBLE;
> - if (!bus->drive)
> - mdio_write_req(bus);
> - bus->drive = 0;
> - }
> - }
> - break;
> - default:
> - break;
> - }
> -}
> -
> /* ETRAX-FS Ethernet MAC block starts here. */
>
> #define RW_MA0_LO 0x00
> --
> 1.7.10.4
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH 3/3] net/bitbang_mdio: Use bitbang core for smc91c111 network device
2013-01-20 11:29 ` Peter Maydell
@ 2013-01-21 13:12 ` Grant Likely
0 siblings, 0 replies; 9+ messages in thread
From: Grant Likely @ 2013-01-21 13:12 UTC (permalink / raw)
To: Peter Maydell; +Cc: Edgar E. Iglesias, Anthony Liguori, qemu-devel, Paul Brook
On Sun, 20 Jan 2013 11:29:32 +0000, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 19 January 2013 22:28, Grant Likely <grant.likely@secretlab.ca> wrote:
> > The smc91c111 device has bitbanged MDIO access, but the model doesn't
> > yet implement it. This patch uses the generalized bitbang MDIO support
> > pulled out of etraxfs Ethernet driver.
>
> > @@ -44,6 +45,13 @@ typedef struct {
> > uint8_t int_level;
> > uint8_t int_mask;
> > MemoryRegion mmio;
> > +
> > + /* MDIO bus. */
> > + struct qemu_mdio mdio_bus;
> > + unsigned int phyaddr;
> > +
> > + /* PHY. */
> > + struct qemu_phy phy;
> > } smc91c111_state;
>
> This surely needs VMState additions so the extra state can be passed
> across migrations. It looks like the MDIO/PHY stuff from the etraxfs code
> doesn't have any kind of state save/restore support, so you probably need
> to first implement that in your new mdio/phy source file, and then refer
> to it here.
Ah, I see. I missed that. I will figure out how to do that and add it to
the next version.
g.
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2013-01-21 13:12 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-01-19 22:28 [Qemu-devel] [PATCH 0/3] Generalize bitbang MDIO and use for versatile-pb Grant Likely
2013-01-19 22:28 ` [Qemu-devel] [PATCH 1/3] net/bitbang_mdio: Generalize etraxfs MDIO bitbanging emulation Grant Likely
2013-01-20 17:29 ` Andreas Färber
2013-01-21 12:51 ` Edgar E. Iglesias
2013-01-19 22:28 ` [Qemu-devel] [PATCH 2/3] net/bitbang_mdio: Never set PHY RST and ANEG_RST bits on register write Grant Likely
2013-01-19 22:28 ` [Qemu-devel] [PATCH 3/3] net/bitbang_mdio: Use bitbang core for smc91c111 network device Grant Likely
2013-01-20 11:29 ` Peter Maydell
2013-01-21 13:12 ` Grant Likely
2013-01-20 17:26 ` [Qemu-devel] [PATCH 0/3] Generalize bitbang MDIO and use for versatile-pb Andreas Färber
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).