summaryrefslogtreecommitdiffstats
path: root/target/linux/realtek/files/drivers/serial
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/realtek/files/drivers/serial')
-rw-r--r--target/linux/realtek/files/drivers/serial/8250_sc16is7x0.c389
-rw-r--r--target/linux/realtek/files/drivers/serial/gpio.h98
-rw-r--r--target/linux/realtek/files/drivers/serial/gpio_8972b.c526
-rw-r--r--target/linux/realtek/files/drivers/serial/gpio_8972b.h195
-rw-r--r--target/linux/realtek/files/drivers/serial/i2c.c305
-rw-r--r--target/linux/realtek/files/drivers/serial/i2c.h42
6 files changed, 1555 insertions, 0 deletions
diff --git a/target/linux/realtek/files/drivers/serial/8250_sc16is7x0.c b/target/linux/realtek/files/drivers/serial/8250_sc16is7x0.c
new file mode 100644
index 000000000..73444c746
--- /dev/null
+++ b/target/linux/realtek/files/drivers/serial/8250_sc16is7x0.c
@@ -0,0 +1,389 @@
+#ifndef __BOOTCODE__
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_reg.h>
+#include <linux/version.h>
+#include <platform.h> // GPIO_ABCD_IRQ, PABCD_ISR
+#include <asm/delay.h>
+#endif
+
+#ifdef __BOOTCODE__
+#define ENODEV 19 /* No such device */
+#define __init
+#endif
+
+#if defined( LINUX_VERSION_CODE ) && (LINUX_VERSION_CODE == KERNEL_VERSION(2,6,30))
+#define LINUX_KERNEL_VERSION_2_6_30 1
+#endif
+
+#ifdef LINUX_KERNEL_VERSION_2_6_30
+#include "bspchip.h" // BSP_GPIO_EFGH_IRQ
+#endif
+
+
+// ------------------------------------------------------------------
+// ------------------------------------------------------------------
+// Basic setup information
+
+#define SC16IS7X0_BAUDRATE 38400
+
+#ifdef CONFIG_SERIAL_SC16IS7X0_XTAL1_CLK_1843200
+#define XTAL1_CLK ( SC16IS7X0_BAUDRATE * 3 * 16 ) // 1.8432 MHZ
+#elif defined( CONFIG_SERIAL_SC16IS7X0_XTAL1_CLK_14746500 )
+#define XTAL1_CLK ( SC16IS7X0_BAUDRATE * 24 * 16 ) // 14.7465 MHZ (NXP demoboard)
+#endif
+
+// ------------------------------------------------------------------
+// ------------------------------------------------------------------
+// I2C level function
+
+#ifndef __BOOTCODE__
+#include "i2c.h"
+#else
+#include "i2c.h"
+#endif
+
+#define I2C_GPIO_ID( port, pin ) ( ( ( port - 'A' ) << 16 ) | ( pin ) )
+
+#ifdef CONFIG_RTK_VOIP_GPIO_8954C_V200
+#define SC16IS7X0_SCL I2C_GPIO_ID( 'G', 1 ) // SCL = G1
+#define SC16IS7X0_SDA I2C_GPIO_ID( 'G', 0 ) // SDA = G0
+#define SC16IS7X0_IRQ I2C_GPIO_ID( 'E', 2 ) // IRQ = E2
+#define SC16IS7X0_IRQ_NUM BSP_GPIO_EFGH_IRQ // BSP_GPIO_EFGH_IRQ=33
+#define SC16IS7X0_IRQ_STATUS_BIT ( 1 << ( 0 + 2 ) ) // clean pending status of E2
+#define SC16IS7X0_IRQ_STATUS_REG PEFGH_ISR
+#elif defined (CONFIG_RTK_VOIP_GPIO_8954C_V400)
+#error "unknown SC16IS7X0 I2C pin assignment"
+#else
+#define SC16IS7X0_RESET I2C_GPIO_ID( 'A', 4 ) // RESET = D3
+#define SC16IS7X0_SCL I2C_GPIO_ID( 'A', 3 ) // SCL = D4
+#define SC16IS7X0_SDA I2C_GPIO_ID( 'A', 5 ) // SDA = D5
+#define SC16IS7X0_IRQ I2C_GPIO_ID( 'A', 6 ) // IRQ = D6
+#define SC16IS7X0_IRQ_NUM BSP_GPIO_ABCD_IRQ // GPIO_ABCD_IRQ=16
+#define SC16IS7X0_IRQ_STATUS_BIT ( 1 << ( 0 + 6 ) ) // clean pending status of D6
+#define SC16IS7X0_IRQ_STATUS_REG PABCD_ISR
+#endif
+
+#define SC16IS7X0_I2C_ADDR 0x9A
+#define SC16IS7X0_I2C_WRITE 0x00
+#define SC16IS7X0_I2C_READ 0x01
+
+static i2c_dev_t sc16is7x0_i2c_dev = {
+ .sclk = SC16IS7X0_SCL,
+ .sdio = SC16IS7X0_SDA,
+ .irq = SC16IS7X0_IRQ,
+#ifdef SC16IS7X0_RESET
+ .reset = SC16IS7X0_RESET,
+#endif
+};
+
+// Register address byte
+// 7 : not used
+// 6~3: A[3:0] UART's internal register select
+// 2~1: channel select: CH1 = 0?!, CH0 = 0
+// 0 : not used
+#define MK_SC16IS7X0_REG_ADDR( uart_reg ) ( ( uart_reg & 0x0F ) << 3 )
+
+unsigned int serial_in_i2c(unsigned int addr, int offset)
+{
+ unsigned short int data;
+
+ //printk( "serial_in_i2c(%X):%X\n", addr, offset );
+
+ if( addr != SC16IS7X0_I2C_ADDR )
+ return 0;
+
+ // start
+ i2c_start_condition( &sc16is7x0_i2c_dev );
+
+ // addr + write
+ i2c_serial_write_byte( &sc16is7x0_i2c_dev, SC16IS7X0_I2C_ADDR |
+ SC16IS7X0_I2C_WRITE );
+
+ // read ACK
+ if( i2c_ACK( &sc16is7x0_i2c_dev ) != 0 )
+ return 0;
+
+ // write register address
+ i2c_serial_write_byte( &sc16is7x0_i2c_dev, MK_SC16IS7X0_REG_ADDR( offset ) );
+
+ // read ACK
+ if( i2c_ACK( &sc16is7x0_i2c_dev ) != 0 )
+ return 0;
+
+ // start
+ i2c_start_condition( &sc16is7x0_i2c_dev );
+
+ // addr + read
+ i2c_serial_write_byte( &sc16is7x0_i2c_dev, SC16IS7X0_I2C_ADDR |
+ SC16IS7X0_I2C_READ );
+
+ // read ACK
+ if( i2c_ACK( &sc16is7x0_i2c_dev ) != 0 )
+ return 0;
+
+ // read data
+ i2c_serial_read( &sc16is7x0_i2c_dev, &data );
+
+ // write negative-ACK
+ i2c_ACK_w( &sc16is7x0_i2c_dev, 1 );
+
+ // stop
+ i2c_stop_condition( &sc16is7x0_i2c_dev );
+
+ //printk( "in[%X]\n", data );
+
+ return data;
+}
+
+unsigned int serial_out_i2c(unsigned int addr, int offset, int value)
+{
+ //printk( "serial_out_i2c(%X):%X,%X\n", addr, offset, value );
+
+ if( addr != SC16IS7X0_I2C_ADDR )
+ return 0;
+
+ // start
+ i2c_start_condition( &sc16is7x0_i2c_dev );
+
+ // addr + write
+ i2c_serial_write_byte( &sc16is7x0_i2c_dev, SC16IS7X0_I2C_ADDR |
+ SC16IS7X0_I2C_WRITE );
+
+ // read ACK
+ if( i2c_ACK( &sc16is7x0_i2c_dev ) != 0 )
+ return 0;
+
+ // write register address
+ i2c_serial_write_byte( &sc16is7x0_i2c_dev, MK_SC16IS7X0_REG_ADDR( offset ) );
+
+ // read ACK
+ if( i2c_ACK( &sc16is7x0_i2c_dev ) != 0 )
+ return 0;
+
+ // write data
+ i2c_serial_write_byte( &sc16is7x0_i2c_dev, value );
+
+ // read ACK
+ if( i2c_ACK( &sc16is7x0_i2c_dev ) != 0 )
+ return 0;
+
+ // stop
+ i2c_stop_condition( &sc16is7x0_i2c_dev );
+
+ return 0;
+}
+
+static void sc16is7X0_set_baudrate(unsigned int baud)
+{
+ unsigned int divisor;
+ unsigned char c;
+
+ //setup baudrate and etc (copy from 8250_early.c)
+#define serial_out( port, offset, value ) serial_out_i2c( SC16IS7X0_I2C_ADDR, offset, value )
+#define serial_in( port, offset ) serial_in_i2c( SC16IS7X0_I2C_ADDR, offset )
+
+ //divisor = port->uartclk / (16 * device->baud);
+ divisor = XTAL1_CLK / (16 * SC16IS7X0_BAUDRATE);
+ c = serial_in(port, UART_LCR);
+ serial_out(port, UART_LCR, c | UART_LCR_DLAB);
+ serial_out(port, UART_DLL, divisor & 0xff);
+ serial_out(port, UART_DLM, (divisor >> 8) & 0xff);
+ serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
+
+#undef serial_out
+#undef serial_in
+}
+
+
+static void __init sc16is7x0_init_i2c( void )
+{
+ // init SCL / SDA
+ i2c_init_SCL_SDA( &sc16is7x0_i2c_dev );
+
+ serial_in_i2c( SC16IS7X0_I2C_ADDR, 1 ); // avoid NO ACK at first time access
+
+ // Enable IRQ
+ i2c_enable_irq( &sc16is7x0_i2c_dev );
+}
+
+// ------------------------------------------------------------------
+// ------------------------------------------------------------------
+// Early printk or bootcode
+
+int __init early_sc16is7x0_init_i2c_and_check( void )
+{
+ unsigned int bak;
+
+ // init i2c
+ sc16is7x0_init_i2c();
+
+ // do simple test (write non-zero, because NO ACK return zero)
+ bak = serial_in_i2c( SC16IS7X0_I2C_ADDR, 1 );
+
+ serial_out_i2c( SC16IS7X0_I2C_ADDR, 1, 0x0F );
+ if( serial_in_i2c( SC16IS7X0_I2C_ADDR, 1 ) != 0x0F )
+ goto label_out;
+
+ // restore
+ serial_out_i2c( SC16IS7X0_I2C_ADDR, 1, bak );
+
+ return 0;
+
+label_out:
+ return -ENODEV;
+}
+
+#ifdef LINUX_KERNEL_VERSION_2_6_30
+int __init early_sc16is7x0_setup(struct console * console, char * option)
+{
+ int ret;
+ unsigned int divisor;
+ unsigned char c;
+
+ ret = early_sc16is7x0_init_i2c_and_check();
+
+ if( ret )
+ return ret;
+
+ // setup baudrate and etc (copy from 8250_early.c)
+#define serial_out( port, offset, value ) serial_out_i2c( SC16IS7X0_I2C_ADDR, offset, value )
+#define serial_in( port, offset ) serial_in_i2c( SC16IS7X0_I2C_ADDR, offset )
+
+ serial_out(port, UART_LCR, 0x3); /* 8n1 */
+ serial_out(port, UART_IER, 0); /* no interrupt */
+ serial_out(port, UART_FCR, 0); /* no fifo */
+ serial_out(port, UART_MCR, 0x3); /* DTR + RTS */
+
+ //divisor = port->uartclk / (16 * device->baud);
+ divisor = XTAL1_CLK / (16 * SC16IS7X0_BAUDRATE);
+ c = serial_in(port, UART_LCR);
+ serial_out(port, UART_LCR, c | UART_LCR_DLAB);
+ serial_out(port, UART_DLL, divisor & 0xff);
+ serial_out(port, UART_DLM, (divisor >> 8) & 0xff);
+ serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
+
+#undef serial_out
+#undef serial_in
+
+ return 0;
+}
+#endif
+
+// ------------------------------------------------------------------
+// ------------------------------------------------------------------
+// Bootcode wrapper
+#if defined( __BOOTCODE__ ) || defined( LINUX_KERNEL_VERSION_2_6_30 )
+unsigned int sc16is7x0_serial_out_i2c(int offset, int value)
+{
+ return serial_out_i2c( SC16IS7X0_I2C_ADDR, offset, value );
+}
+
+unsigned int sc16is7x0_serial_in_i2c(int offset)
+{
+ return serial_in_i2c( SC16IS7X0_I2C_ADDR, offset );
+}
+#endif
+
+// ------------------------------------------------------------------
+// ------------------------------------------------------------------
+// Platform level function
+#ifndef __BOOTCODE__
+int sc16is7x0_clean_interrupt( int irq )
+{
+ if( irq != SC16IS7X0_IRQ_NUM )
+ return 0; // not my irq
+
+ // clean my bit only
+ if( REG32( SC16IS7X0_IRQ_STATUS_REG ) & SC16IS7X0_IRQ_STATUS_BIT ) {
+ REG32( SC16IS7X0_IRQ_STATUS_REG ) = SC16IS7X0_IRQ_STATUS_BIT;
+ return 0;
+ }
+
+ return -1; // not my gpio
+}
+#endif
+
+// ------------------------------------------------------------------
+// ------------------------------------------------------------------
+// UART level function
+#ifndef __BOOTCODE__
+
+#ifdef LINUX_KERNEL_VERSION_2_6_30
+#define PORT_TYPE PORT_16654
+#define PORT_FLAGS /*UPF_BOOT_AUTOCONF |*/ UPF_SKIP_TEST | UPF_FIXED_TYPE | UPF_SHARE_IRQ
+#else
+#define PORT_TYPE 0 // autoconf (2.6.19)
+#define PORT_FLAGS /*UPF_BOOT_AUTOCONF |*/ UPF_SKIP_TEST
+#endif
+
+#define PORT(_base,_irq) \
+ { \
+ .type = PORT_TYPE, \
+ .iobase = _base, \
+ .irq = _irq, \
+ .uartclk = XTAL1_CLK, \
+ .iotype = UPIO_I2C, \
+ .flags = PORT_FLAGS, \
+ }
+
+static struct plat_serial8250_port sc16is7x0_data[] = {
+ PORT(SC16IS7X0_I2C_ADDR, SC16IS7X0_IRQ_NUM),
+ { },
+};
+
+static struct platform_device sc16is7x0_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_SC16IS7X0,
+ .dev = {
+ .platform_data = sc16is7x0_data,
+ },
+};
+
+void __init sc16is7x0_get_port( struct uart_port *port )
+{
+ // call by static void __init serial_init(void)
+ // in linux-2.6.x/arch/mips/realtek/rtl8196b/setup.c
+ memset(port, 0, sizeof(*port));
+
+ port ->type = PORT_16654;
+ port ->iobase = SC16IS7X0_I2C_ADDR;
+ port ->irq = SC16IS7X0_IRQ_NUM;
+ port ->uartclk = XTAL1_CLK;
+#ifdef LINUX_KERNEL_VERSION_2_6_30
+ port ->flags = PORT_FLAGS;
+#else
+ //port ->flags = UPF_SKIP_TEST | UPF_LOW_LATENCY | UPF_SPD_CUST;
+ port ->flags = UPF_SKIP_TEST | UPF_SPD_CUST;
+ //port ->flags = UPF_SKIP_TEST | UPF_SPD_CUST | UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP
+#endif
+ port ->iotype = UPIO_I2C;
+ port ->fifosize = 1;
+#ifdef LINUX_KERNEL_VERSION_2_6_30
+ // linux 2.6.30's early_serial_setup()r doesn't copy custom_divisor
+#else
+ port ->custom_divisor = XTAL1_CLK / (SC16IS7X0_BAUDRATE * 16);
+#endif
+}
+
+static int __init sc16is7x0_init(void)
+{
+ int ret;
+
+ sc16is7x0_init_i2c();
+
+ ret = platform_device_register(&sc16is7x0_device);
+
+ //enable irq
+ REG32(BSP_GIMR) |= BSP_GPIO_ABCD_IE;
+ return ret;
+}
+
+module_init(sc16is7x0_init);
+
+MODULE_AUTHOR("Realtek");
+MODULE_DESCRIPTION("8250 serial probe module for SC16IS7x0");
+MODULE_LICENSE("GPL");
+#endif
+
diff --git a/target/linux/realtek/files/drivers/serial/gpio.h b/target/linux/realtek/files/drivers/serial/gpio.h
new file mode 100644
index 000000000..39019c669
--- /dev/null
+++ b/target/linux/realtek/files/drivers/serial/gpio.h
@@ -0,0 +1,98 @@
+/*
+* Copyright c Realtek Semiconductor Corporation, 2006
+* All rights reserved.
+*
+* Program : GPIO Header File
+* Abstract :
+* Author :
+*
+*/
+
+
+#ifndef __GPIO__
+#define __GPIO__
+
+#ifdef __UBOOT__
+#include <config.h>
+#endif
+#ifndef __BOOTCODE__
+#include <linux/config.h>
+#endif
+//#include "voip_types.h"
+#include <net/rtl/rtl_types.h>
+
+#ifdef CONFIG_RTK_VOIP_DRIVERS_PCM8186
+#include "gpio_8186.h"
+#elif defined(CONFIG_RTK_VOIP_DRIVERS_PCM8651)
+#include "gpio_8651bv.h"
+#elif defined(CONFIG_RTK_VOIP_DRIVERS_PCM8671)
+#include "gpio_8972.h"
+#elif defined(CONFIG_RTK_VOIP_DRIVERS_PCM8672)
+#include "gpio_8672.h"
+#elif defined(CONFIG_RTK_VOIP_DRIVERS_PCM865xC)
+#include "gpio_8952.h"
+#elif defined(CONFIG_RTK_VOIP_DRIVERS_PCM8972B_FAMILY)
+#include "gpio_8972b.h"
+#else
+#error "unknown gpio driver"
+#endif
+
+#define _GPIO_DEBUG_
+
+#ifdef _GPIO_DEBUG_
+#if defined(CONFIG_RTK_VOIP_DRIVERS_PCM8651)
+#define GPIO_PRINT(level, fmt, args...) do { if (gpio_debug >= level) rtlglue_printf(fmt, ## args); } while (0)
+#else
+#define GPIO_PRINT(level, fmt, args...) do { if (gpio_debug >= level) printk(fmt, ## args); } while (0)
+#endif
+#else
+#define GPIO_PRINT(fmt, args...)
+#endif
+
+/*
+ * Every pin of GPIO port can be mapped to a unique ID. All the access to a GPIO pin must use the ID.
+ * This macro is used to map the port and pin into the ID.
+ */
+#define GPIO_ID(port,pin) ((uint32)port<<16|(uint32)pin)
+
+/* This is reversed macro. */
+#define GPIO_PORT(id) (id>>16)
+#define GPIO_PIN(id) (id&0xffff)
+
+#ifdef CONFIG_RTK_VOIP_DRIVERS_PCM8186
+#define RTK_GPIO_INIT(pid, dedicate, dir, interrupt) _rtl8186_initGpioPin(pid, dir, interrupt)
+#define RTK_GPIO_GET(pid, pData) _rtl8186_getGpioDataBit(pid, pData)
+#define RTK_GPIO_SET(pid, data) _rtl8186_setGpioDataBit(pid, data)
+
+#elif defined(CONFIG_RTK_VOIP_DRIVERS_PCM8651)
+#define RTK_GPIO_INIT(pid, dedicate, dir, interrupt) _rtl865x_initGpioPin(pid, dedicate, dir, interrupt)
+#define RTK_GPIO_GET(pid, pData) _rtl865x_getGpioDataBit(pid, pData)
+#define RTK_GPIO_SET(pid, data) _rtl865x_setGpioDataBit(pid, data)
+
+#elif defined(CONFIG_RTK_VOIP_DRIVERS_PCM8671)
+#define RTK_GPIO_INIT(pid, dedicate, dir, interrupt) _rtl867x_initGpioPin(pid, dir, interrupt)
+#define RTK_GPIO_GET(pid, pData) _rtl867x_getGpioDataBit(pid, pData)
+#define RTK_GPIO_SET(pid, data) _rtl867x_setGpioDataBit(pid, data)
+
+#elif defined(CONFIG_RTK_VOIP_DRIVERS_PCM8672)
+#define RTK_GPIO_INIT(pid, dedicate, dir, interrupt) _rtl867x_initGpioPin(pid, dir)
+#define RTK_GPIO_GET(pid, pData) _rtl867x_getGpioDataBit(pid, pData)
+#define RTK_GPIO_SET(pid, data) _rtl867x_setGpioDataBit(pid, data)
+
+#elif defined(CONFIG_RTK_VOIP_DRIVERS_PCM865xC)
+#define RTK_GPIO_INIT(pid, dedicate, dir, interrupt) _rtl865xC_initGpioPin(pid, dedicate, dir, interrupt)
+#define RTK_GPIO_GET(pid, pData) _rtl865xC_getGpioDataBit(pid, pData)
+#define RTK_GPIO_SET(pid, data) _rtl865xC_setGpioDataBit(pid, data)
+
+#elif defined(CONFIG_RTK_VOIP_DRIVERS_PCM8972B_FAMILY)
+#define RTK_GPIO_INIT(pid, dedicate, dir, interrupt) _rtl8972B_initGpioPin(pid, dedicate, dir, interrupt)
+#define RTK_GPIO_GET(pid, pData) _rtl8972B_getGpioDataBit(pid, pData)
+#define RTK_GPIO_SET(pid, data) _rtl8972B_setGpioDataBit(pid, data)
+
+#else
+#error "unknown gpio driver"
+#endif
+
+extern int gpio_debug;
+
+#endif/*__GPIO__*/
diff --git a/target/linux/realtek/files/drivers/serial/gpio_8972b.c b/target/linux/realtek/files/drivers/serial/gpio_8972b.c
new file mode 100644
index 000000000..f52669d26
--- /dev/null
+++ b/target/linux/realtek/files/drivers/serial/gpio_8972b.c
@@ -0,0 +1,526 @@
+/*
+* Copyright c Realtek Semiconductor Corporation, 2008
+* All rights reserved.
+*
+* Program : GPIO Driver
+* Abstract :
+* Author :
+*/
+
+#ifndef __BOOTCODE__
+#include <linux/kernel.h>
+#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<<x)
+static uint32 GpioShare_setting[] =
+ {
+ 0x00000000, /* Port A0 */
+ 0x00000000, /* Port A1 */
+ 0x00000000, /* Port A2 */
+ (SET_BIT(21)|SET_BIT(20)), /* Port A3 */
+ (SET_BIT(21)|SET_BIT(20)), /* Port A4 */
+ (SET_BIT(21)|SET_BIT(20)), /* Port A5 */
+ (SET_BIT(21)|SET_BIT(20)), /* Port A6 */
+ 0x00000000, /* Port A7 */
+ 0x00000000, /* Port B0 */
+ 0x00000000, /* Port B1 */
+ 0x00000000, /* Port B2 */
+ 0x00000000, /* Port B3 */
+ 0x00000000, /* Port B4 */
+ 0x00000000, /* Port B5 */
+ 0x00000000, /* Port B6 */
+ 0x00000000, /* Port B7 */
+ 0x00000000, /* Port C0 */
+ 0x00000000, /* Port C1 */
+ 0x00000000, /* Port C2 */
+ 0x00000000, /* Port C3 */
+ 0x00000000, /* Port C4 */
+ 0x00000000, /* Port C5 */
+ 0x00000000, /* Port C6 */
+ 0x00000000, /* Port C7 */
+ 0x00000000, /* Port D0 */
+ 0x00000000, /* Port D1 */
+ 0x00000000, /* Port D2 */
+ 0x00000000, /* Port D3 */
+ 0x00000000, /* Port D4 */
+ 0x00000000, /* Port D5 */
+ 0x00000000, /* Port D6 */
+ 0x00000000, /* Port D7 */
+ 0x00000000, /* Port E0 */
+ 0x00000000, /* Port E1 */
+ 0x00000000, /* Port E2 */
+ 0x00000000, /* Port E3 */
+ 0x00000000, /* Port E4 */
+ 0x00000000, /* Port E5 */
+ 0x00000000, /* Port E6 */
+ 0x00000000, /* Port E7 */
+ 0x00000000, /* Port F0 */
+ 0x00000000, /* Port F1 */
+ 0x00000000, /* Port F2 */
+ 0x00000000, /* Port F3 */
+ 0x00000000, /* Port F4 */
+ 0x00000000, /* Port F5 */
+ 0x00000000, /* Port F6 */
+ 0x00000000, /* Port F7 */
+ 0x00000000, /* Port G0 */
+ 0x00000000, /* Port G1 */
+ 0x00000000, /* Port G2 */
+ 0x00000000, /* Port G3 */
+ 0x00000000, /* Port G4 */
+ 0x00000000, /* Port G5 */
+ 0x00000000, /* Port G6 */
+ 0x00000000, /* Port G7 */
+ 0x00000000, /* Port H0 */
+ 0x00000000, /* Port H1 */
+ 0x00000000, /* Port H2 */
+ 0x00000000, /* Port H3 */
+ 0x00000000, /* Port H4 */
+ 0x00000000, /* Port H5 */
+ 0x00000000, /* Port H6 */
+ 0x00000000, /* Port H7 */
+ };
+#if 0
+{
+ (SET_BIT(9)|SET_BIT(8)|SET_BIT(7)), /* Port A0 */
+ (SET_BIT(9)|SET_BIT(8)|SET_BIT(7)), /* Port A1 */
+ (SET_BIT(9)|SET_BIT(8)|SET_BIT(7)), /* Port A2 */
+ (SET_BIT(9)|SET_BIT(8)|SET_BIT(7)), /* Port A3 */
+ (SET_BIT(9)|SET_BIT(8)|SET_BIT(7)), /* Port A4 */
+ (SET_BIT(6)|SET_BIT(5)), /* Port A5 */
+ (SET_BIT(6)|SET_BIT(5)), /* Port A6 */
+ (SET_BIT(3)|SET_BIT(2)), /* Port A7 */
+ (SET_BIT(11)|SET_BIT(10)), /* Port B0 */
+ (SET_BIT(13)|SET_BIT(12)), /* Port B1 */
+ (SET_BIT(15)|SET_BIT(14)), /* Port B2 */
+ (SET_BIT(17)|SET_BIT(16)), /* Port B3 */
+ 0x00000000, /* Port B4 */
+ 0x00000000, /* Port B5 */
+ 0x00000000, /* Port B6 */
+ 0x00000000, /* Port B7 */
+ (SET_BIT(19)|SET_BIT(18)), /* Port C0 */
+ (SET_BIT(21)|SET_BIT(20)), /* Port C1 */
+ (SET_BIT(23)|SET_BIT(22)), /* Port C2 */
+ (SET_BIT(25)|SET_BIT(24)), /* Port C3 */
+ (SET_BIT(27)|SET_BIT(26)), /* Port C4 */
+ 0x00000000, /* Port C5 */
+ 0x00000000, /* Port C6 */
+ 0x00000000, /* Port C7 */
+ (SET_BIT(1)|SET_BIT(0)), /* Port D0 */
+ (SET_BIT(1)|SET_BIT(0)), /* Port D1 */
+ (SET_BIT(1)|SET_BIT(0)), /* Port D2 */
+ (SET_BIT(1)|SET_BIT(0)), /* Port D3 */
+ (SET_BIT(1)|SET_BIT(0)), /* Port D4 */
+ (SET_BIT(1)|SET_BIT(0)), /* Port D5 */
+ (SET_BIT(1)|SET_BIT(0)), /* Port D6 */
+ (SET_BIT(1)|SET_BIT(0)), /* Port D7 */
+ (SET_BIT(1)|SET_BIT(0)), /* Port E0 */
+ (SET_BIT(1)|SET_BIT(0)), /* Port E1 */
+ (SET_BIT(1)|SET_BIT(0)), /* Port E2 */
+ (SET_BIT(1)|SET_BIT(0)), /* Port E3 */
+ (SET_BIT(1)|SET_BIT(0)), /* Port E4 */
+ (SET_BIT(1)|SET_BIT(0)), /* Port E5 */
+ (SET_BIT(1)|SET_BIT(0)), /* Port E6 */
+ 0x00000000, /* Port E7 */
+ 0x00000000, /* Port F0 */
+ 0x00000000, /* Port F1 */
+ 0x00000000, /* Port F2 */
+ 0x00000000, /* Port F3 */
+ 0x00000000, /* Port F4 */
+ 0x00000000, /* Port F5 */
+ 0x00000000, /* Port F6 */
+ 0x00000000, /* Port F7 */
+ 0x00000000, /* Port G0 */
+ 0x00000000, /* Port G1 */
+ 0x00000000, /* Port G2 */
+ 0x00000000, /* Port G3 */
+ 0x00000000, /* Port G4 */
+ 0x00000000, /* Port G5 */
+ 0x00000000, /* Port G6 */
+ 0x00000000, /* Port G7 */
+ 0x00000000, /* Port H0 */
+ 0x00000000, /* Port H1 */
+ 0x00000000, /* Port H2 */
+ 0x00000000, /* Port H3 */
+ 0x00000000, /* Port H4 */
+ 0x00000000, /* Port H5 */
+ 0x00000000, /* Port H6 */
+ 0x00000000, /* Port H7 */
+};
+#endif
+#undef SET_BIT
+
+//******************************************* Direction
+static uint32 regGpioDirection[] =
+{
+ GPABCDDIR, /* Port A */
+ GPABCDDIR, /* Port B */
+ GPABCDDIR, /* Port C */
+ GPABCDDIR, /* Port D */
+ GPEFGHDIR, /* Port E */
+ GPEFGHDIR, /* Port F */
+ GPEFGHDIR, /* Port G */
+ GPEFGHDIR, /* Port H */
+};
+
+static uint32 bitStartGpioDirection[] =
+{
+ 0, /* Port A */
+ 8, /* Port B */
+ 16, /* Port C */
+ 24, /* Port D */
+ 0, /* Port E */
+ 8, /* Port F */
+ 16, /* Port G */
+ 24, /* Port H */
+};
+
+//******************************************* Data
+static uint32 regGpioData[] =
+{
+ GPABCDDATA, /* Port A */
+ GPABCDDATA, /* Port B */
+ GPABCDDATA, /* Port C */
+ GPABCDDATA, /* Port D */
+ GPEFGHDATA, /* Port E */
+ GPEFGHDATA, /* Port F */
+ GPEFGHDATA, /* Port G */
+ GPEFGHDATA, /* Port H */
+ GPEFGHDATA, /* Port I */
+};
+
+static uint32 bitStartGpioData[] =
+{
+ 0, /* Port A */
+ 8, /* Port B */
+ 16, /* Port C */
+ 24, /* Port D */
+ 0, /* Port E */
+ 8, /* Port F */
+ 16, /* Port G */
+ 24, /* Port H */
+};
+
+//******************************************* ISR
+static uint32 regGpioInterruptStatus[] =
+{
+ GPABCDISR, /* Port A */
+ GPABCDISR, /* Port B */
+ GPABCDISR, /* Port C */
+ GPABCDISR, /* Port D */
+ GPEFGHISR, /* Port E */
+ GPEFGHISR, /* Port F */
+ GPEFGHISR, /* Port G */
+ GPEFGHISR, /* Port H */
+};
+
+static uint32 bitStartGpioInterruptStatus[] =
+{
+ 0, /* Port A */
+ 8, /* Port B */
+ 16, /* Port C */
+ 24, /* Port D */
+ 0, /* Port E */
+ 8, /* Port F */
+ 16, /* Port G */
+ 24, /* Port H */
+};
+
+//******************************************* IMR
+static uint32 regGpioInterruptEnable[] =
+{
+ GPABIMR, /* Port A */
+ GPABIMR, /* Port B */
+ GPCDIMR, /* Port C */
+ GPCDIMR, /* Port D */
+ GPEFIMR, /* Port E */
+ GPEFIMR, /* Port F */
+ GPGHIMR, /* Port G */
+ GPGHIMR, /* Port H */
+};
+
+static uint32 bitStartGpioInterruptEnable[] =
+{
+ 0, /* Port A */
+ 16, /* Port B */
+ 0, /* Port C */
+ 16, /* Port D */
+ 0, /* Port E */
+ 16, /* Port F */
+ 0, /* Port G */
+ 16, /* Port H */
+};
+
+int gpio_debug = 0;
+
+/*
+@func int32 | _getGpio | abstract GPIO registers
+@parm enum GPIO_FUNC | func | control/data/interrupt register
+@parm enum GPIO_PORT | port | GPIO port
+@parm uint32 | pin | pin number
+@rvalue uint32 | value
+@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 uint32 _getGpio( enum GPIO_FUNC func, enum GPIO_PORT port, uint32 pin )
+{
+
+ GPIO_PRINT(4, "[%s():%d] func=%d port=%d pin=%d\n", __FUNCTION__, __LINE__, func, port, pin );
+ 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 ( REG32(regGpioControl[port]) & ( (uint32)1 << (pin+bitStartGpioControl[port]) ) )
+ return 1;
+ else
+ return 0;
+ 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 ( REG32(regGpioDirection[port]) & ( (uint32)1 << (pin+bitStartGpioDirection[port]) ) )
+ return 1;
+ else
+ return 0;
+ 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 ( REG32(regGpioData[port]) & ( (uint32)1 << (pin+bitStartGpioData[port]) ) )
+ return 1;
+ else
+ return 0;
+ 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] );
+
+ return ( REG32(regGpioInterruptEnable[port]) >> (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
+
diff --git a/target/linux/realtek/files/drivers/serial/gpio_8972b.h b/target/linux/realtek/files/drivers/serial/gpio_8972b.h
new file mode 100644
index 000000000..bce7a4b15
--- /dev/null
+++ b/target/linux/realtek/files/drivers/serial/gpio_8972b.h
@@ -0,0 +1,195 @@
+/*
+* Copyright c Realtek Semiconductor Corporation, 2008
+* All rights reserved.
+*
+* Program : GPIO Header File
+* Abstract :
+* Author :
+*
+*/
+
+
+#ifndef __GPIO_8972B_H
+#define __GPIO_8972B_H
+
+////// For 8982B QA Board /////
+#ifdef CONFIG_RTK_VOIP_GPIO_8982B_QA
+
+#define GPIO "E"
+/* Slic used */
+#define PIN_RESET1 GPIO_ID(GPIO_PORT_E,0) //output
+#define PIN_CS1 GPIO_ID(GPIO_PORT_E,1) //output
+#define PIN_CLK GPIO_ID(GPIO_PORT_E,3) //output
+#define PIN_DI GPIO_ID(GPIO_PORT_E,2) //input
+#if defined(CONFIG_RTK_VOIP_DRIVERS_SLIC_SI3215) || defined(CONFIG_RTK_VOIP_DRIVERS_SLIC_SI3226) || defined(CONFIG_RTK_VOIP_DRIVERS_SLIC_SI3217x)
+#define PIN_DO GPIO_ID(GPIO_PORT_E,4) //output for Si3215 daugher board
+#elif defined CONFIG_RTK_VOIP_DRIVERS_SLIC_LE88221
+#define PIN_DO GPIO_ID(GPIO_PORT_E,4) //output for Le88221 daughter board
+#endif
+
+/* DAA used (Reserved)*/
+#define PIN_RESET3_DAA GPIO_ID(GPIO_PORT_D,0) //output
+#define PIN_CS3_DAA GPIO_ID(GPIO_PORT_D,1) //output
+#define PIN_CLK_DAA GPIO_ID(GPIO_PORT_D,2) //output
+#define PIN_DI_DAA GPIO_ID(GPIO_PORT_D,3) //input
+#define PIN_DO_DAA GPIO_ID(GPIO_PORT_D,4) //output
+
+#endif
+
+////// For 8972B EV Board /////
+#ifdef CONFIG_RTK_VOIP_GPIO_8972B
+//#define GPIO_OC
+
+#define GPIO "E"
+/* SLIC used */
+#ifdef CONFIG_RTK_VOIP_DRIVERS_SLIC_LE89116 // for RTL89116 SLIC card
+#define PIN_RESET1 GPIO_ID(GPIO_PORT_D,7) //output
+#define PIN_CS1 GPIO_ID(GPIO_PORT_D,4) //output
+#define PIN_CLK GPIO_ID(GPIO_PORT_D,3) //output
+#define PIN_DI GPIO_ID(GPIO_PORT_D,5) //input
+#define PIN_DO GPIO_ID(GPIO_PORT_D,6) //output
+#else // for Silab SLIC
+#ifdef GPIO_OC
+#define PIN_RESET1 GPIO_ID(GPIO_PORT_E,6) //output
+#define PIN_CS1 GPIO_ID(GPIO_PORT_E,0) //output
+#define PIN_CLK GPIO_ID(GPIO_PORT_E,5) //output
+#define PIN_DI GPIO_ID(GPIO_PORT_D,0) //input
+#define PIN_DO GPIO_ID(GPIO_PORT_E,3) //output
+#else
+#ifdef CONFIG_RTK_VOIP_DECT_SPI_SUPPORT
+//#define PIN_RESET1 GPIO_ID(GPIO_PORT_E,0) //output
+#define PIN_CS1 GPIO_ID(GPIO_PORT_D,3) //output
+#define PIN_CLK GPIO_ID(GPIO_PORT_D,4) //output
+#define PIN_DI GPIO_ID(GPIO_PORT_D,5) //input
+#define PIN_DO GPIO_ID(GPIO_PORT_D,6) //output
+#define PIN_INT GPIO_ID(GPIO_PORT_D,7) //intput
+#else
+#define PIN_RESET1 GPIO_ID(GPIO_PORT_E,0) //output
+#define PIN_CS1 GPIO_ID(GPIO_PORT_E,1) //output
+#ifdef CONFIG_RTK_VOIP_MULTIPLE_SI32178
+#define PIN_CS2 GPIO_ID(GPIO_PORT_D,5) //output
+#define PIN_CS3 GPIO_ID(GPIO_PORT_F,2) //output
+#define PIN_CS4 GPIO_ID(GPIO_PORT_D,0) //output
+#endif
+#define PIN_CLK GPIO_ID(GPIO_PORT_E,3) //output
+#define PIN_DI GPIO_ID(GPIO_PORT_E,4) //input
+#define PIN_DO GPIO_ID(GPIO_PORT_E,2) //output
+#endif //!GPIO_DECT
+#endif //!GPIO_OC
+#endif //!CONFIG_RTK_VOIP_DRIVERS_SLIC_LE89116
+//#define PIN_INT1 GPIO_ID(GPIO_PORT_E,2) //input
+
+/* DAA used */
+#define PIN_RESET3_DAA GPIO_ID(GPIO_PORT_E,0) //output
+#define PIN_CS3_DAA GPIO_ID(GPIO_PORT_G,0) //output
+#define PIN_CLK_DAA GPIO_ID(GPIO_PORT_G,1) //output
+#define PIN_DI_DAA GPIO_ID(GPIO_PORT_G,7) //input
+#define PIN_DO_DAA GPIO_ID(GPIO_PORT_G,6) //output
+
+/* LED */
+#define PIN_VOIP1_LED GPIO_ID(GPIO_PORT_D,1) //output
+#define PIN_VOIP2_LED GPIO_ID(GPIO_PORT_D,2) //output
+#define PIN_VOIP3_LED GPIO_ID(GPIO_PORT_D,3) //output
+#define PIN_VOIP4_LED GPIO_ID(GPIO_PORT_D,4) //output
+#define PIN_PSTN_LED GPIO_ID(GPIO_PORT_F,5) //output
+
+#endif
+
+////// For IP Phone /////
+#ifdef CONFIG_RTK_VOIP_DRIVERS_IP_PHONE
+/* To be modified!! */
+#define GPIO "A"
+/* SLIC Si3226 */
+#define PIN_RESET1 GPIO_ID(GPIO_PORT_H,7) //output
+#define PIN_INT1 GPIO_ID(GPIO_PORT_E,2) //input
+#define PIN_CS1 GPIO_ID(GPIO_PORT_H,6) //output
+#define PIN_CLK GPIO_ID(GPIO_PORT_E,1) //output
+#define PIN_DI GPIO_ID(GPIO_PORT_G,3) //input
+#define PIN_DO GPIO_ID(GPIO_PORT_G,2) //output
+
+/* DAA used */
+#define PIN_RESET3_DAA GPIO_ID(GPIO_PORT_E,0) //output
+#define PIN_CS3_DAA GPIO_ID(GPIO_PORT_G,0) //output
+#define PIN_CLK_DAA GPIO_ID(GPIO_PORT_G,1) //output
+#define PIN_DI_DAA GPIO_ID(GPIO_PORT_G,7) //input
+#define PIN_DO_DAA GPIO_ID(GPIO_PORT_G,6) //output
+
+/* LED */
+#define PIN_VOIP1_LED GPIO_ID(GPIO_PORT_F,4) //output
+#define PIN_VOIP2_LED GPIO_ID(GPIO_PORT_F,2) //output
+#define PIN_PSTN_LED GPIO_ID(GPIO_PORT_F,5) //output
+#endif
+
+/*==================== FOR RTL8972B Family ==================*/
+#ifdef CONFIG_RTK_VOIP_DRIVERS_PCM8972B_FAMILY
+
+/******** GPIO define ********/
+
+/* define GPIO port */
+enum GPIO_PORT
+{
+ GPIO_PORT_A = 0,
+ GPIO_PORT_B,
+ GPIO_PORT_C,
+ GPIO_PORT_D,
+ GPIO_PORT_E,
+ GPIO_PORT_F,
+ GPIO_PORT_G,
+ GPIO_PORT_H,
+ GPIO_PORT_MAX,
+};
+
+/* define GPIO control pin */
+enum GPIO_CONTROL
+{
+ GPIO_CONT_GPIO = 0,
+ GPIO_CONT_PERI = 0x1,
+};
+
+/* define GPIO direction */
+enum GPIO_DIRECTION
+{
+ GPIO_DIR_IN = 0,
+ GPIO_DIR_OUT =1,
+};
+
+/* define GPIO Interrupt Type */
+enum GPIO_INTERRUPT_TYPE
+{
+ GPIO_INT_DISABLE = 0,
+ GPIO_INT_FALLING_EDGE,
+ GPIO_INT_RISING_EDGE,
+ GPIO_INT_BOTH_EDGE,
+};
+
+/*************** Define RTL8972B Family GPIO Register Set ************************/
+#define GPABCDCNR 0xB8003500
+
+#define GPABCDDIR 0xB8003508
+#define GPABCDDATA 0xB800350C
+#define GPABCDISR 0xB8003510
+#define GPABIMR 0xB8003514
+#define GPCDIMR 0xB8003518
+#define GPEFGHCNR 0xB800351C
+
+#define GPEFGHDIR 0xB8003524
+#define GPEFGHDATA 0xB8003528
+#define GPEFGHISR 0xB800352C
+#define GPEFIMR 0xB8003530
+#define GPGHIMR 0xB8003534
+/**************************************************************************/
+/* Register access macro (REG*()).*/
+#define REG32(reg) (*((volatile uint32 *)(reg)))
+#define REG16(reg) (*((volatile uint16 *)(reg)))
+#define REG8(reg) (*((volatile uint8 *)(reg)))
+
+/********************* Function Prototype in gpio.c ***********************/
+int32 _rtl8972B_initGpioPin(uint32 gpioId, enum GPIO_CONTROL dedicate,
+ enum GPIO_DIRECTION,
+ enum GPIO_INTERRUPT_TYPE interruptEnable );
+int32 _rtl8972B_getGpioDataBit( uint32 gpioId, uint32* pData );
+int32 _rtl8972B_setGpioDataBit( uint32 gpioId, uint32 data );
+
+#endif//CONFIG_RTK_VOIP_DRIVERS_PCM8972B_FAMILY
+
+#endif /* __GPIO_8972B_H */
diff --git a/target/linux/realtek/files/drivers/serial/i2c.c b/target/linux/realtek/files/drivers/serial/i2c.c
new file mode 100644
index 000000000..42fdebd03
--- /dev/null
+++ b/target/linux/realtek/files/drivers/serial/i2c.c
@@ -0,0 +1,305 @@
+#ifdef __UBOOT__
+#include <config.h>
+#endif
+#ifndef __BOOTCODE__
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/string.h>
+#endif
+#ifndef __UBOOT__
+#include <linux/delay.h> // linux and realtek bootcode use
+#endif
+
+#include "gpio.h"
+#include "i2c.h"
+
+#define __i2c_initGpioPin(pid, dir, interrupt) RTK_GPIO_INIT(pid, GPIO_CONT_GPIO, dir, interrupt)
+#define __i2c_getGpioDataBit(pid, pData) RTK_GPIO_GET(pid, pData)
+#define __i2c_setGpioDataBit(pid, data) RTK_GPIO_SET(pid, data)
+
+//-----------------------------
+#if 0 //0: kernel used(udelay), 1: test program used(for(;;))
+#define __test_program_used__
+#else
+#define __kernel_used__
+#endif
+
+#if defined(CONFIG_RTK_VOIP_DRIVERS_CODEC_WM8510)
+//----------------------- WM8510 codec ----------------------------------------------
+#define I2C_RATING_FACTOR 10 //Adjust I2C read and write rating.
+//There is an I2C protocal.
+#define _I2C_WM8510_ //GPIO pin
+//cli() protection for kernel used. Don't define MACRO _WM8510_CLI_PROTECT in test program.
+//#define _WM8510_CLI_PROTECT
+
+#elif defined(CONFIG_RTK_VOIP_DRIVERS_CODEC_ALC5621)
+//----------------------- ALC5621 codec ----------------------------------------------
+#define I2C_RATING_FACTOR 10 //Adjust I2C read and write rating.
+//There is an I2C protocal.
+#define _I2C_ALC5621_ //GPIO pin
+//cli() protection for kernel used. Don't define MACRO _WM8510_CLI_PROTECT in test program.
+ #if defined( CONFIG_RTK_VOIP_GPIO_IPP_8972_V00 ) || defined( CONFIG_RTK_VOIP_GPIO_IPP_8972_V01 ) || defined( CONFIG_RTK_VOIP_GPIO_IPP_8972B_V99 )
+ #define _ALC5621_CLI_PROTECT // 8972 share ALC PIN to other
+ #endif
+#elif defined(CONFIG_SERIAL_SC16IS7X0)
+#define I2C_RATING_FACTOR 1
+#endif
+
+#ifdef __kernel_used__ // pkshih: If we use udelay, factor 1 should be work, doesn't it?
+#undef I2C_RATING_FACTOR
+#define I2C_RATING_FACTOR 1
+#endif
+
+/************************* I2C read/write function ************************/
+void i2c_serial_write_byte(i2c_dev_t* pI2C_Dev, unsigned char data)
+{
+#ifdef __test_program_used__
+ int i;
+#endif
+ char j;
+ __i2c_initGpioPin(pI2C_Dev->sdio, GPIO_DIR_OUT, GPIO_INT_DISABLE);//change sdio to output
+ for (j=7;j>=0;j--) {
+ __i2c_setGpioDataBit( pI2C_Dev->sclk, 0); /* fall down sclk*/
+ __i2c_setGpioDataBit( pI2C_Dev->sdio, ((data)>>j)&0x00000001);//write data,from MSB to LSB
+ //delay 2 us.
+ #ifdef __kernel_used__
+ udelay(2*I2C_RATING_FACTOR);
+ #endif
+ #ifdef __test_program_used__
+ for (i=0;i<2000*I2C_RATING_FACTOR;i++);
+ #endif
+ __i2c_setGpioDataBit( pI2C_Dev->sclk, 1); /* raise sclk*/
+ //delay 1 us.
+ #ifdef __kernel_used__
+ udelay(1*I2C_RATING_FACTOR);
+ #endif
+ #ifdef __test_program_used__
+ for (i=0;i<1000*I2C_RATING_FACTOR;i++);
+ #endif
+ }
+ return;
+}
+
+void i2c_serial_write(i2c_dev_t* pI2C_Dev, unsigned char *data)
+{
+ i2c_serial_write_byte( pI2C_Dev, *data );
+}
+
+unsigned char i2c_ACK(i2c_dev_t* pI2C_Dev)
+{
+#ifdef __test_program_used__
+ int i;
+#endif
+ unsigned int buf;
+#if 0
+ __i2c_setGpioDataBit( pI2C_Dev->sdio, 0); /* fall down sdio*/
+ __i2c_initGpioPin(pI2C_Dev->sdio, GPIO_DIR_IN, GPIO_INT_DISABLE);//change sdio to input
+ __i2c_setGpioDataBit( pI2C_Dev->sclk, 0); /* fall down sclk*/
+#endif
+ //__i2c_setGpioDataBit( pI2C_Dev->sdio, 0); /* fall down sdio*/
+
+ __i2c_setGpioDataBit( pI2C_Dev->sclk, 0); /* fall down sclk*/
+ __i2c_initGpioPin(pI2C_Dev->sdio, GPIO_DIR_IN, GPIO_INT_DISABLE);//change sdio to input
+ //delay 1 us.
+ #ifdef __kernel_used__
+ udelay(1*I2C_RATING_FACTOR);
+ #endif
+ #ifdef __test_program_used__
+ for (i=0;i<1000*I2C_RATING_FACTOR;i++);
+ #endif
+
+ __i2c_setGpioDataBit( pI2C_Dev->sclk, 1); /* raise sclk*/
+ //delay 1 us.
+ #ifdef __kernel_used__
+ udelay(1*I2C_RATING_FACTOR);
+ #endif
+ #ifdef __test_program_used__
+ for (i=0;i<1000*I2C_RATING_FACTOR;i++);
+ #endif
+
+ __i2c_getGpioDataBit(pI2C_Dev->sdio,&buf);
+ if (buf != 0)
+ printk("NO ACK\n");
+ //__i2c_initGpioPin(pI2C_Dev->sdio, GPIO_INT_DISABLE);//change sdio to output
+ __i2c_setGpioDataBit( pI2C_Dev->sclk, 0); /* fall down sclk*/
+ #if 0
+ //delay 1 us.
+ #ifdef __kernel_used__
+ udelay(1*I2C_RATING_FACTOR);
+ #endif
+ #ifdef __test_program_used__
+ for (i=0;i<1000*I2C_RATING_FACTOR;i++);
+ #endif
+ #endif
+ return buf;
+}
+
+void i2c_ACK_w(i2c_dev_t* pI2C_Dev, unsigned char data)
+{
+#ifdef __test_program_used__
+ int i;
+#endif
+
+#if 0
+ __i2c_initGpioPin(pI2C_Dev->sdio, GPIO_DIR_OUT, GPIO_INT_DISABLE);//change sdio to output
+ __i2c_setGpioDataBit( pI2C_Dev->sdio, data); /* sdio send 0 for ACK, 1 for NACK*/
+ __i2c_setGpioDataBit( pI2C_Dev->sclk, 0); /* fall down sclk*/
+#endif
+ __i2c_setGpioDataBit( pI2C_Dev->sclk, 0); /* fall down sclk*/
+ //for (i=0;i<500*I2C_RATING_FACTOR;i++);
+
+ __i2c_initGpioPin(pI2C_Dev->sdio, GPIO_DIR_OUT, GPIO_INT_DISABLE);//change sdio to output
+ __i2c_setGpioDataBit( pI2C_Dev->sdio, data); /* sdio send 0 for ACK, 1 for NACK*/
+
+ //delay 1 us.
+ #ifdef __kernel_used__
+ udelay(1*I2C_RATING_FACTOR);
+ #endif
+ #ifdef __test_program_used__
+ for (i=0;i<1000*I2C_RATING_FACTOR;i++);
+ #endif
+
+ __i2c_setGpioDataBit( pI2C_Dev->sclk, 1); /* raise sclk*/
+ //delay 1 us.
+ #ifdef __kernel_used__
+ udelay(1*I2C_RATING_FACTOR);
+ #endif
+ #ifdef __test_program_used__
+ for (i=0;i<1000*I2C_RATING_FACTOR;i++);
+ #endif
+
+ __i2c_initGpioPin(pI2C_Dev->sdio, GPIO_DIR_IN, GPIO_INT_DISABLE);//change sdio to input
+ __i2c_setGpioDataBit( pI2C_Dev->sclk, 0); /* fall down sclk*/
+ #if 0
+ //delay 1 us.
+ #ifdef __kernel_used__
+ udelay(1*I2C_RATING_FACTOR);
+ #endif
+ #ifdef __test_program_used__
+ for (i=0;i<1000*I2C_RATING_FACTOR;i++);
+ #endif
+ #endif
+ return;
+}
+
+void i2c_serial_read(i2c_dev_t* pI2C_Dev, unsigned short int *data)
+{
+#ifdef __test_program_used__
+ int i;
+#endif
+ char j;
+ unsigned int buf;
+
+ *data = 0;
+
+ __i2c_initGpioPin(pI2C_Dev->sdio, GPIO_DIR_IN, GPIO_INT_DISABLE);//change sdio to input
+ for (j=7;j>=0;j--) {
+ __i2c_setGpioDataBit( pI2C_Dev->sclk, 0); /* fall down sclk*/
+ //delay 2 us.
+ #ifdef __kernel_used__
+ udelay(2*I2C_RATING_FACTOR);
+ #endif
+ #ifdef __test_program_used__
+ for (i=0;i<2000*I2C_RATING_FACTOR;i++);
+ #endif
+ __i2c_setGpioDataBit( pI2C_Dev->sclk, 1); /* raise sclk*/
+ __i2c_getGpioDataBit( pI2C_Dev->sdio, &buf);//read data,from MSB to LSB
+ *data |= (buf<<j);
+ //delay 1 us.
+ #ifdef __kernel_used__
+ udelay(1*I2C_RATING_FACTOR);
+ #endif
+ #ifdef __test_program_used__
+ for (i=0;i<1000*I2C_RATING_FACTOR;i++);
+ #endif
+ }
+ __i2c_initGpioPin(pI2C_Dev->sdio, GPIO_DIR_OUT, GPIO_INT_DISABLE);//change sdio to output
+ return;
+}
+
+void i2c_start_condition(i2c_dev_t* pI2C_Dev)
+{
+#ifdef __test_program_used__
+ int i;
+#endif
+
+ __i2c_initGpioPin(pI2C_Dev->sdio, GPIO_DIR_OUT, GPIO_INT_DISABLE);//change sdio to output
+ __i2c_setGpioDataBit( pI2C_Dev->sdio, 1); /* raise sdio*/
+ __i2c_setGpioDataBit( pI2C_Dev->sclk, 1); /* raise sclk*/
+ //delay 1 us.
+ #ifdef __kernel_used__
+ udelay(1*I2C_RATING_FACTOR);
+ #endif
+ #ifdef __test_program_used__
+ for (i=0;i<1000*I2C_RATING_FACTOR;i++);
+ #endif
+ __i2c_setGpioDataBit( pI2C_Dev->sdio, 0); /* fall down sdio*//*start condition*/
+ //delay 2 us.
+ #ifdef __kernel_used__
+ udelay(2*I2C_RATING_FACTOR);
+ #endif
+ #ifdef __test_program_used__
+ for (i=0;i<2000*I2C_RATING_FACTOR;i++);
+ #endif
+}
+
+void i2c_stop_condition(i2c_dev_t* pI2C_Dev)
+{
+#ifdef __test_program_used__
+ int i;
+#endif
+
+ __i2c_initGpioPin(pI2C_Dev->sdio, GPIO_DIR_OUT, GPIO_INT_DISABLE);//change sdio to output
+ __i2c_setGpioDataBit( pI2C_Dev->sclk, 0); /* fall down sclk*/
+ //delay 1 us.
+ #ifdef __kernel_used__
+ udelay(1*I2C_RATING_FACTOR);
+ #endif
+ #ifdef __test_program_used__
+ for (i=0;i<1000*I2C_RATING_FACTOR;i++);
+ #endif
+ __i2c_setGpioDataBit( pI2C_Dev->sdio, 0); /* fall down sdio*/
+ //delay 1 us.
+ #ifdef __kernel_used__
+ udelay(1*I2C_RATING_FACTOR);
+ #endif
+ #ifdef __test_program_used__
+ for (i=0;i<1000*I2C_RATING_FACTOR;i++);
+ #endif
+ __i2c_setGpioDataBit( pI2C_Dev->sclk, 1); /* raise sclk*/
+ //delay 1 us.
+ #ifdef __kernel_used__
+ udelay(1*I2C_RATING_FACTOR);
+ #endif
+ #ifdef __test_program_used__
+ for (i=0;i<1000*I2C_RATING_FACTOR;i++);
+ #endif
+ __i2c_setGpioDataBit( pI2C_Dev->sdio, 1); /* raise sdio*//*stop condition*/
+}
+
+void i2c_init_SCL_SDA(i2c_dev_t* pI2C_Dev)
+{
+ __i2c_initGpioPin(pI2C_Dev->sclk, GPIO_DIR_OUT, GPIO_INT_DISABLE);
+ __i2c_setGpioDataBit( pI2C_Dev->sclk, 1 );
+ __i2c_initGpioPin(pI2C_Dev->sdio, GPIO_DIR_OUT, GPIO_INT_DISABLE);
+ __i2c_setGpioDataBit( pI2C_Dev->sdio, 1 );
+ __i2c_setGpioDataBit( pI2C_Dev->reset, 1);
+}
+
+void i2c_enable_irq(i2c_dev_t* pI2C_Dev)
+{
+ __i2c_initGpioPin(pI2C_Dev->irq, GPIO_DIR_IN, GPIO_INT_BOTH_EDGE);
+}
+
+void i2c_reset(i2c_dev_t* pI2C_Dev)
+{
+ __i2c_initGpioPin(pI2C_Dev->reset, GPIO_DIR_OUT, GPIO_INT_DISABLE);
+ __i2c_setGpioDataBit( pI2C_Dev->reset, 1);
+ __i2c_setGpioDataBit( pI2C_Dev->reset, 0);
+ udelay( 3 ); // delay 3 us
+ __i2c_setGpioDataBit( pI2C_Dev->reset, 1);
+ udelay( 3 ); // delay 3us
+}
+
diff --git a/target/linux/realtek/files/drivers/serial/i2c.h b/target/linux/realtek/files/drivers/serial/i2c.h
new file mode 100644
index 000000000..f4bdcd99a
--- /dev/null
+++ b/target/linux/realtek/files/drivers/serial/i2c.h
@@ -0,0 +1,42 @@
+#ifndef __BASE_I2C_CORE_H__
+#define __BASE_I2C_CORE_H__
+
+
+/*********************** I2C data struct ********************************************/
+typedef struct i2c_dev_s
+{
+ //unsigned int i2c_reset; //output
+ unsigned int sclk; //output
+ unsigned int sdio; //input or output
+ unsigned int irq; // interrupt (optional)
+ unsigned int reset; // reset (optional)
+} i2c_dev_t;
+
+extern i2c_dev_t i2c_dev;
+
+/*********************** I2C API for base_ic2_xxx ********************************************/
+
+// read / write
+extern void i2c_serial_write(i2c_dev_t* pI2C_Dev, unsigned char *data);
+extern void i2c_serial_write_byte(i2c_dev_t* pI2C_Dev, unsigned char data);
+
+extern unsigned char i2c_ACK(i2c_dev_t* pI2C_Dev);
+
+extern void i2c_ACK_w(i2c_dev_t* pI2C_Dev, unsigned char data);
+
+extern void i2c_serial_read(i2c_dev_t* pI2C_Dev, unsigned short int *data);
+
+// start / stop condition
+extern void i2c_start_condition(i2c_dev_t* pI2C_Dev);
+
+extern void i2c_stop_condition(i2c_dev_t* pI2C_Dev);
+
+// GPIO pins manipulation
+extern void i2c_init_SCL_SDA(i2c_dev_t* pI2C_Dev);
+
+extern void i2c_enable_irq(i2c_dev_t* pI2C_Dev);
+
+extern void i2c_reset(i2c_dev_t* pI2C_Dev);
+
+#endif /* __BASE_I2C_CORE_H__ */
+