diff options
Diffstat (limited to 'target/linux/realtek/files/drivers/serial')
-rw-r--r-- | target/linux/realtek/files/drivers/serial/8250_sc16is7x0.c | 389 | ||||
-rw-r--r-- | target/linux/realtek/files/drivers/serial/gpio.h | 98 | ||||
-rw-r--r-- | target/linux/realtek/files/drivers/serial/gpio_8972b.c | 526 | ||||
-rw-r--r-- | target/linux/realtek/files/drivers/serial/gpio_8972b.h | 195 | ||||
-rw-r--r-- | target/linux/realtek/files/drivers/serial/i2c.c | 305 | ||||
-rw-r--r-- | target/linux/realtek/files/drivers/serial/i2c.h | 42 |
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__ */ + |