376 lines
7.4 KiB
C
376 lines
7.4 KiB
C
#include <linux/init.h>
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/types.h>
|
|
#include <linux/io.h>
|
|
|
|
#include "mvGpp.h"
|
|
|
|
#define MV_DEBUG
|
|
|
|
#ifdef MV_DEBUG
|
|
#define mvOsPrintf printk
|
|
#define DB(x) x
|
|
#else
|
|
#define mvOsPrintf
|
|
#define DB(x)
|
|
#endif
|
|
|
|
static void* mv_reg_base = NULL;
|
|
|
|
static inline uint32_t MV_REG_READ(uint32_t regOffs)
|
|
{
|
|
return *((volatile uint32_t*)(mv_reg_base + regOffs));
|
|
}
|
|
|
|
static inline void MV_REG_WRITE(uint32_t regOffs, uint32_t value)
|
|
{
|
|
*((volatile uint32_t*)(mv_reg_base + regOffs)) = value;
|
|
}
|
|
|
|
static void gppRegSet(uint32_t regOffs, uint32_t mask, uint32_t value)
|
|
{
|
|
uint32_t gppData;
|
|
|
|
gppData = MV_REG_READ(regOffs);
|
|
|
|
gppData &= ~mask;
|
|
|
|
gppData |= (value & mask);
|
|
|
|
MV_REG_WRITE(regOffs, gppData);
|
|
|
|
#ifdef MV_DEBUG
|
|
|
|
if(regOffs != 0x18154)
|
|
{
|
|
do
|
|
{
|
|
uint32_t value;
|
|
value = MV_REG_READ(regOffs);
|
|
// DB(mvOsPrintf("regOffs:0x%x,write:0x%x,read:0x%x\n", regOffs, gppData, value));
|
|
}
|
|
while(0);
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
#define DUMP_GPIO_REG(off) do{ \
|
|
uint32_t value; \
|
|
value = MV_REG_READ(off); \
|
|
printk("*(0x%x)=0x%x\n",off,value);\
|
|
}while(0)
|
|
|
|
void mvGppRegDump(int grp)
|
|
{
|
|
|
|
DUMP_GPIO_REG(MPP_CONTROL_REG(0));
|
|
DUMP_GPIO_REG(MPP_CONTROL_REG(1));
|
|
DUMP_GPIO_REG(MPP_CONTROL_REG(2));
|
|
DUMP_GPIO_REG(MPP_CONTROL_REG(3));
|
|
DUMP_GPIO_REG(MPP_CONTROL_REG(4));
|
|
DUMP_GPIO_REG(MPP_CONTROL_REG(5));
|
|
DUMP_GPIO_REG(MPP_CONTROL_REG(6));
|
|
DUMP_GPIO_REG(MPP_CONTROL_REG(7));
|
|
DUMP_GPIO_REG(MPP_CONTROL_REG(8));
|
|
DUMP_GPIO_REG(MV_GPP_REGS_BASE(grp) + 0x0);
|
|
DUMP_GPIO_REG(MV_GPP_REGS_BASE(grp) + 0x4);
|
|
DUMP_GPIO_REG(MV_GPP_REGS_BASE(grp) + 0x8);
|
|
DUMP_GPIO_REG(MV_GPP_REGS_BASE(grp) + 0xc);
|
|
DUMP_GPIO_REG(MV_GPP_REGS_BASE(grp) + 0x10);
|
|
DUMP_GPIO_REG(MV_GPP_REGS_BASE(grp) + 0x14);
|
|
DUMP_GPIO_REG(MV_GPP_REGS_BASE(grp) + 0x18);
|
|
DUMP_GPIO_REG(MV_GPP_REGS_BASE(grp) + 0x1c);
|
|
DUMP_GPIO_REG(MV_GPP_REGS_BASE(grp) + 0x20);
|
|
DUMP_GPIO_REG(MV_GPP_REGS_BASE(grp) + 0x24);
|
|
}
|
|
|
|
|
|
int mvGppCtlSet(uint32_t group, uint32_t mask, uint32_t value)
|
|
{
|
|
|
|
if(group >= MV_MPP_MAX_GROUP)
|
|
{
|
|
DB(mvOsPrintf("mvGppBlinkEn: ERR. invalid group number \n"));
|
|
return -1;
|
|
}
|
|
|
|
gppRegSet(MPP_CONTROL_REG(group), mask, value);
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t mvGppCtlGet(uint32_t group)
|
|
{
|
|
|
|
uint32_t value;
|
|
value = MV_REG_READ(MPP_CONTROL_REG(group));
|
|
// DB(mvOsPrintf("regOffs:0x%x,read:0x%x\n", MPP_CONTROL_REG(group), value));
|
|
|
|
return value;
|
|
}
|
|
|
|
|
|
int mvGppTypeSet(uint32_t group, uint32_t mask, uint32_t value)
|
|
{
|
|
if(group >= MV_GPP_MAX_GROUP)
|
|
{
|
|
DB(mvOsPrintf("mvGppBlinkEn: ERR. invalid group number \n"));
|
|
return -1;
|
|
}
|
|
|
|
gppRegSet(GPP_DATA_OUT_EN_REG(group), mask, value);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int mvGppBlinkEn(uint32_t group, uint32_t mask, uint32_t value)
|
|
{
|
|
if(group >= MV_GPP_MAX_GROUP)
|
|
{
|
|
DB(mvOsPrintf("mvGppBlinkEn: ERR. invalid group number \n"));
|
|
return -1;
|
|
}
|
|
|
|
gppRegSet(GPP_BLINK_EN_REG(group), mask, value);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int mvGppBlinkSel(uint32_t group, uint32_t mask, uint32_t value)
|
|
{
|
|
|
|
if(group >= MV_GPP_MAX_GROUP)
|
|
{
|
|
DB(mvOsPrintf("mvGppBlinkEn: ERR. invalid group number \n"));
|
|
return -1;
|
|
}
|
|
|
|
gppRegSet(GPP_BLINK_SEL_REG(group), mask, value);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int mvGppBlinkOnDiv(uint32_t group, uint32_t div)
|
|
{
|
|
|
|
if(group >= MV_BLINK_COUNTER_MAX_GROUP)
|
|
{
|
|
DB(mvOsPrintf("mvGppBlinkEn: ERR. invalid group number \n"));
|
|
return -1;
|
|
}
|
|
|
|
MV_REG_WRITE(GPP_BLINK_COUNT_ON(group), div);
|
|
|
|
#ifdef MV_DEBUG
|
|
|
|
do
|
|
{
|
|
uint32_t value;
|
|
value = MV_REG_READ(GPP_BLINK_COUNT_ON(group));
|
|
// DB(mvOsPrintf("regOffs:0x%x,write:0x%x,read:0x%x\n", GPP_BLINK_COUNT_ON(group), div, value));
|
|
}
|
|
while(0);
|
|
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
|
|
int mvGppBlinkOffDiv(uint32_t group, uint32_t div)
|
|
{
|
|
|
|
if(group >= MV_BLINK_COUNTER_MAX_GROUP)
|
|
{
|
|
DB(mvOsPrintf("mvGppBlinkEn: ERR. invalid group number \n"));
|
|
return -1;
|
|
}
|
|
|
|
MV_REG_WRITE(GPP_BLINK_COUNT_OFF(group), div);
|
|
|
|
#ifdef MV_DEBUG
|
|
|
|
do
|
|
{
|
|
uint32_t value;
|
|
value = MV_REG_READ(GPP_BLINK_COUNT_OFF(group));
|
|
// DB(mvOsPrintf("regOffs:0x%x,write:0x%x,read:0x%x\n", GPP_BLINK_COUNT_OFF(group), div, value));
|
|
}
|
|
while(0);
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int mvGppPolaritySet(uint32_t group, uint32_t mask, uint32_t value)
|
|
{
|
|
if(group >= MV_GPP_MAX_GROUP)
|
|
{
|
|
DB(mvOsPrintf("mvGppPolaritySet: ERR. invalid group number \n"));
|
|
return -1;
|
|
}
|
|
|
|
gppRegSet(GPP_DATA_IN_POL_REG(group), mask, value);
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t mvGppPolarityGet(uint32_t group, uint32_t mask)
|
|
{
|
|
uint32_t regVal;
|
|
|
|
if(group >= MV_GPP_MAX_GROUP)
|
|
{
|
|
DB(mvOsPrintf("mvGppActiveSet: Error invalid group number \n"));
|
|
return 0;
|
|
}
|
|
|
|
regVal = MV_REG_READ(GPP_DATA_IN_POL_REG(group));
|
|
|
|
return (regVal & mask);
|
|
}
|
|
|
|
uint32_t mvGppValueGet(uint32_t group, uint32_t mask)
|
|
{
|
|
uint32_t gppData;
|
|
|
|
if(group >= MV_GPP_MAX_GROUP)
|
|
{
|
|
DB(mvOsPrintf("mvGppActiveSet: Error invalid group number \n"));
|
|
return 0;
|
|
}
|
|
|
|
gppData = MV_REG_READ(GPP_DATA_IN_REG(group));
|
|
|
|
gppData &= mask;
|
|
|
|
return gppData;
|
|
|
|
}
|
|
|
|
int mvGppValueSet(uint32_t group, uint32_t mask, uint32_t value)
|
|
{
|
|
if(group >= MV_GPP_MAX_GROUP)
|
|
{
|
|
DB(mvOsPrintf("mvGppActiveSet: Error invalid group number \n"));
|
|
return -1;
|
|
}
|
|
|
|
gppRegSet(GPP_DATA_OUT_REG(group), mask, value);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int mvGPPIntCauseSet(uint32_t group, uint32_t mask, uint32_t value)
|
|
{
|
|
|
|
if(group >= MV_GPP_MAX_GROUP)
|
|
{
|
|
DB(mvOsPrintf("mvGppActiveSet: Error invalid group number \n"));
|
|
return -1;
|
|
}
|
|
|
|
gppRegSet(GPP_INT_CAUSE_REG(group), mask, value);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
uint32_t mvGPPIntCauseGet(uint32_t group, uint32_t mask)
|
|
{
|
|
uint32_t gppData;
|
|
|
|
if(group >= MV_GPP_MAX_GROUP)
|
|
{
|
|
DB(mvOsPrintf("mvGppActiveSet: Error invalid group number \n"));
|
|
return 0;
|
|
}
|
|
|
|
gppData = MV_REG_READ(GPP_INT_CAUSE_REG(group));
|
|
|
|
return (gppData & mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
int mvGPPIntMask(uint32_t group, uint32_t mask, uint32_t value)
|
|
{
|
|
|
|
if(group >= MV_GPP_MAX_GROUP)
|
|
{
|
|
DB(mvOsPrintf("mvGppActiveSet: Error invalid group number \n"));
|
|
return -1;
|
|
}
|
|
|
|
gppRegSet(GPP_INT_MASK_REG(group), mask, value);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int mvGPPIntLvlMask(uint32_t group, uint32_t mask, uint32_t value)
|
|
{
|
|
|
|
if(group >= MV_GPP_MAX_GROUP)
|
|
{
|
|
DB(mvOsPrintf("mvGppActiveSet: Error invalid group number \n"));
|
|
return -1;
|
|
}
|
|
|
|
gppRegSet(GPP_INT_LVL_REG(group), mask, value);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void mvGppAtomicValueClear(uint32_t gpionumber)
|
|
{
|
|
if(gpionumber < 64)
|
|
{
|
|
MV_REG_WRITE(GPP_OUT_CLEAR_REG((int)(gpionumber >> 5)) , 1 << (gpionumber % 32));
|
|
}
|
|
else
|
|
{
|
|
MV_REG_WRITE(GPP_64_66_DATA_OUT_CLEAR_REG , 1 << (gpionumber % 32));
|
|
}
|
|
|
|
}
|
|
|
|
void mvGppAtomicValueSet(uint32_t gpionumber)
|
|
{
|
|
if(gpionumber < 64)
|
|
{
|
|
MV_REG_WRITE(GPP_OUT_SET_REG((int)(gpionumber >> 5)) , 1 << (gpionumber % 32));
|
|
}
|
|
else
|
|
{
|
|
MV_REG_WRITE(GPP_64_66_DATA_OUT_SET_REG , 1 << (gpionumber % 32));
|
|
}
|
|
}
|
|
|
|
|
|
int mvGppInit(void)
|
|
{
|
|
if(!mv_reg_base)
|
|
{
|
|
mv_reg_base = (void*)ioremap(CSBAR, CSBAR_MAP_WIDTH);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void mvGppExit(void)
|
|
{
|
|
if(mv_reg_base)
|
|
{
|
|
iounmap(mv_reg_base);
|
|
mv_reg_base = NULL;
|
|
}
|
|
}
|
|
|