FSG3 phy attempt
Bruce M. Simpson
bms at incunabulum.net
Sat Oct 11 12:10:33 UTC 2008
Hi,
Here's a diff containing all my work on attempting to get the PHY up on
the FSG3.
It is unsuccessful but might be a starting point for someone else.
I can forward my last mail to Pyun about it if that helps.
thanks
BMS
-------------- next part --------------
Index: dev/mii/rlswitch.c
===================================================================
--- dev/mii/rlswitch.c (revision 183760)
+++ dev/mii/rlswitch.c (working copy)
@@ -59,7 +59,8 @@
#include "miibus_if.h"
//#define RL_DEBUG
-#define RL_VLAN
+//#define RL_VLAN
+//#define RL_IS_RTL8305SB
static int rlswitch_probe(device_t);
static int rlswitch_attach(device_t);
@@ -119,6 +120,7 @@
sc->mii_dev = device_get_parent(dev);
mii = device_get_softc(sc->mii_dev);
+#if 1
/*
* We handle all pseudo PHY in a single instance, so never allow
* non-zero * instances!
@@ -127,6 +129,7 @@
device_printf(dev, "ignoring this PHY, non-zero instance\n");
return (ENXIO);
}
+#endif
LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
@@ -359,9 +362,11 @@
MIIBUS_WRITEREG(sc->mii_dev, 4, 25, val);
#endif
+#if 0
#ifdef RL_DEBUG
rlswitch_phydump(dev);
#endif
+#endif
MIIBUS_MEDIAINIT(sc->mii_dev);
return (0);
}
Index: dev/iicbus/x1226rtc.c
===================================================================
--- dev/iicbus/x1226rtc.c (revision 0)
+++ dev/iicbus/x1226rtc.c (revision 0)
@@ -0,0 +1,223 @@
+/*-
+ * Copyright (c) 2008 Bruce M. Simpson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Intersil/Xicor X1226 RTC on I2C "2-wire" bus.
+ *
+ * Note: The Linksys NSLU2 actually has an X1205 on the board.
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/clock.h>
+#include <sys/time.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+
+#include <dev/iicbus/iiconf.h>
+
+#include "iicbus_if.h"
+#include "clock_if.h"
+
+#ifndef IIC_M_WR
+#define IIC_M_WR 0 /* write operation */
+#endif
+
+#define X1226_ADDR 0x6f /* slave address */
+
+#define X1226_RTC_SIZE 8 /* size of BCD register space */
+#define X1226_SC 0x30 /* base of date registers */
+#define X1226_HR 0x32 /* hours */
+#define X1226_HR_PM 0x20 /* HR: time is PM */
+#define X1226_HR_MIL 0x80 /* HR: time is in 24 hour format */
+#define X1226_SR 0x3f /* status register */
+#define X1226_SR_WEL 0x02 /* SR: write enable latch */
+#define X1226_SR_RWEL 0x04 /* SR: register write enable latch */
+
+#define MAX_IIC_DATA_SIZE 7
+
+struct x1226rtc_softc {
+ device_t sc_dev;
+};
+
+static int
+x1226rtc_probe(device_t dev)
+{
+
+ /* XXX really probe? */
+ device_set_desc(dev, "Intersil/Xicor X1226 RTC");
+ return (0);
+}
+
+static int
+x1226rtc_attach(device_t dev)
+{
+ struct x1226rtc_softc *sc = device_get_softc(dev);
+
+ sc->sc_dev = dev;
+
+ clock_register(dev, 1000);
+ return (0);
+}
+
+static int
+x1226rtc_read(device_t dev, uint8_t address, uint8_t *data, uint8_t size)
+{
+ struct iic_msg msg[] = {
+ { X1226_ADDR, IIC_M_WR, 1, &address },
+ { X1226_ADDR, IIC_M_RD, size, data },
+ };
+
+ return (iicbus_transfer(dev, msg, 2));
+}
+
+static int
+x1226rtc_write(device_t dev, uint8_t address, uint8_t *data, uint8_t size)
+{
+ uint8_t buffer[MAX_IIC_DATA_SIZE + 1];
+ struct iic_msg msg[] = {
+ { X1226_ADDR, IIC_M_WR, size + 1, buffer },
+ };
+
+ if (size > MAX_IIC_DATA_SIZE)
+ return (ENOMEM);
+
+ buffer[0] = address;
+ memcpy(buffer + 1, data, size);
+
+ return (iicbus_transfer(dev, msg, 1));
+}
+
+static uint8_t
+x1226rtc_get_hours(uint8_t val)
+{
+ uint8_t ret;
+
+ if ((val & X1226_HR_MIL) != 0)
+ ret = FROMBCD(val & 0x3f);
+ else if ((val & X1226_HR_PM) != 0)
+ ret = FROMBCD(val & 0x1f);
+ else
+ ret = FROMBCD(val & 0x1f) + 12;
+
+ return (ret);
+}
+
+static int
+x1226rtc_gettime(device_t dev, struct timespec *ts)
+{
+ uint8_t date[X1226_RTC_SIZE];
+ struct clocktime ct;
+ int error;
+
+ error = x1226rtc_read(dev, X1226_SC, date, X1226_RTC_SIZE);
+ if (error == 0) {
+ ct.nsec = 0;
+ ct.sec = FROMBCD(date[0] & 0x7f); /* SC */
+ ct.min = FROMBCD(date[1] & 0x7f); /* MN */
+ ct.hour = x1226rtc_get_hours(date[2]); /* HR */
+ ct.day = FROMBCD(date[3] & 0x3f); /* DT */
+ ct.mon = FROMBCD(date[4] & 0x1f); /* MO */
+ ct.year = FROMBCD(date[5]); /* YR */
+ ct.dow = FROMBCD(date[6] & 0x07) - 1; /* DW */
+ ct.year += (FROMBCD(date[7]) & 0x39) * 100; /* Y2K */
+
+ error = clock_ct_to_ts(&ct, ts);
+ if (error) {
+ device_printf(dev, "error %d converting to timespec\n",
+ error);
+ }
+ } else {
+ device_printf(dev, "error %d reading SRAM\n", error);
+ }
+
+ return (error);
+}
+
+static int
+x1226rtc_settime(device_t dev, struct timespec *ts)
+{
+ uint8_t date[X1226_RTC_SIZE];
+ uint8_t sr;
+ struct clocktime ct;
+ int error;
+
+ clock_ts_to_ct(ts, &ct);
+
+ date[0] = TOBCD(ct.sec);
+ date[1] = TOBCD(ct.min);
+ date[2] = TOBCD(ct.hour) | X1226_HR_MIL;
+ date[3] = TOBCD(ct.day);
+ date[4] = TOBCD(ct.mon);
+ date[5] = TOBCD(ct.year % 100);
+ date[6] = TOBCD(ct.dow);
+ date[7] = TOBCD(ct.year / 100);
+
+ sr = X1226_SR_WEL;
+ error = x1226rtc_write(dev, X1226_SR, &sr, 1);
+ if (error) {
+ device_printf(dev, "failed to set %s bit\n", "WEL");
+ return (EIO);
+ }
+
+ sr = X1226_SR_WEL | X1226_SR_WEL;
+ error = x1226rtc_write(dev, X1226_SR, &sr, 1);
+ if (error) {
+ device_printf(dev, "failed to set %s bit\n", "RWEL");
+ return (EIO);
+ }
+
+ error = x1226rtc_write(dev, X1226_SC, date, X1226_RTC_SIZE);
+ if (error)
+ device_printf(dev, "error %d writing to SRAM\n", error);
+
+ return (error);
+}
+
+static device_method_t x1226rtc_methods[] = {
+ DEVMETHOD(device_probe, x1226rtc_probe),
+ DEVMETHOD(device_attach, x1226rtc_attach),
+
+ DEVMETHOD(clock_gettime, x1226rtc_gettime),
+ DEVMETHOD(clock_settime, x1226rtc_settime),
+
+ {0, 0},
+};
+
+static driver_t x1226rtc_driver = {
+ "x1226rtc",
+ x1226rtc_methods,
+ sizeof(struct x1226rtc_softc),
+};
+static devclass_t x1226rtc_devclass;
+
+DRIVER_MODULE(x1226rtc, iicbus, x1226rtc_driver, x1226rtc_devclass, 0, 0);
+MODULE_VERSION(x1226rtc, 1);
+MODULE_DEPEND(x1226rtc, iicbus, 1, 1, 1);
Index: arm/xscale/ixp425/if_npe.c
===================================================================
--- arm/xscale/ixp425/if_npe.c (revision 183760)
+++ arm/xscale/ixp425/if_npe.c (working copy)
@@ -83,6 +83,8 @@
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
+#include "miidevs.h"
+
#include <arm/xscale/ixp425/if_npereg.h>
#include "miibus_if.h"
@@ -140,6 +142,9 @@
struct npestats *sc_stats;
bus_dmamap_t sc_stats_map;
bus_addr_t sc_stats_phys; /* phys addr of sc_stats */
+ int sc_force_bmsr;
+ int sc_force_idr1;
+ int sc_force_idr2;
};
/*
@@ -244,6 +249,8 @@
static uint32_t npe_getimageid(struct npe_softc *);
static int npe_setloopback(struct npe_softc *, int ena);
#endif
+static int npe_miibus_readreg(device_t dev, int phy, int reg);
+static void npe_miibus_writereg(device_t dev, int phy, int reg, int data);
/* NB: all tx done processing goes through one queue */
static int tx_doneqid = -1;
@@ -733,10 +740,45 @@
if (!override_unit(dev, "phy", &sc->sc_phy, 0, MII_NPHY-1))
sc->sc_phy = npeconfig[unit].phy;
+ /*
+ * Allow PHY OUI/model and BMSR to be forced, as some boards have
+ * a PHY which does not have ID registers (e.g. the RTL8305SB
+ * on a Freecom FSG3).
+ */
+ if (!override_unit(dev, "force_bmsr", &sc->sc_force_bmsr, 0, 0xFFFF))
+ sc->sc_force_bmsr = 0;
+ if (!override_unit(dev, "force_idr1", &sc->sc_force_idr1, 0, 0xFFFF))
+ sc->sc_force_idr1 = 0;
+ if (!override_unit(dev, "force_idr2", &sc->sc_force_idr2, 0, 0xFFFF))
+ sc->sc_force_idr2 = 0;
+
KASSERT(npes[npeconfig[unit].npeid] == NULL,
("npe %u already setup", npeconfig[unit].npeid));
npes[npeconfig[unit].npeid] = sc;
+#if 0
+ /*
+ * Attempt to soft-reset the RTL8305SB.
+ */
+ if ((MII_OUI(sc->sc_force_idr1, sc->sc_force_idr2) ==
+ MII_OUI_xxREALTEK) &&
+ (MII_MODEL(sc->sc_force_idr2) == MII_MODEL_xxREALTEK_RTL8305SC) &&
+ (MII_REV(sc->sc_force_idr2) == 0x01)) {
+ int i;
+
+ device_printf(sc->sc_dev,
+ "attempting to soft-reset RTL8305SB\n");
+ npe_miibus_writereg(sc->sc_dev, 3, 0x16, 0x8000);
+ for (i = 0; i <= 4; i++) {
+ npe_miibus_writereg(sc->sc_dev, i, 0x0, 0x8000);
+ // restart autoneg, clear powerdown bit
+ npe_miibus_writereg(sc->sc_dev, i, 0x0, 0x0020);
+ }
+ // disable loopback, enable all ports.
+ npe_miibus_writereg(sc->sc_dev, 3, 0x16, 0x03FF);
+ }
+#endif
+
return 0;
}
@@ -1598,6 +1640,20 @@
if (phy != sc->sc_phy) /* XXX no auto-detect */
return 0xffff;
+
+ if (reg == MII_BMSR && sc->sc_force_bmsr != 0x0000)
+ return (sc->sc_force_bmsr);
+ if (reg == MII_PHYIDR1 && sc->sc_force_idr1 != 0x0000)
+ return (sc->sc_force_idr1);
+ if (reg == MII_PHYIDR2 && sc->sc_force_idr2 != 0x0000)
+ return (sc->sc_force_idr2);
+
+#if 1
+ /* Do NOT allow PHY 5 to be read. */
+ if (sc->sc_force_bmsr != 0x0000 && phy == 5)
+ return (0xffff);
+#endif
+
v = (phy << NPE_MII_ADDR_SHL) | (reg << NPE_MII_REG_SHL)
| NPE_MII_GO;
npe_mii_mdio_write(sc, NPE_MAC_MDIO_CMD, v);
@@ -1605,6 +1661,7 @@
v = npe_mii_mdio_read(sc, NPE_MAC_MDIO_STS);
else
v = 0xffff | NPE_MII_READ_FAIL;
+
return (v & NPE_MII_READ_FAIL) ? 0xffff : (v & 0xffff);
#undef MAXTRIES
}
@@ -1617,6 +1674,13 @@
if (phy != sc->sc_phy) /* XXX */
return;
+
+#if 1
+ /* Do NOT allow PHY 5 to be written. */
+ if (sc->sc_force_bmsr != 0x0000 && phy == 5)
+ return;
+#endif
+
v = (phy << NPE_MII_ADDR_SHL) | (reg << NPE_MII_REG_SHL)
| data | NPE_MII_WRITE
| NPE_MII_GO;
Index: arm/xscale/ixp425/avila_machdep.c
===================================================================
--- arm/xscale/ixp425/avila_machdep.c (revision 183760)
+++ arm/xscale/ixp425/avila_machdep.c (working copy)
@@ -259,6 +259,7 @@
vm_offset_t freemem_after;
vm_offset_t lastaddr;
uint32_t memsize;
+ char *p;
set_cpufuncs();
lastaddr = fake_preload_metadata();
@@ -475,16 +476,29 @@
phys_avail[i++] = trunc_page(0x10000000 + memsize - 1);
phys_avail[i++] = 0;
phys_avail[i] = 0;
-
+
+ /* use static kernel environment if so configured */
+ if (envmode == 1)
+ kern_envp = static_env;
+
+ /*
+ * Catch case of boot_verbose set in environment.
+ */
+ if ((p = getenv("boot_verbose")) != NULL) {
+ if (strcmp(p, "yes") == 0 || strcmp(p, "YES") == 0) {
+ boothowto |= RB_VERBOSE;
+ }
+ freeenv(p);
+ }
+
+ if (boothowto & RB_VERBOSE)
+ bootverbose = 1;
+
/* Do basic tuning, hz etc */
init_param1();
init_param2(physmem);
kdb_init();
- /* use static kernel environment if so configured */
- if (envmode == 1)
- kern_envp = static_env;
-
return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP -
sizeof(struct pcb)));
}
Index: arm/conf/FSG3.hints
===================================================================
--- arm/conf/FSG3.hints (revision 0)
+++ arm/conf/FSG3.hints (revision 0)
@@ -0,0 +1,49 @@
+# $FreeBSD$
+
+#
+# Device wiring for the Freecom FSG3
+#
+
+# DBGU is unit 0
+hint.uart.0.at="ixp0"
+hint.uart.0.addr=0xc8000000
+hint.uart.0.irq=15
+hint.uart.0.flags=0x10
+# USART0 is unit 1
+hint.uart.1.at="ixp0"
+hint.uart.1.addr=0xc8001000
+hint.uart.1.irq=13
+
+# NPE Hardware Queue Manager
+hint.ixpqmgr.0.at="ixp0"
+
+# NPE NIC's, requires ixpqmgr
+hint.npe.0.at="ixp0"
+hint.npe.0.mac="A"
+hint.npe.0.mii="A"
+hint.npe.0.phy=5
+# XXX BMSR for PHY 5 must always be forced.
+# XXX Don't use the rlswitch shared driver
+# for this side of the switch; use a different OUI.
+hint.npe.0.force_bmsr=0x402C
+hint.npe.0.force_idr1=0x000C
+hint.npe.0.force_idr2=0xC851
+
+hint.npe.1.at="ixp0"
+hint.npe.1.mac="B"
+hint.npe.1.mii="A"
+hint.npe.1.phy=4
+# Realtek RTL8305SB (Rev 1)
+# XXX BMSR must always be forced -- RTL8305SB has no ID registers.
+hint.npe.1.force_bmsr=0x4024
+hint.npe.1.force_idr1=0x001C
+hint.npe.1.force_idr2=0xC851
+
+# RTC
+hint.x1226rtc.0.at="iicbus0"
+hint.x1226rtc.0.addr=0x6f
+
+#not yet
+# Slug LED
+# Slug button
+# Slug Buzzer
Index: arm/conf/FSG3.env
===================================================================
--- arm/conf/FSG3.env (revision 0)
+++ arm/conf/FSG3.env (revision 0)
@@ -0,0 +1 @@
+boot_verbose=YES
Index: arm/conf/FSG3
===================================================================
--- arm/conf/FSG3 (revision 0)
+++ arm/conf/FSG3 (revision 0)
@@ -0,0 +1,153 @@
+# NSLU - kernel configuration file for FreeBSD/arm on Linksys NSLU2
+#
+
+machine arm
+ident FSG3
+
+options PHYSADDR=0x10000000
+options KERNPHYSADDR=0x10200000
+options KERNVIRTADDR=0xc0200000 # Used in ldscript.arm
+options FLASHADDR=0x50000000
+options LOADERRAMADDR=0x00000000
+options STARTUP_PAGETABLE_ADDR=0x10000000
+
+# XXX 0x0 is not free in NSLU2 loader, but it *might* be free
+# in the U-Boot loader.
+# Allow 4MB (XXX) for kernel image.
+# XXX Changing this appears to bloat the tramp, why?
+#options FLASHADDR=0x01d00000
+#options LOADERRAMADDR=0x01d00000
+
+include "../xscale/ixp425/std.avila"
+#To statically compile in device wiring instead of /boot/device.hints
+hints "FSG3.hints" #Default places to look for devices.
+
+# For some reason the kernel ain't bootp-ing.
+#env "FSG3.env" # XXX set mountroot
+
+# XXX need tramp w/o symbols for <1MB
+#makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols
+makeoptions DEBUG=-g3 #Build kernel with gdb(1) debug symbols
+
+makeoptions CONF_CFLAGS=-mcpu=xscale
+options HZ=100
+options DEVICE_POLLING
+
+# XXX
+options VERBOSE_SYSINIT
+
+# Debugging for use in -current
+options KDB
+options GDB
+options DDB #Enable the kernel debugger
+
+options ALT_BREAK_TO_DEBUGGER
+
+#options INVARIANTS #Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS #Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+options SCHED_ULE #ULE scheduler
+options INET #InterNETworking
+#options INET6 #IPv6 communications protocols
+options FFS #Berkeley Fast Filesystem
+options SOFTUPDATES #Enable FFS soft updates support
+options UFS_ACL #Support for access control lists
+options UFS_DIRHASH #Improve performance on big directories
+#options NFSCLIENT #Network Filesystem Client
+#options NFSSERVER #Network Filesystem Server
+#options NFSLOCKD #Network Lock Manager
+#options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+#options MSDOSFS #MSDOS Filesystem
+#options CD9660 #ISO 9660 Filesystem
+#options PROCFS #Process filesystem (requires PSEUDOFS)
+options PSEUDOFS #Pseudo-filesystem framework
+options SCSI_DELAY=5000 #Delay (in ms) before probing SCSI
+options KTRACE #ktrace(1) support
+options SYSVSHM #SYSV-style shared memory
+options SYSVMSG #SYSV-style message queues
+options SYSVSEM #SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
+
+options MUTEX_NOINLINE #Mutex inlines are space hogs
+options RWLOCK_NOINLINE #rwlock inlines are space hogs
+options SX_NOINLINE #sx inliens are space hogs
+
+# XXX Until we can get disk drivers to attach above,
+# we will need to attempt network boot.
+options BOOTP
+options BOOTP_NFSROOT
+options BOOTP_NFSV3
+options BOOTP_WIRED_TO=npe0
+options BOOTP_COMPAT
+
+options NFSCLIENT #Network Filesystem Client
+options NFSLOCKD #Network Lock Manager
+options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+
+#options GEOM_MBR
+#options GEOM_PART_MBR
+
+device mem # Memory and kernel memory devices
+device pci
+device uart
+
+# I2C Bus
+device iicbus
+device iicbb
+device iic
+
+device ixpiic # I2C bus glue
+device ixpwdog # watchdog timer
+
+device x1226rtc # I2C real-time clock
+
+####### netwerk
+
+device npe # Network Processing Engine
+device npe_fw
+device firmware
+device qmgr # Q Manager (required by npe)
+
+# XXX There is an RTL8305SB with 5 physical ports. Two are configured
+# as miibus PHYs, however the SB rev does NOT have ID registers, and
+# attempting to probe the BMSR seems to cause problems with the PHY.
+#
+# The rlswitch driver is written for the RTL8305SC, which is a totally
+# different chip -- the vlan register setup is not the same.
+#
+# ukphy is part of mii, we use that for the first port, but reject any
+# attempts to read or write PHY ID 5 (npe0).
+#
+device mii
+device rlswitch
+
+device ether
+device bpf
+
+device pty
+device loop
+
+options XSCALE_CACHE_READ_WRITE_ALLOCATE
+device md # XXX .ko candidate?
+device random # Entropy device
+
+#options ARM_USE_SMALL_ALLOC
+
+# XXX only needed for bootstrap rootfs from usb
+#device usb
+#options USB_DEBUG # XXX not needed <1MB?
+#device ohci
+#device ehci
+#device umass
+#device scbus # SCSI bus (required for SCSI)
+#device da # Direct Access (disks)
+
+# XXX PCI devices have not yet been configured, so
+# the kernel never sees the onboard VIA VT6421A.
+#device atacore
+#device atapci
+#device atavia
+#device atadisk
More information about the freebsd-embedded
mailing list