* [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