Subject: SiS 900 revision 635+ support
To: None <tech-kern@netbsd.org>
From: Joerg Sonnenberger <joerg@britannica.bec.de>
List: tech-kern
Date: 08/13/2003 17:47:14
--GvXjxJ+pjyke8COw
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Hi all,
this is a cleaned version of the patch I sent to current-users@
sometime ago. I didn't recieve any feedback, but I hope this can
be commited.
The patch adds the support for the MII on newer SiS900 revisions.
It has been ported from FreeBSD/OpenBSD. You need this patch if
your SiS chip is detected but no PHY on it.
Regards, Joerg
--GvXjxJ+pjyke8COw
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="if_sip.c.diff"
--- if_sip.c.orig 2003-03-23 01:56:15.000000000 +0100
+++ if_sip.c 2003-08-13 00:22:31.000000000 +0200
@@ -439,6 +439,9 @@
void SIP_DECL(dp83820_mii_writereg)(struct device *, int, int, int);
void SIP_DECL(dp83820_mii_statchg)(struct device *);
#else
+static void sis900_mii_sync(struct sip_softc *);
+static void sis900_mii_send(struct sip_softc *, u_int32_t, int);
+
int SIP_DECL(sis900_mii_readreg)(struct device *, int, int);
void SIP_DECL(sis900_mii_writereg)(struct device *, int, int, int);
void SIP_DECL(sis900_mii_statchg)(struct device *);
@@ -3042,11 +3045,53 @@
bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_EROMAR, val);
}
#else /* ! DP83820 */
+
+#define SIO_SET(x) bus_space_write_4(sc->sc_st,sc->sc_sh,SIS_EECTL, \
+ bus_space_read_4(sc->sc_st,sc->sc_sh,SIS_EECTL) | (x))
+#define SIO_CLR(x) bus_space_write_4(sc->sc_st,sc->sc_sh,SIS_EECTL, \
+ bus_space_read_4(sc->sc_st,sc->sc_sh,SIS_EECTL) & ~(x))
+
+static void
+sis900_mii_sync(struct sip_softc *sc)
+{
+ int i;
+
+ SIO_SET(SIS_MII_DIR|SIS_MII_DATA);
+
+ for (i = 0; i < 32; i++) {
+ SIO_SET(SIS_MII_CLK);
+ DELAY(1);
+ SIO_CLR(SIS_MII_CLK);
+ DELAY(1);
+ }
+}
+
+static void
+sis900_mii_send(struct sip_softc *sc, u_int32_t bits, int cnt)
+{
+ int i;
+
+ SIO_CLR(SIS_MII_CLK);
+
+ for (i = (0x1 << (cnt -1)); i; i >>= 1) {
+ if (bits & i) {
+ SIO_SET(SIS_MII_DATA);
+ } else {
+ SIO_CLR(SIS_MII_DATA);
+ }
+ DELAY(1);
+ SIO_CLR(SIS_MII_CLK);
+ DELAY(1);
+ SIO_SET(SIS_MII_CLK);
+ }
+}
+
/*
* sip_sis900_mii_readreg: [mii interface function]
*
* Read a PHY register on the MII.
*/
+
int
SIP_DECL(sis900_mii_readreg)(struct device *self, int phy, int reg)
{
@@ -3054,8 +3099,75 @@
u_int32_t enphy;
/*
- * The SiS 900 has only an internal PHY on the MII. Only allow
- * MII address 0.
+ * The SiS 900 revision 635 and later uses a different interface.
+ */
+ if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900 &&
+ sc->sc_rev >= SIS_REV_635) {
+ int i, ack, s;
+ u_int16_t mii_data = 0;
+
+ s = splnet();
+
+ /* Turn on data xmit. */
+ SIO_SET(SIS_MII_DIR);
+ sis900_mii_sync(sc);
+
+ /* Send command/address info */
+ sis900_mii_send(sc,SIS_MII_STARTDELIM,2);
+ sis900_mii_send(sc,SIS_MII_READOP,2);
+ sis900_mii_send(sc,phy,5);
+ sis900_mii_send(sc,reg,5);
+
+ /* Idle bit */
+ SIO_CLR(SIS_MII_CLK|SIS_MII_DATA);
+ DELAY(1);
+ SIO_SET(SIS_MII_CLK);
+ DELAY(1);
+
+ /* Turn off xmit. */
+ SIO_CLR(SIS_MII_DIR);
+
+ /* Check for ack */
+ SIO_CLR(SIS_MII_CLK);
+ DELAY(1);
+ ack = bus_space_read_4(sc->sc_st,sc->sc_sh,SIS_EECTL) & SIS_MII_DATA;
+ SIO_SET(SIS_MII_CLK);
+ DELAY(1);
+
+ /*
+ * Now try reading data bits. If the ack failed, we still
+ * need to clock through 16 cycles to keep the PHY(s) in sync.
+ */
+ if (ack) {
+ for(i = 0; i < 16; i++) {
+ SIO_CLR(SIS_MII_CLK);
+ DELAY(1);
+ SIO_SET(SIS_MII_CLK);
+ DELAY(1);
+ }
+ } else {
+ for (i = 0x8000; i; i >>= 1) {
+ SIO_CLR(SIS_MII_CLK);
+ DELAY(1);
+ if (bus_space_read_4(sc->sc_st,sc->sc_sh,SIS_EECTL) & SIS_MII_DATA)
+ mii_data |= i;
+ SIO_SET(SIS_MII_CLK);
+ DELAY(1);
+ }
+ }
+
+ SIO_CLR(SIS_MII_CLK);
+ DELAY(1);
+ SIO_SET(SIS_MII_CLK);
+ DELAY(1);
+
+ splx(s);
+ return mii_data;
+ }
+
+ /*
+ * The SiS 900 before revision 635 has only an internal PHY
+ * on the MII. Only allow MII address 0.
*/
if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900 &&
sc->sc_rev < SIS_REV_635 && phy != 0)
@@ -3082,8 +3194,39 @@
u_int32_t enphy;
/*
- * The SiS 900 has only an internal PHY on the MII. Only allow
- * MII address 0.
+ * The SiS 900 revision 635 and later uses a different interface.
+ */
+ if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900 &&
+ sc->sc_rev >= SIS_REV_635 && phy != 0) {
+ int s;
+
+ s = splnet();
+
+ /* Turn on data output. */
+ SIO_SET(SIS_MII_DIR);
+ sis900_mii_sync(sc);
+ sis900_mii_send(sc,SIS_MII_STARTDELIM,2);
+ sis900_mii_send(sc,SIS_MII_WRITEOP,2);
+ sis900_mii_send(sc,phy,5);
+ sis900_mii_send(sc,reg,5);
+ sis900_mii_send(sc,SIS_MII_TURNAROUND,2);
+ sis900_mii_send(sc,val,16);
+
+ /* Idle bit. */
+ SIO_SET(SIS_MII_CLK);
+ DELAY(1);
+ SIO_CLR(SIS_MII_CLK);
+ DELAY(1);
+
+ /* Turn off xmit. */
+ SIO_CLR(SIS_MII_DIR);
+
+ splx(s);
+ }
+
+ /*
+ * The SiS 900 before revision 635 has only an internal PHY
+ * on the MII. Only allow MII address 0.
*/
if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900 &&
sc->sc_rev < SIS_REV_635 && phy != 0)
--GvXjxJ+pjyke8COw
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="if_sipreg.h.diff"
--- if_sipreg.h.orig 2002-06-30 20:04:12.000000000 +0200
+++ if_sipreg.h 2003-08-13 00:13:35.000000000 +0200
@@ -596,6 +596,17 @@
#ifndef DP83820
#define SIP_NS_PHY(miireg) /* PHY registers (83815) */ \
(0x80 + ((miireg) << 2))
+
+#define SIS_EECTL 0x08
+
+#define SIS_MII_CLK 0x00000040
+#define SIS_MII_DIR 0x00000020
+#define SIS_MII_DATA 0x00000010
+
+#define SIS_MII_STARTDELIM 0x01
+#define SIS_MII_READOP 0x02
+#define SIS_MII_WRITEOP 0x01
+#define SIS_MII_TURNAROUND 0x02
#endif
#ifdef DP83820
--GvXjxJ+pjyke8COw--