cvmx-ixf18201.c revision 215976
1221828Sgrehan/***********************license start*************** 2221828Sgrehan * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights 3221828Sgrehan * reserved. 4221828Sgrehan * 5221828Sgrehan * 6221828Sgrehan * Redistribution and use in source and binary forms, with or without 7221828Sgrehan * modification, are permitted provided that the following conditions are 8221828Sgrehan * met: 9221828Sgrehan * 10221828Sgrehan * * Redistributions of source code must retain the above copyright 11221828Sgrehan * notice, this list of conditions and the following disclaimer. 12221828Sgrehan * 13221828Sgrehan * * Redistributions in binary form must reproduce the above 14221828Sgrehan * copyright notice, this list of conditions and the following 15221828Sgrehan * disclaimer in the documentation and/or other materials provided 16221828Sgrehan * with the distribution. 17221828Sgrehan 18221828Sgrehan * * Neither the name of Cavium Networks nor the names of 19221828Sgrehan * its contributors may be used to endorse or promote products 20221828Sgrehan * derived from this software without specific prior written 21221828Sgrehan * permission. 22221828Sgrehan 23221828Sgrehan * This Software, including technical data, may be subject to U.S. export control 24221828Sgrehan * laws, including the U.S. Export Administration Act and its associated 25221828Sgrehan * regulations, and may be subject to export or import regulations in other 26221828Sgrehan * countries. 27221828Sgrehan 28221828Sgrehan * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29221828Sgrehan * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR 30221828Sgrehan * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31221828Sgrehan * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32221828Sgrehan * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33234695Sgrehan * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34221828Sgrehan * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35221828Sgrehan * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36221828Sgrehan * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37221828Sgrehan * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38221828Sgrehan ***********************license end**************************************/ 39221828Sgrehan 40221828Sgrehan 41221828Sgrehan 42256072Sneel 43221828Sgrehan 44221828Sgrehan/* This file contains support functions for the Cortina IXF18201 SPI->XAUI dual 45221828Sgrehan** MAC. The IXF18201 has dual SPI and dual XAUI interfaces to provide 2 10 gigabit 46221828Sgrehan** interfaces. 47221828Sgrehan** This file supports the EBT5810 evaluation board. To support a different board, 48256072Sneel** the 16 bit read/write functions would need to be customized for that board, and the 49256072Sneel** IXF18201 may need to be initialized differently as well. 50256072Sneel** 51256072Sneel** The IXF18201 and Octeon are configured for 2 SPI channels per interface (ports 0/1, and 16/17). 52256072Sneel** Ports 0 and 16 are the ports that are connected to the XAUI MACs (which are connected to the SFP+ modules) 53256072Sneel** Ports 1 and 17 are connected to the hairpin loopback port on the IXF SPI interface. All packets sent out 54221828Sgrehan** of these ports are looped back the same port they were sent on. The loopback ports are always enabled. 55261275Sjhb** 56221828Sgrehan** The MAC address filtering on the IXF is not enabled. Link up/down events are not detected, only SPI status 57221828Sgrehan** is monitored by default, which is independent of the XAUI/SFP+ link status. 58241489Sneel** 59262350Sjhb** 60221914Sjhb*/ 61256072Sneel#include "cvmx.h" 62221828Sgrehan#include "cvmx-swap.h" 63221828Sgrehan 64261088Sjhb 65261088Sjhb 66256072Sneel 67242275Sneel 68221828Sgrehan#define PAL_BASE (1ull << 63 | 0x1d030000) 69221828Sgrehan#define IXF_ADDR_HI (PAL_BASE + 0xa) 70261088Sjhb#define IXF_ADDR_LO (PAL_BASE + 0xb) 71261088Sjhb#define IXF_ADDR_16 IXF_ADDR_HI /* 16 bit access */ 72221828Sgrehan 73221828Sgrehan#define IXF_WR_DATA_HI (PAL_BASE + 0xc) 74221828Sgrehan#define IXF_WR_DATA_LO (PAL_BASE + 0xd) 75221828Sgrehan#define IXF_WR_DATA_16 IXF_WR_DATA_HI 76242065Sneel 77221828Sgrehan#define IXF_RD_DATA_HI (PAL_BASE + 0x10) 78221828Sgrehan#define IXF_RD_DATA_LO (PAL_BASE + 0x11) 79221828Sgrehan#define IXF_RD_DATA_16 IXF_RD_DATA_HI 80221828Sgrehan 81221828Sgrehan#define IXF_TRANS_TYPE (PAL_BASE + 0xe) 82221828Sgrehan#define IXF_TRANS_STATUS (PAL_BASE + 0xf) 83221828Sgrehan 84221828Sgrehan 85241489Sneeluint16_t cvmx_ixf18201_read16(uint16_t reg_addr) 86241489Sneel{ 87221828Sgrehan cvmx_write64_uint16(IXF_ADDR_16, reg_addr); 88221828Sgrehan cvmx_write64_uint8(IXF_TRANS_TYPE, 1); // Do read 89221828Sgrehan cvmx_wait(800000); 90221828Sgrehan 91234695Sgrehan /* Read result */ 92221828Sgrehan return(cvmx_read64_uint16(IXF_RD_DATA_16)); 93240894Sneel} 94240922Sneel 95241982Sneelvoid cvmx_ixf18201_write16(uint16_t reg_addr, uint16_t data) 96221828Sgrehan{ 97221828Sgrehan cvmx_write64_uint16(IXF_ADDR_16, reg_addr); 98242065Sneel cvmx_write64_uint16(IXF_WR_DATA_16, data); 99242065Sneel cvmx_write64_uint8(IXF_TRANS_TYPE, 0); 100242065Sneel cvmx_wait(800000); 101256072Sneel} 102241489Sneel 103256072Sneel 104256072Sneel 105256072Sneeluint32_t cvmx_ixf18201_read32(uint16_t reg_addr) 106256072Sneel{ 107256072Sneel uint32_t hi, lo; 108256072Sneel 109221828Sgrehan if (reg_addr & 0x1) 110221828Sgrehan { 111221828Sgrehan return(0xdeadbeef); 112221828Sgrehan } 113221828Sgrehan lo = cvmx_ixf18201_read16(reg_addr); 114261088Sjhb hi = cvmx_ixf18201_read16(reg_addr + 1); 115261088Sjhb return((hi << 16) | lo); 116256072Sneel} 117221828Sgrehanvoid cvmx_ixf18201_write32(uint16_t reg_addr, uint32_t data) 118221828Sgrehan{ 119256072Sneel uint16_t hi, lo; 120221828Sgrehan 121221828Sgrehan if (reg_addr & 0x1) 122221828Sgrehan { 123223621Sgrehan return; 124221828Sgrehan } 125221828Sgrehan lo = data & 0xFFFF; 126221828Sgrehan hi = data >> 16; 127266339Sjhb cvmx_ixf18201_write16(reg_addr, lo); 128266339Sjhb cvmx_ixf18201_write16(reg_addr + 1, hi); 129266339Sjhb 130266339Sjhb} 131266339Sjhb 132266339Sjhb 133266339Sjhb#define IXF_REG_MDI_CMD_ADDR1 0x310E 134221828Sgrehan#define IXF_REG_MDI_RD_WR1 0x3110 135221828Sgrehanvoid cvmx_ixf18201_mii_write(int mii_addr, int mmd, uint16_t reg, uint16_t val) 136249396Sneel{ 137249396Sneel uint32_t cmd_val = 0; 138221828Sgrehan 139266339Sjhb 140221828Sgrehan cmd_val = reg; 141261275Sjhb cmd_val |= 0x0 << 26; // Set address operation 142221828Sgrehan cmd_val |= (mii_addr & 0x1f) << 21; // Set PHY addr 143256072Sneel cmd_val |= (mmd & 0x1f) << 16; // Set MMD 144266339Sjhb cmd_val |= 1 << 30; // Do operation 145266339Sjhb cmd_val |= 1 << 31; // enable in progress bit 146221828Sgrehan 147256072Sneel 148256072Sneel 149256072Sneel /* Set up address */ 150256072Sneel cvmx_ixf18201_write32(IXF_REG_MDI_CMD_ADDR1, cmd_val); 151221828Sgrehan 152221828Sgrehan while (cvmx_ixf18201_read32(IXF_REG_MDI_CMD_ADDR1) & ( 1 << 30)) 153221828Sgrehan ; /* Wait for operation to complete */ 154221828Sgrehan 155221828Sgrehan 156221828Sgrehan cvmx_ixf18201_write32(IXF_REG_MDI_RD_WR1, val); 157221828Sgrehan 158221828Sgrehan /* Do read operation */ 159221828Sgrehan cmd_val = 0; 160221828Sgrehan cmd_val |= 0x1 << 26; // Set write operation 161221828Sgrehan cmd_val |= (mii_addr & 0x1f) << 21; // Set PHY addr 162221828Sgrehan cmd_val |= (mmd & 0x1f) << 16; // Set MMD 163221828Sgrehan cmd_val |= 1 << 30; // Do operation 164221828Sgrehan cmd_val |= 1 << 31; // enable in progress bit 165266339Sjhb cvmx_ixf18201_write32(IXF_REG_MDI_CMD_ADDR1, cmd_val); 166266339Sjhb 167266339Sjhb while (cvmx_ixf18201_read32(IXF_REG_MDI_CMD_ADDR1) & ( 1 << 30)) 168266339Sjhb ; /* Wait for operation to complete */ 169221828Sgrehan 170245021Sneel 171245021Sneel} 172221828Sgrehan 173221828Sgrehan 174221828Sgrehanint cvmx_ixf18201_mii_read(int mii_addr, int mmd, uint16_t reg) 175221828Sgrehan{ 176221828Sgrehan uint32_t cmd_val = 0; 177248389Sneel 178221828Sgrehan 179266339Sjhb cmd_val = reg; 180266339Sjhb cmd_val |= 0x0 << 26; // Set address operation 181266339Sjhb cmd_val |= (mii_addr & 0x1f) << 21; // Set PHY addr 182266339Sjhb cmd_val |= (mmd & 0x1f) << 16; // Set MMD 183266339Sjhb cmd_val |= 1 << 30; // Do operation 184266339Sjhb cmd_val |= 1 << 31; // enable in progress bit 185266339Sjhb 186266339Sjhb 187221828Sgrehan 188266339Sjhb /* Set up address */ 189221828Sgrehan cvmx_ixf18201_write32(IXF_REG_MDI_CMD_ADDR1, cmd_val); 190266339Sjhb 191266339Sjhb while (cvmx_ixf18201_read32(IXF_REG_MDI_CMD_ADDR1) & ( 1 << 30)) 192266339Sjhb ; /* Wait for operation to complete */ 193234695Sgrehan 194234695Sgrehan /* Do read operation */ 195221828Sgrehan cmd_val = 0; 196221828Sgrehan cmd_val |= 0x3 << 26; // Set read operation 197221828Sgrehan cmd_val |= (mii_addr & 0x1f) << 21; // Set PHY addr 198221828Sgrehan cmd_val |= (mmd & 0x1f) << 16; // Set MMD 199221828Sgrehan cmd_val |= 1 << 30; // Do operation 200221828Sgrehan cmd_val |= 1 << 31; // enable in progress bit 201221828Sgrehan cvmx_ixf18201_write32(IXF_REG_MDI_CMD_ADDR1, cmd_val); 202221828Sgrehan 203221828Sgrehan while (cvmx_ixf18201_read32(IXF_REG_MDI_CMD_ADDR1) & ( 1 << 30)) 204241489Sneel ; /* Wait for operation to complete */ 205241489Sneel 206221828Sgrehan cmd_val = cvmx_ixf18201_read32(IXF_REG_MDI_RD_WR1); 207266339Sjhb 208240943Sneel return(cmd_val >> 16); 209234695Sgrehan 210234695Sgrehan} 211221828Sgrehan 212221828Sgrehan 213221828Sgrehan 214240894Sneelint cvmx_ixf18201_init(void) 215240894Sneel{ 216240894Sneel int index; /* For indexing the two 'ports' on ixf */ 217240894Sneel int offset; 218240894Sneel 219240894Sneel /* Reset IXF, and take all blocks out of reset */ 220240894Sneel 221240894Sneel/* 222240894SneelInitializing... 223240894SneelPP0:~CONSOLE-> Changing register value, addr 0x0003, old: 0x0000, new: 0x0001 224240894SneelPP0:~CONSOLE-> Changing register value, addr 0x0003, old: 0x0001, new: 0x0000 225240894SneelPP0:~CONSOLE-> **** LLM201(Lochlomond) Driver loaded **** 226240894SneelPP0:~CONSOLE-> LLM201 Driver - Released on Tue Aug 28 09:51:30 2007. 227261275SjhbPP0:~CONSOLE-> retval is: 0 228261275SjhbPP0:~CONSOLE-> Changing register value, addr 0x0003, old: 0x0000, new: 0x0001 229261275SjhbPP0:~CONSOLE-> Changing register value, addr 0x0003, old: 0x0001, new: 0x0000 230261275SjhbPP0:~CONSOLE-> Brought all blocks out of reset 231261275SjhbPP0:~CONSOLE-> Getting default config. 232261275Sjhb*/ 233221828Sgrehan 234221828Sgrehan 235221828Sgrehan cvmx_ixf18201_write16(0x0003, 0x0001); 236221828Sgrehan cvmx_ixf18201_write16(0x0003, 0); 237221828Sgrehan 238242275Sneel /* 239221828SgrehanPP0:~CONSOLE-> Changing register value, addr 0x0000, old: 0x4014, new: 0x4010 240266339SjhbPP0:~CONSOLE-> Changing register value, addr 0x0000, old: 0x4010, new: 0x4014 241266339SjhbPP0:~CONSOLE-> Changing register value, addr 0x0004, old: 0x01ff, new: 0x0140 242266339SjhbPP0:~CONSOLE-> Changing register value, addr 0x0009, old: 0x007f, new: 0x0000 243266339Sjhb */ 244221828Sgrehan cvmx_ixf18201_write16(0x0000, 0x4010); 245221828Sgrehan cvmx_ixf18201_write16(0x0000, 0x4014); 246221828Sgrehan cvmx_ixf18201_write16(0x0004, 0x0140); 247221828Sgrehan cvmx_ixf18201_write16(0x0009, 0); 248221828Sgrehan 249221828Sgrehan 250221828Sgrehan /* 251221828SgrehanPP0:~CONSOLE-> Changing register value, addr 0x000e, old: 0x0000, new: 0x000f 252221828SgrehanPP0:~CONSOLE-> Changing register value, addr 0x000f, old: 0x0000, new: 0x0004 253221828SgrehanPP0:~CONSOLE-> Changing register value, addr 0x000f, old: 0x0004, new: 0x0006 254221828SgrehanPP0:~CONSOLE-> Changing register value, addr 0x000e, old: 0x000f, new: 0x00f0 255221828SgrehanPP0:~CONSOLE-> Changing register value, addr 0x000f, old: 0x0006, new: 0x0040 256261275SjhbPP0:~CONSOLE-> Changing register value, addr 0x000f, old: 0x0040, new: 0x0060 257221828Sgrehan */ 258266339Sjhb // skip GPIO, 0xe/0xf 259221828Sgrehan 260221828Sgrehan 261221828Sgrehan /* 262221828SgrehanPP0:~CONSOLE-> Changing register value, addr 0x3100, old: 0x57fb, new: 0x7f7b 263221828SgrehanPP0:~CONSOLE-> Changing register value, addr 0x3600, old: 0x57fb, new: 0x7f7b 264221828SgrehanPP0:~CONSOLE-> Changing register value, addr 0x3005, old: 0x8010, new: 0x0040 265221828SgrehanPP0:~CONSOLE-> Changing register value, addr 0x3006, old: 0x061a, new: 0x0000 266221828SgrehanPP0:~CONSOLE-> Changing register value, addr 0x3505, old: 0x8010, new: 0x0040 267221828SgrehanPP0:~CONSOLE-> Changing register value, addr 0x3506, old: 0x061a, new: 0x0000 268221828Sgrehan */ 269256072Sneel for (index = 0; index < 2;index++ ) 270221828Sgrehan { 271249396Sneel offset = 0x500 * index; 272249396Sneel cvmx_ixf18201_write32(0x3100 + offset, 0x47f7b); 273221828Sgrehan cvmx_ixf18201_write16(0x3005 + offset, 0x0040); 274221828Sgrehan cvmx_ixf18201_write16(0x3006 + offset, 0); 275241454Sneel } 276241454Sneel 277261275Sjhb /*PP0:~CONSOLE-> *** SPI soft reset ***, block id: 0 278241454SneelPP0:~CONSOLE-> Changing register value, addr 0x3007, old: 0xf980, new: 0xf9c0 279266339SjhbPP0:~CONSOLE-> Changing register value, addr 0x3008, old: 0xa6f0, new: 0x36f0 280266339SjhbPP0:~CONSOLE-> Changing register value, addr 0x3000, old: 0x0080, new: 0x0060 281241454SneelPP0:~CONSOLE-> Changing register value, addr 0x3002, old: 0x0200, new: 0x0040 282253854SgrehanPP0:~CONSOLE-> Changing register value, addr 0x3003, old: 0x0100, new: 0x0000 283253854SgrehanPP0:~CONSOLE-> Changing register value, addr 0x30c2, old: 0x0080, new: 0x0060 284253854SgrehanPP0:~CONSOLE-> Changing register value, addr 0x300a, old: 0x0800, new: 0x0000 285253854SgrehanPP0:~CONSOLE-> Changing register value, addr 0x3007, old: 0xf9c0, new: 0x89c0 286253854SgrehanPP0:~CONSOLE-> Changing register value, addr 0x3016, old: 0x0000, new: 0x0010 287253854SgrehanPP0:~CONSOLE-> Changing register value, addr 0x3008, old: 0x36f0, new: 0x3610 288241454SneelPP0:~CONSOLE-> Changing register value, addr 0x3012, old: 0x0000, new: 0x0010 289221828SgrehanPP0:~CONSOLE-> Changing register value, addr 0x3007, old: 0x89c0, new: 0x8980 290221828SgrehanPP0:~CONSOLE-> Changing register value, addr 0x3008, old: 0x3610, new: 0xa210 291221828SgrehanPP0:~CONSOLE-> 292221828Sgrehan 293221828Sgrehan */ 294221828Sgrehan 295221828Sgrehan 296221828Sgrehan for (index = 0; index < 2;index++ ) 297221828Sgrehan { 298221828Sgrehan offset = 0x500 * index; 299221828Sgrehan int cal_len_min_1 = 0; /* Calendar length -1. Must match number 300221828Sgrehan ** of ports configured for interface.*/ 301221828Sgrehan cvmx_ixf18201_write16(0x3007 + offset, 0x81c0 | (cal_len_min_1 << 11)); 302221828Sgrehan cvmx_ixf18201_write16(0x3008 + offset, 0x3600 | (cal_len_min_1 << 4)); 303221828Sgrehan cvmx_ixf18201_write16(0x3000 + offset, 0x0060); 304245704Sneel cvmx_ixf18201_write16(0x3002 + offset, 0x0040); 305245704Sneel cvmx_ixf18201_write16(0x3003 + offset, 0x0000); 306245704Sneel cvmx_ixf18201_write16(0x30c2 + offset, 0x0060); 307245704Sneel cvmx_ixf18201_write16(0x300a + offset, 0x0000); 308245704Sneel cvmx_ixf18201_write16(0x3007 + offset, 0x81c0 | (cal_len_min_1 << 11)); 309245704Sneel cvmx_ixf18201_write16(0x3016 + offset, 0x0010); 310245704Sneel cvmx_ixf18201_write16(0x3008 + offset, 0x3600 | (cal_len_min_1 << 4)); 311221828Sgrehan cvmx_ixf18201_write16(0x3012 + offset, 0x0010); 312245704Sneel cvmx_ixf18201_write16(0x3007 + offset, 0x8180 | (cal_len_min_1 << 11)); 313221828Sgrehan cvmx_ixf18201_write16(0x3008 + offset, 0xa200 | (cal_len_min_1 << 4)); 314221828Sgrehan 315249396Sneel cvmx_ixf18201_write16(0x3090 + offset, 0x0301); /* Enable hairpin loopback */ 316249396Sneel } 317221828Sgrehan 318221828Sgrehan 319221828Sgrehan 320256072Sneel /* 321221828SgrehanPP0:~CONSOLE-> Changing register value, addr 0x0004, old: 0x0140, new: 0x1fff 322221828SgrehanPP0:~CONSOLE-> Changing register value, addr 0x0009, old: 0x0000, new: 0x007f 323221828SgrehanPP0:~CONSOLE-> Changing register value, addr 0x310b, old: 0x0004, new: 0xffff 324249396SneelPP0:~CONSOLE-> Changing register value, addr 0x310a, old: 0x7f7b, new: 0xffff 325249396Sneel 326249396Sneel */ 327249396Sneel 328249396Sneel cvmx_ixf18201_write16(0x0004, 0x1fff); 329249396Sneel cvmx_ixf18201_write16(0x0009, 0x007f); 330249396Sneel#if 0 331221828Sgrehan /* MDI autoscan */ 332249396Sneel cvmx_ixf18201_write16(0x310b, 0xffff); 333221828Sgrehan cvmx_ixf18201_write16(0x310a, 0xffff); 334256072Sneel#endif 335256072Sneel 336256072Sneel 337256072Sneel /* 338221828Sgrehan *** 32 bit register, trace only captures part of it... 339221828SgrehanPP0:~CONSOLE-> Changing register value, addr 0x3100, old: 0x7f7b, new: 0x7f78 340266339SjhbPP0:~CONSOLE-> Changing register value, addr 0x3600, old: 0x7f7b, new: 0x7f78 341266339Sjhb */ 342256072Sneel 343261088Sjhb for (index = 0; index < 2;index++ ) 344261088Sjhb { 345221828Sgrehan offset = 0x500 * index; 346221828Sgrehan cvmx_ixf18201_write32(0x3100 + offset, 0x47f7c); /* Also enable jumbo frames */ 347221828Sgrehan /* Set max packet size to 9600 bytes, max supported by IXF18201 */ 348221828Sgrehan cvmx_ixf18201_write32(0x3114 + offset, 0x25800000); 349221828Sgrehan } 350221828Sgrehan 351221828Sgrehan 352221828Sgrehan cvmx_wait(100000000); 353249396Sneel 354249396Sneel /* Now reset the PCS blocks in the phy. This seems to be required after 355221828Sgrehan ** bringing up the Cortina. */ 356221828Sgrehan cvmx_ixf18201_mii_write(1, 3, 0, 0x8000); 357241178Sneel cvmx_ixf18201_mii_write(5, 3, 0, 0x8000); 358256072Sneel 359241178Sneel 360241178Sneel return 1; 361256072Sneel 362256072Sneel} 363241362Sneel