1210284Sjmallett/***********************license start*************** 2232812Sjmallett * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3215990Sjmallett * reserved. 4210284Sjmallett * 5210284Sjmallett * 6215990Sjmallett * Redistribution and use in source and binary forms, with or without 7215990Sjmallett * modification, are permitted provided that the following conditions are 8215990Sjmallett * met: 9210284Sjmallett * 10215990Sjmallett * * Redistributions of source code must retain the above copyright 11215990Sjmallett * notice, this list of conditions and the following disclaimer. 12210284Sjmallett * 13215990Sjmallett * * Redistributions in binary form must reproduce the above 14215990Sjmallett * copyright notice, this list of conditions and the following 15215990Sjmallett * disclaimer in the documentation and/or other materials provided 16215990Sjmallett * with the distribution. 17215990Sjmallett 18232812Sjmallett * * Neither the name of Cavium Inc. nor the names of 19215990Sjmallett * its contributors may be used to endorse or promote products 20215990Sjmallett * derived from this software without specific prior written 21215990Sjmallett * permission. 22215990Sjmallett 23215990Sjmallett * This Software, including technical data, may be subject to U.S. export control 24215990Sjmallett * laws, including the U.S. Export Administration Act and its associated 25215990Sjmallett * regulations, and may be subject to export or import regulations in other 26215990Sjmallett * countries. 27215990Sjmallett 28215990Sjmallett * 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 30215990Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31215990Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32215990Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33215990Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34215990Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35215990Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36215990Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37215990Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38210284Sjmallett ***********************license end**************************************/ 39210284Sjmallett 40210284Sjmallett 41210284Sjmallett 42210284Sjmallett 43210284Sjmallett 44210284Sjmallett 45215990Sjmallett 46210284Sjmallett/** 47210284Sjmallett * @file 48210284Sjmallett * 49210284Sjmallett * Interface to the Thunder specific devices 50210284Sjmallett * 51232812Sjmallett * <hr>$Revision: 70030 $<hr> 52210284Sjmallett * 53210284Sjmallett */ 54210284Sjmallett 55210284Sjmallett#include "cvmx.h" 56210284Sjmallett#include "cvmx-sysinfo.h" 57210284Sjmallett#include "cvmx-thunder.h" 58210284Sjmallett#include "cvmx-gpio.h" 59210284Sjmallett#include "cvmx-twsi.h" 60210284Sjmallett 61210284Sjmallett 62210284Sjmallettstatic const int BYPASS_STATUS = 1<<5; /* GPIO 5 */ 63210284Sjmallettstatic const int BYPASS_EN = 1<<6; /* GPIO 6 */ 64210284Sjmallettstatic const int WDT_BP_CLR = 1<<7; /* GPIO 7 */ 65210284Sjmallett 66210284Sjmallettstatic const int RTC_CTL_ADDR = 0x7; 67210284Sjmallettstatic const int RTC_CTL_BIT_EOSC = 0x80; 68210284Sjmallettstatic const int RTC_CTL_BIT_WACE = 0x40; 69210284Sjmallettstatic const int RTC_CTL_BIT_WD_ALM = 0x20; 70210284Sjmallettstatic const int RTC_CTL_BIT_WDSTR = 0x8; 71210284Sjmallettstatic const int RTC_CTL_BIT_AIE = 0x1; 72210284Sjmallettstatic const int RTC_WD_ALM_CNT_BYTE0_ADDR = 0x4; 73210284Sjmallett 74210284Sjmallett#define CVMX_LAN_BYPASS_MSG(...) do {} while(0) 75210284Sjmallett 76210284Sjmallett/* 77210284Sjmallett * Board-specifc RTC read 78210284Sjmallett * Time is expressed in seconds from epoch (Jan 1 1970 at 00:00:00 UTC) 79210284Sjmallett */ 80210284Sjmallettuint32_t cvmx_rtc_ds1374_read(void) 81210284Sjmallett{ 82210284Sjmallett int retry; 83210284Sjmallett uint8_t sec; 84210284Sjmallett uint32_t time; 85210284Sjmallett 86210284Sjmallett for(retry=0; retry<2; retry++) 87210284Sjmallett { 88210284Sjmallett time = cvmx_twsi_read8(CVMX_RTC_DS1374_ADDR, 0x0); 89210284Sjmallett time |= (cvmx_twsi_read8_cur_addr(CVMX_RTC_DS1374_ADDR) & 0xff) << 8; 90210284Sjmallett time |= (cvmx_twsi_read8_cur_addr(CVMX_RTC_DS1374_ADDR) & 0xff) << 16; 91210284Sjmallett time |= (cvmx_twsi_read8_cur_addr(CVMX_RTC_DS1374_ADDR) & 0xff) << 24; 92210284Sjmallett 93210284Sjmallett sec = cvmx_twsi_read8(CVMX_RTC_DS1374_ADDR, 0x0); 94210284Sjmallett if (sec == (time & 0xff)) 95210284Sjmallett break; /* Time did not roll-over, value is correct */ 96210284Sjmallett } 97210284Sjmallett 98210284Sjmallett return time; 99210284Sjmallett} 100210284Sjmallett 101210284Sjmallett/* 102210284Sjmallett * Board-specific RTC write 103210284Sjmallett * Time is expressed in seconds from epoch (Jan 1 1970 at 00:00:00 UTC) 104210284Sjmallett */ 105210284Sjmallettint cvmx_rtc_ds1374_write(uint32_t time) 106210284Sjmallett{ 107210284Sjmallett int rc; 108210284Sjmallett int retry; 109210284Sjmallett uint8_t sec; 110210284Sjmallett 111210284Sjmallett for(retry=0; retry<2; retry++) 112210284Sjmallett { 113210284Sjmallett rc = cvmx_twsi_write8(CVMX_RTC_DS1374_ADDR, 0x0, time & 0xff); 114210284Sjmallett rc |= cvmx_twsi_write8(CVMX_RTC_DS1374_ADDR, 0x1, (time >> 8) & 0xff); 115210284Sjmallett rc |= cvmx_twsi_write8(CVMX_RTC_DS1374_ADDR, 0x2, (time >> 16) & 0xff); 116210284Sjmallett rc |= cvmx_twsi_write8(CVMX_RTC_DS1374_ADDR, 0x3, (time >> 24) & 0xff); 117210284Sjmallett sec = cvmx_twsi_read8(CVMX_RTC_DS1374_ADDR, 0x0); 118210284Sjmallett if (sec == (time & 0xff)) 119210284Sjmallett break; /* Time did not roll-over, value is correct */ 120210284Sjmallett } 121210284Sjmallett 122210284Sjmallett return (rc ? -1 : 0); 123210284Sjmallett} 124210284Sjmallett 125210311Sjmallettstatic int cvmx_rtc_ds1374_alarm_config(int WD, int WDSTR, int AIE) 126210284Sjmallett{ 127210284Sjmallett int val; 128210284Sjmallett 129210284Sjmallett val = cvmx_twsi_read8(CVMX_RTC_DS1374_ADDR,RTC_CTL_ADDR); 130210284Sjmallett val = val & ~RTC_CTL_BIT_EOSC; /* Make sure that oscillator is running */ 131210284Sjmallett WD?(val = val | RTC_CTL_BIT_WD_ALM):(val = val & ~RTC_CTL_BIT_WD_ALM); 132210284Sjmallett WDSTR?(val = val | RTC_CTL_BIT_WDSTR):(val = val & ~RTC_CTL_BIT_WDSTR); 133210284Sjmallett AIE?(val = val | RTC_CTL_BIT_AIE):(val = val & ~RTC_CTL_BIT_AIE); 134210284Sjmallett cvmx_twsi_write8(CVMX_RTC_DS1374_ADDR,RTC_CTL_ADDR, val); 135210284Sjmallett return 0; 136210284Sjmallett} 137210284Sjmallett 138210311Sjmallettstatic int cvmx_rtc_ds1374_alarm_set(int alarm_on) 139210284Sjmallett{ 140210284Sjmallett uint8_t val; 141210284Sjmallett 142210284Sjmallett if (alarm_on) 143210284Sjmallett { 144210284Sjmallett val = cvmx_twsi_read8(CVMX_RTC_DS1374_ADDR,RTC_CTL_ADDR); 145210284Sjmallett cvmx_twsi_write8(CVMX_RTC_DS1374_ADDR,RTC_CTL_ADDR, val | RTC_CTL_BIT_WACE); 146210284Sjmallett } 147210284Sjmallett else 148210284Sjmallett { 149210284Sjmallett val = cvmx_twsi_read8(CVMX_RTC_DS1374_ADDR,RTC_CTL_ADDR); 150210284Sjmallett cvmx_twsi_write8(CVMX_RTC_DS1374_ADDR,RTC_CTL_ADDR, val & ~RTC_CTL_BIT_WACE); 151210284Sjmallett } 152210284Sjmallett return 0; 153210284Sjmallett} 154210284Sjmallett 155210284Sjmallett 156210311Sjmallettstatic int cvmx_rtc_ds1374_alarm_counter_set(uint32_t interval) 157210284Sjmallett{ 158210284Sjmallett int i; 159210284Sjmallett int rc = 0; 160210284Sjmallett 161210284Sjmallett for(i=0;i<3;i++) 162210284Sjmallett { 163210284Sjmallett rc |= cvmx_twsi_write8(CVMX_RTC_DS1374_ADDR, RTC_WD_ALM_CNT_BYTE0_ADDR+i, interval & 0xFF); 164210284Sjmallett interval >>= 8; 165210284Sjmallett } 166210284Sjmallett return rc; 167210284Sjmallett} 168210284Sjmallett 169210311Sjmallett#if 0 /* XXX unused */ 170210311Sjmallettstatic uint32_t cvmx_rtc_ds1374_alarm_counter_get(void) 171210284Sjmallett{ 172210284Sjmallett int i; 173210284Sjmallett uint32_t interval = 0; 174210284Sjmallett 175210284Sjmallett for(i=0;i<3;i++) 176210284Sjmallett { 177210284Sjmallett interval |= ( cvmx_twsi_read8(CVMX_RTC_DS1374_ADDR,RTC_WD_ALM_CNT_BYTE0_ADDR+i) & 0xff) << (i*8); 178210284Sjmallett } 179210284Sjmallett return interval; 180210284Sjmallett} 181210311Sjmallett#endif 182210284Sjmallett 183210284Sjmallett 184210284Sjmallett#ifdef CVMX_RTC_DEBUG 185210284Sjmallett 186210284Sjmallettvoid cvmx_rtc_ds1374_dump_state(void) 187210284Sjmallett{ 188210284Sjmallett int i = 0; 189210284Sjmallett 190210284Sjmallett cvmx_dprintf("RTC:\n"); 191210284Sjmallett cvmx_dprintf("%d : %02X ", i, cvmx_twsi_read8(CVMX_RTC_DS1374_ADDR, 0x0)); 192210284Sjmallett for(i=1; i<10; i++) 193210284Sjmallett { 194210284Sjmallett cvmx_dprintf("%02X ", cvmx_twsi_read8_cur_addr(CVMX_RTC_DS1374_ADDR)); 195210284Sjmallett } 196210284Sjmallett cvmx_dprintf("\n"); 197210284Sjmallett} 198210284Sjmallett 199210284Sjmallett#endif /* CVMX_RTC_DEBUG */ 200210284Sjmallett 201210284Sjmallett 202210284Sjmallett/* 203210284Sjmallett * LAN bypass functionality 204210284Sjmallett */ 205210284Sjmallett 206210284Sjmallett/* Private initialization function */ 207210284Sjmallettstatic int cvmx_lan_bypass_init(void) 208210284Sjmallett{ 209210284Sjmallett const int CLR_PULSE = 100; /* Longer than 100 ns (on CPUs up to 1 GHz) */ 210210284Sjmallett 211210284Sjmallett //Clear GPIO 6 212210284Sjmallett cvmx_gpio_clear(BYPASS_EN); 213210284Sjmallett 214210284Sjmallett //Disable WDT 215210284Sjmallett cvmx_rtc_ds1374_alarm_set(0); 216210284Sjmallett 217210284Sjmallett //GPIO(7) Send a low pulse 218210284Sjmallett cvmx_gpio_clear(WDT_BP_CLR); 219210284Sjmallett cvmx_wait(CLR_PULSE); 220210284Sjmallett cvmx_gpio_set(WDT_BP_CLR); 221210284Sjmallett return 0; 222210284Sjmallett} 223210284Sjmallett 224210284Sjmallett/** 225210284Sjmallett * Set LAN bypass mode. 226210284Sjmallett * 227210284Sjmallett * Supported modes are: 228210284Sjmallett * - CVMX_LAN_BYPASS_OFF 229210284Sjmallett * <br>LAN ports are connected ( port 0 <--> Octeon <--> port 1 ) 230210284Sjmallett * 231210284Sjmallett * - CVMX_LAN_BYPASS_GPIO 232210284Sjmallett * <br>LAN bypass is controlled by software using cvmx_lan_bypass_force() function. 233210284Sjmallett * When transitioning to this mode, default is LAN bypass enabled 234210284Sjmallett * ( port 0 <--> port 1, -- Octeon ). 235210284Sjmallett * 236210284Sjmallett * - CVMX_LAN_BYPASS_WATCHDOG 237210284Sjmallett * <br>LAN bypass is inactive as long as a watchdog is kept alive. 238210284Sjmallett * The default expiration time is 1 second and the function to 239210284Sjmallett * call periodically to prevent watchdog expiration is 240210284Sjmallett * cvmx_lan_bypass_keep_alive(). 241210284Sjmallett * 242210284Sjmallett * @param mode LAN bypass mode 243210284Sjmallett * 244210284Sjmallett * @return Error code, or 0 in case of success 245210284Sjmallett */ 246210284Sjmallettint cvmx_lan_bypass_mode_set(cvmx_lan_bypass_mode_t mode) 247210284Sjmallett{ 248210284Sjmallett switch(mode) 249210284Sjmallett { 250210284Sjmallett case CVMX_LAN_BYPASS_GPIO: 251210284Sjmallett /* make lan bypass enable */ 252210284Sjmallett cvmx_lan_bypass_init(); 253210284Sjmallett cvmx_gpio_set(BYPASS_EN); 254210284Sjmallett CVMX_LAN_BYPASS_MSG("Enable LAN bypass by GPIO. \n"); 255210284Sjmallett break; 256210284Sjmallett 257210284Sjmallett case CVMX_LAN_BYPASS_WATCHDOG: 258210284Sjmallett /* make lan bypass enable */ 259210284Sjmallett cvmx_lan_bypass_init(); 260210284Sjmallett /* Set WDT parameters and turn it on */ 261210284Sjmallett cvmx_rtc_ds1374_alarm_counter_set(0x1000); /* 4096 ticks = 1 sec */ 262210284Sjmallett cvmx_rtc_ds1374_alarm_config(1,1,1); 263210284Sjmallett cvmx_rtc_ds1374_alarm_set(1); 264210284Sjmallett CVMX_LAN_BYPASS_MSG("Enable LAN bypass by WDT. \n"); 265210284Sjmallett break; 266210284Sjmallett 267210284Sjmallett case CVMX_LAN_BYPASS_OFF: 268210284Sjmallett /* make lan bypass disable */ 269210284Sjmallett cvmx_lan_bypass_init(); 270210284Sjmallett CVMX_LAN_BYPASS_MSG("Disable LAN bypass. \n"); 271210284Sjmallett break; 272210284Sjmallett 273210284Sjmallett default: 274210284Sjmallett CVMX_LAN_BYPASS_MSG("%s: LAN bypass mode %d not supported\n", __FUNCTION__, mode); 275210284Sjmallett break; 276210284Sjmallett } 277210284Sjmallett return 0; 278210284Sjmallett} 279210284Sjmallett 280210284Sjmallett/** 281210284Sjmallett * Refresh watchdog timer. 282210284Sjmallett * 283210284Sjmallett * Call periodically (less than 1 second) to prevent triggering LAN bypass. 284210284Sjmallett * The alternative cvmx_lan_bypass_keep_alive_ms() is provided for cases 285210284Sjmallett * where a variable interval is required. 286210284Sjmallett */ 287210284Sjmallettvoid cvmx_lan_bypass_keep_alive(void) 288210284Sjmallett{ 289210284Sjmallett cvmx_rtc_ds1374_alarm_counter_set(0x1000); /* 4096 ticks = 1 second */ 290210284Sjmallett} 291210284Sjmallett 292210284Sjmallett/** 293210284Sjmallett * Refresh watchdog timer, setting a specific expiration interval. 294210284Sjmallett * 295210284Sjmallett * @param interval_ms Interval, in milliseconds, to next watchdog expiration. 296210284Sjmallett */ 297210284Sjmallettvoid cvmx_lan_bypass_keep_alive_ms(uint32_t interval_ms) 298210284Sjmallett{ 299210284Sjmallett cvmx_rtc_ds1374_alarm_counter_set((interval_ms * 0x1000) / 1000); 300210284Sjmallett} 301210284Sjmallett 302210284Sjmallett/** 303210284Sjmallett * Control LAN bypass via software. 304210284Sjmallett * 305210284Sjmallett * @param force_bypass Force LAN bypass to active (1) or inactive (0) 306210284Sjmallett * 307210284Sjmallett * @return Error code, or 0 in case of success 308210284Sjmallett */ 309210284Sjmallettint cvmx_lan_bypass_force(int force_bypass) 310210284Sjmallett{ 311210284Sjmallett if (force_bypass) 312210284Sjmallett { 313210284Sjmallett //Set GPIO 6 314210284Sjmallett cvmx_gpio_set(BYPASS_EN); 315210284Sjmallett } 316210284Sjmallett else 317210284Sjmallett { 318210284Sjmallett cvmx_lan_bypass_init(); 319210284Sjmallett } 320210284Sjmallett return 0; 321210284Sjmallett} 322210284Sjmallett 323210284Sjmallett/** 324210284Sjmallett * Return status of LAN bypass circuit. 325210284Sjmallett * 326210284Sjmallett * @return 1 if ports are in LAN bypass, or 0 if normally connected 327210284Sjmallett */ 328210284Sjmallettint cvmx_lan_bypass_is_active(void) 329210284Sjmallett{ 330210284Sjmallett return !!(cvmx_gpio_read() & BYPASS_STATUS); 331210284Sjmallett} 332