/* * Copyright c Realtek Semiconductor Corporation, 2008 * All rights reserved. * * Program : GPIO Driver * Abstract : * Author : */ #ifndef __BOOTCODE__ #include #endif #include "gpio.h" /*==================== FOR RTL8972B Family ==================*/ #ifdef CONFIG_RTK_VOIP_DRIVERS_PCM8972B_FAMILY enum GPIO_FUNC { GPIO_FUNC_DEDICATE, GPIO_FUNC_DIRECTION, GPIO_FUNC_DATA, GPIO_FUNC_INTERRUPT_STATUS, GPIO_FUNC_INTERRUPT_ENABLE, GPIO_FUNC_MAX, }; //******************************************* GPIO control static uint32 regGpioControl[] = { GPABCDCNR, /* Port A */ GPABCDCNR, /* Port B */ GPABCDCNR, /* Port C */ GPABCDCNR, /* Port D */ GPEFGHCNR, /* Port E */ GPEFGHCNR, /* Port F */ GPEFGHCNR, /* Port G */ GPEFGHCNR, /* Port H */ }; static uint32 bitStartGpioControl[] = { 0, /* Port A */ 8, /* Port B */ 16, /* Port C */ 24, /* Port D */ 0, /* Port E */ 8, /* Port F */ 16, /* Port G */ 24, /* Port H */ }; //******************************************* GPIO Share pin config #if 0 static uint32 GpioShare_data[] = { 0xFF1F0FFF, 0x0000007f, }; #endif #define SHAREPIN_REGISTER 0xB8000040 #define SET_BIT(x) (1<> (pin*2+bitStartGpioInterruptEnable[port]) ) & (uint32)0x3; break; case GPIO_FUNC_INTERRUPT_STATUS: GPIO_PRINT(5, "[%s():%d] regGpioInterruptStatus[port]=0x%08x bitStartGpioInterruptEnable[port]=%d\n", __FUNCTION__, __LINE__, regGpioInterruptStatus[port], bitStartGpioInterruptStatus[port] ); if ( REG32(regGpioInterruptStatus[port]) & ( (uint32)1 << (pin+bitStartGpioInterruptStatus[port]) ) ) return 1; else return 0; break; case GPIO_FUNC_MAX: printk("Wrong GPIO function\n"); break; } return 0xffffffff; } /* @func int32 | _setGpio | abstract GPIO registers @parm enum GPIO_FUNC | func | control/data/interrupt register @parm enum GPIO_PORT | port | GPIO port @parm uint32 | pin | pin number @parm uint32 | data | value @rvalue NONE @comm This function is for internal use only. You don't need to care what register address of GPIO is. This function abstracts these information. */ static void _setGpio( enum GPIO_FUNC func, enum GPIO_PORT port, uint32 pin, uint32 data ) { GPIO_PRINT(4, "[%s():%d] func=%d port=%d pin=%d data=%d\n", __FUNCTION__, __LINE__, func, port, pin, data ); switch( func ) { case GPIO_FUNC_DEDICATE: GPIO_PRINT(5, "[%s():%d] regGpioControl[port]=0x%08x bitStartGpioControl[port]=%d\n", __FUNCTION__, __LINE__, regGpioControl[port], bitStartGpioControl[port] ); if ( data ) REG32(regGpioControl[port]) |= (uint32)1 << (pin+bitStartGpioControl[port]); else { REG32(regGpioControl[port]) &= ~((uint32)1 << (pin+bitStartGpioControl[port])); //printk("oldsharepin_register=%x", REG32(SHAREPIN_REGISTER)); REG32(SHAREPIN_REGISTER) |= GpioShare_setting[(port<<3)|pin]; //printk("newsharepin_register=%x", REG32(SHAREPIN_REGISTER)); //GPIO_PRINT(5,"GPIOSET(%x)",(port<<3)|pin); //printk("[%d,%d]GPIOSET(%x)", port, pin,(port<<3)|pin); } break; case GPIO_FUNC_DIRECTION: GPIO_PRINT(5, "[%s():%d] regGpioDirection[port]=0x%08x bitStartGpioDirection[port]=%d\n", __FUNCTION__, __LINE__, regGpioDirection[port], bitStartGpioDirection[port] ); if ( data ) REG32(regGpioDirection[port]) |= (uint32)1 << (pin+bitStartGpioDirection[port]); else REG32(regGpioDirection[port]) &= ~((uint32)1 << (pin+bitStartGpioDirection[port])); break; case GPIO_FUNC_DATA: GPIO_PRINT(5, "[%s():%d] regGpioData[port]=0x%08x bitStartGpioData[port]=%d\n", __FUNCTION__, __LINE__, regGpioData[port], bitStartGpioData[port] ); if ( data ) REG32(regGpioData[port]) |= (uint32)1 << (pin+bitStartGpioData[port]); else REG32(regGpioData[port]) &= ~((uint32)1 << (pin+bitStartGpioData[port])); break; case GPIO_FUNC_INTERRUPT_ENABLE: GPIO_PRINT(5, "[%s():%d] regGpioInterruptEnable[port]=0x%08x bitStartGpioInterruptEnable[port]=%d\n", __FUNCTION__, __LINE__, regGpioInterruptEnable[port], bitStartGpioInterruptEnable[port] ); REG32(regGpioInterruptEnable[port]) &= ~((uint32)0x3 << (pin*2+bitStartGpioInterruptEnable[port])); REG32(regGpioInterruptEnable[port]) |= (uint32)data << (pin*2+bitStartGpioInterruptEnable[port]); break; case GPIO_FUNC_INTERRUPT_STATUS: GPIO_PRINT(5, "[%s():%d] regGpioInterruptStatus[port]=0x%08x bitStartGpioInterruptStatus[port]=%d\n", __FUNCTION__, __LINE__, regGpioInterruptStatus[port], bitStartGpioInterruptStatus[port] ); if ( data ) REG32(regGpioInterruptStatus[port]) |= (uint32)1 << (pin+bitStartGpioInterruptStatus[port]); else REG32(regGpioInterruptStatus[port]) &= ~((uint32)1 << (pin+bitStartGpioInterruptStatus[port])); break; case GPIO_FUNC_MAX: printk("Wrong GPIO function\n"); break; } } /* @func int32 | _rtl8972B_initGpioPin | Initiate a specifed GPIO port. @parm uint32 | gpioId | The GPIO port that will be configured @parm enum GPIO_PERIPHERAL | dedicate | Dedicated peripheral type @parm enum GPIO_DIRECTION | direction | Data direction, in or out @parm enum GPIO_INTERRUPT_TYPE | interruptEnable | Interrupt mode @rvalue SUCCESS | success. @rvalue FAILED | failed. Parameter error. @comm This function is used to initialize GPIO port. */ int32 _rtl8972B_initGpioPin( uint32 gpioId, enum GPIO_CONTROL dedicate, enum GPIO_DIRECTION direction, enum GPIO_INTERRUPT_TYPE interruptEnable ) { uint32 port = GPIO_PORT( gpioId ); uint32 pin = GPIO_PIN( gpioId ); if ( port >= GPIO_PORT_MAX ) return FAILED; if ( pin >= 8 ) return FAILED; switch ( dedicate ) { case GPIO_CONT_GPIO: _setGpio( GPIO_FUNC_DEDICATE, port, pin, 0 ); break; case GPIO_CONT_PERI: _setGpio( GPIO_FUNC_DEDICATE, port, pin, 1 ); break; } _setGpio( GPIO_FUNC_DIRECTION, port, pin, direction ); _setGpio( GPIO_FUNC_INTERRUPT_ENABLE, port, pin, interruptEnable ); return SUCCESS; } /* @func int32 | _rtl8972B_getGpioDataBit | Get the bit value of a specified GPIO ID. @parm uint32 | gpioId | GPIO ID @parm uint32* | data | Pointer to store return value @rvalue SUCCESS | success. @rvalue FAILED | failed. Parameter error. @comm */ int32 _rtl8972B_getGpioDataBit( uint32 gpioId, uint32* pData ) { uint32 port = GPIO_PORT( gpioId ); uint32 pin = GPIO_PIN( gpioId ); if ( port >= GPIO_PORT_MAX ) return FAILED; if ( pin >= 8 ) return FAILED; if ( pData == NULL ) return FAILED; *pData = _getGpio( GPIO_FUNC_DATA, port, pin ); GPIO_PRINT(3, "[%s():%d] (port=%d,pin=%d)=%d\n", __FUNCTION__, __LINE__, port, pin, *pData ); return SUCCESS; } /* @func int32 | _rtl8972B_setGpioDataBit | Set the bit value of a specified GPIO ID. @parm uint32 | gpioId | GPIO ID @parm uint32 | data | Data to write @rvalue SUCCESS | success. @rvalue FAILED | failed. Parameter error. @comm */ int32 _rtl8972B_setGpioDataBit( uint32 gpioId, uint32 data ) { uint32 port = GPIO_PORT( gpioId ); uint32 pin = GPIO_PIN( gpioId ); if ( port >= GPIO_PORT_MAX ) return FAILED; if ( pin >= 8 ) return FAILED; GPIO_PRINT(3, "[%s():%d] (port=%d,pin=%d)=%d\n", __FUNCTION__, __LINE__, port, pin, data ); _setGpio( GPIO_FUNC_DATA, port, pin, data ); return SUCCESS; } #endif //CONFIG_RTK_VOIP_DRIVERS_PCM8972B_FAMILY