summaryrefslogtreecommitdiffstats
path: root/target/linux/realtek/files/drivers/char
diff options
context:
space:
mode:
authorRoman Yeryomin <roman@advem.lv>2012-09-13 00:40:35 +0300
committerRoman Yeryomin <roman@advem.lv>2012-12-03 00:13:21 +0200
commit5deb3317cb51ac52de922bb55f8492624018906d (patch)
treec2fbe6346699d9bb0f2100490c3029519bb8fde8 /target/linux/realtek/files/drivers/char
parent0239d37124f9184b478a42de8a7fa1bc85a6a6fe (diff)
Add realtek target files
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'target/linux/realtek/files/drivers/char')
-rw-r--r--target/linux/realtek/files/drivers/char/rtl_gpio.c1387
-rw-r--r--target/linux/realtek/files/drivers/char/rtl_mdio/Makefile2
-rw-r--r--target/linux/realtek/files/drivers/char/rtl_mdio/rtl_mdio.c1316
-rw-r--r--target/linux/realtek/files/drivers/char/rtl_mdio/rtl_mdio.h309
4 files changed, 3014 insertions, 0 deletions
diff --git a/target/linux/realtek/files/drivers/char/rtl_gpio.c b/target/linux/realtek/files/drivers/char/rtl_gpio.c
new file mode 100644
index 000000000..2269e7ded
--- /dev/null
+++ b/target/linux/realtek/files/drivers/char/rtl_gpio.c
@@ -0,0 +1,1387 @@
+/*
+ * FILE NAME rtl_gpio.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ * GPIO For Flash Reload Default
+ *
+ * Author: jimmylin@realtek.com.tw
+ *
+ * Copyright 2005 Realtek Semiconductor Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+//#define CONFIG_USING_JTAG 1
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/interrupt.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/reboot.h>
+#include <linux/kmod.h>
+#include <linux/proc_fs.h>
+//#include "bspchip.h"
+#define AUTO_CONFIG
+
+// 2009-0414
+//#define DET_WPS_SPEC
+#ifndef CONFIG_RTK_VOIP_DRIVERS_ATA_DECT //DECT SPI use GPIO E interrupt, need refine code to share irq.
+#ifndef CONFIG_SERIAL_SC16IS7X0 //SC16IS7x0 use GPIO E interrupt, too.
+#define USE_INTERRUPT_GPIO
+#endif
+#endif
+
+#if defined(CONFIG_RTL_8196C) || defined(CONFIG_RTL_8198)
+#ifndef CONFIG_RTK_VOIP
+ #define READ_RF_SWITCH_GPIO
+#endif
+#endif
+
+#if defined(CONFIG_RTL_8196C) || defined(CONFIG_RTL_8198)
+ #include "drivers/net/rtl819x/AsicDriver/rtl865xc_asicregs.h"
+/*define the GPIO physical address to customer_gpio.h*/
+#ifdef CONFIG_RTK_VOIP
+ #if defined (CONFIG_RTK_VOIP_GPIO_8954C_V100) || \
+ defined (CONFIG_RTK_VOIP_GPIO_8964C_QA)
+
+
+ // GPIO E7
+ #define RESET_PIN_IOBASE PEFGH_CNR //RTL_GPIO_PEFGH_CNR
+ #define RESET_PIN_DIRBASE PEFGH_DIR //RTL_GPIO_PEFGH_DIR
+ #define RESET_PIN_DATABASE PEFGH_DAT //RTL_GPIO_PEFGH_DATA
+ #define RESET_PIN_NO 7 //pin number of the EFGH
+
+ // GPIO G0
+ #define RESET_LED_IOBASE PEFCH_CNR //RTL_GPIO_PEFGH_CNR
+ #define RESET_LED_DIRBASE PEFGH_DIR //RTL_GPIO_PEFGH_DIR
+ #define RESET_LED_DATABASE PEFGH_DAT //RTL_GPIO_PEFGH_DATA
+ #define RESET_LED_NO 16 //pin number of the EFGH
+
+ // GPIO G1
+ #define AUTOCFG_LED_IOBASE PEFGH_CNR //RTL_GPIO_PEFGH_CNR
+ #define AUTOCFG_LED_DIRBASE PEFGH_DIR //RTL_GPIO_PEFGH_DIR
+ #define AUTOCFG_LED_DATABASE PEFGH_DAT //RTL_GPIO_PEFGH_DATA
+ #define AUTOCFG_LED_NO 17 //pin number of the EFGH
+
+ // GPIO E2
+ #define AUTOCFG_PIN_IOBASE PEFGH_CNR //RTL_GPIO_PEFGH_CNR
+ #define AUTOCFG_PIN_DIRBASE PEFGH_DIR //RTL_GPIO_PEFGH_DIR
+ #define AUTOCFG_PIN_DATABASE PEFGH_DAT //RTL_GPIO_PEFGH_DATA
+ #define AUTOCFG_PIN_NO 2 //pin number of the EFGH)
+
+ #define AUTOCFG_PIN_IMR PEF_IMR
+ #define RTL_GPIO_MUX_DATA 0x00004300 //MUX for GPIO
+
+ #elif defined(CONFIG_RTK_VOIP_GPIO_8954C_V200) || \
+ defined(CONFIG_RTK_VOIP_GPIO_8954C_V400)
+
+ // GPIO F4 DEFAULT_Button
+ #define RESET_PIN_IOBASE PEFGH_CNR //RTL_GPIO_PEFGH_CNR
+ #define RESET_PIN_DIRBASE PEFGH_DIR //RTL_GPIO_PEFGH_DIR
+ #define RESET_PIN_DATABASE PEFGH_DAT //RTL_GPIO_PEFGH_DATA
+ #define RESET_PIN_NO 12 //pin number of the EFGH
+
+ // GPIO E7 SYS LED
+ #define RESET_LED_IOBASE PEFGH_CNR //RTL_GPIO_PEFGH_CNR
+ #define RESET_LED_DIRBASE PEFGH_DIR //RTL_GPIO_PEFGH_DIR
+ #define RESET_LED_DATABASE PEFGH_DAT //RTL_GPIO_PEFGH_DATA
+ #define RESET_LED_NO 7 //number of the EFGH
+
+ // GPIO F0 WPS LED
+ #define AUTOCFG_LED_IOBASE PEFGH_CNR //RTL_GPIO_PEFGH_CNR
+ #define AUTOCFG_LED_DIRBASE PEFGH_DIR //RTL_GPIO_PEFGH_DIR
+ #define AUTOCFG_LED_DATABASE PEFGH_DAT //RTL_GPIO_PEFGH_DATA
+ #define AUTOCFG_LED_NO 8 //pin number of the EFGH
+
+ // GPIO F3 WPS Button
+ #define AUTOCFG_PIN_IOBASE PEFGH_CNR //RTL_GPIO_PEFGH_CNR
+ #define AUTOCFG_PIN_DIRBASE PEFGH_DIR //RTL_GPIO_PEFGH_DIR
+ #define AUTOCFG_PIN_DATABASE PEFGH_DAT //RTL_GPIO_PEFGH_DATA
+ #define AUTOCFG_PIN_NO 11 //pin number of the EFGH
+ #define AUTOCFG_PIN_IMR PEF_IMR
+ #define RTL_GPIO_MUX_DATA 0x00000300 //MUX for GPIO
+ #endif
+
+ #define RTL_GPIO_MUX 0xB8000040
+
+ //#define RTL_GPIO_WIFI_ONOFF 19
+ #define AUTOCFG_BTN_PIN AUTOCFG_PIN_NO
+ #define AUTOCFG_LED_PIN AUTOCFG_LED_NO
+ #define RESET_LED_PIN RESET_LED_NO
+ #define RESET_BTN_PIN RESET_PIN_NO
+
+#else
+#if defined(CONFIG_RTL_8196C)
+ #if defined(CONFIG_RTL_8196CS)
+ #define PCIE0_BASE 0xb9000000
+ #define PCIE_BASE_OFFSET (PCIE0_BASE+0x40)
+ #define PCIE_PIN_MUX PCIE_BASE_OFFSET
+ #define RESET_PIN_IOBASE (PCIE_BASE_OFFSET+4)
+ #define WPS_PIN_IOBASE (PCIE_BASE_OFFSET+4)
+ #define WPS_LED_IOBASE (PCIE_BASE_OFFSET)
+ #define PCIE_GPIO_IMR (PCIE_BASE_OFFSET+8)
+ #define MODE_MARSK 24
+ #define MODE_MARSK1 28
+ #define DIR_MASK 16
+ #define DIR_MASK1 24
+ #define IN_MASK 0
+ #define OUT_MASK 8
+ #define OUT_MASK1 20
+
+ // GPIO A0
+ //#define RESET_PIN_IOBASE RESET_PIN_IOBASE //RTL_GPIO_PABCD_CNR
+ #define RESET_PIN_DIRBASE RESET_PIN_IOBASE //RTL_GPIO_PABCD_DIR
+ #define RESET_PIN_DATABASE RESET_PIN_IOBASE //RTL_GPIO_PABCD_DATA
+ #define RESET_PIN_NO 0 /*number of the ABCD*/
+
+ // GPIO C2
+ #define RESET_LED_IOBASE PABCD_CNR //RTL_GPIO_PABCD_CNR
+ #define RESET_LED_DIRBASE PABCD_DIR //RTL_GPIO_PABCD_DIR
+ #define RESET_LED_DATABASE PABCD_DAT //RTL_GPIO_PABCD_DATA
+ #define RESET_LED_NO 2 /*number of the ABCD*/
+
+ // GPIO C4
+ #define AUTOCFG_LED_IOBASE WPS_LED_IOBASE //RTL_GPIO_PABCD_CNR
+ #define AUTOCFG_LED_DIRBASE WPS_LED_IOBASE //RTL_GPIO_PABCD_DIR
+ #define AUTOCFG_LED_DATABASE WPS_LED_IOBASE //RTL_GPIO_PABCD_DATA
+ #define AUTOCFG_LED_NO 20 /*number of the ABCD*/
+
+ // GPIO A1
+ #define AUTOCFG_PIN_IOBASE WPS_PIN_IOBASE //RTL_GPIO_PABCD_CNR
+ #define AUTOCFG_PIN_DIRBASE WPS_PIN_IOBASE //RTL_GPIO_PABCD_DIR
+ #define AUTOCFG_PIN_DATABASE WPS_PIN_IOBASE //RTL_GPIO_PABCD_DATA
+ #define AUTOCFG_PIN_NO 2 /*number of the ABCD)*/
+ #define AUTOCFG_PIN_IMR PCIE_GPIO_IMR
+ #else
+ // GPIO A0
+ #define RESET_PIN_IOBASE PABCD_CNR //RTL_GPIO_PABCD_CNR
+ #define RESET_PIN_DIRBASE PABCD_DIR //RTL_GPIO_PABCD_DIR
+ #define RESET_PIN_DATABASE PABCD_DAT //RTL_GPIO_PABCD_DATA
+ #define RESET_PIN_NO 0 /*number of the ABCD*/
+
+ // GPIO C2
+ #define RESET_LED_IOBASE PABCD_CNR //RTL_GPIO_PABCD_CNR
+ #define RESET_LED_DIRBASE PABCD_DIR //RTL_GPIO_PABCD_DIR
+ #define RESET_LED_DATABASE PABCD_DAT //RTL_GPIO_PABCD_DATA
+ #define RESET_LED_NO 18 /*number of the ABCD*/
+
+ // GPIO C4
+ #define AUTOCFG_LED_IOBASE PABCD_CNR //RTL_GPIO_PABCD_CNR
+ #define AUTOCFG_LED_DIRBASE PABCD_DIR //RTL_GPIO_PABCD_DIR
+ #define AUTOCFG_LED_DATABASE PABCD_DAT //RTL_GPIO_PABCD_DATA
+ #define AUTOCFG_LED_NO 20 /*number of the ABCD*/
+
+ // GPIO A1
+ #define AUTOCFG_PIN_IOBASE PABCD_CNR //RTL_GPIO_PABCD_CNR
+ #define AUTOCFG_PIN_DIRBASE PABCD_DIR //RTL_GPIO_PABCD_DIR
+ #define AUTOCFG_PIN_DATABASE PABCD_DAT //RTL_GPIO_PABCD_DATA
+ #define AUTOCFG_PIN_NO 1 /*number of the ABCD)*/
+ #define AUTOCFG_PIN_IMR PAB_IMR
+ #endif
+#ifdef CONFIG_POCKET_ROUTER_SUPPORT
+ #define RTL_GPIO_MUX_GPIOA2 (3<<20)
+ #define RTL_GPIO_MUX_GPIOB3 (3<<2)
+ #define RTL_GPIO_MUX_GPIOB2 (3<<0)
+ #define RTL_GPIO_MUX_GPIOC0 (3<<12)
+ #define RTL_GPIO_MUX_POCKETAP_DATA (RTL_GPIO_MUX_GPIOA2 | RTL_GPIO_MUX_GPIOB3 | RTL_GPIO_MUX_GPIOB2 | RTL_GPIO_MUX_GPIOC0)
+
+ #define RTL_GPIO_CNR_GPIOA2 (1<<2)
+ #define RTL_GPIO_CNR_GPIOB3 (1<<11)
+ #define RTL_GPIO_CNR_GPIOB2 (1<<10)
+ #define RTL_GPIO_CNR_GPIOC0 (1<<16)
+ #define RTL_GPIO_CNR_POCKETAP_DATA (RTL_GPIO_CNR_GPIOA2 | RTL_GPIO_CNR_GPIOB3 | RTL_GPIO_CNR_GPIOB2 | RTL_GPIO_CNR_GPIOC0)
+
+ #define RTL_GPIO_DIR_GPIOA2 (1<<2) /* &- */
+ #define RTL_GPIO_DIR_GPIOB3 (1<<11) /* &- */
+ #define RTL_GPIO_DIR_GPIOB2 (1<<10) /* |*/
+ #define RTL_GPIO_DIR_GPIOC0 (1<<16) /* &- */
+
+ #define RTL_GPIO_DAT_GPIOA2 (1<<2)
+ #define RTL_GPIO_DAT_GPIOB3 (1<<11)
+ #define RTL_GPIO_DAT_GPIOB2 (1<<10)
+ #define RTL_GPIO_DAT_GPIOC0 (1<<16)
+
+ static int ap_cli_rou_time_state[2] = {0};
+ static char ap_cli_rou_state = 0;
+ static char ap_cli_rou_idx=0;
+ static char pocketAP_hw_set_flag='0';
+
+ static char dc_pwr_plugged_time_state = 0;
+ static char dc_pwr_plugged_state = 0;
+ static char dc_pwr_plugged_flag = '0';
+
+ static int pwr_saving_state=0;
+ static char pwr_saving_led_toggle = 0;
+#endif
+
+
+#elif defined(CONFIG_RTL_8198)
+ // GPIO H1
+ #define RESET_PIN_IOBASE PEFGH_CNR //RTL_GPIO_PABCD_CNR
+ #define RESET_PIN_DIRBASE PEFGH_DIR //RTL_GPIO_PABCD_DIR
+ #define RESET_PIN_DATABASE PEFGH_DAT //RTL_GPIO_PABCD_DATA
+ #define RESET_PIN_NO 25 /*number of the ABCD*/
+
+ // GPIO H3
+ #define RESET_LED_IOBASE PEFGH_CNR //RTL_GPIO_PABCD_CNR
+ #define RESET_LED_DIRBASE PEFGH_DIR //RTL_GPIO_PABCD_DIR
+ #define RESET_LED_DATABASE PEFGH_DAT //RTL_GPIO_PABCD_DATA
+ #define RESET_LED_NO 27 /*number of the ABCD*/
+
+ // GPIO G4
+ #define AUTOCFG_LED_IOBASE PEFGH_CNR //RTL_GPIO_PABCD_CNR
+ #define AUTOCFG_LED_DIRBASE PEFGH_DIR //RTL_GPIO_PABCD_DIR
+ #define AUTOCFG_LED_DATABASE PEFGH_DAT //RTL_GPIO_PABCD_DATA
+ #define AUTOCFG_LED_NO 20 /*number of the ABCD*/
+
+ // GPIO E1
+ #define AUTOCFG_PIN_IOBASE PEFGH_CNR //RTL_GPIO_PABCD_CNR
+ #define AUTOCFG_PIN_DIRBASE PEFGH_DIR //RTL_GPIO_PABCD_DIR
+ #define AUTOCFG_PIN_DATABASE PEFGH_DAT //RTL_GPIO_PABCD_DATA
+ #define AUTOCFG_PIN_NO 1 /*number of the ABCD)*/
+ #define AUTOCFG_PIN_IMR PGH_IMR
+
+#endif
+ // GPIO C3
+ #define WIFI_ONOFF_PIN_IOBASE PABCD_CNR //RTL_GPIO_PABCD_CNR
+ #define WIFI_ONOFF_PIN_DIRBASE PABCD_DIR //RTL_GPIO_PABCD_DIR
+ #define WIFI_ONOFF_PIN_DATABASE PABCD_DAT //RTL_GPIO_PABCD_DATA
+ #define WIFI_ONOFF_PIN_NO 19/*umber of the ABCD)*/
+ #define WIFI_ONOFF_PIN_IMR PAB_IMR
+
+/*
+ #define RTL_GPIO_MUX 0xB8000030
+ #define RTL_GPIO_MUX_DATA 0x0FC00380//for WIFI ON/OFF and GPIO
+
+
+
+ #define AUTOCFG_BTN_PIN AUTOCFG_PIN_NO // 1
+ #define AUTOCFG_LED_PIN AUTOCFG_LED_NO//20
+ #define RESET_LED_PIN RESET_LED_NO //18
+ #define RESET_BTN_PIN RESET_PIN_NO //0
+ #define RTL_GPIO_WIFI_ONOFF WIFI_ONOFF_PIN_NO
+*/
+ #define RTL_GPIO_MUX 0xB8000040
+ #ifdef CONFIG_8198_PORT5_GMII
+ #define RTL_GPIO_MUX_DATA 0x00340000
+ #else
+ #define RTL_GPIO_MUX_DATA 0x00340C00//for WIFI ON/OFF and GPIO
+ #endif
+ #define RTL_GPIO_WIFI_ONOFF 19
+
+#if defined(CONFIG_RTL_8196C)
+ #if defined(CONFIG_RTL_8196CS)
+ #define AUTOCFG_BTN_PIN 2
+ #define AUTOCFG_LED_PIN 1
+ #define RESET_LED_PIN 2
+ #define RESET_BTN_PIN 0
+ #else
+ #define AUTOCFG_BTN_PIN 3
+ #define AUTOCFG_LED_PIN 4
+ #define RESET_LED_PIN 6
+ #define RESET_BTN_PIN 5
+ #endif
+
+#elif defined(CONFIG_RTL_8198)
+ #define AUTOCFG_BTN_PIN 24
+ #define AUTOCFG_LED_PIN 26
+ #define RESET_LED_PIN 27
+ #define RESET_BTN_PIN 25
+#endif
+
+#endif // CONFIG_RTK_VOIP
+#endif // CONFIG_RTL_8196C || CONFIG_RTL_8198
+
+// 2009-0414
+#ifdef USE_INTERRUPT_GPIO
+#ifdef CONFIG_RTK_VOIP
+ #define GPIO_IRQ_NUM (16+17) // GPIO_EFGH
+#else
+ #define GPIO_IRQ_NUM 1
+#endif
+#endif
+
+ #define PROBE_TIME 5
+
+
+#define PROBE_NULL 0
+#define PROBE_ACTIVE 1
+#define PROBE_RESET 2
+#define PROBE_RELOAD 3
+#define RTL_R32(addr) (*(volatile unsigned long *)(addr))
+#define RTL_W32(addr, l) ((*(volatile unsigned long*)(addr)) = (l))
+#define RTL_R8(addr) (*(volatile unsigned char*)(addr))
+#define RTL_W8(addr, l) ((*(volatile unsigned char*)(addr)) = (l))
+
+//#define GPIO_DEBUG
+#ifdef GPIO_DEBUG
+/* note: prints function name for you */
+# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
+#else
+# define DPRINTK(fmt, args...)
+#endif
+
+static struct timer_list probe_timer;
+static unsigned int probe_counter;
+static unsigned int probe_state;
+
+static char default_flag='0';
+//Brad add for update flash check 20080711
+int start_count_time=0;
+int Reboot_Wait=0;
+
+static int get_dc_pwr_plugged_state();
+
+
+
+//#ifdef CONFIG_RTL865X_AC
+
+#ifdef CONFIG_POCKET_ROUTER_SUPPORT
+static struct timer_list pocket_ap_timer;
+#endif
+
+#ifdef USE_INTERRUPT_GPIO
+static int wps_button_push = 0;
+
+#endif
+#if defined(CONFIG_RTL_8196CS)
+void update_pcie_status(void)
+{
+ unsigned int temp;
+ temp=RTL_R32(0xb8b00728);
+ temp=RTL_R32(PCIE_PIN_MUX);
+ temp=RTL_R32(RESET_PIN_DATABASE);
+
+
+ //printk("LINE: %x d:%x * %x****R:%x\n",__LINE__,RTL_R32(0xb8b00728),RTL_R32(PCIE_PIN_MUX),RTL_R32(RESET_PIN_DATABASE));
+}
+#endif
+
+#ifdef AUTO_CONFIG
+static unsigned int AutoCfg_LED_Blink;
+static unsigned int AutoCfg_LED_Toggle;
+static unsigned int AutoCfg_LED_Slow_Blink;
+static unsigned int AutoCfg_LED_Slow_Toggle;
+
+void autoconfig_gpio_init(void)
+{
+#if defined(CONFIG_RTL_8196CS)
+ RTL_W32(AUTOCFG_PIN_IOBASE,(RTL_R32(AUTOCFG_PIN_IOBASE)&(~((1 << AUTOCFG_BTN_PIN)<<MODE_MARSK))));
+ RTL_W32(AUTOCFG_LED_IOBASE,(RTL_R32(AUTOCFG_LED_IOBASE)&(~((1 << AUTOCFG_LED_PIN)<<MODE_MARSK1))));
+
+ // Set GPIOA pin 1 as input pin for auto config button
+ RTL_W32(AUTOCFG_PIN_DIRBASE, (RTL_R32(AUTOCFG_PIN_DIRBASE) & (~(((1 << AUTOCFG_BTN_PIN))<<DIR_MASK1))));
+
+ // Set GPIOA ping 3 as output pin for auto config led
+ RTL_W32(AUTOCFG_LED_DIRBASE, (RTL_R32(AUTOCFG_LED_DIRBASE) | ((1 << AUTOCFG_LED_PIN)<<DIR_MASK1)));
+
+ // turn off auto config led in the beginning
+ RTL_W32(AUTOCFG_LED_DATABASE, (RTL_R32(AUTOCFG_LED_DATABASE) | ((1 << AUTOCFG_LED_PIN)<<OUT_MASK1)));
+ update_pcie_status();
+ //printk("LINE: %x d:%x * %x****R:%x\n",__LINE__,RTL_R32(0xb8b00728),RTL_R32(PCIE_PIN_MUX),RTL_R32(RESET_PIN_DATABASE));
+#else
+ RTL_W32(AUTOCFG_PIN_IOBASE,(RTL_R32(AUTOCFG_PIN_IOBASE)&(~(1 << AUTOCFG_BTN_PIN))));
+ RTL_W32(AUTOCFG_LED_IOBASE,(RTL_R32(AUTOCFG_LED_IOBASE)&(~(1 << AUTOCFG_LED_PIN))));
+
+ // Set GPIOA pin 1 as input pin for auto config button
+ RTL_W32(AUTOCFG_PIN_DIRBASE, (RTL_R32(AUTOCFG_PIN_DIRBASE) & (~(1 << AUTOCFG_BTN_PIN))));
+
+ // Set GPIOA ping 3 as output pin for auto config led
+ RTL_W32(AUTOCFG_LED_DIRBASE, (RTL_R32(AUTOCFG_LED_DIRBASE) | (1 << AUTOCFG_LED_PIN)));
+
+ // turn off auto config led in the beginning
+ RTL_W32(AUTOCFG_LED_DATABASE, (RTL_R32(AUTOCFG_LED_DATABASE) | (1 << AUTOCFG_LED_PIN)));
+#endif
+}
+#ifdef CONFIG_RTL_8196C_GW_MP
+
+void all_led_on(void)
+{
+ //printk("Into MP GPIO");
+ #ifdef CONFIG_RTL_8196C_GW_MP
+ RTL_W32(0xB8000030, (RTL_R32(0xB8000030) | 0x00F00F80 ));
+ RTL_W32(PABCD_CNR, (RTL_R32(PABCD_CNR) & (~(1 << PS_LED_GREEN_PIN))));
+ RTL_W32(PABCD_CNR, (RTL_R32(PABCD_CNR) & (~(1 << PS_LED_ORANGE_PIN))));
+
+ RTL_W32(PABCD_DIR, (RTL_R32(PABCD_DIR) | (1 << PS_LED_GREEN_PIN)));
+ RTL_W32(PABCD_DIR, (RTL_R32(PABCD_DIR) | (1 << PS_LED_ORANGE_PIN)));
+
+ RTL_W32(PABCD_DAT, (RTL_R32(PABCD_DAT) | (1 << PS_LED_GREEN_PIN)));
+ RTL_W32(PABCD_DAT, (RTL_R32(PABCD_DAT) & (~(1 << PS_LED_ORANGE_PIN))));
+
+ /* inet_led init setting */
+ RTL_W32(PABCD_CNR, (RTL_R32(PABCD_CNR) & (~(1 << INET_LED_GREEN_PIN))));
+ RTL_W32(PABCD_CNR, (RTL_R32(PABCD_CNR) & (~(1 << INET_LED_ORANGE_PIN))));
+
+ RTL_W32(PABCD_DIR, (RTL_R32(PABCD_DIR) | (1 << INET_LED_GREEN_PIN)));
+ RTL_W32(PABCD_DIR, (RTL_R32(PABCD_DIR) | (1 << INET_LED_ORANGE_PIN)));
+
+ RTL_W32(AUTOCFG_LED_DIRBASE, (RTL_R32(AUTOCFG_LED_DIRBASE) & (~(1 << AUTOCFG_LED_PIN_MP))));
+
+ RTL_W32(PABCD_DIR, (RTL_R32(PABCD_DIR) | (1 << AUTOCFG_LED_PIN_MP)));
+
+ //RTL_W32(PABCD_DAT, (RTL_R32(PABCD_DAT) & (~(1 << INET_LED_GREEN_PIN))));
+ //RTL_W32(PABCD_DAT, (RTL_R32(PABCD_DAT) | (1 << INET_LED_ORANGE_PIN)));
+ RTL_W32(PABCD_DAT, (RTL_R32(PABCD_DAT) & (~(1 << PS_LED_GREEN_PIN))));
+ RTL_W32(PABCD_DAT, (RTL_R32(PABCD_DAT) & (~(1 << PS_LED_ORANGE_PIN))));
+ RTL_W32(PABCD_DAT, (RTL_R32(PABCD_DAT) & (~(1 << INET_LED_GREEN_PIN))));
+ RTL_W32(PABCD_DAT, (RTL_R32(PABCD_DAT) & (~(1 << INET_LED_ORANGE_PIN))));
+ RTL_W32(PABCD_DAT, (RTL_R32(PABCD_DAT) & (~(1 << AUTOCFG_LED_PIN_MP))));
+ RTL_W32(RESET_LED_DATABASE, (RTL_R32(RESET_LED_DATABASE) & (~(1 << RESET_LED_PIN_MP))));
+ #endif
+
+}
+#endif
+#if defined(CONFIG_RTL_8196CS)
+
+void autoconfig_gpio_off(void)
+{
+ RTL_W32(AUTOCFG_LED_DATABASE, (RTL_R32(AUTOCFG_LED_DATABASE) | ((1 << AUTOCFG_LED_PIN)<<OUT_MASK1)));
+ AutoCfg_LED_Blink = 0;
+ update_pcie_status();
+ //printk("LINE: %x d:%x * %x****R:%x\n",__LINE__,RTL_R32(0xb8b00728),RTL_R32(PCIE_PIN_MUX),RTL_R32(RESET_PIN_DATABASE));
+}
+
+
+void autoconfig_gpio_on(void)
+{
+ RTL_W32(AUTOCFG_LED_DATABASE, (RTL_R32(AUTOCFG_LED_DATABASE) & (~((1 << AUTOCFG_LED_PIN)<<OUT_MASK1))));
+ //printk("LINE: %x d:%x * %x****R:%x\n",__LINE__,RTL_R32(0xb8b00728),RTL_R32(PCIE_PIN_MUX),RTL_R32(RESET_PIN_DATABASE));
+ update_pcie_status();
+ AutoCfg_LED_Blink = 0;
+}
+
+
+void autoconfig_gpio_blink(void)
+{
+ RTL_W32(AUTOCFG_LED_DATABASE, (RTL_R32(AUTOCFG_LED_DATABASE) & (~((1 << AUTOCFG_LED_PIN)<<OUT_MASK1))));
+ //printk("LINE: %x d:%x * %x****R:%x\n",__LINE__,RTL_R32(0xb8b00728),RTL_R32(PCIE_PIN_MUX),RTL_R32(RESET_PIN_DATABASE));
+ update_pcie_status();
+ AutoCfg_LED_Blink = 1;
+ AutoCfg_LED_Toggle = 1;
+
+}
+
+
+
+#else
+void autoconfig_gpio_off(void)
+{
+ RTL_W32(AUTOCFG_LED_DATABASE, (RTL_R32(AUTOCFG_LED_DATABASE) | (1 << AUTOCFG_LED_PIN)));
+ AutoCfg_LED_Blink = 0;
+}
+
+
+void autoconfig_gpio_on(void)
+{
+ RTL_W32(AUTOCFG_LED_DATABASE, (RTL_R32(AUTOCFG_LED_DATABASE) & (~(1 << AUTOCFG_LED_PIN))));
+ AutoCfg_LED_Blink = 0;
+}
+
+
+void autoconfig_gpio_blink(void)
+{
+ RTL_W32(AUTOCFG_LED_DATABASE, (RTL_R32(AUTOCFG_LED_DATABASE) & (~(1 << AUTOCFG_LED_PIN))));
+
+ AutoCfg_LED_Blink = 1;
+ AutoCfg_LED_Toggle = 1;
+ AutoCfg_LED_Slow_Blink = 0;
+
+}
+
+void autoconfig_gpio_slow_blink(void)
+{
+ RTL_W32(AUTOCFG_LED_DATABASE, (RTL_R32(AUTOCFG_LED_DATABASE) & (~(1 << AUTOCFG_LED_PIN))));
+
+ AutoCfg_LED_Blink = 1;
+ AutoCfg_LED_Toggle = 1;
+ AutoCfg_LED_Slow_Blink = 1;
+ AutoCfg_LED_Slow_Toggle = 1;
+
+}
+
+#endif
+
+
+#endif // AUTO_CONFIG
+
+
+
+
+static void rtl_gpio_timer(unsigned long data)
+{
+ unsigned int pressed=1;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+ struct pid *pid;
+#endif
+#if defined(CONFIG_RTL_8196CS)
+ update_pcie_status();
+#endif
+#if defined(CONFIG_RTL_8196C) || defined(CONFIG_RTL_8198)
+
+ if ((RTL_R32(RESET_PIN_DATABASE) & (1 << RESET_BTN_PIN)))
+
+#endif
+ {
+ pressed = 0;
+
+ //turn off LED0
+ #ifndef CONFIG_RTL_8196C_GW_MP
+ RTL_W32(RESET_LED_DATABASE, (RTL_R32(RESET_LED_DATABASE) | ((1 << RESET_LED_PIN))));
+ #endif
+ }
+ else
+ {
+ DPRINTK("Key pressed %d!\n", probe_counter+1);
+ }
+
+ if (RTL_R32(AUTOCFG_PIN_DATABASE) & (1 << AUTOCFG_BTN_PIN)){
+ wps_button_push = 0;
+ }else{
+ wps_button_push++;
+ }
+
+ if (probe_state == PROBE_NULL)
+ {
+ if (pressed)
+ {
+ probe_state = PROBE_ACTIVE;
+ probe_counter++;
+ }
+ else
+ probe_counter = 0;
+ }
+ else if (probe_state == PROBE_ACTIVE)
+ {
+ if (pressed)
+ {
+ probe_counter++;
+
+ if ((probe_counter >=2 ) && (probe_counter <=PROBE_TIME))
+ {
+ DPRINTK("2-5 turn on led\n");
+ //turn on LED0
+ RTL_W32(RESET_LED_DATABASE, (RTL_R32(RESET_LED_DATABASE) & (~(1 << RESET_LED_PIN))));
+ }
+ else if (probe_counter >= PROBE_TIME)
+ {
+ // sparkling LED0
+ DPRINTK(">5 \n");
+
+ if (probe_counter & 1)
+ RTL_W32(RESET_LED_DATABASE, (RTL_R32(RESET_LED_DATABASE) | ((1 << RESET_LED_PIN))));
+ else
+ RTL_W32(RESET_LED_DATABASE, (RTL_R32(RESET_LED_DATABASE) & (~(1 << RESET_LED_PIN))));
+ }
+ }
+ else
+ {
+ #if defined(CONFIG_RTL865X_SC)
+ if (probe_counter < 5)
+ #else
+ if (probe_counter < 2)
+ #endif
+ {
+ probe_state = PROBE_NULL;
+ probe_counter = 0;
+ DPRINTK("<2 \n");
+ #if defined(CONFIG_RTL865X_SC)
+ ResetToAutoCfgBtn = 1;
+ #endif
+ }
+ else if (probe_counter >= PROBE_TIME)
+ {
+
+
+ //reload default
+ default_flag = '1';
+
+ //kernel_thread(reset_flash_default, (void *)1, SIGCHLD);
+ return;
+
+ }
+ else
+ {
+ DPRINTK("2-5 reset 1\n");
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
+ kill_proc(1,SIGTERM,1);
+ #else
+ pid = get_pid(find_vpid(1));
+ kill_pid(pid,SIGTERM,1);
+ #endif
+ DPRINTK("2-5 reset 2\n");
+ //kernel_thread(reset_flash_default, 0, SIGCHLD);
+ return;
+ }
+ }
+ }
+
+#ifdef AUTO_CONFIG
+ if (AutoCfg_LED_Blink==1)
+ {
+ if (AutoCfg_LED_Toggle) {
+ #if defined(CONFIG_RTL_8196CS)
+ RTL_W32(AUTOCFG_LED_DATABASE, (RTL_R32(AUTOCFG_LED_DATABASE) | ((1 << AUTOCFG_LED_PIN)<<OUT_MASK1)));
+ #else
+ RTL_W32(AUTOCFG_LED_DATABASE, (RTL_R32(AUTOCFG_LED_DATABASE) | (1 << AUTOCFG_LED_PIN)));
+ #endif
+ }
+ else {
+ #if defined(CONFIG_RTL_8196CS)
+ RTL_W32(AUTOCFG_LED_DATABASE, (RTL_R32(AUTOCFG_LED_DATABASE) & (~((1 << AUTOCFG_LED_PIN)<<OUT_MASK1))));
+ #else
+ RTL_W32(AUTOCFG_LED_DATABASE, (RTL_R32(AUTOCFG_LED_DATABASE) & (~(1 << AUTOCFG_LED_PIN))));
+ #endif
+
+ }
+
+ if(AutoCfg_LED_Slow_Blink)
+ {
+ if(AutoCfg_LED_Slow_Toggle)
+ AutoCfg_LED_Toggle = AutoCfg_LED_Toggle;
+ else
+ AutoCfg_LED_Toggle = AutoCfg_LED_Toggle? 0 : 1;
+
+ AutoCfg_LED_Slow_Toggle = AutoCfg_LED_Slow_Toggle? 0 : 1;
+ }
+ else
+ AutoCfg_LED_Toggle = AutoCfg_LED_Toggle? 0 : 1;
+
+ }
+#endif
+
+
+ mod_timer(&probe_timer, jiffies + HZ);
+
+}
+
+#ifdef CONFIG_RTL_FLASH_DUAL_IMAGE_ENABLE
+
+#define SYSTEM_CONTRL_DUMMY_REG 0xb8000068
+
+int is_bank2_root()
+{
+ //boot code will steal System's dummy register bit0 (set to 1 ---> bank2 booting
+ //for 8198 formal chip
+ if ((RTL_R32(SYSTEM_CONTRL_DUMMY_REG)) & (0x00000001)) // steal for boot bank idenfy
+ return 1;
+
+ return 0;
+}
+static int read_bootbank_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+ char flag='1';
+
+ if (is_bank2_root()) // steal for boot bank idenfy
+ flag='2';
+
+ len = sprintf(page, "%c\n", flag);
+
+ if (len <= off+count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len > count) len = count;
+ if (len < 0) len = 0;
+ return len;
+}
+#endif
+
+#ifdef AUTO_CONFIG
+#if defined(USE_INTERRUPT_GPIO)
+static irqreturn_t gpio_interrupt_isr(int irq, void *dev_instance, struct pt_regs *regs)
+{
+ wps_button_push = 1;
+#ifdef CONFIG_RTK_VOIP
+ RTL_W32(PEFGH_ISR, RTL_R32(PEFGH_ISR));
+#else
+ RTL_W32(PABCD_ISR, RTL_R32(PABCD_ISR));
+#endif
+ return IRQ_HANDLED;
+}
+#endif
+
+static int read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+ char flag;
+
+#if defined(USE_INTERRUPT_GPIO)
+// 2009-0414
+ if (wps_button_push) {
+ flag = '1';
+ //wps_button_push = 0; //mark it for select wlan interface by button pressed time
+ }
+ else{
+ if (RTL_R32(AUTOCFG_PIN_DATABASE) & (1 << AUTOCFG_BTN_PIN)){
+ flag = '0';
+ }else{
+ //printk("wps button be held \n");
+ flag = '1';
+ }
+
+ }
+// 2009-0414
+#else
+
+ if (RTL_R32(AUTOCFG_PIN_DATABASE) & (1 << AUTOCFG_BTN_PIN))
+ flag = '0';
+ else {
+ flag = '1';
+ }
+#endif // CONFIG_RTL865X_KLD
+
+ len = sprintf(page, "%c\n", flag);
+
+
+ if (len <= off+count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len > count) len = count;
+ if (len < 0) len = 0;
+ return len;
+}
+
+
+
+#ifdef CONFIG_RTL_KERNEL_MIPS16_CHAR
+__NOMIPS16
+#endif
+static int write_proc(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char flag[20];
+//Brad add for update flash check 20080711
+
+ char start_count[10], wait[10];
+
+ if (count < 2)
+ return -EFAULT;
+
+ DPRINTK("file: %08x, buffer: %s, count: %lu, data: %08x\n",
+ (unsigned int)file, buffer, count, (unsigned int)data);
+
+ if (buffer && !copy_from_user(&flag, buffer, 1)) {
+ if (flag[0] == 'E') {
+ autoconfig_gpio_init();
+ #ifdef CONFIG_RTL865X_CMO
+ extra_led_gpio_init();
+ #endif
+ }
+ else if (flag[0] == '0')
+ autoconfig_gpio_off();
+ else if (flag[0] == '1')
+ autoconfig_gpio_on();
+ else if (flag[0] == '2')
+ autoconfig_gpio_blink();
+#ifndef CONFIG_RTL_8196CS
+ else if (flag[0] == '3')
+ autoconfig_gpio_slow_blink();
+#endif
+
+#ifdef CONFIG_RTL_8196C_GW_MP
+ else if (flag[0] == '9') // disable system led
+ {
+ all_led_on();
+ }
+#endif
+
+#ifdef CONFIG_RTL865X_CMO
+ else if (flag[0] == '3')
+ wep_wpa_led_on();
+ else if (flag[0] == '5')
+ wep_wpa_led_off();
+ else if (flag[0] == '6')
+ mac_ctl_led_on();
+ else if (flag[0] == '7')
+ mac_ctl_led_off();
+ else if (flag[0] == '8')
+ bridge_repeater_led_on();
+ else if (flag[0] == '9')
+ bridge_repeater_led_off();
+ else if (flag[0] == 'A')
+ system_led_on();
+// else if (flag[0] == 'B')
+// system_led_off();
+ else if (flag[0] == 'C')
+ lan_led_on();
+ else if (flag[0] == 'D')
+ lan_led_off();
+ else if (flag[0] == 'Z')
+ printk("gpio test test\n");
+// else if (flag[0] == '9')
+// system_led_blink = 2;
+#endif
+
+//Brad add for update flash check 20080711
+
+ else if (flag[0] == '4'){
+ start_count_time= 1;
+ sscanf(buffer, "%s %s", start_count, wait);
+ Reboot_Wait = (simple_strtol(wait,NULL,0))*100;
+ }
+
+
+ else
+ {}
+
+ return count;
+ }
+ else
+ return -EFAULT;
+}
+#endif // AUTO_CONFIG
+
+static int default_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+
+ len = sprintf(page, "%c\n", default_flag);
+ if (len <= off+count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len>count) len = count;
+ if (len<0) len = 0;
+ return len;
+}
+
+#ifdef CONFIG_RTL_KERNEL_MIPS16_CHAR
+__NOMIPS16
+#endif
+static int default_write_proc(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ if (count < 2)
+ return -EFAULT;
+ if (buffer && !copy_from_user(&default_flag, buffer, 1)) {
+ return count;
+ }
+ return -EFAULT;
+}
+
+#ifdef READ_RF_SWITCH_GPIO
+static int rf_switch_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+ char flag;
+
+ if (RTL_R32(WIFI_ONOFF_PIN_DATABASE) & (1<<WIFI_ONOFF_PIN_NO)){
+ flag = '1';
+ }else{
+ flag = '0';
+ }
+ len = sprintf(page, "%c\n", flag);
+
+ if (len <= off+count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len > count) len = count;
+ if (len < 0) len = 0;
+ return len;
+}
+#endif
+
+#ifdef CONFIG_POCKET_ROUTER_SUPPORT
+static int write_pocketAP_hw_set_flag_proc(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ unsigned int reg_cnr, reg_dir;
+
+ if (count != 2)
+ return -EFAULT;
+ if (buffer && !copy_from_user(&pocketAP_hw_set_flag, buffer, 1)) {
+
+ }
+ return -EFAULT;
+}
+
+static int read_pocketAP_hw_set_flag_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+
+ len = sprintf(page, "%c\n", pocketAP_hw_set_flag);
+
+ if (len <= off+count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len > count) len = count;
+ if (len < 0) len = 0;
+
+//panic_printk("\r\n __[%s-%u]",__FILE__,__LINE__);
+ return len;
+
+}
+
+
+
+static int read_ap_client_rou_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+ char flag;
+ int gpioA2_flag,gpioB3_flag;
+
+
+ if(ap_cli_rou_state == 2)
+ {
+ len = sprintf(page, "%c\n", '2'); // AP
+ }
+ else if(ap_cli_rou_state == 1)
+ {
+ len = sprintf(page, "%c\n", '1'); // Client
+ }
+ else if(ap_cli_rou_state == 3)
+ {
+ len = sprintf(page, "%c\n", '3'); // Router
+ }
+ else
+ {
+ len = sprintf(page, "%c\n", '0');
+ }
+
+ if (len <= off+count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len > count) len = count;
+ if (len < 0) len = 0;
+
+//panic_printk("\r\n __[%s-%u]",__FILE__,__LINE__);
+ return len;
+}
+
+static int read_dc_pwr_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+ char flag;
+ int pluged_state=0;
+//panic_printk("\r\n 0x%x__[%s-%u]",RTL_R32(RESET_PIN_DATABASE),__FILE__,__LINE__);
+
+ pluged_state = get_dc_pwr_plugged_state();
+ if(pluged_state == 1)
+ {
+ len = sprintf(page, "%c\n", '1');
+ }
+ else if(pluged_state == 2)
+ {
+ len = sprintf(page, "%c\n", '2');
+ }
+ else
+ {
+ len = sprintf(page, "%c\n", '0');
+ }
+
+ if (len <= off+count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len > count) len = count;
+ if (len < 0) len = 0;
+
+//panic_printk("\r\n len=[%u]__[%s-%u]",len,__FILE__,__LINE__);
+ return len;
+}
+
+static int read_dc_pwr_plugged_flag_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+
+ len = sprintf(page, "%c\n", dc_pwr_plugged_flag);
+
+ if (len <= off+count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len > count) len = count;
+ if (len < 0) len = 0;
+
+//panic_printk("\r\n __[%s-%u]",__FILE__,__LINE__);
+ dc_pwr_plugged_flag = '0';
+ return len;
+
+}
+static int read_EnablePHYIf_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+ char flag;
+
+//panic_printk("\r\n 0x%x__[%s-%u]",RTL_R32(RESET_PIN_DATABASE),__FILE__,__LINE__);
+
+ if(RTL_R32(0xBB804114) & (0x01))
+ {
+ flag = '1';
+ }
+ else
+ {
+ flag = '0';
+ }
+
+ len = sprintf(page, "%c\n", flag);
+
+ if (len <= off+count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len > count) len = count;
+ if (len < 0) len = 0;
+
+//panic_printk("\r\n len=[%u]__[%s-%u]",len,__FILE__,__LINE__);
+ return len;
+}
+
+static int get_pocketAP_ap_cli_rou_state()
+{
+ int gpioA2_flag,gpioB3_flag;
+
+ if(RTL_R32(RESET_PIN_DATABASE) & (RTL_GPIO_DAT_GPIOA2))
+ {
+ gpioA2_flag = 1;
+ }
+ else
+ {
+ gpioA2_flag = 0;
+ }
+
+ if(RTL_R32(RESET_PIN_DATABASE) & (RTL_GPIO_DAT_GPIOB3))
+ {
+ gpioB3_flag = 1;
+ }
+ else
+ {
+ gpioB3_flag = 0;
+ }
+
+ return ((1<<gpioA2_flag)|gpioB3_flag);
+}
+
+static int get_dc_pwr_plugged_state()
+{
+
+ if(RTL_R32(RESET_PIN_DATABASE) & (RTL_GPIO_DAT_GPIOC0))
+ {
+ return 1; //plugged
+ }
+ else
+ {
+ return 2; //unplugged
+ }
+
+}
+
+static int check_EnablePHYIf()
+{
+ if(RTL_R32(0xBB804114) & (0x01))
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+
+}
+
+static void pocket_ap_timer_func(unsigned long data)
+{
+//panic_printk("\r\n __[%s-%u]",__FILE__,__LINE__);
+
+ if(ap_cli_rou_idx >= 1)
+ ap_cli_rou_idx = 0;
+ else
+ ap_cli_rou_idx++;
+
+ ap_cli_rou_time_state[ap_cli_rou_idx]=get_pocketAP_ap_cli_rou_state();
+ dc_pwr_plugged_time_state = get_dc_pwr_plugged_state();
+
+ if(ap_cli_rou_time_state[0] == ap_cli_rou_time_state[1] )
+ {
+ if(ap_cli_rou_state != ap_cli_rou_time_state[0])
+ {
+ ap_cli_rou_state = ap_cli_rou_time_state[0];
+ pocketAP_hw_set_flag = '0';
+ }
+ }
+
+ if(dc_pwr_plugged_state == 0)
+ {
+ dc_pwr_plugged_state = dc_pwr_plugged_time_state;
+ }
+ else if(dc_pwr_plugged_state != dc_pwr_plugged_time_state)
+ {
+ dc_pwr_plugged_state = dc_pwr_plugged_time_state;
+ dc_pwr_plugged_flag = '1';
+ }
+
+//B8b00728 & 0x1F 0x11:L0 0x14:L1
+//panic_printk("\r\n [%d-%d-%d-%d],__[%s-%u]",ap_cli_rou_time_state[0],ap_cli_rou_time_state[1],ap_cli_rou_state,__FILE__,__LINE__);
+
+//panic_printk("\r\n [0x%x]",RTL_R32(0xB8b00728) & (0x1F));
+ pwr_saving_state=(RTL_R32(0xB8b00728) & (0x1F));
+//panic_printk("\r\n pwr_saving_state = [0x%x]",pwr_saving_state);
+
+ if(pwr_saving_state == 0x14) // L1 state, in low speed
+ {
+ if (pwr_saving_led_toggle < 2) {
+ RTL_W32(PABCD_DAT, (RTL_R32(PABCD_DAT) | (RTL_GPIO_DAT_GPIOB2)));
+ pwr_saving_led_toggle++;
+ }
+ else if (pwr_saving_led_toggle < 4){
+ RTL_W32(PABCD_DAT, (RTL_R32(PABCD_DAT) & (~(RTL_GPIO_DAT_GPIOB2))));
+ pwr_saving_led_toggle++;
+ if(pwr_saving_led_toggle == 4)
+ pwr_saving_led_toggle = 0;
+ }
+ else
+ {
+ pwr_saving_led_toggle = 0;
+ }
+ }
+ else // L0 state, always on
+ {
+ RTL_W32(PABCD_DAT, (RTL_R32(PABCD_DAT) & (~(RTL_GPIO_DAT_GPIOB2))));
+ }
+
+
+ mod_timer(&pocket_ap_timer, jiffies + HZ/2);
+}
+#endif
+int __init rtl_gpio_init(void)
+{
+ struct proc_dir_entry *res=NULL;
+
+ printk("Realtek GPIO Driver for Flash Reload Default\n");
+
+ // Set GPIOA pin 10(8181)/0(8186) as input pin for reset button
+
+#if defined(CONFIG_RTL_8196C) || defined(CONFIG_RTL_8198)
+#ifndef CONFIG_USING_JTAG
+ RTL_W32(RTL_GPIO_MUX, (RTL_R32(RTL_GPIO_MUX) | (RTL_GPIO_MUX_DATA)));
+#endif
+#if defined(CONFIG_RTL_8198)
+ RTL_W32(RTL_GPIO_MUX, (RTL_R32(RTL_GPIO_MUX) | 0xf));
+#endif
+#if defined(CONFIG_RTL_8196CS)
+extern int PCIE_reset_procedure(int PCIE_Port0and1_8196B_208pin, int Use_External_PCIE_CLK, int mdio_reset,unsigned long conf_addr);
+#define CLK_MANAGE 0xb8000010
+#define PCI_CONFIG_COMMAND (0xB8B10000+4)
+#define PCI_CONFIG_LATENCY (0xB8B10000+0x0c)
+#define PCI_CONFIG_BASE0 (0xB8B10000+0x10)
+#define PCI_CONFIG_BASE1 (0xB8B10000+0x18)
+ extern void setBaseAddressRegister(void);
+ RTL_W32(CLK_MANAGE, (RTL_R32(CLK_MANAGE) | BIT(11)));
+ mdelay(10);
+ PCIE_reset_procedure(0, 0, 1, 0xb8b10000);
+ setBaseAddressRegister();
+ {
+
+ int i=0;
+ *((volatile unsigned long *)PCI_CONFIG_BASE1) = 0x19000000;
+ //DEBUG_INFO("...config_base1 = 0x%08lx\n", *((volatile unsigned long *)PCI_CONFIG_BASE1));
+ for(i=0; i<1000000; i++);
+ *((volatile unsigned char *)PCI_CONFIG_COMMAND) = 0x07;
+ //DEBUG_INFO("...command = 0x%08lx\n", *((volatile unsigned long *)PCI_CONFIG_COMMAND));
+ for(i=0; i<1000000; i++);
+ *((volatile unsigned short *)PCI_CONFIG_LATENCY) = 0x2000;
+ for(i=0; i<1000000; i++);
+ //DEBUG_INFO("...latency = 0x%08lx\n", *((volatile unsigned long *)PCI_CONFIG_LATENCY));
+ }
+
+#endif
+#ifdef CONFIG_POCKET_ROUTER_SUPPORT
+
+//panic_printk("\r\n 0x%x__[%s-%u]",RTL_R32(RTL_GPIO_MUX),__FILE__,__LINE__);
+#ifndef CONFIG_USING_JTAG
+ RTL_W32(RTL_GPIO_MUX, (RTL_R32(RTL_GPIO_MUX) | (RTL_GPIO_MUX_POCKETAP_DATA)));
+#endif
+//panic_printk("\r\n 0x%x__[%s-%u]",RTL_R32(RTL_GPIO_MUX),__FILE__,__LINE__);
+ RTL_W32(PABCD_CNR, (RTL_R32(PABCD_CNR) & (~(RTL_GPIO_CNR_POCKETAP_DATA))));
+
+
+
+
+
+ RTL_W32(PABCD_DIR, (RTL_R32(PABCD_DIR) & (~(RTL_GPIO_DIR_GPIOA2))));
+
+ RTL_W32(PABCD_DIR, (RTL_R32(PABCD_DIR) & (~(RTL_GPIO_DIR_GPIOB3))));
+
+ RTL_W32(PABCD_DIR, (RTL_R32(PABCD_DIR) | ((RTL_GPIO_DIR_GPIOB2))));
+
+ RTL_W32(PABCD_DIR, (RTL_R32(PABCD_DIR) & (~(RTL_GPIO_DIR_GPIOC0))));
+
+#endif //end of CONFIG_POCKET_ROUTER_SUPPORT
+#if defined(CONFIG_RTL_8196CS)
+ RTL_W32(PCIE_PIN_MUX,(RTL_R32(PCIE_PIN_MUX)&(~(1<<29)))|(1<<13) );
+ RTL_W32(RESET_PIN_IOBASE, (RTL_R32(RESET_PIN_IOBASE) & (~((1 << RESET_BTN_PIN)<<MODE_MARSK))));
+ RTL_W32(RESET_PIN_DIRBASE, (RTL_R32(RESET_PIN_DIRBASE) & (~((1 << RESET_BTN_PIN)<<DIR_MASK ))));
+
+#else
+ RTL_W32(RESET_PIN_IOBASE, (RTL_R32(RESET_PIN_IOBASE) & (~(1 << RESET_BTN_PIN))));
+ RTL_W32(RESET_PIN_DIRBASE, (RTL_R32(RESET_PIN_DIRBASE) & (~(1 << RESET_BTN_PIN))));
+#endif
+#if defined(READ_RF_SWITCH_GPIO)
+ RTL_W32(WIFI_ONOFF_PIN_IOBASE, (RTL_R32(WIFI_ONOFF_PIN_DIRBASE) & ( ~(1<<RTL_GPIO_WIFI_ONOFF))));
+ RTL_W32(WIFI_ONOFF_PIN_DIRBASE, (RTL_R32(WIFI_ONOFF_PIN_DIRBASE) & (~(1<<RTL_GPIO_WIFI_ONOFF))));
+ RTL_W32(WIFI_ONOFF_PIN_DATABASE, (RTL_R32(WIFI_ONOFF_PIN_DATABASE) & (~(1<<RTL_GPIO_WIFI_ONOFF))));
+
+#endif // #if defined(READ_RF_SWITCH_GPIO)
+#endif // #if defined(CONFIG_RTL865X)
+#if defined(CONFIG_RTL_8196CS)
+ RTL_W32(RESET_LED_IOBASE, (RTL_R32(RESET_LED_IOBASE) | (((1 << RESET_LED_PIN)))));
+ RTL_W32(RESET_LED_DIRBASE, (RTL_R32(RESET_LED_DIRBASE) | ((1 << RESET_LED_PIN))));
+#else
+ // Set GPIOA ping 2 as output pin for reset led
+ RTL_W32(RESET_LED_DIRBASE, (RTL_R32(RESET_LED_DIRBASE) | ((1 << RESET_LED_PIN))));
+#endif
+#ifdef CONFIG_RTL_FLASH_DUAL_IMAGE_ENABLE
+ res = create_proc_entry("bootbank", 0, NULL);
+ if (res) {
+ res->read_proc = read_bootbank_proc;
+ //res->write_proc = write_bootbank_proc;
+ }
+ else {
+ printk("read bootbank, create proc failed!\n");
+ }
+#endif
+#ifdef AUTO_CONFIG
+ res = create_proc_entry("gpio", 0, NULL);
+ if (res) {
+ res->read_proc = read_proc;
+ res->write_proc = write_proc;
+ }
+ else {
+ printk("Realtek GPIO Driver, create proc failed!\n");
+ }
+
+// 2009-0414
+#if defined(USE_INTERRUPT_GPIO)
+#if defined(CONFIG_RTL_8198) && !defined(CONFIG_RTK_VOIP)
+ RTL_R32(AUTOCFG_PIN_IMR) |= (0x01 << (AUTOCFG_BTN_PIN-16)*2); // enable interrupt in falling-edge
+#else
+ RTL_R32(AUTOCFG_PIN_IMR) |= (0x01 << AUTOCFG_BTN_PIN*2); // enable interrupt in falling-edge
+#endif
+ if (request_irq(GPIO_IRQ_NUM, gpio_interrupt_isr, IRQF_DISABLED, "rtl_gpio", NULL)) {
+ //panic_printk("gpio request_irq(%d) error!\n", GPIO_IRQ_NUM);
+ }
+#endif
+// 2009-0414
+#endif
+
+ res = create_proc_entry("load_default", 0, NULL);
+ if (res) {
+ res->read_proc = default_read_proc;
+ res->write_proc = default_write_proc;
+ }
+
+#ifdef READ_RF_SWITCH_GPIO
+ res = create_proc_entry("rf_switch", 0, NULL);
+ if (res) {
+ res->read_proc = rf_switch_read_proc;
+ res->write_proc = NULL;
+ }
+#endif
+
+
+
+#ifdef CONFIG_POCKET_ROUTER_SUPPORT
+
+ res = create_proc_entry("dc_pwr", 0, NULL);
+ if (res)
+ res->read_proc = read_dc_pwr_proc;
+ else
+ printk("create read_dc_pwr_proc failed!\n");
+
+ res = create_proc_entry("dc_pwr_plugged_flag", 0, NULL);
+ if (res)
+ {
+ res->read_proc = read_dc_pwr_plugged_flag_proc;
+ }
+ else
+ printk("create read_pocketAP_hw_set_flag_proc failed!\n");
+
+ res = create_proc_entry("ap_client_rou", 0, NULL);
+ if (res)
+ res->read_proc = read_ap_client_rou_proc;
+ else
+ printk("create read_ap_client_rou_proc failed!\n");
+
+ res = create_proc_entry("pocketAP_hw_set_flag", 0, NULL);
+ if (res)
+ {
+ res->read_proc = read_pocketAP_hw_set_flag_proc;
+ res->write_proc = write_pocketAP_hw_set_flag_proc;
+ }
+ else
+ printk("create read_pocketAP_hw_set_flag_proc failed!\n");
+
+ res = create_proc_entry("phyif", 0, NULL);
+ if (res)
+ res->read_proc = read_EnablePHYIf_proc;
+ else
+ printk("create read_EnablePHYIf_proc failed!\n");
+
+ init_timer(&pocket_ap_timer);
+ pocket_ap_timer.data = (unsigned long)NULL;
+ pocket_ap_timer.function = &pocket_ap_timer_func;
+ mod_timer(&pocket_ap_timer, jiffies + HZ);
+#endif
+
+ init_timer(&probe_timer);
+ probe_counter = 0;
+ probe_state = PROBE_NULL;
+ probe_timer.expires = jiffies + HZ;
+ probe_timer.data = (unsigned long)NULL;
+ probe_timer.function = &rtl_gpio_timer;
+ mod_timer(&probe_timer, jiffies + HZ);
+
+#ifdef CONFIG_RTL865X_CMO
+ extra_led_gpio_init();
+#endif
+ return 0;
+}
+
+
+static void __exit rtl_gpio_exit(void)
+{
+ printk("Unload Realtek GPIO Driver \n");
+ del_timer_sync(&probe_timer);
+}
+
+
+module_exit(rtl_gpio_exit);
+module_init(rtl_gpio_init);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIO driver for Reload default");
diff --git a/target/linux/realtek/files/drivers/char/rtl_mdio/Makefile b/target/linux/realtek/files/drivers/char/rtl_mdio/Makefile
new file mode 100644
index 000000000..18b38e500
--- /dev/null
+++ b/target/linux/realtek/files/drivers/char/rtl_mdio/Makefile
@@ -0,0 +1,2 @@
+
+obj-y += rtl_mdio.o
diff --git a/target/linux/realtek/files/drivers/char/rtl_mdio/rtl_mdio.c b/target/linux/realtek/files/drivers/char/rtl_mdio/rtl_mdio.c
new file mode 100644
index 000000000..85cc3ffda
--- /dev/null
+++ b/target/linux/realtek/files/drivers/char/rtl_mdio/rtl_mdio.c
@@ -0,0 +1,1316 @@
+/*
+################################################################################
+#
+# RTL8198 MDIO char driver
+#
+# Copyright(c) 2010 Realtek Semiconductor Corp. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# Author:
+# Realtek WiFi AP software team <cn_sd8@realtek.com>
+# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
+#
+################################################################################
+*/
+/*================================================================*/
+/* System Include Files */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/ioport.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/circ_buf.h>
+#include <asm/uaccess.h>
+#include <linux/timer.h>
+#include <linux/proc_fs.h>
+#include <linux/interrupt.h>
+#include "bspchip.h"
+
+
+/*================================================================*/
+/* Local Include Files */
+
+#include "rtl_mdio.h"
+
+//#define CONFIG_RTL8197B_B_CUT_PATCH
+/*================================================================*/
+/* Global Variables */
+
+int cpu_suspend_enabled = 0;
+
+
+/*================================================================*/
+/* Local Variables */
+static struct mdio_priv *dev_priv=NULL;
+
+#ifdef SIMULATION
+static unsigned char data_in[256];
+static int data_in_len = 0, data_in_read_idx = 0;
+
+static unsigned short data_out;
+static int data_out_len = 0, msg_is_fetched = 0;
+static unsigned long reg_scr =0, reg_isr=0;
+#endif
+
+
+
+
+/*================================================================*/
+#if 0
+int pre_jiffies=1;
+
+void* MAX_FUNCT;
+unsigned int MAX_STACK=8*1024;
+unsigned int PRINT_STACK=2428;
+unsigned int COPY_STACK=2428;
+
+unsigned int MAX_FUNCT_call[40];
+
+#define PRINT_INTV (1*60*100)
+/* print max sp ever 3min */
+//extern volatile int jiffies;
+
+
+void __attribute__((__no_instrument_function__))
+__cyg_profile_func_enter(void *this_func, void *call_site)
+{
+ unsigned int sp_addr;
+ unsigned int sp_size;
+
+#if 0
+ if (this_func == rtk_voip_dsp_init)
+ {
+ printk("rtk_voip_dsp_init enter\n");
+ }
+#endif
+
+ __asm__ __volatile__("ori %0, $29, 0": "=r"(sp_addr) );
+
+ sp_size = sp_addr & 8191;
+
+ if(MAX_STACK > sp_size)
+ {
+ MAX_STACK = sp_size;
+ MAX_FUNCT = this_func;
+
+ if (COPY_STACK > sp_size) {
+ COPY_STACK = sp_size;
+ copy_trace(sp_addr);
+ }
+
+
+ }
+
+ if ( ((int)jiffies - pre_jiffies) > PRINT_INTV ) {
+
+ pre_jiffies = jiffies;
+ printk("MAXSP,%x,%d.", MAX_FUNCT, MAX_STACK);
+
+ if (PRINT_STACK > MAX_STACK) {
+ int i;
+ unsigned long flags;
+ save_flags(flags); cli();
+ PRINT_STACK = MAX_STACK;
+ printk("\nCall Trace:");
+
+ for (i=0 ; i<40 ; i++) {
+ if (0==MAX_FUNCT_call[i])
+ break;
+ printk(" [<%08lx>]", MAX_FUNCT_call[i]);
+ if ( 4==(i%5))
+ printk("\n");
+ }
+ restore_flags(flags);
+ }
+ MAX_STACK = 8*1024;
+ }
+}
+
+void __attribute__((__no_instrument_function__))
+__cyg_profile_func_exit(void *this_func, void *call_site)
+{
+#if 0
+ if (this_func == rtk_voip_dsp_init)
+ {
+ printk("rtk_voip_dsp_init exit\n");
+ }
+#endif
+}
+
+#include <asm-mips/uaccess.h>
+
+void __attribute__((__no_instrument_function__)) copy_trace(unsigned int *sp)
+{
+ int i;
+ //int column = 0;
+ unsigned int *stack;
+ unsigned long kernel_start, kernel_end;
+
+ extern char _stext, _etext;
+
+ stack = sp ;
+ i = 0;
+
+ kernel_start = (unsigned long) &_stext;
+ kernel_end = (unsigned long) &_etext;
+
+
+ //printk("\nCall Trace:");
+
+ while ((unsigned long) stack & (PAGE_SIZE -1)) {
+ unsigned long addr;
+
+ if (__get_user(addr, stack++)) {
+ printk(" (Bad stack address)\n");
+ break;
+ }
+
+ /*
+ * If the address is either in the text segment of the
+ * kernel, or in the region which contains vmalloc'ed
+ * memory, it *may* be the address of a calling
+ * routine; if so, print it so that someone tracing
+ * down the cause of the crash will be able to figure
+ * out the call path that was taken.
+ */
+
+ if (addr >= kernel_start && addr < kernel_end) {
+
+ MAX_FUNCT_call[i]=addr;
+ //printk(" [<%08lx>]", addr);
+ //if (column++ == 5) {
+ // printk("\n");
+ // column = 0;
+ //}
+ if (++i > 40) {
+ //printk(" ...");
+ break;
+ }
+ }
+
+
+ }
+
+ //if (column != 0)
+ // printk("\n");
+
+ for ( ; i<40; i++)
+ MAX_FUNCT_call[i] = 0;
+}
+#endif
+/*================================================================*/
+
+
+
+
+/*================================================================*/
+/* Routine Implementations */
+
+#ifdef SIMULATION
+static unsigned long register_read_dw(int offset)
+{
+ unsigned long status = 0;
+ unsigned short wdata = 0;
+
+ if (offset == REG_ISR) {
+ status = reg_isr;
+
+ if (data_in_len > data_in_read_idx)
+ status |= IP_NEWMSG;
+
+ if (msg_is_fetched) {
+ status |= IP_MSGFETCH;
+ msg_is_fetched = 0;
+ }
+
+ return status;
+ }
+ else if (offset == REG_RCR) {
+ ASSERT(data_in_len > data_in_read_idx);
+ memcpy(&wdata, &data_in[data_in_read_idx], 2);
+ data_in_read_idx += 2;
+ status |= wdata;
+ return status;
+ }
+ else if (offset == REG_SYSCR) {
+ return reg_scr;
+ }
+ else {
+ ASSERT(0);
+ return status;
+ }
+}
+
+static void register_write_dw(int offset, unsigned long data)
+{
+ if (offset == REG_SSR) {
+ unsigned short wData = (unsigned short)data;
+
+ memcpy(&data_out, &wData, 2);
+ data_out_len = 2;
+ }
+ else if (offset == REG_ISR) {
+ reg_isr &= ~data ;
+ }
+}
+#endif // SIMULATION
+
+#ifdef KDB_MSG
+static void inline debugk_out(unsigned char *label, unsigned char *data, int data_length)
+{
+ int i,j;
+ int num_blocks;
+ int block_remainder;
+
+ num_blocks = data_length >> 4;
+ block_remainder = data_length & 15;
+
+ if (label)
+ DEBUGK_OUT("%s\n", label);
+
+ if (data==NULL || data_length==0)
+ return;
+
+ for (i=0; i<num_blocks; i++) {
+ printk("\t");
+ for (j=0; j<16; j++)
+ printk("%02x ", data[j + (i<<4)]);
+ printk("\n");
+ }
+
+ if (block_remainder > 0) {
+ printk("\t");
+ for (j=0; j<block_remainder; j++)
+ printk("%02x ", data[j+(num_blocks<<4)]);
+ printk("\n");
+ }
+}
+#endif // KDB_MSG
+
+unsigned long static get_ether_phy_reg(unsigned long phyId, unsigned long regId)
+{
+ unsigned long status;
+
+ WRITE_MEM32((void *)MDCIOCR, COMMAND_READ | ( phyId << PHYADD_OFFSET ) | ( regId << REGADD_OFFSET ));
+
+ do { status = READ_MEM32( MDCIOSR ); } while ( ( status & MDCIO_STATUS ) != 0 );
+
+ status &= 0xffff;
+ return status;
+}
+
+static void set_ether_phy_reg(unsigned long phyId, unsigned long regId, unsigned long wData)
+{
+ WRITE_MEM32(MDCIOCR, COMMAND_WRITE | ( phyId << PHYADD_OFFSET ) | ( regId << REGADD_OFFSET ) | wData);
+
+ while( ( READ_MEM32( MDCIOSR ) & MDCIO_STATUS ) != 0 ); /* wait until command complete */
+}
+
+static int is_checksum_ok(unsigned char *data, int len)
+{
+ int i;
+ unsigned char sum=0;
+
+ for (i=0; i<len; i++)
+ sum += data[i];
+
+ if (sum == 0)
+ return 1;
+ else
+ return 0;
+}
+
+static unsigned char append_checksum(unsigned char *data, int len)
+{
+ int i;
+ unsigned char sum=0;
+
+ for (i=0; i<len; i++)
+ sum += data[i];
+
+ sum = ~sum + 1;
+ return sum;
+}
+
+static int indicate_evt(struct mdio_priv *priv, int id, unsigned char *data, int data_len)
+{
+ int size;
+
+ size = CIRC_SPACE(priv->evt_que_head, priv->evt_que_tail, EV_QUE_MAX);
+ if (size == 0) {
+ DEBUGK_ERR("Indication queue full, drop event!\n");
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
+ if (priv->host_pid != -1)
+ kill_proc(priv->host_pid, SIGUSR1, 1);
+#else
+ if (priv->host_pid != NULL)
+ kill_pid(priv->host_pid, SIGUSR1, 1);
+#endif
+
+ return 0;
+ }
+
+ ASSERT(data_len < MDIO_BUFSIZE);
+
+ priv->ind_evt_que[priv->evt_que_head].id = id;
+ priv->ind_evt_que[priv->evt_que_head].len = data_len;
+ memcpy(&priv->ind_evt_que[priv->evt_que_head].buf, data, data_len);
+ priv->evt_que_head = (priv->evt_que_head + 1) & (EV_QUE_MAX - 1);
+#if 0 //mark_nfbi , now we use polling instead of singal in HCD
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
+ if (priv->host_pid != -1)
+ kill_proc(priv->host_pid, SIGUSR1, 1);
+#else
+ if (priv->host_pid != NULL)
+ kill_pid(priv->host_pid, SIGUSR1, 1);
+#endif
+#endif
+ return 1;
+}
+
+static int retrieve_evt(struct mdio_priv *priv, unsigned char *out)
+{
+ int len = 0;
+
+ if (CIRC_CNT(priv->evt_que_head, priv->evt_que_tail, EV_QUE_MAX) > 0) { // more than one evt pending
+ len = EVT_BUF_OFFSET + priv->ind_evt_que[priv->evt_que_tail].len;
+ memcpy(out, &priv->ind_evt_que[priv->evt_que_tail], len);
+ priv->evt_que_tail = (priv->evt_que_tail + 1) & (EV_QUE_MAX - 1);
+ }
+ return len;
+}
+
+static void process_rx_cmd(struct mdio_priv *priv, unsigned short data)
+{
+ if (priv->rx_cmd_time &&
+ (priv->rx_cmd_state == STATE_RX_WAIT_LEN ||
+ priv->rx_cmd_state == STATE_RX_WAIT_DATA) &&
+ (priv->cmd_timeout && TIME_DIFF(jiffies, priv->rx_cmd_time) > priv->cmd_timeout)) {
+ DEBUGK_ERR("Rx cmd timeout [%ld][0x%x], discard pending cmd!\n", TIME_DIFF(jiffies, priv->rx_cmd_time), data);
+ RESET_RX_STATE;
+ return;
+ }
+
+ if ((data & FIRST_CMD_MASK) && (priv->rx_cmd_state != STATE_RX_INIT)) {
+ DEBUGK_ERR("Rx Sync bit but not in INIT_STATE [%d][0x%x], discard pending cmd!\n", priv->rx_cmd_state, data);
+ RESET_RX_STATE;
+ }
+
+ if (priv->rx_cmd_state == STATE_RX_INIT) {
+ ASSERT(priv->data_in.len == 0);
+
+ if (!(data & FIRST_CMD_MASK)) {
+ DEBUGK_ERR("Got invalid rx cmd id [0x%x], discard it!\n", data);
+ goto invalid_cmd;
+ }
+ PUT_IN_DATA(data); // cmd id
+ priv->rx_cmd_state = STATE_RX_WAIT_LEN;
+ priv->rx_cmd_time = jiffies;
+ }
+ else { // STATE_RX_WAIT_LEN or STATE_RX_WAIT_DATA
+ // check if first cmd byte is '0'
+ if (data & 0xff00) {
+ DEBUGK_ERR("1st byte of rx cmd not zero [%x]!\n", data >> 8);
+ goto invalid_cmd;
+ }
+
+ if (priv->rx_cmd_state == STATE_RX_WAIT_LEN) {
+ PUT_IN_DATA(data);
+ priv->rx_cmd_state = STATE_RX_WAIT_DATA;
+ priv->rx_cmd_remain_len = (data + 1)*2; // including checksum
+ priv->rx_cmd_time = jiffies;
+ }
+ else { // in STATE_RX_WAIT_DATA
+ ASSERT (priv->rx_cmd_remain_len > 0);
+
+ PUT_IN_DATA(data);
+ priv->rx_cmd_remain_len -= 2;
+ if (priv->rx_cmd_remain_len <= 0) { // rx last bye, calcuate checksum
+ if (!is_checksum_ok(priv->data_in.buf, priv->data_in.len)) {
+ DEBUGK_ERR("Rx cmd cheksum error!\n");
+ goto invalid_cmd;
+ }
+ priv->data_in.len -= 2; // substract checksum length
+
+ indicate_evt(priv, IND_CMD_EV, priv->data_in.buf, priv->data_in.len);
+
+ RESET_RX_STATE;
+ }
+ else
+ priv->rx_cmd_time = jiffies;
+ }
+ }
+
+ return;
+
+invalid_cmd:
+ RESET_RX_STATE;
+}
+
+static void transmit_msg(struct mdio_priv *priv)
+{
+ unsigned short data;
+
+ if (priv->data_out.len <= 0 || priv->tx_status_transmitting_len >= priv->data_out.len)
+ return;
+
+ memcpy(&data, priv->data_out.buf+priv->tx_status_transmitting_len, 2);
+ register_write_dw(REG_SSR, (unsigned long)data);
+
+ priv->tx_status_transmitting_len += 2;
+
+ if (priv->tx_status_transmitting_len >= priv->data_out.len)
+ priv->tx_status_state = STATE_TX_INIT;
+ else
+ priv->tx_status_state = STATE_TX_IN_PROGRESS;
+}
+
+#ifdef CONFIG_RTK_VOIP_ETHERNET_DSP_IS_DSP
+
+static irqreturn_t mdio_interrupt(int irq, void *dev_id)
+{
+ struct mdio_priv *priv = (struct mdio_priv *)dev_id;
+
+ unsigned long status, data;
+
+ while (1) {
+ status = register_read_dw(REG_ISR);
+ if (!status)
+ break;
+
+ register_write_dw(REG_ISR, status); // clear interrupt
+
+ unsigned long st_dsp_id;
+ extern int Set_Ethernet_DSP_ID(unsigned char dsp_id);
+ extern unsigned int Get_Ethernet_DSP_ID(void);
+ printk("in mdio_interrupt, status = 0x%x\n", status);
+
+ if (status & 0x8)//bit3
+ {
+ data = register_read_dw(REG_SYSCR) & 0xF;// use SYSCR bit 0~3 to decide DSP ID for each DSP. up to 16 DSP.
+
+ if((data>=0) && (data<=3))
+ {
+ Set_Ethernet_DSP_ID((unsigned char)data);
+ //printk("Set DSP ID to %d\n", data);
+
+ // Singal AP process to chage DSP MAC addr
+ printk("signal to hcd to change MAC Addr\n");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
+ if (priv->host_pid != -1)
+ kill_proc(priv->host_pid, SIGUSR2, 1);
+#else
+ if (priv->host_pid != -1)
+ kill_pid(priv->host_pid, SIGUSR2, 1);
+#endif
+ }
+ else
+ printk("%s: NOT support dsp_id=%d\n", __FUNCTION__, data);
+ }
+ else
+ {
+ printk("Get unknown mdio interrupt status = 0x%x\n", status);
+ }
+
+ if (status & IP_NEWMSG) {
+ data = register_read_dw(REG_RCR);
+ process_rx_cmd(priv, (unsigned short)data);
+ }
+ if (status & IP_MSGFETCH) {
+ transmit_msg(priv);
+ }
+ if (status & (IP_ISOLATION|IP_ETHMAC|IP_WLANMAC|IP_ETHPHY |IP_WLANPHY|IP_SELMIICLK)) {
+ data = register_read_dw(REG_SYSCR);
+ data &= (CR_ISOLATION |CR_ETHMAC|CR_WLANMAC|CR_ETHPHY|CR_WLANPHY|CR_SELMIICLK);
+ indicate_evt(priv, IND_SYSCTL_EV, (unsigned char *)&data, sizeof(data));
+ }
+#ifdef CONFIG_RTK_VOIP_ETHERNET_DSP_IS_DSP
+ if (status & ~(IP_MSGFETCH|IP_NEWMSG|IP_ISOLATION|IP_ETHMAC|
+ IP_WLANMAC|IP_ETHPHY |IP_WLANPHY |IP_SELMIICLK |IP_CUSTOM3)) {
+#else
+ if (status & ~(IP_MSGFETCH|IP_NEWMSG|IP_ISOLATION|IP_ETHMAC|
+ IP_WLANMAC|IP_ETHPHY |IP_WLANPHY|IP_SELMIICLK)) {
+#endif
+ DEBUGK_ERR("Got satus=0x%x, not supported yet!\n", (unsigned int)status);
+ }
+ }
+ return IRQ_HANDLED;
+}
+
+#else
+
+//static void mdio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mdio_interrupt(int irq, void *dev_id)
+{
+ struct mdio_priv *priv = (struct mdio_priv *)dev_id;
+
+ unsigned long status, data;
+
+ while (1) {
+ status = register_read_dw(REG_ISR);
+ if (!status)
+ break;
+
+ register_write_dw(REG_ISR, status); // clear interrupt
+
+ if (status & IP_NEWMSG) {
+ data = register_read_dw(REG_RCR);
+ process_rx_cmd(priv, (unsigned short)data);
+ }
+ if (status & IP_MSGFETCH) {
+ transmit_msg(priv);
+ }
+ if (status & (IP_ISOLATION|IP_ETHMAC|IP_WLANMAC|IP_ETHPHY |IP_WLANPHY|IP_SELMIICLK)) {
+ data = register_read_dw(REG_SYSCR);
+ data &= (CR_ISOLATION |CR_ETHMAC|CR_WLANMAC|CR_ETHPHY|CR_WLANPHY|CR_SELMIICLK);
+ indicate_evt(priv, IND_SYSCTL_EV, (unsigned char *)&data, sizeof(data));
+ }
+ if (status & ~(IP_MSGFETCH|IP_NEWMSG|IP_ISOLATION|IP_ETHMAC|
+ IP_WLANMAC|IP_ETHPHY |IP_WLANPHY|IP_SELMIICLK)) {
+ DEBUGK_ERR("Got satus=0x%x, not supported yet!\n", (unsigned int)status);
+ }
+ }
+ return IRQ_HANDLED;
+}
+
+#endif
+
+void toggle_usb_device_insert_bit(void)
+{
+ unsigned long flags;
+
+ if (dev_priv == NULL)
+ return;
+ spin_lock_irqsave(&dev_priv->reglock, flags);
+ if (REG32(REG_SYSSR) & SR_USBInsertStatus)
+ REG32(REG_SYSSR) = REG32(REG_SYSSR) & (~SR_USBInsertStatus);
+ else
+ REG32(REG_SYSSR) = REG32(REG_SYSSR) | SR_USBInsertStatus;
+ spin_unlock_irqrestore(&dev_priv->reglock, flags);
+ //printk("usb device inserted\n");
+}
+
+void toggle_usb_device_remove_bit(void)
+{
+ unsigned long flags;
+
+ if (dev_priv == NULL)
+ return;
+ spin_lock_irqsave(&dev_priv->reglock, flags);
+ if (REG32(REG_SYSSR) & SR_USBRemoveStatus)
+ REG32(REG_SYSSR) = REG32(REG_SYSSR) & (~SR_USBRemoveStatus);
+ else
+ REG32(REG_SYSSR) = REG32(REG_SYSSR) | SR_USBRemoveStatus;
+ spin_unlock_irqrestore(&dev_priv->reglock, flags);
+ //printk("usb device removed\n");
+}
+
+void set_wlanlink_bit(int val)
+{
+ unsigned long flags;
+
+ if (dev_priv == NULL)
+ return;
+ spin_lock_irqsave(&dev_priv->reglock, flags);
+ if (val)
+ REG32(REG_SYSSR) = REG32(REG_SYSSR) | SR_WLANLink;
+ else
+ REG32(REG_SYSSR) = REG32(REG_SYSSR) & (~SR_WLANLink);
+ spin_unlock_irqrestore(&dev_priv->reglock, flags);
+}
+
+static void mdio_reg_poll_timer(unsigned long task_priv)
+{
+ unsigned long flags;
+ unsigned long reg1, reg2;
+ struct mdio_priv *priv = (struct mdio_priv *)task_priv;
+
+ if (!priv->poll_timer_up)
+ return;
+
+ if (priv->reg_BMCR_write != REG32(REG_BMCR)) {
+ //printk("1. priv->reg_BMCR_write=%x\n", priv->reg_BMCR_write);
+ reg1 = reg2 = REG32(REG_BMCR);
+ if ((reg1&0x8000) && (priv->reg_BMCR_write&0x8000)) //check "reset" bit
+ reg1 &= 0x7fff;
+ if ((reg1&0x0200) && (priv->reg_BMCR_write&0x0200)) //check "restart auto negotiation" bit
+ reg1 &= 0xfdff;
+
+ if (priv->force_power_down)
+ reg1 |= 0x0800; //power down
+ priv->reg_BMCR_write = reg2;
+ set_ether_phy_reg(ETH_PORT_NUM, 0, reg1);
+ if (reg1 & 0x1000) {
+ if ((priv->reg_ANAR_write & 0x0180) == 0x0000)
+ set_ether_phy_reg(6, 0, 0x120c);
+ else
+ set_ether_phy_reg(6, 0, 0x1208);
+ }
+#ifdef CONFIG_RTL8197B_B_CUT_PATCH
+ else {
+ if (reg1 & 0x2000) //100M
+ set_ether_phy_reg(6, 0, 0x120c);
+ else //10M
+ set_ether_phy_reg(6, 0, 0x1208);
+ }
+#endif
+ //printk("2. priv->reg_BMCR_write=%x\n", priv->reg_BMCR_write);
+ }
+
+ if (priv->reg_BMCR_read != get_ether_phy_reg(ETH_PORT_NUM, 0)) {
+ //printk("1. priv->reg_BMCR_read=%x\n", priv->reg_BMCR_read);
+ priv->reg_BMCR_read = get_ether_phy_reg(ETH_PORT_NUM, 0);
+ if (priv->reg_BMCR_write & 0x0800) //power down
+ REG32(REG_BMCR) = priv->reg_BMCR_read;
+ else
+ REG32(REG_BMCR) = priv->reg_BMCR_read & 0xf7ff;
+ //printk("2. priv->reg_BMCR_read=%x\n", priv->reg_BMCR_read);
+ }
+
+ if (priv->reg_BMSR_read != get_ether_phy_reg(ETH_PORT_NUM, 1)) {
+ reg1 = get_ether_phy_reg(ETH_PORT_NUM, 1);
+ if ((priv->reg_BMSR_read ^ reg1) & (~BIT(2))) {
+ //toggle EthPHYStatusChange bit to generate interrupt
+ spin_lock_irqsave(&priv->reglock, flags);
+ if (REG32(REG_SYSSR) & SR_EthPHYStatusChange)
+ REG32(REG_SYSSR) = REG32(REG_SYSSR) & (~SR_EthPHYStatusChange);
+ else
+ REG32(REG_SYSSR) = REG32(REG_SYSSR) | SR_EthPHYStatusChange;
+ spin_unlock_irqrestore(&priv->reglock, flags);
+ //printk("EthPhy status changed!\n");
+ }
+
+ priv->reg_BMSR_read = reg1;
+ REG32(REG_BMSR) = priv->reg_BMSR_read;
+
+ if (priv->eth_phy_link_status != ((priv->reg_BMSR_read & BIT(2)) ? 1 : 0)) {
+ priv->eth_phy_link_status = ((priv->reg_BMSR_read & BIT(2)) ? 1 : 0);
+ spin_lock_irqsave(&priv->reglock, flags);
+ if (priv->eth_phy_link_status)
+ REG32(REG_SYSSR) = REG32(REG_SYSSR) | SR_EthLink;
+ else
+ REG32(REG_SYSSR) = REG32(REG_SYSSR) & (~SR_EthLink);
+ spin_unlock_irqrestore(&priv->reglock, flags);
+ //DEBUGK_OUT("Ether Link changed [%d]!\n", priv->eth_phy_link_status);
+ //printk("Ether Link changed [%d]!\n", priv->eth_phy_link_status);
+ }
+ }
+
+ if (!(priv->reg_BMCR_write&0x8000)) {
+ if (priv->reg_ANAR_write != REG32(REG_ANAR)) {
+ //printk("1. priv->reg_ANAR_write=%x\n", priv->reg_ANAR_write);
+ priv->reg_ANAR_write = REG32(REG_ANAR);
+ //printk("2. priv->reg_ANAR_write=%x\n", priv->reg_ANAR_write);
+ set_ether_phy_reg(ETH_PORT_NUM, 4, priv->reg_ANAR_write);
+ //printk("3. priv->reg_ANAR_write=%x\n", priv->reg_ANAR_write);
+ if (priv->reg_BMCR_write&0x1000) {
+ if ((priv->reg_ANAR_write & 0x0180) == 0x0000)
+ set_ether_phy_reg(6, 0, 0x120c);
+ else
+ set_ether_phy_reg(6, 0, 0x1208);
+ }
+ }
+ }
+
+ if (priv->reg_ANAR_read != get_ether_phy_reg(ETH_PORT_NUM, 4)) {
+ //printk("1. priv->reg_ANAR_read=%x\n", priv->reg_ANAR_read);
+ priv->reg_ANAR_read = get_ether_phy_reg(ETH_PORT_NUM, 4);
+ //printk("2. priv->reg_ANAR_read=%x\n", priv->reg_ANAR_read);
+ REG32(REG_ANAR) = priv->reg_ANAR_read;
+ }
+
+ if (priv->reg_ANLPAR_read != get_ether_phy_reg(ETH_PORT_NUM, 5)) {
+ priv->reg_ANLPAR_read = get_ether_phy_reg(ETH_PORT_NUM, 5);
+ REG32(REG_ANLPAR) = priv->reg_ANLPAR_read;
+ }
+
+ mod_timer(&priv->reg_poll_timer, jiffies + priv->phy_reg_poll_time);
+}
+
+static int mdio_open(struct inode *inode, struct file *filp)
+{
+ filp->private_data = dev_priv;
+ //MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int mdio_close(struct inode *inode, struct file *filp)
+{
+ //MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static ssize_t mdio_read (struct file *filp, char *buf, size_t count, loff_t *offset)
+{
+ struct mdio_priv *priv = (struct mdio_priv *)filp->private_data;
+
+ if (!buf)
+ return 0;
+
+ count = retrieve_evt(priv, buf);
+
+ return count;
+}
+
+static ssize_t mdio_write (struct file *filp, const char *buf, size_t count, loff_t *offset)
+{
+ struct mdio_priv *priv = (struct mdio_priv *)filp->private_data;
+ unsigned short last_word = 0;
+
+ if (!buf) {
+ DEBUGK_ERR("buf = NULL!\n");
+ goto ret;
+ }
+
+ if (count > MDIO_BUFSIZE) {
+ DEBUGK_ERR("write length too big!\n");
+ count = -EFAULT;
+ goto ret;
+ }
+
+ if (priv->tx_status_state != STATE_TX_INIT) {
+ DEBUGK_ERR("Transmit status, but not in valid state [%d]. Reset state!\n", priv->tx_status_state);
+ priv->tx_status_state = STATE_TX_INIT;
+ }
+
+ if (count %2) {
+ DEBUGK_ERR("Invalid Tx size [%d]!\n", count);
+ count = -EFAULT;
+ goto ret;
+ }
+
+ if (copy_from_user((void *)priv->data_out.buf, buf, count)) {
+ DEBUGK_ERR("copy_from_user() error!\n");
+ count = -EFAULT;
+ goto ret;
+ }
+
+#ifdef KDB_MSG
+ debugk_out("write data", priv->data_out.buf, count);
+#endif
+
+ last_word = (unsigned short) append_checksum(priv->data_out.buf, count);
+ memcpy(&priv->data_out.buf[count], &last_word, 2);
+
+ priv->data_out.len = count + sizeof(last_word);
+ priv->tx_status_transmitting_len = 0;
+ priv->tx_status_state = STATE_TX_INIT;
+
+ transmit_msg(priv);
+
+ret:
+ return count;
+}
+
+static void dump_private_data(void)
+{
+ //int i;
+
+ printk("cmd_timeout=%d\n", dev_priv->cmd_timeout);
+ printk("poll_timer_up=%d\n", dev_priv->poll_timer_up);
+ printk("phy_reg_poll_time=%d\n", dev_priv->phy_reg_poll_time);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
+ printk("host_pid=%d\n", dev_priv->host_pid);
+#else
+ printk("host_pid=0x%p\n", dev_priv->host_pid);
+#endif
+ printk("force_power_down=%d\n", dev_priv->force_power_down);
+ printk("eth_phy_link_status=%d\n", dev_priv->eth_phy_link_status);
+ printk("\nreg_BMCR_write=0x%04lx\n", dev_priv->reg_BMCR_write);
+ printk("reg_BMCR_read=0x%04lx\n", dev_priv->reg_BMCR_read);
+ printk("reg_BMSR_read=0x%04lx\n", dev_priv->reg_BMSR_read);
+ printk("reg_ANAR_write=0x%04lx\n", dev_priv->reg_ANAR_write);
+ printk("reg_ANAR_read=0x%04lx\n", dev_priv->reg_ANAR_read);
+ printk("reg_ANLPAR_read=0x%04lx\n", dev_priv->reg_ANLPAR_read);
+
+ printk("\nevt_que_head=%d\n", dev_priv->evt_que_head);
+ printk("evt_que_tail=%d\n", dev_priv->evt_que_tail);
+ printk("evt_que count=%d\n", CIRC_CNT(dev_priv->evt_que_head, dev_priv->evt_que_tail, EV_QUE_MAX));
+ printk("evt_que space=%d\n", CIRC_SPACE(dev_priv->evt_que_head, dev_priv->evt_que_tail, EV_QUE_MAX));
+
+ printk("\ntx_status_state:");
+ switch(dev_priv->tx_status_state) {
+ case STATE_TX_INIT:
+ printk("STATE_TX_INIT\n");
+ break;
+ case STATE_TX_IN_PROGRESS:
+ printk("STATE_TX_IN_PROGRESS\n");
+ break;
+ }
+ printk("tx_status_transmitting_len=%d\n", dev_priv->tx_status_transmitting_len);
+
+ printk("rx_cmd_state:");
+ switch(dev_priv->rx_cmd_state) {
+ case STATE_RX_INIT:
+ printk("STATE_RX_INIT\n");
+ break;
+ case STATE_RX_WAIT_LEN:
+ printk("STATE_RX_WAIT_LEN\n");
+ break;
+ case STATE_RX_WAIT_DATA:
+ printk("STATE_RX_WAIT_DATA\n");
+ break;
+ case STATE_RX_WAIT_DAEMON:
+ printk("STATE_RX_WAIT_DAEMON\n");
+ break;
+ }
+ printk("rx_cmd_remain_len=%d\n", dev_priv->rx_cmd_remain_len);
+ printk("rx_cmd_time=%lx jiffies=%lx (%d sec)\n", dev_priv->rx_cmd_time, jiffies, (int)(jiffies-dev_priv->rx_cmd_time)/HZ);
+}
+
+void mdio_private_command(int type)
+{
+ switch(type) {
+ case 0: //stop reg poll timer
+ dev_priv->poll_timer_up = 0;
+ break;
+ case 1: //start reg poll timer
+ dev_priv->poll_timer_up = 1;
+ mod_timer(&dev_priv->reg_poll_timer, jiffies + dev_priv->phy_reg_poll_time);
+ break;
+ case 2: //force power down: on
+ dev_priv->force_power_down = 1;
+ dev_priv->reg_BMCR_write = 0xf0000; //force poll timer to do power down
+ break;
+ case 3: //force power down: off
+ dev_priv->force_power_down = 0;
+ dev_priv->reg_BMCR_write = 0xf0000; //force poll timer to do power down
+ break;
+ case 4:
+ dump_private_data();
+ break;
+ case 5: //WLAN link up
+ set_wlanlink_bit(1);
+ break;
+ case 6: //WLAN link down
+ set_wlanlink_bit(0);
+ break;
+ }
+}
+
+static int mdio_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ unsigned long flags;
+ struct mdio_priv *priv = (struct mdio_priv *)filp->private_data;
+ int val, retval = 0;
+ unsigned char bval;
+ struct mdio_mem32_param mem_param;
+ struct reg_param regparam;
+
+ /*
+ * extract the type and number bitfields, and don't decode
+ * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()
+ */
+ if (_IOC_TYPE(cmd) != MDIO_IOC_MAGIC) return -ENOTTY;
+ if (_IOC_NR(cmd) > MDIO_IOCTL_MAXNR) return -ENOTTY;
+
+ switch (cmd) {
+ case MDIO_IOCTL_PRIV_CMD:
+ retval = get_user(val, (int *)arg);
+ if (retval == 0) {
+ mdio_private_command(val);
+ }
+ break;
+ case MDIO_IOCTL_GET_REG:
+ retval = copy_from_user(&regparam, (struct reg_param *)arg, sizeof(struct reg_param));
+ if (retval == 0) {
+ //printk("1regparam.addr=%x regparam.val=%x\n", regparam.addr, regparam.val);
+ regparam.val = get_ether_phy_reg(((regparam.addr>>16)&0xffff), (regparam.addr&0xffff));
+ //printk("2regparam.addr=%x regparam.val=%x\n", regparam.addr, regparam.val);
+ }
+ retval = copy_to_user((struct reg_param *)arg, &regparam, sizeof(struct reg_param));
+ break;
+ case MDIO_IOCTL_SET_REG:
+ retval = copy_from_user(&regparam, (struct reg_param *)arg, sizeof(struct reg_param));
+ if (retval == 0) {
+ //printk("regparam.addr=%x regparam.val=%x\n", regparam.addr, regparam.val);
+ set_ether_phy_reg(((regparam.addr>>16)&0xffff), (regparam.addr&0xffff), regparam.val);
+ }
+ break;
+ case MDIO_IOCTL_SET_HOST_PID:
+ retval = copy_from_user((void *)&val, (void *)arg, 4);
+ if (retval == 0) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
+ priv->host_pid = val;
+#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)
+ priv->host_pid = find_pid_ns(val,0);
+#else
+ // TODO : Check in stable 2.6.27
+ priv->host_pid = task_pid(find_task_by_vpid(val));
+ //priv->host_pid = task_pid(current);
+#endif
+ DEBUGK_OUT("set pid=%d\n", val);
+ printk("set pid=%d priv->host_pid=%p\n", val, priv->host_pid);
+ }
+ spin_lock_irqsave(&priv->reglock, flags);
+ REG32(REG_SYSSR) = REG32(REG_SYSSR) | SR_AllSoftwareReady;
+ spin_unlock_irqrestore(&priv->reglock, flags);
+ break;
+ case MDIO_IOCTL_SET_CMD_TIMEOUT:
+ retval = copy_from_user((void *)&bval, (void *)arg, 1);
+ if (retval == 0) {
+ priv->cmd_timeout = (int)bval;
+ DEBUGK_OUT("set cmd_timeout=%d\n", priv->cmd_timeout);
+ }
+ break;
+ case MDIO_IOCTL_SET_PHY_POLL_TIME:
+ retval = copy_from_user( (void *)&bval, (void *)arg, 1);
+ if (retval == 0) {
+ priv->phy_reg_poll_time = (int)bval;
+ mod_timer(&priv->reg_poll_timer, jiffies + priv->phy_reg_poll_time);
+ DEBUGK_OUT("set poll_time=%d\n", priv->phy_reg_poll_time);
+ }
+ break;
+ case MDIO_IOCTL_READ_MEM:
+ retval = copy_from_user( (void *)&mem_param.addr, (void *)arg, 4);
+ if (retval == 0) {
+ mem_param.val = READ_MEM32(mem_param.addr);
+ retval = copy_to_user((void *)arg, (void *)&mem_param.val, 4);
+ DEBUGK_OUT("read_mem: addr=0x%x, data=0x%x\n", (int)mem_param.addr, (int)mem_param.val);
+ }
+ break;
+ case MDIO_IOCTL_WRITE_MEM:
+ retval = copy_from_user((void *)&mem_param, (void *)arg, sizeof(mem_param));
+ if (retval == 0) {
+ WRITE_MEM32(mem_param.addr, mem_param.val);
+ DEBUGK_OUT("write_mem: addr=0x%x, data=0x%x\n", (int)mem_param.addr, (int)mem_param.val);
+ }
+ break;
+ case MDIO_IOCTL_SET_MII_PAUSE:
+ retval = copy_from_user( (void *)&bval, (void *)arg, 1);
+ if (retval == 0) {
+ if (bval == 0) // disable pause
+ WRITE_MEM32(PCRP0, (~(0x3<<PauseFlowControl))&READ_MEM32(PCRP0));
+ else
+ WRITE_MEM32(PCRP0, (3<<PauseFlowControl)|READ_MEM32(PCRP0));
+ DEBUGK_OUT("set mii_pause=%d\n", bval);
+ }
+ break;
+ case MDIO_IOCTL_SET_ETH_PAUSE:
+ retval = copy_from_user( (void *)&bval, (void *)arg, 1);
+ if (retval == 0) {
+ if (bval == 0) // disable pause
+ WRITE_MEM32(PCRP3, (~(0x3<<PauseFlowControl))&READ_MEM32(PCRP3));
+ else
+ WRITE_MEM32(PCRP3, (3<<PauseFlowControl)|READ_MEM32(PCRP3));
+ DEBUGK_OUT("set eth_pause=%d\n", bval);
+ }
+ break;
+ case MDIO_IOCTL_SET_MII_CLK:
+ retval = copy_from_user( (void *)&val, (void *)arg, 4);
+ if (retval == 0) {
+ if (val == 0) { //00: 25MHz at 100M mode
+ WRITE_MEM32(PCRP0, (~(0x3<<20))&READ_MEM32(PCRP0)); //force 100Mbps for port 0
+ WRITE_MEM32(P0GMIICR, (~(1<<22))&READ_MEM32(P0GMIICR)); //Turbo MII off
+ }
+ else if (val == 1) { //01: 2.5MHz at 10M mode
+ WRITE_MEM32(PCRP0, (1<<20)|((~(0x3<<20))&READ_MEM32(PCRP0))); //force 10Mbps for port 0
+ WRITE_MEM32(P0GMIICR, (~(1<<22))&READ_MEM32(P0GMIICR)); //Turbo MII off
+ }
+ else if (val == 2) { //10: 50MHz at Turbo-MII mode
+ WRITE_MEM32(PCRP0, (~(0x3<<20))&READ_MEM32(PCRP0)); //force 100Mbps for port 0
+ WRITE_MEM32(P0GMIICR, (1<<22)|READ_MEM32(P0GMIICR)); //using Turbo MII
+ }
+ //printk("set mii clk=%d\n", val);
+ }
+ break;
+ case MDIO_IOCTL_SET_SUSPEND:
+ retval = copy_from_user( (void *)&bval, (void *)arg, 1);
+ if (retval == 0) {
+ cpu_suspend_enabled = (int) bval;
+ DEBUGK_OUT("set cpu_suspend=%d\n", bval);
+ }
+ break;
+ case MDIO_IOCTL_READ_SCR:
+ val = register_read_dw(REG_SYSCR);
+ retval = copy_to_user((void *)arg, (void *)&val, sizeof(val));
+ DEBUGK_OUT("read_src src=0x%x\n", val);
+ break;
+#ifdef CONFIG_RTK_VOIP_ETHERNET_DSP_IS_DSP
+ case MDIO_IOCTL_READ_DSP_ID:
+ {
+ unsigned int id;
+ extern unsigned int Get_Ethernet_DSP_ID(void);
+ id = Get_Ethernet_DSP_ID();
+ retval = copy_to_user((void *)arg, (void *)&id, sizeof(id));
+ printk("Get DSP ID = %d\n", id);
+ break;
+ }
+#endif
+#ifdef JUMP_CMD
+ case MDIO_IOCTL_JUMP_ADDR:
+ retval = copy_from_user( (void *)&val, (void *)arg, sizeof(val));
+ if (retval == 0) {
+ extern void setup_reboot_addr(unsigned long addr);
+ extern int is_fault;
+
+ DEBUGK_OUT("jump to addr=0x%x\n", val);
+ setup_reboot_addr((unsigned long)val);
+ is_fault = 1; // cause watchdog reset
+ }
+ break;
+#endif
+ default: /* redundant, as cmd was checked against MAXNR */
+ DEBUGK_ERR("Invalid ioctl cmd [0x%x]!\n", cmd);
+ return -ENOTTY;
+ }
+ return retval;
+}
+
+#ifdef SIMULATION
+static int read_proc(char *buf, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int size = 0;
+
+ if (data_out_len > 0) {
+
+fetch_again:
+ while (data_out_len > 0) {
+ data_out_len = 0;
+ size += sprintf(&buf[size], "%04x ", data_out);
+ }
+
+ msg_is_fetched = 1;
+
+ mdio_interrupt(0, (void *)dev_priv, (struct pt_regs *)NULL);
+
+ if (data_out_len > 0)
+ goto fetch_again;
+
+ strcat(&buf[size++], "\n");
+ }
+
+ return size;
+}
+
+static unsigned short _atoi(char *s, int base)
+{
+ int k = 0;
+
+ k = 0;
+ if (base == 10) {
+ while (*s != '\0' && *s >= '0' && *s <= '9') {
+ k = 10 * k + (*s - '0');
+ s++;
+ }
+ }
+ else {
+ while (*s != '\0') {
+ int v;
+ if ( *s >= '0' && *s <= '9')
+ v = *s - '0';
+ else if ( *s >= 'a' && *s <= 'f')
+ v = *s - 'a' + 10;
+ else if ( *s >= 'A' && *s <= 'F')
+ v = *s - 'A' + 10;
+ else {
+ DEBUGK_ERR("error hex format [%x]!\n", *s);
+ return 0;
+ }
+ k = 16 * k + v;
+ s++;
+ }
+ }
+ return (unsigned short)k;
+}
+
+
+static int write_proc(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char tmp[100];
+ int len=count;
+ unsigned short in_data;
+
+ if (!memcmp(buffer, "cmd: ", 5)) {
+ buffer += 5;
+ len -= 5;
+ data_in_len = 0;
+ while (len > 0) {
+ memcpy(tmp, buffer, 4);
+ tmp[4] = '\0';
+
+ in_data = _atoi(tmp, 16);
+
+ memcpy(&data_in[data_in_len], &in_data, 2);
+ data_in_len += 2;
+ len -= 5;
+ buffer += 5;
+ }
+
+ data_in_read_idx = 0;
+ mdio_interrupt(0, (void *)dev_priv, (struct pt_regs *)NULL);
+ }
+ else if (!memcmp(buffer, "scr: ", 5)) {
+ buffer += 5;
+ memcpy(tmp, buffer, 4);
+ tmp[4] = '\0';
+ reg_scr = _atoi(tmp, 16);
+ }
+ else if (!memcmp(buffer, "isr: ", 5)) {
+ buffer += 5;
+ memcpy(tmp, buffer, 4);
+ tmp[4] = '\0';
+ reg_isr = _atoi(tmp, 16);
+
+ mdio_interrupt(0, (void *)dev_priv, (struct pt_regs *)NULL);
+ }
+ else {
+ printk("Invalid cmd!\n");
+ }
+
+ return count;
+}
+#endif
+
+
+static void __exit mdio_exit(void)
+{
+ //DEBUGK_OUT("%s: major=%d, minor=%d\n", __FUNCTION__, MAJOR(inode->i_rdev), MINOR(inode->i_rdev));
+
+ REG32(REG_IMR) = 0;
+
+ free_irq(BSP_NFBI_IRQ, dev_priv);
+
+ del_timer_sync(&dev_priv->reg_poll_timer);
+
+ kfree(dev_priv);
+
+ dev_priv = NULL;
+}
+
+static struct file_operations mdio_fops = {
+ read: mdio_read,
+ write: mdio_write,
+ ioctl: mdio_ioctl,
+ open: mdio_open,
+ release: mdio_close,
+};
+
+static int __init mdio_init(void)
+{
+ struct mdio_priv *priv;
+
+ if (register_chrdev(DRIVER_MAJOR, DRIVER_NAME, &mdio_fops)) {
+ DEBUGK_ERR(KERN_ERR DRIVER_NAME": unable to get major %d\n", DRIVER_MAJOR);
+ return -EIO;
+ }
+
+#ifdef SIMULATION
+ struct proc_dir_entry *res;
+ res = create_proc_entry("mdio_flag", 0, NULL);
+ if (res) {
+ res->read_proc = read_proc;
+ res->write_proc = write_proc;
+ }
+ else {
+ DEBUGK_ERR(KERN_ERR DRIVER_NAME": unable to create /proc/mdio_flag\n");
+ return -1;
+ }
+#endif
+
+ printk(KERN_INFO DRIVER_NAME" driver "DRIVER_VER" at %x (Interrupt %d)\n", NFBI_BASE, BSP_NFBI_IRQ);
+
+ DEBUGK_OUT("%s: major=%d, minor=%d\n", __FUNCTION__, MAJOR(inode->i_rdev), MINOR(inode->i_rdev));
+
+ priv = (struct mdio_priv *)kmalloc(sizeof (struct mdio_priv), GFP_KERNEL);
+ if(!priv)
+ return -ENOMEM;
+
+ memset((void *)priv, 0, sizeof (struct mdio_priv));
+ priv->reglock = SPIN_LOCK_UNLOCKED;
+ //if (request_irq(BSP_NFBI_IRQ, mdio_interrupt, SA_INTERRUPT, DRIVER_NAME, (void *)priv)) {
+ //if (request_irq(BSP_NFBI_IRQ, mdio_interrupt, IRQF_DISABLED, DRIVER_NAME, (void *)priv)) {
+ if (request_irq(BSP_NFBI_IRQ, mdio_interrupt, 0, DRIVER_NAME, (void *)priv)) {
+ DEBUGK_ERR(KERN_ERR DRIVER_NAME": IRQ %d is not free.\n", BSP_NFBI_IRQ);
+ return -1;
+ }
+ else
+ printk("Request BSP_NFBI_IRQ successfully.\n");
+
+ REG32(REG_IMR) = NEEDED_IRQ_MASK;
+
+#if 1
+ //force the poll time to update the register
+ priv->reg_BMCR_write = 0xf0000;
+ priv->reg_BMCR_read = 0xf0000;
+ priv->reg_BMSR_read = 0xf0000;
+ priv->reg_ANAR_write = 0xf0000;
+ priv->reg_ANAR_read = 0xf0000;
+ priv->reg_ANLPAR_read = 0xf0000;
+ priv->eth_phy_link_status = -1;
+#else
+ priv->reg_BMCR_write = REG32(REG_BMCR);
+ set_ether_phy_reg(ETH_PORT_NUM, 0, priv->reg_BMCR_write);
+
+ priv->reg_BMCR_read = get_ether_phy_reg(ETH_PORT_NUM, 0);
+ REG32(REG_BMCR) = priv->reg_BMCR_read;
+
+ priv->reg_BMSR_read = get_ether_phy_reg(ETH_PORT_NUM, 1);
+ REG32(REG_BMSR) = priv->reg_BMSR_read;
+
+ priv->reg_ANAR_write = REG32(REG_ANAR);
+ set_ether_phy_reg(ETH_PORT_NUM, 4, priv->reg_ANAR_write);
+ //printk("priv->reg_ANAR_write=%x\n", priv->reg_ANAR_write);
+
+ priv->reg_ANAR_read = get_ether_phy_reg(ETH_PORT_NUM, 4);
+ REG32(REG_ANAR) = priv->reg_ANAR_read;
+ //printk("priv->reg_ANAR_read=%x\n", priv->reg_ANAR_read);
+
+ priv->reg_ANLPAR_read = get_ether_phy_reg(ETH_PORT_NUM, 5);
+ REG32(REG_ANLPAR) = priv->reg_ANLPAR_read;
+
+ priv->eth_phy_link_status = ((priv->reg_BMSR_read & BIT(2)) ? 1 : 0);
+#endif
+
+ init_timer(&priv->reg_poll_timer);
+ priv->reg_poll_timer.data = (unsigned long)priv;
+ priv->reg_poll_timer.function = mdio_reg_poll_timer;
+ priv->poll_timer_up = 0;
+ priv->force_power_down = 0;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
+ priv->host_pid = -1;
+#else
+ priv->host_pid = NULL;
+#endif
+ dev_priv = priv;
+
+ return 0;
+}
+
+
+/*================================================================*/
+
+module_init(mdio_init);
+module_exit(mdio_exit);
+
+MODULE_DESCRIPTION("Driver for RTL8197B MDC/MDIO");
+MODULE_LICENSE("none-GPL");
+//EXPORT_NO_SYMBOLS;
diff --git a/target/linux/realtek/files/drivers/char/rtl_mdio/rtl_mdio.h b/target/linux/realtek/files/drivers/char/rtl_mdio/rtl_mdio.h
new file mode 100644
index 000000000..5def6bd34
--- /dev/null
+++ b/target/linux/realtek/files/drivers/char/rtl_mdio/rtl_mdio.h
@@ -0,0 +1,309 @@
+/*
+################################################################################
+#
+# RTL8198 MDIO char driver header
+#
+# Copyright(c) 2010 Realtek Semiconductor Corp. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# Author:
+# Realtek WiFi AP software team <cn_sd8@realtek.com>
+# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
+#
+################################################################################
+*/
+/*================================================================*/
+
+#ifndef INCLUDE_RTL_MDIO_H
+#define INCLUDE_RTL_MDIO_H
+
+
+/*================================================================*/
+/* Compiling Flags */
+
+#define KDB_ERR // defined to print out error message
+//#define KDB_MSG // defined to print out debug message
+//#define SIMULATION // defined to do simuation
+#ifndef CONFIG_RTK_VOIP_ETHERNET_DSP_IS_DSP
+#define JUMP_CMD // defined to add jump ioctl cmd, for development purpose
+#endif
+
+
+/*================================================================*/
+/* Constant Definitions */
+
+#define DRIVER_NAME "rtl_mdio"
+#define DRIVER_VER "0.2"
+#define IO_LEN 0x40
+#define DRIVER_MAJOR 14
+#define MDIO_BUFSIZE 516 //2 + 2 + 2*255 + 2
+#define EV_QUE_MAX 16
+//#define BIT(x) (1 << (x))
+
+// RTL8197B IRQ number and Register offset
+#define NFBI_BASE 0xb8019000 // NFBI base address
+#define REG_RCR (0x00+NFBI_BASE) // Receive Command Register
+#define REG_SSR (0x04+NFBI_BASE) // Send Status Register
+#define REG_SYSCR (0x08+NFBI_BASE) // System Control Register
+#define REG_SYSSR (0x0C+NFBI_BASE) // System Status Register
+#define REG_IMR (0x10+NFBI_BASE) // Interrupt Mask Register
+#define REG_ISR (0x14+NFBI_BASE) // Interrupt Status Register
+#define REG_BMCR (0x20+NFBI_BASE) // Basic Mode Control Register
+#define REG_BMSR (0x24+NFBI_BASE) // Basic Mode Status Register
+#define REG_ANAR (0x28+NFBI_BASE) // Auto-Negotiation Advertisement Register
+#define REG_ANLPAR (0x2C+NFBI_BASE) // Auto-Negotiation Link Partner Ability Register
+#define REG_NFBIRR (0x30+NFBI_BASE) // NFBI Reset Control Register
+
+// bitmask definition for ISR
+#define IP_ISOLATION BIT(15) // ISOLATION Interrupt Pending
+#define IP_ETHMAC BIT(14) // Enable/disable Ethernet MAC
+#define IP_WLANMAC BIT(13) // Enable/disable WLAN MAC
+#define IP_ETHPHY BIT(12) // Enable/disable Ethernet PHY
+#define IP_WLANPHY BIT(11) // Enable/disable WLAN PHY
+#define IP_SELMIICLK BIT(10) // Select MII Clock Speed
+#define IP_RSVD9 BIT(9) // Reserved
+#define IP_CUSTOM8 BIT(8) // Customized used 8
+#define IP_CUSTOM7 BIT(7) // Customized used 7
+#define IP_CUSTOM6 BIT(6) // Customized used 6
+#define IP_CUSTOM5 BIT(5) // Customized used 5
+#define IP_CUSTOM4 BIT(4) // Customized used 4
+#define IP_CUSTOM3 BIT(3) // Customized used 3
+#define IP_MSGFETCH BIT(2) // Previous msg has been fetched
+#define IP_NEWMSG BIT(1) // New msg has come
+#define IP_RSVD0 BIT(0) // Reserved
+
+// bitmask definition for SCR
+#define CR_ISOLATION BIT(15) // ISOLATION control bit
+#define CR_ETHMAC BIT(14) // Ethernet MAC control bit
+#define CR_WLANMAC BIT(13) // WLAN MAC control bit
+#define CR_ETHPHY BIT(12) // Ethernet PHY control bi
+#define CR_WLANPHY BIT(11) // WLAN PHY control bit
+#define CR_SELMIICLK (BIT(10)|BIT(9)) // Select MII Clock Speed control bit
+#define CR_CUSTOM8 BIT(8) // Customized used 8
+#define CR_CUSTOM7 BIT(7) // Customized used 7
+#define CR_CUSTOM6 BIT(6) // Customized used 6
+#define CR_CUSTOM5 BIT(5) // Customized used 5
+#define CR_CUSTOM4 BIT(4) // Customized used 4
+#define CR_CUSTOM3 BIT(3) // Customized used 3
+#define CR_CUSTOM2 BIT(2) // Customized used 2
+#define CR_CUSTOM1 BIT(1) // Customized used 1
+#define CR_CUSTOM0 BIT(0) // Customized used 0
+
+// bitmask definition for SYSSR
+#define SR_CheckSumDone BIT(15)
+#define SR_CheckSumOK BIT(14)
+#define SR_WLANLink BIT(13)
+#define SR_EthLink BIT(12)
+#define SR_EthPHYStatusChange BIT(11)
+#define SR_AllSoftwareReady BIT(10)
+#define SR_USBInsertStatus BIT(7)
+#define SR_USBRemoveStatus BIT(6)
+#define SR_BootcodeReady BIT(5)
+
+// rx cmd id bitmask
+#define FIRST_CMD_MASK BIT(15)
+
+// All received interrupt mask
+#ifdef CONFIG_RTK_VOIP_ETHERNET_DSP_IS_DSP
+#define NEEDED_IRQ_MASK (IP_NEWMSG|IP_MSGFETCH|IP_SELMIICLK|IP_WLANPHY| \
+ IP_ETHPHY|IP_WLANMAC|IP_ETHMAC|IP_ISOLATION|IP_CUSTOM3)
+#else
+#define NEEDED_IRQ_MASK (IP_NEWMSG|IP_MSGFETCH|IP_SELMIICLK|IP_WLANPHY| \
+ IP_ETHPHY|IP_WLANMAC|IP_ETHMAC|IP_ISOLATION)
+#endif
+
+/* Ether register base address */
+#define MACCR_BASE 0xbb804000 /* Internal Ether MAC base address */
+#define PCRAM_BASE (MACCR_BASE+0x100) /* Per-port Configuration Register */
+#define PCRP0 (0x004 + PCRAM_BASE) /* Port Configuration Register of Port 0 */
+#define PCRP3 (0x010 + PCRAM_BASE) /* Port Configuration Register of Port 3 */
+#define P0GMIICR (0x04C + PCRAM_BASE) /* Port-0 GMII Configuration Register */
+#define PauseFlowControl 8 /* Bit-shift number of PauseFlowControl */
+
+/* MAC control register field definitions */
+#define MDCIOCR (0x004+MACCR_BASE) /* MDC/MDIO Command */
+#define MDCIOSR (0x008+MACCR_BASE) /* MDC/MDIO Status */
+//#define STATUS (1<<31) /* 0: Process Done, 1: In progress */
+//STATUS has been defined in linux-2.6.30/arch/rlx/include/asm/ptrace.h
+#define MDCIO_STATUS (1<<31) /* 0: Process Done, 1: In progress */
+
+/* MDCIOCR - MDC/MDIO Command */
+#define COMMAND_READ (0<<31) /* 0:Read Access, 1:Write Access */
+#define COMMAND_WRITE (1<<31) /* 0:Read Access, 1:Write Access */
+
+#define PHYADD_OFFSET (24) /* PHY Address, said, PHY ID */
+#define REGADD_OFFSET (16) /* PHY Register */
+
+#define ETH_PORT_NUM (3) /* Port number of built-in Ether phy */
+#define MII_PORT_NUM (0) /* Port number of NFBI MII */
+
+// rx cmd state
+enum {
+ STATE_RX_INIT,
+ STATE_RX_WAIT_LEN,
+ STATE_RX_WAIT_DATA,
+ STATE_RX_WAIT_DAEMON
+};
+
+// tx status state
+enum {
+ STATE_TX_INIT,
+ STATE_TX_IN_PROGRESS
+};
+
+// indication event id
+enum {
+ IND_CMD_EV,
+ IND_SYSCTL_EV
+};
+
+// cmd id of write data
+enum {
+ WRITE_MDIO,
+ SET_CMD_TIMEOUT,
+ SET_PHY_POLL_TIME,
+ SET_HOST_PID,
+};
+
+// cmd id of ioctl
+#define MDIO_IOC_MAGIC 'k'
+
+#define MDIO_IOCTL_SET_HOST_PID _IOW(MDIO_IOC_MAGIC, 0, int)
+#define MDIO_IOCTL_SET_CMD_TIMEOUT _IOW(MDIO_IOC_MAGIC, 1, char)
+#define MDIO_IOCTL_SET_PHY_POLL_TIME _IOW(MDIO_IOC_MAGIC, 2, char)
+#define MDIO_IOCTL_READ_MEM _IOWR(MDIO_IOC_MAGIC, 3, int)
+#define MDIO_IOCTL_WRITE_MEM _IOW(MDIO_IOC_MAGIC, 4, struct mdio_mem32_param)
+#define MDIO_IOCTL_SET_MII_PAUSE _IOW(MDIO_IOC_MAGIC, 5, char)
+#define MDIO_IOCTL_SET_SUSPEND _IOW(MDIO_IOC_MAGIC, 6, char)
+#define MDIO_IOCTL_READ_SCR _IOR(MDIO_IOC_MAGIC, 7, int)
+#define MDIO_IOCTL_JUMP_ADDR _IOW(MDIO_IOC_MAGIC, 8, int)
+#define MDIO_IOCTL_PRIV_CMD _IOW(MDIO_IOC_MAGIC, 9, int)
+#define MDIO_IOCTL_GET_REG _IOWR(MDIO_IOC_MAGIC, 10, struct reg_param)
+#define MDIO_IOCTL_SET_REG _IOW(MDIO_IOC_MAGIC, 11, struct reg_param)
+#define MDIO_IOCTL_SET_MII_CLK _IOW(MDIO_IOC_MAGIC, 12, int)
+#define MDIO_IOCTL_SET_ETH_PAUSE _IOW(MDIO_IOC_MAGIC, 13, char)
+#ifdef CONFIG_RTK_VOIP_ETHERNET_DSP_IS_DSP
+#define MDIO_IOCTL_READ_DSP_ID _IOW(MDIO_IOC_MAGIC, 14, unsigned int)
+#define MDIO_IOCTL_MAXNR 14
+#else
+#define MDIO_IOCTL_MAXNR 13
+#endif
+
+#define TIME_DIFF(a, b) ((a >= b)? (a - b):(0xffffffff - b + a + 1))
+#define EVT_BUF_OFFSET ((int)(long *)&(((struct evt_msg *)0)->buf))
+#ifdef REG32
+ #undef REG32
+#endif
+#define REG32(reg) (*((volatile unsigned long *)(reg)))
+
+#ifdef WRITE_MEM32
+ #undef WRITE_MEM32
+ #undef READ_MEM32
+#endif
+#define WRITE_MEM32(reg,val) REG32(reg)=val
+#define READ_MEM32(reg) REG32(reg)
+
+#ifndef SIMULATION
+#define register_read_dw(offset) (REG32(offset))
+#define register_write_dw(offset, data) (REG32(offset)=data)
+#endif
+
+#define PUT_IN_DATA(data) { \
+ memcpy(&priv->data_in.buf[priv->data_in.len], &data, 2); \
+ priv->data_in.len += 2; \
+}
+
+#define RESET_RX_STATE { \
+ priv->rx_cmd_state = STATE_RX_INIT; \
+ priv->data_in.len = 0; \
+ priv->rx_cmd_time = 0; \
+}
+
+#ifdef KDB_MSG
+ #define DEBUGK_OUT(fmt, args...) printk("%s_%s: "fmt, DRIVER_NAME, __FUNCTION__, ## args)
+
+ #define ASSERT(expr) \
+ if(!(expr)) { \
+ printk( "\033[33;41m%s:%d: assert(%s)\033[m\n", \
+ __FILE__,__LINE__,#expr); \
+ }
+#else
+ #define DEBUGK_OUT(fmt, args...)
+
+ #define ASSERT(expr)
+#endif
+
+#ifdef KDB_ERR
+ #define DEBUGK_ERR(fmt, args...) printk("%s_%s_ERR: "fmt, DRIVER_NAME, __FUNCTION__, ## args)
+#else
+ #define DEBUGK_ERR(fmt, args...)
+#endif
+
+/*================================================================*/
+/* Structure Definition */
+
+struct buf_ar {
+ int len;
+ unsigned char buf[MDIO_BUFSIZE];
+};
+
+struct evt_msg {
+ int id; // event id
+ int len; // length in buf
+ unsigned char buf[MDIO_BUFSIZE];
+};
+
+struct mdio_mem32_param {
+ unsigned long addr;
+ unsigned long val;
+};
+
+struct reg_param {
+ unsigned long addr;
+ unsigned long val;
+};
+
+#ifdef __KERNEL__
+struct mdio_priv {
+ int cmd_timeout; // in 10ms
+ int phy_reg_poll_time; // in 10ms
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
+ int host_pid; // pid of host-daemon
+#else
+ struct pid *host_pid;
+#endif
+ int poll_timer_up;
+ int force_power_down;
+ struct timer_list reg_poll_timer;
+ unsigned long reg_BMCR_read, reg_BMCR_write;
+ unsigned long reg_BMSR_read;
+ unsigned long reg_ANAR_read, reg_ANAR_write;
+ unsigned long reg_ANLPAR_read;
+ int eth_phy_link_status;
+ struct file *filp;
+ struct buf_ar data_out;
+ struct buf_ar data_in;
+ int rx_cmd_state;
+ unsigned long rx_cmd_time;
+ int rx_cmd_remain_len;
+ int tx_status_state;
+ int tx_status_transmitting_len;
+ int evt_que_head, evt_que_tail;
+ struct evt_msg ind_evt_que[EV_QUE_MAX];
+ spinlock_t reglock;
+};
+#endif
+
+#endif // INCLUDE_RTL_MDIO_H