From: Masayuki Ohtake Subject: OKI Semiconductor PCH IEEE1588 driver This driver implements IEEE1588 controls for PCH. Signed-off-by: Masayuki Ohtake Acked-by: Wang Qi --- drivers/char/Kconfig | 7 ++ drivers/char/Makefile | 2 drivers/char/pch_ieee1588/Makefile | 10 drivers/char/pch_ieee1588/pch_1588_hal.c | 4040 drivers/char/pch_ieee1588/pch_1588_hal.h | 885 drivers/char/pch_ieee1588/pch_1588_main.c | 1192 drivers/char/pch_ieee1588/pch_1588_main.h | 702 drivers/char/pch_ieee1588/pch_1588_pci.c | 700 drivers/char/pch_ieee1588/pch_1588_pci.h | 122 drivers/char/pch_ieee1588/pch_common.h | 146 drivers/char/pch_ieee1588/pch_debug.h | 60 +++++++++++++++++++++++++++++++ 11 files changed, zz insertions(+) diff -urN linux-2.6.33-rc3/drivers/char/Kconfig topcliff-2.6.33-rc3/drivers/char/Kconfig --- linux-2.6.33-rc3/drivers/char/Kconfig 2010-01-06 09:02:46.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/Kconfig 2010-03-09 10:14:52.000000000 +0900 @@ -4,6 +4,13 @@ menu "Character devices" +config PCH_IEEE1588 + tristate "PCH IEEE1588" + depends on PCI + help + If you say yes to this option, support will be included for the + PCH IEEE1588 Host controller. + config VT bool "Virtual terminal" if EMBEDDED depends on !S390 diff -urN linux-2.6.33-rc3/drivers/char/Makefile topcliff-2.6.33-rc3/drivers/char/Makefile --- linux-2.6.33-rc3/drivers/char/Makefile 2010-01-06 09:02:46.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/Makefile 2010-03-05 22:57:39.000000000 +0900 @@ -111,6 +111,8 @@ obj-$(CONFIG_JS_RTC) += js-rtc.o js-rtc-y = rtc.o +obj-$(CONFIG_PCH_IEEE1588) += pch_ieee1588/ + # Files generated that shall be removed upon make clean clean-files := consolemap_deftbl.c defkeymap.c diff -urN linux-2.6.33-rc3/drivers/char/pch_ieee1588/Makefile topcliff-2.6.33-rc3/drivers/char/pch_ieee1588/Makefile --- linux-2.6.33-rc3/drivers/char/pch_ieee1588/Makefile 1970-01-01 09:00:00.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/pch_ieee1588/Makefile 2010-03-10 04:52:54.000000000 +0900 @@ -0,0 +1,10 @@ +ifeq ($(CONFIG_IEEE1588_DEBUG_CORE),y) +EXTRA_CFLAGS += -DDEBUG +endif + +obj-$(CONFIG_PCH_IEEE1588) += pch_ieee1588.o + +#for A0_A1_SAMPLE LSI board +EXTRA_CFLAGS+=-DIOH_IEEE1588_A0_A1_SAMPLE_BUG + +pch_ieee1588-objs := pch_1588_main.o pch_1588_pci.o pch_1588_hal.o diff -urN linux-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_hal.c topcliff-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_hal.c --- linux-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_hal.c 1970-01-01 09:00:00.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_hal.c 2010-03-09 10:34:22.000000000 +0900 @@ -0,0 +1,4040 @@ + /*! + * @file ioh_1588_hal.c + * @brief + * This file has the definitions for HALLAyer APIs. + * @version 0.92 + * @section + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * History: + * modified to support Intel IOH GE IEEE 1588 hardware + * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. + * All rights reserved. + * derived from + * IEEE 1588 Time Synchronization Driver for Intel EP80579 + * Copyright(c) 2007,2008 Intel Corporation. All rights reserved. + * All rights reserved. + * + */ + +#include +#include "pch_common.h" +#include "pch_debug.h" +#include +#include "pch_1588_hal.h" + +/* + * HAL API definitions for the IEEE 1588 module + */ + +/*! @ingroup IEEE1588 + * @def INLINE + * @brief The macro used instead of the keyword __inline. +*/ +#define INLINE inline + +/*Register read/write macros*/ +#define IOH_REG_32_READ(regAddr, varRef) (*(varRef) = IOH_READ32(regAddr)) +#define IOH_REG_32_WRITE(regAddr, varValue) IOH_WRITE32(varValue, regAddr) +#define IOH_BIT_SET_CHECK(regAddr, bitMask) \ + ((IOH_READ32(regAddr) & (bitMask)) == (bitMask)) + +#ifdef IOH_IEEE1588_A1_SAMPLE_BUG +/*global variable to store tick rate*/ +static unsigned long gTickRateApp; +#endif + +/* function prototypes */ +/* TS_Control register access routines */ +static INLINE void ioh_1588_pps_imask_set(void); +static INLINE void ioh_1588_amms_imask_set(void); +static INLINE void ioh_1588_asms_imask_set(void); +static INLINE void ioh_1588_ttm_imask_set(void); +static INLINE void ioh_1588_pps_imask_clear(void); +static INLINE void ioh_1588_amms_imask_clear(void); +static INLINE void ioh_1588_asms_imask_clear(void); +static INLINE void ioh_1588_ttm_imask_clear(void); +static INLINE unsigned long ioh_1588_pps_imask_get(void); +static INLINE unsigned long ioh_1588_amms_imask_get(void); +static INLINE unsigned long ioh_1588_asms_imask_get(void); +static INLINE unsigned long ioh_1588_ttm_imask_get(void); +static INLINE void ioh_1588_block_reset(void); + +/* TS_Event register access routines */ +static INLINE unsigned long ioh_1588_pps_evt_get(void); +static INLINE unsigned long ioh_1588_amms_evt_get(void); +static INLINE unsigned long ioh_1588_asms_evt_get(void); +static INLINE unsigned long ioh_1588_ttm_evt_get(void); +static INLINE void ioh_1588_pps_evt_clear(void); +static INLINE void ioh_1588_amms_evt_clear(void); +static INLINE void ioh_1588_asms_evt_clear(void); +static INLINE void ioh_1588_ttm_evt_clear(void); + +/* TS_Addend register access routines - Frequency Scaling Value */ +static INLINE void ioh_1588_addend_set(unsigned long fsv); +static INLINE void ioh_1588_addend_get(unsigned long *fsv); + +/* TS_PPS_Compare register access routines */ +static INLINE void ioh_1588_pps_set(unsigned long fsv); +static INLINE void ioh_1588_pps_get(unsigned long *fsv); +/* TS_SYSTimeLo, Hi registers access routines */ +static INLINE void ioh_1588_sys_snap_set(unsigned long sys_time_low, + unsigned long sys_time_high); +static INLINE void ioh_1588_sys_snap_get(unsigned long *sys_time_low, + unsigned long *sys_time_high); +/* TS_TrgtTimeLo, Hi registers access routines */ +static INLINE void ioh_1588_tgt_snap_set(unsigned long tgt_time_low, + unsigned long tgt_time_high); +static INLINE void ioh_1588_tgt_snap_get(unsigned long *tgt_time_low, + unsigned long *tgt_time_high); +/* TS_ASMSLo, Hi registers access routines */ +static INLINE void ioh_1588_aux_slave_snap_get(unsigned long *asms_low, + unsigned long *asms_high); +/* TS_AMMSLo, Hi registers access routines */ +static INLINE void ioh_1588_aux_master_snap_get(unsigned long *amms_low, + unsigned long *amms_high); + +/* TS_Ch_Control register access routines */ +static INLINE void ioh_1588_master_mode_set(unsigned long master_mode); +static INLINE unsigned long ioh_1588_master_mode_get(void); +static INLINE void ioh_1588_timestamp_all_set(unsigned long allMsg); +static INLINE unsigned long ioh_1588_timestamp_all_get(void); +static INLINE void ioh_1588_op_mode_set(unsigned long mode); +static INLINE unsigned long ioh_1588_op_mode_get(void); +static INLINE void ioh_1588_version_set(unsigned long versionVal); +static INLINE unsigned long ioh_1588_version_get(void); + +/* TS_Ch_Event register access routines */ +static INLINE unsigned long ioh_1588_rx_snap_evt(void); +static INLINE unsigned long ioh_1588_tx_snap_evt(void); +static INLINE void ioh_1588_rx_snap_evt_clear(void); +static INLINE void ioh_1588_tx_snap_evt_clear(void); +/* TS_TxSnapLo, Hi registers access routines */ +static INLINE void ioh_1588_tx_snap_get(unsigned long *txs_low, + unsigned long *txs_high); +/* TS_RxSnapLo, Hi registers access routines */ +static INLINE void ioh_1588_rx_snap_get(unsigned long *rxs_low, + unsigned long *rxs_high); +/* TS_srcUUIDLo, Hi registers access routines */ +static INLINE void ioh_1588_uuid_seqid_get(unsigned long *uuid_low, + unsigned long *uuid_high, + unsigned int *seq_id); + +static INLINE unsigned long ioh_1588_can_snap_valid(void); +static INLINE unsigned long ioh_1588_can_snap_ovr(void); +static INLINE void ioh_1588_can_snap_valid_clear(void); +static INLINE void ioh_1588_can_snap_ovr_clear(void); +static INLINE void ioh_1588_can_snap_get(unsigned long *rxs_low, + unsigned long *rxs_high); + +static INLINE void ioh_1588_eth_enable_set(void); +static INLINE void ioh_1588_eth_enable_clear(void); +static INLINE unsigned long ioh_1588_eth_enable_get(void); +static INLINE void ioh_1588_can_enable_set(void); +static INLINE void ioh_1588_can_enable_clear(void); +static INLINE unsigned long ioh_1588_can_enable_get(void); +static INLINE void ioh_1588_station_set(unsigned long station, + unsigned long value); +static INLINE void ioh_1588_station_get(unsigned long station, + unsigned long *value); + +/* Masks to extract High and Low SHORTs from unsigned long values */ +#define IOH_1588_MSB_SHORT_MASK (0xFFFF0000) +#define IOH_1588_LSB_SHORT_MASK (0x0000FFFF) + +/* Location of SeqID in the register */ +#define IOH_1588_SID_LOC (16) + +/* Variable declarations */ + +/** + * Client registered callback routines for + * a) the target time reached or exceeded interrupt notification + * b) the auxiliary time stamps availability interrupt notification + * c) the pulse per second match interrupt notification + */ +static ioh1588TargetTimeCallback ioh_tt_cbptr = + (ioh1588TargetTimeCallback) NULL; +static ioh1588AuxTimeCallback ioh_am_cbptr = (ioh1588AuxTimeCallback) NULL; +static ioh1588AuxTimeCallback ioh_as_cbptr = (ioh1588AuxTimeCallback) NULL; +static ioh1588PulsePerSecondCallback ioh_pps_cbptr = + (ioh1588PulsePerSecondCallback) NULL; + +/* The transmit and receive timestamp statistics */ +static struct ioh1588Stats ioh_1588_stats = { 0, 0 }; + +/* To save the state of all registers of the module */ +static struct ioh_1588_regs_set ioh_1588_regs; + +/* IO mapped virtual address for the 1588 registers */ +static unsigned long ioh_1588_base; + +/* local functions definitions. */ + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_pps_imask_set(void) + * @brief Enable PPS Interrupt + * @param None + * @retval None +*/ + +static INLINE void ioh_1588_pps_imask_set(void) +{ + /* SET the ppsm bit */ + IOH_SET_ADDR_BIT(ioh_1588_base + IOH_1588_TSC_OFFSET, + IOH_1588_TSC_PPSM_MASK); +} + +/** @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_amms_imask_set(void) + * @brief Enable Auxiliary Master Mode Snapshot Interrupt + * @param None + * @retval None +*/ +static INLINE void ioh_1588_amms_imask_set(void) +{ + /* SET the amms bit */ + IOH_SET_ADDR_BIT(ioh_1588_base + IOH_1588_TSC_OFFSET, + IOH_1588_TSC_AMMS_MASK); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_asms_imask_set(void) + * @brief Enable Auxiliary Slave Mode Snapshot Interrupt + * @param None + * @retval None +*/ +static INLINE void ioh_1588_asms_imask_set(void) +{ + /* SET the asms bit */ + IOH_SET_ADDR_BIT(ioh_1588_base + IOH_1588_TSC_OFFSET, + IOH_1588_TSC_ASMS_MASK); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_ttm_imask_set(void) + * @brief Enable Target Time Interrupt + * @param None + * @retval None +*/ +static INLINE void ioh_1588_ttm_imask_set(void) +{ + /* SET the ttm bit */ + IOH_SET_ADDR_BIT(ioh_1588_base + IOH_1588_TSC_OFFSET, + IOH_1588_TSC_TTM_MASK); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE unsigned long ioh_1588_pps_imask_get(void) + * @brief Get PPS Interrupt Mask value + * @param None + * @retval unsigned long +*/ +static INLINE unsigned long ioh_1588_pps_imask_get(void) +{ + /* Is the ppsm bit SET? */ + return IOH_BIT_SET_CHECK(ioh_1588_base + IOH_1588_TSC_OFFSET, + IOH_1588_TSC_PPSM_MASK); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE unsigned long ioh_1588_amms_imask_get(void) + * @brief Get Auxiliary Master Mode Snapshot Interrupt Mask value + * @param None + * @retval unsigned long +*/ +static INLINE unsigned long ioh_1588_amms_imask_get(void) +{ + /* Is the amms bit SET? */ + return IOH_BIT_SET_CHECK(ioh_1588_base + IOH_1588_TSC_OFFSET, + IOH_1588_TSC_AMMS_MASK); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + @fn static INLINE unsigned long ioh_1588_asms_imask_get(void) + @brief Get Auxiliary Slave Mode Snapshot Interrupt Mask value + @param None + @retval unsigned long +*/ +static INLINE unsigned long ioh_1588_asms_imask_get(void) +{ + /* Is the asms bit SET? */ + return IOH_BIT_SET_CHECK(ioh_1588_base + IOH_1588_TSC_OFFSET, + IOH_1588_TSC_ASMS_MASK); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE unsigned long ioh_1588_ttm_imask_get(void) + * @brief Get Target Time Interrupt Mask value + * @param None. + * @retval unsigned long +*/ +static INLINE unsigned long ioh_1588_ttm_imask_get(void) +{ + /* Is the ttm bit SET? */ + return IOH_BIT_SET_CHECK(ioh_1588_base + IOH_1588_TSC_OFFSET, + IOH_1588_TSC_TTM_MASK); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + @fn static INLINE void ioh_1588_pps_imask_clear(void) + @brief Disable PPS Interrupt + @param None + @retval None +*/ +static INLINE void ioh_1588_pps_imask_clear(void) +{ + /* CLEAR the ppsm bit */ + IOH_CLR_ADDR_BIT(ioh_1588_base + IOH_1588_TSC_OFFSET, + IOH_1588_TSC_PPSM_MASK); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_amms_imask_clear(void) + * @brief Disable Auxiliary Master Mode Snapshot Interrupt. + * @param None. + * @retval None +*/ +static INLINE void ioh_1588_amms_imask_clear(void) +{ + /* CLEAR the amms bit */ + IOH_CLR_ADDR_BIT(ioh_1588_base + IOH_1588_TSC_OFFSET, + IOH_1588_TSC_AMMS_MASK); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_asms_imask_clear(void) + * @brief Disable Auxiliary Slave Mode Snapshot Interrupt + * @param None + * @retval None +*/ +static INLINE void ioh_1588_asms_imask_clear(void) +{ + /* CLEAR the asms bit */ + IOH_CLR_ADDR_BIT(ioh_1588_base + IOH_1588_TSC_OFFSET, + IOH_1588_TSC_ASMS_MASK); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_ttm_imask_clear(void) + * @brief Disable Target Time Interrupt + * @param None + * @retval None +*/ +static INLINE void ioh_1588_ttm_imask_clear(void) +{ + /* CLEAR the ttm bit */ + IOH_CLR_ADDR_BIT(ioh_1588_base + IOH_1588_TSC_OFFSET, + IOH_1588_TSC_TTM_MASK); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_block_reset(void) + * @brief Reset Hardware Assist block + * @param None + * @retval None +*/ +static INLINE void ioh_1588_block_reset(void) +{ + /* SET the rst bit */ + IOH_SET_ADDR_BIT(ioh_1588_base + IOH_1588_TSC_OFFSET, + IOH_1588_TSC_RESET); + /* CLEAR the rst bit */ + IOH_CLR_ADDR_BIT(ioh_1588_base + IOH_1588_TSC_OFFSET, + IOH_1588_TSC_RESET); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE unsigned long ioh_1588_pps_evt_get(void) + * @brief Poll for PPS event + * @param None + * @retval unsigned long +*/ +static INLINE unsigned long ioh_1588_pps_evt_get(void) +{ + /* Check for PPS event */ + return IOH_BIT_SET_CHECK(ioh_1588_base + IOH_1588_TSE_OFFSET, + IOH_1588_TSE_PPS); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE unsigned long ioh_1588_amms_evt_get(void) + * @brief Poll for Auxiliary Master Mode Snapshot Captured event + * @param None + * @retval unsigned long +*/ +static INLINE unsigned long ioh_1588_amms_evt_get(void) +{ + /* Check for AMMS event */ + return IOH_BIT_SET_CHECK(ioh_1588_base + IOH_1588_TSE_OFFSET, + IOH_1588_TSE_SNM); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE unsigned long ioh_1588_asms_evt_get(void) + * @brief Poll for Auxiliary Slave Mode Snapshot Captured event + * @param None + * @retval unsigned long +*/ +static INLINE unsigned long ioh_1588_asms_evt_get(void) +{ + /* Check ASMS event */ + return IOH_BIT_SET_CHECK(ioh_1588_base + IOH_1588_TSE_OFFSET, + IOH_1588_TSE_SNS); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE unsigned long ioh_1588_ttm_evt_get(void) + * @brief Poll for Target Time Reached event + * @param None + * @retval unsigned long +*/ +static INLINE unsigned long ioh_1588_ttm_evt_get(void) +{ + /* Check target time pending event */ + return IOH_BIT_SET_CHECK(ioh_1588_base + IOH_1588_TSE_OFFSET, + IOH_1588_TSE_TTIPEND); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_pps_evt_clear(void) + * @brief Clear PPS event + * @param None + * @retval None +*/ +static INLINE void ioh_1588_pps_evt_clear(void) +{ + /* clear the pps bit */ + IOH_SET_ADDR_BIT(ioh_1588_base + IOH_1588_TSE_OFFSET, IOH_1588_TSE_PPS); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_amms_evt_clear(void) + * @brief Clear Auxiliary Master Mode Snapshot Captured event + * @param None. + * @retval None. +*/ +static INLINE void ioh_1588_amms_evt_clear(void) +{ + /* clear the snm bit */ + IOH_SET_ADDR_BIT(ioh_1588_base + IOH_1588_TSE_OFFSET, IOH_1588_TSE_SNM); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_asms_evt_clear(void) + * @brief Clear Auxiliary Slave Mode Snapshot Captured event + * @param None + * @retval None +*/ +static INLINE void ioh_1588_asms_evt_clear(void) +{ + /* clear the sns bit */ + IOH_SET_ADDR_BIT(ioh_1588_base + IOH_1588_TSE_OFFSET, IOH_1588_TSE_SNS); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_ttm_evt_clear(void) + * @brief Clear Target Time Reached event + * @param None + * @retval None +*/ +static INLINE void ioh_1588_ttm_evt_clear(void) +{ + /* CLEAR the ttipend bit */ + IOH_SET_ADDR_BIT(ioh_1588_base + IOH_1588_TSE_OFFSET, + IOH_1588_TSE_TTIPEND); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_sys_snap_set( + * unsigned long sys_time_low, unsigned long sys_time_high) + * @brief Set System Time value + * @param sys_time_low [IN] The system time low. + * @param sys_time_high {In} The system time high. + * @retval None +*/ +static INLINE void +ioh_1588_sys_snap_set(unsigned long sys_time_low, unsigned long sys_time_high) +{ + /* Update the System Time Low Register contents */ + IOH_REG_32_WRITE(ioh_1588_base + IOH_1588_STL_OFFSET, sys_time_low); + + /* Update the System Time High Register contents */ + IOH_REG_32_WRITE(ioh_1588_base + IOH_1588_STH_OFFSET, sys_time_high); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE voidioh_1588_sys_snap_get( + * unsigned long *sys_time_low, unsigned long *sys_time_high) + * @brief Get System Time Low value + * @param sys_time_low [OUT] The system time low. + * @param sys_time_high [OUT] The system time high. + * @retval None +*/ +static INLINE void +ioh_1588_sys_snap_get(unsigned long *sys_time_low, unsigned long *sys_time_high) +{ + /* Get the System Time Low Register contents */ + IOH_REG_32_READ(ioh_1588_base + IOH_1588_STL_OFFSET, sys_time_low); + + /* Get the System Time High Register contents */ + IOH_REG_32_READ(ioh_1588_base + IOH_1588_STH_OFFSET, sys_time_high); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_tgt_snap_set ( + * unsigned long tgt_time_low, unsigned long tgt_time_high) + * @brief Set Target Time value + * @param tgt_time_low [IN] The target time low. + * @param tgt_time_high [IN] The target time high. + * @retval None. +*/ +static INLINE void +ioh_1588_tgt_snap_set(unsigned long tgt_time_low, unsigned long tgt_time_high) +{ + /* Update the Target Time Low Register contents */ + IOH_REG_32_WRITE(ioh_1588_base + IOH_1588_TTL_OFFSET, tgt_time_low); + + /* Update the Target Time High Register contents */ + IOH_REG_32_WRITE(ioh_1588_base + IOH_1588_TTH_OFFSET, tgt_time_high); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_tgt_snap_get( + * unsigned long *tgt_time_low, unsigned long *tgt_time_high) + * @brief Get Target Time value + * @param tgt_time_low [OUT] The target time low. + * @param tgt_time_high [IN] The target time high. + * @retval None +*/ +static INLINE void +ioh_1588_tgt_snap_get(unsigned long *tgt_time_low, unsigned long *tgt_time_high) +{ + /* Get the Target Time Low Register contents */ + IOH_REG_32_READ(ioh_1588_base + IOH_1588_TTL_OFFSET, tgt_time_low); + + /* Get the Target Time High Register contents */ + IOH_REG_32_READ(ioh_1588_base + IOH_1588_TTH_OFFSET, tgt_time_high); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_addend_set(unsigned long fsv) + * @brief Set Frequency Scaling Value + * @param fsv [IN] Frequency + * @retval None +*/ +static INLINE void ioh_1588_addend_set(unsigned long fsv) +{ + /* Update the Addend Register contents */ + IOH_REG_32_WRITE(ioh_1588_base + IOH_1588_ADD_OFFSET, fsv); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_addend_get(unsigned long *fsv) + * @brief Get Frequency Scaling Value + * @param fsv [OUT] The frequency. + * @retval None +*/ +static INLINE void ioh_1588_addend_get(unsigned long *fsv) +{ + /* Get the Addend Register contents */ + IOH_REG_32_READ(ioh_1588_base + IOH_1588_ADD_OFFSET, fsv); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_pps_set(unsigned long pps) + * @brief Set Pulse Per Second Value + * @param pps [IN] The pulse per second value. + * @retval None. +*/ +static INLINE void ioh_1588_pps_set(unsigned long pps) +{ + /* Update the PPS Compare Register contents */ + IOH_REG_32_WRITE(ioh_1588_base + IOH_1588_PPS_OFFSET, pps); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_pps_get(unsigned long *pps) + * @brief Get Pulse Per Second Value + * @param pps [OUT] The pulse per second value. + * @retval None. +*/ +static INLINE void ioh_1588_pps_get(unsigned long *pps) +{ + /* Get the PPS Compare Register contents */ + IOH_REG_32_READ(ioh_1588_base + IOH_1588_PPS_OFFSET, pps); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_aux_master_snap_get( + * unsigned long *amms_low, unsigned long *amms_high) + * @brief Get AMMS value + * @param amms_low [OUT] AMMS low value. + * @param amms_high [OUT] AMMS high value. + * @retval None. +*/ +static INLINE void +ioh_1588_aux_master_snap_get(unsigned long *amms_low, unsigned long *amms_high) +{ + /* Get the Auxiliary Master Mode Snapshot Low Register contents */ + IOH_REG_32_READ(ioh_1588_base + IOH_1588_AMSL_OFFSET, amms_low); + + /* Get the Auxiliary Master Mode Snapshot High Register contents */ + IOH_REG_32_READ(ioh_1588_base + IOH_1588_AMSH_OFFSET, amms_high); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_aux_slave_snap_get( + * unsigned long *asms_low, unsigned long *asms_high) + * @brief Get ASMS value + * @param asms_low [OUT] The ASMS low value. + * @param asms_high [OUT] The ASMS high value. + * @retval None +*/ +static INLINE void +ioh_1588_aux_slave_snap_get(unsigned long *asms_low, unsigned long *asms_high) +{ + /* Get the Auxiliary Slave Mode Snapshot Low Register contents */ + IOH_REG_32_READ(ioh_1588_base + IOH_1588_ASSL_OFFSET, asms_low); + + /* Get the Auxiliary Slave Mode Snapshot High Register contents */ + IOH_REG_32_READ(ioh_1588_base + IOH_1588_ASSH_OFFSET, asms_high); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_master_mode_set( + * unsigned long master_mode) + * @brief Set the channel mode to 1588 Master/Slave + * @param master_mode [IN] The channel mode. + * @retval None +*/ +static INLINE void ioh_1588_master_mode_set(unsigned long master_mode) +{ + /* SET or CLEAR the Master Mode */ + if (TRUE == master_mode) { + IOH_DEBUG("ioh_1588_master_mode_set: setting master mode\n"); + /* SET the mm bit */ + IOH_SET_ADDR_BIT(ioh_1588_base + IOH_1588_CC_OFFSET, + IOH_1588_CC_MM); + } else { + IOH_DEBUG("ioh_1588_master_mode_set: clearing master mode\n"); + /* CLEAR the mm bit */ + IOH_CLR_ADDR_BIT(ioh_1588_base + IOH_1588_CC_OFFSET, + IOH_1588_CC_MM); + } +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE unsigned long ioh_1588_master_mode_get (void) + * @brief Check for 1588 master mode of channel + * @param None. + * @retval unsigned long +*/ +static INLINE unsigned long ioh_1588_master_mode_get(void) +{ + /* Is the mm bit SET? */ + return IOH_BIT_SET_CHECK(ioh_1588_base + IOH_1588_CC_OFFSET, + IOH_1588_CC_MM); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_timestamp_all_set( + * unsigned long allMsg) + * @brief Set Timestamp all or only PTP messages flag + * @param allMsg [IN] All/PTP messages. + * @retval None +*/ +static INLINE void ioh_1588_timestamp_all_set(unsigned long allMsg) +{ + /* SET or CLEAR the All Message Timestamping */ + if (TRUE == allMsg) { + IOH_DEBUG + ("ioh_1588_timestamp_all_set: time stamp all messages\n"); + /* SET the ta bit */ + IOH_SET_ADDR_BIT(ioh_1588_base + IOH_1588_CC_OFFSET, + IOH_1588_CC_TA); + } else { /* else of if (TRUE == allMsg) */ + + IOH_DEBUG + ("ioh_1588_timestamp_all_set: time stamp PTP messages \ + only\n"); + /* CLEAR the ta bit */ + IOH_CLR_ADDR_BIT(ioh_1588_base + IOH_1588_CC_OFFSET, + IOH_1588_CC_TA); + } +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE unsigned long ioh_1588_timestamp_all_get(void) + * @brief Check for Timestamp all OR only PTP messages flag + * @param None. + * @retval unsigned long +*/ +static INLINE unsigned long ioh_1588_timestamp_all_get(void) +{ + /* Is the ta bit SET? */ + return IOH_BIT_SET_CHECK(ioh_1588_base + IOH_1588_CC_OFFSET, + IOH_1588_CC_TA); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_version_set( + * unsigned long versionVal) + * @brief Set the 1588 version number + * @param versionVal [IN] The version value. + * @retval None. +*/ +static INLINE void ioh_1588_version_set(unsigned long versionVal) +{ + if (TRUE == versionVal) { + IOH_DEBUG + ("ioh_1588_version_set supports IEEE1588 v1 and \ + IEEE1588-2008\n"); + /* SET the version bit */ + IOH_SET_ADDR_BIT(ioh_1588_base + IOH_1588_CC_OFFSET, + IOH_1588_CC_VERSION); + } else { + IOH_DEBUG("ioh_1588_version_set supports IEEE1588 v1 only\n"); + /* CLEAR the version bit */ + IOH_CLR_ADDR_BIT(ioh_1588_base + IOH_1588_CC_OFFSET, + IOH_1588_CC_VERSION); + } +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE unsigned long ioh_1588_version_get (void) + * @brief Get the 1588 version number + * @param None. + * @retval unsigned long +*/ +static INLINE unsigned long ioh_1588_version_get(void) +{ + /* Is the version bit SET? */ + return IOH_BIT_SET_CHECK(ioh_1588_base + IOH_1588_CC_OFFSET, + IOH_1588_CC_VERSION); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE unsigned long ioh_1588_can_snap_valid (void) + * @brief CAN Timestamp available + * @param None + * @retval unsigned long +*/ +static INLINE unsigned long ioh_1588_can_snap_valid(void) +{ + /* Is the valid bit SET? */ + return IOH_BIT_SET_CHECK(ioh_1588_base + IOH_1588_CCE_OFFSET, + IOH_1588_CE_VAL); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE unsigned long ioh_1588_can_snap_ovr(void) + * @brief CAN Timestamp overrun + * @param None + * @retval unsigned long +*/ +static INLINE unsigned long ioh_1588_can_snap_ovr(void) +{ + /* Is the ovr bit SET? */ + return IOH_BIT_SET_CHECK(ioh_1588_base + IOH_1588_CCE_OFFSET, + IOH_1588_CE_OVR); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_can_snap_valid_clear(void) + * @brief Clear CAN Timestamp valid flag + * @param None + * @retval None +*/ +static INLINE void ioh_1588_can_snap_valid_clear(void) +{ + /* CLEAR the valid bit by writing '1' onto it */ + IOH_REG_32_WRITE(ioh_1588_base + IOH_1588_CCE_OFFSET, IOH_1588_CE_VAL); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_can_snap_ovr_clear(void) + * @brief Clear CAN Timestamp overrun flag + * @param None + * @retval None +*/ +static INLINE void ioh_1588_can_snap_ovr_clear(void) +{ + /* CLEAR the overrun bit */ + IOH_REG_32_WRITE(ioh_1588_base + IOH_1588_CCE_OFFSET, IOH_1588_CE_OVR); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE unsigned long ioh_1588_rx_snap_evt(void) + * @brief Receive Timestamp available + * @param None + * @retval unsigned long +*/ +static INLINE unsigned long ioh_1588_rx_snap_evt(void) +{ + /* Is the rxs bit SET? */ + return IOH_BIT_SET_CHECK(ioh_1588_base + IOH_1588_CE_OFFSET, + IOH_1588_CE_RXS); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn + * @brief Transmit Timestamp available + * @param None + * @retval unsigned long +*/ +static INLINE unsigned long ioh_1588_tx_snap_evt(void) +{ + /* Is the txs bit SET? */ + return IOH_BIT_SET_CHECK(ioh_1588_base + IOH_1588_CE_OFFSET, + IOH_1588_CE_TXS); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_rx_snap_evt_clear(void) + * @brief Clear Receive Timestamp available event + * @param None. + * @retval None.*/ +static INLINE void ioh_1588_rx_snap_evt_clear(void) +{ + /* CLEAR the rxs bit */ + IOH_REG_32_WRITE(ioh_1588_base + IOH_1588_CE_OFFSET, IOH_1588_CE_RXS); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_tx_snap_evt_clear(void) + * @brief Clear Transmit Timestamp available event + * @param None + * @retval None +*/ +static INLINE void ioh_1588_tx_snap_evt_clear(void) +{ + unsigned long ev_reg; + + IOH_REG_32_READ(ioh_1588_base + IOH_1588_CE_OFFSET, &ev_reg); + IOH_DEBUG + ("ioh_1588_tx_snap_evt_clear event reg content before clearing= %lx\n", + ev_reg); + + /* CLEAR the txs bit */ + IOH_REG_32_WRITE(ioh_1588_base + IOH_1588_CE_OFFSET, IOH_1588_CE_TXS); + + IOH_REG_32_READ(ioh_1588_base + IOH_1588_CE_OFFSET, &ev_reg); + IOH_DEBUG + ("ioh_1588_tx_snap_evt_clear event reg content after clearing= %lx\n", + ev_reg); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_can_snap_get( + * unsigned long *rxs_low,unsigned long *rxs_high) + * @brief Get PTP CAN Port Timestamp value + * @param rxs_low [OUT] The CAN Rx low value. + * @param rxs_high [OUT] The CAN Rx high value. + * @retval None. +*/ +static INLINE void +ioh_1588_can_snap_get(unsigned long *rxs_low, unsigned long *rxs_high) +{ + /* Get the Receive Timestamp/Snapshot Low Register contents */ + IOH_REG_32_READ(ioh_1588_base + IOH_1588_CXSL_OFFSET, rxs_low); + + /* Get the Receive Timestamp/Snapshot High Register contents */ + IOH_REG_32_READ(ioh_1588_base + IOH_1588_CXSH_OFFSET, rxs_high); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_rx_snap_get( + * unsigned long *rxs_low, unsigned long *rxs_high) + * @brief Get PTP Port Rx Timestamp value + * @param rxs_low [OUT] The Snap Rx value. + * @param rxs_high [OUT] The Snap Rx Value. + * @reatval None +*/ +static INLINE void +ioh_1588_rx_snap_get(unsigned long *rxs_low, unsigned long *rxs_high) +{ + /* Get the Receive Timestamp/Snapshot Low Register contents */ + IOH_REG_32_READ(ioh_1588_base + IOH_1588_RSL_OFFSET, rxs_low); + + /* Get the Receive Timestamp/Snapshot High Register contents */ + IOH_REG_32_READ(ioh_1588_base + IOH_1588_RSH_OFFSET, rxs_high); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_tx_snap_get( + * unsigned long *txs_low, unsigned long *txs_high) + * @brief Get PTP Port Tx Timestamp value + * @param txs_low [OUT] The Port Tx value low. + * @param txs_high [OUT] The Port Tx value high. + * @retval None +*/ +static INLINE void +ioh_1588_tx_snap_get(unsigned long *txs_low, unsigned long *txs_high) +{ + /* Get the Transmit Timestamp/Snapshot Low Register contents */ + IOH_REG_32_READ(ioh_1588_base + IOH_1588_XSL_OFFSET, txs_low); + + /* Get the Transmit Timestamp/Snapshot High Register contents */ + IOH_REG_32_READ(ioh_1588_base + IOH_1588_XSH_OFFSET, txs_high); + +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_uuid_seqid_get( + * unsigned long *uuid_low,unsigned long *uuid_high, unsigned int *seq_id) + * @brief Get UUID High (16-bit value) & Sequence ID (16-bit value) of + * PTP message + * @param uuid_low [OUT] The UUID low value. + * @param seq_id [OUT] The sequence ID. + * @retval None. +*/ +static INLINE void +ioh_1588_uuid_seqid_get(unsigned long *uuid_low, + unsigned long *uuid_high, unsigned int *seq_id) +{ + unsigned long regval = 0; + + /* Get the UUID Low Register contents */ + IOH_REG_32_READ(ioh_1588_base + IOH_1588_UID_OFFSET, uuid_low); + + /* Get the Sequence ID and Source UUID High Register contents */ + IOH_REG_32_READ(ioh_1588_base + IOH_1588_SID_OFFSET, ®val); + + *seq_id = (regval >> IOH_1588_SID_LOC); + *uuid_high = (regval & IOH_1588_LSB_SHORT_MASK); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_op_mode_set(unsigned long mode) + * @brief Sets the operation mode. + * @param mode [IN] The mode value. + * @retval None. +*/ +static INLINE void ioh_1588_op_mode_set(unsigned long mode) +{ + unsigned long regval; + + IOH_REG_32_READ(ioh_1588_base + IOH_1588_CC_OFFSET, ®val); + regval = + (regval & ~IOH_1588_CC_MODE_MASK) | (mode << + IOH_1588_CC_MODE_SHIFT); + /* set the operaion mode bits */ + IOH_REG_32_WRITE(ioh_1588_base + IOH_1588_CC_OFFSET, regval); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE unsigned long ioh_1588_op_mode_get(void) + * @brief Gets the operation mode. + * @param None. + * @retval unsigned long +*/ +static INLINE unsigned long ioh_1588_op_mode_get(void) +{ + unsigned long regval; + unsigned long mode; + + IOH_REG_32_READ(ioh_1588_base + IOH_1588_CC_OFFSET, ®val); + /* get the operaion mode bits */ + mode = (regval & IOH_1588_CC_MODE_MASK) >> IOH_1588_CC_MODE_SHIFT; + + return mode; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_eth_enable_set(void) + * @brief Enbales the eth. + * @param None. + * @retval None. +*/ +static INLINE void ioh_1588_eth_enable_set(void) +{ + /* SET the eth_enable bit */ + IOH_SET_ADDR_BIT(ioh_1588_base + IOH_1588_ECS_OFFSET, IOH_1588_ECS_ETH); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_eth_enable_clear(void) + * @brief Clears the eth enable. + * @param None. + * @retval None. +*/ +static INLINE void ioh_1588_eth_enable_clear(void) +{ + /* Clear the eth_enable bit */ + IOH_CLR_ADDR_BIT(ioh_1588_base + IOH_1588_ECS_OFFSET, IOH_1588_ECS_ETH); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE unsigned long ioh_1588_eth_enable_get(void) + * @brief Gets the eth enable. + * @param None. + * @retval unsigned long +*/ +static INLINE unsigned long ioh_1588_eth_enable_get(void) +{ + /* Is eth_enable bit set? */ + return IOH_BIT_SET_CHECK(ioh_1588_base + IOH_1588_ECS_OFFSET, + IOH_1588_ECS_ETH); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_can_enable_set(void) + * @brief Sets the CAN enable. + * @param None + * @retval None +*/ +static INLINE void ioh_1588_can_enable_set(void) +{ + /* SET the can_enable bit */ + IOH_SET_ADDR_BIT(ioh_1588_base + IOH_1588_ECS_OFFSET, IOH_1588_ECS_CAN); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_can_enable_clear(void) + * @brief Sets the CAN enable clear + * @param None + * @retval None +*/ +static INLINE void ioh_1588_can_enable_clear(void) +{ + /* Clear the can_enable bit */ + IOH_CLR_ADDR_BIT(ioh_1588_base + IOH_1588_ECS_OFFSET, IOH_1588_ECS_CAN); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE unsigned long ioh_1588_can_enable_get(void) + * @brief Gets the CAN enable status. + * @param None. + * @retval unsigned long +*/ +static INLINE unsigned long ioh_1588_can_enable_get(void) +{ + /* Is can_enable bit set? */ + return IOH_BIT_SET_CHECK(ioh_1588_base + IOH_1588_ECS_OFFSET, + IOH_1588_ECS_CAN); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_station_set(unsigned long station, + * unsigned long value) + * @brief Set the station[1-6] address to be used in PTP message + * @param station [IN] The Station. + * @param value [IN] The Value. + * @retval None. +*/ +static INLINE void +ioh_1588_station_set(unsigned long station, unsigned long value) +{ + IOH_DEBUG("ioh_1588_station_set;setting station address=%lx\n", value); + /* Set the Station Address Register contents */ + IOH_REG_32_WRITE(ioh_1588_base + IOH_1588_STA_OFFSET + + station * sizeof(int), value); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn static INLINE void ioh_1588_station_get (unsigned long station, + * unsigned long *value) + * @brief Get the station[1-6] address used in PTP message + * @param station [IN] The station. + * @param value [OUT] The value. + * @retval None. +*/ +static INLINE void +ioh_1588_station_get(unsigned long station, unsigned long *value) +{ + /* Get the Station Address Register contents */ + IOH_REG_32_READ(ioh_1588_base + IOH_1588_STA_OFFSET + + station * sizeof(int), value); + *value &= 0xFF; /* only one byte */ +} + +/** + * Support functions definitions + */ + +/** + * @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_disable_interrupts(void) + * @brief Disables all interrupts on the 1588 device. + * @param None + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + */ + +enum ioh_status ioh_1588_disable_interrupts(void) +{ + if (ioh_1588_base != 0) { + IOH_DEBUG + ("ioh_1588_disable_interrupts:invoking \ + ioh_1588_ttm_imask_clear\n"); + ioh_1588_ttm_imask_clear(); + IOH_DEBUG + ("ioh_1588_disable_interrupts:invoking \ + ioh_1588_asms_imask_clear\n"); + ioh_1588_asms_imask_clear(); + IOH_DEBUG + ("ioh_1588_disable_interrupts:invoking \ + ioh_1588_amms_imask_clear\n"); + ioh_1588_amms_imask_clear(); + IOH_DEBUG + ("ioh_1588_disable_interrupts:invoking \ + ioh_1588_pps_imask_clear\n"); + ioh_1588_pps_imask_clear(); + } + return IOH_1588_SUCCESS; +} + +/** + * @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_interrupt_pending( + * unsigned long *pending) + * @brief Check whether there is any pending interrupts from the 1588 + * device. + * @param pending [IN] Pending flag which set to TRUE if there is any + * pending interrupt + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + */ +enum ioh_status ioh_1588_interrupt_pending(unsigned long *pending) +{ + *pending = FALSE; + if (ioh_1588_pps_evt_get() || ioh_1588_amms_evt_get() || + ioh_1588_asms_evt_get() || ioh_1588_ttm_evt_get()) { + IOH_DEBUG("ioh_1588_interrupt_pending:interrupt pending\n"); + *pending = TRUE; + } else { + IOH_DEBUG("ioh_1588_interrupt_pending:NO interrupt pending\n"); + } + + return IOH_1588_SUCCESS; +} + +/** + * @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh1588PTPPortMode ioh_1588_port_mode_get( + * enum ioh1588PTPPort ptpPort) + * @brief Function to determine the port mode + * @param ptpPort [IN] Interested port (GBE_0) + * @retval enum ioh1588PTPPortMode + * - IOH_1588PTP_PORT_MASTER + * - IOH_1588PTP_PORT_SLAVE + * - IOH_1588PTP_PORT_ANYMODE + */ +enum ioh1588PTPPortMode ioh_1588_port_mode_get(enum ioh1588PTPPort ptpPort) +{ + /* Local variables */ + unsigned long master_mode = FALSE; + unsigned long any_mode = FALSE; + enum ioh1588PTPPortMode port_mode = IOH_1588PTP_PORT_SLAVE; + + /* Get the Mode of the PTP Port */ + master_mode = ioh_1588_master_mode_get(); + any_mode = ioh_1588_timestamp_all_get(); + + /* Is ANY mode (all message timestamp mode) on? */ + if (TRUE == any_mode) { + IOH_DEBUG + ("ioh_1588_port_mode_get:all messages being timestamped\n"); + /* + * When Any mode is set, all messages are time stamped, + * irrespective of the Master/Slave mode bit + */ + port_mode = IOH_1588PTP_PORT_ANYMODE; + IOH_DEBUG + ("ioh_1588_port_mode_get:port_mode = \ + IOH_1588PTP_PORT_ANYMODE\n"); + } else { + /* Is Master mode on? */ + if (TRUE == master_mode) { + port_mode = IOH_1588PTP_PORT_MASTER; + IOH_DEBUG + ("ioh_1588_port_mode_get:port_mode = \ + IOH_1588PTP_PORT_MASTER\n"); + } else { + port_mode = IOH_1588PTP_PORT_SLAVE; + IOH_DEBUG + ("ioh_1588_port_mode_get:port_mode = \ + IOH_1588PTP_PORT_SLAVE\n"); + } + } + + return port_mode; +} + +/* + * Public API definitions + */ + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_blpl_base_address_set(unsigned long base_addr) + * + * @brief Function sets the virtual address of registers + * @remarks This API will set the starting virtual addresses for the + * 1588 hardware registers. The main tasks performed by this + * function are: + * - If the aargument passed is NULL, return status + * IOH_1588_INVALIDPARAM + * - Set base address of IEEE 1588 registers to specified value + * + * + * @param base_addr [IN] - Virtual address of IEEE 1588 module registers + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARAM - Invalid parameter passed + */ +enum ioh_status ioh_1588_blpl_base_address_set(unsigned long base_addr) +{ + if (!base_addr) { + IOH_LOG(KERN_ERR, + "ioh_1588_blpl_base_address_set:invalid base address\ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + ioh_1588_base = base_addr; + IOH_DEBUG("ioh_1588_blpl_base_address_set:base address=%lx\n", + ioh_1588_base); + + /* Initialize the callback pointers */ + ioh_tt_cbptr = (ioh1588TargetTimeCallback) NULL; + ioh_am_cbptr = (ioh1588AuxTimeCallback) NULL; + ioh_as_cbptr = (ioh1588AuxTimeCallback) NULL; + ioh_pps_cbptr = (ioh1588PulsePerSecondCallback) NULL; + IOH_DEBUG("ioh_1588_blpl_base_address_set:initialized callback ptrs\n"); + + /* Reset the statistics counters */ + ioh_1588_stats.rxMsgs = ioh_1588_stats.txMsgs = 0; + IOH_DEBUG("ioh_1588_blpl_base_address_set:reset statistics counters\n"); + + /* Clear availability of various events */ + IOH_DEBUG + ("ioh_1588_blpl_base_address_set:invoking \ + ioh_1588_pps_evt_clear\n"); + ioh_1588_pps_evt_clear(); + IOH_DEBUG + ("ioh_1588_blpl_base_address_set:invoking \ + ioh_1588_ttm_evt_clear\n"); + ioh_1588_ttm_evt_clear(); + IOH_DEBUG + ("ioh_1588_blpl_base_address_set:invoking \ + ioh_1588_amms_evt_clear\n"); + ioh_1588_amms_evt_clear(); + IOH_DEBUG + ("ioh_1588_blpl_base_address_set:invoking \ + ioh_1588_asms_evt_clear\n"); + ioh_1588_asms_evt_clear(); + + IOH_DEBUG("ioh_1588_blpl_base_address_set:returning success\n"); + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_ptp_port_config_set( + * enum ioh1588PTPPort ptpPort, enum ioh1588PTPPortMode ptpPortMode) + * + * @brief Configure IEEE 1588 Hardware Assist message detection on a given PTP + * port + * + * @remarks This API enables the time stamping on a particular PTP port. + * The main tasks performed by this function are: + * - Validate the parameters and return + * IOH_1588_INVALIDPARAM, if found invalid + * - Modify the TS_Channel_Control register to set the + * requested mode + * + * + * @param ptpPort [IN] - port on which PTP message detection to be enabled + * @param ptpPortMode [IN]- Master/Slave/All messages + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARAM - Invalid parameters passed + */ +enum ioh_status +ioh_1588_ptp_port_config_set(enum ioh1588PTPPort ptpPort, + enum ioh1588PTPPortMode ptpPortMode) +{ + /* Verify the parameters for proper values */ + if (ptpPort != IOH_1588_GBE_0_1588PTP_PORT) { + IOH_LOG(KERN_ERR, + "ioh_1588_ptp_port_config_set:invalid ptp port\ + returning IOH_1588_GBE_0_1588PTP_PORT\n"); + return IOH_1588_INVALIDPARAM; + } + + /* Set the Mode of the PTP Port */ + switch (ptpPortMode) { + case IOH_1588PTP_PORT_MASTER: + { + IOH_DEBUG + ("ioh_1588_ptp_port_config_set:port_mode=\ + IOH_1588PTP_PORT_MASTER\n"); + IOH_DEBUG + ("ioh_1588_ptp_port_config_set:invoking \ + ioh_1588_master_mode_set \ + with param TRUE\n"); + ioh_1588_master_mode_set(TRUE); + IOH_DEBUG + ("ioh_1588_ptp_port_config_set:invoking \ + ioh_1588_timestamp_all_set \ + with param FALSE\n"); + ioh_1588_timestamp_all_set(FALSE); + break; + } + case IOH_1588PTP_PORT_SLAVE: + { + IOH_DEBUG + ("ioh_1588_ptp_port_config_set:port_mode=\ + IOH_1588PTP_PORT_SLAVE\n"); + IOH_DEBUG + ("ioh_1588_ptp_port_config_set:invoking \ + ioh_1588_master_mode_set \ + with param FALSE\n"); + ioh_1588_master_mode_set(FALSE); + IOH_DEBUG + ("ioh_1588_ptp_port_config_set:invoking \ + ioh_1588_timestamp_all_set \ + with param FALSE\n"); + ioh_1588_timestamp_all_set(FALSE); + break; + } + case IOH_1588PTP_PORT_ANYMODE: + { + IOH_DEBUG + ("ioh_1588_ptp_port_config_set:port_mode=\ + IOH_1588PTP_PORT_ANYMODE\n"); + IOH_DEBUG + ("ioh_1588_ptp_port_config_set:invoking \ + ioh_1588_master_mode_set \ + with param FALSE\n"); + ioh_1588_master_mode_set(FALSE); + IOH_DEBUG + ("ioh_1588_ptp_port_config_set:invoking \ + ioh_1588_timestamp_all_set \ + with param TRUE\n"); + ioh_1588_timestamp_all_set(TRUE); + break; + } + default: + { + IOH_LOG(KERN_ERR, "ioh_1588_ptp_port_config_set: \ + Invalid Port Mode (%d) \ + returning IOH_1588_INVALIDPARAM\n", + ptpPortMode); + return IOH_1588_INVALIDPARAM; + } + } + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_ptp_port_config_get( + * enum ioh1588PTPPort ptpPort, + * enum ioh1588PTPPortMode *ptpPortMode) + * + * @brief Get the configuration of IEEE 1588 Hardware Assist message + * detection + * for given PTP port + * + * @remarks This API retrieves the time stamping configuration of the given + * PTP port. + * The main tasks performed by this function are: + * - Validate the parameters and return + * IOH_1588_INVALIDPARAM, if found invalid + * - Return the current master/slave mode from + * TS_Channel_Control register + * + * + * @param ptpPort [IN] port for which PTP message configuration + * to be obtained + * @param ptpPortMode [OUT] Master/Slave/All messages + * + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARAM - Invalid parameters passed + */ +enum ioh_status +ioh_1588_ptp_port_config_get(enum ioh1588PTPPort ptpPort, + enum ioh1588PTPPortMode *ptpPortMode) +{ + /* Verify the parameters for proper values */ + if ((ptpPort != IOH_1588_GBE_0_1588PTP_PORT) || + ((enum ioh1588PTPPortMode *) NULL == ptpPortMode)) { + IOH_LOG(KERN_ERR, + "ioh_1588_ptp_port_config_get:\ + invalid port_mode or port \ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + /* Get the Mode of the PTP Port */ + IOH_DEBUG + ("ioh_1588_ptp_port_config_get:invoking ioh_1588_port_mode_get\n"); + *ptpPortMode = ioh_1588_port_mode_get(ptpPort); + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_ptp_rx_poll( + * enum ioh1588PTPPort ptpPort, + * struct ioh1588PtpMsgData *ptpMsgData) + * + * @brief Poll the IEEE 1588 Hardware Assist receive side message/time + * stamp + * detection status for given PTP Port + * + * @remarks This API will poll for the availability of a time stamp on the + * received Sync (in slave mode) or Delay_Req (in master mode) + * messages. + * The buffer is provided by the caller. + * The steps performed in this function are: + * - If ptpPort not valid or ptpMsgData is NULL return + * IOH_1588_INVALID_PARAM + * - Find out whether locked /unlocked mode. + * - If locked mode ,check the TS_Channel_Event register for Rx + * event + * - If locked mode, return NO TIMESTAMP if no Rx event flag is + * set. + * - Read the time stamp from RECV_Snapshot low, high and + * - SourceUUID0 low, high registers + * - Clear SourceUUId if the mode is not master/slave and PTP v1 + * only. + * - Increment RX messages captured statistics counter + * - If locked mode ,clear the RX event is TS_Channel_Event + * register + * + * + * @param ptpPort [IN] port on which time stamp availability + * to be checked + * @param ptpMsgData [out] Captured time stamp and other message + * information + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARAM - Invalid parameters passed + * @li IOH_1588_NOTIMESTAMP - Time stamp not available + * @li IOH_1588_FAILED - Internal error occurred + */ +enum ioh_status +ioh_1588_ptp_rx_poll(enum ioh1588PTPPort ptpPort, \ + struct ioh1588PtpMsgData *ptpMsgData) +{ + unsigned long locked_mode = FALSE; + + enum ioh1588PTPPortMode port_mode = IOH_1588PTP_PORT_MODE_INVALID; + enum ioh1588PTPVersion ptpVersion = IOH_1588PTP_VERSION_INVALID; + enum ioh1588PTPOperationMode opMode = IOH_1588PTP_OP_MODE_INVALID; + + /* Verify the parameters for proper values */ + if ((ptpPort != IOH_1588_GBE_0_1588PTP_PORT) || + ((struct ioh1588PtpMsgData *) NULL == ptpMsgData)) { + IOH_LOG(KERN_ERR, + "ioh_1588_ptp_rx_poll:invalid port or ptp message \ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + /*Get the PTP version */ + ptpVersion = ioh_1588_version_get(); + + /*check if locked/unlocked mode */ + if (ptpVersion == IOH_1588PTP_VERSION_0) { /*PTP v1 only */ + /* Get the Mode of the PTP Port if only PTPv1 is supported */ + port_mode = ioh_1588_port_mode_get(ptpPort); + if (port_mode != IOH_1588PTP_PORT_ANYMODE) + locked_mode = TRUE; + } else { /*PTP v1 & v2 */ + + /*get operation mode */ + opMode = ioh_1588_op_mode_get(); + if ((opMode != IOH_1588PTP_OP_MODE_V1_ALL_MSGS) && + (opMode != IOH_1588PTP_OP_MODE_V1_V2_ALL_MSGS)) { + locked_mode = TRUE; + } + } + + /*if locked mode,check event flag */ + if ((TRUE == locked_mode) && (TRUE != ioh_1588_rx_snap_evt())) { + IOH_DEBUG + ("ioh_1588_ptp_rx_poll:locked mode-event flag not set\n"); + IOH_DEBUG("ioh_1588_ptp_rx_poll:NO TIMESTAMP \ + returning IOH_1588_NOTIMESTAMP\n"); + return IOH_1588_NOTIMESTAMP; + } + + /* Fetch the receive timestamp */ + IOH_DEBUG("ioh_1588_ptp_rx_poll:invoking ioh_1588_rx_snap_get\n"); + ioh_1588_rx_snap_get(&ptpMsgData->ptpTimeStamp.timeValueLowWord, + &ptpMsgData->ptpTimeStamp.timeValueHighWord); + + IOH_DEBUG + ("ioh_1588_ptp_rx_poll:ioh_1588_ptp_rx_poll Snapshot (Hi:Low): \ + %lx : %lx\n", + ptpMsgData->ptpTimeStamp.timeValueHighWord, + ptpMsgData->ptpTimeStamp.timeValueLowWord); + + /* Fetch the UUID & Seq# of PTP messages in 'Master/Slave Mode' only */ + if ((TRUE == locked_mode) && (IOH_1588PTP_VERSION_0 == ptpVersion)) { + IOH_DEBUG + ("ioh_1588_ptp_rx_poll:invoking ioh_1588_uuid_seqid_get\n"); + ioh_1588_uuid_seqid_get(&ptpMsgData->ptpUuid.uuidValueLowWord, + &ptpMsgData->ptpUuid. + uuidValueHighHalfword, + &ptpMsgData->ptpSequenceNumber); + } + /* Clear-off the UUID & Seq# of all the messages in 'Any Mode' */ + else { + IOH_DEBUG + ("ioh_1588_ptp_rx_poll:port mode is ANYMODE,clearing off \ + UUID & SeqNumber\n"); + ptpMsgData->ptpUuid.uuidValueLowWord = 0; + ptpMsgData->ptpUuid.uuidValueHighHalfword = 0; + ptpMsgData->ptpSequenceNumber = 0; + } + + /* Increment receive timestamp counter + * Note:In unlocked modes,this will get incremented + * for every rx time stamp poll. + */ + ioh_1588_stats.rxMsgs++; + IOH_DEBUG("ioh_1588_ptp_rx_poll:incremented rcv timestamp \ + counter=%ld\n", ioh_1588_stats.rxMsgs); + + /* + * Fill-in the PTP message type.This can be done + * only when PTP v1 alone is supported and mode + * is master/slave.Set the message type as unknown + * for all other cases. + */ + if (ptpVersion == IOH_1588PTP_VERSION_0) { /*PTP v1 only */ + switch (port_mode) { + case IOH_1588PTP_PORT_MASTER: + { + IOH_DEBUG + ("ioh_1588_ptp_rx_poll:PTP message type=\ + IOH_1588PTP_MSGTYPE_DELAYREQ\n"); + ptpMsgData->ptpMsgType = + IOH_1588PTP_MSGTYPE_DELAYREQ; + break; + } + case IOH_1588PTP_PORT_SLAVE: + { + IOH_DEBUG + ("ioh_1588_ptp_rx_poll:PTP message type=\ + IOH_1588PTP_MSGTYPE_SYNC\n"); + ptpMsgData->ptpMsgType = + IOH_1588PTP_MSGTYPE_SYNC; + break; + } + case IOH_1588PTP_PORT_ANYMODE: + { + IOH_DEBUG + ("ioh_1588_ptp_rx_poll:PTP message type=\ + IOH_1588PTP_MSGTYPE_UNKNOWN\n"); + ptpMsgData->ptpMsgType = + IOH_1588PTP_MSGTYPE_UNKNOWN; + break; + } + default: + { + IOH_LOG(KERN_ERR, + "ioh_1588_ptp_rx_poll(): Invalid Port \ + Mode \ + returning IOH_1588_FAILED\n"); + return IOH_1588_FAILED; + } + } + } else { /*PTP v1 & v2 */ + + IOH_DEBUG + ("ioh_1588_ptp_rx_poll:PTP message type=\ + IOH_1588PTP_MSGTYPE_UNKNOWN\n"); + ptpMsgData->ptpMsgType = IOH_1588PTP_MSGTYPE_UNKNOWN; + } + + /* If locked mode allow next timestamp to be captured */ + if (TRUE == locked_mode) { + IOH_DEBUG + ("ioh_1588_ptp_rx_poll:invoking \ + ioh_1588_rx_snap_evt_clear\n"); + ioh_1588_rx_snap_evt_clear(); + } + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_ptp_tx_poll( + * enum ioh1588PTPPort ptpPort, + * struct ioh1588PtpMsgData *ptpMsgData) + * + * @brief Poll the IEEE 1588 Hardware Assist transmit side message/time + * stamp + * detection status for given PTP Port + * + * @remarks This API will poll for the availability of a time stamp on the + * transmit side Sync (in master mode) or Delay_Req (in slave mode) + * messages. + * The buffer is provided by the caller. + * The main tasks performed by this function are: + * - If ptpPort not valid or ptpMsgData is NULL + * return IOH_1588_INVALID_PARAM + * - Find out whether locked /unlocked mode. + * - If locked mode ,check the TS_Channel_Event register for Tx + * event + * - If locked mode, return NO TIMESTAMP if no Tx event flag is + * set. + * - Read the time stamp from XMIT_Snapshot low, high registers + * - Increment TX messages captured statistics counter + * - If locked mode, clear the TX event is TS_Channel_Event + * register + * + * + * @param ptpPort [IN] port on which time stamp availability to be + * checked + * @param ptpMsgData [OUT] Captured time stamp and other message + * information + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARAM - Invalid parameters passed + * @li IOH_1588_NOTIMESTAMP - Time stamp not available + * @li IOH_1588_FAILED - Internal error occurred + */ +enum ioh_status +ioh_1588_ptp_tx_poll(enum ioh1588PTPPort ptpPort, \ + struct ioh1588PtpMsgData *ptpMsgData) +{ + unsigned long locked_mode = FALSE; + + enum ioh1588PTPPortMode port_mode = IOH_1588PTP_PORT_MODE_INVALID; + enum ioh1588PTPVersion ptpVersion = IOH_1588PTP_VERSION_INVALID; + enum ioh1588PTPOperationMode opMode = IOH_1588PTP_OP_MODE_INVALID; + + /* Verify the parameters for proper values */ + if ((ptpPort != IOH_1588_GBE_0_1588PTP_PORT) || + ((struct ioh1588PtpMsgData *) NULL == ptpMsgData)) { + IOH_LOG(KERN_ERR, + "ioh_1588_ptp_tx_poll:invalid port or ptp message \ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + /*Get the PTP version */ + ptpVersion = ioh_1588_version_get(); + + /*check if locked/unlocked mode */ + if (ptpVersion == IOH_1588PTP_VERSION_0) { /*PTP v1 only */ + /* Get the Mode of the PTP Port if only PTPv1 is supported */ + port_mode = ioh_1588_port_mode_get(ptpPort); + if (port_mode != IOH_1588PTP_PORT_ANYMODE) + locked_mode = TRUE; + } else { /*PTP v1 & v2 */ + + /*get operation mode */ + opMode = ioh_1588_op_mode_get(); + if ((opMode != IOH_1588PTP_OP_MODE_V1_ALL_MSGS) && + (opMode != IOH_1588PTP_OP_MODE_V1_V2_ALL_MSGS)) { + locked_mode = TRUE; + } + } + + /*if locked mode,check event flag */ + if ((TRUE == locked_mode) && (TRUE != ioh_1588_tx_snap_evt())) { + IOH_DEBUG + ("ioh_1588_ptp_tx_poll:locked mode-event flag not set\n"); + IOH_DEBUG + ("ioh_1588_ptp_tx_poll:ioh_1588_ptp_tx_poll NO TIMESTAMP \ + returning IOH_1588_NOTIMESTAMP\n"); + return IOH_1588_NOTIMESTAMP; + } + + /* read time stamp registers */ + ioh_1588_tx_snap_get(&ptpMsgData->ptpTimeStamp.timeValueLowWord, + &ptpMsgData->ptpTimeStamp.timeValueHighWord); + + IOH_DEBUG + ("ioh_1588_ptp_tx_poll:ioh_1588_ptp_tx_poll Snapshot (Hi:Low): \ + %lx : %lx\n", + ptpMsgData->ptpTimeStamp.timeValueHighWord, + ptpMsgData->ptpTimeStamp.timeValueLowWord); + /* + * Fill the UUID and Seq# with invalid values (zeros) + * since they are not relevant for transmit timestamp + */ + ptpMsgData->ptpUuid.uuidValueLowWord = 0; + ptpMsgData->ptpUuid.uuidValueHighHalfword = 0; + ptpMsgData->ptpSequenceNumber = 0; + + /* + * Increment transmit timestamp counter + * Note:In unlocked modes,this will get incremented + * for every tx time stamp poll + */ + ioh_1588_stats.txMsgs++; + IOH_DEBUG("ioh_1588_ptp_tx_poll:incremented tx timestamp counter=%ld\n", + ioh_1588_stats.txMsgs); + + /* + * Fill-in the PTP message type.This can be done + * only when PTP v1 alone is supported and mode + * is master/slave.Set the message type as unknown + * for all other cases. + */ + if (ptpVersion == IOH_1588PTP_VERSION_0) { /*PTP v1 only */ + switch (port_mode) { + case IOH_1588PTP_PORT_MASTER: + { + IOH_DEBUG + ("ioh_1588_ptp_tx_poll:PTP message type=\ + IOH_1588PTP_MSGTYPE_SYNC\n"); + ptpMsgData->ptpMsgType = + IOH_1588PTP_MSGTYPE_SYNC; + break; + } + case IOH_1588PTP_PORT_SLAVE: + { + IOH_DEBUG + ("ioh_1588_ptp_tx_poll:PTP message type=\ + IOH_1588PTP_MSGTYPE_DELAYREQ\n"); + ptpMsgData->ptpMsgType = + IOH_1588PTP_MSGTYPE_DELAYREQ; + break; + } + case IOH_1588PTP_PORT_ANYMODE: + { + IOH_DEBUG + ("ioh_1588_ptp_tx_poll:PTP message type=\ + IOH_1588PTP_MSGTYPE_UNKNOWN\n"); + ptpMsgData->ptpMsgType = + IOH_1588PTP_MSGTYPE_UNKNOWN; + break; + } + default: + { + IOH_LOG(KERN_ERR, + "ioh_1588_ptp_tx_poll(): \ + Invalid Port Mode \ + returning IOH_1588_FAILED\n"); + return IOH_1588_FAILED; + } + } + } else { /*PTP v1 & v2 */ + + IOH_DEBUG + ("ioh_1588_ptp_tx_poll:PTP message type=\ + IOH_1588PTP_MSGTYPE_UNKNOWN\n"); + ptpMsgData->ptpMsgType = IOH_1588PTP_MSGTYPE_UNKNOWN; + } + + /* If locked mode allow next timestamp to be captured */ + if (locked_mode) { + IOH_DEBUG + ("ioh_1588_ptp_tx_poll:invoking ioh_1588_tx_snap_evt_clear\n"); + ioh_1588_tx_snap_evt_clear(); + } + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_system_time_set( + * struct ioh1588TimeValue systemTime) + * + * @brief This API sets the system time to given value + * @remarks Sets the System Time in the IEEE 1588 hardware assist block. + * + * @param systemTime [IN] value to set the system time to + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + */ +enum ioh_status ioh_1588_system_time_set(struct ioh1588TimeValue systemTime) +{ + unsigned long old_fsv = 0; + + /* Retrieve old Frequency Scaling Value */ + IOH_DEBUG("ioh_1588_system_time_set:invoking ioh_1588_addend_get\n"); + ioh_1588_addend_get(&old_fsv); + IOH_DEBUG("ioh_1588_system_time_set:existing freq scaling value=%lx\n", + old_fsv); + + /* + * Set the Frequency Scaling Value to zero (0) so that + * System Time doesn't get incremented while it is being written to + */ + IOH_DEBUG("ioh_1588_system_time_set:invoking ioh_1588_addend_set \ + to set frequncy scaling value to 0\n"); + ioh_1588_addend_set(0); + + /* Update System Time with user specified values */ + IOH_DEBUG("ioh_1588_system_time_set:invoking \ + ioh_1588_ioh_1588_sys_snap_set \ + with values low=%lx,high=%lx\n", + systemTime.timeValueLowWord, systemTime.timeValueHighWord); + ioh_1588_sys_snap_set(systemTime.timeValueLowWord, + systemTime.timeValueHighWord); + + /* + * Let the hardware assist re-evaluate the target time reached + * condition based on the new system time + */ + IOH_DEBUG("ioh_1588_system_time_set:invoking ioh_1588_ttm_evt_clear\n"); + ioh_1588_ttm_evt_clear(); + + /* + * Restore old Frequency Scaling Value so that System Time + * can be incremented + */ + IOH_DEBUG("ioh_1588_system_time_set:invoking ioh_1588_addend_set \ + to restore freq scaling value\n"); + ioh_1588_addend_set(old_fsv); + + IOH_DEBUG("ioh_1588_system_time_set:returning IOH_1588_SUCCESS\n"); + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_system_time_get( + * struct ioh1588TimeValue *systemTime) + * + * @brief Gets the System Time from the IEEE 1588 hardware assist block + * @remarks This API gets the System time. + * The main steps followed in this function are: + * - Return IOH_1588_INVALIDPARAM if argument passed is NULL + * - Return the current system time by reading the SystemTime low, + * high registers + * + * + * @param systemTime [OUT] - Address to which system time is to be + * returned + * + * @return enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARAM - Invalid address passed + */ +enum ioh_status ioh_1588_system_time_get(struct ioh1588TimeValue *systemTime) +{ + /* Verify the parameter */ + if ((struct ioh1588TimeValue *) NULL == systemTime) { + IOH_LOG(KERN_ERR, "ioh_1588_system_time_get:invalid parameter \ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + /* Fetch System Time */ + ioh_1588_sys_snap_get(&systemTime->timeValueLowWord, + &systemTime->timeValueHighWord); + + IOH_DEBUG("ioh_1588_system_time_get:invoked \ + ioh_1588_ioh_1588_sys_snap_get \ + system time:low=%lx,high=%lx\n", + systemTime->timeValueLowWord, systemTime->timeValueHighWord); + IOH_DEBUG("ioh_1588_system_time_get returning IOH_1588_SUCCESS\n"); + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_tick_rate_set(unsigned long tickRate) + * + * @brief Sets the Frequency Scaling Value in the IEEE 1588 hardware + * assist block + * + * @remarks This API sets the Tick Rate (Frequency Scaling Value) in the + * IEEE 1588 block. This value determines the progress at which + * the System time advances. + * Note: For the A1 hardware sample, the addend register value + * configured in the hardware + * is calculated as follows: + * Addend register value = Logical right shift tickRate by 1 and + * set MSB to 1 + * + * @param tickRate [IN] Frequency scaling value + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + */ +enum ioh_status ioh_1588_tick_rate_set(unsigned long tickRate) +{ + /* Update the Frequency Scaling Value */ +#ifdef IOH_IEEE1588_A1_SAMPLE_BUG + /*back up tick rate provided by app */ + gTickRateApp = tickRate; + /*calculate actual tick rate for device */ + IOH_DEBUG("ioh_1588_tick_rate_set:tick rate [app]=%lx\n", tickRate); + tickRate = ((tickRate >> 1) | 0x80000000); + IOH_DEBUG("ioh_1588_tick_rate_set:tick rate [dev]=%lx\n", tickRate); +#endif + IOH_DEBUG("ioh_1588_tick_rate_set:invoking ioh_1588_addend_set \ + with tick rate=%lx\n", tickRate); + ioh_1588_addend_set(tickRate); + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_tick_rate_get(unsigned long *tickRate) + * + * @brief Gets the Frequency Scaling Value from the IEEE 1588 hardware + * assist block + * + * @remarks This API gets the Tick Rate (Frequency Scaling Value) used in + * the IEEE 1588 block. + * This value determines the progress at which the System time + * advances. + * The main steps followed in this function are: + * - Return IOH_1588_INVALIDPARAM if argument passed is NULL + * - Return the content of Addend register + * + * + * @param tickRate [IN] - Address where current Frequency scaling value is + * returned + * + * @return enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARM - Invalid address passed + */ +enum ioh_status ioh_1588_tick_rate_get(unsigned long *tickRate) +{ + /* Verify the parameter */ + if ((unsigned long *)NULL == tickRate) { + IOH_LOG(KERN_ERR, "ioh_1588_tick_rate_get:invalid tick rate\ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } +#ifdef IOH_IEEE1588_A1_SAMPLE_BUG + /* Retrieve Frequency Scaling Value stored in software buffer */ + *tickRate = gTickRateApp; +#else + /* Retrieve Current Frequency Scaling Value */ + ioh_1588_addend_get(tickRate); +#endif + IOH_DEBUG("ioh_1588_tick_rate_get:invoked ioh_1588_addend_get\ + the tick rate=%lx\n", *tickRate); + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_target_time_interrupt_enable( + * ioh1588TargetTimeCallback callBack) + * + * @brief Enable the target time reached/exceeded system time interrupt + * + * @remarks This API enables the interrupt that occurs when the System time + * reaches the Target time set in the IEEE 1588 hardware assist + * block. + * The main steps followed in this function are: + * - Return IOH_1588_INVALIDPARAM if argument passed is NULL + * - Modify Time Sync Control Register to enable target time + * interrupt + * - Set the handler to callback function provided + * + * + * @param callBack [IN] - Routine to be invoked when target time reached + * interrupt occurs + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARAM - Null parameter passed for callback + */ +enum ioh_status +ioh_1588_target_time_interrupt_enable(ioh1588TargetTimeCallback callBack) +{ + /* Verify the parameter */ + if ((ioh1588TargetTimeCallback) NULL == callBack) { + IOH_LOG(KERN_ERR, "ioh_1588_target_time_interrupt_enable\ + invalid callback;returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + /* Register the Callback */ + ioh_tt_cbptr = callBack; + + /* Set target time interrupt mask */ + IOH_DEBUG("ioh_1588_target_time_interrupt_enable:invoking\ + ioh_1588_ttm_imask_set\n"); + ioh_1588_ttm_imask_set(); + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_target_time_interrupt_disable(void) + * + * @brief Disable the target time reached/exceeded system time interrupt + * + * @remarks This API disables the interrupt that occurs when the System time + * reaches the Target time set in the IEEE 1588 hardware assist + * block. + * The main steps followed in this function are: + * - Modify Time Sync Control Register to disable target time + * interrupt + * - Clear the callback handler + * + * @param None + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + */ +enum ioh_status ioh_1588_target_time_interrupt_disable(void) +{ + /* Clear target time interrupt mask */ + IOH_DEBUG("ioh_1588_target_time_interrupt_disable:invoking \ + ioh_1588_ttm_imask_clear\n"); + ioh_1588_ttm_imask_clear(); + + /* Unregister the Callback */ + ioh_tt_cbptr = (ioh1588TargetTimeCallback) NULL; + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_target_time_poll( + * unsigned long *ttmPollFlag, struct ioh1588TimeValue *targetTime) + * + * @brief Poll to verify whether the System time is greater or equal + * to the Target time in the IEEE 1588 hardware assist block. + * + * @remarks The main steps followed in this function are: + * - Validate the parameters and return IOH_1588_INVALIDPARAM, if + * not valid + * - If callback function registered, return status + * IOH_1588_INTERRUPTMODEINUSE + * - Read the TS_Event register to check for the presence of valid + * snapshot + * - Read the TargetTimeSnap low, high registers + * - Clear the event from TS_Event register + * + * + * @param ttmPollFlag [OUT] TRUE if target time has reached system + * time + * FALSE if target time has not reached + * system time + * @param targetTime [OUT] Snap shot of target time captured + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARAM - Null parameter passed + * @li IOH_1588_INTERRUPTMODEINUSE - Interrupt mode is in use + */ +enum ioh_status +ioh_1588_target_time_poll(unsigned long *ttmPollFlag, + struct ioh1588TimeValue *targetTime) +{ + /* Verify the parameters */ + if (((unsigned long *)NULL == ttmPollFlag) || + ((struct ioh1588TimeValue *) NULL == targetTime)) { + IOH_LOG(KERN_ERR, "ioh_1588_target_time_poll: invalid param\ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + /* Is interrupt mode of processing is enabled? */ + if ((ioh1588TargetTimeCallback) NULL != ioh_tt_cbptr) { + IOH_LOG(KERN_ERR, + "ioh_1588_target_time_poll:returning \ + IOH_1588_INTERRUPTMODEINUSE\n"); + return IOH_1588_INTERRUPTMODEINUSE; + } + + /* Is the System Time reached or exceeded Target Time? */ + *ttmPollFlag = ioh_1588_ttm_evt_get(); + if (FALSE == *ttmPollFlag) { + IOH_DEBUG + ("ioh_1588_target_time_poll:target time not reached\n"); + /* Target Time not to be returned yet */ + targetTime->timeValueLowWord = 0; + targetTime->timeValueHighWord = 0; + + return IOH_1588_SUCCESS; + } + + IOH_DEBUG("ioh_1588_target_time_poll:target time reached\n"); + /* Get the Target Time */ + ioh_1588_tgt_snap_get(&targetTime->timeValueLowWord, + &targetTime->timeValueHighWord); + + IOH_DEBUG("ioh_1588_target_time_poll:target time:low=%lx high=%lx\n", + targetTime->timeValueLowWord, targetTime->timeValueHighWord); + + IOH_DEBUG + ("ioh_1588_target_time_poll:invoking ioh_1588_ttm_evt_clear\n"); + /* Clear the target time reached condition (ttipend bit) */ + ioh_1588_ttm_evt_clear(); + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_target_time_set( + * struct ioh1588TimeValue targetTime) + * + * @brief Sets the Target Time in the IEEE 1588 hardware assist block + * + * @remarks This API will set the Target Time to a given value. + * + * @param targetTime [IN] - Target time to set + * + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + */ +enum ioh_status ioh_1588_target_time_set(struct ioh1588TimeValue targetTime) +{ + unsigned long old_mask = FALSE; + + /* Retrieve existing target time interrupt mask value */ + old_mask = ioh_1588_ttm_imask_get(); + IOH_DEBUG("ioh_1588_target_time_set:target time interrupt mask=%lx\n", + old_mask); + + /* + * Clear the target time interrupt mask so that the interrupt will not + * come + * during the time we manipulate the registers. + */ + IOH_DEBUG("ioh_1588_target_time_set:invoking ioh_1588_ttm_imask_clear\ + to clear the target time interrupt mask\n"); + ioh_1588_ttm_imask_clear(); + + IOH_DEBUG("ioh_1588_target_time_set:invoking ioh_1588_tgt_snap_set \ + with values:low=%lx,high=%lx\n", \ + targetTime.timeValueLowWord, targetTime.timeValueHighWord); + /* Update Target Time with user specified values */ + ioh_1588_tgt_snap_set(targetTime.timeValueLowWord, + targetTime.timeValueHighWord); + + /* + * Let the hardware assist re-evaluate the target time reached + * condition based on the new target time + */ + IOH_DEBUG("ioh_1588_target_time_set:invoking ioh_1588_ttm_evt_clear\n"); + ioh_1588_ttm_evt_clear(); + + /* Restore the preserved target time interrupt mask value */ + if (TRUE == old_mask) { + IOH_DEBUG + ("ioh_1588_target_time_set:invoking \ + ioh_1588_ttm_imask_set\n"); + ioh_1588_ttm_imask_set(); + } + + IOH_DEBUG("ioh_1588_target_time_set:returning IOH_1588_SUCCESS\n"); + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_target_time_get( + * struct ioh1588TimeValue *targetTime) + * + * @brief Gets the Target Time in the IEEE 1588 hardware assist block + * + * @remarks This API will get the Target Time from IEEE 1588 block + * - Return IOH_1588_INVALIDPARAM if argument passed is NULL + * - Read and return the content of TargetTime low, high registers + * + * + * @param targetTime [IN] - Address to which target time is to be returned + * + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARAM - Null parameter passed + */ +enum ioh_status ioh_1588_target_time_get(struct ioh1588TimeValue *targetTime) +{ + /* Verify the parameter */ + if ((struct ioh1588TimeValue *) NULL == targetTime) { + IOH_DEBUG("ioh_1588_target_time_get:invalid param \ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + /* Get Target Time */ + ioh_1588_tgt_snap_get(&targetTime->timeValueLowWord, + &targetTime->timeValueHighWord); + IOH_DEBUG("ioh_1588_target_time_get:invoked ioh_1588_tgt_snap_get \ + target time:low=%lx,high:%lx\n", \ + targetTime->timeValueLowWord, targetTime->timeValueHighWord); + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_aux_time_interrupt_enable( + * enum ioh1588AuxMode auxMode,ioh1588AuxTimeCallback callBack) + * + * @brief Enables the interrupt for the Auxiliary Master/Slave mode for + * Time + * Stamp in the IEEE 1588 hardware assist block + * + * @remarks This API will enable the Auxiliary Master/Slave + * Time stamp Interrupt. The main steps followed in + * this function are: + * - Return IOH_1588_INVALIDPARAM if argument passed is NULL + * - Modify the Time Sync Controller register to enable the + * interrupt + * - Set the callback routine + * + * + * @param auxMode [IN] - Auxiliary slave or master mode + * @param callBack [IN] - Callback to be invoked when interrupt + * fires + * + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARAM - Null parameter passed + */ +enum ioh_status +ioh_1588_aux_time_interrupt_enable(enum ioh1588AuxMode auxMode, + ioh1588AuxTimeCallback callBack) +{ + /* Verify the parameters */ + if ((IOH_1588_AUXMODE_INVALID <= auxMode) || + ((ioh1588AuxTimeCallback) NULL == callBack)) { + IOH_DEBUG("ioh_1588_aux_time_interrupt_enable:invalid param \ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + /* Register the Callback and SET the amm/asm bits on */ + if (IOH_1588_AUXMODE_MASTER == auxMode) { + IOH_DEBUG + ("ioh_1588_aux_time_interrupt_enable:IOH_1588_AUXMODE_MASTER \ + invoking ioh_1588_amms_imask_set\n"); + ioh_am_cbptr = callBack; + ioh_1588_amms_imask_set(); + + } else { + IOH_DEBUG + ("ioh_1588_aux_time_interrupt_enable:IOH_1588_AUXMODE_SLAVE \ + invoking ioh_1588_asms_imask_set\n"); + ioh_as_cbptr = callBack; + ioh_1588_asms_imask_set(); + } + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_aux_time_interrupt_disable( + * enum ioh1588AuxMode auxMode) + * + * @brief Disables the interrupt for the Auxiliary Master/Slave mode for + * Time + * Stamp in the IEEE 1588 hardware assist block + * + * @remarks This API will disable the Auxiliary Master/Slave + * Time stamp Interrupt. The main steps followed in this + * function are: + * - Return IOH_1588_INVALIDPARAM if auxMode passed is not valid + * - Modify the Time Sync Controller register to disable the + * interrupt + * - Clear the callback handler + * + * + * @param auxMode [IN] - Auxiliary slave or master mode + * + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARAM - Invalid mode specified + */ +enum ioh_status ioh_1588_aux_time_interrupt_disable(enum ioh1588AuxMode auxMode) +{ + /* Verify the parameters */ + if (IOH_1588_AUXMODE_INVALID <= auxMode) { + IOH_DEBUG("ioh_1588_aux_time_interrupt_disable:invalid param \ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + if (IOH_1588_AUXMODE_MASTER == auxMode) { + IOH_DEBUG + ("ioh_1588_aux_time_interrupt_disable:\ + IOH_1588_AUXMODE_MASTER\ + invoking ioh_1588_amms_imask_clear\n"); + ioh_1588_amms_imask_clear(); + ioh_am_cbptr = (ioh1588AuxTimeCallback) NULL; + } else { + IOH_DEBUG + ("ioh_1588_aux_time_interrupt_disable:\ + IOH_1588_AUXMODE_SLAVE\ + invoking ioh_1588_asms_imask_clear\n"); + ioh_1588_asms_imask_clear(); + ioh_as_cbptr = (ioh1588AuxTimeCallback) NULL; + } + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_aux_time_poll( + * enum ioh1588AuxMode auxMode, unsigned long *pollFlag, + * struct ioh1588TimeValue*auxTime) + * + * @brief Poll for the Auxiliary Time Stamp captured event for the mode + * requested + * + * @remarks Polls for the Time stamp in the appropriate Auxiliary Snapshot + * Registers based on the mode specified. Return true and + * the contents of the Auxiliary snapshot if it is available + * otherwise return false. The main steps followed in this function + * are: + * - Validate the parameters and return IOH_1588_INVALIDPARAM if + * found invalid + * - If callbacks registered, return status + * IOH_1588_INTERRUPTMODEINUSE + * - Read the TS_Event register to check for the presence of valid + * snapshot + * - If the event is not set, return status IOH_1588_NOTIMESTAMP + * - Read the AuxSlaveModeSnap or AuxMasterModeSnap low, high + * registers depending on the auxMode + * - Clear the event from TS_Event register + * + * + * @param auxMode [IN] Auxiliary Snapshot Register + * (Master/Slave) to be checked + * @param pollFlag [OUT] TRUE if time stamp captured in aux + * snapshot register + * FALSE if the time stamp not captured + * @param auxTime [OUT] Buffer for returning captured Auxiliary + * Snapshot time + * + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARAM - Invalid parameter passed + * @li IOH_1588_INTERRUPTMODEINUSE - Interrupt mode is in use + */ +enum ioh_status +ioh_1588_aux_time_poll(enum ioh1588AuxMode auxMode, unsigned long *pollFlag, + struct ioh1588TimeValue *auxTime) +{ + unsigned long ammsFlag = FALSE; + unsigned long asmsFlag = FALSE; + + /* Verify the parameters */ + if (((unsigned long *)NULL == pollFlag) || + (IOH_1588_AUXMODE_INVALID <= auxMode) || + ((struct ioh1588TimeValue *) NULL == auxTime)) { + IOH_DEBUG("ioh_1588_aux_time_poll:invalid param \ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + /* Get Auxiliary Master/Slave Mode Snapshot */ + if (IOH_1588_AUXMODE_MASTER == auxMode) { + IOH_DEBUG("ioh_1588_aux_time_poll:IOH_1588_AUXMODE_MASTER\n"); + /* Is interrupt mode of processing is enabled? */ + if ((ioh1588AuxTimeCallback) NULL != ioh_am_cbptr) { + IOH_DEBUG + ("ioh_1588_aux_time_poll:interrupt mode in use\n"); + return IOH_1588_INTERRUPTMODEINUSE; + } + + /* Is the Auxiliary Master Mode Snapshot available? */ + ammsFlag = ioh_1588_amms_evt_get(); + if (FALSE == ammsFlag) { + IOH_DEBUG("ioh_1588_aux_time_poll:NO Auxiliary Master \ + Mode Snapshot available\n"); + *pollFlag = FALSE; + auxTime->timeValueLowWord = 0; + auxTime->timeValueHighWord = 0; + return IOH_1588_SUCCESS; + } + + /* Get Auxiliary Master Snapshot */ + ioh_1588_aux_master_snap_get(&auxTime->timeValueLowWord, + &auxTime->timeValueHighWord); + IOH_DEBUG("ioh_1588_aux_time_poll:Auxiliary Master Snapshot \ + low=%lx,high=%lx\n", auxTime->timeValueLowWord, \ + auxTime->timeValueHighWord); + + *pollFlag = TRUE; + + /* Clear the snapshot availability condition */ + IOH_DEBUG + ("ioh_1588_aux_time_poll:invoking ioh_1588_amms_evt_clear\n"); + ioh_1588_amms_evt_clear(); + } else { /* IOH_1588_AUXMODE_SLAVE == auxMode */ + + IOH_DEBUG("ioh_1588_aux_time_poll:IOH_1588_AUXMODE_SLAVE\n"); + /* Is interrupt mode of processing is enabled? */ + if ((ioh1588AuxTimeCallback) NULL != ioh_as_cbptr) { + IOH_DEBUG + ("ioh_1588_aux_time_poll:interrupt mode in use\n"); + return IOH_1588_INTERRUPTMODEINUSE; + } + + /* Is the Auxiliary Slave Mode Snapshot available? */ + asmsFlag = ioh_1588_asms_evt_get(); + if (FALSE == asmsFlag) { + IOH_DEBUG("ioh_1588_aux_time_poll:NO Auxiliary Slave \ + Mode Snapshot available\n"); + *pollFlag = FALSE; + auxTime->timeValueLowWord = 0; + auxTime->timeValueHighWord = 0; + return IOH_1588_SUCCESS; + } + + /* Get Auxiliary Slave Snapshot */ + ioh_1588_aux_slave_snap_get(&auxTime->timeValueLowWord, + &auxTime->timeValueHighWord); + IOH_DEBUG("ioh_1588_aux_time_poll:Auxiliary Slave Snapshot \ + low=%lx,high=%lx\n", auxTime->timeValueLowWord, \ + auxTime->timeValueHighWord); + + *pollFlag = TRUE; + + /* Clear the snapshot availability condition */ + IOH_DEBUG + ("ioh_1588_aux_time_poll:invoking ioh_1588_amms_evt_clear\n"); + ioh_1588_asms_evt_clear(); + } + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_reset(void) + * + * @brief Resets the IEEE 1588 hardware assist block + * + * @remarks Resets the IEEE 1588 hardware assist block. The + * main steps followed in this function are: + * - Set the reset bit of Time Sync Control register + * - Clear the reset bit of Time Sync Control register + * -Note: For A0/A1 sample, test mode setting is enabled for + * the 64 bit System Time Register. This is a work around for + * the non continuous value in the 64 bit System Time Register + * consisting of High(32bit) / Low(32bit) + * + * + * @param None + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation is successful + */ +enum ioh_status ioh_1588_reset(void) +{ + /* Reset Hardware Assist */ + IOH_DEBUG("ioh_1588_reset:invoking ioh_1588_block_reset\n"); + ioh_1588_block_reset(); + + /* Clear Stats */ + ioh_1588_stats.rxMsgs = ioh_1588_stats.txMsgs = 0; + + /* Unregister any Callback Routines */ + IOH_DEBUG("ioh_1588_reset:unregistering callbacks\n"); + ioh_pps_cbptr = (ioh1588PulsePerSecondCallback) NULL; + ioh_am_cbptr = (ioh1588AuxTimeCallback) NULL; + ioh_as_cbptr = (ioh1588AuxTimeCallback) NULL; + ioh_tt_cbptr = (ioh1588TargetTimeCallback) NULL; + +#ifdef IOH_IEEE1588_A0_A1_SAMPLE_BUG + /*enable all 32 bits in system time registers */ + ioh_1588_set_system_time_count(); +#endif + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_chnl_reset(enum ioh1588PTPPort ptpPort) + * + * @brief Resets the IEEE 1588 channel by resetting the hardware block + * + * @remarks This API also sets the reset bit in the IEEE1588 to fully + * resets the block. The main steps followed in this function + * are: + * - Return IOH_1588_INVALIDPARAM if ptpPort passed is not valid + * - Perform a block level reset by invoking ioh_1588_reset + * + * + * @param ptpPort [IN] The PTP port that is to be reset + * + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + */ +enum ioh_status ioh_1588_chnl_reset(enum ioh1588PTPPort ptpPort) +{ + IOH_DEBUG("ioh_1588_chnl_reset:invoking ioh_1588_reset\n"); + return ioh_1588_reset(); +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_stats_get(struct ioh1588Stats *stats) + * + * @brief Returns the ioh1588 Statistics + * + * @remarks This API will return the statistics of the snapshots captured + * for + * receive and transmit of messages. The main steps followed in + * this + * function are: + * - Return IOH_1588_INVALIDPARAM if argument passed is NULL + * - Return the counter values stored for Rx and Tx messages + * + * + * @param stats [OUT] Buffer for returning the statistics + * counter values + * + * + * @note These counters are updated only when the client application + * polls for + * the time stamps or interrupt are enabled. + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation is successful + * @li IOH_1588_INVALIDPARAM - NULL parameter passed + */ + +enum ioh_status ioh_1588_stats_get(struct ioh1588Stats *stats) +{ + /* Verify the parameter */ + if ((struct ioh1588Stats *) NULL == stats) { + IOH_DEBUG("ioh_1588_stats_get:invalid param \ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + /* Return the statistics */ + stats->rxMsgs = ioh_1588_stats.rxMsgs; + stats->txMsgs = ioh_1588_stats.txMsgs; + IOH_DEBUG("ioh_1588_stats_get:stats-txMsg=%lx,rxMsg=%lx\n", + stats->txMsgs, stats->rxMsgs); + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn void ioh_1588_stats_reset(void) + * + * @brief Resets the statistics counters + * + * @remarks This API will reset the statistics counters maintained by the + * driver + * + * @param None + * @retval None + */ +void ioh_1588_stats_reset(void) +{ + /* Clear the statistics */ + IOH_DEBUG("ioh_1588_stats_reset:clearing stats\n"); + ioh_1588_stats.rxMsgs = ioh_1588_stats.txMsgs = 0; + + return; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn void ioh_1588_save_state(void) + * + * @brief Save the state of all registers + * + * @remarks Save the content of all registers of IEEE1588 module + * + * @param None. + * + * @retval None + */ +void ioh_1588_save_state(void) +{ + int i; + unsigned long val; + + /* Time stamp control register */ + ioh_1588_regs.ts_control = + (ioh_1588_ttm_imask_get() << IOH_1588_TSC_TTM_SHIFT) | + (ioh_1588_asms_imask_get() << IOH_1588_TSC_ASMS_SHIFT) | + (ioh_1588_amms_imask_get() << IOH_1588_TSC_AMMS_SHIFT) | + (ioh_1588_pps_imask_get() << IOH_1588_TSC_PPSM_SHIFT); + IOH_DEBUG("ioh_1588_save_state:TS_CONTROL reg=%lx\n", + ioh_1588_regs.ts_control); + + /* + * Time stamp event register; clear on write, + * so no point in reading and then saving; + * Will be cleared on restore to start in a clean slate + */ + ioh_1588_regs.ts_event = IOH_1588_TSE_TTIPEND | IOH_1588_TSE_SNS | + IOH_1588_TSE_SNM | IOH_1588_TSE_PPS; + IOH_DEBUG("ioh_1588_save_state:TS_EVENT reg=%lx\n", + ioh_1588_regs.ts_event); + + /* Addend register */ + ioh_1588_addend_get(&ioh_1588_regs.ts_addend); + IOH_DEBUG("ioh_1588_save_state:TS_ADDEND reg=%lx\n", + ioh_1588_regs.ts_addend); + + /* PPS comapre register */ + ioh_1588_pps_get(&ioh_1588_regs.ts_compare); + IOH_DEBUG("ioh_1588_save_state:TS_COMPARE reg=%lx\n", + ioh_1588_regs.ts_compare); + + /* System time Low and Hi registers */ + ioh_1588_sys_snap_get(&ioh_1588_regs.ts_syslo, &ioh_1588_regs.ts_syshi); + IOH_DEBUG("ioh_1588_save_state:sys time reg-low =%lx,high=%lx\n", + ioh_1588_regs.ts_syslo, ioh_1588_regs.ts_syshi); + + /* Target time Low and Hi registers */ + ioh_1588_tgt_snap_get(&ioh_1588_regs.ts_tgtlo, &ioh_1588_regs.ts_tgthi); + IOH_DEBUG("ioh_1588_save_state:target time reg-low =%lx,high=%lx\n", + ioh_1588_regs.ts_tgtlo, ioh_1588_regs.ts_tgthi); + +#if 0 + /* + * Below registers are read only, so no point in reading/storing, since + * we can't restore them + */ + /* Slave mode snapshot Low and Hi registers */ + ioh_1588_aux_slave_snap_get(&ioh_1588_regs.ts_asmslo, + &ioh_1588_regs.ts_asmshi); + + /* Master mode snapshot Low and Hi registers */ + ioh_1588_aux_master_snap_get(&ioh_1588_regs.ts_ammslo, + &ioh_1588_regs.ts_ammshi); +#endif + ioh_1588_regs.ts_cc = + (ioh_1588_master_mode_get() << IOH_1588_CC_MM_SHIFT) | + (ioh_1588_timestamp_all_get() << IOH_1588_CC_TA_SHIFT) | + (ioh_1588_op_mode_get() << IOH_1588_CC_MODE_SHIFT) | + (ioh_1588_version_get() << IOH_1588_CC_VERSION_SHIFT); + IOH_DEBUG("ioh_1588_save_state:TS_CC reg=%lx\n", ioh_1588_regs.ts_cc); + + /* Channel event register, not saved - will be cleared on restore */ + ioh_1588_regs.ts_ce = IOH_1588_CE_TXS | IOH_1588_CE_RXS; + +#if 0 + /* + * Below registers are read only, so no point in reading/storing, since + * we can't restore them + */ + ioh_1588_rx_snap_get(&ioh_1588_regs.ts_xslo, &ioh_1588_regs.ts_xshi); + ioh_1588_tx_snap_get(&ioh_1588_regs.ts_rslo, &ioh_1588_regs.ts_rshi); + ioh_1588_uuid_seqid_get(&ioh_1588_regs.ts_uuidlo, + &ioh_1588_regs.ts_uuidhi); + + /* CAN */ + ioh_1588_can_snap_get(&ioh_1588_regs.ts_cxslo, &ioh_1588_regs.ts_cxshi); +#endif + + /* CAN Channel event register, not saved - will be cleared on restore */ + ioh_1588_regs.ts_cce = IOH_1588_CE_OVR | IOH_1588_CE_VAL; + + /* Ethernet CAN selector register */ + ioh_1588_regs.ts_sel = + (ioh_1588_eth_enable_get() << IOH_1588_ECS_ETH_SHIFT) | + (ioh_1588_can_enable_get() << IOH_1588_ECS_CAN_SHIFT); + IOH_DEBUG("ioh_1588_save_state:TS_SEL reg=%lx\n", ioh_1588_regs.ts_sel); + + /* Station Address registers */ + for (i = 0; i < IOH_1588_STATION_BYTES; i++) { + ioh_1588_station_get(i, &val); + ioh_1588_regs.ts_sti[i] = val & 0xff; + IOH_DEBUG("ioh_1588_save_state:TS_ST[%d] reg=%d\n", i, + ioh_1588_regs.ts_sti[i]); + } +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn void ioh_1588_restore_state(void) + * + * @brief Restore the state of all registers + * + * @remarks Restores the content of all registers of IEEE1588 module. + * Note: For A0/A1 sample, test mode setting is enabled for + * the 64 bit System Time Register. This is a work around for + * the non continuous value in the 64 bit System Time + * Register + * consisting of High(32bit) / Low(32bit) + * + * @param None + * @retval None + */ +void ioh_1588_restore_state(void) +{ + int i; + + /* Time stamp control register */ + if (ioh_1588_regs.ts_control & IOH_1588_TSC_TTM_MASK) { + IOH_DEBUG + ("ioh_1588_restore_state:invoking ioh_1588_ttm_imask_set\n"); + ioh_1588_ttm_imask_set(); + } + if (ioh_1588_regs.ts_control & IOH_1588_TSC_ASMS_MASK) { + IOH_DEBUG + ("ioh_1588_restore_state:invoking ioh_1588_asms_imask_set\n"); + ioh_1588_asms_imask_set(); + } + if (ioh_1588_regs.ts_control & IOH_1588_TSC_AMMS_MASK) { + IOH_DEBUG + ("ioh_1588_restore_state:invoking ioh_1588_amms_imask_set\n"); + ioh_1588_amms_imask_set(); + } + if (ioh_1588_regs.ts_control & IOH_1588_TSC_PPSM_MASK) { + IOH_DEBUG + ("ioh_1588_restore_state:invoking ioh_1588_pps_imask_set\n"); + ioh_1588_pps_imask_set(); + } + + /* Time stamp event register; clear all events */ + IOH_DEBUG("ioh_1588_restore_state:invoking ioh_1588_ttm_evt_clear\n"); + ioh_1588_ttm_evt_clear(); + IOH_DEBUG("ioh_1588_restore_state:invoking ioh_1588_asms_evt_clear\n"); + ioh_1588_asms_evt_clear(); + IOH_DEBUG("ioh_1588_restore_state:invoking ioh_1588_amms_evt_clear\n"); + ioh_1588_amms_evt_clear(); + IOH_DEBUG("ioh_1588_restore_state:invoking ioh_1588_pps_evt_clear\n"); + ioh_1588_pps_evt_clear(); + +#ifdef IOH_IEEE1588_A0_A1_SAMPLE_BUG + /*enable all 32 bits in system time registers */ + ioh_1588_set_system_time_count(); +#endif + + /* Addend register */ + IOH_DEBUG("ioh_1588_restore_state:invoking ioh_1588_addend_set\n"); + ioh_1588_addend_set(ioh_1588_regs.ts_addend); + + /* PPS comapre register */ + IOH_DEBUG("ioh_1588_restore_state:invoking ioh_1588_pps_set\n"); + ioh_1588_pps_set(ioh_1588_regs.ts_compare); + + /* System time Low and Hi registers */ + IOH_DEBUG("ioh_1588_restore_state:invoking ioh_1588_sys_snap_set\n"); + ioh_1588_sys_snap_set(ioh_1588_regs.ts_syslo, ioh_1588_regs.ts_syshi); + + /* Target time Low and Hi registers */ + IOH_DEBUG("ioh_1588_restore_state:invoking ioh_1588_tgt_snap_set\n"); + ioh_1588_tgt_snap_set(ioh_1588_regs.ts_tgtlo, ioh_1588_regs.ts_tgthi); + + /* Ethernet Channel Control register */ + if (ioh_1588_regs.ts_cc & IOH_1588_CC_MM) { + IOH_DEBUG + ("ioh_1588_restore_state:invoking ioh_1588_master_mode_set\ + with TRUE as parameter\n"); + ioh_1588_master_mode_set(TRUE); + } + if (ioh_1588_regs.ts_cc & IOH_1588_CC_TA) { + IOH_DEBUG + ("ioh_1588_restore_state:invoking ioh_1588_timestamp_all_set\ + with TRUE as parameter\n"); + ioh_1588_timestamp_all_set(TRUE); + } + IOH_DEBUG("ioh_1588_restore_state:invoking ioh_1588_op_mode_set\n"); + ioh_1588_op_mode_set((ioh_1588_regs.ts_cc & IOH_1588_CC_MODE_MASK) >> + IOH_1588_CC_MODE_SHIFT); + if (ioh_1588_regs.ts_cc & IOH_1588_CC_VERSION) { + IOH_DEBUG("ioh_1588_restore_state:invoking ioh_1588_version_set\ + with IOH_1588PTP_VERSION_1 as parameter\n"); + ioh_1588_version_set(IOH_1588PTP_VERSION_1); + } + + /* Channel event register, cleared on restore */ + IOH_DEBUG + ("ioh_1588_restore_state:invoking ioh_1588_rx_snap_evt_clear\n"); + ioh_1588_rx_snap_evt_clear(); + IOH_DEBUG + ("ioh_1588_restore_state:invoking ioh_1588_tx_snap_evt_clear\n"); + ioh_1588_tx_snap_evt_clear(); + + /* CAN Channel event register, cleared on restore */ + IOH_DEBUG + ("ioh_1588_restore_state:invoking ioh_1588_tx_snap_ovr_clear\n"); + ioh_1588_can_snap_ovr_clear(); + IOH_DEBUG + ("ioh_1588_restore_state:invoking ioh_1588_tx_snap_valid_clear\n"); + ioh_1588_can_snap_valid_clear(); + + /* Ethernet CAN selector register */ + if (ioh_1588_regs.ts_sel & IOH_1588_ECS_ETH) { + IOH_DEBUG + ("ioh_1588_restore_state:invoking ioh_1588_eth_enable_set\n"); + ioh_1588_eth_enable_set(); + } + if (ioh_1588_regs.ts_sel & IOH_1588_ECS_CAN) { + IOH_DEBUG + ("ioh_1588_restore_state:invoking ioh_1588_can_enable_set\n"); + ioh_1588_can_enable_set(); + } + + /* Station Address registers */ + for (i = 0; i < IOH_1588_STATION_BYTES; i++) { + IOH_DEBUG("ioh_1588_restore_state:invoking ioh_1588_station_set\ + for station=%d\n", i); + ioh_1588_station_set(i, ioh_1588_regs.ts_sti[i]); + } +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn void ioh_1588_show(void) + * + * @brief Display the dump of IEEE 1588 registers + * + * @remarks This API will dump the contents of configuration, event and + * snapshot + * registers of the IEEE1588 module + * + * @param None. + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS + */ +enum ioh_status ioh_1588_show(void) +{ + int i; + unsigned long flag = FALSE; + unsigned long reg_low = 0; + unsigned long reg_hi = 0; + unsigned int seq_id = 0; + unsigned long uuid_low = 0; + unsigned long uuid_hi = 0; + + /*dump all register as such */ + IOH_DEBUG("TS Control Register offset = %x,content = %x\n", + IOH_1588_TSC_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_TSC_OFFSET)); + IOH_DEBUG("TS Event Register offset = %x,content = %x\n", + IOH_1588_TSE_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_TSE_OFFSET)); + IOH_DEBUG("TS Addend Register offset = %x,content = %x\n", + IOH_1588_ADD_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_ADD_OFFSET)); + IOH_DEBUG("TS Accumulator Register offset = %x,content = %x\n", + IOH_1588_ACC_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_ACC_OFFSET)); + IOH_DEBUG("TS Test Register offset = %x,content = %x\n", + IOH_1588_TST_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_TST_OFFSET)); + IOH_DEBUG("TS PPS Compare Register offset = %x,content = %x\n", + IOH_1588_PPS_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_PPS_OFFSET)); + IOH_DEBUG("TS System Time Low Register offset = %x,content = %x\n", + IOH_1588_STL_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_STL_OFFSET)); + IOH_DEBUG("TS System Time High Register offset = %x,content = %x\n", + IOH_1588_STH_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_STH_OFFSET)); + IOH_DEBUG("TS Target Time Low Register offset = %x,content = %x\n", + IOH_1588_TTL_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_TTL_OFFSET)); + IOH_DEBUG("TS Target Time High Register offset = %x,content = %x\n", + IOH_1588_TTH_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_TTH_OFFSET)); + IOH_DEBUG + ("TS Aux Slave Mode Snapshot Low Register offset = %x,content = %x\n", + IOH_1588_ASSL_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_ASSL_OFFSET)); + IOH_DEBUG + ("TS Aux Slave Mode Snapshot High Register offset = %x,content = %x\n", + IOH_1588_ASSH_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_ASSH_OFFSET)); + IOH_DEBUG + ("TS Aux Master Mode Snapshot Low Register offset = %x,content = %x\n", + IOH_1588_AMSL_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_AMSL_OFFSET)); + IOH_DEBUG + ("TS Aux Master Mode Snapshot High Register offset = %x,content = %x\n", + IOH_1588_AMSH_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_AMSH_OFFSET)); + IOH_DEBUG("TS Channel Control Register offset = %x,content = %x\n", + IOH_1588_CC_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_CC_OFFSET)); + IOH_DEBUG("TS Channel Event Register offset = %x,content = %x\n", + IOH_1588_CE_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_CE_OFFSET)); + IOH_DEBUG("TS Tx Snapshot High Register offset = %x,content = %x\n", + IOH_1588_XSH_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_XSH_OFFSET)); + IOH_DEBUG("TS Tx Snapshot Low Register offset = %x,content = %x\n", + IOH_1588_XSL_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_XSL_OFFSET)); + IOH_DEBUG("TS Rx Snapshot Low Register offset = %x,content = %x\n", + IOH_1588_RSL_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_RSL_OFFSET)); + IOH_DEBUG("TS Rx Snapshot High Register offset = %x,content = %x\n", + IOH_1588_RSH_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_RSH_OFFSET)); + IOH_DEBUG("TS Source UUID Low Register offset = %x,content = %x\n", + IOH_1588_UID_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_UID_OFFSET)); + IOH_DEBUG + ("TS Source UUID High/SequenceID Register offset = %x,content = %x\n", + IOH_1588_SID_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_SID_OFFSET)); + IOH_DEBUG("TS CAN Channel Status Register offset = %x,content = %x\n", + IOH_1588_CCE_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_CCE_OFFSET)); + IOH_DEBUG("TS CAN Snapshot Low Register offset = %x,content = %x\n", + IOH_1588_CXSL_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_CXSL_OFFSET)); + IOH_DEBUG("TS CAN Snapshot High Register offset = %x,content = %x\n", + IOH_1588_CXSH_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_CXSH_OFFSET)); + IOH_DEBUG("TS Ethernet/CAN Selecti Register offset = %x,content = %x\n", + IOH_1588_ECS_OFFSET, + IOH_READ32(ioh_1588_base + IOH_1588_ECS_OFFSET)); + /* Station Address registers */ + IOH_DEBUG("TS Station Address [1-6]"); + for (i = 0; i < IOH_1588_STATION_BYTES; i++) { + ioh_1588_station_get(i, ®_low); + IOH_DEBUG(":%02lx", reg_low); + } + IOH_DEBUG("\n"); + + /* Target time reached interrupt mask */ + flag = ioh_1588_ttm_imask_get(); + IOH_LOG(KERN_ERR, "Target Time Interrupt Mask: %s\n", + ((TRUE == flag) ? "Set" : "Clear")); + + /* Auxiliary Slave Mode Snapshot interrupt mask */ + flag = ioh_1588_asms_imask_get(); + IOH_LOG(KERN_ERR, "ASMS Interrupt Mask: %s\n", + ((TRUE == flag) ? "Set" : "Clear")); + + /* Auxiliary Master Mode Snapshot interrupt mask */ + flag = ioh_1588_amms_imask_get(); + IOH_LOG(KERN_ERR, "AMMS Interrupt Mask: %s\n", + ((TRUE == flag) ? "Set" : "Clear")); + + /* Pulse per second interrupt mask */ + flag = ioh_1588_pps_imask_get(); + IOH_LOG(KERN_ERR, "PPS Interrupt Mask: %s\n", + ((TRUE == flag) ? "Set" : "Clear")); + + /* TS_Event Register */ + /* Target time interrupt event */ + flag = ioh_1588_ttm_evt_get(); + IOH_LOG(KERN_ERR, "Target Time Interrupt Pending: %s\n", + ((TRUE == flag) ? "Set" : "Clear")); + + /* Auxiliary Slave Mode Snapshot event */ + flag = ioh_1588_asms_evt_get(); + IOH_LOG(KERN_ERR, "ASMS Snapshot Event: %s\n", + ((TRUE == flag) ? "Set" : "Clear")); + + /* Auxiliary Master Mode Snapshot event */ + flag = ioh_1588_amms_evt_get(); + IOH_LOG(KERN_ERR, "AMMS Snapshot Event: %s\n", + ((TRUE == flag) ? "Set" : "Clear")); + + /* PPS Match event */ + flag = ioh_1588_pps_evt_get(); + IOH_LOG(KERN_ERR, "PPS Match Event: %s\n", + ((TRUE == flag) ? "Set" : "Clear")); + + /* Addend Register */ + reg_low = 0; + ioh_1588_addend_get(®_low); + IOH_LOG(KERN_ERR, "Frequency Scaling Value: %lx\n", reg_low); + + /* PPS Comapre Register */ + reg_low = 0; + ioh_1588_pps_get(®_low); + IOH_LOG(KERN_ERR, "PPS Compare Register Value: %lx\n", reg_low); + + /* System Time registers */ + reg_low = reg_hi = 0; + ioh_1588_sys_snap_get(®_low, ®_hi); + IOH_LOG(KERN_ERR, "System Time (Hi:Low): %lx : %lx\n", reg_hi, reg_low); + + /* Target Time registers */ + reg_low = reg_hi = 0; + ioh_1588_tgt_snap_get(®_low, ®_hi); + IOH_LOG(KERN_ERR, "Target Time (Hi:Low): %lx : %lx\n", reg_hi, reg_low); + + /* Auxiliary Slave Mode Snapshot registers */ + reg_low = reg_hi = 0; + ioh_1588_aux_slave_snap_get(®_low, ®_hi); + IOH_LOG(KERN_ERR, + "Auxiliary Slave Mode Snapshot (Hi:Low) : %lx : %lx\n", reg_hi, + reg_low); + + /* Auxiliary Master Mode Snapshot registers */ + reg_low = reg_hi = 0; + ioh_1588_aux_master_snap_get(®_low, ®_hi); + IOH_LOG(KERN_ERR, + "Auxiliary Master Mode Snapshot (Hi:Low): %lx : %lx\n", reg_hi, + reg_low); + + /* Ethernet port */ + IOH_LOG(KERN_ERR, "\nPTP Eth Port\n"); + + /* Master Mode */ + flag = ioh_1588_master_mode_get(); + IOH_LOG(KERN_ERR, "Master Mode: %s\n", + ((TRUE == flag) ? "Set" : "Clear")); + + /* Timestamp All PTP messages */ + flag = ioh_1588_timestamp_all_get(); + IOH_LOG(KERN_ERR, "Timestamp All Messages: %s\n", + ((TRUE == flag) ? "Set" : "Clear")); + + /* Version */ + flag = ioh_1588_version_get(); + IOH_LOG(KERN_ERR, "Version support: %s\n", + ((TRUE == flag) ? "v1 and v2" : "v1 only")); + + /* Receive Snapshot Locked */ + flag = ioh_1588_rx_snap_evt(); + IOH_LOG(KERN_ERR, "Receive Snapshot Locked: %s\n", + ((TRUE == flag) ? "Set" : "Clear")); + + /* Transmit Snapshot Locked */ + flag = ioh_1588_tx_snap_evt(); + IOH_LOG(KERN_ERR, "Transmit Snapshot Locked: %s\n", + ((TRUE == flag) ? "Set" : "Clear")); + + /* Receive Snapshot registers */ + reg_low = reg_hi = 0; + ioh_1588_rx_snap_get(®_low, ®_hi); + IOH_LOG(KERN_ERR, "Receive Snapshot (Hi:Low): %lx : %lx\n", reg_hi, + reg_low); + + /* Transmit Snapshot registers */ + reg_low = reg_hi = 0; + ioh_1588_tx_snap_get(®_low, ®_hi); + IOH_LOG(KERN_ERR, "Transmit Snapshot (Hi:Low): %lx : %lx\n", reg_hi, + reg_low); + + /* UUID and Seqquence Id */ + ioh_1588_uuid_seqid_get(&uuid_low, &uuid_hi, &seq_id); + IOH_LOG(KERN_ERR, "UUID (Hi:Lo): %lx : %lx\n", uuid_hi, uuid_low); + IOH_LOG(KERN_ERR, "Sequence id: %x\n", seq_id); + + /* CAN port */ + IOH_LOG(KERN_ERR, "\nPTP CAN Port:\n"); + + /* Snapshot Valid */ + flag = ioh_1588_can_snap_valid(); + IOH_LOG(KERN_ERR, "Snapshot Valid : %s\n", + ((TRUE == flag) ? "Set" : "Clear")); + + /* Snapshot Overrun */ + flag = ioh_1588_can_snap_ovr(); + IOH_LOG(KERN_ERR, "Snapshot Overrun: %s\n", + ((TRUE == flag) ? "Set" : "Clear")); + + /* CAN Snapshot registers */ + reg_low = reg_hi = 0; + ioh_1588_can_snap_get(®_low, ®_hi); + IOH_LOG(KERN_ERR, "CAN Snapshot (Hi:Low): %lx : %lx\n", reg_hi, + reg_low); + + /* Ethernet Selector */ + flag = ioh_1588_eth_enable_get(); + IOH_LOG(KERN_ERR, "\nEthernet Enable: %s\n", + ((TRUE == flag) ? "Set" : "Clear")); + + /* CAN Selector */ + flag = ioh_1588_can_enable_get(); + IOH_LOG(KERN_ERR, "CAN Enable: %s\n", + ((TRUE == flag) ? "Set" : "Clear")); + + /* Station Address Registers */ + IOH_LOG(KERN_ERR, "Station Address [1-6]"); + for (i = 0; i < IOH_1588_STATION_BYTES; i++) { + ioh_1588_station_get(i, ®_low); + IOH_LOG(KERN_ERR, ":%02lx", reg_low); + } + IOH_LOG(KERN_ERR, "\n"); + + /* Statistics */ + IOH_LOG(KERN_ERR, + "Receive Snapshot Count: %lu\nTransmit Snapshot Count: %lu\n", + ioh_1588_stats.rxMsgs, ioh_1588_stats.txMsgs); + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_ptp_can_poll ( + * enum ioh1588PTPPort ptpPort, + * struct ioh1588TimeValue *ptpTimeStamp) + * + * @brief Polls the IEEE 1588 message time stamp detect status on a given + * CAN PTP Port. + * + * @remarks This API polls for the availability of a time stamp on a CAN + * port. + * + * @param ptpPort [IN] PTP port to poll + * @param ptpTimeStamp [OUT] Buffer to store the snapshot captured + * + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARAM - Invalid parameters passed + * @li IOH_1588_NOTIMESTAMP - No time stamp available + */ +enum ioh_status +ioh_1588_ptp_can_poll(enum ioh1588PTPPort ptpPort, \ + struct ioh1588TimeValue *ptpTimeStamp) +{ + unsigned long valid = FALSE; + unsigned long overrun = FALSE; + + /* Verify the parameters for proper values */ + if ((ptpPort != IOH_1588_CAN_0_1588PTP_PORT) || + ((struct ioh1588TimeValue *) NULL == ptpTimeStamp)) { + IOH_DEBUG("ioh_1588_ptp_can_poll:invalid params\ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + /* Check whether a new timestamp available? */ + IOH_DEBUG("ioh_1588_ptp_can_poll:invoking ioh_1588_can_snap_valid\n"); + valid = ioh_1588_can_snap_valid(); + + /* there is not a valid timestamp */ + if (TRUE != valid) { + IOH_DEBUG("ioh_1588_ptp_can_poll:no valid timestamp\ + returning IOH_1588_NOTIMESTAMP\n"); + return IOH_1588_NOTIMESTAMP; + } + + /* check overrun bit before retreiving timestamp */ + IOH_DEBUG("ioh_1588_ptp_can_poll:invoking ioh_1588_can_snap_ovr\n"); + overrun = ioh_1588_can_snap_ovr(); + + /* if the timestamp has been overwritten */ + if (TRUE == overrun) { + IOH_DEBUG("ioh_1588_ptp_can_poll:overrun occured\n"); + /* reset valid and overrun bits */ + IOH_DEBUG + ("ioh_1588_ptp_can_poll:invoking \ + ioh_1588_can_snap_valid_clear\n"); + ioh_1588_can_snap_valid_clear(); + IOH_DEBUG + ("ioh_1588_ptp_can_poll:invoking \ + ioh_1588_can_snap_ovr_clear\n"); + ioh_1588_can_snap_ovr_clear(); + + /* return no valid timestamp available */ + ptpTimeStamp->timeValueLowWord = 0; + ptpTimeStamp->timeValueHighWord = 0; + + IOH_DEBUG + ("ioh_1588_ptp_can_poll:returning IOH_1588_NOTIMESTAMP\n"); + return IOH_1588_NOTIMESTAMP; + } + + /* Fetch the receive timestamp */ + ioh_1588_can_snap_get(&ptpTimeStamp->timeValueLowWord, + &ptpTimeStamp->timeValueHighWord); + IOH_DEBUG("ioh_1588_ptp_can_poll:timestamp-low=%lx,high=%lx\n", + ptpTimeStamp->timeValueLowWord, + ptpTimeStamp->timeValueHighWord); + + /* check overrun bit again to ensure timestamp is valid */ + overrun = ioh_1588_can_snap_ovr(); + + /* if the timestamp has been overwritten */ + if (TRUE == overrun) { + IOH_DEBUG("ioh_1588_ptp_can_poll:overrun occured\n"); + /* reset valid and overrun bits */ + IOH_DEBUG + ("ioh_1588_ptp_can_poll:invoking \ + ioh_1588_can_snap_valid_clear\n"); + ioh_1588_can_snap_valid_clear(); + IOH_DEBUG + ("ioh_1588_ptp_can_poll:invoking \ + ioh_1588_can_snap_ovr_clear\n"); + ioh_1588_can_snap_ovr_clear(); + + /* return no valid timestamp available */ + ptpTimeStamp->timeValueLowWord = 0; + ptpTimeStamp->timeValueHighWord = 0; + + IOH_DEBUG + ("ioh_1588_ptp_can_poll:returning IOH_1588_NOTIMESTAMP\n"); + return IOH_1588_NOTIMESTAMP; + } + + /* reset valid bit */ + IOH_DEBUG + ("ioh_1588_ptp_can_poll:invoking ioh_1588_can_snap_valid_clear\n"); + ioh_1588_can_snap_valid_clear(); + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_handler(void) + * + * @brief Interrupt handler for the IEEE 1588 module + * + * @remarks Interrupt handler for the IEEE 1588 module + * The Interrupts are handled in the following order + * - 1 - Target Time Reached/Hit Condition + * - 2 - Auxiliary Master Timestamp + * - 3 - Auxiliary Slave Timestamp + * - 4 - pulse per second + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + */ +enum ioh_status ioh_1588_handler(void) +{ + struct ioh1588TimeValue tgt_time = { 0, 0 }; + struct ioh1588TimeValue aux_time = { 0, 0 }; + unsigned long pps; + + /* If valid callbacks are available process each interrupt */ + + /* Handle Target Time Reached or Exceeded Interrupt */ + if ((NULL != ioh_tt_cbptr) && (TRUE == ioh_1588_ttm_evt_get())) { + IOH_DEBUG + ("ioh_1588_handler:Target Time Reached or Exceeded \ + Interrupt\n"); + IOH_DEBUG("ioh_1588_handler:invoking ioh_1588_ttm_imask_clear\ + to disable interrupts\n"); + /* Disable interrupt */ + ioh_1588_ttm_imask_clear(); + + /* Target Time registers contents */ + ioh_1588_tgt_snap_get(&tgt_time.timeValueLowWord, + &tgt_time.timeValueHighWord); + IOH_DEBUG("ioh_1588_handler:target time-low=%lx,high=%lx\n", + tgt_time.timeValueLowWord, + tgt_time.timeValueHighWord); + + IOH_DEBUG("ioh_1588_handler:invoking callback\n"); + /* Invoke client callback */ + (*ioh_tt_cbptr) (tgt_time); + + /* Clear the target time reached condition (ttipend bit) */ + IOH_DEBUG("ioh_1588_handler:invoking ioh_1588_ttm_evt_clear\n"); + ioh_1588_ttm_evt_clear(); + } + + /* Handle Auxiliary Master Mode Snapshot Interrupt */ + if ((NULL != ioh_am_cbptr) && (TRUE == ioh_1588_amms_evt_get())) { + IOH_DEBUG + ("ioh_1588_handler:Auxiliary Master Mode Snapshot Interrupt\n"); + /* Disable interrupt */ + IOH_DEBUG("ioh_1588_handler:invoking ioh_1588_amms_imask_clear\ + to disable interrupts\n"); + ioh_1588_amms_imask_clear(); + + /* Fetch Auxiliary Master Mode Snapshot */ + ioh_1588_aux_master_snap_get(&aux_time.timeValueLowWord, + &aux_time.timeValueHighWord); + IOH_DEBUG + ("ioh_1588_handler:Auxiliary Master Mode Snapshot-low=%lx,\ + high=%lx\n", + aux_time.timeValueLowWord, aux_time.timeValueHighWord); + + IOH_DEBUG("ioh_1588_handler:invoking callback\n"); + /* Return Auxiliary Master Mode Snapshot */ + (*ioh_am_cbptr) (IOH_1588_AUXMODE_MASTER, aux_time); + + /* Clear the snapshot availability condition */ + IOH_DEBUG + ("ioh_1588_handler:invoking ioh_1588_amms_evt_clear\n"); + ioh_1588_amms_evt_clear(); + } + + /* Handle Auxiliary Slave Mode Snapshot Interrupt */ + if ((NULL != ioh_as_cbptr) && (TRUE == ioh_1588_asms_evt_get())) { + IOH_DEBUG + ("ioh_1588_handler:Auxiliary Slave Mode Snapshot Interrupt\n"); + /* Disable interrupt */ + IOH_DEBUG("ioh_1588_handler:invoking ioh_1588_asms_imask_clear\ + to disable interrupts\n"); + ioh_1588_asms_imask_clear(); + + /* Fetch Auxiliary Slave Mode Snapshot */ + ioh_1588_aux_slave_snap_get(&aux_time.timeValueLowWord, + &aux_time.timeValueHighWord); + IOH_DEBUG + ("ioh_1588_handler:Auxiliary Master Mode Snapshot-low=%lx,\ + high=%lx\n", + aux_time.timeValueLowWord, aux_time.timeValueHighWord); + + /* Return Auxiliary Slave Mode Snapshot */ + IOH_DEBUG("ioh_1588_handler:invoking callback\n"); + (*ioh_as_cbptr) (IOH_1588_AUXMODE_SLAVE, aux_time); + + /* Clear the snapshot availability condition */ + IOH_DEBUG + ("ioh_1588_handler:invoking ioh_1588_asms_evt_clear\n"); + ioh_1588_asms_evt_clear(); + } + + /* Handle Pulse Per Second Interrupt */ + if ((NULL != ioh_pps_cbptr) && (TRUE == ioh_1588_pps_evt_get())) { + IOH_DEBUG("ioh_1588_handler:Pulse Per Second Interrupt\n"); + /* Disable interrupt */ + IOH_DEBUG("ioh_1588_handler:invoking ioh_1588_pps_imask_clear\ + to disable interrupts\n"); + ioh_1588_pps_imask_clear(); + + /* Fetch PPS compare register */ + IOH_DEBUG("ioh_1588_handler:invoking ioh_1588_pps_get\n"); + ioh_1588_pps_get(&pps); + + /* Invoke the call back */ + IOH_DEBUG("ioh_1588_handler:invoking callback\n"); + (*ioh_pps_cbptr) (pps); + + /* Clear the snapshot availability condition */ + IOH_DEBUG("ioh_1588_handler:invoking ioh_1588_pps_evt_clear\n"); + ioh_1588_pps_evt_clear(); + + } + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_ptp_version_get( + * enum ioh1588PTPPort ptpPort, enum ioh1588PTPVersion *ptpVersion) + * + * @brief Retrieves IEEE 1588 PTP version supported on the given PTP port. + * + * @remarks This API retrieves IEEE 1588 PTP version supported on given PTP + * port. + * The main steps followed in this function are: + * - Return IOH_1588_INVALIDPARAM if ptpPort passed is not valid or + * ptpVersion passed is NULL + * - Ensure that the module is initialized and the port is valid + * - Return the PTP version that is supported from the + * TS_Channel_Control register, bit 31 + * + * + * @param ptpPort [IN] PTP port + * @param ptpVersion [OUT] Version supported on PTP port + * + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation is successful + * @li IOH_1588_INVALIDPARAM - Invalid parameters passed + */ +enum ioh_status +ioh_1588_ptp_version_get(enum ioh1588PTPPort ptpPort, \ + enum ioh1588PTPVersion *ptpVersion) +{ + /* Verify the parameters for proper values */ + if ((ptpPort != IOH_1588_GBE_0_1588PTP_PORT) || (ptpVersion == NULL)) { + IOH_DEBUG("ioh_1588_ptp_version_get:invalid params\ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + IOH_DEBUG("ioh_1588_ptp_version_get:invoking ioh_1588_version_get\n"); + *ptpVersion = ioh_1588_version_get(); + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_ptp_version_set( + * enum ioh1588PTPPort ptpPort, + * enum ioh1588PTPVersion ptpVersion) + * + * @brief Configures IEEE 1588 PTP version to be used on given PTP port. + * + * @remarks This API set the IEEE 1588 PTP version to be used on given PTP + * port. + * The main steps followed in this function are: + * - Validate parameter + * - Ensure that the module is initialized and the version + * requested is valid + * - Set the version in TS_Channel_Control register, bit 31 + * + * + * @param ptpPort [IN] PTP port + * @param ptpVersion [IN] Version to be supported on PTP port + * + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation is successful + * @li IOH_1588_INVALIDPARAM - Invalid parameters passed + */ +enum ioh_status +ioh_1588_ptp_version_set(enum ioh1588PTPPort ptpPort, \ + enum ioh1588PTPVersion ptpVersion) +{ + /* Verify the parameters for proper values */ + if ((ptpPort != IOH_1588_GBE_0_1588PTP_PORT) || + ((ptpVersion != IOH_1588PTP_VERSION_0) && + (ptpVersion != IOH_1588PTP_VERSION_1))) { + IOH_DEBUG("ioh_1588_ptp_version_set:invalid params\ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + IOH_DEBUG("ioh_1588_ptp_version_get:invoking ioh_1588_version_set\n"); + ioh_1588_version_set(ptpVersion); + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_ptp_operation_mode_set( + * enum ioh1588PTPPort ptpPort, + * enum ioh1588PTPOperationMode ptpMode) + * + * @brief Configure the IEEE 1588 PTP operation mode of given PTP port. + * + * @remarks This API will set the operation mode on given PTP port. + * The main steps followed in this function are: + * - Ensure that the module is initialized and the mode requested + * is valid + * - If not valid, return status IOH_1588_INVALIDPARAM + * - Set the requested operation mode in TS_Channel_Control + * register, bits 16-20 + * + * + * @param ptpPort [IN] PTP port to configure + * @param ptpMode [IN] Operation mode to be used + * + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARAM - Invalid parameters passed + */ +enum ioh_status +ioh_1588_ptp_operation_mode_set(enum ioh1588PTPPort ptpPort, + enum ioh1588PTPOperationMode ptpMode) +{ + /* Verify the parameters for proper values */ + if ((ptpPort != IOH_1588_GBE_0_1588PTP_PORT) || + ((ptpMode != IOH_1588PTP_OP_MODE_SYNC_DELAYREQ_MSGS) && + (ptpMode != IOH_1588PTP_OP_MODE_V1_ALL_MSGS) && + (ptpMode != IOH_1588PTP_OP_MODE_V1_V2_EVENT_MSGS) && + (ptpMode != IOH_1588PTP_OP_MODE_V1_V2_ALL_MSGS))) { + IOH_DEBUG("ioh_1588_ptp_operation_mode_set:invalid params\ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + IOH_DEBUG("ioh_1588_ptp_version_get:invoking ioh_1588_op_mode_set\n"); + ioh_1588_op_mode_set(ptpMode); + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_ptp_operation_mode_get( + * enum ioh1588PTPPort ptpPort, + * enum ioh1588PTPOperationMode *ptpMode) + * + * @brief Gets the current PTP operation mode of given PTP port. + * + * @remarks This API will get the operation mode of given PTP port. + * The main steps followed in this function are: + * - Ensure that the module is initialized and the port is valid + * - If not valid, return status IOH_1588_INVALIDPARAM + * - Return the PTP operation mode that is currently in use by + * reading the TS_Channel_Control register, bits 16-20 + * + * + * @param ptpPort [IN] PTP port to configure + * @param ptpMode [OUT] Address where PTP operation mode is + * returned + * + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARAM - Null parameter passed + */ +enum ioh_status +ioh_1588_ptp_operation_mode_get(enum ioh1588PTPPort ptpPort, + enum ioh1588PTPOperationMode *ptpMode) +{ + /* Verify the parameters for proper values */ + if ((ptpPort != IOH_1588_GBE_0_1588PTP_PORT) || (ptpMode == NULL)) { + IOH_DEBUG("ioh_1588_ptp_operation_mode_get:invalid params\ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + IOH_DEBUG + ("ioh_1588_ptp_operation_mode_get:invoking ioh_1588_op_mode_get\n"); + *ptpMode = ioh_1588_op_mode_get(); + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_pulse_per_sec_interrupt_enable( + * ioh1588PulsePerSecondCallback callBack) + * + * @brief Enable the Pulse Per Second match interrupt + * + * @remarks This API will enable the Pulse Per Second match interrupt. + * This interrupt is generated when the low word of System + * Time matches the value in the Pulse Per Second compare + * register in the IEEE hardware assist block. The main steps + * followed in this function are: + * - Return IOH_1588_INVALIDPARAM if argument passed is NULL + * - Modify the Time Sync Controller register to enable the + * interrupt + * - Set the callback routine + * + * @param callBack [IN] Routine to be invoked when interrupt + * fires + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARAM - Null parameter passed + */ +enum ioh_status +ioh_1588_pulse_per_sec_interrupt_enable(ioh1588PulsePerSecondCallback callBack) +{ + /* Verify the parameter */ + if ((ioh1588PulsePerSecondCallback) NULL == callBack) { + IOH_DEBUG + ("ioh_1588_pulse_per_sec_interrupt_enable:invalid params\ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + /* Register the Callback */ + ioh_pps_cbptr = callBack; + + /* Set target time interrupt mask */ + IOH_DEBUG("ioh_1588_pulse_per_sec_interrupt_enable:invoking \ + ioh_1588_pps_imask_set\n"); + ioh_1588_pps_imask_set(); + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_pulse_per_sec_interrupt_disable(void) + * + * @brief Disable the Pulse Per Second match interrupt + * + * @remarks This API will disable the Pulse Per Second match interrupt. + * This interrupt is generated when the low word of System + * Time matches the value in the Pulse Per Second compare + * register in the IEEE hardware assist block. The main + * steps followed in this function are: + * - Modify the Time Sync Controller register to disable the + * interrupt + * - Clear the callback routine + * + * @param None + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + */ +enum ioh_status ioh_1588_pulse_per_sec_interrupt_disable(void) +{ + /* Clear pulse per second interrupt mask */ + IOH_DEBUG("ioh_1588_pulse_per_sec_interrupt_disable:invoking \ + ioh_1588_pps_imask_clear\n"); + ioh_1588_pps_imask_clear(); + + /* Unregister the Callback */ + ioh_pps_cbptr = (ioh1588PulsePerSecondCallback) NULL; + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_pulse_per_sec_time_set(unsigned long + * ppsTime) + * + * @brief Sets the Pulse Per Second match time in the IEEE 1588 hardware + * assist block + * + * @remarks This API will set the PPS match register with the value supplied + * The main steps followed in this function are: + * - Return IOH_1588_INVALIDPARAM if argument passed is NULL + * - Set the time in PPS Compare Register + * + * + * @param ppsTime [IN] Value to be stored in pps match register + * + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation is successful + * @li IOH_1588_INVALIDPARAM - Null parameter passed + */ +enum ioh_status ioh_1588_pulse_per_sec_time_set(unsigned long ppsTime) +{ + unsigned long old_mask = FALSE; + + /* Retrieve existing pps mask value */ + old_mask = ioh_1588_pps_imask_get(); + IOH_DEBUG + ("ioh_1588_pulse_per_sec_time_set:target time interrupt mask=%lx\n", + old_mask); + + /* + * Clear the pps time interrupt mask so that the interrupt will not come + * during the time we manipulate the registers. + */ + IOH_DEBUG + ("ioh_1588_pulse_per_sec_time_set:invoking ioh_1588_pps_imask_clear\ + to clear the pps interrupt mask\n"); + ioh_1588_pps_imask_clear(); + + /* Update the PPS time */ + IOH_DEBUG + ("ioh_1588_pulse_per_sec_time_set:invoking ioh_1588_pps_set\n"); + + ioh_1588_pps_set(ppsTime); + + /* + * Let the hardware assist re-evaluate the pps reached + * condition based on the new pps value + */ + IOH_DEBUG + ("ioh_1588_pulse_per_sec_time_set:invoking ioh_1588_pps_evt_clear\n"); + ioh_1588_pps_evt_clear(); + + /* Restore the preserved pps interrupt mask value */ + if (TRUE == old_mask) { + IOH_DEBUG + ("ioh_1588_pulse_per_sec_time_set:invoking \ + ioh_1588_pps_imask_set\n"); + ioh_1588_pps_imask_set(); + } + + IOH_DEBUG + ("ioh_1588_pulse_per_sec_time_set:returning IOH_1588_SUCCESS\n"); + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_pulse_per_sec_time_get( + * unsigned long *ppsTime) + * + * @brief Gets the Pulse Per Second match time from the IEEE 1588 hardware + * assist block + * + * @remarks This API will get the PPS match register content + * from IEEE 1588 block. The main steps followed in this + * function are: + * - Return IOH_1588_INVALIDPARAM if argument passed is NULL + * - Return the time from PPS compare register + * + * + * @param ppsTime [OUT] Buffer for returning the pps match value + * + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARAM - Null parameter passed + */ +enum ioh_status ioh_1588_pulse_per_sec_time_get(unsigned long *ppsTime) +{ + /* Verify the parameter */ + if ((unsigned long *)NULL == ppsTime) { + IOH_DEBUG("ioh_1588_pulse_per_sec_time_get:invalid params\ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + /* Retrieve PPS Value */ + IOH_DEBUG + ("ioh_1588_pulse_per_sec_time_get:invoking ioh_1588_pps_get\n"); + ioh_1588_pps_get(ppsTime); + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_eth_enable(void) + * + * @brief Sets the eth_enb bit (bit 0) of Ethernet-CAN Select Register + * @remarks This API enables the IEEE 1588 hardware time stamping of PTP + * traffic + * on the Ethernet interface + * + * @param None + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + */ +enum ioh_status ioh_1588_eth_enable(void) +{ + if (ioh_1588_base != 0) { + IOH_DEBUG + ("ioh_1588_eth_enable:invoking ioh_1588_eth_enable_set\n"); + ioh_1588_eth_enable_set(); + } + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_eth_disable(void) + * + * @brief Clears the eth_enb bit (bit 0) of Ethernet-CAN Select Register + * @remarks This API disables the IEEE 1588 hardware time stamping of PTP + * traffic + * on the Ethernet interface + * + * @param None + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + */ +enum ioh_status ioh_1588_eth_disable(void) +{ + if (ioh_1588_base != 0) { + IOH_DEBUG + ("ioh_1588_eth_disable:invoking ioh_1588_eth_enable_clear\n"); + ioh_1588_eth_enable_clear(); + } + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_can_enable(void) + * + * @brief Sets the can_enb bit (bit 1) of Ethernet-CAN Select Register + * @remraks This API enables the IEEE 1588 hardware time stamping of PTP + * traffic + * on the CAN interface + * + * @param None + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + */ +enum ioh_status ioh_1588_can_enable(void) +{ + if (ioh_1588_base != 0) { + IOH_DEBUG + ("ioh_1588_can_enable:invoking ioh_1588_can_enable_set\n"); + ioh_1588_can_enable_set(); + } + + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_can_disable(void) + * + * @brief Clear the can_enb bit (bit 1) of Ethernet-CAN Select Register + * @remarks This API disables the IEEE 1588 hardware time stamping of PTP + * traffic + * on the CAN interface + * + * @param None + * + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + */ +enum ioh_status ioh_1588_can_disable(void) +{ + if (ioh_1588_base != 0) { + IOH_DEBUG + ("ioh_1588_can_disable:invoking ioh_1588_can_enable_clear\n"); + ioh_1588_can_enable_clear(); + } + + return IOH_1588_SUCCESS; +} + +/** + * @ingroup IEEE_1588_UtilitiesAPI + * @fn static int get_decimal(unsigned char ch) + * + * @brief Returns the decimal value of the passed + * hexadecimal value. + * + * @note Returns -1 if the passed arguement is invalid. + * + * @param ch [IN] The hexadecimal value that has to be converted. + * + * @retval int + * - On Success --> decimal Value + * - Invalid value --> -1 + */ +static int get_decimal(unsigned char ch) +{ + int ret; + + if ((ch >= '0') && (ch <= '9')) { + ret = ch - '0'; + return ret; + } else if ((ch >= 'A') && (ch <= 'F')) { + ret = 10 + ch - 'A'; + return ret; + } else if ((ch >= 'a') && (ch <= 'f')) { + ret = 10 + ch - 'a'; + return ret; + } + + return -1; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_set_station_address ( + * unsigned char *addr) + * + * @brief This API sets the station address used by IEEE 1588 hardware + * when looking + * at PTP traffic on the ethernet interface + * + * @param addr [IN] Address which contain the column separated + * address to be used + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARAM - Invalid address string + */ +enum ioh_status ioh_1588_set_station_address(unsigned char *addr) +{ + int i; + + /* Verify the parameter */ + if ((ioh_1588_base == 0) || (unsigned char *)NULL == addr) { + IOH_DEBUG("ioh_1588_set_station_address :invalid params\ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + for (i = 0; i < IOH_1588_STATION_BYTES; i++) { /* For all station + address bytes */ + unsigned long val = 0; + int tmp; + + tmp = get_decimal(addr[i * 3]); + if (tmp < 0) { + IOH_DEBUG("ioh_1588_set_station_address :invalid params\ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + val = tmp * 16; + tmp = get_decimal(addr[(i * 3) + 1]); + if (tmp < 0) { + IOH_DEBUG("ioh_1588_set_station_address :invalid params\ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + val += tmp; + if ((i < 5) && (addr[(i * 3) + 2] != ':')) { /* Expects ':' + separated addresses */ + IOH_DEBUG("ioh_1588_set_station_address :invalid params\ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + /* Ideally we should set the address only after validating + entire string */ + IOH_DEBUG + ("ioh_1588_set_station_address \ + :invoking ioh_1588_station_set\n"); + ioh_1588_station_set(i, val); + } + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_get_station_address(char *addr) + * @brief This API gets the station address currently used by IEEE 1588 + * hardware when looking at PTP traffic on the ethernet interface + * + * @param addr [OUT] Buffer to which column separated address is + * returned + * @retval enum ioh_status + * @li IOH_1588_SUCCESS - Operation successful + * @li IOH_1588_INVALIDPARAM - Null parameter passed + */ +enum ioh_status ioh_1588_get_station_address(char *addr) +{ + int i; + + /* Verify the parameter */ + if ((char *)NULL == addr) { + IOH_DEBUG("ioh_1588_get_station_address:invalid params\ + returning IOH_1588_INVALIDPARAM\n"); + return IOH_1588_INVALIDPARAM; + } + + for (i = 0; i < IOH_1588_STATION_BYTES; i++) { + unsigned long val = 0; + + ioh_1588_station_get(i, &val); + addr[i * 3] = val / 16; + if (addr[i * 3] > 9) + addr[i * 3] += 'a' - 10; + else + addr[i * 3] += '0'; + addr[i * 3 + 1] = val % 16; + if (addr[i * 3 + 1] > 9) + addr[i * 3 + 1] += 'a' - 10; + else + addr[i * 3 + 1] += '0'; + addr[i * 3 + 2] = ':'; + } + addr[17] = '\0'; + return IOH_1588_SUCCESS; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_aux_target_time_interrupt_enable( + * void *callBack) + * + * @brief This API just returns an error. + * + * @remarks This API is just for compatibility. It just returns an error. + * + * @param callBack [IN] Callback to be invoked when interrupt + * fires + * + * + * @retval enum ioh_status + * @li IOH_1588_UNSUPPORTED - Operation is not supported + */ +enum ioh_status ioh_1588_aux_target_time_interrupt_enable(void *callBack) +{ + IOH_DEBUG("ioh_1588_aux_target_time_interrupt_enable:unsupported\n"); + return IOH_1588_UNSUPPORTED; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_aux_target_time_interrupt_disable(void) + * + * @brief This API just returns an error. + * + * @remarks This API is just for compatibility. It just returns an error. + * + * @param None + * + * @retval enum ioh_status + * @li IOH_1588_UNSUPPORTED - Operation is not supported + */ +enum ioh_status ioh_1588_aux_target_time_interrupt_disable(void) +{ + IOH_DEBUG("ioh_1588_aux_target_time_interrupt_disable:unsupported\n"); + return IOH_1588_UNSUPPORTED; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_aux_target_time_poll( + * unsigned long *attmPollFlag, + * struct ioh1588TimeValue *targetTime) + * + * @brief This API just returns an error. + * + * @remarks This API is just for compatibility. It just returns an error. + * + * @param attmPollFlag [OUT] Flag returning the availablity of a + * snapshot + * @param targetTime [OUT] Snapshot captured + * + * + * @retval enum ioh_status + * @li IOH_1588_UNSUPPORTED - Operation supported + */ +enum ioh_status +ioh_1588_aux_target_time_poll(unsigned long *attmPollFlag, + struct ioh1588TimeValue *targetTime) +{ + IOH_DEBUG("ioh_1588_aux_target_time_poll:unsupported\n"); + return IOH_1588_UNSUPPORTED; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_aux_target_time_set( + * struct ioh1588TimeValue targetTime) + * + * @brief This API just returns an error. + * + * @remarks This API is just for compatibility. It just returns an error. + * + * @param targetTime [IN] Time to set to + * + * + * @retval enum ioh_status + * @li IOH_1588_UNSUPPORTED - Operation supported + */ +enum ioh_status ioh_1588_aux_target_time_set(struct ioh1588TimeValue targetTime) +{ + IOH_DEBUG("ioh_1588_aux_target_time_set:unsupported\n"); + return IOH_1588_UNSUPPORTED; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_aux_target_time_get( + * struct ioh1588TimeValue *targetTime) + * + * @brief This API just returns an error. + * + * @remarks This API is just for compatibility. It just returns an error. + * + * @param targetTime [OUT] Buffer for returning time snapshot + * + * + * @retval enum ioh_status + * @li IOH_1588_UNSUPPORTED - Operation supported + */ +enum ioh_status ioh_1588_aux_target_time_get( + struct ioh1588TimeValue *targetTime) +{ + IOH_DEBUG("ioh_1588_aux_target_time_get:unsupported\n"); + return IOH_1588_UNSUPPORTED; +} + +/*! @ingroup IEEE_1588_HALLayerAPI + * + * @fn int ioh_1588_eth_can_get(void) + * + * @brief This function returns the modes [ethernet/CAN] enabled + * + * @retval int + * - the modes enabled + */ +int ioh_1588_eth_can_get(void) +{ + int ieee_mode = 0; + + if (ioh_1588_eth_enable_get() == 1) + ieee_mode |= IOH_IEEE1588_ETH; + if (ioh_1588_can_enable_get() == 1) + ieee_mode |= IOH_IEEE1588_CAN; + + return ieee_mode; +} + +#ifdef IOH_IEEE1588_A0_A1_SAMPLE_BUG +/*! @ingroup IEEE_1588_HALLayerAPI + * + * @fn void ioh_1588_set_system_time_count(void) + * + * @brief This function enables all 64 bits in system time registers + * [high & low]. This is a work-around for non continuous value + * in the SystemTime Register + * + * @retval none + */ +void ioh_1588_set_system_time_count(void) +{ + IOH_REG_32_WRITE((ioh_1588_base + 0xC0), 0x1); + IOH_REG_32_WRITE((ioh_1588_base + 0xC4), 0xFFFFFFFF); + IOH_REG_32_WRITE((ioh_1588_base + 0xC0), 0x0); +} +#endif diff -urN linux-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_hal.h topcliff-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_hal.h --- linux-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_hal.h 1970-01-01 09:00:00.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_hal.h 2010-03-09 07:40:00.000000000 +0900 @@ -0,0 +1,885 @@ + /*! + * @file ioh_1588_hal.h + * @brief + * This file lists the declarations of IEEE_1588_HALLayer APIs. + * @version 0.92 + * @section + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * History: + * modified to support Intel IOH GE IEEE 1588 hardware + * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. + * All rights reserved. + * derived from + * IEEE 1588 Time Synchronization Driver for Intel EP80579 + * Copyright(c) 2007,2008 Intel Corporation. All rights reserved. + * All rights reserved. + * + */ + +#ifndef IOH_1588_HAL_H +#define IOH_1588_HAL_H + +#include "pch_1588_main.h" + +/* IOH 1588 Hardware Assist Module Register offsets */ +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSC_OFFSET +@brief TS Control Register Offset +*/ +#define IOH_1588_TSC_OFFSET (0x00) /* TS_Control */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSE_OFFSET +@brief TS Event Register Offset +*/ +#define IOH_1588_TSE_OFFSET (0x04) /* TS_Event */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_ADD_OFFSET +@brief TS Addend Register Offset +*/ +#define IOH_1588_ADD_OFFSET (0x08) /* TS_Addend */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_ACC_OFFSET +@brief TS Accumulator Register Offset +*/ +#define IOH_1588_ACC_OFFSET (0x0C) /* TS_Accum */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TST_OFFSET +@brief TS Test Register Offset +*/ +#define IOH_1588_TST_OFFSET (0x10) /* TS_Test */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_PPS_OFFSET +@brief TS PPS Compare Register Offset +*/ +#define IOH_1588_PPS_OFFSET (0x14) /* TS_PPS_Compare */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_STL_OFFSET +@brief TS System Time Low Register Offset +*/ +#define IOH_1588_STL_OFFSET (0x20) /* TS_SysTimeLo */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_STH_OFFSET +@brief TS System Time High Register Offset +*/ +#define IOH_1588_STH_OFFSET (0x24) /* TS_SysTimeHi */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TTL_OFFSET +@brief TS Target Time Low Register Offset +*/ +#define IOH_1588_TTL_OFFSET (0x28) /* TS_TrgtLo */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TTH_OFFSET +@brief TS Target Time High Register Offset +*/ +#define IOH_1588_TTH_OFFSET (0x2c) /* TS_TrgtHi */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_ASSL_OFFSET +@brief TS Aux Slave Mode Snapshot Low Register Offset +*/ +#define IOH_1588_ASSL_OFFSET (0x30) /* TS_ASMSLo */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_ASSH_OFFSET +@brief TS Aux Slave Mode Snapshot High Register Offset +*/ +#define IOH_1588_ASSH_OFFSET (0x34) /* TS_ASMSHi */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_ASSH_OFFSET +@brief TS Aux Master Mode Snapshot Low Register Offset +*/ +#define IOH_1588_AMSL_OFFSET (0x38) /* TS_AMMSLo */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_AMSH_OFFSET +@brief TS Aux Master Mode Snapshot High Register Offset +*/ +#define IOH_1588_AMSH_OFFSET (0x3C) /* TS_AMMSHi */ + +/* Ethernet */ +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_CC_OFFSET +@brief TS Channel Control Register Offset +*/ +#define IOH_1588_CC_OFFSET (0x40) /* TS_Ch_Contr */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_CE_OFFSET +@brief TS Channel Event Register Offset +*/ +#define IOH_1588_CE_OFFSET (0x44) /* TS_Ch_Event */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_XSL_OFFSET +@brief TS Tx Snapshot Low Register Offset +*/ +#define IOH_1588_XSL_OFFSET (0x48) /* TS_TxSnapLo */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_XSH_OFFSET +@brief TS Tx Snapshot High Register Offset +*/ +#define IOH_1588_XSH_OFFSET (0x4C) /* TS_TxSnapHi */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_RSL_OFFSET +@brief TS Rx Snapshot Low Register Offset +*/ +#define IOH_1588_RSL_OFFSET (0x50) /* TS_RxSnapLo */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_RSH_OFFSET +@brief TS Rx Snapshot High Register Offset +*/ +#define IOH_1588_RSH_OFFSET (0x54) /* TS_RxSnapHi */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_UID_OFFSET +@brief TS Source UUID Low Register Offset +*/ +#define IOH_1588_UID_OFFSET (0x58) /* TS_SrcUUID */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_SID_OFFSET +@brief TS Source UUID High/SequenceID Register Offset +*/ +#define IOH_1588_SID_OFFSET (0x5C) /* TS_SrcUUID */ + +/* CAN */ +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_CCE_OFFSET +@brief TS CAN Channel Status Register Offset +*/ +#define IOH_1588_CCE_OFFSET (0x60) /* TS_CAN_Stat */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_CXSL_OFFSET +@brief TS CAN Snapshot Low Register Offset +*/ +#define IOH_1588_CXSL_OFFSET (0x64) /* TS_CAN_Snap */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_CXSH_OFFSET +@brief TS CAN Snapshot High Register Offset +*/ +#define IOH_1588_CXSH_OFFSET (0x68) /* TS_CAN_Snap */ + +/* Selector */ +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_ECS_OFFSET +@brief TS Ethernet/CAN Select Register Offset +*/ +#define IOH_1588_ECS_OFFSET (0x6c) /* TS_SEL */ + +/* Station Address 1-6 */ +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_STA_OFFSET +@brief TS Station Address Register Offset +*/ +#define IOH_1588_STA_OFFSET (0x70) /* TS_ST1 */ + +/* Bit Masks of Control Register */ +/* Hardware Assist Reset */ +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSC_RESET_SHIFT +@brief Reset Bit position in Control Register +*/ +#define IOH_1588_TSC_RESET_SHIFT 0 + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSC_RESET +@brief Bit Maks for Reset Bit in Control Register +*/ +#define IOH_1588_TSC_RESET (1 << IOH_1588_TSC_RESET_SHIFT) + +/* Target Time Interrupt Mask */ +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSC_TIM_SHIFT +@brief Bit position of Target Time Interrupt Bit in Control + Register +*/ +#define IOH_1588_TSC_TTM_SHIFT 1 + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSC_TIM_MASK +@brief Bit Mask for Target Time Interrupt in Control Register +*/ +#define IOH_1588_TSC_TTM_MASK (1 << IOH_1588_TSC_TTM_SHIFT) + +/* Auxiliary Slave Mode snapshot Interrupt Mask */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSC_ASMS_SHIFT +@brief Bit position of Aux Slave Mode snapshot + Interrupt in Control Register +*/ +#define IOH_1588_TSC_ASMS_SHIFT 2 + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSC_ASMS_MASK +@brief Bit Mask for Aux Slave Mode snapshot + Interrupt in Control Register +*/ +#define IOH_1588_TSC_ASMS_MASK (1 << IOH_1588_TSC_ASMS_SHIFT) + +/* Auxiliary Master Mode snapshot Interrupt Mask */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSC_AMMS_SHIFT +@brief Bit position for for Aux Master Mode snapshot + Interrupt in Control Register +*/ +#define IOH_1588_TSC_AMMS_SHIFT 3 + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSC_AMMS_MASK +@brief Bit mask for for Aux Master Mode snapshot + Interrupt in Control Register +*/ +#define IOH_1588_TSC_AMMS_MASK (1 << IOH_1588_TSC_AMMS_SHIFT) + +/* Pulse Per Second Interrupt Mask */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSC_PPSM_SHIFT +@brief Bit position of Pulse Per Second + Interrupt in Control Register +*/ +#define IOH_1588_TSC_PPSM_SHIFT 4 + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSC_PPSM_MASK +@brief Bit mask of Pulse Per Second + Interrupt in Control Register +*/ +#define IOH_1588_TSC_PPSM_MASK (1 << IOH_1588_TSC_PPSM_SHIFT) + +/* Bit Masks of Event Register */ +/* Target Time Interrupt Pending Event */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSE_TTIPEND_SHIFT +@brief Bit position of Target Time Interrupt + Pending in Event Register +*/ +#define IOH_1588_TSE_TTIPEND_SHIFT 1 + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSE_TTIPEND +@brief Bit mask of Target Time Interrupt + Pending in Event Register +*/ +#define IOH_1588_TSE_TTIPEND (1 << IOH_1588_TSE_TTIPEND_SHIFT) + +/* Auxiliary Slave Mode snapshot Event */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSE_SNS_SHIFT +@brief Bit position of Aux Slave Mode snapshot + in Event Register +*/ +#define IOH_1588_TSE_SNS_SHIFT 2 + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSE_SNS +@brief Bit mask of Aux Slave Mode snapshot + in Event Register +*/ +#define IOH_1588_TSE_SNS (1 << IOH_1588_TSE_SNS_SHIFT) + +/* Auxiliary Master Mode snapshot Event */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSE_SNM_SHIFT +@brief Bit position of Aux Master Mode snapshot + in Event Register +*/ +#define IOH_1588_TSE_SNM_SHIFT 3 + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSE_SNM +@brief Bit mask of Aux Master Mode snapshot + in Event Register +*/ +#define IOH_1588_TSE_SNM (1 << IOH_1588_TSE_SNM_SHIFT) + +/* Pulse Per Second Match */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSE_PPS_SHIFT +@brief Bit position of Pusle Per Second Match + in Event Register +*/ +#define IOH_1588_TSE_PPS_SHIFT 4 + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_TSE_PPS +@brief Bit mask of Pusle Per Second Match + in Event Register +*/ +#define IOH_1588_TSE_PPS (1 << IOH_1588_TSE_PPS_SHIFT) + +/* Bit Masks of Channel Control Register */ +/* Timestamp Master or Slave Mode Control Flag */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_CC_MM_SHIFT +@brief Bit position of Timestamp Master/Slave Mode + in Channel Control Register +*/ +#define IOH_1588_CC_MM_SHIFT 0 + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_CC_MM +@brief Bit mask of Timestamp Master/Slave Mode + control flag in + in Channel Control Register +*/ +#define IOH_1588_CC_MM (1 << IOH_1588_CC_MM_SHIFT) + +/* Timestamp All Messages Control Flag */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_CC_TA_SHIFT +@brief Bit position of Timestamp all messages + Mode control flag + in Channel Control Register +*/ +#define IOH_1588_CC_TA_SHIFT 1 + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_CC_TA +@brief Bit mask of Timestamp all messages + Mode control flag + in Channel Control Register +*/ +#define IOH_1588_CC_TA (1 << IOH_1588_CC_TA_SHIFT) + +/* Mode bits */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_CC_MODE_SHIFT +@brief Bit position of mode bits + in Channel Control Register +*/ +#define IOH_1588_CC_MODE_SHIFT 16 + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_CC_MODE_MASK +@brief Bit mask for mode bits + in Channel Control Register +*/ +#define IOH_1588_CC_MODE_MASK (0x001F0000) + +/* Version bit */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_CC_VERSION_SHIFT +@brief Bit position for version bits + in Channel Control Register +*/ +#define IOH_1588_CC_VERSION_SHIFT 31 + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_CC_VERSION +@brief Bit mask for version bits + in Channel Control Register +*/ +#define IOH_1588_CC_VERSION (1 << IOH_1588_CC_VERSION_SHIFT) + +/* Bit Masks of Channel Event Register */ +/* Transmit Snapshot Locked Indicator Flag */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_CE_TXS +@brief Bit mask for Transmit Snapshot Locked bit + in Channel Event Register +*/ +#define IOH_1588_CE_TXS (1 << 0) + +/* Receive Snapshot Locked Indicator Flag */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_CE_TXS +@brief Bit mask for Receive Snapshot Locked bit + in Channel Event Register +*/ +#define IOH_1588_CE_RXS (1 << 1) + +/* Bit Masks of CAN Channel Event Register */ +/* Overrun Indicator Flag */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_CE_OVR +@brief Bit mask for Overrun Indicator bit + in Channel Event Register +*/ +#define IOH_1588_CE_OVR (1 << 0) + +/* Valid Indicator Flag */ +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_CE_VAL +@brief Bit mask for Valid Indicator bit + in Channel Event Register +*/ +#define IOH_1588_CE_VAL (1 << 1) + +/* Ethernet Enable bit */ +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_ECS_ETH_SHIFT +@brief Bit position for Ethernet Enable bit + in Ethernet/CAN select Register +*/ +#define IOH_1588_ECS_ETH_SHIFT 0 + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_ECS_ETH +@brief Bit mask for Ethernet Enable bit + in Ethernet/CAN select Register +*/ +#define IOH_1588_ECS_ETH (1 << IOH_1588_ECS_ETH_SHIFT) +/* Can Enable bit */ + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_ECS_CAN_SHIFT +@brief Bit position for CAN Enable bit + in Ethernet/CAN select Register +*/ +#define IOH_1588_ECS_CAN_SHIFT 1 + +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_ECS_CAN +@brief Bit mask for CAN Enable bit + in Ethernet/CAN select Register +*/ +#define IOH_1588_ECS_CAN (1 << IOH_1588_ECS_CAN_SHIFT) + +/* Station Address bytes */ +/*! @ingroup IEEE_1588_HALLayerAPI +@def IOH_1588_STATION_BYTES +@brief Bytes for Station Address +*/ +#define IOH_1588_STATION_BYTES 6 + +/*! @ingroup IEEE_1588_HALLayerAPI +@def DRIVER_NAME +@brief The name of this driver +*/ +#define DRIVER_NAME "ioh_ieee1588" + +#define IOH_IEEE1588_ETH (1 << 0) +#define IOH_IEEE1588_CAN (1 << 1) + +/*! @ingroup IEEE_1588_HALLayerAPI +@typedef typedef void (*ioh1588TargetTimeCallback) + (struct ioh1588TimeValue tgt_time) +@brief Pointer for Callback function for Target Time interrupt +@see + - ioh_1588_blpl_base_address_set + - ioh_1588_target_time_interrupt_enable + - ioh_1588_target_time_interrupt_disable + - ioh_1588_target_time_poll + - ioh_1588_reset +*/ +typedef void (*ioh1588TargetTimeCallback) (struct ioh1588TimeValue tgt_time); + +/*! @ingroup IEEE_1588_HALLayerAPI +@typedef typedef void (*ioh1588AuxTimeCallback) + (enum ioh1588AuxMode aux_mode, + struct ioh1588TimeValue aux_time) +@brief Pointer for Callback function for Aux Time interrupt +@see + - ioh_1588_blpl_base_address_set + - ioh_1588_aux_time_interrupt_enable + - ioh_1588_aux_time_interrupt_disable + - ioh_1588_aux_time_poll + - ioh_1588_reset +*/ +typedef void (*ioh1588AuxTimeCallback) (enum ioh1588AuxMode aux_mode, + struct ioh1588TimeValue aux_time); + +/*! @ingroup IEEE_1588_HALLayerAPI +@typedef typedef void (*ioh1588PulsePerSecondCallback)( + unsigned long pps) +@brief Pointer for Callback function for Pulse Per Second + interrupt +@see + - ioh_1588_blpl_base_address_set + - ioh_1588_pulse_per_sec_interrupt_enable + - ioh_1588_pulse_per_sec_interrupt_disable + - ioh_1588_reset +*/ +typedef void (*ioh1588PulsePerSecondCallback) (unsigned long pps); + +/** + * prototypes of HAL APIs + */ + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_blpl_base_address_set(unsigned long base_addr) + */ +enum ioh_status ioh_1588_blpl_base_address_set(unsigned long base_addr); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_ptp_port_config_set( + * enum ioh1588PTPPort ptpPort, + * enum ioh1588PTPPortMode ptpPortMode) + */ +enum ioh_status +ioh_1588_ptp_port_config_set(enum ioh1588PTPPort ptpPort, + enum ioh1588PTPPortMode ptpPortMode); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_ptp_port_config_get( + * enum ioh1588PTPPort ptpPort, + * enum ioh1588PTPPortMode *ptpPortMode) + */ +enum ioh_status +ioh_1588_ptp_port_config_get(enum ioh1588PTPPort ptpPort, + enum ioh1588PTPPortMode *ptpPortMode); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_ptp_rx_poll( + * enum ioh1588PTPPort ptpPort, + * struct ioh1588PtpMsgData *ptpMsgData) + * + * + */ +enum ioh_status +ioh_1588_ptp_rx_poll( + enum ioh1588PTPPort ptpPort, \ + struct ioh1588PtpMsgData *ptpMsgData); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_ptp_tx_poll( + * enum ioh1588PTPPort ptpPort, + * struct ioh1588PtpMsgData *ptpMsgData) + * + */ +enum ioh_status +ioh_1588_ptp_tx_poll( + enum ioh1588PTPPort ptpPort, \ + struct ioh1588PtpMsgData *ptpMsgData); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_system_time_set( + * struct ioh1588TimeValue systemTime) + * + */ +enum ioh_status ioh_1588_system_time_set(struct ioh1588TimeValue systemTime); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_system_time_get( + * struct ioh1588TimeValue *systemTime) + * + */ +enum ioh_status ioh_1588_system_time_get(struct ioh1588TimeValue *systemTime); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_tick_rate_set(unsigned long tickRate) + * + */ +enum ioh_status ioh_1588_tick_rate_set(unsigned long tickRate); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_tick_rate_get(unsigned long *tickRate) + * + */ +enum ioh_status ioh_1588_tick_rate_get(unsigned long *tickRate); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_target_time_interrupt_enable( + * ioh1588TargetTimeCallback callBack) + * + */ +enum ioh_status +ioh_1588_target_time_interrupt_enable(ioh1588TargetTimeCallback callBack); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_target_time_interrupt_disable(void) + * + */ +enum ioh_status ioh_1588_target_time_interrupt_disable(void); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_target_time_poll( + * unsigned long *ttmPollFlag, + * struct ioh1588TimeValue *targetTime) + * + */ +enum ioh_status +ioh_1588_target_time_poll(unsigned long *ttmPollFlag, + struct ioh1588TimeValue *targetTime); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_target_time_set( + * struct ioh1588TimeValue targetTime) + * + */ +enum ioh_status ioh_1588_target_time_set(struct ioh1588TimeValue targetTime); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_target_time_get( + * struct ioh1588TimeValue *targetTime) + * + */ +enum ioh_status ioh_1588_target_time_get(struct ioh1588TimeValue *targetTime); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_aux_time_interrupt_enable( + enum ioh1588AuxMode auxMode, + * ioh1588AuxTimeCallback callBack) + * + */ +enum ioh_status +ioh_1588_aux_time_interrupt_enable(enum ioh1588AuxMode auxMode, + ioh1588AuxTimeCallback callBack); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_aux_time_interrupt_disable( + enum ioh1588AuxMode auxMode) + * + */ +enum ioh_status ioh_1588_aux_time_interrupt_disable( + enum ioh1588AuxMode auxMode); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_aux_time_poll( + * enum ioh1588AuxMode auxMode, + * unsigned long *pollFlag, + * struct ioh1588TimeValue *auxTime) + * + */ +enum ioh_status +ioh_1588_aux_time_poll(enum ioh1588AuxMode auxMode, + unsigned long *pollFlag, + struct ioh1588TimeValue *auxTime); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_reset(void) + * + */ +enum ioh_status ioh_1588_reset(void); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_chnl_reset(enum ioh1588PTPPort ptpPort) + * + */ +enum ioh_status ioh_1588_chnl_reset(enum ioh1588PTPPort ptpPort); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_stats_get(struct ioh1588Stats *stats) + * + */ +enum ioh_status ioh_1588_stats_get(struct ioh1588Stats *stats); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn void ioh_1588_stats_reset(void) + * + */ +void ioh_1588_stats_reset(void); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn void ioh_1588_show(void) + * + */ +enum ioh_status ioh_1588_show(void); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_pulse_per_sec_interrupt_enable( + * ioh1588PulsePerSecondCallback callBack) + * + */ +enum ioh_status +ioh_1588_pulse_per_sec_interrupt_enable(ioh1588PulsePerSecondCallback callBack); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_pulse_per_sec_interrupt_disable(void) + * + */ +enum ioh_status ioh_1588_pulse_per_sec_interrupt_disable(void); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_pulse_per_sec_time_get(unsigned long *ppsTime) + * + */ +enum ioh_status ioh_1588_pulse_per_sec_time_get(unsigned long *ppsTime); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_pulse_per_sec_time_set(unsigned long ppsTime) + * + */ +enum ioh_status ioh_1588_pulse_per_sec_time_set(unsigned long ppsTime); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_ptp_can_poll ( + * enum ioh1588PTPPort ptpPort, + * struct ioh1588TimeValue *ptpTimeStamp) + * + */ +enum ioh_status ioh_1588_ptp_can_poll(enum ioh1588PTPPort ptpPort, + struct ioh1588TimeValue *ptpTimeStamp); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_ptp_version_get(enum ioh1588PTPPort ptpPort, + * enum ioh1588PTPVersion *ptpVersion) + * + */ +enum ioh_status +ioh_1588_ptp_version_get(enum ioh1588PTPPort ptpPort, + enum ioh1588PTPVersion *ptpVersion); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_ptp_version_set(enum ioh1588PTPPort ptpPort, + * enum ioh1588PTPVersion ptpVersion) + * + */ +enum ioh_status +ioh_1588_ptp_version_set( + enum ioh1588PTPPort ptpPort, \ + enum ioh1588PTPVersion ptpVersion); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_ptp_operation_mode_set( + * enum ioh1588PTPPort ptpPort, + * enum ioh1588PTPOperationMode ptpMode) + * + */ +enum ioh_status +ioh_1588_ptp_operation_mode_set(enum ioh1588PTPPort ptpPort, + enum ioh1588PTPOperationMode ptpMode); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_ptp_operation_mode_get(enum ioh1588PTPPort ptpPort, + * enum ioh1588PTPOperationMode *ptpMode) + */ +enum ioh_status +ioh_1588_ptp_operation_mode_get(enum ioh1588PTPPort ptpPort, + enum ioh1588PTPOperationMode *ptpMode); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_handler(void) + * + */ +enum ioh_status ioh_1588_handler(void); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_aux_target_time_interrupt_enable(void *callBack) + * + */ +enum ioh_status ioh_1588_aux_target_time_interrupt_enable(void *callBack); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_aux_target_time_interrupt_disable(void) + * + */ +enum ioh_status ioh_1588_aux_target_time_interrupt_disable(void); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_aux_target_time_poll( + * unsigned long *attmPollFlag, struct ioh1588TimeValue *targetTime) + * + */ +enum ioh_status +ioh_1588_aux_target_time_poll(unsigned long *attmPollFlag, + struct ioh1588TimeValue *targetTime); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_aux_target_time_set( + * struct ioh1588TimeValue targetTime) + * + */ +enum ioh_status ioh_1588_aux_target_time_set( + struct ioh1588TimeValue targetTime); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_aux_target_time_get( + * struct ioh1588TimeValue *targetTime) + * + */ +enum ioh_status ioh_1588_aux_target_time_get( + struct ioh1588TimeValue *stargetTime); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_disable_interrupts(void) + * + */ +enum ioh_status ioh_1588_disable_interrupts(void); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_interrupt_pending(unsigned long *pending) + * + */ +enum ioh_status ioh_1588_interrupt_pending(unsigned long *pending); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_eth_enable(void) + * + */ +enum ioh_status ioh_1588_eth_enable(void); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_eth_disable(void) + * + */ +enum ioh_status ioh_1588_eth_disable(void); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_can_enable(void) + * + */ +enum ioh_status ioh_1588_can_enable(void); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_can_disable(void) + * + */ +enum ioh_status ioh_1588_can_disable(void); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_set_station_address (unsigned char *addr) + * + */ +enum ioh_status ioh_1588_set_station_address(unsigned char *addr); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn enum ioh_status ioh_1588_get_station_address(char *addr) + * + */ +enum ioh_status ioh_1588_get_station_address(char *addr); + +/*! @ingroup IEEE_1588_HALLayerAPI + * @fn int ioh_1588_eth_can_get(void) + * + */ +int ioh_1588_eth_can_get(void); + +#ifdef IOH_IEEE1588_A0_A1_SAMPLE_BUG +void ioh_1588_set_system_time_count(void); +#endif + +#endif /* IOH_1588_HAL_H */ diff -urN linux-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_main.c topcliff-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_main.c --- linux-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_main.c 1970-01-01 09:00:00.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_main.c 2010-03-09 10:33:42.000000000 +0900 @@ -0,0 +1,1192 @@ + /*! + * @file ioh_1588_main.c + * @brief + * This file contains the definitions of the IEEE_1588_InterfaceLayer APIs + * @version 0.92 + * @section + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * History: + * modified to support Intel IOH GE IEEE 1588 hardware + * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. + * All rights reserved. + * derived from + * IEEE 1588 Time Synchronization Driver for Intel EP80579 + * Copyright(c) 2007,2008 Intel Corporation. All rights reserved. + * All rights reserved. + */ + +#include "pch_1588_pci.h" +#include "pch_1588_main.h" +#include "pch_1588_hal.h" +#include "pch_debug.h" +#include + +/* Linux functions prototypes */ +static int ioh_1588_open(struct inode *inode, struct file *filep); +static int ioh_1588_release(struct inode *inode, struct file *filep); +static int ioh_1588_ioctl(struct inode *inode, struct file *filep, + unsigned int cmd, unsigned long arg); + +/* Linux file operations */ +/*! @ingroup IEEE_1588_Global + * @var ioh_1588_fops + * @brief The structure variable used to specify the + * driver specific functionalities to the kernel + * subsystem. +*/ +const struct file_operations ioh_1588_fops = { + .owner = THIS_MODULE, + .open = ioh_1588_open, + .release = ioh_1588_release, + .ioctl = ioh_1588_ioctl, +}; + +/* For notify ioctls - values are populated from isr callbacks */ +/*! @ingroup IEEE_1588_Global + * @var ioh_1588_target_time + * @brief This variable is updated from the target time reached callback + */ +struct ioh1588TimeValue ioh_1588_target_time; +/*! @ingroup IEEE_1588_Global + * @var ioh_1588_aux_time + * @brief This variable is updated from the Auxiliary master/slave time + * captured callback + */ +struct ioh1588AuxTimeIoctl ioh_1588_aux_time; +/*! @ingroup IEEE_1588_Global + * @var ioh_1588_pps_time + * @brief This variable is updated from the Pulse per second match + * callback + */ +unsigned long ioh_1588_pps_time; + +typedef int (*ioc_func_ptr) (unsigned long cmd, char *arg); +static int ioc_handle_notify(unsigned long cmd, char *buf); +static int ioc_handle_clr_notify(unsigned long cmd, char *buf); +static int ioc_handle_reset(unsigned long cmd, char *buf); +static int ioc_handle_show(unsigned long cmd, char *buf); +static int ioc_handle_stats(unsigned long cmd, char *buf); +static int ioc_handle_stats_reset(unsigned long cmd, char *buf); +static int ioc_handle_int_enable(unsigned long cmd, char *buf); +static int ioc_handle_int_disable(unsigned long cmd, char *buf); +static int ioc_handle_port_config(unsigned long cmd, char *buf); +static int ioc_handle_poll(unsigned long cmd, char *buf); +static int ioc_handle_time_set(unsigned long cmd, char *buf); +static int ioc_handle_time_get(unsigned long cmd, char *buf); +static int ioc_handle_tick_rate(unsigned long cmd, char *buf); +static int ioc_handle_pps_reqt(unsigned long cmd, char *buf); +static int ioc_handle_version_reqt(unsigned long cmd, char *buf); +static int ioc_handle_op_mode_reqt(unsigned long cmd, char *buf); + +/* IOCTL command and their associated functions */ + +/*! @ingroup IEEE_1588_Global + * @struct ioh_1588_ioc_tbl + * @brief Structure to map the ioctl command to the associated function + */ +static const struct ioh_1588_ioc_tbl { + unsigned long cmd; + ioc_func_ptr func; +} ioh_1588_ioc_tbl[] = { + { + IOCTL_1588_TARG_TIME_NOTIFY, ioc_handle_notify}, { + IOCTL_1588_AUX_TIME_NOTIFY, ioc_handle_notify}, { + IOCTL_1588_PULSE_PER_SEC_NOTIFY, ioc_handle_notify}, { + IOCTL_1588_AUX_TARG_TIME_NOTIFY, ioc_handle_notify}, { + IOCTL_1588_TARG_TIME_CLR_NOTIFY, ioc_handle_clr_notify}, { + IOCTL_1588_AUX_TIME_CLR_NOTIFY, ioc_handle_clr_notify}, { + IOCTL_1588_PULSE_PER_SEC_CLR_NOTIFY, ioc_handle_clr_notify}, { + IOCTL_1588_AUX_TARG_TIME_CLR_NOTIFY, ioc_handle_clr_notify}, { + IOCTL_1588_RESET, ioc_handle_reset}, { + IOCTL_1588_CHNL_RESET, ioc_handle_reset}, /* for this case too */ + { + IOCTL_1588_SHOW_ALL, ioc_handle_show}, { + IOCTL_1588_STATS_GET, ioc_handle_stats}, { + IOCTL_1588_STATS_RESET, ioc_handle_stats_reset}, { + IOCTL_1588_TARG_TIME_INTRPT_ENABLE, ioc_handle_int_enable}, { + IOCTL_1588_AUX_TIME_INTRPT_ENABLE, ioc_handle_int_enable}, { + IOCTL_1588_PULSE_PER_SEC_INTRPT_ENABLE, ioc_handle_int_enable}, { + IOCTL_1588_AUX_TARG_TIME_INTRPT_ENABLE, ioc_handle_int_enable}, { + IOCTL_1588_TARG_TIME_INTRPT_DISABLE, ioc_handle_int_disable}, { + IOCTL_1588_AUX_TIME_INTRPT_DISABLE, ioc_handle_int_disable}, { + IOCTL_1588_PULSE_PER_SEC_INTRPT_DISABLE, ioc_handle_int_disable}, { + IOCTL_1588_AUX_TARG_TIME_INTRPT_DISABLE, ioc_handle_int_disable}, { + IOCTL_1588_PORT_CONFIG_SET, ioc_handle_port_config}, { + IOCTL_1588_PORT_CONFIG_GET, ioc_handle_port_config}, { + IOCTL_1588_RX_POLL, ioc_handle_poll}, { + IOCTL_1588_TX_POLL, ioc_handle_poll}, { + IOCTL_1588_CAN_POLL, ioc_handle_poll}, { + IOCTL_1588_TARG_TIME_POLL, ioc_handle_poll}, { + IOCTL_1588_AUX_TIME_POLL, ioc_handle_poll}, { + IOCTL_1588_AUX_TARG_TIME_POLL, ioc_handle_poll}, { + IOCTL_1588_SYS_TIME_SET, ioc_handle_time_set}, { + IOCTL_1588_TARG_TIME_SET, ioc_handle_time_set}, { + IOCTL_1588_AUX_TARG_TIME_SET, ioc_handle_time_set}, { + IOCTL_1588_SYS_TIME_GET, ioc_handle_time_get}, { + IOCTL_1588_TARG_TIME_GET, ioc_handle_time_get}, { + IOCTL_1588_AUX_TARG_TIME_GET, ioc_handle_time_get}, { + IOCTL_1588_TICK_RATE_GET, ioc_handle_tick_rate}, { + IOCTL_1588_TICK_RATE_SET, ioc_handle_tick_rate}, { + IOCTL_1588_PULSE_PER_SEC_TIME_SET, ioc_handle_pps_reqt}, { + IOCTL_1588_PULSE_PER_SEC_TIME_GET, ioc_handle_pps_reqt}, { + IOCTL_1588_PORT_VERSION_SET, ioc_handle_version_reqt}, { + IOCTL_1588_PORT_VERSION_GET, ioc_handle_version_reqt}, { + IOCTL_1588_PORT_OPERATION_MODE_SET, ioc_handle_op_mode_reqt}, { +IOCTL_1588_PORT_OPERATION_MODE_GET, ioc_handle_op_mode_reqt},}; + +#define IOH_1588_IOC_TBL_ENTRIES \ + (sizeof ioh_1588_ioc_tbl / sizeof ioh_1588_ioc_tbl[0]) + +/*! @ingroup IEEE_1588_InterfaceLayerAPI + * @fn int ioh_1588_open(struct inode *inode, struct file *filep) + * @brief This function is called when the driver interface is opened + * @remarks This function is registered at the driver initialization + * point (module_init) and invoked when a process opens the + * IEEE 1588 device node. + * + * @param inode [IN] pointer to device inode structure + * @param filep [IN] pointer to open file structure + * + * @return int + * - Returns 0 on success and <0 on failure + */ +static int ioh_1588_open(struct inode *inode, struct file *filep) +{ + if (ioh_1588_devp->suspend) { + IOH_LOG(KERN_ERR, + "ioh_1588_open returning as device is suspended\n"); + return -EINTR; + } + IOH_DEBUG("ioh_1588_open\n"); + + return 0; +} + +/*! @ingroup IEEE_1588_InterfaceLayerAPI + * @fn int ioh_1588_release(struct inode *inode, struct file *filep) + * @brief This function is called when the driver interface is closed + * @remarks This function is registered at the driver initialization + * point (module_init) and invoked when the last process + * which has an open file table entry for the device + * exits or does a close of the device file. + * + * @param inode [IN] pointer to device inode structure + * @param filep [IN] pointer to open file structure + * + * @retval int + * - Returns 0 on success and <0 on failure + */ +static int ioh_1588_release(struct inode *inode, struct file *filep) +{ + IOH_DEBUG("ioh_1588_release\n"); + + return 0; +} + +/*! @ingroup IEEE_1588_InterfaceLayerAPI + * @fn int ioh_1588_ioctl(struct inode *inode, struct file *filep, + * unsigned int cmd, unsigned long arg) + * @brief This function implements the ioctl interface of the driver + * @remarks This function is registered at the driver initialization + * point (module_init) and invoked when a user process + * invokes the .ioctl. call on the device + * + * @param inode [IN] pointer to device inode structure + * @param filep [IN] pointer to open file structure + * @param cmd [IN] ioctl command + * @param arg [INOUT] argument passed to the command + * + * @retval int + * - Returns 0 on success and <0 on failure + */ +static int ioh_1588_ioctl(struct inode *inode, struct file *filep, + unsigned int cmd, unsigned long arg) +{ + char buffer[0x64]; + unsigned int argsz; + int i, ret = 0; + + if ((!ioh_1588_devp->initialized) || (ioh_1588_devp->suspend)) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl:device is suspended OR \ + uninitialized\n"); + return -EINTR; + } + + argsz = _IOC_SIZE(cmd); + + if (argsz > sizeof buffer) { + IOH_LOG(KERN_ERR, "ioh_1588_ioctl: buffer size too small.\n"); + return -EINVAL; + } + + /* if data is being written to the driver */ + if (_IOC_DIR(cmd) & _IOC_WRITE) { + /* get the data passed in by user */ + if (copy_from_user(&buffer, (void *)arg, argsz)) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: could not copy user space \ + data.\n"); + return -EFAULT; + } + } + + for (i = 0; i < IOH_1588_IOC_TBL_ENTRIES; i++) { + if (ioh_1588_ioc_tbl[i].cmd == cmd) { + ret = ioh_1588_ioc_tbl[i].func(cmd, buffer); + break; + } + } + if (i >= IOH_1588_IOC_TBL_ENTRIES) { /* did not find a match */ + IOH_LOG(KERN_ERR, "ioh_1588_ioctl: unknown command (0x%x)\n", + cmd); + return -EINVAL; + } + + /* if data is being read from the driver */ + if ((ret == 0) && (_IOC_DIR(cmd) & _IOC_READ)) { + if (copy_to_user((void *)arg, buffer, argsz)) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: could not copy data to user \ + space.\n"); + return -EFAULT; + } + } + + return ret; +} + +/* Handles all NOTIFY IOCTLs */ +/*! @ingroup IEEE_1588_UtilitiesAPI + * @fn ioc_handle_notify (unsigned long cmd, char *buf) + * @brief Handles all NOTIFY IOCTLs + * @param cmd [IN] the IOCTL command + * @param buf [OUT] the reference to data to be returned + * @retval int + * - 0 + *
+ */ +static int ioc_handle_notify(unsigned long cmd, char *buf) +{ + unsigned int bytes_ret = 0; + void *param_addr = NULL; + wait_queue_head_t *event = NULL; + unsigned int eventnum = 0; + + if (IOCTL_1588_AUX_TARG_TIME_NOTIFY == cmd) { + IOH_LOG(KERN_ERR, "ioc_handle_notify \ + returning...[cmd = IOCTL_1588_AUX_TARG_TIME_NOTIFY]\n"); + return -EINVAL; + } + /* request to be notified of a 1588 interrupt event Target Time */ + else if (cmd == IOCTL_1588_TARG_TIME_NOTIFY) { + IOH_DEBUG + ("ioc_handle_notify cmd = IOCTL_1588_TARG_TIME_NOTIFY]\n"); + event = &ioh_1588_devp->notify_evt[TARG_TIME_EVENT_NUM]; + bytes_ret = sizeof(struct ioh1588TimeValue); + param_addr = &ioh_1588_target_time; + eventnum = TARG_TIME_EVENT_NUM; + } else if (cmd == IOCTL_1588_AUX_TIME_NOTIFY) { + IOH_DEBUG + ("ioc_handle_notify cmd = IOCTL_1588_AUX_TIME_NOTIFY]\n"); + event = &ioh_1588_devp->notify_evt[AUX_TIME_EVENT_NUM]; + bytes_ret = sizeof(struct ioh1588AuxTimeIoctl); + param_addr = &ioh_1588_aux_time; + eventnum = AUX_TIME_EVENT_NUM; + } else { + event = &ioh_1588_devp->notify_evt[PPS_EVENT_NUM]; + bytes_ret = sizeof(unsigned long); + param_addr = &ioh_1588_pps_time; + eventnum = PPS_EVENT_NUM; + } + + ioh_1588_devp->event_flags[eventnum] = 0; + + /* wait infinitely for a 1588 interrupt event to occur */ + IOH_DEBUG("ioc_handle_notify waiting for interrupt event...\n"); + wait_event_interruptible(*event, + ioh_1588_devp->event_flags[eventnum] == 1); + IOH_DEBUG("ioc_handle_notify got interrupt event...\n"); + + /* copy global data retreived from interrupt handler */ + (void)memcpy((void *)&buf, (const void *)param_addr, bytes_ret); + + /* reset global data to 0 */ + (void)memset((void *)param_addr, 0, bytes_ret); + + ioh_1588_devp->event_flags[eventnum] = 0; + + return 0; +} + +/* Handles all CLEAR NOTIFY IOCTLs */ +/*! @ingroup IEEE_1588_UtilitiesAPI + * @fn ioc_handle_clr_notify (unsigned long cmd, char *buf) + * @brief Handles all CLEAR NOTIFY IOCTLs + * @param cmd [IN] the IOCTL command + * @param buf unused + * @retval int + * - 0 on success + * - -EINVAL for unsupported IOCTL + *
+ */ +static int ioc_handle_clr_notify(unsigned long cmd, char *buf) +{ + unsigned int eventnum = 0; + + /* + * request to release a notify thread that is waiting + * on a 1588 interrupt event + */ + if (cmd == IOCTL_1588_TARG_TIME_CLR_NOTIFY) { + IOH_DEBUG + ("ioc_handle_clr_notify cmd=\ + IOCTL_1588_TARG_TIME_CLR_NOTIFY\n"); + eventnum = TARG_TIME_EVENT_NUM; + } else if (cmd == IOCTL_1588_AUX_TIME_CLR_NOTIFY) { + IOH_DEBUG + ("ioc_handle_clr_notify cmd=\ + IOCTL_1588_AUX_TIME_CLR_NOTIFY\n"); + eventnum = AUX_TIME_EVENT_NUM; + } else if (cmd == IOCTL_1588_PULSE_PER_SEC_CLR_NOTIFY) { + IOH_DEBUG + ("ioc_handle_clr_notify cmd=\ + IOCTL_1588_PULSE_PER_SEC_CLR_NOTIFY\n"); + eventnum = PPS_EVENT_NUM; + } else if (cmd == IOCTL_1588_AUX_TARG_TIME_CLR_NOTIFY) { + IOH_DEBUG + ("ioc_handle_clr_notify cmd=\ + IOCTL_1588_AUX_TARG_TIME_CLR_NOTIFY\n"); + IOH_LOG(KERN_ERR, "ioc_handle_clr_notify returning -EINVAL\n"); + return -EINVAL; + } + + ioh_1588_devp->event_flags[eventnum] = 1; + + IOH_DEBUG("ioc_handle_clr_notify waking up blocking notify call...\n"); + wake_up_interruptible(&ioh_1588_devp->notify_evt[eventnum]); + return 0; +} + +/* Handles reset and channel reset IOCTLs */ + +/*! @ingroup IEEE_1588_UtilitiesAPI + * @fn ioc_handle_reset (unsigned long cmd, char *buf) + * @brief Handles reset and channel reset IOCTLs + * @param cmd [IN] the IOCTL command + * @param buf unused + * @retval int + * - 0 on success + * - -EINVAL when hardware reset fails + *
+ */ +static int ioc_handle_reset(unsigned long cmd, char *buf) +{ + int i = 0; + int ieee_mode; + unsigned char station[STATION_ADDR_LEN] = "00:00:00:00:00:00"; + + IOH_DEBUG("ioc_handle_reset: invoking ioh_1588_reset\n"); + + /*retrieve eth/CAN mode */ + ieee_mode = ioh_1588_eth_can_get(); + + /*retrive station address */ + ioh_1588_get_station_address(station); + + /* reset the 1588 hardware */ + if (ioh_1588_reset() != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, "ioc_handle_reset: ioh_1588_reset failed\n"); + return -EINVAL; + } + /* Anyway, now clear all the events */ + for (i = 0; i < NUM_EVENTS; i++) + ioh_1588_devp->event_flags[i] = 0; + /*set ETH/CAN mode */ + if (ieee_mode & IOH_IEEE1588_ETH) + ioh_1588_eth_enable(); + if (ieee_mode & IOH_IEEE1588_CAN) + ioh_1588_can_enable(); + + /*set station address */ + if (strcmp(station, "00:00:00:00:00:00") != 0) { + if (ioh_1588_set_station_address(station) != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_reset: could not set station \ + address\n"); + } + } + + IOH_DEBUG("ioc_handle_reset: returning 0\n"); + return 0; +} + +/* Handles reset statistics IOCTL */ +/*! @ingroup IEEE_1588_UtilitiesAPI + * @fn ioc_handle_stats_reset (unsigned long cmd, char *buf) + * @brief Handles reset statistics IOCTLs + * @param cmd unused + * @param buf unused + * @retval int + * - 0 on success + *
+ */ +static int ioc_handle_stats_reset(unsigned long cmd, char *buf) +{ + + IOH_DEBUG("ioc_handle_stats_reset: invoking ioh_1588_stats_reset\n"); + ioh_1588_stats_reset(); + IOH_DEBUG("ioc_handle_stats_reset: returning 0\n"); + return 0; +} + +/* Handles get statistics IOCTL */ +/*! @ingroup IEEE_1588_UtilitiesAPI + * @fn ioc_handle_stats (unsigned long cmd, char *buf) + * @brief Handles get statistics IOCTL + * @param cmd [IN] the IOCTL command + * @param buf [OUT] reference to statistics retrieved + * @retval int + * - 0 on success + *
+ */ +static int ioc_handle_stats(unsigned long cmd, char *buf) +{ + IOH_DEBUG("ioc_handle_stats: invoking ioh_ioh_1588_stats_get\n"); + if (ioh_1588_stats_get((struct ioh1588Stats *) buf) != \ + IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: ioh_1588_stats_get failed\n"); + return -EINVAL; + } + IOH_DEBUG("ioc_handle_statst: returning 0\n"); + return 0; +} + +/* Handles show all IOCTL */ +/*! @ingroup IEEE_1588_UtilitiesAPI + * @fn ioc_handle_show (unsigned long cmd, char *buf) + * @brief Handles show all IOCTL + * @param cmd unused + * @param buf unused + * @retval int + * - 0 on success + * - -EINVAL when @ref ioh_1588_show fails + *
+ */ +static int ioc_handle_show(unsigned long cmd, char *buf) +{ + IOH_DEBUG("ioc_handle_show: invoking ioh_1588_show\n"); + if (ioh_1588_show() != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, "ioh_1588_ioctl: ioh_1588_show failed\n"); + return -EINVAL; + } + IOH_DEBUG("ioc_handle_show: returning 0\n"); + return 0; +} + +/* Handles all interrupt enable IOCTLs */ +/*! @ingroup IEEE_1588_UtilitiesAPI + * @fn ioc_handle_int_enable (unsigned long cmd, char *buf) + * @brief Handles all interrupt enable IOCTLs + * @param cmd [IN] the IOCTL command + * @param buf [IN] the reference to auxiliary mode + * @retval int + * - 0 on success + * - -EINVAL failed to enable interrupt + *
+ */ +static int ioc_handle_int_enable(unsigned long cmd, char *buf) +{ + int ret = 0; + + if (IOCTL_1588_TARG_TIME_INTRPT_ENABLE == cmd) { + IOH_DEBUG + ("ioc_handle_int_enable cmd=\ + IOCTL_1588_TARG_TIME_INTRPT_ENABLE \ + invoking \ + ioh_1588_target_time_interrupt_enable\n"); + if (ioh_1588_target_time_interrupt_enable(target_time_callback) + != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, "ioh_1588_ioctl: \ + ioh_1588_target_time_interrupt_enable \ + failed\n"); + ret = -EINVAL; + } + } else if (IOCTL_1588_AUX_TIME_INTRPT_ENABLE == cmd) { + enum ioh1588AuxMode aux_mode; + IOH_DEBUG + ("ioc_handle_int_enable cmd=\ + IOCTL_1588_AUX_TIME_INTRPT_ENABLE \ + invoking ioh_1588_aux_time_interrupt_enable\n"); + + (void)memcpy((void *)&aux_mode, (const void *)buf, + sizeof(enum ioh1588AuxMode)); + + if (ioh_1588_aux_time_interrupt_enable + (aux_mode, auxiliary_time_callback) != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, "ioh_1588_ioctl: \ + ioh_1588_aux_time_interrupt_enable \ + failed\n"); + ret = -EINVAL; + } + } else if (IOCTL_1588_PULSE_PER_SEC_INTRPT_ENABLE == cmd) { + IOH_DEBUG + ("ioc_handle_int_enable cmd=\ + IOCTL_1588_PULSE_PER_SEC_INTRPT_ENABLE \ + invoking \ + ioh_1588_pulse_per_sec_interrupt_enable\n"); + if (ioh_1588_pulse_per_sec_interrupt_enable + (pulse_per_sec_callback) + != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, "ioh_1588_ioctl: \ + ioh_1588_pps_interrupt_enable \ + failed\n"); + ret = -EINVAL; + } + } else { /* IOCTL_1588_AUX_TARG_TIME_INTRPT_ENABLE */ + + IOH_DEBUG + ("ioc_handle_int_enable cmd=\ + OCTL_1588_AUX_TARG_TIME_INTRPT_ENABLE \ + invoking \ + ioh_1588_aux_target_time_interrupt_enable\n"); + if (ioh_1588_aux_target_time_interrupt_enable((void *)NULL) + != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, "ioh_1588_ioctl: \ + ioh_1588_aux_target_time_interrupt_enable \ + failed\n"); + ret = -EINVAL; + } + } + return ret; +} + +/* Handles all interrupt disable IOCTLs */ +/*! @ingroup IEEE_1588_UtilitiesAPI + * @fn ioc_handle_int_disable (unsigned long cmd, char *buf) + * @brief Handles all interrupt enable IOCTLs + * @param cmd [IN] the IOCTL command + * @param buf [IN] the reference to auxiliary mode + * @retval int + * - 0 on success + * - -EINVAL failed to disable interrupt + *
+ */ +static int ioc_handle_int_disable(unsigned long cmd, char *buf) +{ + int ret = 0; + + if (IOCTL_1588_TARG_TIME_INTRPT_DISABLE == cmd) { + IOH_DEBUG + ("ioc_handle_int_disable cmd=\ + IOCTL_1588_TARG_TIME_INTRPT_DISABLE \ + invoking \ + ioh_1588_target_time_interrupt_disable\n"); + if (ioh_1588_target_time_interrupt_disable() + != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, "ioh_1588_ioctl: \ + ioh_1588_target_time_interrupt_disable \ + failed\n"); + ret = -EINVAL; + } + } else if (IOCTL_1588_AUX_TIME_INTRPT_DISABLE == cmd) { + enum ioh1588AuxMode aux_mode; + IOH_DEBUG + ("ioc_handle_int_disable cmd=\ + IOCTL_1588_AUX_TIME_INTRPT_DISABLE \ + invoking \ + ioh_1588_aux_time_interrupt_disable\n"); + + (void)memcpy((void *)&aux_mode, (const void *)buf, + sizeof(enum ioh1588AuxMode)); + + if (ioh_1588_aux_time_interrupt_disable(aux_mode) + != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, "ioh_1588_ioctl: \ + ioh_1588_aux_time_interrupt_disable \ + failed\n"); + ret = -EINVAL; + } + } else if (IOCTL_1588_PULSE_PER_SEC_INTRPT_DISABLE == cmd) { + IOH_DEBUG + ("ioc_handle_int_disable cmd=\ + IOCTL_1588_PULSE_PER_SEC_INTRPT_DISABLE \ + invoking \ + ioh_1588_pulse_per_sec_interrupt_disable\n"); + if (ioh_1588_pulse_per_sec_interrupt_disable() != + IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, "ioh_1588_ioctl: \ + ioh_1588_pulse_per_sec_interrupt_disable \ + failed\n"); + ret = -EINVAL; + } + } else { /* IOCTL_1588_AUX_TARG_TIME_INTRPT_DISABLE */ + + IOH_DEBUG + ("ioc_handle_int_disable cmd=\ + IOCTL_1588_AUX_TARG_TIME_INTRPT_DISABLE \ + invoking \ + ioh_1588_aux_target_time_interrupt_disable\n"); + if (ioh_1588_aux_target_time_interrupt_disable() != + IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, "ioh_1588_ioctl: \ + ioh_1588_aux_target_time_interrupt_disable \ + failed\n"); + ret = -EINVAL; + } + } + return ret; +} + +/* Handles port config set/get IOCTLs */ +/*! @ingroup IEEE_1588_UtilitiesAPI + * @fn ioc_handle_port_config (unsigned long cmd, char *buf) + * @brief Handles port config set/get IOCTLs + * @param cmd [IN] the IOCTL command + * @param buf [IN] the port configuration + * @retval int + * - 0 on success + * - -EINVAL failed to set/get port configuration + *
+ */ +static int ioc_handle_port_config(unsigned long cmd, char *buf) +{ + struct ioh1588PortCfgIoctl *port_cfg_ioctl = \ + (struct ioh1588PortCfgIoctl *) buf; + + if (IOCTL_1588_PORT_CONFIG_SET == cmd) { + IOH_DEBUG + ("ioc_handle_port_config cmd = IOCTL_1588_PORT_CONFIG_SET \ + invoking ioh_1588_ptp_port_config_set\n"); + + if (ioh_1588_ptp_port_config_set(port_cfg_ioctl->ptpPort, + port_cfg_ioctl->ptpPortMode) != + IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: ioh_1588_ptp_port_config_set \ + failed\n"); + return -EINVAL; + } + } else { /* IOCTL_1588_PORT_CONFIG_GET */ + + IOH_DEBUG + ("ioc_handle_port_config cmd = IOCTL_1588_PORT_CONFIG_GET \ + invoking ioh_1588_ptp_port_config_get\n"); + if (ioh_1588_ptp_port_config_get + (port_cfg_ioctl->ptpPort, + &port_cfg_ioctl->ptpPortMode) != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: ioh_1588_ptp_port_config_get \ + failed\n"); + return -EINVAL; + } + } + return 0; +} + +/* Handles all POLL IOCTLs */ +/*! @ingroup IEEE_1588_UtilitiesAPI + * @fn ioc_handle_poll (unsigned long cmd, char *buf) + * @brief Handles all poll IOCTLs + * @param cmd [IN] the IOCTL command + * @param buf [IN] the poll configuration + * @retval int + * - 0 on success + * - -EINVAL on failure + *
+ */ +static int ioc_handle_poll(unsigned long cmd, char *buf) +{ + int ret = 0; + struct ioh1588RxTxPollIoctl *poll_ioctl = \ + (struct ioh1588RxTxPollIoctl *) buf; + struct ioh1588CANPollIoctl *can_poll_ioctl = \ + (struct ioh1588CANPollIoctl *) buf; + struct ioh1588TimePollIoctl *time_poll_ioctl = \ + (struct ioh1588TimePollIoctl *) buf; + + if (IOCTL_1588_RX_POLL == cmd) { + IOH_DEBUG("ioc_handle_poll: cmd = IOCTL_1588_RX_POLL \ + invoking ioh_1588_ptp_rx_poll\n"); + ret = ioh_1588_ptp_rx_poll(poll_ioctl->ptpPort, + &poll_ioctl->ptpMsgData); + if ((ret != IOH_1588_SUCCESS) && \ + (ret != IOH_1588_NOTIMESTAMP)) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: ioh_1588_ptp_rx_poll \ + failed\n"); + ret = -EINVAL; + } + } else if (IOCTL_1588_TX_POLL == cmd) { + IOH_DEBUG("ioc_handle_poll: cmd = IOCTL_1588_TX_POLL \ + invoking ioh_1588_ptp_tx_poll\n"); + ret = ioh_1588_ptp_tx_poll(poll_ioctl->ptpPort, + &poll_ioctl->ptpMsgData); + if ((ret != IOH_1588_SUCCESS) && \ + (ret != IOH_1588_NOTIMESTAMP)) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: ioh_1588_ptp_tx_poll \ + failed\n"); + ret = -EINVAL; + } + } else if (IOCTL_1588_CAN_POLL == cmd) { + IOH_DEBUG("ioc_handle_poll: cmd = IOCTL_1588_CAN_POLL \ + invoking ioh_1588_ptp_can_poll\n"); + ret = ioh_1588_ptp_can_poll(can_poll_ioctl->ptpPort, + &can_poll_ioctl->ptpTimeStamp); + if ((ret != IOH_1588_SUCCESS) && \ + (ret != IOH_1588_NOTIMESTAMP)) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: ioh_1588_ptp_can_poll \ + failed\n"); + ret = -EINVAL; + } + } else if (IOCTL_1588_TARG_TIME_POLL == cmd) { + IOH_DEBUG("ioc_handle_poll: cmd = IOCTL_1588_TARG_TIME_POLL " + "invoking ioh_1588_target_time_poll\n"); + if (ioh_1588_target_time_poll(&time_poll_ioctl->pollFlag, + &time_poll_ioctl->timeVal) != + IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: ioh_1588_target_time_poll \ + failed\n"); + ret = -EINVAL; + } + } else if (IOCTL_1588_AUX_TIME_POLL == cmd) { + IOH_DEBUG("ioc_handle_poll: cmd = IOCTL_1588_AUX_TIME_POLL " + "invoking ioh_1588_aux_time_poll\n"); + if (ioh_1588_aux_time_poll(time_poll_ioctl->auxMode, + &time_poll_ioctl->pollFlag, + &time_poll_ioctl->timeVal) + != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: ioh_1588_aux_time_poll \ + failed\n"); + ret = -EINVAL; + } + } else { /* IOCTL_1588_AUX_TARG_TIME_POLL */ + + IOH_DEBUG + ("ioc_handle_poll: cmd = IOCTL_1588_AUX_TARG_TIME_POLL " + "invoking ioh_1588_aux_target_time_poll\n"); + if (ioh_1588_aux_target_time_poll + (&time_poll_ioctl->pollFlag, + &time_poll_ioctl->timeVal) != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: ioh_1588_aux_target_time_poll \ + failed\n"); + ret = -EINVAL; + } + } + if ((unsigned long)ret == IOH_1588_NOTIMESTAMP) + ret = 0; + return ret; +} + +/* Handles all Time Set IOCTLs */ +/*! @ingroup IEEE_1588_UtilitiesAPI + * @fn ioc_handle_time_set (unsigned long cmd, char *buf) + * @brief Handles all Time Set IOCTLs + * @param cmd [IN] the IOCTL command + * @param buf [IN] the time value + * @retval int + * - 0 on success + * - -EINVAL on failure + *
+ */ +static int ioc_handle_time_set(unsigned long cmd, char *buf) +{ + struct ioh1588TimeValue time_value; + + (void)memcpy((void *)&time_value, (const void *)buf, + sizeof(struct ioh1588TimeValue)); + + if (IOCTL_1588_SYS_TIME_SET == cmd) { + IOH_DEBUG("ioc_handle_time_set cmd=IOCTL_1588_SYS_TIME_SET \ + invoking ioh_1588_system_time_set\n"); + if (ioh_1588_system_time_set(time_value) != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: ioh_1588_system_time_set \ + failed\n"); + return -EINVAL; + } + } else if (IOCTL_1588_TARG_TIME_SET == cmd) { + IOH_DEBUG("ioc_handle_time_set cmd=IOCTL_1588_TARG_TIME_SET \ + invoking ioh_1588_target_time_set\n"); + if (ioh_1588_target_time_set(time_value) != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: ioh_1588_target_time_set \ + failed\n"); + return -EINVAL; + } + } else { /* IOCTL_1588_AUX_TARG_TIME_SET */ + + IOH_DEBUG + ("ioc_handle_time_set cmd=IOCTL_1588_AUX_TARG_TIME_SET \ + invoking ioh_1588_aux_target_time_set\n"); + if (ioh_1588_aux_target_time_set(time_value) != + IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: ioh_1588_aux_target_time_set \ + failed\n"); + return -EINVAL; + } + } + return 0; +} + +/* Handles all Time Get IOCTLs */ +/*! @ingroup IEEE_1588_UtilitiesAPI + * @fn ioc_handle_time_get (unsigned long cmd, char *buf) + * @brief Handles all Time Get IOCTLs + * @param cmd [IN] the IOCTL command + * @param buf [OUT] the time value + * @retval int + * - 0 on success + * - -EINVAL on failure + *
+ */ +static int ioc_handle_time_get(unsigned long cmd, char *buf) +{ + struct ioh1588TimeValue time_value; + + if (IOCTL_1588_SYS_TIME_GET == cmd) { + IOH_DEBUG("ioc_handle_time_get cmd=IOCTL_1588_SYS_TIME_GET \ + invoking ioh_1588_system_time_get\n"); + if (ioh_1588_system_time_get(&time_value) != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: ioh_1588_system_time_get \ + failed\n"); + return -EINVAL; + } + } else if (IOCTL_1588_TARG_TIME_GET == cmd) { + IOH_DEBUG("ioc_handle_time_get cmd=IOCTL_1588_TARG_TIME_GET \ + invoking ioh_1588_target_time_get\n"); + if (ioh_1588_target_time_get(&time_value) != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: ioh_1588_target_time_get \ + failed\n"); + return -EINVAL; + } + } else { /* IOCTL_1588_AUX_TARG_TIME_GET */ + + IOH_DEBUG + ("ioc_handle_time_get cmd=IOCTL_1588_AUX_TARG_TIME_GET \ + invoking ioh_1588_aux_target_time_get\n"); + if (ioh_1588_aux_target_time_get(&time_value)) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: ioh_1588_aux_target_time_set \ + failed\n"); + return -EINVAL; + } + } + + (void)memcpy((void *)buf, (const void *)&time_value, + sizeof(struct ioh1588TimeValue)); + return 0; +} + +/* Handles tick rate get/set IOCTLs */ +/*! @ingroup IEEE_1588_UtilitiesAPI + * @fn ioc_handle_tick_rate (unsigned long cmd, char *buf) + * @brief Handles tick rate get/set IOCTLs + * @param cmd [IN] the IOCTL command + * @param buf [OUT] the tick rate + * @retval int + * - 0 on success + * - -EINVAL on failure + *
+ */ +static int ioc_handle_tick_rate(unsigned long cmd, char *buf) +{ + unsigned long val; + + if (IOCTL_1588_TICK_RATE_GET == cmd) { + IOH_DEBUG("ioc_handle_tick_rate cmd =IOCTL_1588_TICK_RATE_GET \ + invoking ioh_1588_tick_rate_get\n"); + if (ioh_1588_tick_rate_get(&val) != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: ioh_1588_tick_rate_get \ + failed\n"); + return -EINVAL; + } + + (void)memcpy((void *)buf, (const void *)&val, sizeof val); + } else { /* (cmd == IOCTL_1588_TICK_RATE_SET) */ + + IOH_DEBUG("ioc_handle_tick_rate cmd =IOCTL_1588_TICK_RATE_SET \ + invoking ioh_1588_tick_rate_set\n"); + (void)memcpy((void *)&val, (const void *)buf, sizeof val); + + if (ioh_1588_tick_rate_set(val) != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: ioh_1588_tick_rate_set \ + failed\n"); + return -EINVAL; + } + } + return 0; +} + +/* Handles pps time get/set IOCTLs */ +/*! @ingroup IEEE_1588_UtilitiesAPI + * @fn ioc_handle_pps_reqt (unsigned long cmd, char *buf) + * @brief Handles pps time get/set IOCTLs + * @param cmd [IN] the IOCTL command + * @param buf [INOUT] the pulse per second value + * @retval int + * - 0 on success + * - -EINVAL on failure + *
+ */ +static int ioc_handle_pps_reqt(unsigned long cmd, char *buf) +{ + unsigned long val; + + if (IOCTL_1588_PULSE_PER_SEC_TIME_SET == cmd) { + IOH_DEBUG + ("ioc_handle_pps_reqt cmd=\ + IOCTL_1588_PULSE_PER_SEC_TIME_SET \ + invoking ioh_1588_pulse_per_sec_time_set\n"); + (void)memcpy((void *)&val, (const void *)buf, sizeof val); + if (ioh_1588_pulse_per_sec_time_set(val) != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, "ioh_1588_ioctl: \ + ioh_1588_pulse_per_sec_time_set \ + failed\n"); + return -EINVAL; + } + } else { /* IOCTL_1588_PULSE_PER_SEC_TIME_GET */ + + IOH_DEBUG + ("ioc_handle_pps_reqt cmd=\ + IOCTL_1588_PULSE_PER_SEC_TIME_GET \ + invoking ioh_1588_pulse_per_sec_time_get\n"); + if (ioh_1588_pulse_per_sec_time_get(&val) != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, "ioh_1588_ioctl: \ + ioh_1588_pulse_per_sec_time_get failed\n"); + return -EINVAL; + } + (void)memcpy((void *)buf, (const void *)&val, sizeof val); + } + return 0; +} + +/* Handles ptp version get/set IOCTLs */ +/*! @ingroup IEEE_1588_UtilitiesAPI + * @fn ioc_handle_version_reqt (unsigned long cmd, char *buf) + * @brief Handles ptp version get/set IOCTLs + * @param cmd [IN] the IOCTL command + * @param buf [INOUT]the ptp version + * @retval int + * - 0 on success + * - -EINVAL on failure + *
+ */ +static int ioc_handle_version_reqt(unsigned long cmd, char *buf) +{ + struct ioh1588VersionIoctl *version_ioctl = \ + (struct ioh1588VersionIoctl *) buf; + + if (IOCTL_1588_PORT_VERSION_SET == cmd) { + IOH_DEBUG + ("ioc_handle_version_reqt cmd=IOCTL_1588_PORT_VERSION_SET \ + invoking ioh_1588_ptp_version_set\n"); + if (ioh_1588_ptp_version_set + (version_ioctl->ptpPort, + version_ioctl->ptpVersion) != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: ioh_1588_ptp_version_set \ + failed\n"); + return -EINVAL; + } + } else { /* IOCTL_1588_PORT_VERSION_GET */ + + IOH_DEBUG + ("ioc_handle_version_reqt cmd=IOCTL_1588_PORT_VERSION_GET \ + invoking ioh_1588_ptp_version_get\n"); + if (ioh_1588_ptp_version_get + (version_ioctl->ptpPort, + &version_ioctl->ptpVersion) != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: ioh_1588_ptp_version_get \ + failed\n"); + return -EINVAL; + } + } + return 0; +} + +/* Handles ptp operation mode get/set IOCTLs */ +/*! @ingroup IEEE_1588_UtilitiesAPI + * @fn ioc_handle_op_mode_reqt (unsigned long cmd, char *buf) + * @brief Handles ptp operation mode get/set IOCTLs + * @param cmd [IN] the IOCTL command + * @param buf [INOUT]the ptp operation mode + * @retval int + * - 0 on success + * - -EINVAL on failure + *
+ */ +static int ioc_handle_op_mode_reqt(unsigned long cmd, char *buf) +{ + struct ioh1588OperationModeIoctl *opmode_ioctl = + (struct ioh1588OperationModeIoctl *) buf; + + if (IOCTL_1588_PORT_OPERATION_MODE_SET == cmd) { + IOH_DEBUG + ("ioc_handle_op_mode_reqt cmd=\ + IOCTL_1588_PORT_OPERATION_MODE_SET \ + invoking ioh_1588_ptp_operation_mode_set\n"); + if (ioh_1588_ptp_operation_mode_set + (opmode_ioctl->ptpPort, + opmode_ioctl->ptpOpMode) != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: \ + ioh_1588_ptp_operation_mode_set failed\n"); + return -EINVAL; + } + } else { /* IOCTL_1588_PORT_OPERATION_MODE_GET */ + + IOH_DEBUG + ("ioc_handle_op_mode_reqt cmd=\ + IOCTL_1588_PORT_OPERATION_MODE_GET \ + invoking ioh_1588_ptp_operation_mode_get\n"); + if (ioh_1588_ptp_operation_mode_get + (opmode_ioctl->ptpPort, + &opmode_ioctl->ptpOpMode) != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_ioctl: \ + ioh_1588_ptp_operation_mode_get failed\n"); + return -EINVAL; + } + } + return 0; +} + +/*! @ingroup InterfaceLayerNotifyRoutines + * @fn irqreturn_t ioh_1588_isr(int irq, void *p_data) + * @brief This function is the driver interrupt service routine. + * + * @param irq [IN] interrupt number + * @param p_data caller data + * + * @retval irqreturn_t + * - IRQ_HANDLED => interrupt handled, + * - IRQ_NONE => this device did not interrupt + */ +irqreturn_t ioh_1588_isr(int irq, void *p_data) +{ + unsigned long pending = 0; + + (void)ioh_1588_interrupt_pending(&pending); + if (!pending) { + IOH_DEBUG("ioh_1588_isr: no pending interrupt\n"); + return IRQ_NONE; + } + + if (ioh_1588_handler() != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, "ioh_1588_isr: ioh_1588_handler failed\n"); + return IRQ_NONE; + } + + return IRQ_HANDLED; +} + +/*! @ingroup InterfaceLayerNotifyRoutines + * @fn void target_time_callback(struct ioh1588TimeValue tgt_time) + * @brief The callback function that is called from the HAL + * when the target time expired interrupt occurs + * + * @param tgt_time target time register timestamp + * + * @retval None + */ +void target_time_callback(struct ioh1588TimeValue tgt_time) +{ + /* + * copy the target time value to the global value to be read by the + * notify ioctl + */ + (void)memcpy((void *)&ioh_1588_target_time, (const void *)&tgt_time, + sizeof(struct ioh1588TimeValue)); + + ioh_1588_devp->event_flags[TARG_TIME_EVENT_NUM] = 1; + + IOH_DEBUG("target_time_callback: signalling the notify ioctl \ + that the target time has expired\n"); + /* signal the notify ioctl that the target time has expired */ + wake_up_interruptible(&ioh_1588_devp->notify_evt[TARG_TIME_EVENT_NUM]); +} + +/*! @ingroup InterfaceLayerNotifyRoutines + * @fn void auxiliary_time_callback(enum ioh1588AuxMode aux_mode, + * struct ioh1588TimeValue aux_time) + * @brief The callback function that is called from the HAL + * when an aux time interrupt has occurred + * + * @param aux_mode master, slave, or any + * @param aux_time aux time register timestamp + * + * @return None + */ +void auxiliary_time_callback(enum ioh1588AuxMode aux_mode, \ + struct ioh1588TimeValue aux_time) +{ + /* + * copy the aux time value and aux mode to the global value + * to be read by the notify ioctl + */ + + ioh_1588_aux_time.auxMode = aux_mode; + (void)memcpy((void *)&ioh_1588_aux_time.auxTime, + (const void *)&aux_time, \ + sizeof(struct ioh1588AuxTimeIoctl)); + + ioh_1588_devp->event_flags[AUX_TIME_EVENT_NUM] = 1; + + IOH_DEBUG("auxiliary_time_callback: signalling the notify ioctl \ + that the auxiliary time stamp has been set\n"); + + /* + * signal the notify ioctl that the aux timestamp has been set + */ + wake_up_interruptible(&ioh_1588_devp->notify_evt[AUX_TIME_EVENT_NUM]); +} + +/*! @ingroup InterfaceLayerNotifyRoutines + * @fn void pulse_per_sec_callback(unsigned long pps) + * @brief This is a callback function that will be called from the HAL + * when the pulse per second time has expired which generates an + * interrupt + * + * @param pps pulse per second register timestamp + * + * @retval None + */ +void pulse_per_sec_callback(unsigned long pps) +{ + ioh_1588_pps_time = pps; + + ioh_1588_devp->event_flags[PPS_EVENT_NUM] = 1; + + IOH_DEBUG("pulse_per_sec_callback: signalling the notify ioctl \ + that the pulse per second time has expired\n"); + /* signal the notify ioctl that the pulse per second time has expired */ + + wake_up_interruptible(&ioh_1588_devp->notify_evt[PPS_EVENT_NUM]); +} diff -urN linux-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_main.h topcliff-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_main.h --- linux-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_main.h 1970-01-01 09:00:00.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_main.h 2010-03-09 10:22:48.000000000 +0900 @@ -0,0 +1,702 @@ + /*! + * @file ioh_1588_main.h + * @brief + * This file contains the declarations of IEEE_1588_InterfaceLayer APIs + * @version 0.92 + * @section + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * History: + * modified to support Intel IOH GE IEEE 1588 hardware + * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. + * All rights reserved. + * derived from + * IEEE 1588 Time Synchronization Driver for Intel EP80579 + * Copyright(c) 2007,2008 Intel Corporation. All rights reserved. + * All rights reserved. + * + */ + +#ifndef IOH_1588_MAIN_H +#define IOH_1588_MAIN_H + +#ifdef __GNUC__ +#define UNUSED __attribute__ ((unused)) +#define UNUSED_ARG(x) +#else +#define UNUSED +#define UNUSED_ARG(x) (void) x +#endif + +#include + +#define TRUE 1 +#define FALSE 0 + +/*! @defgroup IEEE1588*/ + +/*! @defgroup IEEE_1588_Global + * @ingroup IEEE1588 + * @brief This group describes the global entities within + * the module. + * @remarks This group includes all the global data structures + * used within the modules. These are mainly used to + * store the device related information, so that it can + * be used by other functions of the modules. + *
+ * */ + +/*! @defgroup IEEE_1588_PCILayer + * @ingroup IEEE1588 + * @brief This group describes the PCI layer interface + * functionalities. + * @remarks This group contains the functions and data structures + * that are used to interface the module with PCI Layer + * subsystem of the Kernel. + *
+ * */ + +/*! @defgroup IEEE_1588_InterfaceLayer + * @ingroup IEEE1588 + * @brief This group describes the Driver interface functionalities. + * @remarks This group contains the data structures and functions used + * to interface the module driver with the kernel subsystem. + *
+ * */ + +/*! @defgroup IEEE_1588_HALLayer + * @ingroup IEEE1588 + * @brief This group describes the hardware specific functionalities. + * @remarks This group contains the functions and data structures used + * by the module to communicate with the hardware. These + * functions are device specific and designed according to the + * device specifications. + *
+ * */ + +/*! @defgroup IEEE_1588_Utilities + * @ingroup IEEE1588 + * @brief This group describes the utility functionalities. + * @remarks This group contains the functions and data structures used + * to assist the other functionalities in their operations. + *
+ **/ + +/*! @defgroup IEEE_1588_PCILayerAPI + * @ingroup IEEE_1588_PCILayer + * @brief This group contains the API(functions) used as the PCI + * interface between the Kernel subsystem and the module. + *
+ **/ + +/*! @defgroup IEEE_1588_PCILayerFacilitators + * @ingroup IEEE_1588_PCILayer + * @brief This group contains the data structures used by the PCI + * Layer APIs for their functionalities. + *
+ **/ + +/*! @defgroup IEEE_1588_InterfaceLayerAPI + * @ingroup IEEE_1588_InterfaceLayer + * @brief This group contains the API(functions) used as the Driver + * interface between the Kernel subsystem and the module. + *
+ **/ + +/*! @defgroup IEEE_1588_InterfaceLayerFacilitators + * @ingroup IEEE_1588_InterfaceLayer + * @brief This group contains the data structures used by the Driver + * interface APIs for their functionalities. + *
+ **/ + +/*! @defgroup IEEE_1588_HALLayerAPI + * @ingroup IEEE_1588_HALLayer + * @brief This group contains the APIs(functions) used to interact with + * the hardware. These APIs act as an interface between the + * hardware and the other driver functions. + *
+ **/ + +/*! @defgroup IEEE_1588_UtilitiesAPI + * @ingroup IEEE_1588_Utilities + * @brief This group contains the APIs(functions) used by other + * functions + * in their operations. + *
+ **/ + +/* 1588 module ioctl command codes */ + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOC_1588_BASE + * @brief The unique one byte data used to define + * the IOCTL commands + */ +#define IOC_1588_BASE 0x88 + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_PORT_CONFIG_SET + * @brief Set the IEEE 1588 Ethernet port to Mater/Slave/All mode + */ +#define IOCTL_1588_PORT_CONFIG_SET \ + _IOW(IOC_1588_BASE, 0, struct ioh1588PortCfgIoctl) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_PORT_CONFIG_GET + * @brief Get the IEEE 1588 Ethernet port Configuration mode + */ +#define IOCTL_1588_PORT_CONFIG_GET \ + _IOWR(IOC_1588_BASE, 1, struct ioh1588PortCfgIoctl) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_RX_POLL + * @brief Poll for receive timestamp captured on the IEEE 1588 ethernet + * channel + */ +#define IOCTL_1588_RX_POLL _IOWR(IOC_1588_BASE, 2, struct ioh1588RxTxPollIoctl) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_TX_POLL + * @brief Poll for transmit timestamp captured on the IEEE 1588 ethernet + * channel + */ +#define IOCTL_1588_TX_POLL _IOWR(IOC_1588_BASE, 3, struct ioh1588RxTxPollIoctl) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_CAN_POLL + * @brief Poll for timestamp captured on the IEEE 1588 CAN channel + */ +#define IOCTL_1588_CAN_POLL _IOWR(IOC_1588_BASE, 4, struct ioh1588CANPollIoctl) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_SYS_TIME_GET + * @brief Get the IEEE 1588 system time from the module + */ +#define IOCTL_1588_SYS_TIME_GET _IOR(IOC_1588_BASE, 5, struct ioh1588TimeValue) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_SYS_TIME_SET + * @brief Set the IEEE 1588 system time on the module + */ +#define IOCTL_1588_SYS_TIME_SET _IOW(IOC_1588_BASE, 6, struct ioh1588TimeValue) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_TICK_RATE_SET + * @brief Set the frequency scaling value used on IEEE 1588 module + */ +#define IOCTL_1588_TICK_RATE_SET _IOW(IOC_1588_BASE, 7, unsigned long) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_TICK_RATE_GET + * @brief Get the frequency scaling value used on IEEE 1588 module + */ +#define IOCTL_1588_TICK_RATE_GET _IOR(IOC_1588_BASE, 8, unsigned long) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_TARG_TIME_INTRPT_ENABLE + * @brief Enable the target time reached/exceeded interrupt on IEEE 1588 module + */ +#define IOCTL_1588_TARG_TIME_INTRPT_ENABLE _IO(IOC_1588_BASE, 9) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_TARG_TIME_INTRPT_DISABLE + * @brief Disable the target time reached/exceeded interrupt on IEEE 1588 module + */ +#define IOCTL_1588_TARG_TIME_INTRPT_DISABLE _IO(IOC_1588_BASE, 10) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_TARG_TIME_POLL + * @brief Poll for the target time reached/exceeded condition on IEEE 1588 + * module + */ +#define IOCTL_1588_TARG_TIME_POLL \ + _IOR(IOC_1588_BASE, 11, struct ioh1588TimePollIoctl) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_TARG_TIME_SET + * @brief Set the target time to match on IEEE 1588 module + */ +#define IOCTL_1588_TARG_TIME_SET \ + _IOW(IOC_1588_BASE, 12, struct ioh1588TimeValue) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_TARG_TIME_GET + * @brief Get the target time currently set on IEEE 1588 module + */ +#define IOCTL_1588_TARG_TIME_GET \ + _IOR(IOC_1588_BASE, 13, struct ioh1588TimeValue) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_AUX_TIME_INTRPT_ENABLE + * @brief Enable the auxiliary time captured interrupt on IEEE 1588 module + */ +#define IOCTL_1588_AUX_TIME_INTRPT_ENABLE \ + _IOW(IOC_1588_BASE, 14, enum ioh1588AuxMode) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_AUX_TIME_INTRPT_DISABLE + * @brief Disable the auxiliary time captured interrupt on IEEE 1588 module + */ +#define IOCTL_1588_AUX_TIME_INTRPT_DISABLE \ + _IOW(IOC_1588_BASE, 15, enum ioh1588AuxMode) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_AUX_TIME_POLL + * @brief Poll for the auxiliary time captured on IEEE 1588 module + */ +#define IOCTL_1588_AUX_TIME_POLL \ + _IOWR(IOC_1588_BASE, 16, struct ioh1588TimePollIoctl) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_RESET + * @brief Reset the IEEE 1588 module + */ +#define IOCTL_1588_RESET _IO(IOC_1588_BASE, 17) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_CHNL_RESET + * @brief Reset the IEEE 1588 channel + */ +#define IOCTL_1588_CHNL_RESET _IOW(IOC_1588_BASE, 18, enum ioh1588PTPPort) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_STATS_GET + * @brief Get the timestamp captured counters from the IEEE 1588 module + */ +#define IOCTL_1588_STATS_GET _IOR(IOC_1588_BASE, 19, struct ioh1588Stats) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_STATS_RESET + * @brief Reset the timestamp captured counters maintained for IEEE 1588 module + */ +#define IOCTL_1588_STATS_RESET _IO(IOC_1588_BASE, 20) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_SHOW_ALL + * @brief Display the register contents of IEEE 1588 module + */ +#define IOCTL_1588_SHOW_ALL _IO(IOC_1588_BASE, 21) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_AUX_TARG_TIME_INTRPT_ENABLE + * @brief Enable Auxiliary target time reached interrupt - not supported + */ +#define IOCTL_1588_AUX_TARG_TIME_INTRPT_ENABLE _IO(IOC_1588_BASE, 22) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_AUX_TARG_TIME_INTRPT_DISABLE + * @brief Disable Auxiliary target time reached interrupt - not supported + */ +#define IOCTL_1588_AUX_TARG_TIME_INTRPT_DISABLE _IO(IOC_1588_BASE, 23) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_AUX_TARG_TIME_POLL + * @brief Poll for Auxiliary target time captured - not supported + */ +#define IOCTL_1588_AUX_TARG_TIME_POLL \ + _IOR(IOC_1588_BASE, 24, struct ioh1588TimePollIoctl) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_AUX_TARG_TIME_SET + * @brief Set Auxiliary target time - not supported + */ +#define IOCTL_1588_AUX_TARG_TIME_SET \ + _IOW(IOC_1588_BASE, 25, struct ioh1588TimeValue) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_AUX_TARG_TIME_GET + * @brief Get Auxiliary target time currently set - not supported + */ +#define IOCTL_1588_AUX_TARG_TIME_GET \ + _IOR(IOC_1588_BASE, 26, struct ioh1588TimeValue) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_PULSE_PER_SEC_INTRPT_ENABLE + * @brief Enable Pulse per second match interrupt + */ +#define IOCTL_1588_PULSE_PER_SEC_INTRPT_ENABLE _IO(IOC_1588_BASE, 27) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_PULSE_PER_SEC_INTRPT_DISABLE + * @brief Disable Pulse per second match interrupt + */ +#define IOCTL_1588_PULSE_PER_SEC_INTRPT_DISABLE _IO(IOC_1588_BASE, 28) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_TARG_TIME_NOTIFY + * @brief Block till a target time reached interrupt occurs + */ +#define IOCTL_1588_TARG_TIME_NOTIFY \ + _IOR(IOC_1588_BASE, 29, struct ioh1588TimeValue) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_AUX_TIME_NOTIFY + * @brief Block till an auxiliary time captured interrupt occurs + */ +#define IOCTL_1588_AUX_TIME_NOTIFY \ + _IOR(IOC_1588_BASE, 30, struct ioh1588AuxTimeIoctl) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_AUX_TARG_TIME_NOTIFY + * @brief Block till an auxiliary target time reached interrupt occurs - not + * supported + */ +#define IOCTL_1588_AUX_TARG_TIME_NOTIFY \ + _IOR(IOC_1588_BASE, 31, struct ioh1588TimeValue) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_PULSE_PER_SEC_NOTIFY + * @brief Block till a pulse per second match interrupt occurs + */ +#define IOCTL_1588_PULSE_PER_SEC_NOTIFY _IOR(IOC_1588_BASE, 32, unsigned long) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_TARG_TIME_CLR_NOTIFY + * @brief Unblock a process waiting on target time reached interrupt + */ +#define IOCTL_1588_TARG_TIME_CLR_NOTIFY _IO(IOC_1588_BASE, 33) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_AUX_TIME_CLR_NOTIFY + * @brief Unblock a process waiting on auxiliary time captured interrupt + */ +#define IOCTL_1588_AUX_TIME_CLR_NOTIFY _IO(IOC_1588_BASE, 34) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_AUX_TARG_TIME_CLR_NOTIFY + * @brief Unblock a process waiting on an auxiliary target time reached + * interrupt - not supported + */ +#define IOCTL_1588_AUX_TARG_TIME_CLR_NOTIFY _IO(IOC_1588_BASE, 35) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_PULSE_PER_SEC_CLR_NOTIFY + * @brief Unblock a process waiting on a pulse per second match interrupt + */ +#define IOCTL_1588_PULSE_PER_SEC_CLR_NOTIFY _IO(IOC_1588_BASE, 36) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_PULSE_PER_SEC_TIME_GET + * @brief Get the currently specified pulse per second match time + */ +#define IOCTL_1588_PULSE_PER_SEC_TIME_GET _IOR(IOC_1588_BASE, 37, unsigned long) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_PULSE_PER_SEC_TIME_SET + * @brief Specify the pulse per second match time + */ +#define IOCTL_1588_PULSE_PER_SEC_TIME_SET _IOW(IOC_1588_BASE, 38, unsigned long) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_PORT_VERSION_SET + * @brief Set the PTP version to be used on the given PTP channel + */ +#define IOCTL_1588_PORT_VERSION_SET \ + _IOW(IOC_1588_BASE, 39, struct ioh1588VersionIoctl) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_PORT_VERSION_GET + * @brief Get the PTP version used on the given PTP channel + */ +#define IOCTL_1588_PORT_VERSION_GET \ + _IOWR(IOC_1588_BASE, 40, struct ioh1588VersionIoctl) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_PORT_OPERATION_MODE_SET + * @brief Set the PTP messages that are matched by the module on the given PTP + * channel + */ +#define IOCTL_1588_PORT_OPERATION_MODE_SET \ + _IOW(IOC_1588_BASE, 41, struct ioh1588OperationModeIoctl) + +/*! @ingroup IEEE_1588_InterfaceLayer + * @def IOCTL_1588_PORT_OPERATION_MODE_GET + * @brief Get the PTP messages that are currently matched by the module on given + * PTP channel + */ +#define IOCTL_1588_PORT_OPERATION_MODE_GET \ + _IOWR(IOC_1588_BASE, 42, struct ioh1588OperationModeIoctl) + +/** + * @ingroup IEEE_1588_InterfaceLayer + * @enum ioh1588PTPPort + * @brief IEEE 1588 PTP Communication Port(Channel) + */ +enum ioh1588PTPPort { /* ioh1588PTPPort */ + IOH_1588_GBE_0_1588PTP_PORT, /**< PTP Communication Port on GBE-0 */ + IOH_1588_CAN_0_1588PTP_PORT, /**< PTP Communication Port on CAN-0 */ + IOH_1588_PORT_INVALID /**< Invalid PTP Communication Port */ +}; + +/** + * @ingroup IEEE_1588_InterfaceLayer + * @enum ioh1588PTPPortMode + * @brief PTP Port mode - Master or Slave or any + */ +enum ioh1588PTPPortMode { /* ioh1588PTPPortMode */ + IOH_1588PTP_PORT_MASTER, /**< Master Mode */ + IOH_1588PTP_PORT_SLAVE, /**< Slave Mode */ + IOH_1588PTP_PORT_ANYMODE, /**< Timestamp all messages */ + IOH_1588PTP_PORT_MODE_INVALID /**< Invalid PTP Port Mode */ +}; + +/** + * @ingroup IEEE_1588_InterfaceLayer + * @struct ioh1588PortCfgIoctl + * @brief Struct to pass port config data for ioctl call + */ +struct ioh1588PortCfgIoctl { /* ioh1588PortCfgIoctl */ + enum ioh1588PTPPort ptpPort; /**< IEEE 1588 PTP Communication Port */ + enum ioh1588PTPPortMode ptpPortMode; /**< Master, Slave, + or Any mode */ +}; + +/** + * @ingroup IEEE_1588_InterfaceLayer + * @enum ioh1588PTPMsgType + * @brief PTP Messages types that can be detected on communication port + */ +enum ioh1588PTPMsgType { /* ioh1588PTPMsgType */ + IOH_1588PTP_MSGTYPE_SYNC, /**< PTP Sync message sent by Master or + received by Slave */ + IOH_1588PTP_MSGTYPE_DELAYREQ, /**< PTP Delay_Req message sent by Slave + or received by Master */ + IOH_1588PTP_MSGTYPE_UNKNOWN /**< Other PTP and non-PTP message sent + or received by both Master + and/or Slave */ +}; + +/** + * @ingroup IEEE_1588_InterfaceLayer + * @struct ioh1588TimeValue + * @brief Struct to hold 64 bit SystemTime and TimeStamp values + */ +struct ioh1588TimeValue { /* ioh1588TimeValue */ + unsigned long timeValueLowWord; /**< Lower 32 bits of time value */ + unsigned long timeValueHighWord; /**< Upper 32 bits of time value */ +}; + +/** + * @ingroup IEEE_1588_InterfaceLayer + * @struct ioh1588Uuid + * @brief Struct to hold 48 bit UUID values captured in Sync or Delay_Req + * messages + */ +struct ioh1588Uuid{ /* ioh1588Uuid */ + unsigned long uuidValueLowWord; /**< The lower 32 bits of UUID */ + unsigned long uuidValueHighHalfword; /**< The upper 16 bits of UUID */ +}; + +/** + * @ingroup IEEE_1588_InterfaceLayer + * @struct ioh1588PtpMsgData + * @brief Struct for data from the PTP message returned when TimeStamp + * available + */ +struct ioh1588PtpMsgData{ /* ioh1588PtpMsgData */ + enum ioh1588PTPMsgType ptpMsgType; /**< PTP Messages type */ + struct ioh1588TimeValue ptpTimeStamp; /**< 64 bit TimeStamp value from + PTP Message */ + struct ioh1588Uuid ptpUuid; /**< 48 bit UUID value from the + PTP Message */ + unsigned int ptpSequenceNumber; /**< 16 bit Sequence Number from PTP + Message */ +}; + +/** + * @ingroup IEEE_1588_InterfaceLayer + * @struct ioh1588RxTxPollIoctl + * @brief Struct to pass PTP message data for ioctl call + */ +struct ioh1588RxTxPollIoctl{ /* ioh1588RxTxPollIoctl */ + enum ioh1588PTPPort ptpPort; /**< IEEE 1588 PTP Communication Port */ + struct ioh1588PtpMsgData ptpMsgData; /**< PTP message data */ +}; + +/** + * @ingroup IEEE_1588_InterfaceLayer + * @struct ioh1588CANPollIoctl + * @brief Struct to pass CAN timestamp data for ioctl call + */ +struct ioh1588CANPollIoctl{ /* ioh1588CANPollIoctl */ + enum ioh1588PTPPort ptpPort; /**< IEEE 1588 PTP Communication + Port */ + struct ioh1588TimeValue ptpTimeStamp; /**< CAN PTP timestamp */ +}; + +/** + * @ingroup IEEE_1588_InterfaceLayer + * @enum ioh1588AuxMode + * @brief Master or Slave Auxiliary Time Stamp (Snap Shot) + */ +enum ioh1588AuxMode{ /* ioh1588AuxMode */ + IOH_1588_AUXMODE_MASTER, /**< Auxiliary Master Mode */ + IOH_1588_AUXMODE_SLAVE, /**< Auxiliary Slave Mode */ + IOH_1588_AUXMODE_INVALID /**< Invalid Auxiliary Mode */ +}; + +/** + * @ingroup IEEE_1588_InterfaceLayer + * @struct ioh1588TimePollIoctl + * @brief Struct to pass timestamp data for ioctl call + */ +struct ioh1588TimePollIoctl { /* ioh1588TimePollIoctl */ + unsigned long pollFlag; /**< time event */ + struct ioh1588TimeValue timeVal; /**< timestamp value */ + enum ioh1588AuxMode auxMode; /**< Master or Slave mode */ +}; + +/** + * @ingroup IEEE_1588_InterfaceLayer + * @struct ioh1588Stats + * @brief Provides the number of times timestamps are locked for rx and tx + * PTP + * messages. The counters are reinitialized when the module is + * reset. + */ +struct ioh1588Stats { /* ioh1588Stats */ + unsigned long rxMsgs; /**< Count of timestamps for received PTP Msgs */ + unsigned long txMsgs; /**< Count of timestamps for transmitted PTP + Msgs */ +}; + +/** + * @ingroup IEEE_1588_InterfaceLayer + * @struct ioh1588AuxTimeIoctl + * @brief Struct to pass aux time data for ioctl call + */ +struct ioh1588AuxTimeIoctl { /* ioh1588AuxTimeIoctl */ + enum ioh1588AuxMode auxMode; /**< aux mode: master or slave */ + struct ioh1588TimeValue auxTime; /**< aux time snapshot */ +}; + +/** + * @ingroup IEEE_1588_InterfaceLayer + * @enum ioh1588PTPVersion + * @brief 1588 PTP version value that can be detected on communication + * port + */ +enum ioh1588PTPVersion { /* ioh1588PTPVersion */ + IOH_1588PTP_VERSION_0, /**< support version 1 only */ + IOH_1588PTP_VERSION_1, /**< support both version 1 and version + 2 */ + IOH_1588PTP_VERSION_INVALID /**< Invalid version */ +}; + +/** + * @ingroup IEEE_1588_InterfaceLayer + * @struct ioh1588VersionIoctl + * @brief Struct to pass timestamp data for ioctl call + */ +struct ioh1588VersionIoctl { /* ioh1588VersionIoctl */ + enum ioh1588PTPPort ptpPort; /**< IEEE 1588 PTP Communication Port */ + enum ioh1588PTPVersion ptpVersion; /**< version value */ +}; + +/** + * @ingroup IEEE_1588_InterfaceLayer + * @enum ioh1588VersionIoctl + * @brief 1588 PTP operation mode value that can be detected on + * communication port + */ +enum ioh1588PTPOperationMode { /* ioh1588PTPOperationMode */ + IOH_1588PTP_OP_MODE_SYNC_DELAYREQ_MSGS, + /**< timestamp version 1 SYNC and DELAYED_REQ only */ + IOH_1588PTP_OP_MODE_V1_ALL_MSGS, + /**< timestamp version 1 all messages */ + IOH_1588PTP_OP_MODE_V1_V2_EVENT_MSGS, + /**< timestamp version 1 and 2 event messages only */ + IOH_1588PTP_OP_MODE_V1_V2_ALL_MSGS, + /**< timestamp version 1 and 2 all messages */ + IOH_1588PTP_OP_MODE_INVALID /**< Invalid mode */ +}; + +/** + * @ingroup IEEE_1588_InterfaceLayer + * @struct ioh1588OperationModeIoctl + * @brief Struct to pass timestamp data for ioctl call + */ +struct ioh1588OperationModeIoctl { /* ioh1588OperationModeIoctl */ + enum ioh1588PTPPort ptpPort; /**< IEEE 1588 PTP Communication + Port */ + enum ioh1588PTPOperationMode ptpOpMode; /**< IEEE 1588 operation mode */ +}; + +/** + * @ingroup IEEE_1588_Global + * @enum ioh_status + * @brief The status as returned from the HAL + */ +enum ioh_status { /* ioh_status */ + IOH_1588_SUCCESS, /**< operation successful */ + IOH_1588_INVALIDPARAM, /**< parameter passed is invalid */ + IOH_1588_NOTIMESTAMP, /**< no time stamp available when + polled */ + IOH_1588_INTERRUPTMODEINUSE, /**< while operating in interrupt mode, + polling not permitted */ + IOH_1588_FAILED, /**< Internal error in driver */ + IOH_1588_UNSUPPORTED, /**< Implementation does not support + this feature */ +}; + +/* IEEE 1588 registers to save and restore on suspend/resume */ + +/** @ingroup IEEE_1588_Global + * @struct ioh_1588_regs_set + * @brief IEEE 1588 registers to save and restore on suspend/resume + */ +struct ioh_1588_regs_set { + unsigned long ts_control; + unsigned long ts_event; /* not saved, cleared on restore */ + unsigned long ts_addend; + unsigned long ts_accum; /* not saved/restored */ + unsigned long ts_test; /* not saved/restored */ + unsigned long ts_compare; + unsigned long ts_syslo; + unsigned long ts_syshi; + unsigned long ts_tgtlo; + unsigned long ts_tgthi; + unsigned long ts_asmslo; /* not saved/restored */ + unsigned long ts_asmshi; /* not saved/restored */ + unsigned long ts_ammslo; /* not saved/restored */ + unsigned long ts_ammshi; /* not saved/restored */ + + /* Ethernet */ + unsigned long ts_cc; + unsigned long ts_ce; /* not saved, cleared on restore */ + unsigned long ts_xslo; /* not saved/restored */ + unsigned long ts_xshi; /* not saved/restored */ + unsigned long ts_rslo; /* not saved/restored */ + unsigned long ts_rshi; /* not saved/restored */ + unsigned long ts_uuidlo; /* not saved/restored */ + unsigned long ts_uuidhi; /* not saved/restored */ + + /* CAN */ + unsigned long ts_cce; /* not saved, cleared on restore */ + unsigned long ts_cxslo; /* not saved/restored */ + unsigned long ts_cxshi; /* not saved/restored */ + + unsigned long ts_sel; /* Selector */ + unsigned char ts_sti[6]; /* station addresses */ +}; + +/* callback function prototypes */ +extern void target_time_callback(struct ioh1588TimeValue targetTime); +extern void auxiliary_time_callback(enum ioh1588AuxMode aux_mode, \ + struct ioh1588TimeValue auxTime); +extern void pulse_per_sec_callback(unsigned long pps); +#endif /* IOH_1588_H */ diff -urN linux-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_pci.c topcliff-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_pci.c --- linux-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_pci.c 1970-01-01 09:00:00.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_pci.c 2010-03-09 10:32:42.000000000 +0900 @@ -0,0 +1,700 @@ + /*! + * @file ioh_1588_pci.c + * @brief + * This file contains the definitions of IEEE_1588_PCILayer APIs + * @version 0.92 + * @section + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * History: + * modified to support Intel IOH GE IEEE 1588 hardware + * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. + * All rights reserved. + * derived from + * IEEE 1588 Time Synchronization Driver for Intels EP80579 + * Copyright(c) 2007,2008 Intel Corporation. All rights reserved. + * All rights reserved. + * + */ + +#include "pch_1588_pci.h" +#include "pch_1588_hal.h" +#include "pch_debug.h" + +#ifdef CONFIG_PM +static int ioh_1588_suspend(struct pci_dev *pdev, pm_message_t state); +static int ioh_1588_resume(struct pci_dev *pdev); +#endif +static int ioh_1588_probe(struct pci_dev *pdev, const struct pci_device_id *id); +static void ioh_1588_remove(struct pci_dev *pdev); + +/*! @ingroup IEEE_1588_PCILayerFacilitators + * @struct ioh_1588_pcidev_id + * @brief PCI device ids supported by this driver + * @remarks This structure is used to specify the Ids of the + * devices supported by the driver module during + * registering of the module as PCI driver.The values + * within the structure is maintained by the kernel + * subsystem to recognize the individual devices + * when they are attached to the system. Depending + * on this the corresponding device functionalities + * such as probe, remove, suspend,... are invoked. + * + * @note This structure contains the Vendor and device + * IDs of the device supported by the driver module. + * + * @see + * - ioh_1588_pcidev + *
+ */ +static const struct pci_device_id ioh_1588_pcidev_id[] = { + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_IOH_1588)}, + {0}, +}; + +/* Linux pci operations */ +/*! @ingroup IEEE_1588_PCILayerFacilitators +* @struct ioh_1588_pcidev +* @brief Store the references of PCI driver interfaces to kernel. +* @remarks This strutcure is used to specify the driver specific +* functionalities to the kernel subsystem. The kernel invokes +* these functionalities depending on the supported device and +* the events that occured. +* +* @note This structure is registered with the kernel via the call +* pci_register_driver from @ref ioh_1588_init +* @see +* - ioh_1588_init +* - ioh_1588_exit +*
+*/ + +static struct pci_driver ioh_1588_pcidev = { + .name = DRIVER_NAME, + .id_table = ioh_1588_pcidev_id, + .probe = ioh_1588_probe, + .remove = ioh_1588_remove, +#ifdef CONFIG_PM + .suspend = ioh_1588_suspend, + .resume = ioh_1588_resume, +#endif +}; + +/* instance of driver data structure */ +/*! @ingroup IEEE_1588_PCILayerFacilitators + * @var ioh_1588_dev + * @brief instance of driver data structure + * @see + * - ioh_1588_probe + * - ioh_1588_init + * - ioh_1588_remove + * - ioh_1588_suspend + * - ioh_1588_resume + *
+ */ +static struct ioh_1588_dev ioh_1588_dev; + +/*! @ingroup IEEE_1588_Global + * @var ioh_1588_devp + * @brief Pointer to driver data structure + * @see + * - ioc_handle_notify + * - ioc_handle_clr_notify + * - ioc_handle_reset + * - target_time_callback + * - auxiliary_time_callback + * - pulse_per_sec_callback + * - ioh_1588_open + *
+ */ + +struct ioh_1588_dev *ioh_1588_devp = &ioh_1588_dev; + +/*! @ingroup IEEE_1588_PCILayerFacilitators + * @struct ioh_1588_params_ + * @brief structure to hold the module parameters + * @see + * - ioh_1588_init + * - ioh_1588_probe + *
+ */ +static struct ioh_1588_params_ { + /* module parameters */ + int eth_enable; /**< IEEE 1588 on ethernet interface + 0=Disabled 1=Enabled (default 1)*/ + int can_enable; /**< IEEE 1588 on CAN interface + 0=Disabled 1=Enabled (default 0)*/ + int major; /**< IEEE 1588 device major number to + use (default system assigned)*/ + unsigned char station[STATION_ADDR_LEN]; /**< IEEE 1588 station address + to use - column separated hex values*/ +} ioh_1588_param = { +1, 0, 0, "00:00:00:00:00:00"}; + +module_param_named(eth_enable, ioh_1588_param.eth_enable, bool, 0444); +MODULE_PARM_DESC(eth_enable, + "IEEE 1588 on ethernet interface 0=Disabled 1=Enabled \ + (default 1)"); + +module_param_named(can_enable, ioh_1588_param.can_enable, bool, 0444); +MODULE_PARM_DESC(can_enable, + "IEEE 1588 on CAN interface 0=Disabled 1=Enabled (default 0)"); + +module_param_named(major, ioh_1588_param.major, int, 0444); +MODULE_PARM_DESC(major, + "IEEE 1588 device major number to use (default system \ + assigned)"); + +module_param_string(station, ioh_1588_param.station, + sizeof ioh_1588_param.station, 0444); +MODULE_PARM_DESC(station, + "IEEE 1588 station address to use - column separated hex \ + values"); + +/*!@ingroup IEEE_1588_PCILayerAPI + * @fn int ioh_1588_probe(struct pci_dev *pdev,const struct pci_device_id *id) + * @brief + * This function is called right after insmod by the PCI core. Here we enable + * the + * device to make the device's resources live. We can then read PCI CFG space + * and init the device. + * + * @remarks + * The main tasks performed by this method are: + * - Allocate PCI resource required using + * request_mem_region API + * and map the memory to kernel virtual space using + * ioremap API. + * - Enable the PCI device using pci_enable_device + * API. + * - Initialize global variables and wait queues + * using + * init_waitqueue_head API + * - Set the memory address to be used by the HAL + * using ioh_1588_blpl_base_address_set API + * - Register the interrupt handler using request_irq + * API + * - Register the charecter driver using + * sregister_chrdev_region/ + * alloc_chrdev_region APIs based on whether major + * number has been + * provided by the user or not. + * - Add the device to the system using the APIs + * cdev_init and + * cdev_add. + * - If any of the above calls fail, undo the steps + * performed before the failure and return + * appropraite error + * status. + * - Depending on the parameters passed during module + * load, + * enable/disable PTP clock synchronization control + * on GbE + * (using ioh_1588_eth_enable/ioh_1588_eth_disable + * API). /CAN + * (using ioh_1588_can_enable/ioh_1588_can_disable + * API) channel. + * - Set the Station address as specified in the + * module + * parameter using ioh_1588_set_station_address + * API + * -Note: For A0/A1 sample, test mode setting is enabled for + * the 64 bit System Time Register. This is a work around + * for + * the non continuous value in the 64 bit System Time + * Register + * consisting of High(32bit) / Low(32bit) + * + * + * @param pdev [INOUT] pci device structure + * @param id [IN] list of devices supported by this driver + * + * @return int + * - 0 Success + * - -ENODEV request_mem_region or ioremap or + * pci_enable_device or request_irq error + * + * @see + * - ioh_1588_pcidev + *
+ */ + +static int __devinit +ioh_1588_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + int ret = 0; + dev_t devno; + int i; + + UNUSED_ARG(id); + + /* enable the 1588 pci device */ + ret = pci_enable_device(pdev); + if (ret != 0) { + IOH_LOG(KERN_ERR, + "ioh_1588_probe:could not enable the pci device\n"); + goto exit_error; + } + IOH_DEBUG("ioh_1588_probe:pci_enable_device success\n"); + + ioh_1588_dev.mem_base = pci_resource_start(pdev, IO_MEM_BAR); + + if (!ioh_1588_dev.mem_base) { + IOH_LOG(KERN_ERR, + "ioh_1588_probe: could not locate IO memory address\n"); + /*disable the pci device */ + pci_disable_device(pdev); + ret = -ENODEV; + goto exit_error; + } + IOH_DEBUG("ioh_1588_probe:allocated IO memory address\n"); + + /* retreive the available length of the IO memory space */ + ioh_1588_dev.mem_size = pci_resource_len(pdev, IO_MEM_BAR); + + /* allocate the memory for the device registers */ + if (!request_mem_region + (ioh_1588_dev.mem_base, ioh_1588_dev.mem_size, "1588_regs")) { + IOH_LOG(KERN_ERR, + "ioh_1588_probe: could not allocate register memory \ + space\n"); + ioh_1588_dev.mem_base = 0; + /*disable the pci device */ + pci_disable_device(pdev); + ret = -EBUSY; + goto exit_error; + } + IOH_DEBUG("ioh_1588_probe:allocated register memory space\n"); + + /* get the virtual address to the 1588 registers */ + ioh_1588_dev.mem_virt = + ioremap(ioh_1588_dev.mem_base, ioh_1588_dev.mem_size); + + if (!ioh_1588_dev.mem_virt) { + pci_disable_device(pdev); + IOH_LOG(KERN_ERR, + "ioh_1588_probe: Could not get virtual address\n"); + /*release memory acquired for device registers */ + release_mem_region(ioh_1588_dev.mem_base, + ioh_1588_dev.mem_size); + ioh_1588_dev.mem_base = 0; + /*disable the pci device */ + pci_disable_device(pdev); + ret = -ENOMEM; + goto exit_error; + } + IOH_DEBUG("ioh_1588_probe:obtained virtual address=%p\n", + ioh_1588_dev.mem_virt); + + for (i = 0; i < NUM_EVENTS; i++) { + init_waitqueue_head(&ioh_1588_dev.notify_evt[i]); + ioh_1588_dev.event_flags[i] = 0; + } + IOH_DEBUG("ioh_1588_probe:initialized wait queue heads\n"); + + ret = + ioh_1588_blpl_base_address_set((unsigned int)ioh_1588_dev.mem_virt); + if (ret != IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_probe: ioh_1588_blpl_base_address_set \ + failed\n"); + /*unmap io */ + iounmap(ioh_1588_dev.mem_virt); + ioh_1588_dev.mem_virt = 0; + /*release memory acquired for device */ + release_mem_region(ioh_1588_dev.mem_base, + ioh_1588_dev.mem_size); + ioh_1588_dev.mem_base = 0; + /*disable device */ + pci_disable_device(pdev); + goto exit_error; + } + IOH_DEBUG("ioh_1588_probe:set base address\n"); + + ret = request_irq(pdev->irq, &ioh_1588_isr, IRQF_SHARED, DRIVER_NAME, + &ioh_1588_dev); + if (ret != 0) { + IOH_LOG(KERN_ERR, "ioh_1588_probe: failed to get irq %d\n", + pdev->irq); + /*unmap io */ + iounmap(ioh_1588_dev.mem_virt); + ioh_1588_dev.mem_virt = 0; + /*release memory acquired for device */ + release_mem_region(ioh_1588_dev.mem_base, + ioh_1588_dev.mem_size); + ioh_1588_dev.mem_base = 0; + /*disable device */ + pci_disable_device(pdev); + goto exit_error; + } + IOH_DEBUG("ioh_1588_probe:registered IRQ handler successfully\n"); + + /*register the module */ + if (ioh_1588_param.major != 0) { /* user specified a major + number, use it */ + IOH_DEBUG("ioh_1588_probe:using user specified major number\n"); + devno = MKDEV(ioh_1588_param.major, 0); + ret = register_chrdev_region(devno, 1, DRIVER_NAME); + ioh_1588_dev.devno = devno; /* store it */ + } else { /* request and reserve a device number */ + + IOH_DEBUG + ("ioh_1588_probe:dynamically allocating major number\n"); + ret = + alloc_chrdev_region(&ioh_1588_dev.devno, 0, 1, DRIVER_NAME); + devno = MKDEV(MAJOR(ioh_1588_dev.devno), 0); + } + if (ret < 0) { + IOH_LOG(KERN_ERR, + "ioh_1588_probe: Could not register module (major %d)\ + \n", + ioh_1588_param.major); + /*free irq */ + free_irq(pdev->irq, &ioh_1588_dev); + /*unmap io */ + iounmap(ioh_1588_dev.mem_virt); + ioh_1588_dev.mem_virt = 0; + /*release memory acquired for device */ + release_mem_region(ioh_1588_dev.mem_base, + ioh_1588_dev.mem_size); + ioh_1588_dev.mem_base = 0; + /*disable device */ + pci_disable_device(pdev); + goto exit_error; + } + IOH_DEBUG("ioh_1588_probe:registered the module(major %d)\n", + ioh_1588_param.major); + + /* init cdev struct for adding device to kernel */ + cdev_init(&ioh_1588_dev.cdev, &ioh_1588_fops); + ioh_1588_dev.cdev.owner = THIS_MODULE; + ioh_1588_dev.cdev.ops = &ioh_1588_fops; + + ret = cdev_add(&ioh_1588_dev.cdev, devno, 1); + if (ret != 0) { + IOH_LOG(KERN_ERR, "ioh_1588_probe: cdev_add failed\n"); + /*free region allocated for char device */ + unregister_chrdev_region(ioh_1588_dev.devno, 1); + /*free irq */ + free_irq(pdev->irq, &ioh_1588_dev); + /*unmap io */ + iounmap(ioh_1588_dev.mem_virt); + ioh_1588_dev.mem_virt = 0; + /*release memory acquired for device */ + release_mem_region(ioh_1588_dev.mem_base, + ioh_1588_dev.mem_size); + ioh_1588_dev.mem_base = 0; + /*disable device */ + pci_disable_device(pdev); + goto exit_error; + } + IOH_DEBUG("ioh_1588_probe: cdev_add successful\n"); + + ioh_1588_dev.initialized = 1; + /* indicate success */ + ioh_1588_dev.irq = pdev->irq; + + /*reset the ieee1588 h/w */ + ioh_1588_reset(); + + if (ioh_1588_param.eth_enable != 0) { /* Enable by default */ + IOH_DEBUG("ioh_1588_probe: invoking ioh_1588_eth_enable \ + to enable ethernet\n"); + (void)ioh_1588_eth_enable(); + } else { + IOH_DEBUG("ioh_1588_probe: invoking ioh_1588_eth_disable \ + to disable ethernet\n"); + (void)ioh_1588_eth_disable(); + } + if (ioh_1588_param.can_enable == 1) { /* Enable if requested */ + IOH_DEBUG("ioh_1588_probe: invoking ioh_1588_can_enable \ + to enable CAN\n"); + (void)ioh_1588_can_enable(); + } else { + IOH_DEBUG("ioh_1588_probe: invoking ioh_1588_can_disable \ + to disable CAN\n"); + (void)ioh_1588_can_disable(); + } + if (strcmp(ioh_1588_param.station, "00:00:00:00:00:00") != 0) { + if (ioh_1588_set_station_address(ioh_1588_param.station) != + IOH_1588_SUCCESS) { + IOH_LOG(KERN_ERR, + "ioh_1588_probe: Invalid station address \ + parameter\n" + "Module loaded; But, station address not set \ + correctly\n"); + } + } + IOH_DEBUG("ioh_1588_probe: probe succeeded\n"); + + return 0; + +exit_error: + + IOH_LOG(KERN_ERR, "ioh_1588_probe: probe failed\n"); + return ret; +} + +/*! @ingroup IEEE_1588_PCILayerAPI + * @fn void ioh_1588_remove(struct pci_dev *pdev) + * @brief + * This function is called when the pci driver is being unloaded from the + * kernel. + * @remarks + * The main tasks performed by this method are: + * - Free the interrupt line using free_irq API. + * - Disable the PCI device using pci_disable_device API. + * - Unmap the PCI memory and release the same using iounmap API. + * - Delete the char device from the system using cdev_del API. + * - Unregister the driver using unregister_chrdev_region API. + * + * @param pdev [INOUT] pci device structure + * + * @return None + *@see + - ioh_1588_pcidev + * + *
+ */ + +static void __devexit ioh_1588_remove(struct pci_dev *pdev) +{ + /* disable the interrupts on the 1588 hardware */ + IOH_DEBUG("ioh_1588_remove: disabling interrupts by \ + invoking ioh_1588_disable_interrupts\n"); + (void)ioh_1588_disable_interrupts(); + + /* free the interrupt */ + if (pdev->irq != 0) { + free_irq(pdev->irq, &ioh_1588_dev); + IOH_DEBUG("ioh_1588_remove: unregistered IRQ handler\n"); + } + + /* unmap the virtual IO memory space */ + if (ioh_1588_dev.mem_virt != 0) { + iounmap(ioh_1588_dev.mem_virt); + IOH_DEBUG + ("ioh_1588_remove: unmaped the virtual IO memory space\n"); + } + + /* release the reserved IO memory space */ + if (ioh_1588_dev.mem_base != 0) { + release_mem_region(ioh_1588_dev.mem_base, + ioh_1588_dev.mem_size); + IOH_DEBUG + ("ioh_1588_remove: released the reserved IO memory \ + space\n"); + } + + /* remove cdev struct from system */ + cdev_del(&ioh_1588_dev.cdev); + IOH_DEBUG("ioh_1588_remove: removed the cdev from system\n"); + + unregister_chrdev_region(ioh_1588_dev.devno, 1); + IOH_DEBUG("ioh_1588_remove:unregisterd the module\n"); + + /*disable the device */ + pci_disable_device(pdev); + IOH_DEBUG("ioh_1588_remove:disabled the device\n"); + + IOH_LOG(KERN_ERR, "ioh_1588_remove: complete\n"); +} + +#ifdef CONFIG_PM +/*! @ingroup IEEE_1588_PCILayerAPI + * @fn int ioh_1588_suspend(struct pci_dev *pdev,pm_message_t state) + * @brief + * This function is called to suspend a device before being put into a + * low power state. + * + * @remarks + * The main tasks performed by this method are: + * - Save PCI configuration space by invoking pci_save_state API. + * - If the above step fails, return the error from pci_save_state + * API. + * - Disable the PCI device using the pci_disable_device API. + * - Put the device to new power state using pci_set_power_state + * API. + * + * + * @param pdev [INOUT] pci device structure + * @param state [IN] suspend state + * + * @return int + * - 0 on success + * - -ENOMEM pci_save_state fails + * + * @see + * - ioh_1588_pcidev + *
+ * */ +static int ioh_1588_suspend(struct pci_dev *pdev, pm_message_t state) +{ + + IOH_DEBUG("ioh_1588_suspend: disabling interrupts by \ + invoking ioh_1588_disable_interrupts\n"); + (void)ioh_1588_disable_interrupts(); + + ioh_1588_dev.suspend = 1; + + IOH_DEBUG("ioh_1588_suspend: saving register values by \ + invoking ioh_1588_save_state\n"); + ioh_1588_save_state(); + + pci_disable_device(pdev); + IOH_DEBUG("ioh_1588_suspend: disabled the device\n"); + + (void)pci_enable_wake(pdev, PCI_D3hot, 0); + IOH_DEBUG("ioh_1588_suspend: disabled PM notifications\n"); + + if (pci_save_state(pdev) != 0) { + IOH_LOG(KERN_ERR, + "ioh_1588_suspend: could not save PCI config state\n"); + return -ENOMEM; + } + IOH_DEBUG("ioh_1588_suspend: saved state\n"); + + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + IOH_DEBUG("ioh_1588_suspend: returning success\n"); + return 0; +} + +/*! @ingroup IEEE_1588_PCILayerAPI + * @fn int ioh_1588_resume(struct pci_dev *pdev) + * @brief + * This function is called to resume a device after being put into a + * low power state. + * @remarks + * The main tasks performed by this method are: + * - Restore the power state of the device using + * pci_set_power_state + * API. + * - Restore the PCI configuration space using pci_restore_state + * API. + * - Enable the PCI device using pci_enable_device API. + * - If pci_enable_device fails, return the error status; + * else return 0. + * + * + * @param pdev [INOUT] pci device structure + * + * @return int + * - 0 on success + * - -EIO pci_enable_device fails + * - -EINVAL pci_enable_device fails + * @see + * - ioh_1588_pcidev + *
+ */ + +static int ioh_1588_resume(struct pci_dev *pdev) +{ + int ret; + + pci_set_power_state(pdev, PCI_D0); + + ret = pci_restore_state(pdev); + + if (ret != 0) { + IOH_LOG(KERN_ERR, + "ioh_1588_resume: pci_restore_state failed\n"); + return ret; + } + IOH_DEBUG("ioh_1588_resume: restored state\n"); + + ret = pci_enable_device(pdev); + + if (ret) { + IOH_LOG(KERN_ERR, + "ioh_1588_resume: pci_enable_device failed\n"); + return ret; + } + + IOH_DEBUG("ioh_1588_resume: enabled device\n"); + + (void)pci_enable_wake(pdev, PCI_D3hot, 0); + IOH_DEBUG("ioh_1588_resume: disabled PM notifications\n"); + + IOH_DEBUG("ioh_1588_resume: restoring register values by \ + invoking ioh_1588_restore_state\n"); + ioh_1588_restore_state(); + + ioh_1588_dev.suspend = 0; + + IOH_DEBUG("ioh_1588_resume: returning success\n"); + return 0; +} +#endif + +/*! @ingroup IEEE_1588_InterfaceLayerAPI + * @fn void ioh_1588_exit(void) + * @brief Un-loads the IEEE 1588 PCI driver. + * @remarks This function is invoked when the driver is + * unloaded. The main task performed by this + * function is un-registering the module as + * PCI driver. + * @param None + * @return None + *
+ */ +static void __exit ioh_1588_exit(void) +{ + + pci_unregister_driver(&ioh_1588_pcidev); + + IOH_DEBUG("ioh_1588_exit: Driver unloaded\n"); +} + +/*! @ingroup IEEE_1588_InterfaceLayerAPI + * @fn int ioh_1588_init(void) + * @brief Initializes the driver. + * @remarks This function is the entry point for the driver. + * The main tasks performed by this method are: + * - Register IEEE 1588 driver as a PCI driver by calling + * pci_register_driver + * + * @param None + * + * @return int + * - 0 on success + * - -EBUSY register_chrdev_region fails + * - -ENOMEM cdev_add/register_chrdev_region/ + * pci_register_driver fails + * - -EEXIST pci_register_driver fails + * - -EINVAL pci_register_driver fails + *
+ */ +static int __init ioh_1588_init(void) +{ + int ret; + + (void)memset((void *)&ioh_1588_dev, 0, sizeof ioh_1588_dev); + + /* register the driver with the pci core */ + ret = pci_register_driver(&ioh_1588_pcidev); + + if (ret) + IOH_LOG(KERN_ERR, "ioh_1588_init: pci_register failed\n"); + + IOH_DEBUG("ioh_1588_init: pci_register success\n"); + return ret; +} + +module_init(ioh_1588_init); +module_exit(ioh_1588_exit); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, ioh_1588_pcidev_id); diff -urN linux-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_pci.h topcliff-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_pci.h --- linux-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_pci.h 1970-01-01 09:00:00.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/pch_ieee1588/pch_1588_pci.h 2010-03-09 05:27:48.000000000 +0900 @@ -0,0 +1,122 @@ + /*! + * @file ioh_1588_pci.h + * @brief + * This file lists the declarations for IEEE_1588_PCILayer APIs. + * @version 0.92 + * @section + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * History: + * modified to support Intel IOH GE IEEE 1588 hardware + * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. + * All rights reserved. + * derived from + * IEEE 1588 Time Synchronization Driver for Intel EP80579 + * Copyright(c) 2007,2008 Intel Corporation. All rights reserved. + * All rights reserved. + * + */ + +#ifndef IOH_1588_PCI_H +#define IOH_1588_PCI_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*! @ingroup IEEE_1588_Global + * @def DRIVER_NAME + * @brief Macro representing the name of this driver + *
+ */ +#define DRIVER_NAME "ioh_ieee1588" + +/*! @ingroup IEEE_1588_Global + * @def STATION_ADDR_LEN + * @brief Macro representing the station address length + *
+ */ +#define STATION_ADDR_LEN 20 + +/*! @ingroup IEEE_1588_PCILayer + @def PCI_VENDOR_ID_IOH + @brief Outlines the PCI Vendor ID for IOH board. + */ + +/*! @ingroup IEEE_1588_PCILayer + @def PCI_DEVICE_ID_IOH_1588 + @brief Outlines the PCI Device ID for IEEE 1588 device. + */ +#define PCI_DEVICE_ID_IOH_1588 0x8819 + +/*! @ingroup IEEE_1588_PCILayer + * @def IO_MEM_BAR + * @brief Macro representing IO memory BAR + *
+ */ +#define IO_MEM_BAR 1 + +/* enumeration of events used */ + +/*! @ingroup IEEE_1588_Global + * @enum notify_event + * @brief enumeration of events used + *
+ */ +enum _notify_event { + TARG_TIME_EVENT_NUM, + AUX_TIME_EVENT_NUM, + PPS_EVENT_NUM, + NUM_EVENTS +}; + +/* private driver data */ +/*! @ingroup IEEE_1588_Global + * @struct ioh_1588_dev_t + * @brief Driver private data + *
+ */ +struct ioh_1588_dev { + dev_t devno; /**< The device (major) number. */ + struct cdev cdev; /**< The cdev structure instance. */ + void *mem_virt; /**< The virtual memory base address.*/ + unsigned int mem_base; /**< The physical memory base address.*/ + unsigned int mem_size; /**< The memory size. */ + unsigned int irq; /**< The IRQ line of the device.*/ + unsigned int suspend:1; /**< The suspend flag. */ + unsigned int initialized:1; /**< The initialized flag. */ + /* event variables */ + unsigned int event_flags[NUM_EVENTS]; /**< The event variables. */ + wait_queue_head_t notify_evt[NUM_EVENTS]; /**< The notify event + variable.*/ +}; + +extern struct ioh_1588_dev *ioh_1588_devp; +extern const struct file_operations ioh_1588_fops; +irqreturn_t ioh_1588_isr(int irq, void *p_data); +extern void ioh_1588_save_state(void); +extern void ioh_1588_restore_state(void); + +#endif /* IOH_1588_PCI_H */ diff -urN linux-2.6.33-rc3/drivers/char/pch_ieee1588/pch_common.h topcliff-2.6.33-rc3/drivers/char/pch_ieee1588/pch_common.h --- linux-2.6.33-rc3/drivers/char/pch_ieee1588/pch_common.h 1970-01-01 09:00:00.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/pch_ieee1588/pch_common.h 2010-03-09 05:56:11.000000000 +0900 @@ -0,0 +1,146 @@ +/*! + * @file ioh_common.h + * @brief Provides the macro definitions used by all files. + * @version 1.0.0.0 + * @section + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * History: + * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. + * All rights reserved. + * + * created: + * WIPRO 03/07/2009 + * modified: + * WIPRO 05/08/2009 + * + */ + +#ifndef __IOH_COMMON_H__ +#define __IOH_COMMON_H__ + +/*! @ingroup Global +@def IOH_WRITE8 +@brief Macro for writing 8 bit data to an io/mem address +*/ +#define IOH_WRITE8(val, addr) iowrite8((val), (void __iomem *)(addr)) +/*! @ingroup Global +@def IOH_LOG +@brief Macro for writing 16 bit data to an io/mem address +*/ +#define IOH_WRITE16(val, addr) iowrite16((val), (void __iomem *)(addr)) +/*! @ingroup Global +@def IOH_LOG +@brief Macro for writing 32 bit data to an io/mem address +*/ +#define IOH_WRITE32(val, addr) iowrite32((val), (void __iomem *)(addr)) + +/*! @ingroup Global +@def IOH_READ8 +@brief Macro for reading 8 bit data from an io/mem address +*/ +#define IOH_READ8(addr) ioread8((void __iomem *)(addr)) +/*! @ingroup Global +@def IOH_READ16 +@brief Macro for reading 16 bit data from an io/mem address +*/ +#define IOH_READ16(addr) ioread16((void __iomem *)(addr)) +/*! @ingroup Global +@def IOH_READ32 +@brief Macro for reading 32 bit data from an io/mem address +*/ +#define IOH_READ32(addr) ioread32((void __iomem *)(addr)) +/*! @ingroup Global +@def IOH_WRITE32_F +@brief Macro for writing 32 bit data to an io/mem address +*/ +#define IOH_WRITE32_F(val, addr) do \ + { IOH_WRITE32((val), (addr)); (void)IOH_READ32((addr)); } while (0); + +/*! @ingroup Global +@def IOH_WRITE_BYTE +@brief Macro for writing 1 byte data to an io/mem address +*/ +#define IOH_WRITE_BYTE IOH_WRITE8 +/*! @ingroup Global +@def IOH_WRITE_WORD +@brief Macro for writing 1 word data to an io/mem address +*/ +#define IOH_WRITE_WORD IOH_WRITE16 +/*! @ingroup Global +@def IOH_WRITE_LONG +@brief Macro for writing long data to an io/mem address +*/ +#define IOH_WRITE_LONG IOH_WRITE32 + +/*! @ingroup Global +@def IOH_READ_BYTE +@brief Macro for reading 1 byte data from an io/mem address +*/ +#define IOH_READ_BYTE IOH_READ8 +/*! @ingroup Global +@def IOH_READ_WORD +@brief Macro for reading 1 word data from an io/mem address +*/ +#define IOH_READ_WORD IOH_READ16 +/*! @ingroup Global +@def IOH_READ_LONG +@brief Macro for reading long data from an io/mem address +*/ +#define IOH_READ_LONG IOH_READ32 + +/* Bit Manipulation Macros */ + +/*! @ingroup Global +@def IOH_READ_LONG +@brief macro to set a specified bit(mask) at the + specified address +*/ +#define IOH_SET_ADDR_BIT(addr, bitmask) IOH_WRITE_LONG((IOH_READ_LONG(addr) |\ + (bitmask)), (addr)) + +/*! @ingroup Global +@def IOH_READ_LONG +@brief macro to clear a specified bit(mask) at the specified address +*/ +#define IOH_CLR_ADDR_BIT(addr, bitmask) IOH_WRITE_LONG((IOH_READ_LONG(addr) &\ + ~(bitmask)), (addr)) + +/*! @ingroup Global +@def IOH_READ_LONG +@brief macro to set a specified bitmask for a variable +*/ +#define IOH_SET_BITMSK(var, bitmask) ((var) |= (bitmask)) + +/*! @ingroup Global +@def IOH_READ_LONG +@brief macro to clear a specified bitmask for a variable +*/ +#define IOH_CLR_BITMSK(var, bitmask) ((var) &= (~(bitmask))) + +/*! @ingroup Global +@def IOH_READ_LONG +@brief macro to set a specified bit for a variable +*/ +#define IOH_SET_BIT(var, bit) ((var) |= (1<<(bit))) + +/*! @ingroup Global +@def IOH_READ_LONG +@brief macro to clear a specified bit for a variable +*/ +#define IOH_CLR_BIT(var, bit) ((var) &= ~(1<<(bit))) + +#endif diff -urN linux-2.6.33-rc3/drivers/char/pch_ieee1588/pch_debug.h topcliff-2.6.33-rc3/drivers/char/pch_ieee1588/pch_debug.h --- linux-2.6.33-rc3/drivers/char/pch_ieee1588/pch_debug.h 1970-01-01 09:00:00.000000000 +0900 +++ topcliff-2.6.33-rc3/drivers/char/pch_ieee1588/pch_debug.h 2010-03-09 05:37:47.000000000 +0900 @@ -0,0 +1,60 @@ +/*! + * @file ioh_debug.h + * @brief Provides the macro definitions used for debugging. + * @version 1.0.0.0 + * @section + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * History: + * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD. + * All rights reserved. + * + * created: + * WIPRO 03/07/2009 + * modified: + * WIPRO 05/08/2009 + * + */ + +#ifndef __IOH_DEBUG_H__ +#define __IOH_DEBUG_H__ + +#ifdef MODULE +#define IOH_LOG(level, fmt, args...) printk(level "%s:" fmt "\n",\ + THIS_MODULE->name, ##args) +#else +#define IOH_LOG(level, fmt, args...) printk(level "%s:" fmt "\n" ,\ + __FILE__, ##args) +#endif + + +#ifdef DEBUG + #define IOH_DEBUG(fmt, args...) IOH_LOG(KERN_DEBUG, fmt, ##args) +#else + #define IOH_DEBUG(fmt, args...) +#endif + +#ifdef IOH_TRACE_ENABLED + #define IOH_TRACE IOH_DEBUG +#else + #define IOH_TRACE(fmt, args...) +#endif + +#define IOH_TRACE_ENTER IOH_TRACE("Enter %s", __func__) +#define IOH_TRACE_EXIT IOH_TRACE("Exit %s", __func__) + + +#endif