2  * drivers/net/phy/davicom.c
 
   4  * Driver for Davicom PHYs
 
   8  * Copyright (c) 2004 Freescale Semiconductor, Inc.
 
  10  * This program is free software; you can redistribute  it and/or modify it
 
  11  * under  the terms of  the GNU General  Public License as published by the
 
  12  * Free Software Foundation;  either version 2 of the  License, or (at your
 
  13  * option) any later version.
 
  16 #include <linux/config.h>
 
  17 #include <linux/kernel.h>
 
  18 #include <linux/sched.h>
 
  19 #include <linux/string.h>
 
  20 #include <linux/errno.h>
 
  21 #include <linux/unistd.h>
 
  22 #include <linux/slab.h>
 
  23 #include <linux/interrupt.h>
 
  24 #include <linux/init.h>
 
  25 #include <linux/delay.h>
 
  26 #include <linux/netdevice.h>
 
  27 #include <linux/etherdevice.h>
 
  28 #include <linux/skbuff.h>
 
  29 #include <linux/spinlock.h>
 
  31 #include <linux/module.h>
 
  32 #include <linux/mii.h>
 
  33 #include <linux/ethtool.h>
 
  34 #include <linux/phy.h>
 
  38 #include <asm/uaccess.h>
 
  40 #define MII_DM9161_SCR          0x10
 
  41 #define MII_DM9161_SCR_INIT     0x0610
 
  43 /* DM9161 Interrupt Register */
 
  44 #define MII_DM9161_INTR 0x15
 
  45 #define MII_DM9161_INTR_PEND            0x8000
 
  46 #define MII_DM9161_INTR_DPLX_MASK       0x0800
 
  47 #define MII_DM9161_INTR_SPD_MASK        0x0400
 
  48 #define MII_DM9161_INTR_LINK_MASK       0x0200
 
  49 #define MII_DM9161_INTR_MASK            0x0100
 
  50 #define MII_DM9161_INTR_DPLX_CHANGE     0x0010
 
  51 #define MII_DM9161_INTR_SPD_CHANGE      0x0008
 
  52 #define MII_DM9161_INTR_LINK_CHANGE     0x0004
 
  53 #define MII_DM9161_INTR_INIT            0x0000
 
  54 #define MII_DM9161_INTR_STOP    \
 
  55 (MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \
 
  56  | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK)
 
  58 /* DM9161 10BT Configuration/Status */
 
  59 #define MII_DM9161_10BTCSR      0x12
 
  60 #define MII_DM9161_10BTCSR_INIT 0x7800
 
  62 MODULE_DESCRIPTION("Davicom PHY driver");
 
  63 MODULE_AUTHOR("Andy Fleming");
 
  64 MODULE_LICENSE("GPL");
 
  67 #define DM9161_DELAY 1
 
  68 static int dm9161_config_intr(struct phy_device *phydev)
 
  72         temp = phy_read(phydev, MII_DM9161_INTR);
 
  77         if(PHY_INTERRUPT_ENABLED == phydev->interrupts )
 
  78                 temp &= ~(MII_DM9161_INTR_STOP);
 
  80                 temp |= MII_DM9161_INTR_STOP;
 
  82         temp = phy_write(phydev, MII_DM9161_INTR, temp);
 
  87 static int dm9161_config_aneg(struct phy_device *phydev)
 
  92         err = phy_write(phydev, MII_BMCR, BMCR_ISOLATE);
 
  97         /* Configure the new settings */
 
  98         err = genphy_config_aneg(phydev);
 
 106 static int dm9161_config_init(struct phy_device *phydev)
 
 110         /* Isolate the PHY */
 
 111         err = phy_write(phydev, MII_BMCR, BMCR_ISOLATE);
 
 116         /* Do not bypass the scrambler/descrambler */
 
 117         err = phy_write(phydev, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
 
 122         /* Clear 10BTCSR to default */
 
 123         err = phy_write(phydev, MII_DM9161_10BTCSR, MII_DM9161_10BTCSR_INIT);
 
 128         /* Reconnect the PHY, and enable Autonegotiation */
 
 129         err = phy_write(phydev, MII_BMCR, BMCR_ANENABLE);
 
 137 static int dm9161_ack_interrupt(struct phy_device *phydev)
 
 139         int err = phy_read(phydev, MII_DM9161_INTR);
 
 141         return (err < 0) ? err : 0;
 
 144 static struct phy_driver dm9161_driver = {
 
 145         .phy_id         = 0x0181b880,
 
 146         .name           = "Davicom DM9161E",
 
 147         .phy_id_mask    = 0x0ffffff0,
 
 148         .features       = PHY_BASIC_FEATURES,
 
 149         .config_init    = dm9161_config_init,
 
 150         .config_aneg    = dm9161_config_aneg,
 
 151         .read_status    = genphy_read_status,
 
 152         .driver         = { .owner = THIS_MODULE,},
 
 155 static struct phy_driver dm9131_driver = {
 
 156         .phy_id         = 0x00181b80,
 
 157         .name           = "Davicom DM9131",
 
 158         .phy_id_mask    = 0x0ffffff0,
 
 159         .features       = PHY_BASIC_FEATURES,
 
 160         .flags          = PHY_HAS_INTERRUPT,
 
 161         .config_aneg    = genphy_config_aneg,
 
 162         .read_status    = genphy_read_status,
 
 163         .ack_interrupt  = dm9161_ack_interrupt,
 
 164         .config_intr    = dm9161_config_intr,
 
 165         .driver         = { .owner = THIS_MODULE,},
 
 168 static int __init davicom_init(void)
 
 172         ret = phy_driver_register(&dm9161_driver);
 
 176         ret = phy_driver_register(&dm9131_driver);
 
 182         phy_driver_unregister(&dm9161_driver);
 
 187 static void __exit davicom_exit(void)
 
 189         phy_driver_unregister(&dm9161_driver);
 
 190         phy_driver_unregister(&dm9131_driver);
 
 193 module_init(davicom_init);
 
 194 module_exit(davicom_exit);