1215976Sjmallett/***********************license start*************** 2232812Sjmallett * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3215976Sjmallett * reserved. 4215976Sjmallett * 5215976Sjmallett * 6215976Sjmallett * Redistribution and use in source and binary forms, with or without 7215976Sjmallett * modification, are permitted provided that the following conditions are 8215976Sjmallett * met: 9215976Sjmallett * 10215976Sjmallett * * Redistributions of source code must retain the above copyright 11215976Sjmallett * notice, this list of conditions and the following disclaimer. 12215976Sjmallett * 13215976Sjmallett * * Redistributions in binary form must reproduce the above 14215976Sjmallett * copyright notice, this list of conditions and the following 15215976Sjmallett * disclaimer in the documentation and/or other materials provided 16215976Sjmallett * with the distribution. 17215976Sjmallett 18232812Sjmallett * * Neither the name of Cavium Inc. nor the names of 19215976Sjmallett * its contributors may be used to endorse or promote products 20215976Sjmallett * derived from this software without specific prior written 21215976Sjmallett * permission. 22215976Sjmallett 23215976Sjmallett * This Software, including technical data, may be subject to U.S. export control 24215976Sjmallett * laws, including the U.S. Export Administration Act and its associated 25215976Sjmallett * regulations, and may be subject to export or import regulations in other 26215976Sjmallett * countries. 27215976Sjmallett 28215976Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29232812Sjmallett * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30215976Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31215976Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32215976Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33215976Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34215976Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35215976Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36215976Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37215976Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38215976Sjmallett ***********************license end**************************************/ 39215976Sjmallett 40215976Sjmallett 41215976Sjmallett 42215976Sjmallett 43215976Sjmallett 44215976Sjmallett/* This file contains support functions for the Cortina IXF18201 SPI->XAUI dual 45215976Sjmallett** MAC. The IXF18201 has dual SPI and dual XAUI interfaces to provide 2 10 gigabit 46215976Sjmallett** interfaces. 47215976Sjmallett** This file supports the EBT5810 evaluation board. To support a different board, 48215976Sjmallett** the 16 bit read/write functions would need to be customized for that board, and the 49215976Sjmallett** IXF18201 may need to be initialized differently as well. 50215976Sjmallett** 51215976Sjmallett** The IXF18201 and Octeon are configured for 2 SPI channels per interface (ports 0/1, and 16/17). 52215976Sjmallett** Ports 0 and 16 are the ports that are connected to the XAUI MACs (which are connected to the SFP+ modules) 53215976Sjmallett** Ports 1 and 17 are connected to the hairpin loopback port on the IXF SPI interface. All packets sent out 54215976Sjmallett** of these ports are looped back the same port they were sent on. The loopback ports are always enabled. 55215976Sjmallett** 56215976Sjmallett** The MAC address filtering on the IXF is not enabled. Link up/down events are not detected, only SPI status 57215976Sjmallett** is monitored by default, which is independent of the XAUI/SFP+ link status. 58215976Sjmallett** 59215976Sjmallett** 60215976Sjmallett*/ 61215976Sjmallett#include "cvmx.h" 62215976Sjmallett#include "cvmx-swap.h" 63215976Sjmallett 64215976Sjmallett 65215976Sjmallett 66215976Sjmallett 67215976Sjmallett 68215976Sjmallett#define PAL_BASE (1ull << 63 | 0x1d030000) 69215976Sjmallett#define IXF_ADDR_HI (PAL_BASE + 0xa) 70215976Sjmallett#define IXF_ADDR_LO (PAL_BASE + 0xb) 71215976Sjmallett#define IXF_ADDR_16 IXF_ADDR_HI /* 16 bit access */ 72215976Sjmallett 73215976Sjmallett#define IXF_WR_DATA_HI (PAL_BASE + 0xc) 74215976Sjmallett#define IXF_WR_DATA_LO (PAL_BASE + 0xd) 75215976Sjmallett#define IXF_WR_DATA_16 IXF_WR_DATA_HI 76215976Sjmallett 77215976Sjmallett#define IXF_RD_DATA_HI (PAL_BASE + 0x10) 78215976Sjmallett#define IXF_RD_DATA_LO (PAL_BASE + 0x11) 79215976Sjmallett#define IXF_RD_DATA_16 IXF_RD_DATA_HI 80215976Sjmallett 81215976Sjmallett#define IXF_TRANS_TYPE (PAL_BASE + 0xe) 82215976Sjmallett#define IXF_TRANS_STATUS (PAL_BASE + 0xf) 83215976Sjmallett 84215976Sjmallett 85215976Sjmallettuint16_t cvmx_ixf18201_read16(uint16_t reg_addr) 86215976Sjmallett{ 87215976Sjmallett cvmx_write64_uint16(IXF_ADDR_16, reg_addr); 88215976Sjmallett cvmx_write64_uint8(IXF_TRANS_TYPE, 1); // Do read 89215976Sjmallett cvmx_wait(800000); 90215976Sjmallett 91215976Sjmallett /* Read result */ 92215976Sjmallett return(cvmx_read64_uint16(IXF_RD_DATA_16)); 93215976Sjmallett} 94215976Sjmallett 95215976Sjmallettvoid cvmx_ixf18201_write16(uint16_t reg_addr, uint16_t data) 96215976Sjmallett{ 97215976Sjmallett cvmx_write64_uint16(IXF_ADDR_16, reg_addr); 98215976Sjmallett cvmx_write64_uint16(IXF_WR_DATA_16, data); 99215976Sjmallett cvmx_write64_uint8(IXF_TRANS_TYPE, 0); 100215976Sjmallett cvmx_wait(800000); 101215976Sjmallett} 102215976Sjmallett 103215976Sjmallett 104215976Sjmallett 105215976Sjmallettuint32_t cvmx_ixf18201_read32(uint16_t reg_addr) 106215976Sjmallett{ 107215976Sjmallett uint32_t hi, lo; 108215976Sjmallett 109215976Sjmallett if (reg_addr & 0x1) 110215976Sjmallett { 111215976Sjmallett return(0xdeadbeef); 112215976Sjmallett } 113215976Sjmallett lo = cvmx_ixf18201_read16(reg_addr); 114215976Sjmallett hi = cvmx_ixf18201_read16(reg_addr + 1); 115215976Sjmallett return((hi << 16) | lo); 116215976Sjmallett} 117215976Sjmallettvoid cvmx_ixf18201_write32(uint16_t reg_addr, uint32_t data) 118215976Sjmallett{ 119215976Sjmallett uint16_t hi, lo; 120215976Sjmallett 121215976Sjmallett if (reg_addr & 0x1) 122215976Sjmallett { 123215976Sjmallett return; 124215976Sjmallett } 125215976Sjmallett lo = data & 0xFFFF; 126215976Sjmallett hi = data >> 16; 127215976Sjmallett cvmx_ixf18201_write16(reg_addr, lo); 128215976Sjmallett cvmx_ixf18201_write16(reg_addr + 1, hi); 129215976Sjmallett 130215976Sjmallett} 131215976Sjmallett 132215976Sjmallett 133215976Sjmallett#define IXF_REG_MDI_CMD_ADDR1 0x310E 134215976Sjmallett#define IXF_REG_MDI_RD_WR1 0x3110 135215976Sjmallettvoid cvmx_ixf18201_mii_write(int mii_addr, int mmd, uint16_t reg, uint16_t val) 136215976Sjmallett{ 137215976Sjmallett uint32_t cmd_val = 0; 138215976Sjmallett 139215976Sjmallett 140215976Sjmallett cmd_val = reg; 141215976Sjmallett cmd_val |= 0x0 << 26; // Set address operation 142215976Sjmallett cmd_val |= (mii_addr & 0x1f) << 21; // Set PHY addr 143215976Sjmallett cmd_val |= (mmd & 0x1f) << 16; // Set MMD 144215976Sjmallett cmd_val |= 1 << 30; // Do operation 145215976Sjmallett cmd_val |= 1 << 31; // enable in progress bit 146215976Sjmallett 147215976Sjmallett 148215976Sjmallett 149215976Sjmallett /* Set up address */ 150215976Sjmallett cvmx_ixf18201_write32(IXF_REG_MDI_CMD_ADDR1, cmd_val); 151215976Sjmallett 152215976Sjmallett while (cvmx_ixf18201_read32(IXF_REG_MDI_CMD_ADDR1) & ( 1 << 30)) 153215976Sjmallett ; /* Wait for operation to complete */ 154215976Sjmallett 155215976Sjmallett 156215976Sjmallett cvmx_ixf18201_write32(IXF_REG_MDI_RD_WR1, val); 157215976Sjmallett 158215976Sjmallett /* Do read operation */ 159215976Sjmallett cmd_val = 0; 160215976Sjmallett cmd_val |= 0x1 << 26; // Set write operation 161215976Sjmallett cmd_val |= (mii_addr & 0x1f) << 21; // Set PHY addr 162215976Sjmallett cmd_val |= (mmd & 0x1f) << 16; // Set MMD 163215976Sjmallett cmd_val |= 1 << 30; // Do operation 164215976Sjmallett cmd_val |= 1 << 31; // enable in progress bit 165215976Sjmallett cvmx_ixf18201_write32(IXF_REG_MDI_CMD_ADDR1, cmd_val); 166215976Sjmallett 167215976Sjmallett while (cvmx_ixf18201_read32(IXF_REG_MDI_CMD_ADDR1) & ( 1 << 30)) 168215976Sjmallett ; /* Wait for operation to complete */ 169215976Sjmallett 170215976Sjmallett 171215976Sjmallett} 172215976Sjmallett 173215976Sjmallett 174215976Sjmallettint cvmx_ixf18201_mii_read(int mii_addr, int mmd, uint16_t reg) 175215976Sjmallett{ 176215976Sjmallett uint32_t cmd_val = 0; 177215976Sjmallett 178215976Sjmallett 179215976Sjmallett cmd_val = reg; 180215976Sjmallett cmd_val |= 0x0 << 26; // Set address operation 181215976Sjmallett cmd_val |= (mii_addr & 0x1f) << 21; // Set PHY addr 182215976Sjmallett cmd_val |= (mmd & 0x1f) << 16; // Set MMD 183215976Sjmallett cmd_val |= 1 << 30; // Do operation 184215976Sjmallett cmd_val |= 1 << 31; // enable in progress bit 185215976Sjmallett 186215976Sjmallett 187215976Sjmallett 188215976Sjmallett /* Set up address */ 189215976Sjmallett cvmx_ixf18201_write32(IXF_REG_MDI_CMD_ADDR1, cmd_val); 190215976Sjmallett 191215976Sjmallett while (cvmx_ixf18201_read32(IXF_REG_MDI_CMD_ADDR1) & ( 1 << 30)) 192215976Sjmallett ; /* Wait for operation to complete */ 193215976Sjmallett 194215976Sjmallett /* Do read operation */ 195215976Sjmallett cmd_val = 0; 196215976Sjmallett cmd_val |= 0x3 << 26; // Set read operation 197215976Sjmallett cmd_val |= (mii_addr & 0x1f) << 21; // Set PHY addr 198215976Sjmallett cmd_val |= (mmd & 0x1f) << 16; // Set MMD 199215976Sjmallett cmd_val |= 1 << 30; // Do operation 200215976Sjmallett cmd_val |= 1 << 31; // enable in progress bit 201215976Sjmallett cvmx_ixf18201_write32(IXF_REG_MDI_CMD_ADDR1, cmd_val); 202215976Sjmallett 203215976Sjmallett while (cvmx_ixf18201_read32(IXF_REG_MDI_CMD_ADDR1) & ( 1 << 30)) 204215976Sjmallett ; /* Wait for operation to complete */ 205215976Sjmallett 206215976Sjmallett cmd_val = cvmx_ixf18201_read32(IXF_REG_MDI_RD_WR1); 207215976Sjmallett 208215976Sjmallett return(cmd_val >> 16); 209215976Sjmallett 210215976Sjmallett} 211215976Sjmallett 212215976Sjmallett 213215976Sjmallett 214215976Sjmallettint cvmx_ixf18201_init(void) 215215976Sjmallett{ 216215976Sjmallett int index; /* For indexing the two 'ports' on ixf */ 217215976Sjmallett int offset; 218215976Sjmallett 219215976Sjmallett /* Reset IXF, and take all blocks out of reset */ 220215976Sjmallett 221215976Sjmallett/* 222215976SjmallettInitializing... 223215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x0003, old: 0x0000, new: 0x0001 224215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x0003, old: 0x0001, new: 0x0000 225215976SjmallettPP0:~CONSOLE-> **** LLM201(Lochlomond) Driver loaded **** 226215976SjmallettPP0:~CONSOLE-> LLM201 Driver - Released on Tue Aug 28 09:51:30 2007. 227215976SjmallettPP0:~CONSOLE-> retval is: 0 228215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x0003, old: 0x0000, new: 0x0001 229215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x0003, old: 0x0001, new: 0x0000 230215976SjmallettPP0:~CONSOLE-> Brought all blocks out of reset 231215976SjmallettPP0:~CONSOLE-> Getting default config. 232215976Sjmallett*/ 233215976Sjmallett 234215976Sjmallett 235215976Sjmallett cvmx_ixf18201_write16(0x0003, 0x0001); 236215976Sjmallett cvmx_ixf18201_write16(0x0003, 0); 237215976Sjmallett 238215976Sjmallett /* 239215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x0000, old: 0x4014, new: 0x4010 240215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x0000, old: 0x4010, new: 0x4014 241215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x0004, old: 0x01ff, new: 0x0140 242215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x0009, old: 0x007f, new: 0x0000 243215976Sjmallett */ 244215976Sjmallett cvmx_ixf18201_write16(0x0000, 0x4010); 245215976Sjmallett cvmx_ixf18201_write16(0x0000, 0x4014); 246215976Sjmallett cvmx_ixf18201_write16(0x0004, 0x0140); 247215976Sjmallett cvmx_ixf18201_write16(0x0009, 0); 248215976Sjmallett 249215976Sjmallett 250215976Sjmallett /* 251215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x000e, old: 0x0000, new: 0x000f 252215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x000f, old: 0x0000, new: 0x0004 253215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x000f, old: 0x0004, new: 0x0006 254215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x000e, old: 0x000f, new: 0x00f0 255215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x000f, old: 0x0006, new: 0x0040 256215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x000f, old: 0x0040, new: 0x0060 257215976Sjmallett */ 258215976Sjmallett // skip GPIO, 0xe/0xf 259215976Sjmallett 260215976Sjmallett 261215976Sjmallett /* 262215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x3100, old: 0x57fb, new: 0x7f7b 263215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x3600, old: 0x57fb, new: 0x7f7b 264215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x3005, old: 0x8010, new: 0x0040 265215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x3006, old: 0x061a, new: 0x0000 266215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x3505, old: 0x8010, new: 0x0040 267215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x3506, old: 0x061a, new: 0x0000 268215976Sjmallett */ 269215976Sjmallett for (index = 0; index < 2;index++ ) 270215976Sjmallett { 271215976Sjmallett offset = 0x500 * index; 272215976Sjmallett cvmx_ixf18201_write32(0x3100 + offset, 0x47f7b); 273215976Sjmallett cvmx_ixf18201_write16(0x3005 + offset, 0x0040); 274215976Sjmallett cvmx_ixf18201_write16(0x3006 + offset, 0); 275215976Sjmallett } 276215976Sjmallett 277215976Sjmallett /*PP0:~CONSOLE-> *** SPI soft reset ***, block id: 0 278215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x3007, old: 0xf980, new: 0xf9c0 279215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x3008, old: 0xa6f0, new: 0x36f0 280215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x3000, old: 0x0080, new: 0x0060 281215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x3002, old: 0x0200, new: 0x0040 282215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x3003, old: 0x0100, new: 0x0000 283215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x30c2, old: 0x0080, new: 0x0060 284215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x300a, old: 0x0800, new: 0x0000 285215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x3007, old: 0xf9c0, new: 0x89c0 286215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x3016, old: 0x0000, new: 0x0010 287215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x3008, old: 0x36f0, new: 0x3610 288215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x3012, old: 0x0000, new: 0x0010 289215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x3007, old: 0x89c0, new: 0x8980 290215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x3008, old: 0x3610, new: 0xa210 291215976SjmallettPP0:~CONSOLE-> 292215976Sjmallett 293215976Sjmallett */ 294215976Sjmallett 295215976Sjmallett 296215976Sjmallett for (index = 0; index < 2;index++ ) 297215976Sjmallett { 298215976Sjmallett offset = 0x500 * index; 299215976Sjmallett int cal_len_min_1 = 0; /* Calendar length -1. Must match number 300215976Sjmallett ** of ports configured for interface.*/ 301215976Sjmallett cvmx_ixf18201_write16(0x3007 + offset, 0x81c0 | (cal_len_min_1 << 11)); 302215976Sjmallett cvmx_ixf18201_write16(0x3008 + offset, 0x3600 | (cal_len_min_1 << 4)); 303215976Sjmallett cvmx_ixf18201_write16(0x3000 + offset, 0x0060); 304215976Sjmallett cvmx_ixf18201_write16(0x3002 + offset, 0x0040); 305215976Sjmallett cvmx_ixf18201_write16(0x3003 + offset, 0x0000); 306215976Sjmallett cvmx_ixf18201_write16(0x30c2 + offset, 0x0060); 307215976Sjmallett cvmx_ixf18201_write16(0x300a + offset, 0x0000); 308215976Sjmallett cvmx_ixf18201_write16(0x3007 + offset, 0x81c0 | (cal_len_min_1 << 11)); 309215976Sjmallett cvmx_ixf18201_write16(0x3016 + offset, 0x0010); 310215976Sjmallett cvmx_ixf18201_write16(0x3008 + offset, 0x3600 | (cal_len_min_1 << 4)); 311215976Sjmallett cvmx_ixf18201_write16(0x3012 + offset, 0x0010); 312215976Sjmallett cvmx_ixf18201_write16(0x3007 + offset, 0x8180 | (cal_len_min_1 << 11)); 313215976Sjmallett cvmx_ixf18201_write16(0x3008 + offset, 0xa200 | (cal_len_min_1 << 4)); 314215976Sjmallett 315215976Sjmallett cvmx_ixf18201_write16(0x3090 + offset, 0x0301); /* Enable hairpin loopback */ 316215976Sjmallett } 317215976Sjmallett 318215976Sjmallett 319215976Sjmallett 320215976Sjmallett /* 321215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x0004, old: 0x0140, new: 0x1fff 322215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x0009, old: 0x0000, new: 0x007f 323215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x310b, old: 0x0004, new: 0xffff 324215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x310a, old: 0x7f7b, new: 0xffff 325215976Sjmallett 326215976Sjmallett */ 327215976Sjmallett 328215976Sjmallett cvmx_ixf18201_write16(0x0004, 0x1fff); 329215976Sjmallett cvmx_ixf18201_write16(0x0009, 0x007f); 330215976Sjmallett#if 0 331215976Sjmallett /* MDI autoscan */ 332215976Sjmallett cvmx_ixf18201_write16(0x310b, 0xffff); 333215976Sjmallett cvmx_ixf18201_write16(0x310a, 0xffff); 334215976Sjmallett#endif 335215976Sjmallett 336215976Sjmallett 337215976Sjmallett /* 338215976Sjmallett *** 32 bit register, trace only captures part of it... 339215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x3100, old: 0x7f7b, new: 0x7f78 340215976SjmallettPP0:~CONSOLE-> Changing register value, addr 0x3600, old: 0x7f7b, new: 0x7f78 341215976Sjmallett */ 342215976Sjmallett 343215976Sjmallett for (index = 0; index < 2;index++ ) 344215976Sjmallett { 345215976Sjmallett offset = 0x500 * index; 346215976Sjmallett cvmx_ixf18201_write32(0x3100 + offset, 0x47f7c); /* Also enable jumbo frames */ 347215976Sjmallett /* Set max packet size to 9600 bytes, max supported by IXF18201 */ 348215976Sjmallett cvmx_ixf18201_write32(0x3114 + offset, 0x25800000); 349215976Sjmallett } 350215976Sjmallett 351215976Sjmallett 352215976Sjmallett cvmx_wait(100000000); 353215976Sjmallett 354215976Sjmallett /* Now reset the PCS blocks in the phy. This seems to be required after 355215976Sjmallett ** bringing up the Cortina. */ 356215976Sjmallett cvmx_ixf18201_mii_write(1, 3, 0, 0x8000); 357215976Sjmallett cvmx_ixf18201_mii_write(5, 3, 0, 0x8000); 358215976Sjmallett 359215976Sjmallett 360215976Sjmallett return 1; 361215976Sjmallett 362215976Sjmallett} 363