Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * drivers/net/phy/cicada.c
  3  *
  4  * Driver for Cicada PHYs
  5  *
  6  * Author: Andy Fleming
  7  *
  8  * Copyright (c) 2004 Freescale Semiconductor, Inc.
  9  *
 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.
 14  *
 15  */
 16 #include <linux/kernel.h>
 17 #include <linux/string.h>
 18 #include <linux/errno.h>
 19 #include <linux/unistd.h>
 20 #include <linux/slab.h>
 21 #include <linux/interrupt.h>
 22 #include <linux/init.h>
 23 #include <linux/delay.h>
 24 #include <linux/netdevice.h>
 25 #include <linux/etherdevice.h>
 26 #include <linux/skbuff.h>
 27 #include <linux/spinlock.h>
 28 #include <linux/mm.h>
 29 #include <linux/module.h>
 30 #include <linux/mii.h>
 31 #include <linux/ethtool.h>
 32 #include <linux/phy.h>
 33 
 34 #include <asm/io.h>
 35 #include <asm/irq.h>
 36 #include <asm/uaccess.h>
 37 
 38 /* Cicada Extended Control Register 1 */
 39 #define MII_CIS8201_EXT_CON1           0x17
 40 #define MII_CIS8201_EXTCON1_INIT       0x0000
 41 
 42 /* Cicada Interrupt Mask Register */
 43 #define MII_CIS8201_IMASK               0x19
 44 #define MII_CIS8201_IMASK_IEN           0x8000
 45 #define MII_CIS8201_IMASK_SPEED 0x4000
 46 #define MII_CIS8201_IMASK_LINK          0x2000
 47 #define MII_CIS8201_IMASK_DUPLEX        0x1000
 48 #define MII_CIS8201_IMASK_MASK          0xf000
 49 
 50 /* Cicada Interrupt Status Register */
 51 #define MII_CIS8201_ISTAT               0x1a
 52 #define MII_CIS8201_ISTAT_STATUS        0x8000
 53 #define MII_CIS8201_ISTAT_SPEED 0x4000
 54 #define MII_CIS8201_ISTAT_LINK          0x2000
 55 #define MII_CIS8201_ISTAT_DUPLEX        0x1000
 56 
 57 /* Cicada Auxiliary Control/Status Register */
 58 #define MII_CIS8201_AUX_CONSTAT        0x1c
 59 #define MII_CIS8201_AUXCONSTAT_INIT    0x0004
 60 #define MII_CIS8201_AUXCONSTAT_DUPLEX  0x0020
 61 #define MII_CIS8201_AUXCONSTAT_SPEED   0x0018
 62 #define MII_CIS8201_AUXCONSTAT_GBIT    0x0010
 63 #define MII_CIS8201_AUXCONSTAT_100     0x0008
 64 
 65 MODULE_DESCRIPTION("Cicadia PHY driver");
 66 MODULE_AUTHOR("Andy Fleming");
 67 MODULE_LICENSE("GPL");
 68 
 69 static int cis820x_config_init(struct phy_device *phydev)
 70 {
 71         int err;
 72 
 73         err = phy_write(phydev, MII_CIS8201_AUX_CONSTAT,
 74                         MII_CIS8201_AUXCONSTAT_INIT);
 75 
 76         if (err < 0)
 77                 return err;
 78 
 79         err = phy_write(phydev, MII_CIS8201_EXT_CON1,
 80                         MII_CIS8201_EXTCON1_INIT);
 81 
 82         return err;
 83 }
 84 
 85 static int cis820x_ack_interrupt(struct phy_device *phydev)
 86 {
 87         int err = phy_read(phydev, MII_CIS8201_ISTAT);
 88 
 89         return (err < 0) ? err : 0;
 90 }
 91 
 92 static int cis820x_config_intr(struct phy_device *phydev)
 93 {
 94         int err;
 95 
 96         if(phydev->interrupts == PHY_INTERRUPT_ENABLED)
 97                 err = phy_write(phydev, MII_CIS8201_IMASK, 
 98                                 MII_CIS8201_IMASK_MASK);
 99         else
100                 err = phy_write(phydev, MII_CIS8201_IMASK, 0);
101 
102         return err;
103 }
104 
105 /* Cicada 8201, a.k.a Vitesse VSC8201 */
106 static struct phy_driver cis8201_driver = {
107         .phy_id         = 0x000fc410,
108         .name           = "Cicada Cis8201",
109         .phy_id_mask    = 0x000ffff0,
110         .features       = PHY_GBIT_FEATURES,
111         .flags          = PHY_HAS_INTERRUPT,
112         .config_init    = &cis820x_config_init,
113         .config_aneg    = &genphy_config_aneg,
114         .read_status    = &genphy_read_status,
115         .ack_interrupt  = &cis820x_ack_interrupt,
116         .config_intr    = &cis820x_config_intr,
117         .driver         = { .owner = THIS_MODULE,},
118 };
119 
120 /* Cicada 8204 */
121 static struct phy_driver cis8204_driver = {
122         .phy_id         = 0x000fc440,
123         .name           = "Cicada Cis8204",
124         .phy_id_mask    = 0x000fffc0,
125         .features       = PHY_GBIT_FEATURES,
126         .flags          = PHY_HAS_INTERRUPT,
127         .config_init    = &cis820x_config_init,
128         .config_aneg    = &genphy_config_aneg,
129         .read_status    = &genphy_read_status,
130         .ack_interrupt  = &cis820x_ack_interrupt,
131         .config_intr    = &cis820x_config_intr,
132         .driver         = { .owner = THIS_MODULE,},
133 };
134 
135 static int __init cicada_init(void)
136 {
137         int ret;
138 
139         ret = phy_driver_register(&cis8204_driver);
140         if (ret)
141                 goto err1;
142 
143         ret = phy_driver_register(&cis8201_driver);
144         if (ret)
145                 goto err2;
146         return 0;
147 
148 err2:
149         phy_driver_unregister(&cis8204_driver);
150 err1:
151         return ret;
152 }
153 
154 static void __exit cicada_exit(void)
155 {
156         phy_driver_unregister(&cis8204_driver);
157         phy_driver_unregister(&cis8201_driver);
158 }
159 
160 module_init(cicada_init);
161 module_exit(cicada_exit);
162 
  This page was automatically generated by the LXR engine.