Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* $Date: 2005/11/12 02:13:49 $ $RCSfile: my3126.c,v $ $Revision: 1.15 $ */
0003 #include "cphy.h"
0004 #include "elmer0.h"
0005 #include "suni1x10gexp_regs.h"
0006 
0007 /* Port Reset */
0008 static int my3126_reset(struct cphy *cphy, int wait)
0009 {
0010     /*
0011      * This can be done through registers.  It is not required since
0012      * a full chip reset is used.
0013      */
0014     return 0;
0015 }
0016 
0017 static int my3126_interrupt_enable(struct cphy *cphy)
0018 {
0019     schedule_delayed_work(&cphy->phy_update, HZ/30);
0020     t1_tpi_read(cphy->adapter, A_ELMER0_GPO, &cphy->elmer_gpo);
0021     return 0;
0022 }
0023 
0024 static int my3126_interrupt_disable(struct cphy *cphy)
0025 {
0026     cancel_delayed_work_sync(&cphy->phy_update);
0027     return 0;
0028 }
0029 
0030 static int my3126_interrupt_clear(struct cphy *cphy)
0031 {
0032     return 0;
0033 }
0034 
0035 #define OFFSET(REG_ADDR)    (REG_ADDR << 2)
0036 
0037 static int my3126_interrupt_handler(struct cphy *cphy)
0038 {
0039     u32 val;
0040     u16 val16;
0041     u16 status;
0042     u32 act_count;
0043     adapter_t *adapter;
0044     adapter = cphy->adapter;
0045 
0046     if (cphy->count == 50) {
0047         cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
0048         val16 = (u16) val;
0049         status = cphy->bmsr ^ val16;
0050 
0051         if (status & MDIO_STAT1_LSTATUS)
0052             t1_link_changed(adapter, 0);
0053         cphy->bmsr = val16;
0054 
0055         /* We have only enabled link change interrupts so it
0056            must be that
0057          */
0058         cphy->count = 0;
0059     }
0060 
0061     t1_tpi_write(adapter, OFFSET(SUNI1x10GEXP_REG_MSTAT_CONTROL),
0062         SUNI1x10GEXP_BITMSK_MSTAT_SNAP);
0063     t1_tpi_read(adapter,
0064         OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW), &act_count);
0065     t1_tpi_read(adapter,
0066         OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW), &val);
0067     act_count += val;
0068 
0069     /* Populate elmer_gpo with the register value */
0070     t1_tpi_read(adapter, A_ELMER0_GPO, &val);
0071     cphy->elmer_gpo = val;
0072 
0073     if ( (val & (1 << 8)) || (val & (1 << 19)) ||
0074          (cphy->act_count == act_count) || cphy->act_on ) {
0075         if (is_T2(adapter))
0076             val |= (1 << 9);
0077         else if (t1_is_T1B(adapter))
0078             val |= (1 << 20);
0079         cphy->act_on = 0;
0080     } else {
0081         if (is_T2(adapter))
0082             val &= ~(1 << 9);
0083         else if (t1_is_T1B(adapter))
0084             val &= ~(1 << 20);
0085         cphy->act_on = 1;
0086     }
0087 
0088     t1_tpi_write(adapter, A_ELMER0_GPO, val);
0089 
0090     cphy->elmer_gpo = val;
0091     cphy->act_count = act_count;
0092     cphy->count++;
0093 
0094     return cphy_cause_link_change;
0095 }
0096 
0097 static void my3126_poll(struct work_struct *work)
0098 {
0099     struct cphy *cphy = container_of(work, struct cphy, phy_update.work);
0100 
0101     my3126_interrupt_handler(cphy);
0102 }
0103 
0104 static int my3126_set_loopback(struct cphy *cphy, int on)
0105 {
0106     return 0;
0107 }
0108 
0109 /* To check the activity LED */
0110 static int my3126_get_link_status(struct cphy *cphy,
0111             int *link_ok, int *speed, int *duplex, int *fc)
0112 {
0113     u32 val;
0114     u16 val16;
0115     adapter_t *adapter;
0116 
0117     adapter = cphy->adapter;
0118     cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
0119     val16 = (u16) val;
0120 
0121     /* Populate elmer_gpo with the register value */
0122     t1_tpi_read(adapter, A_ELMER0_GPO, &val);
0123     cphy->elmer_gpo = val;
0124 
0125     *link_ok = (val16 & MDIO_STAT1_LSTATUS);
0126 
0127     if (*link_ok) {
0128         /* Turn on the LED. */
0129         if (is_T2(adapter))
0130              val &= ~(1 << 8);
0131         else if (t1_is_T1B(adapter))
0132              val &= ~(1 << 19);
0133     } else {
0134         /* Turn off the LED. */
0135         if (is_T2(adapter))
0136              val |= (1 << 8);
0137         else if (t1_is_T1B(adapter))
0138              val |= (1 << 19);
0139     }
0140 
0141     t1_tpi_write(adapter, A_ELMER0_GPO, val);
0142     cphy->elmer_gpo = val;
0143     *speed = SPEED_10000;
0144     *duplex = DUPLEX_FULL;
0145 
0146     /* need to add flow control */
0147     if (fc)
0148         *fc = PAUSE_RX | PAUSE_TX;
0149 
0150     return 0;
0151 }
0152 
0153 static void my3126_destroy(struct cphy *cphy)
0154 {
0155     kfree(cphy);
0156 }
0157 
0158 static const struct cphy_ops my3126_ops = {
0159     .destroy        = my3126_destroy,
0160     .reset          = my3126_reset,
0161     .interrupt_enable   = my3126_interrupt_enable,
0162     .interrupt_disable  = my3126_interrupt_disable,
0163     .interrupt_clear    = my3126_interrupt_clear,
0164     .interrupt_handler  = my3126_interrupt_handler,
0165     .get_link_status    = my3126_get_link_status,
0166     .set_loopback       = my3126_set_loopback,
0167     .mmds           = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS |
0168                    MDIO_DEVS_PHYXS),
0169 };
0170 
0171 static struct cphy *my3126_phy_create(struct net_device *dev,
0172             int phy_addr, const struct mdio_ops *mdio_ops)
0173 {
0174     struct cphy *cphy = kzalloc(sizeof (*cphy), GFP_KERNEL);
0175 
0176     if (!cphy)
0177         return NULL;
0178 
0179     cphy_init(cphy, dev, phy_addr, &my3126_ops, mdio_ops);
0180     INIT_DELAYED_WORK(&cphy->phy_update, my3126_poll);
0181     cphy->bmsr = 0;
0182 
0183     return cphy;
0184 }
0185 
0186 /* Chip Reset */
0187 static int my3126_phy_reset(adapter_t * adapter)
0188 {
0189     u32 val;
0190 
0191     t1_tpi_read(adapter, A_ELMER0_GPO, &val);
0192     val &= ~4;
0193     t1_tpi_write(adapter, A_ELMER0_GPO, val);
0194     msleep(100);
0195 
0196     t1_tpi_write(adapter, A_ELMER0_GPO, val | 4);
0197     msleep(1000);
0198 
0199     /* Now lets enable the Laser. Delay 100us */
0200     t1_tpi_read(adapter, A_ELMER0_GPO, &val);
0201     val |= 0x8000;
0202     t1_tpi_write(adapter, A_ELMER0_GPO, val);
0203     udelay(100);
0204     return 0;
0205 }
0206 
0207 const struct gphy t1_my3126_ops = {
0208     .create = my3126_phy_create,
0209     .reset = my3126_phy_reset
0210 };