Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * drivers/net/phy/qsemi.c
0004  *
0005  * Driver for Quality Semiconductor PHYs
0006  *
0007  * Author: Andy Fleming
0008  *
0009  * Copyright (c) 2004 Freescale Semiconductor, Inc.
0010  */
0011 #include <linux/kernel.h>
0012 #include <linux/string.h>
0013 #include <linux/errno.h>
0014 #include <linux/unistd.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/init.h>
0017 #include <linux/delay.h>
0018 #include <linux/netdevice.h>
0019 #include <linux/etherdevice.h>
0020 #include <linux/skbuff.h>
0021 #include <linux/spinlock.h>
0022 #include <linux/mm.h>
0023 #include <linux/module.h>
0024 #include <linux/mii.h>
0025 #include <linux/ethtool.h>
0026 #include <linux/phy.h>
0027 
0028 #include <asm/io.h>
0029 #include <asm/irq.h>
0030 #include <linux/uaccess.h>
0031 
0032 /* ------------------------------------------------------------------------- */
0033 /* The Quality Semiconductor QS6612 is used on the RPX CLLF                  */
0034 
0035 /* register definitions */
0036 
0037 #define MII_QS6612_MCR      17  /* Mode Control Register      */
0038 #define MII_QS6612_FTR      27  /* Factory Test Register      */
0039 #define MII_QS6612_MCO      28  /* Misc. Control Register     */
0040 #define MII_QS6612_ISR      29  /* Interrupt Source Register  */
0041 #define MII_QS6612_IMR      30  /* Interrupt Mask Register    */
0042 #define MII_QS6612_IMR_INIT 0x003a
0043 #define MII_QS6612_PCR      31  /* 100BaseTx PHY Control Reg. */
0044 
0045 #define QS6612_PCR_AN_COMPLETE  0x1000
0046 #define QS6612_PCR_RLBEN    0x0200
0047 #define QS6612_PCR_DCREN    0x0100
0048 #define QS6612_PCR_4B5BEN   0x0040
0049 #define QS6612_PCR_TX_ISOLATE   0x0020
0050 #define QS6612_PCR_MLT3_DIS 0x0002
0051 #define QS6612_PCR_SCRM_DESCRM  0x0001
0052 
0053 MODULE_DESCRIPTION("Quality Semiconductor PHY driver");
0054 MODULE_AUTHOR("Andy Fleming");
0055 MODULE_LICENSE("GPL");
0056 
0057 /* Returns 0, unless there's a write error */
0058 static int qs6612_config_init(struct phy_device *phydev)
0059 {
0060     /* The PHY powers up isolated on the RPX,
0061      * so send a command to allow operation.
0062      * XXX - My docs indicate this should be 0x0940
0063      * ...or something.  The current value sets three
0064      * reserved bits, bit 11, which specifies it should be
0065      * set to one, bit 10, which specifies it should be set
0066      * to 0, and bit 7, which doesn't specify.  However, my
0067      * docs are preliminary, and I will leave it like this
0068      * until someone more knowledgable corrects me or it.
0069      * -- Andy Fleming
0070      */
0071     return phy_write(phydev, MII_QS6612_PCR, 0x0dc0);
0072 }
0073 
0074 static int qs6612_ack_interrupt(struct phy_device *phydev)
0075 {
0076     int err;
0077 
0078     /* The Interrupt Source register is not self-clearing, bits 4 and 5 are
0079      * cleared when MII_BMSR is read and bits 1 and 3 are cleared when
0080      * MII_EXPANSION is read
0081      */
0082     err = phy_read(phydev, MII_QS6612_ISR);
0083 
0084     if (err < 0)
0085         return err;
0086 
0087     err = phy_read(phydev, MII_BMSR);
0088 
0089     if (err < 0)
0090         return err;
0091 
0092     err = phy_read(phydev, MII_EXPANSION);
0093 
0094     if (err < 0)
0095         return err;
0096 
0097     return 0;
0098 }
0099 
0100 static int qs6612_config_intr(struct phy_device *phydev)
0101 {
0102     int err;
0103 
0104     if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
0105         /* clear any interrupts before enabling them */
0106         err = qs6612_ack_interrupt(phydev);
0107         if (err)
0108             return err;
0109 
0110         err = phy_write(phydev, MII_QS6612_IMR,
0111                 MII_QS6612_IMR_INIT);
0112     } else {
0113         err = phy_write(phydev, MII_QS6612_IMR, 0);
0114         if (err)
0115             return err;
0116 
0117         /* clear any leftover interrupts */
0118         err = qs6612_ack_interrupt(phydev);
0119     }
0120 
0121     return err;
0122 
0123 }
0124 
0125 static irqreturn_t qs6612_handle_interrupt(struct phy_device *phydev)
0126 {
0127     int irq_status;
0128 
0129     irq_status = phy_read(phydev, MII_QS6612_ISR);
0130     if (irq_status < 0) {
0131         phy_error(phydev);
0132         return IRQ_NONE;
0133     }
0134 
0135     if (!(irq_status & MII_QS6612_IMR_INIT))
0136         return IRQ_NONE;
0137 
0138     /* the interrupt source register is not self-clearing */
0139     qs6612_ack_interrupt(phydev);
0140 
0141     phy_trigger_machine(phydev);
0142 
0143     return IRQ_HANDLED;
0144 }
0145 
0146 static struct phy_driver qs6612_driver[] = { {
0147     .phy_id     = 0x00181440,
0148     .name       = "QS6612",
0149     .phy_id_mask    = 0xfffffff0,
0150     /* PHY_BASIC_FEATURES */
0151     .config_init    = qs6612_config_init,
0152     .config_intr    = qs6612_config_intr,
0153     .handle_interrupt = qs6612_handle_interrupt,
0154 } };
0155 
0156 module_phy_driver(qs6612_driver);
0157 
0158 static struct mdio_device_id __maybe_unused qs6612_tbl[] = {
0159     { 0x00181440, 0xfffffff0 },
0160     { }
0161 };
0162 
0163 MODULE_DEVICE_TABLE(mdio, qs6612_tbl);