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 /* $Date: 2005/11/12 02:13:49 $ $RCSfile: my3126.c,v $ $Revision: 1.15 $ */
  2 #include "cphy.h"
  3 #include "elmer0.h"
  4 #include "suni1x10gexp_regs.h"
  5 
  6 /* Port Reset */
  7 static int my3126_reset(struct cphy *cphy, int wait)
  8 {
  9         /*
 10          * This can be done through registers.  It is not required since
 11          * a full chip reset is used.
 12          */
 13         return 0;
 14 }
 15 
 16 static int my3126_interrupt_enable(struct cphy *cphy)
 17 {
 18         schedule_delayed_work(&cphy->phy_update, HZ/30);
 19         t1_tpi_read(cphy->adapter, A_ELMER0_GPO, &cphy->elmer_gpo);
 20         return 0;
 21 }
 22 
 23 static int my3126_interrupt_disable(struct cphy *cphy)
 24 {
 25         cancel_rearming_delayed_work(&cphy->phy_update);
 26         return 0;
 27 }
 28 
 29 static int my3126_interrupt_clear(struct cphy *cphy)
 30 {
 31         return 0;
 32 }
 33 
 34 #define OFFSET(REG_ADDR)    (REG_ADDR << 2)
 35 
 36 static int my3126_interrupt_handler(struct cphy *cphy)
 37 {
 38         u32 val;
 39         u16 val16;
 40         u16 status;
 41         u32 act_count;
 42         adapter_t *adapter;
 43         adapter = cphy->adapter;
 44 
 45         if (cphy->count == 50) {
 46                 cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
 47                 val16 = (u16) val;
 48                 status = cphy->bmsr ^ val16;
 49 
 50                 if (status & MDIO_STAT1_LSTATUS)
 51                         t1_link_changed(adapter, 0);
 52                 cphy->bmsr = val16;
 53 
 54                 /* We have only enabled link change interrupts so it
 55                    must be that
 56                  */
 57                 cphy->count = 0;
 58         }
 59 
 60         t1_tpi_write(adapter, OFFSET(SUNI1x10GEXP_REG_MSTAT_CONTROL),
 61                 SUNI1x10GEXP_BITMSK_MSTAT_SNAP);
 62         t1_tpi_read(adapter,
 63                 OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW), &act_count);
 64         t1_tpi_read(adapter,
 65                 OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW), &val);
 66         act_count += val;
 67 
 68         /* Populate elmer_gpo with the register value */
 69         t1_tpi_read(adapter, A_ELMER0_GPO, &val);
 70         cphy->elmer_gpo = val;
 71 
 72         if ( (val & (1 << 8)) || (val & (1 << 19)) ||
 73              (cphy->act_count == act_count) || cphy->act_on ) {
 74                 if (is_T2(adapter))
 75                         val |= (1 << 9);
 76                 else if (t1_is_T1B(adapter))
 77                         val |= (1 << 20);
 78                 cphy->act_on = 0;
 79         } else {
 80                 if (is_T2(adapter))
 81                         val &= ~(1 << 9);
 82                 else if (t1_is_T1B(adapter))
 83                         val &= ~(1 << 20);
 84                 cphy->act_on = 1;
 85         }
 86 
 87         t1_tpi_write(adapter, A_ELMER0_GPO, val);
 88 
 89         cphy->elmer_gpo = val;
 90         cphy->act_count = act_count;
 91         cphy->count++;
 92 
 93         return cphy_cause_link_change;
 94 }
 95 
 96 static void my3216_poll(struct work_struct *work)
 97 {
 98         struct cphy *cphy = container_of(work, struct cphy, phy_update.work);
 99 
100         my3126_interrupt_handler(cphy);
101 }
102 
103 static int my3126_set_loopback(struct cphy *cphy, int on)
104 {
105         return 0;
106 }
107 
108 /* To check the activity LED */
109 static int my3126_get_link_status(struct cphy *cphy,
110                         int *link_ok, int *speed, int *duplex, int *fc)
111 {
112         u32 val;
113         u16 val16;
114         adapter_t *adapter;
115 
116         adapter = cphy->adapter;
117         cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
118         val16 = (u16) val;
119 
120         /* Populate elmer_gpo with the register value */
121         t1_tpi_read(adapter, A_ELMER0_GPO, &val);
122         cphy->elmer_gpo = val;
123 
124         *link_ok = (val16 & MDIO_STAT1_LSTATUS);
125 
126         if (*link_ok) {
127                 /* Turn on the LED. */
128                 if (is_T2(adapter))
129                          val &= ~(1 << 8);
130                 else if (t1_is_T1B(adapter))
131                          val &= ~(1 << 19);
132         } else {
133                 /* Turn off the LED. */
134                 if (is_T2(adapter))
135                          val |= (1 << 8);
136                 else if (t1_is_T1B(adapter))
137                          val |= (1 << 19);
138         }
139 
140         t1_tpi_write(adapter, A_ELMER0_GPO, val);
141         cphy->elmer_gpo = val;
142         *speed = SPEED_10000;
143         *duplex = DUPLEX_FULL;
144 
145         /* need to add flow control */
146         if (fc)
147                 *fc = PAUSE_RX | PAUSE_TX;
148 
149         return 0;
150 }
151 
152 static void my3126_destroy(struct cphy *cphy)
153 {
154         kfree(cphy);
155 }
156 
157 static struct cphy_ops my3126_ops = {
158         .destroy                = my3126_destroy,
159         .reset                  = my3126_reset,
160         .interrupt_enable       = my3126_interrupt_enable,
161         .interrupt_disable      = my3126_interrupt_disable,
162         .interrupt_clear        = my3126_interrupt_clear,
163         .interrupt_handler      = my3126_interrupt_handler,
164         .get_link_status        = my3126_get_link_status,
165         .set_loopback           = my3126_set_loopback,
166         .mmds                   = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS |
167                                    MDIO_DEVS_PHYXS),
168 };
169 
170 static struct cphy *my3126_phy_create(struct net_device *dev,
171                         int phy_addr, const struct mdio_ops *mdio_ops)
172 {
173         struct cphy *cphy = kzalloc(sizeof (*cphy), GFP_KERNEL);
174 
175         if (!cphy)
176                 return NULL;
177 
178         cphy_init(cphy, dev, phy_addr, &my3126_ops, mdio_ops);
179         INIT_DELAYED_WORK(&cphy->phy_update, my3216_poll);
180         cphy->bmsr = 0;
181 
182         return cphy;
183 }
184 
185 /* Chip Reset */
186 static int my3126_phy_reset(adapter_t * adapter)
187 {
188         u32 val;
189 
190         t1_tpi_read(adapter, A_ELMER0_GPO, &val);
191         val &= ~4;
192         t1_tpi_write(adapter, A_ELMER0_GPO, val);
193         msleep(100);
194 
195         t1_tpi_write(adapter, A_ELMER0_GPO, val | 4);
196         msleep(1000);
197 
198         /* Now lets enable the Laser. Delay 100us */
199         t1_tpi_read(adapter, A_ELMER0_GPO, &val);
200         val |= 0x8000;
201         t1_tpi_write(adapter, A_ELMER0_GPO, val);
202         udelay(100);
203         return 0;
204 }
205 
206 const struct gphy t1_my3126_ops = {
207         .create = my3126_phy_create,
208         .reset = my3126_phy_reset
209 };
210 
  This page was automatically generated by the LXR engine.