/** @par LICENCE
* @verbatim
 Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code and the documentation.
        
        ADDI-DATA GmbH
        Dieselstrasse 3 
        D-77833 Ottersweier
        Tel: +19(0)7223/9493-0
        Fax: +49(0)7223/9493-92
        http://www.addi-data-com
        info@addi-data.com

    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; either version 2 of the License, or
    (at your option) any later version.

    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 shoud find the complete GPL in the COPYING file accompanying 
    this source code. 
* @endverbatim
*/

#ifndef __TCW_H__
#define __TCW_H__

/* algo. for timer counter watchdog is the same - hence the name TCW */

/** stop TWC 
 * @param[in] base_address The base address of the iomapping block for this TCW  
 *  
 */
static inline void tcw_stop( unsigned long base_address )
{
	register uint32_t val = inl( base_address + APCIE1564_TCW_CONTROL_REG );

	/* clear the bit enable/disable, using the current configuration for all bits but "trg" und "Clr Counter" */
	val = (val & 0xFFFFF9FE );
	
	outl( val, base_address + APCIE1564_TCW_CONTROL_REG);
}

/* set all config bits to 0 (disable also interrupt) */
static inline void tcw_reset( unsigned long base_address )
{
	outl( 0x0, base_address + APCIE1564_TCW_CONTROL_REG );
	outl( 0x0 , base_address + APCIE1564_TCW_RELOAD_VALUE_REG);
}

static inline void tcw_set_reload_value(unsigned long base_address, uint32_t reload_value)
{
	outl ( reload_value , base_address + APCIE1564_TCW_RELOAD_VALUE_REG);
}

/** clear TWC 
 * 
 * @param[in] base_address The base address of the iomapping block for this TCW
 * */
static inline void tcw_clear( unsigned long base_address)
{
	uint32_t val = inl(base_address + APCIE1564_TCW_CONTROL_REG);
	
	/* set the bit "clear counter", using the current configuration for all bits but "trg" und "Clr Counter" */
	val = (val & (0xFFFFF9FF)) | (1<<10);

	outl( val, base_address+APCIE1564_TCW_CONTROL_REG);
}

/* read current TCW value 
 * 
 * @param[in] base_address The base address of the iomapping block for this TCW
 * @return The current value (32bits)
 */
static inline uint32_t tcw_read_value(unsigned long base_address)
{
	return inl(base_address + APCIE1564_TCW_VALUE_REG );
}

/** set the bit E/D IRQ 
 * @param[in] base_address The base address of the iomapping block for this TCW
 */ 
static inline void tcw_enable_interrupt(unsigned long base_address)
{
	uint32_t val = inl( base_address + APCIE1564_TCW_CONTROL_REG );
	
	/* set the bit "E/D IRQ", using the current configuration for all bits but "trg" und "Clr Counter" */
	val = (val & (0xFFFFF9FF)) | (1<<1);
	
	outl(val, base_address + APCIE1564_TCW_CONTROL_REG);
	
}

/* clear the bit E/D IRQ 
 * @param[in] base_address The base address of the iomapping block for this TCW
 * 
 */
static inline void tcw_disable_interrupt(unsigned long base_address)
{
	uint32_t val = inl( base_address + APCIE1564_TCW_CONTROL_REG );
	
	/* clear the bit "E/D IRQ", using the current configuration for all bits but "trg" und "Clr Counter" */
	val = (val & 0xFFFFF9FD);
	outl(val, base_address + APCIE1564_TCW_CONTROL_REG);
}

/** Get interrupt status.
 * 
 * ! for counter and timer, reading the IRQ status register acknowledge it  
 * 
 * @return 1 if the counter has generated an interrupt, 0 otherwise
 */
static inline uint32_t tcw_get_interrupt_status(unsigned long base_address)
{
	return ( 0x1 & inl( base_address + APCIE1564_TCW_IRQ_REG ) );
}

static inline void tcw_trigger(unsigned long base_address)
{
	uint32_t val = inl( base_address + APCIE1564_TCW_CONTROL_REG );
	
	/* set the bit "trg", using the current configuration for all bits but "trg" und "Clr Counter" - set the bit trigger*/
	//val = (val & (uint32_t) (0xFFFFF9FF)) | (uint32_t) (1<<9);
	val = (val & (uint32_t) (0xFFFFF9FF)) | (uint32_t) 0x200;
	
	outl(val, base_address + APCIE1564_TCW_CONTROL_REG);
}

static inline uint32_t tcw_get_status(unsigned long base_address)
{
	return (inl(base_address+APCIE1564_TCW_STATUS_REG)) & 0x0000000F;
}           

static inline uint32_t tcw_get_config(unsigned long base_address)
{
	return inl(base_address + APCIE1564_TCW_CONTROL_REG);
}

static inline int TCW_SOFTWARE_TRIGGER_STATUS(uint32_t status)
{
	return ((status >> 1) & 0x1);
} 
static inline int TCW_SOFTWARE_CLEAR_STATUS(uint32_t status)
{
	return ((status >> 3) & 0x1);
}

static inline int TCW_OVERFLOW_STATUS(uint32_t status)
{
	return ((status) & 0x1);
}



#endif // __TCW_H__
