1/* 2 * drivers/net/titan_mdio.c - Driver for Titan ethernet ports 3 * 4 * Copyright (C) 2003 PMC-Sierra Inc. 5 * Author : Manish Lachwani (lachwani@pmc-sierra.com) 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 * 21 * Management Data IO (MDIO) driver for the Titan GMII. Interacts with the Marvel PHY 22 * on the Titan. No support for the TBI as yet. 23 * 24 */ 25 26#include "titan_mdio.h" 27 28#define MDIO_DEBUG 29 30/* 31 * Local constants 32 */ 33#define MAX_CLKA 1023 34#define MAX_PHY_DEV 31 35#define MAX_PHY_REG 31 36#define WRITEADDRS_OPCODE 0x0 37#define READ_OPCODE 0x2 38#define WRITE_OPCODE 0x1 39#define MAX_MDIO_POLL 100 40 41/* 42 * Titan MDIO and SCMB registers 43 */ 44#define TITAN_GE_SCMB_CONTROL 0x01c0 /* SCMB Control */ 45#define TITAN_GE_SCMB_CLKA 0x01c4 /* SCMB Clock A */ 46#define TITAN_GE_MDIO_COMMAND 0x01d0 /* MDIO Command */ 47#define TITAN_GE_MDIO_DEVICE_PORT_ADDRESS 0x01d4 /* MDIO Device and Port addrs */ 48#define TITAN_GE_MDIO_DATA 0x01d8 /* MDIO Data */ 49#define TITAN_GE_MDIO_INTERRUPTS 0x01dC /* MDIO Interrupts */ 50 51/* 52 * Function to poll the MDIO 53 */ 54static int titan_ge_mdio_poll(void) 55{ 56 int i, val; 57 58 for (i = 0; i < MAX_MDIO_POLL; i++) { 59 val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_COMMAND); 60 61 if (!(val & 0x8000)) 62 return TITAN_GE_MDIO_GOOD; 63 } 64 65 return TITAN_GE_MDIO_ERROR; 66} 67 68 69/* 70 * Initialize and configure the MDIO 71 */ 72int titan_ge_mdio_setup(titan_ge_mdio_config *titan_mdio) 73{ 74 unsigned long val; 75 76 /* Reset the SCMB and program into MDIO mode*/ 77 TITAN_GE_MDIO_WRITE(TITAN_GE_SCMB_CONTROL, 0x9000); 78 TITAN_GE_MDIO_WRITE(TITAN_GE_SCMB_CONTROL, 0x1000); 79 80 /* CLK A */ 81 val = TITAN_GE_MDIO_READ(TITAN_GE_SCMB_CLKA); 82 val = ( (val & ~(0x03ff)) | (titan_mdio->clka & 0x03ff)); 83 TITAN_GE_MDIO_WRITE(TITAN_GE_SCMB_CLKA, val); 84 85 /* Preamble Suppresion */ 86 val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_COMMAND); 87 val = ( (val & ~(0x0001)) | (titan_mdio->mdio_spre & 0x0001)); 88 TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_COMMAND, val); 89 90 /* MDIO mode */ 91 val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS); 92 val = ( (val & ~(0x4000)) | (titan_mdio->mdio_mode & 0x4000)); 93 TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS, val); 94 95 return TITAN_GE_MDIO_GOOD; 96} 97 98/* 99 * Set the PHY address in indirect mode 100 */ 101int titan_ge_mdio_inaddrs(int dev_addr, int reg_addr) 102{ 103 volatile unsigned long val; 104 105 /* Setup the PHY device */ 106 val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS); 107 val = ( (val & ~(0x1f00)) | ( (dev_addr << 8) & 0x1f00)); 108 val = ( (val & ~(0x001f)) | ( reg_addr & 0x001f)); 109 TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS, val); 110 111 /* Write the new address */ 112 val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_COMMAND); 113 val = ( (val & ~(0x0300)) | ( (WRITEADDRS_OPCODE << 8) & 0x0300)); 114 TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_COMMAND, val); 115 116 return TITAN_GE_MDIO_GOOD; 117} 118 119/* 120 * Read the MDIO register. This is what the individual parametes mean: 121 * 122 * dev_addr : PHY ID 123 * reg_addr : register offset 124 * 125 * See the spec for the Titan MAC. We operate in the Direct Mode. 126 */ 127 128#define MAX_RETRIES 2 129 130int titan_ge_mdio_read(int dev_addr, int reg_addr, unsigned int *pdata) 131{ 132 volatile unsigned long val; 133 int retries = 0; 134 135 /* Setup the PHY device */ 136 137again: 138 val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS); 139 val = ( (val & ~(0x1f00)) | ( (dev_addr << 8) & 0x1f00)); 140 val = ( (val & ~(0x001f)) | ( reg_addr & 0x001f)); 141 val |= 0x4000; 142 TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS, val); 143 144 udelay(30); 145 146 /* Issue the read command */ 147 val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_COMMAND); 148 val = ( (val & ~(0x0300)) | ( (READ_OPCODE << 8) & 0x0300)); 149 TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_COMMAND, val); 150 151 udelay(30); 152 153 if (titan_ge_mdio_poll() != TITAN_GE_MDIO_GOOD) 154 return TITAN_GE_MDIO_ERROR; 155 156 *pdata = (unsigned int)TITAN_GE_MDIO_READ(TITAN_GE_MDIO_DATA); 157 val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_INTERRUPTS); 158 159 udelay(30); 160 161 if (val & 0x2) { 162 if (retries == MAX_RETRIES) 163 return TITAN_GE_MDIO_ERROR; 164 else { 165 retries++; 166 goto again; 167 } 168 } 169 170 return TITAN_GE_MDIO_GOOD; 171} 172 173/* 174 * Write to the MDIO register 175 * 176 * dev_addr : PHY ID 177 * reg_addr : register that needs to be written to 178 * 179 */ 180int titan_ge_mdio_write(int dev_addr, int reg_addr, unsigned int data) 181{ 182 volatile unsigned long val; 183 184 if (titan_ge_mdio_poll() != TITAN_GE_MDIO_GOOD) 185 return TITAN_GE_MDIO_ERROR; 186 187 /* Setup the PHY device */ 188 val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS); 189 val = ( (val & ~(0x1f00)) | ( (dev_addr << 8) & 0x1f00)); 190 val = ( (val & ~(0x001f)) | ( reg_addr & 0x001f)); 191 val |= 0x4000; 192 TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS, val); 193 194 udelay(30); 195 196 /* Setup the data to write */ 197 TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_DATA, data); 198 199 udelay(30); 200 201 /* Issue the write command */ 202 val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_COMMAND); 203 val = ( (val & ~(0x0300)) | ( (WRITE_OPCODE << 8) & 0x0300)); 204 TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_COMMAND, val); 205 206 udelay(30); 207 208 if (titan_ge_mdio_poll() != TITAN_GE_MDIO_GOOD) 209 return TITAN_GE_MDIO_ERROR; 210 211 val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_INTERRUPTS); 212 if (val & 0x2) 213 return TITAN_GE_MDIO_ERROR; 214 215 return TITAN_GE_MDIO_GOOD; 216} 217