LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [Patch] Full Duplex DM9161 MII support on MPC8272ADS
@ 2004-12-15 13:31 alebas
  0 siblings, 0 replies; only message in thread
From: alebas @ 2004-12-15 13:31 UTC (permalink / raw)
  To: linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 522 bytes --]


Hi,

This patch tries to add MII support for the DM9161 PHY
used in the mpc8272ads boards. I have literally copied
this from the driver in kernel 2.4

I have also included modifications nedded to support
both PHYs on the board (as done in kernel 2.4).

Two more minor changes are also in the patch
 - PHY_INTERRUPT is changed from IRQ7 to IRQ5 in mpc8272ads
 - Access to BCSR to enable the second console in function
   m82xx_board_init is commented out (it was generating
   an exception).


Best regards

Alex Bastos



[-- Attachment #2: dm9161_mii_and_mpc8272.diff --]
[-- Type: application/octet-stream, Size: 10065 bytes --]

--- snapshot/arch/ppc/8260_io/fcc_enet.c	2004-12-15 13:07:39.000000000 +0100
+++ linuxppc/arch/ppc/8260_io/fcc_enet.c	2004-12-14 20:28:00.000000000 +0100
@@ -86,6 +86,18 @@
 	const phy_cmd_t *shutdown;
 } phy_info_t;
 
+/* Register definitions for the PHY. */
+
+#define MII_REG_CR          0  /* Control Register                         */
+#define MII_REG_SR          1  /* Status Register                          */
+#define MII_REG_PHYIR1      2  /* PHY Identification Register 1            */
+#define MII_REG_PHYIR2      3  /* PHY Identification Register 2            */
+#define MII_REG_ANAR        4  /* A-N Advertisement Register               */
+#define MII_REG_ANLPAR      5  /* A-N Link Partner Ability Register        */
+#define MII_REG_ANER        6  /* A-N Expansion Register                   */
+#define MII_REG_ANNPTR      7  /* A-N Next Page Transmit Register          */
+#define MII_REG_ANLPRNPR    8  /* A-N Link Partner Received Next Page Reg. */
+
 /* values for phy_status */
 
 #define PHY_CONF_ANE	0x0001  /* 1 auto-negotiation enabled */
@@ -287,6 +299,12 @@
 #define PC_MDCK		((uint)0x00000000)
 #endif	/* ifdef CONFIG_USE_MDIO */
 
