/************************************************************ * * * GPIO driver should be build alone, do not reference other drivers * * * *************************************************************/ #include #include #include #include #include #include #include #include #include "gpio.h" #include #include #include #include #include #include #include #include #define HWEMIFunction 1 PGPIO_DEV pGPIODev; INT8 gpiotablename[] = "gGPIOTableMain"; /* =============================================================================== Global Misc ================================================================================= */ static inline void SetMMIO_DWORD(UINT8* mmiobase, ULONG dwIndex, ULONG dwData) { writel(dwData, mmiobase+dwIndex); } static inline void SetMMIO_DWORD_MASK(UINT8* mmiobase, ULONG dwIndex, ULONG dwData, ULONG dwMask) { ULONG dwRes, dwValue; dwRes = readl(mmiobase+dwIndex); dwValue = ((dwData & dwMask) | (dwRes & ~dwMask)); writel(dwValue, mmiobase+dwIndex); } static inline ULONG GetMMIO_DWORD(UINT8* mmiobase, ULONG dwIndex) { ULONG dwRes; dwRes = readl(mmiobase+dwIndex); return dwRes; } /* =============================================================================== Global Driver code ================================================================================= */ static UINT32 GPIOWriteValueH, GPIOWriteValueL; #define PWM0_PeriodReg 0xbe0f0100 #define PWM0_CtrlReg 0xbe0f0104 #define PWM_EnableBit 0x80000000 #define PWM_PeriodOneSec 0x02ee0000 #define GPIOModeMask 0x80 // 80:GPIO mode, 00:PWM mode #define GreenLEDMask 0x80 #define RedLedMask 0x40 typedef struct _LED_FLICK_DEV_ { struct cdev cdev; struct delayed_work LED_FLICK_Work; }LED_FLICK_DEV,*PLED_FLICK_DEV; static LED_FLICK_DEV LED_FLICK_dev, *pLED_FLICK_dev=NULL; static UINT8 led_flick_value, led_flick_status, led_flick_flag; static UINT8 led_g_pwm_pin, led_r_pwm_pin; static CUSTIMIZATION_TABLEPTR pCustTAB = (volatile CUSTIMIZATION_TABLEPTR)SPI_OPTIONDATA_SHADOWADDR; static void LED_FLICK_fun(void) { int flick_time; led_flick_flag = 0; if ( led_flick_value & 0x0f ) { if ( (led_flick_value & 0x0f) == 0x0f ) { flick_time = (2 * HZ); } else { flick_time = (2 * HZ) / (15-(led_flick_value & 0x0f)); } } else { if (pCustTAB->GreenLEDMode) { if ( led_flick_value & 0x80 ) { GPIOWriteFun((UINT8)pCustTAB->GreenLEDNum, 1); } else { GPIOWriteFun((UINT8)pCustTAB->GreenLEDNum, 0); } } if (pCustTAB->RedLEDMode) { if ( led_flick_value & 0x40 ) { GPIOWriteFun((UINT8)pCustTAB->RedLEDNum, 1); } else { GPIOWriteFun((UINT8)pCustTAB->RedLEDNum, 0); } } return; } if ( pCustTAB->GreenLEDMode && (led_flick_value & 0x80) ) { // Green LED GPIOWriteFun((UINT8)pCustTAB->GreenLEDNum, led_flick_status); } if ( pCustTAB->RedLEDMode && (led_flick_value & 0x40) ) { // Red LED GPIOWriteFun((UINT8)pCustTAB->RedLEDNum, led_flick_status); } if ( led_flick_status == 1 ) { led_flick_status = 0; } else { led_flick_status = 1; } if ( led_flick_value & 0xc0 ) { if ( flick_time != 0 ) { schedule_delayed_work(&pLED_FLICK_dev->LED_FLICK_Work, flick_time ); led_flick_flag = 1; } } } void GPIOFunctionSelect(UINT8 index, UINT8 mode) { UINT8* mmiobase; ULONG Reg; UINT8 bits; if(index >= SIS326_GPIO_MAXNUM) { printk(KERN_EMERG "DisableGPIO ERR index\n"); return; } mmiobase = pGPIODev->mmio_vbase; if(index<=63) { mode = mode & 0x3; // set "function selection" mux to "GPIO (set '00') " Reg = 0x600 + (index / 16) * 4; bits = (index % 16) * 2; SetMMIO_DWORD_MASK(mmiobase, Reg, (mode << bits), (0x3 << bits)); // set '00' to select default function } DBG_MSG1(DBGCFG_GPIO, "Disable GPIO%d\n", index); } EXPORT_SYMBOL(GPIOFunctionSelect); static UINT8 RM_GPIOReadFunc(UINT8 index) { #if (CONFIG_CHIPID == 0x531) || (CONFIG_CHIPID == 0x533) UINT8 value=0; index = index - RM_GPIO_0; // index must between RM_GPIO_0 to RM_GPIO_8 //RMIIRXD0 as GPIO in "0xbe000210[20]='1'0xbe00019c[15]='0'" 0xbe000210[1]='1' 0xbe0001d4[1] if (index == 0) { *(volatile UINT32 *)(0xbe000210) = *(volatile UINT32 *)(0xbe000210) | 0x02 | (1<<20); *(volatile UINT32 *)(0xbe00019c) = *(volatile UINT32 *)(0xbe00019c) & (~(1<<15)); value = (*(volatile UINT8 *)(0xbe0001d4) & 0x02) >> 1; DBG_MSG1(DBGCFG_GPIO,"RM_GPIO%d = %d\n", index, value); return value; } return 0; #else return 0; #endif #if 0 UINT32 rmGPIOtmpVal=0; rmGPIOtmpVal = *(volatile UINT32 *)(RM_GPIO_SEL_REG); if ( rmGPIOtmpVal & (1<<(index<<1)) ) { value = 1; } else { value = 0; } //DBG_MSG1(DBGCFG_GPIO,"RM_GPIO%d read %d\n",index, value); return value; #endif } static UINT8 LVDS_GPIOReadFunc(UINT8 index, UINT8 tryRead) { UINT8 value=0; UINT32 tmpVal=0; if(tryRead==0) { *(volatile UINT32 *)(0xbe00012c) &= (~(R_EN_2ND_UARTA | R_EN_1ST_UARTB)); switch(index){ case GPO_TXP4: case GPO_TXN4: #if (CONFIG_CHIPID == 0x331) || (CONFIG_CHIPID == 0x131) || (CONFIG_CHIPID == 0x8506)|| (CONFIG_CHIPID == 0x6710) *(volatile UINT32 *)(0xbe000208) &= (~(1<<4)); *(volatile UINT32 *)(LVDS_GPIO_SEL_REG) |= (1<<3); *(volatile UINT32 *)(LVDS_GPIO_SEL_REG) &= (~(1<<0)); *(volatile UINT32 *)(LVDS_GPIO_SEL_REG1) &= (~((1<<4) | (1<<17))); // LVA_TXP4/LVA_TXN4 as GPO ==> 0xbe00025c[4] = '0' and 0xbe00025c[17] = '0' #else *(volatile UINT32 *)(LVDS_GPIO_SEL_REG1) &= (~(1<<4)); // LVA_TXP4/LVA_TXN4 as GPO ==> 0xbe00025c[4] = '0' #endif break; case GPO_TXP9: case GPO_TXN9: #if (CONFIG_CHIPID == 0x331) || (CONFIG_CHIPID == 0x131) || (CONFIG_CHIPID == 0x8506) || (CONFIG_CHIPID == 0x6710) *(volatile UINT32 *)(LVDS_GPIO_SEL_REG) &= (~(1<<1)); *(volatile UINT32 *)(LVDS_GPIO_SEL_REG) |= (1<<4); *(volatile UINT32 *)(LVDS_GPIO_SEL_REG1) &= (~((1<<9) | (1<<17))); // LVA_TXP4/LVA_TXN4 as GPO ==> 0xbe00025c[9] = '0' and 0xbe00025c[17] = '0' #else *(volatile UINT32 *)(LVDS_GPIO_SEL_REG1) &= (~(1<<9)); // LVA_TXP4/LVA_TXN4 as GPO ==> 0xbe00025c[9] = '0' #endif break; } } tmpVal = *(volatile UINT32 *)(LVDS_GPIO_SEL_REG); if(tmpVal & (1<<(16+(index%GPO_TXP4)))){ value=1; } else{ value=0; } if (index == GPO_TXP4) { if((*(volatile UINT32 *)0xbe0001c8)&0x40) value = 1; else value = 0; } else if (index == GPO_TXN4) { if((*(volatile UINT32 *)0xbe0001c8)&0x2) value = 1; else value = 0; } else if (index == GPO_TXP9) { if((*(volatile UINT32 *)0xbe0001c8)&0x4) value = 1; else value = 0; } else if (index == GPO_TXN9) { if((*(volatile UINT32 *)0xbe0001c8)&0x8) value = 1; else value = 0; } //DBG_MSG1(DBGCFG_GPIO,"LVDS_GPIO%d read %d\n",index, value); return value; } static void RM_GPIOWriteFunc(UINT8 index, UINT8 value) { UINT32 rmGPIOtmpVal=0; index = index - RM_GPIO_0; rmGPIOtmpVal = *(volatile UINT32 *)(RM_GPIO_SEL_REG); if ( index != 6 ) { // enable GPIO mode rmGPIOtmpVal |= (1<<(index+20)); if ( value ) { rmGPIOtmpVal |= (1<<(index<<1)); } else { rmGPIOtmpVal &= (~(1<<(index<<1))); } } else { if ( value ) { rmGPIOtmpVal |= (1<<(index+20)); // Output mode enable for RM_GPO_6 to high } else { rmGPIOtmpVal &= (~(1<<(index+20))); // Output mode disable for RM_GPO_6 to low } } *(volatile UINT32 *)(RM_GPIO_SEL_REG) = rmGPIOtmpVal; DBG_MSG1(DBGCFG_GPIO,"RM_GPIO%d set %d\t%08x\n",index, value, *(volatile UINT32 *)(RM_GPIO_SEL_REG)); } static void LVDS_GPIOWriteFunc(UINT8 index, UINT8 value) { UINT32 tmpVal=0; *(volatile UINT32 *)(0xbe00012c) &= (~(R_EN_2ND_UARTA | R_EN_1ST_UARTB)); //0xbe00012c[13] = 0 //0xbe00012c[14] = 0 tmpVal = *(volatile UINT32 *)(LVDS_GPIO_SEL_REG); switch(index){ case GPO_TXP4: case GPO_TXN4: #if (CONFIG_CHIPID == 0x331) || (CONFIG_CHIPID == 0x131) || (CONFIG_CHIPID == 0x8506)|| (CONFIG_CHIPID == 0x6710) *(volatile UINT32 *)(LVDS_GPIO_SEL_REG) |= (1<<0); *(volatile UINT32 *)(LVDS_GPIO_SEL_REG) &= (~(1<<3)); *(volatile UINT32 *)(LVDS_GPIO_SEL_REG1) &= (~((1<<4) | (1<<17))); // LVA_TXP4/LVA_TXN4 as GPO ==> 0xbe00025c[4] = '0' and 0xbe00025c[17] = '0' #else *(volatile UINT32 *)(LVDS_GPIO_SEL_REG1) &= (~(1<<4)); // LVA_TXP4/LVA_TXN4 as GPO ==> 0xbe00025c[4] = '0' #endif tmpVal |= (1<<0); break; case GPO_TXP9: case GPO_TXN9: #if (CONFIG_CHIPID == 0x331) || (CONFIG_CHIPID == 0x131) || (CONFIG_CHIPID == 0x8506) || (CONFIG_CHIPID == 0x6710) *(volatile UINT32 *)(LVDS_GPIO_SEL_REG) |= (1<<1); *(volatile UINT32 *)(LVDS_GPIO_SEL_REG) &= (~(1<<4)); *(volatile UINT32 *)(LVDS_GPIO_SEL_REG1) &= (~((1<<9) | (1<<17))); // LVA_TXP4/LVA_TXN4 as GPO ==> 0xbe00025c[9] = '0' and 0xbe00025c[17] = '0' #else *(volatile UINT32 *)(LVDS_GPIO_SEL_REG1) &= (~(1<<9)); // LVA_TXP4/LVA_TXN4 as GPO ==> 0xbe00025c[9] = '0' #endif tmpVal |= (1<<1); break; case GPO_TCP2: case GPO_TCN2: tmpVal |= (1<<2); break; } if ( value ) { tmpVal |= (1<<(16+(index%GPO_TXP4))); } else { tmpVal &= (~(1<<(16+(index%GPO_TXP4)))); } *(volatile UINT32 *)(LVDS_GPIO_SEL_REG) = tmpVal; DBG_MSG1(DBGCFG_GPIO,"LVDS_GPIO%d set %d\t%08x\n",index, value, *(volatile UINT32 *)(LVDS_GPIO_SEL_REG)); } void SetLed(UINT8 LED_NO, UINT8 LED_MODE, UINT8 LED_Mask, UINT8 LED_Status) { UINT8 LEDvalue; UINT32 pwmProid = 0; led_flick_value = LED_Status; if ( LED_MODE ) { // GPIO mode //DBG_MSG1(DBGCFG_GPIO, "[GPIO]LED GPIO mdoe: %02x S:%02x\n", LED_NO, LED_Status); if ( LED_Status & LED_Mask ) { // check Green status High LEDvalue = 1; } else { LEDvalue = 0; } GPIOWriteFun(LED_NO, LEDvalue); DBG_MSG1(DBGCFG_GPIO, "LED GPIO%d:%d\n", LED_NO, LEDvalue); } else { // PWM mode if ( LED_NO > 3 ) { DBG_MSG1(DBGCFG_GPIO, "LED PWM ERR: %02x\n", LED_NO); return; } if(LED_Mask & RedLedMask) GPIOFunctionSelect(led_r_pwm_pin, 0); // disable GPIO mode else if(LED_Mask & GreenLEDMask) GPIOFunctionSelect(led_g_pwm_pin, 0); // disable GPIO mode else {} //DBG_MSG1(DBGCFG_GPIO, "[GPIO]LED PWM mdoe: %02x S:%02x\n", LED_NO, LED_Status); pwmProid = PWM_PeriodOneSec >> (LED_Status & 0x0f); *(UINT32 *)(PWM0_PeriodReg + LED_NO * 8) = pwmProid; *(UINT32 *)(PWM0_CtrlReg + LED_NO * 8) = 0; if ( LED_Status & LED_Mask ) { if ( LED_Status & 0x0f ) { *(UINT32 *)(PWM0_CtrlReg + LED_NO * 8) = (pwmProid >> 1) | PWM_EnableBit; } else { *(UINT32 *)(PWM0_CtrlReg + LED_NO * 8) = pwmProid | PWM_EnableBit; } } DBG_MSG1(DBGCFG_GPIO, "Period:%08x\tCtrl:%08x\n", *(UINT32 *)(PWM0_PeriodReg + LED_NO * 8), *(UINT32 *)(PWM0_CtrlReg + LED_NO * 8)); } if ( (LED_Status & 0x0f )!= 0 ) { schedule_delayed_work(&pLED_FLICK_dev->LED_FLICK_Work, ((2 * HZ)/(LED_Status & 0x0f)) ); led_flick_flag = 1; } else if ( led_flick_flag == 1 ) { cancel_delayed_work(&pLED_FLICK_dev->LED_FLICK_Work); flush_delayed_work(&pLED_FLICK_dev->LED_FLICK_Work); led_flick_flag = 0; } } void CustomLedFun(UINT8 LedStatus) { led_flick_value = LedStatus; #ifndef CONFIG_GLED_DISABLE SetLed(pCustTAB->GreenLEDNum, pCustTAB->GreenLEDMode, GreenLEDMask, LedStatus); #endif SetLed(pCustTAB->RedLEDNum, pCustTAB->RedLEDMode, RedLedMask, LedStatus); } EXPORT_SYMBOL(CustomLedFun); UINT8 GPIOReadFun(UINT8 index) { ULONG Reg; UINT8 bits; ULONG W_Data; UINT8 gpiovalue = 0; if(index > (S2IC_GPIO_MAXNUM - 1)) { printk(KERN_EMERG "GPIORd ERR index\n"); return STATUS_DATA_ERROR; } if (index < SIS326_GPIO_MAXNUM) { #if (CONFIG_CHIPID == 0x6710) if ( index == GPIO_7 || index == GPIO_8) *(volatile UINT32 *)(GPIO_HDMI_SEL_REG) |= (1 << 20); else if ( index == GPIO_12 || index == GPIO_13) *(volatile UINT32 *)(GPIO_HDMI_SEL_REG) |= (1 << 21); #endif // set GPIO input / output control register to "input mode" Reg = 0x618 + (index / 32) * 4; bits = index % 32; SetMMIO_DWORD_MASK(pGPIODev->mmio_vbase, Reg, (0x1 << bits), (0x1 << bits)); // set '1' to select "input mode" // set "function selection" mux to "GPIO (set '01') " Reg = 0x600 + (index / 16) * 4; bits = (index % 16) * 2; SetMMIO_DWORD_MASK(pGPIODev->mmio_vbase, Reg, (0x1 << bits), (0x3 << bits)); // set '01' to select "GPIO" // get GPIO input value Reg = 0x610 + (index / 32) * 4; bits = index % 32; W_Data = (GetMMIO_DWORD(pGPIODev->mmio_vbase, Reg) >> bits) & 0x1; DBG_MSG1(DBGCFG_GPIO, "Rd GPIO%d:%x\n", (UINT32)index, (UINT32)W_Data); gpiovalue = (UINT8)W_Data; } else if ((index >= GPO_TXP4) && (index <= GPO_TCN2)) { // lvds GPO read function gpiovalue = LVDS_GPIOReadFunc(index,0); } else if ((index >= RM_GPIO_0) && (index <= RM_GPIO_8)) { // RM_GPO read function gpiovalue = RM_GPIOReadFunc(index); } return gpiovalue; } EXPORT_SYMBOL(GPIOReadFun); UINT8 GPIOTryRead(UINT8 index) //only read value, donot change status { ULONG Reg; UINT8 bits; ULONG W_Data = 0; if (index > (S2IC_GPIO_MAXNUM - 1)) { printk(KERN_EMERG "GPIOTryRd ERR index\n"); return STATUS_DATA_ERROR; } if (index < SIS326_GPIO_MAXNUM) { // get GPIO input value Reg = 0x610 + (index / 32) * 4; bits = index % 32; W_Data = (GetMMIO_DWORD(pGPIODev->mmio_vbase, Reg) >> bits) & 0x1; } else if ((index >= GPO_TXP4) && (index <= GPO_TCN2)) { // lvds GPO read function W_Data = LVDS_GPIOReadFunc(index,1); } else if ((index >= RM_GPIO_0) && (index <= RM_GPIO_8)) { // RM_GPO read function W_Data = RM_GPIOReadFunc(index); } return (UINT8)W_Data; } EXPORT_SYMBOL(GPIOTryRead); void GPIOWriteFun(UINT8 index, UINT8 value) { UINT8* mmiobase; ULONG Reg; UINT8 bits; if(index > (S2IC_GPIO_MAXNUM - 1)) { DBG_MSG1(DBGCFG_GPIO, "GPIOWr ERR index\n"); return; } mmiobase = pGPIODev->mmio_vbase; if(value > 1) { DBG_MSG1(DBGCFG_GPIO, "GPIOWr ERR val\n"); return; } // set GPIO output value //Reg = 0x610 + (index / 32) * 4; //bits = index % 32; //SetMMIO_DWORD_MASK(mmiobase, Reg, (value << bits), (0x1 << bits)); // set output value bits = index % 32; #ifdef CONFIG_SUPPORT_IR_TX GPIOWriteValueL = GetMMIO_DWORD(pGPIODev->mmio_vbase, 0x610); GPIOWriteValueH = GetMMIO_DWORD(pGPIODev->mmio_vbase, 0x614); #endif if ( index < 32 ) { if ( value == 1 ) { GPIOWriteValueL = GPIOWriteValueL | (0x01 << bits); } else { GPIOWriteValueL = GPIOWriteValueL & (~(0x01 << bits)); } #if (CONFIG_CHIPID == 0x6710) if ( index == GPIO_7 || index == GPIO_8) *(volatile UINT32 *)(GPIO_HDMI_SEL_REG) |= (1 << 20); else if ( index == GPIO_12 || index == GPIO_13) *(volatile UINT32 *)(GPIO_HDMI_SEL_REG) |= (1 << 21); #endif SetMMIO_DWORD(mmiobase, 0x610, GPIOWriteValueL); } else if ( index >= 32 && index < 64 ){ if ( value == 1 ) { GPIOWriteValueH = GPIOWriteValueH | (0x01 << bits); } else { GPIOWriteValueH = GPIOWriteValueH & ~((0x01 << bits)); } SetMMIO_DWORD(mmiobase, 0x614, GPIOWriteValueH); } else if ((index >= GPO_TXP4) && (index <= GPO_TCN2)) { // lvds GPO read function LVDS_GPIOWriteFunc(index, value); return; } else if( index >= RM_GPIO_0 && index <= RM_GPIO_8 ){ RM_GPIOWriteFunc(index, value); return; } else if ( index == GPO_IVDD_SEL ) { if ( value == 1 ) { *(volatile UINT32 *)(GPO_IVDD_SEL_REG) = *(volatile UINT32 *)(GPO_IVDD_SEL_REG) | (1<<29); } else { *(volatile UINT32 *)(GPO_IVDD_SEL_REG) = *(volatile UINT32 *)(GPO_IVDD_SEL_REG) & (~(1<<29)); } return; } else if (GPO_VBUS_EN == index) { if (1 == value) { *(volatile UINT8 *)(GPO_VBUS_EN_REG) = *(volatile UINT8 *)(GPO_VBUS_EN_REG) | (1 << 7); } else { *(volatile UINT8 *)(GPO_VBUS_EN_REG) = *(volatile UINT8 *)(GPO_VBUS_EN_REG) & (~(1 << 7)); } return; } else { printk(KERN_EMERG "GPIO(%d) number overflow\n",index); return; } // set GPIO input / output control register to "output mode" Reg = 0x618 + (index / 32) * 4; bits = index % 32; SetMMIO_DWORD_MASK(mmiobase, Reg, (0x0 << bits), (0x1 << bits)); // set '0' to select "output mode" // set "function selection" mux to "GPIO (set '01') " Reg = 0x600 + (index / 16) * 4; bits = (index % 16) * 2; SetMMIO_DWORD_MASK(mmiobase, Reg, (0x1 << bits), (0x3 << bits)); // set '01' to select "GPIO" DBG_MSG1(DBGCFG_GPIO, "Wr GPIO%d:%x\n", index, value); } EXPORT_SYMBOL(GPIOWriteFun); void GPIOOpenDrainWriteFun(UINT8 index, UINT8 value) { ULONG Reg; UINT8 bits; //DBG_MSG1(DBGCFG_GPIO, "GPIOOpenDrainWriteFun index 0x%x value 0x%x\n",index,value); if(index > (S2IC_GPIO_MAXNUM - 1)) { DBG_MSG1(DBGCFG_GPIO, "GPIOOpenDrainWr ERR index\n"); return; } if(value > 1) { DBG_MSG1(DBGCFG_GPIO, "GPIOOpenDrainWr ERR val\n"); return; } if (index < SIS326_GPIO_MAXNUM) { // (disable the "pull-low" enable bit and) enable the "pull-high" enable bit Reg = 0x624; // pull-high enable register (for GPIO32-35) bits = index - 32; SetMMIO_DWORD_MASK(pGPIODev->mmio_vbase, (Reg + 8), 0, (0x1 << bits)); // disable the pull-low enable bit SetMMIO_DWORD_MASK(pGPIODev->mmio_vbase, Reg, (0x1 << bits), (0x1 << bits)); // enable the pull-high enable bit // set GPIO output value to '0' //Reg = 0x610 + (index / 32) * 4; //bits = index % 32; //SetMMIO_DWORD_MASK(mmiobase, Reg, (0x0 << bits), (0x1 << bits)); // set output value = 0 bits = index % 32; if ( index < 32 ) { GPIOWriteValueL = GPIOWriteValueL & (~(0x01 << bits)); SetMMIO_DWORD(pGPIODev->mmio_vbase, 0x610, GPIOWriteValueL); } else { GPIOWriteValueH = GPIOWriteValueH & (~(0x01 << bits)); SetMMIO_DWORD(pGPIODev->mmio_vbase, 0x614, GPIOWriteValueH); } // set GPIO input / output control register to "input mode / output mode" if value = 1 / 0 (so that the output would be 1 / 0) Reg = 0x618 + (index / 32) * 4; bits = index % 32; SetMMIO_DWORD_MASK(pGPIODev->mmio_vbase, Reg, (value << bits), (0x1 << bits)); // value ==> IO mode control ==> output value // set "function selection" mux to "GPIO (set '01') " Reg = 0x600 + (index / 16) * 4; bits = (index % 16) * 2; SetMMIO_DWORD_MASK(pGPIODev->mmio_vbase, Reg, (0x1 << bits), (0x3 << bits)); // set '01' to select "GPIO" DBG_MSG1(DBGCFG_GPIO, "OpenDrainWr GPIO%d:%x\n", index, value); } } EXPORT_SYMBOL(GPIOOpenDrainWriteFun); void EnableGPIOInterrupt(UINT8 index, UINT8 mode) { UINT8* mmiobase; ULONG Reg; UINT8 bits; ULONG dwINTStatus; #if 0 if (index >= SIS326_GPIO_MAXNUM) { DBG_MSG1(DBGCFG_GPIO, "EnGPIOInt ERR index %d\n", index); return; } if (mode > 3) { DBG_MSG1(DBGCFG_GPIO, "EnGPIOInt ERR mode\n"); return; } #endif if (pGPIODev->callbackfuntable[index].function == 0) { DBG_MSG1(DBGCFG_GPIO, "EnGPIOInt ERR func\n"); return; } #if 0 // set GPIO to "input mode" (and get the input value) GPIOReadFun(index); #endif mmiobase = pGPIODev->mmio_vbase; // set GPIO (input) interrupt polarity mode (for the trigger mode) Reg = 0x630 + (index / 32) * 4; bits = index % 32; SetMMIO_DWORD_MASK(mmiobase, Reg, ((mode & 0x1) << bits), (0x1 << bits)); // set '1' to select "rising-edge or high-level" , '0' to select "falling-edge or low-level" triggered // set GPIO (input) interrupt trigger mode (level or edge triggerred) Reg = 0x638 + (index / 32) * 4; bits = index % 32; SetMMIO_DWORD_MASK(mmiobase, Reg, ((mode >> 0x1) << bits), (0x1 << bits)); // set '1' to select "edge triggered" , '0' to select "level triggered" // clear GPIO interrupt status before we enable this interrupt enable bit Reg = 0x640 + (index / 32) * 4; bits = index % 32; dwINTStatus = GetMMIO_DWORD(mmiobase, Reg); SetMMIO_DWORD(mmiobase, Reg, (dwINTStatus & (0x1 << bits))); // write-1-clear // set GPIO (input) interrupt enable bit Reg = 0x648 + (index / 32) * 4; bits = index % 32; SetMMIO_DWORD_MASK(mmiobase, Reg, (0x1 << bits), (0x1 << bits)); // set '1' to enable interrupt for this GPIO DBG_MSG1(DBGCFG_GPIO, "EnGPIOInt:%d\n", index); } EXPORT_SYMBOL(EnableGPIOInterrupt); void DisableGPIOInterrupt(UINT8 index) { UINT8* mmiobase; ULONG Reg; UINT8 bits; #if 0 if (index >= SIS326_GPIO_MAXNUM) { DBG_MSG1(DBGCFG_GPIO, "DisableGPIOInt ERR index %d\n", index); return; } #endif mmiobase = pGPIODev->mmio_vbase; // disable GPIO (input) interrupt enable bit Reg = 0x648 + (index / 32) * 4; bits = index % 32; SetMMIO_DWORD_MASK(mmiobase, Reg, (0x0 << bits), (0x1 << bits)); // set '0' to disable interrupt for this GPIO #if 0 // reset "function selection" mux to discard "GPIO" Reg = 0x600 + (index / 16) * 4; bits = (index % 16) * 2; SetMMIO_DWORD_MASK(mmiobase, Reg, (0x0 << bits), (0x3 << bits)); // set '00' to discard "GPIO" #endif DBG_MSG1(DBGCFG_GPIO, "DisableGPIOInt:%d\n", index); } EXPORT_SYMBOL(DisableGPIOInterrupt); void RegGPIOCallBackFun(UINT8 index,void (*function)(void)) { if (index >= SIS326_GPIO_MAXNUM) { DBG_MSG1(DBGCFG_GPIO, "RegGPIOCallBack ERR index %d\n", index); return; } if (function == NULL) { DBG_MSG1(DBGCFG_GPIO, "RegGPIOCallBack ERR func\n"); pGPIODev->callbackfuntable[index].function = 0; return; } pGPIODev->callbackfuntable[index].function = function; DBG_MSG1(DBGCFG_GPIO, "RegGPIOCallBack:%d\n", index); } EXPORT_SYMBOL(RegGPIOCallBackFun); #if 0 void UnRegGPIOCallBackFun(UINT8 index) { if(index >= SIS326_GPIO_MAXNUM) { DBG_MSG1(DBGCFG_GPIO, "UnRegGPIOCallBack ERR index %d\n", index); return; } DisableGPIOInterrupt(index); pGPIODev->callbackfuntable[index].function = 0; DBG_MSG1(DBGCFG_GPIO, "UnRegGPIOCallBack:%d\n", index); } EXPORT_SYMBOL(UnRegGPIOCallBackFun); #endif struct semaphore sisgpio_semaphore; #if 0 UINT32 ClkDetectStateFun95xx(UINT8 ClkDetectIndex) { UINT32 vco; down(&sisgpio_semaphore); switch (ClkDetectIndex) { case cpuclk: writeb(0x10,(UINT8 *)0xbe000113); writeb(0x11,(UINT8 *)0xbe000113); break; case mmioclk: writeb(0x32,(UINT8 *)0xbe000113); writeb(0x33,(UINT8 *)0xbe000113); break; case mclk: writeb(0x30,(UINT8 *)0xbe000113); writeb(0x31,(UINT8 *)0xbe000113); break; case lvdsclk: writeb(0x50,(UINT8 *)0xbe000113); writeb(0x51,(UINT8 *)0xbe000113); break; case x1clk: writeb(0x40,(UINT8 *)0xbe000113); writeb(0x41,(UINT8 *)0xbe000113); break; case mpeg2_eclk: writeb(0x20,(UINT8 *)0xbe000113); writeb(0x21,(UINT8 *)0xbe000113); break; case dvclk: writeb(0xc0,(UINT8 *)0xbe000113); writeb(0xc1,(UINT8 *)0xbe000113); break; case audioclk: writeb(0xa0,(UINT8 *)0xbe000113); writeb(0xa1,(UINT8 *)0xbe000113); break; case audio36mclk: writeb(0xd0,(UINT8 *)0xbe000113); writeb(0xd1,(UINT8 *)0xbe000113); break; case cvd2clk: writeb(0x12,(UINT8 *)0xbe000113); writeb(0x13,(UINT8 *)0xbe000113); break; case hdmiclk: writeb(0x60,(UINT8 *)0xbe000113); writeb(0x61,(UINT8 *)0xbe000113); break; case gclk: writeb(0xe0,(UINT8 *)0xbe000113); writeb(0xe1,(UINT8 *)0xbe000113); break; case tsclk: writeb(0xb0,(UINT8 *)0xbe000113); writeb(0xb1,(UINT8 *)0xbe000113); break; case usb12mclk: writeb(0x80,(UINT8 *)0xbe000113); writeb(0x81,(UINT8 *)0xbe000113); break; case usb30mclk: writeb(0x90,(UINT8 *)0xbe000113); writeb(0x91,(UINT8 *)0xbe000113); break; case usb48mclk: writeb(0x02,(UINT8 *)0xbe000113); writeb(0x03,(UINT8 *)0xbe000113); break; case spiclk: writeb(0xf0,(UINT8 *)0xbe000113); writeb(0xf1,(UINT8 *)0xbe000113); break; case ejtclk: writeb(0x70,(UINT8 *)0xbe000113); writeb(0x71,(UINT8 *)0xbe000113); break; case rosclk: writeb(0x00,(UINT8 *)0xbe000113); writeb(0x01,(UINT8 *)0xbe000113); break; case auxirdrop: writeb(0x22,(UINT8 *)0xbe000113); writeb(0x23,(UINT8 *)0xbe000113); break; case half_hsdclk: writeb(0xc2,(UINT8 *)0xbe000113); writeb(0xc3,(UINT8 *)0xbe000113); break; case vclk_h264: writeb(0x82,(UINT8 *)0xbe000113); writeb(0x83,(UINT8 *)0xbe000113); break; default: DBG_MSG1(DBGCFG_GPIO, "CLK_DET wrong type:%d\n", ClkDetectIndex); up(&sisgpio_semaphore); return 0; } mdelay(5); vco = readl((ULONG *)0xbe0001c0); DBG_MSG1(DBGCFG_GPIO, "clk index %d\trate:%d\n", ClkDetectIndex, vco); up(&sisgpio_semaphore); return vco; } EXPORT_SYMBOL(ClkDetectStateFun95xx); #endif //********************************************************** //* //* Device Opreation //* //********************************************************** #if 0 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,8)) static long GPIOIoctlFun(struct file *pFile,UINT32 cmd, unsigned long arg) #else static INT32 GPIOIoctlFun(struct inode *inode, struct file *pFile,UINT32 cmd, unsigned long arg) #endif { INT32 retval; UINT32 data, addr; ioctl_parameter *parameter; //DBG_MSG1(DBGCFG_GPIO, "WDTIoctlFun"); if (_IOC_TYPE(cmd) != SIS_IOC_MAGIC) { DBG_MSG1(DBGCFG_GPIO, "Invalid cmd"); return -ENOTTY; } retval = 0; switch(cmd) { case GPIO_IOC_CLKDET: parameter = (ioctl_parameter*)arg; if ( copy_from_user(&addr,&(parameter->para1),sizeof(ULONG)) ) { DBG_MSG1(DBGCFG_GPIO,"[GPIO]cpFromUser fail\n"); return -EFAULT; } data = ClkDetectStateFun95xx(addr); if ( copy_to_user(&(parameter->para2),&data,sizeof(ULONG)) ) { DBG_MSG1(DBGCFG_GPIO,"[GPIO]cpToUser fail\n"); return -EFAULT; } break; default: retval = -ENOTTY; break; } return retval; } #endif static irqreturn_t GPIO_ISR(INT32 irq, void* dev_id, struct pt_regs *regs) { UINT8* mmiobase; ULONG dwINTStatus0; ULONG dwINTStatus1; ULONG dwINTEnable0; ULONG dwINTEnable1; ULONG i = 0; if(pGPIODev == NULL) { DBG_MSG1(DBGCFG_GPIO, "GPIO_ISR ERR: No pGPIODev\n"); return IRQ_HANDLED; } mmiobase = pGPIODev->mmio_vbase; DBG_MSG1(DBGCFG_GPIO, "\nGPIO_ISR=>\n"); dwINTStatus0 = GetMMIO_DWORD(mmiobase, 0x640); dwINTStatus1 = GetMMIO_DWORD(mmiobase, 0x644); dwINTEnable0 = GetMMIO_DWORD(mmiobase, 0x648); dwINTEnable1 = GetMMIO_DWORD(mmiobase, 0x64c); SetMMIO_DWORD(mmiobase, 0x640, dwINTStatus0); // write-1-clear SetMMIO_DWORD(mmiobase, 0x644, dwINTStatus1); // write-1-clear while(dwINTStatus0 != 0) { // check each GPIO interrupt status if((dwINTStatus0 & 0x1) && (dwINTEnable0 & 0x1)) { if(pGPIODev->callbackfuntable[i].function != NULL) { pGPIODev->callbackfuntable[i].function(); // handle each GPIO interrupt } else{ //NULL function DisableGPIOInterrupt(i); } DBG_MSG1(DBGCFG_GPIO, "GPIO_ISR: GPIO%d INT triggered\n", (UINT32)i); } dwINTStatus0 >>= 1; dwINTEnable0 >>= 1; i++; } i = 32; while(dwINTStatus1 != 0) { // check each GPIO interrupt status if((dwINTStatus1 & 0x1) && (dwINTEnable1 & 0x1)) { if(pGPIODev->callbackfuntable[i].function != NULL) { pGPIODev->callbackfuntable[i].function(); // handle each GPIO interrupt } else{ //NULL function DisableGPIOInterrupt(i); } DBG_MSG1(DBGCFG_GPIO, "GPIO_ISR: GPIO%d INT triggered\n", (UINT32)i); } dwINTStatus1 >>= 1; dwINTEnable1 >>= 1; i++; } DBG_MSG1(DBGCFG_GPIO, "\nGPIO_ISR<=\n"); return IRQ_HANDLED; } static void mips_GPIO_dispatch(struct pt_regs *regs) { do_IRQ(IRQ_Peripheral); } static struct irqaction gpio_irqaction = { .handler = (irq_handler_t)&GPIO_ISR, .flags = IRQF_DISABLED , .name = "gpio", }; #if (CONFIG_CHIPID == 0x6710) static void mips_memout_range_dispatch(struct pt_regs *regs) { unsigned int *sp,*gp; __asm__ __volatile__("move\t%0,$28" : "=r" (gp)); sp = (unsigned int *)gp[18]; printk("<0>$0\t:%08x %08x %08x %08x\n",0,sp[7],sp[8],sp[9]); printk("<0>$4\t:%08x %08x %08x %08x\n",sp[10],sp[11],sp[12],sp[13]); printk("<0>$8\t:%08x %08x %08x %08x\n",sp[14],sp[15],sp[16],sp[17]); printk("<0>$12\t:%08x %08x %08x %08x\n",sp[18],sp[19],sp[20],sp[21]); printk("<0>$16\t:%08x %08x %08x %08x\n",sp[22],sp[23],sp[24],sp[25]); printk("<0>$20\t:%08x %08x %08x %08x\n",sp[26],sp[27],sp[28],sp[29]); printk("<0>$24\t:%08x %08x\n",sp[30],sp[31]); printk("<0>$28\t:%08x %08x %08x %08x\n",sp[34],sp[35],sp[36],sp[37]); printk("<0>Hi\t:%08x\n",sp[39]); printk("<0>Lo\t:%08x\n",sp[40]); printk("<0>epc\t:%08x\n",sp[43]); printk("<0>ra\t:%08x\n",sp[37]); printk("<0>Status\t:%08x\n",sp[38]); printk("<0>Cause\t:%08x\n",sp[42]); printk("Process word (pid: %d, threadinfo=%08x, task=%08x %s)\n",current->pid,(unsigned int)gp,(unsigned int)current,current->comm); *(volatile unsigned char *)0xbe010034 = *(volatile unsigned char *)0xbe010034; dump_stack(); while(1); } static void enable_memout_range_irq(void) { set_vi_handler(5, (vi_handler_t)mips_memout_range_dispatch); do { *(volatile unsigned char *)0xbe010034 = *(volatile unsigned char *)0xbe010034; } while(*(volatile unsigned char *)0xbe010034&0x1); enable_irq(5); } #endif #if 0 static UINT32 VGA_ON = 1; // record the VGA V-sync status static irqreturn_t VGA_ISR(INT32 irq, void* dev_id, struct pt_regs *regs) { UINT8* mmiobase; ULONG dwINTStatus0; if(pGPIODev == NULL) { DBG_MSG1(DBGCFG_GPIO, "VGA_ISR ERR: No pGPIODev\n"); return IRQ_HANDLED; } mmiobase = pGPIODev->mmio_vbase; DBG_MSG1(DBGCFG_GPIO, "\nVGA_ISR=>\n"); // get VGA-WakeUp/Disconnect register original value dwINTStatus0 = GetMMIO_DWORD(mmiobase, 0x700); // process the VGA-WakeUp/Disconnect interrupts and clear (w1c) the interrupt status if((dwINTStatus0 & (0x3 << 29)) == (0x3 << 29)) // 2010. gaia fixed 365 queer issue { VGA_ON = 1; noticekmf(KMF2UMF_EVID_VGA, KMF2UMF_EVTYPE_VGA_PORTSTATUS,(void *)&VGA_ON, 1); DBG_MSG1(DBGCFG_GPIO, "VGA_ISR: WakeUp INT triggered\n"); // disable VGA-WakeUp interrupt, // clear VGA-WakeUp/Disconnect interrupt status once, // and enable VGA-Disconnect interrupt SetMMIO_DWORD(mmiobase, 0x700, ((dwINTStatus0 & ~(0x1 << 31)) | (0x2a << 24))); } else if((dwINTStatus0 & (0x3 << 25)) == (0x3 << 25)) // 2010. gaia fixed 365 queer issue { VGA_ON = 0; noticekmf(KMF2UMF_EVID_VGA, KMF2UMF_EVTYPE_VGA_PORTSTATUS,(void *)&VGA_ON, 1); DBG_MSG1(DBGCFG_GPIO, "VGA_ISR: Disconnect INT triggered\n"); // disable VGA-Disconnect interrupt, // clear VGA-WakeUp/Disconnect interrupt status once, // and enable VGA-WakeUp interrupt SetMMIO_DWORD(mmiobase, 0x700, ((dwINTStatus0 & ~(0x1 << 27)) | (0xa2 << 24))); } // TODO: We should implement a function to tell the UMF to open or close the panel if it's needed ... // TODO: Test and check the VGA V-sync detect range settings later ... DBG_MSG1(DBGCFG_GPIO, "\nVGA_ISR<=\n"); return IRQ_HANDLED; } static void mips_VGA_dispatch(struct pt_regs *regs) { do_IRQ(IRQ_VGAWakeUp); } static struct irqaction vga_irqaction = { .handler = (irq_handler_t)&VGA_ISR, .flags = IRQF_DISABLED , .name = "vgawake", }; void VGAWakeUpInit(void) { UINT8* mmiobase; ULONG W_Data; if(pGPIODev == NULL) { DBG_MSG1(DBGCFG_GPIO, "VGAWakeUpInit ERR\n"); return; } mmiobase = pGPIODev->mmio_vbase; // get VGA-WakeUp/Disconnect register original value W_Data = GetMMIO_DWORD(mmiobase, 0x700); // clear (w1c) the interrupt status and enable VGA-WakeUp/Disconnect functions SetMMIO_DWORD(mmiobase, 0x700, (W_Data & 0x33ffffff)); // disable VGA-WakeUp/Disconnect functions once SetMMIO_DWORD(mmiobase, 0x700, (W_Data | (0xee << 24) | (0xff << 8))); // enable VGA-WakeUp/Disconnect functions and clear (w1c) the interrupt status, and set the VGA-WakeUp Top-Range-Number to 0xFF (work-around for SiS328 A0) #if (1) SetMMIO_DWORD_MASK(mmiobase, 0x70c, 0x10000000, 0x10000000); // set VGA interrupt selection 0x70c[28] 1: To detect vsync or hsync #endif // 2010.07.13 enable ISR after set VGA register to avoid INT trigger before Set regsister and hold the system set_vi_handler(IRQ_VGAWakeUp, (vi_handler_t)mips_VGA_dispatch); setup_irq(IRQ_VGAWakeUp, &vga_irqaction); DBG_MSG1(DBGCFG_GPIO, "VGA-WakeUp/Disconnect En\n"); } void VGAWakeUpExit(void) { UINT8* mmiobase; ULONG W_Data; if(pGPIODev == NULL) { DBG_MSG1(DBGCFG_GPIO, "VGAWakeUpExit ERR\n"); return; } mmiobase = pGPIODev->mmio_vbase; // get VGA-WakeUp/Disconnect register original value W_Data = GetMMIO_DWORD(mmiobase, 0x700) & 0x33ffffff; // disable VGA-WakeUp/Disconnect functions and clear (w1c) the interrupt status SetMMIO_DWORD(mmiobase, 0x700, W_Data); // disable VGA-WakeUp/Disconnect functions SetMMIO_DWORD(mmiobase, 0x700, (W_Data | (0x22 << 24))); // clear (w1c) the interrupt status // free the VGA-WakeUp/Disconnect IRQ and ISR free_irq(IRQ_VGAWakeUp, pGPIODev); // TODO: Why can't we use free_irq(... , NULL) ?? DBG_MSG1(DBGCFG_GPIO, "VGA-WakeUp/Disconnect Disabled\n"); } #endif /* =============================================================================== Customer Driver ocde ================================================================================= */ #if HWEMIFunction /* EMI hw function, changed PLL to reduece EMI */ #if (CONFIG_CHIPID != 0x330) void EMI_DRAM_SSC(UINT8 level, void *ssc_value_188, void *ssc_value_1a8, void *ssc_value_Magic_Number){ #else void EMI_DRAM_SSC(UINT8 level){ #endif volatile UINT32 SDM_MAX, SDM_INC, reg1a8; volatile UINT32 reg188, sample_rate; volatile UINT8 FEBDIV; // SDM_MAX = ROUND(32768 * (fdev * 0.000001) * Fmain, 0) // SDM_INC = ROUND(4*SDM_MAX*ftri/(sample rate*1000), 1) // Fmain = (R_MEM_PLL_MUL[7:0]+1) / 2 // 0xbe0001a4[7:0] #if (CONFIG_CHIPID == 0x6710) volatile UINT8 i, tmp; FEBDIV = *(volatile UINT8 *)(0xbe140053); #else FEBDIV = *(volatile UINT8 *)(0xbe0001a4); #endif #if (CONFIG_CHIPID == 0x131) || (CONFIG_CHIPID == 0x8506)|| (CONFIG_CHIPID == 0x6710) SDM_MAX = 25000 * (FEBDIV + 1) / 2; // SDM_MAX = 25000 * Fmain #else SDM_MAX = 32768 * (FEBDIV + 1) / 2; // SDM_MAX = 32768 * Fmain #endif #if (CONFIG_CHIPID == 0x6710) reg188 = 0; reg1a8 = readl((ULONG *)(0xbe140058)); #else reg188 = *(volatile ULONG *)(0xbe000188); reg1a8 = readl((ULONG *)(0xbe0001a8)); reg188 &= 0xFFFFF800; // clear SDM_INC[10:0], reserved[11]:x reg188 |= 0xF000; // set SDM_TYPE_SEL[15], SDM_SPREAD[14], SDM_DOWNSPREAD[13], and SDM_RSTN[12] #endif // SDM_MAX = 32768 * Fmain * (fdev/1000) switch( level ) { case 0: reg188 &= 0xFFFF0000; #if (CONFIG_CHIPID == 0x6710) writew(0, (void *)0xbe14005a); #else writew(reg188, (void *)0xbe000188); #endif goto store_to_flash; case 1: SDM_MAX = SDM_MAX * 1; // fdev = 1000 break; case 2: SDM_MAX = SDM_MAX * 2; // fdev = 2000 break; case 3: SDM_MAX = SDM_MAX * 3; // fdev = 3000 break; case 4: SDM_MAX = SDM_MAX * 4; // fdev = 4000 break; case 5: SDM_MAX = SDM_MAX * 5; // fdev = 5000 break; default: #if (CONFIG_CHIPID == 0x6710) writew(0, (void *)0xbe14005a); #else writew(reg188, (void *)0xbe000188); #endif goto store_to_flash; } SDM_MAX = SDM_MAX / 1000; // SDM_MAX = 32768 * Fmain * (fdev * 0.000001) #if (CONFIG_CHIPID == 0x533) || (CONFIG_CHIPID == 0x131) || (CONFIG_CHIPID == 0x8506) sample_rate = *(volatile UINT8 *)(0xbe0001a5) & 0x01; // 0xbe0001a4[8] #elif (CONFIG_CHIPID == 0x6710) sample_rate = *(volatile UINT8 *)(0xbe140054) & 0x03; #else sample_rate = *(volatile UINT8 *)(0xbe0001a5) & 0x1f; // 0xbe0001a4[12:8] #endif #if (CONFIG_CHIPID == 0x6710) tmp = 1; for (i=0; i < sample_rate; i++) tmp *= 2; sample_rate = 24000 / tmp; #else sample_rate = 24576 / (sample_rate + 1); // sample rate * 1000 #endif SDM_INC = (SDM_MAX * 4 * 33 ) / sample_rate; // ftri=33.333, reg188 |= SDM_INC; DBG_MSG1(DBGCFG_GPIO, "SDM_MAX:%08x\tSDM_INC:%08x\treg188:%04x\n", SDM_MAX, SDM_INC, reg188); reg1a8 &= 0xFFFE0000; // Clear SDM_MAX[16:0] reg1a8 |= SDM_MAX; store_to_flash: #if (CONFIG_CHIPID != 0x330) memcpy(ssc_value_188, (const void *)®188, 2); memcpy(ssc_value_1a8, (const void *)®1a8, 2); *(UINT32 *)ssc_value_Magic_Number = 0x28825252; DBG_MSG1(DBGCFG_GPIO,"reg188:%08x\treg1a8:%08x\n", reg188, reg1a8); #endif #if (CONFIG_CHIPID == 0x6710) if (reg188) { reg1a8 = (reg1a8&0x0001FFFF) | (reg188<<17) | 0xF0000000; writel(reg1a8, (void *)(0xbe140058)); } else { writel(reg1a8&0x0001FFFF, (void *)(0xbe140058)); } #else writel(reg1a8, (void *)(0xbe0001a8)); writel(reg188, (void *)(0xbe000188)); #endif DBG_MSG1(DBGCFG_GPIO, "reg188:%08x\treg1a8:%08x\n", readl((ULONG *)(0xbe000188)), readl((ULONG *)(0xbe0001a8))); return; } EXPORT_SYMBOL(EMI_DRAM_SSC); #endif static INT32 GPIOOpenFun(struct inode *inode, struct file *pFile) { //DBG_MSG1(DBGCFG_GPIO, "[GPIO] GPIOOpenFun ==> \n"); pFile->private_data = pGPIODev; //DBG_MSG1(DBGCFG_GPIO, "[GPIO] GPIOOpenFun <==\n"); return 0; } #if 0 static INT32 GPIOCloseFun(struct inode *inode, struct file *pFile) { //DBG_MSG1(DBGCFG_GPIO, "[GPIO] GPIOCloseFun ==>\n"); //DBG_MSG1(DBGCFG_GPIO, "[GPIO] GPIOCloseFun <==\n"); return 0; } #endif GPIOMAINConfig_t *gGPIOTab = NULL; UINT32 gTableSize = 0; UINT8 GPIOGetValue(UINT8 TabIndex) { UINT8 Level; if (TabIndex >= gTableSize) { DBG_MSG1(DBGCFG_GPIO,"Pin not in GPIOTab\n"); return GPIO_LEVEL_TRI; } if (gGPIOTab[TabIndex].Index >= GPIO_NOT_USE) { DBG_MSG1(DBGCFG_GPIO,"GPIOTab[%d], not use\n", TabIndex); return GPIO_LEVEL_TRI; } switch(gGPIOTab[TabIndex].MainAction) { case GPIO_INPUT: Level = GPIOReadFun(gGPIOTab[TabIndex].Index); break; default: DBG_MSG1(DBGCFG_GPIO,"GPIOTab[%d], not input\n", TabIndex); return GPIO_LEVEL_TRI; } return Level; } UINT8 GPIOSetValue(UINT8 TabIndex, GPIOState_t State) { if (TabIndex >= gTableSize) { DBG_MSG1(DBGCFG_GPIO,"Pin not in GPIOTab\n"); return 1; } if (gGPIOTab[TabIndex].Index >= GPIO_NOT_USE) { DBG_MSG1(DBGCFG_GPIO,"GPIOTab[%d], not use\n", TabIndex); return 1; } switch(gGPIOTab[TabIndex].MainAction) { case GPIO_OUTPUT: if( State == GPIO_FUNC_ONLEVEL) { if (gGPIOTab[TabIndex].MainLevelInvert) { GPIOWriteFun(gGPIOTab[TabIndex].Index, GPIO_LEVEL_LOW); } else { GPIOWriteFun(gGPIOTab[TabIndex].Index, GPIO_LEVEL_HIGH); } } else if (( State == GPIO_FUNC_OFFLEVEL)) { if (gGPIOTab[TabIndex].MainLevelInvert) { GPIOWriteFun(gGPIOTab[TabIndex].Index, GPIO_LEVEL_HIGH); } else { GPIOWriteFun(gGPIOTab[TabIndex].Index, GPIO_LEVEL_LOW); } } else { DBG_MSG1(DBGCFG_GPIO, "GPIO_OUTPUT ERR GPIOTab[%d]\n", TabIndex); return 1; } break; case GPIO_OPEN_DRAIN: if( State == GPIO_FUNC_ONLEVEL) GPIOReadFun(gGPIOTab[TabIndex].Index); else if ( State == GPIO_FUNC_OFFLEVEL) GPIOWriteFun(gGPIOTab[TabIndex].Index, (UINT8)0); else { DBG_MSG1(DBGCFG_GPIO, "GPIO_OPEN_DRAIN ERR GPIOTab[%d]\n", TabIndex); return 1; } break; default: DBG_MSG1(DBGCFG_GPIO,"ERR GPIOTab[%d]\n", TabIndex); return 1; } return 0; } UINT8 GPIOSetValueByPinNumber(UINT8 PinNum, GPIOState_t State) { UINT8 TabIndex = 0; UINT8 ret = 1; /* Find GPIO table index whick what to control */ if (gTableSize == 0) { DBG_MSG1(DBGCFG_GPIO,"GPIO TabSize=0\n"); } if (PinNum >= GPIO_NOT_USE) { return 1; } for (TabIndex = 0; TabIndex < gTableSize; TabIndex++) { if (gGPIOTab[TabIndex].Index == PinNum) { break; } } ret = GPIOSetValue(TabIndex, State); return ret; } UINT8 GPIOSetValueByPinFunc(GPIODriverFunc_t PinFunc, GPIOState_t State) { UINT8 TabIndex = 0; UINT8 ret = 1; /* Find GPIO table index whick what to control */ for (TabIndex = 0; TabIndex < gTableSize; TabIndex++) { if (gGPIOTab[TabIndex].DriverFunc == PinFunc) { break; } } if (TabIndex >= gTableSize) { return 1; } /* Check GPIO table index */ if (gGPIOTab[TabIndex].DriverFunc == GPIO_PIN_DRIVER_IGNORE ) { DBG_MSG1(DBGCFG_GPIO, "GPIO_DRIVER_IGNORE GPIOTab[%d]\n", TabIndex); return 0; } ret = GPIOSetValue(TabIndex, State); return ret; } UINT8 GPIOGetValueByPinNumber(UINT8 PinNum) { UINT8 Level; UINT8 TabIndex = 0; /* Find GPIO table index whick what to control */ for (TabIndex = 0; TabIndex < gTableSize; TabIndex++) { if (gGPIOTab[TabIndex].Index == PinNum) { break; } } Level = GPIOGetValue(TabIndex); return Level; } UINT8 GPIOGetValueByPinFunc(GPIODriverFunc_t PinFunc) { UINT8 Level; UINT8 TabIndex = 0; /* Find GPIO table index whick what to control */ for (TabIndex = 0; TabIndex < gTableSize; TabIndex++) { if (gGPIOTab[TabIndex].DriverFunc == PinFunc) { break; } } if (TabIndex >= gTableSize) { return GPIO_LEVEL_TRI; } /* Check GPIO table index */ if (gGPIOTab[TabIndex].DriverFunc == GPIO_PIN_DRIVER_IGNORE ) { DBG_MSG1(DBGCFG_GPIO, "GPIO_DRIVER_IGNORE GPIOTab[%d]\n", TabIndex); return GPIO_LEVEL_TRI; } Level = GPIOGetValue(TabIndex); return Level; } UINT32 GPIOSetDefaultValue(void) { UINT8 TabIndex = 0; /* Find GPIO table index whick what to control */ for (TabIndex = 0; TabIndex < gTableSize; TabIndex++) { if (gGPIOTab[TabIndex].MainAction == GPIO_OUTPUT) { GPIOWriteFun(gGPIOTab[TabIndex].Index, gGPIOTab[TabIndex].MainInitLevel); } } return 0; } void echo_Handler(INT8 *buf, size_t size) { UINT8 gpioindex; UINT8 gpiovalue; UINT8 i; ULONG tmp,tmp1,tmp2; switch(buf[0]) { case 'g': if(buf[1]=='r'){ //echo gr00 gpioindex = (buf[2]-'0')*10+(buf[3]-'0'); if (gpioindex < S2IC_GPIO_MAXNUM) { gpiovalue = GPIOReadFun(gpioindex); printk(KERN_EMERG "GPIORd(%d)=%d\n",gpioindex, gpiovalue); } } if(buf[1]=='p'){ //echo gp001 //push pull gpio gpioindex = (buf[2]-'0')*10+(buf[3]-'0'); gpiovalue = (buf[4]-'0'); if (gpioindex < S2IC_GPIO_MAXNUM) { GPIOWriteFun(gpioindex, gpiovalue); } printk(KERN_EMERG "GPIOWr ok\n"); //DBG_MSG1(DBGCFG_GPIO,"GPIOWriteFun(%d, %d)\n",gpioindex, gpiovalue); } if(buf[1]=='o'){ //echo go001 //open drain gpioindex = (buf[2]-'0')*10+(buf[3]-'0'); gpiovalue = (buf[4]-'0'); GPIOOpenDrainWriteFun(gpioindex, gpiovalue); printk(KERN_EMERG "GPIOOpenDrainWr ok\n"); //DBG_MSG1(DBGCFG_GPIO,"GPIOOpenDrainWriteFun(%d, %d)\n",gpioindex, gpiovalue); } if (buf[1]=='t') { // echo gt00 // try read gpioindex = (buf[2]-'0')*10+(buf[3]-'0'); gpiovalue = GPIOTryRead(gpioindex); printk(KERN_EMERG "GPIOTryRd(%d)=%d\n",gpioindex, gpiovalue); } break; case 'd': //echo d for(i=0;i<64;i++){ tmp2 = readl((ULONG *)(0xbe0f0600+(i/16)*4)); tmp = readl((ULONG *)(0xbe0f0618+(i/32)*4)); tmp1 = readl((ULONG *)(0xbe0f0610+(i/32)*4)); printk(KERN_EMERG "%2d\t%c\tI/O:%d\tVal:%d\n",(INT32)i ,( ((tmp2>>i*2) & 0x3) == 0x01 )?'Y':'N' ,(INT32)((tmp >> i)&0x1), (INT32)((tmp1 >> i)&0x1)); } break; case 'c': if ( buf[1]=='u' ) { // echo cu?? gpioindex = (buf[2]-'0')*0x10+(buf[3]-'0'); CustomLedFun(gpioindex); //DBG_MSG1(DBGCFG_GPIO,"SetCustomLed:%d\n", gpioindex); } break; } } static INT32 EchoWriteFun(struct file *file, const INT8 __user * buf, size_t size, loff_t * ppos) { size_t in_sz = 0x100; INT8 *inbuf = drv_kmalloc(sizeof(GPIO_DEV), GFP_KERNEL, MODULEID_GPIO); if(inbuf) { in_sz = (size < in_sz)?size:in_sz; if(copy_from_user(inbuf,buf,in_sz) == 0) { echo_Handler(inbuf,in_sz); } drv_kfree(inbuf, MODULEID_GPIO); } return size; } static struct file_operations GPIOFops = { .owner = THIS_MODULE, // .read = EchoReadFun, .write = EchoWriteFun, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,8)) // .unlocked_ioctl = GPIOIoctlFun, #else // .ioctl = GPIOIoctlFun, #endif .open = GPIOOpenFun, // .release = GPIOCloseFun, }; INT32 GPIOInit(void) { INT32 err; dev_t devno; UINT8 TabIndex; /* 2013.10 disable YPP debug for gpio 43 44 */ SetMMIO_DWORD_MASK((UINT8*)0xbe000038, 0, (1<<6), (1<<6)); sema_init(&sisgpio_semaphore, 1); #if 1 pGPIODev = (PGPIO_DEV)kmalloc(sizeof(GPIO_DEV), GFP_KERNEL); #else pGPIODev = (PGPIO_DEV)drv_kmalloc(sizeof(GPIO_DEV), GFP_KERNEL, MODULEID_GPIO); #endif memset(pGPIODev, 0, sizeof(GPIO_DEV)); //DBG_MSG1(DBGCFG_GPIO, "[GPIO] =>GPIOInit\n"); pGPIODev->mmio_vbase = (UINT8*)MMIOBASE_Peripheral; pGPIODev->irq = IRQ_Peripheral; set_vi_handler(IRQ_Peripheral, (vi_handler_t)mips_GPIO_dispatch); setup_irq(IRQ_Peripheral, &gpio_irqaction); #if (CONFIG_CHIPID == 0x6710) enable_memout_range_irq(); #endif ////////////////////////////////////////////// devno = MKDEV(SISGPIO_DEV_MAJOR, 0); err = register_chrdev_region(devno, 1, "sisgpio"); if(err) { DBG_MSG1(DBGCFG_GPIO, "GPIOInit Failed\n"); return -EIO; } cdev_init(&pGPIODev->cdev, &GPIOFops); pGPIODev->cdev.owner = THIS_MODULE; err = cdev_add(&pGPIODev->cdev, devno, 1); if(err) { DBG_MSG1(DBGCFG_GPIO, "GPIOInit Failed\n"); return -EIO; } // VGAWakeUpInit(); // enable VGA-WakeUp/Disconnect functions // initial LED FLICK led_flick_value = 0; led_flick_status = 0; led_flick_flag = 0; pLED_FLICK_dev = &LED_FLICK_dev; memset(pLED_FLICK_dev,0,sizeof(LED_FLICK_DEV)); INIT_DELAYED_WORK(&pLED_FLICK_dev->LED_FLICK_Work, (void *)LED_FLICK_fun); GPIOWriteValueL = GetMMIO_DWORD(pGPIODev->mmio_vbase, 0x610); GPIOWriteValueH = GetMMIO_DWORD(pGPIODev->mmio_vbase, 0x614); GetCustomerData(gpiotablename, (void *)&gGPIOTab, &gTableSize); gTableSize /= sizeof(GPIOMAINConfig_t); //DBG_MSG1(DBGCFG_GPIO, "[GPIO] GPIOInit <= \n"); for (TabIndex = 0; TabIndex < gTableSize; TabIndex++) { if (gGPIOTab[TabIndex].DriverFunc == GPIO_PIN_LED_G_PWM) { led_g_pwm_pin = gGPIOTab[TabIndex].Index; continue; } if (gGPIOTab[TabIndex].DriverFunc == GPIO_PIN_LED_R_PWM) { led_r_pwm_pin = gGPIOTab[TabIndex].Index; } } return 0; } #if 0 void GPIOExit(void) { dev_t devno = MKDEV(SISGPIO_DEV_MAJOR, 0); //DBG_MSG1(DBGCFG_GPIO, "[GPIO] =>GPIOExit\n"); VGAWakeUpExit(); // disable VGA-WakeUp/Disconnect functions free_irq(IRQ_Peripheral, pGPIODev); //sisgpio_exit(pGPIODev); cdev_del(&pGPIODev->cdev); unregister_chrdev_region(devno, 1); #if 1 kfree(pGPIODev); #else drv_kfree(pGPIODev, MODULEID_GPIO); #endif pGPIODev = NULL; //DBG_MSG1(DBGCFG_GPIO, "[GPIO] GPIOExit <= \n"); } #endif #ifndef INIT_BY_KMF module_init (GPIOInit); module_exit (GPIOExit); #endif MODULE_LICENSE("Dual BSD/GPL");