/***************************************************************************/
/*                             Druckersoftware                             */
/*                    Copyright (C) Carl Valentin GmbH                     */
/***************************************************************************/

/*
 * KM_DmaChan_ControlModulAccess.c
 *
 *  Created on: May 31, 2016
 *      Author: preitinger
 */


/*. IMPORT ================================================================*/
#include "KM_DmaChan_ControlModulAccess.h"
//#include <linux/bitops.h>
/*. ENDIMPORT =============================================================*/

/*. LOCAL =================================================================*/

/*-------------------------------- Makros ---------------------------------*/

// uebersichtliche Klassen- und Methodenverwendung (ja, auch in C kein Prob ;-))
#define MYCONCAT(a,b,c) a##b##c
#define MYCONNECT(a,b,c) MYCONCAT(a,b,c)
#define P DmaChan // (P)ackage
#define P_(TypeOrFunc) MYCONNECT(P,_,TypeOrFunc)
#define M P_(MappedIo)
#define M_(Func) MYCONNECT(M,_,Func)

/*--------------------------- Typdeklarationen ----------------------------*/

/*------------------------------ Prototypen -------------------------------*/

/*------------------------ Konstantendeklarationen ------------------------*/

/*------------------------- modulglobale Variable -------------------------*/

/*. ENDLOCAL ==============================================================*/





int
DmaChan_ControlModulAccess_create(DmaChan_ControlModulAccess* this) {
	int res;

	ASSERT(this);
	res = M_(create)(&this->_mappedIo, 0x44e10000, 0x2000);
	return res;
}

void
DmaChan_ControlModulAccess_delete(DmaChan_ControlModulAccess* this) {
	ASSERT(this);
	M_(delete)(&this->_mappedIo);
}

void
DmaChan_ControlModulAccess_setCrossbarMapping(DmaChan_ControlModulAccess* this, int channel, int crossbarEvt) {
    unsigned long tpcc_evt_mux_0_3_off = 0xf90;
    unsigned long off;
    uint32_t val;
    int bitPos;

    // check args
    ASSERT(this);
    ASSERT(channel >= 0 && channel < 64);
    ASSERT(crossbarEvt >= 0 && crossbarEvt < 64);

//    pr_info("setCrossbarMapping: channel=%d, crossbarEvt=%d\n", channel, crossbarEvt);

    bitPos = ((channel & 3) << 3); // aequivalent zu (channel % 4) * 8;
    off = tpcc_evt_mux_0_3_off + ((channel >> 2) << 2);
//    pr_info("setCrossbarMapping: off=%lx\n", off);
	val = M_(get32)(&this->_mappedIo, off);
//	pr_info("old val: %x\n", val);
	val &= ~GENMASK(bitPos + 5, bitPos);
//	val &= ~((BIT(6) - 1) << ((channel & 3) << 3)); gleiches wie oben mit genmask, aber nicht leserlich
//	pr_info("val masked: %x\n", val);
//	pr_info("shift by %d\n", bitPos);
	val |= (crossbarEvt << bitPos); // aequivalent zu (crossbarEvt << (8 * (channel % 4))); siehe hw manual SPRUH73K - October 2011 - Revised June 2014, S. 1425
//	pr_info("val ored: %x\n", val);
	M_(set32)(&this->_mappedIo, off, val);

}

void
DmaChan_ControlModulAccess_printCrossbarMapping(DmaChan_ControlModulAccess* this, int channel) {
    unsigned long tpcc_evt_mux_0_3_off = 0xf90;
    unsigned long off;
    uint32_t val;
    int bitPos;

    // check args
    ASSERT(this);
    ASSERT(channel >= 0 && channel < 64);

//    pr_info("setCrossbarMapping: channel=%d, crossbarEvt=%d\n", channel, crossbarEvt);

    bitPos = ((channel & 3) << 3); // aequivalent zu (channel % 4) * 8;
    off = tpcc_evt_mux_0_3_off + ((channel >> 2) << 2);
    val = M_(get32)(&this->_mappedIo, off);
    pr_info("crossbar val for channel %d: %d\n", channel, val);

}

void
DmaChan_ControlModulAccess_setPinMux(DmaChan_ControlModulAccess* this, int off, int mode, bool pullEnabled, bool upSelected, bool receiverEnabled) {
	uint32_t val;

	// check args
	ASSERT(this);
	ASSERT(off >= 0 && off <= 0x234);
	ASSERT(mode >= 0 && mode < 8);

	val = M_(get32)(&this->_mappedIo, 0x800 | off);
	// manipulate val
	// fast/slow bit wird vorerst so gelassen wie es ist
	// and
	val &= ~(BIT(6) - 1);
	// or
	val |= mode;
	val |= ((pullEnabled ? 0 : 1) << 3);
	val |= (upSelected ? 1 : 0) << 4;
	val |= (receiverEnabled ? 1 : 0) << 5;

	M_(set32)(&this->_mappedIo, 0x800 | off, val);

}


EXPORT_SYMBOL(DmaChan_ControlModulAccess_create);
EXPORT_SYMBOL(DmaChan_ControlModulAccess_delete);
EXPORT_SYMBOL(DmaChan_ControlModulAccess_setCrossbarMapping);
EXPORT_SYMBOL(DmaChan_ControlModulAccess_setPinMux);
