cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mv88x201x.c (8713B)


      1/*****************************************************************************
      2 *                                                                           *
      3 * File: mv88x201x.c                                                         *
      4 * $Revision: 1.12 $                                                         *
      5 * $Date: 2005/04/15 19:27:14 $                                              *
      6 * Description:                                                              *
      7 *  Marvell PHY (mv88x201x) functionality.                                   *
      8 *  part of the Chelsio 10Gb Ethernet Driver.                                *
      9 *                                                                           *
     10 * This program is free software; you can redistribute it and/or modify      *
     11 * it under the terms of the GNU General Public License, version 2, as       *
     12 * published by the Free Software Foundation.                                *
     13 *                                                                           *
     14 * You should have received a copy of the GNU General Public License along   *
     15 * with this program; if not, see <http://www.gnu.org/licenses/>.            *
     16 *                                                                           *
     17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
     18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
     19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
     20 *                                                                           *
     21 * http://www.chelsio.com                                                    *
     22 *                                                                           *
     23 * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
     24 * All rights reserved.                                                      *
     25 *                                                                           *
     26 * Maintainers: maintainers@chelsio.com                                      *
     27 *                                                                           *
     28 * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
     29 *          Tina Yang               <tainay@chelsio.com>                     *
     30 *          Felix Marti             <felix@chelsio.com>                      *
     31 *          Scott Bardone           <sbardone@chelsio.com>                   *
     32 *          Kurt Ottaway            <kottaway@chelsio.com>                   *
     33 *          Frank DiMambro          <frank@chelsio.com>                      *
     34 *                                                                           *
     35 * History:                                                                  *
     36 *                                                                           *
     37 ****************************************************************************/
     38
     39#include "cphy.h"
     40#include "elmer0.h"
     41
     42/*
     43 * The 88x2010 Rev C. requires some link status registers * to be read
     44 * twice in order to get the right values. Future * revisions will fix
     45 * this problem and then this macro * can disappear.
     46 */
     47#define MV88x2010_LINK_STATUS_BUGS    1
     48
     49static int led_init(struct cphy *cphy)
     50{
     51	/* Setup the LED registers so we can turn on/off.
     52	 * Writing these bits maps control to another
     53	 * register. mmd(0x1) addr(0x7)
     54	 */
     55	cphy_mdio_write(cphy, MDIO_MMD_PCS, 0x8304, 0xdddd);
     56	return 0;
     57}
     58
     59static int led_link(struct cphy *cphy, u32 do_enable)
     60{
     61	u32 led = 0;
     62#define LINK_ENABLE_BIT 0x1
     63
     64	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, &led);
     65
     66	if (do_enable & LINK_ENABLE_BIT) {
     67		led |= LINK_ENABLE_BIT;
     68		cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, led);
     69	} else {
     70		led &= ~LINK_ENABLE_BIT;
     71		cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, led);
     72	}
     73	return 0;
     74}
     75
     76/* Port Reset */
     77static int mv88x201x_reset(struct cphy *cphy, int wait)
     78{
     79	/* This can be done through registers.  It is not required since
     80	 * a full chip reset is used.
     81	 */
     82	return 0;
     83}
     84
     85static int mv88x201x_interrupt_enable(struct cphy *cphy)
     86{
     87	/* Enable PHY LASI interrupts. */
     88	cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL,
     89			MDIO_PMA_LASI_LSALARM);
     90
     91	/* Enable Marvell interrupts through Elmer0. */
     92	if (t1_is_asic(cphy->adapter)) {
     93		u32 elmer;
     94
     95		t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
     96		elmer |= ELMER0_GP_BIT6;
     97		t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
     98	}
     99	return 0;
    100}
    101
    102static int mv88x201x_interrupt_disable(struct cphy *cphy)
    103{
    104	/* Disable PHY LASI interrupts. */
    105	cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, 0x0);
    106
    107	/* Disable Marvell interrupts through Elmer0. */
    108	if (t1_is_asic(cphy->adapter)) {
    109		u32 elmer;
    110
    111		t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
    112		elmer &= ~ELMER0_GP_BIT6;
    113		t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
    114	}
    115	return 0;
    116}
    117
    118static int mv88x201x_interrupt_clear(struct cphy *cphy)
    119{
    120	u32 elmer;
    121	u32 val;
    122
    123#ifdef MV88x2010_LINK_STATUS_BUGS
    124	/* Required to read twice before clear takes affect. */
    125	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_RXSTAT, &val);
    126	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_TXSTAT, &val);
    127	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, &val);
    128
    129	/* Read this register after the others above it else
    130	 * the register doesn't clear correctly.
    131	 */
    132	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
    133#endif
    134
    135	/* Clear link status. */
    136	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
    137	/* Clear PHY LASI interrupts. */
    138	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, &val);
    139
    140#ifdef MV88x2010_LINK_STATUS_BUGS
    141	/* Do it again. */
    142	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_RXSTAT, &val);
    143	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_TXSTAT, &val);
    144#endif
    145
    146	/* Clear Marvell interrupts through Elmer0. */
    147	if (t1_is_asic(cphy->adapter)) {
    148		t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer);
    149		elmer |= ELMER0_GP_BIT6;
    150		t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer);
    151	}
    152	return 0;
    153}
    154
    155static int mv88x201x_interrupt_handler(struct cphy *cphy)
    156{
    157	/* Clear interrupts */
    158	mv88x201x_interrupt_clear(cphy);
    159
    160	/* We have only enabled link change interrupts and so
    161	 * cphy_cause must be a link change interrupt.
    162	 */
    163	return cphy_cause_link_change;
    164}
    165
    166static int mv88x201x_set_loopback(struct cphy *cphy, int on)
    167{
    168	return 0;
    169}
    170
    171static int mv88x201x_get_link_status(struct cphy *cphy, int *link_ok,
    172				     int *speed, int *duplex, int *fc)
    173{
    174	u32 val = 0;
    175
    176	if (link_ok) {
    177		/* Read link status. */
    178		cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
    179		val &= MDIO_STAT1_LSTATUS;
    180		*link_ok = (val == MDIO_STAT1_LSTATUS);
    181		/* Turn on/off Link LED */
    182		led_link(cphy, *link_ok);
    183	}
    184	if (speed)
    185		*speed = SPEED_10000;
    186	if (duplex)
    187		*duplex = DUPLEX_FULL;
    188	if (fc)
    189		*fc = PAUSE_RX | PAUSE_TX;
    190	return 0;
    191}
    192
    193static void mv88x201x_destroy(struct cphy *cphy)
    194{
    195	kfree(cphy);
    196}
    197
    198static const struct cphy_ops mv88x201x_ops = {
    199	.destroy           = mv88x201x_destroy,
    200	.reset             = mv88x201x_reset,
    201	.interrupt_enable  = mv88x201x_interrupt_enable,
    202	.interrupt_disable = mv88x201x_interrupt_disable,
    203	.interrupt_clear   = mv88x201x_interrupt_clear,
    204	.interrupt_handler = mv88x201x_interrupt_handler,
    205	.get_link_status   = mv88x201x_get_link_status,
    206	.set_loopback      = mv88x201x_set_loopback,
    207	.mmds              = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS |
    208			      MDIO_DEVS_PHYXS | MDIO_DEVS_WIS),
    209};
    210
    211static struct cphy *mv88x201x_phy_create(struct net_device *dev, int phy_addr,
    212					 const struct mdio_ops *mdio_ops)
    213{
    214	u32 val;
    215	struct cphy *cphy = kzalloc(sizeof(*cphy), GFP_KERNEL);
    216
    217	if (!cphy)
    218		return NULL;
    219
    220	cphy_init(cphy, dev, phy_addr, &mv88x201x_ops, mdio_ops);
    221
    222	/* Commands the PHY to enable XFP's clock. */
    223	cphy_mdio_read(cphy, MDIO_MMD_PCS, 0x8300, &val);
    224	cphy_mdio_write(cphy, MDIO_MMD_PCS, 0x8300, val | 1);
    225
    226	/* Clear link status. Required because of a bug in the PHY.  */
    227	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT2, &val);
    228	cphy_mdio_read(cphy, MDIO_MMD_PCS, MDIO_STAT2, &val);
    229
    230	/* Allows for Link,Ack LED turn on/off */
    231	led_init(cphy);
    232	return cphy;
    233}
    234
    235/* Chip Reset */
    236static int mv88x201x_phy_reset(adapter_t *adapter)
    237{
    238	u32 val;
    239
    240	t1_tpi_read(adapter, A_ELMER0_GPO, &val);
    241	val &= ~4;
    242	t1_tpi_write(adapter, A_ELMER0_GPO, val);
    243	msleep(100);
    244
    245	t1_tpi_write(adapter, A_ELMER0_GPO, val | 4);
    246	msleep(1000);
    247
    248	/* Now lets enable the Laser. Delay 100us */
    249	t1_tpi_read(adapter, A_ELMER0_GPO, &val);
    250	val |= 0x8000;
    251	t1_tpi_write(adapter, A_ELMER0_GPO, val);
    252	udelay(100);
    253	return 0;
    254}
    255
    256const struct gphy t1_mv88x201x_ops = {
    257	.create = mv88x201x_phy_create,
    258	.reset = mv88x201x_phy_reset
    259};