+/* PHY addresses */
+/* default to dynamic config of phy addresses */
+#define FCC1_PHY_ADDR 0
+#define FCC2_PHY_ADDR 2
+#define FCC3_PHY_ADDR 3
+
 /* A table of information for supporting FCCs.  This does two things.
  * First, we know how many FCCs we have and they are always externally
  * numbered from zero.  Second, it holds control register and I/O
@@ -294,6 +312,7 @@
  */
 typedef struct fcc_info {
 	uint	fc_fccnum;
+	uint	fc_phyaddr;
 	uint	fc_cpmblock;
 	uint	fc_cpmpage;
 	uint	fc_proff;
@@ -307,7 +326,7 @@
 
 static fcc_info_t fcc_ports[] = {
 #ifdef CONFIG_FCC1_ENET
-	{ 0, CPM_CR_FCC1_SBLOCK, CPM_CR_FCC1_PAGE, PROFF_FCC1, SIU_INT_FCC1,
+	{ 0, FCC1_PHY_ADDR, CPM_CR_FCC1_SBLOCK, CPM_CR_FCC1_PAGE, PROFF_FCC1, SIU_INT_FCC1,
 		(PC_F1RXCLK | PC_F1TXCLK), CMX1_CLK_ROUTE, CMX1_CLK_MASK,
 # if defined(CONFIG_TQM8260) || defined(CONFIG_ADS8272)
 		PC_MDIO, PC_MDCK },
@@ -316,7 +335,7 @@
 # endif
 #endif
 #ifdef CONFIG_FCC2_ENET
-	{ 1, CPM_CR_FCC2_SBLOCK, CPM_CR_FCC2_PAGE, PROFF_FCC2, SIU_INT_FCC2,
+	{ 1, FCC2_PHY_ADDR, CPM_CR_FCC2_SBLOCK, CPM_CR_FCC2_PAGE, PROFF_FCC2, SIU_INT_FCC2,
 		(PC_F2RXCLK | PC_F2TXCLK), CMX2_CLK_ROUTE, CMX2_CLK_MASK,
 # if defined(CONFIG_TQM8260) || defined(CONFIG_ADS8272)
 		PC_MDIO, PC_MDCK },
@@ -327,7 +346,7 @@
 # endif
 #endif
 #ifdef CONFIG_FCC3_ENET
-	{ 2, CPM_CR_FCC3_SBLOCK, CPM_CR_FCC3_PAGE, PROFF_FCC3, SIU_INT_FCC3,
+	{ 2, FCC3_PHY_ADDR, CPM_CR_FCC3_SBLOCK, CPM_CR_FCC3_PAGE, PROFF_FCC3, SIU_INT_FCC3,
 		(PC_F3RXCLK | PC_F3TXCLK), CMX3_CLK_ROUTE, CMX3_CLK_MASK,
 # if defined(CONFIG_TQM8260) || defined(CONFIG_ADS8272)
 		PC_MDIO, PC_MDCK },
@@ -1203,6 +1222,148 @@
 
 #endif /* CONFIG_FEC_DM9131 */
 
+#if defined (CONFIG_FCC_DM9161)
+/* ------------------------------------------------------------------------- */
+/* DM9161 Control register values */
+#define MIIM_DM9161_CR_STOP     0x0400
+#define MIIM_DM9161_CR_RSTAN    0x1200
+
+#define MIIM_DM9161_SCR         0x10
+#define MIIM_DM9161_SCR_INIT    0x0610
+
+/* DM9161 Specified Configuration and Status Register */
+#define MIIM_DM9161_SCSR        0x11
+#define MIIM_DM9161_SCSR_100F   0x8000
+#define MIIM_DM9161_SCSR_100H   0x4000
+#define MIIM_DM9161_SCSR_10F    0x2000
+#define MIIM_DM9161_SCSR_10H    0x1000
+/* DM9161 10BT register */
+#define MIIM_DM9161_10BTCSR     0x12
+#define MIIM_DM9161_10BTCSR_INIT 0x7800
+/* DM9161 Interrupt Register */
+#define MIIM_DM9161_INTR        0x15
+#define MIIM_DM9161_INTR_PEND           0x8000
+#define MIIM_DM9161_INTR_DPLX_MASK      0x0800
+#define MIIM_DM9161_INTR_SPD_MASK       0x0400
+#define MIIM_DM9161_INTR_LINK_MASK      0x0200
+#define MIIM_DM9161_INTR_MASK           0x0100
+#define MIIM_DM9161_INTR_DPLX_CHANGE    0x0010
+#define MIIM_DM9161_INTR_SPD_CHANGE     0x0008
+#define MIIM_DM9161_INTR_LINK_CHANGE    0x0004
+#define MIIM_DM9161_INTR_INIT           0x0000
+#define MIIM_DM9161_INTR_STOP   \
+(MIIM_DM9161_INTR_DPLX_MASK | MIIM_DM9161_INTR_SPD_MASK \
+   | MIIM_DM9161_INTR_LINK_MASK | MIIM_DM9161_INTR_MASK)
+
+static void mii_parse_dm9161_sr(uint mii_reg, struct net_device * dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint regstat,  timeout=0xffff;
+	
+	while(!(mii_reg & 0x0020) && timeout--)
+	{
+	    regstat=mk_mii_read(MII_REG_SR);
+	    regstat |= fep->phy_addr <<23;
+	    mii_reg = mii_send_receive(fep->fip,regstat);
+	}
+
+	mii_parse_sr(mii_reg, dev);
+}
+
+static void mii_parse_dm9161_scsr(uint mii_reg, struct net_device * dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint s = fep->phy_status;
+	s &= ~(PHY_STAT_SPMASK); 
+	switch((mii_reg >>12) & 0xf) {
+		case 1: 
+			{
+				s |= PHY_STAT_10HDX;
+				printk("10BaseT Half Duplex\n");
+				break;
+			}
+		case 2:
+			{
+				s |= PHY_STAT_10FDX;
+				printk("10BaseT Full Duplex\n");
+				break;
+			}
+		case 4:
+			{
+				s |= PHY_STAT_100HDX;
+				printk("100BaseT Half Duplex\n");
+				break;
+			}
+		case 8: 
+			{
+				s |= PHY_STAT_100FDX; 
+				printk("100BaseT Full Duplex\n");
+				break;
+			}
+	}
+	
+	fep->phy_status = s;
+	
+}
+
+static void mii_dm9161_wait(uint mii_reg, struct net_device *dev)
+{
+	int timeout = HZ;
+	
+	/* Davicom takes a bit to come up after a reset,
+	 * so wait here for a bit */
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(timeout);
+}
+
+static phy_info_t phy_info_dm9161 = {
+	0x00181b88,
+	"Davicom DM9161E",
+	(const phy_cmd_t[]) { /* config */
+		{ mk_mii_write(MII_REG_CR, MIIM_DM9161_CR_STOP), NULL}, 
+		/* Do not bypass the scrambler/descrambler */
+		{ mk_mii_write(MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT), NULL},
+		/* Configure 10BTCSR register */
+		{ mk_mii_write(MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT),NULL}, 
+		/* Configure some basic stuff */
+		{ mk_mii_write(MII_REG_CR, 0x1000), NULL},
+		{ mk_mii_read(MII_REG_CR), mii_parse_cr },
+		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+		{ mk_mii_end,} 
+	},
+	(const phy_cmd_t[]) { /* startup */
+		/* Restart Auto Negotiation */
+		{ mk_mii_write(MII_REG_CR, MIIM_DM9161_CR_RSTAN), NULL}, 
+		/* Status is read once to clear old link state */
+		{ mk_mii_read(MII_REG_SR), mii_dm9161_wait},
+		/* Auto-negotiate */
+		{ mk_mii_read(MII_REG_SR), mii_parse_dm9161_sr},
+		/* Read the status */
+		{ mk_mii_read(MIIM_DM9161_SCSR), mii_parse_dm9161_scsr},
+		/* Clear any pending interrupts */
+		{ mk_mii_read(MIIM_DM9161_INTR), NULL},
+		/* Enable Interrupts */
+		{ mk_mii_write(MIIM_DM9161_INTR, MIIM_DM9161_INTR_INIT), NULL}, 
+		{ mk_mii_end,}
+	},
+	(const phy_cmd_t[]) { /* ack_int */
+		{ mk_mii_read(MIIM_DM9161_INTR), NULL},
+#if 0
+                { mk_mii_read(MII_REG_SR), NULL},
+                { mk_mii_read(MII_REG_SR), mii_parse_dm9161_sr},
+                { mk_mii_read(MIIM_DM9161_SCSR), mii_parse_dm9161_scsr},
+#endif
+                { mk_mii_end,}
+        },
+        (const phy_cmd_t[]) { /* shutdown */
+		{ mk_mii_read(MIIM_DM9161_INTR),NULL}, 
+		{ mk_mii_write(MIIM_DM9161_INTR, MIIM_DM9161_INTR_STOP), NULL}, 
+		{ mk_mii_end,}
+	},
+};
+
+
+#endif /* CONFIG_FEC_DM9161 */
 
 static phy_info_t *phy_info[] = {
 
@@ -1222,6 +1383,10 @@
 	&phy_info_dm9131,
 #endif /* CONFIG_FEC_DM9131 */
 
+#if defined (CONFIG_FCC_DM9161)
+	&phy_info_dm9161,
+#endif
+	
 #ifdef CONFIG_FCC_GENERIC_PHY
 	/* Generic PHY support.  This must be the last PHY in the table.
 	 * It will be used to support any PHY that doesn't match a previous
@@ -1596,7 +1761,7 @@
 	 	* remainder of the interface.
 	 	*/
 		cep->phy_id_done = 0;
-		cep->phy_addr = 0;
+		cep->phy_addr = fip->fc_phyaddr;
 		mii_queue(dev, mk_mii_read(MII_PHYSID1), mii_discover_phy);
 		INIT_WORK(&cep->phy_relink, mii_display_status, dev);
 		INIT_WORK(&cep->phy_display_config, mii_display_config, dev);
@@ -1954,6 +2119,10 @@
 		printk("Can't get FCC IRQ %d\n", fip->fc_interrupt);
 
 #ifdef	PHY_INTERRUPT
+#ifdef CONFIG_ADS8272
+        if (request_irq(PHY_INTERRUPT, mii_link_interrupt, SA_SHIRQ,
+							"mii", dev) < 0)
+#else
 	/* Make IRQn edge triggered.  This does not work if PHY_INTERRUPT is
 	 * on Port C.
 	 */
@@ -1962,6 +2131,7 @@
 
 	if (request_irq(PHY_INTERRUPT, mii_link_interrupt, 0,
 							"mii", dev) < 0)
+#endif
 		printk("Can't get MII IRQ %d\n", PHY_INTERRUPT);
 #endif	/* PHY_INTERRUPT */
 
@@ -1984,6 +2154,8 @@
 	*/
         *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_FETHIEN;
         *(volatile uint *)(BCSR_ADDR + 4) |=  BCSR1_FETH_RST;
+	*(volatile uint *)(BCSR_ADDR + 12) &= ~BCSR3_FETHIEN2;
+	*(volatile uint *)(BCSR_ADDR + 12) |=  BCSR3_FETH2_RST;
 #endif
 
 #if defined(CONFIG_USE_MDIO) || defined(CONFIG_TQM8260)
--- snapshot/arch/ppc/platforms/pq2ads.h	2004-12-15 13:07:40.000000000 +0100
+++ linuxppc/arch/ppc/platforms/pq2ads.h	2004-12-14 14:58:39.000000000 +0100
@@ -40,8 +40,14 @@
 #define BCSR1_FETH_RST		((uint)0x04000000)	/* 0 == reset */
 #define BCSR1_RS232_EN1		((uint)0x02000000)	/* 0 == enable */
 #define BCSR1_RS232_EN2		((uint)0x01000000)	/* 0 == enable */
+#define BCSR3_FETHIEN2          ((uint)0x10000000)      /* 0 == enable */
+#define BCSR3_FETH2_RST         ((uint)0x80000000)      /* 0 == reset */
 
+#ifdef CONFIG_ADS8272
+#define PHY_INTERRUPT	SIU_INT_IRQ5
+#else
 #define PHY_INTERRUPT	SIU_INT_IRQ7
+#endif
 
 #ifdef CONFIG_PCI
 /* PCI interrupt controller */
--- snapshot/arch/ppc/platforms/pq2ads.c	2004-12-15 13:07:43.000000000 +0100
+++ linuxppc/arch/ppc/platforms/pq2ads.c	2004-11-25 09:59:05.000000000 +0100
@@ -22,5 +22,5 @@
 m82xx_board_init(void)
 {
 	/* Enable the 2nd UART port */
-        *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_RS232_EN2;
+        /* *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_RS232_EN2;*/
 }
--- snapshot/arch/ppc/8260_io/Kconfig	2004-12-15 13:07:43.000000000 +0100
+++ linuxppc/arch/ppc/8260_io/Kconfig	2004-12-09 12:56:31.000000000 +0100
@@ -53,6 +53,12 @@
 config FCC_QS6612
 	bool "QS6612"
 
+config FCC_DM9131
+	bool "DM9131"
+
+config FCC_DM9161
+	bool "DM9161"
+
 endchoice
 endmenu
 

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2004-12-15 13:11 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-12-15 13:31 [Patch] Full Duplex DM9161 MII support on MPC8272ADS alebas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox