aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/mediatek/patches
diff options
context:
space:
mode:
authorJohn Crispin <john@openwrt.org>2015-11-02 10:18:50 +0000
committerJohn Crispin <john@openwrt.org>2015-11-02 10:18:50 +0000
commit25afe99b31f4ef3d835f96545e370770c230ac44 (patch)
tree5dbe83834a0a67121c557b7549a13221317f07eb /target/linux/mediatek/patches
parent12e0d2737f558e886cf698e939f1758ab6a64947 (diff)
downloadupstream-25afe99b31f4ef3d835f96545e370770c230ac44.tar.gz
upstream-25afe99b31f4ef3d835f96545e370770c230ac44.tar.bz2
upstream-25afe99b31f4ef3d835f96545e370770c230ac44.zip
mediatek: add support for the new MT7623 Arm SoC
the support is still WIP. next steps are to make the pmic and ethernet work. this is the first commit to make sure nothing gets lost. Signed-off-by: John Crispin <blogic@openwrt.org> SVN-Revision: 47354
Diffstat (limited to 'target/linux/mediatek/patches')
-rw-r--r--target/linux/mediatek/patches/0001-clk-make-strings-in-parent-name-arrays-const.patch100
-rw-r--r--target/linux/mediatek/patches/0002-clk-mediatek-Add-initial-common-clock-support-for-Me.patch977
-rw-r--r--target/linux/mediatek/patches/0003-clk-mediatek-Add-reset-controller-support.patch155
-rw-r--r--target/linux/mediatek/patches/0004-clk-mediatek-Add-basic-clocks-for-Mediatek-MT8135.patch952
-rw-r--r--target/linux/mediatek/patches/0005-clk-mediatek-Add-basic-clocks-for-Mediatek-MT8173.patch1179
-rw-r--r--target/linux/mediatek/patches/0006-soc-mediatek-Add-infracfg-misc-driver-support.patch179
-rw-r--r--target/linux/mediatek/patches/0007-dt-bindings-soc-Add-documentation-for-the-MediaTek-S.patch57
-rw-r--r--target/linux/mediatek/patches/0008-soc-Mediatek-Add-SCPSYS-power-domain-driver.patch573
-rw-r--r--target/linux/mediatek/patches/0009-dt-bindings-ARM-Mediatek-Document-devicetree-binding.patch154
-rw-r--r--target/linux/mediatek/patches/0010-thermal-consistently-use-int-for-temperatures.patch1155
-rw-r--r--target/linux/mediatek/patches/0011-thermal-trivial-fix-typo-in-comment.patch27
-rw-r--r--target/linux/mediatek/patches/0012-thermal-remove-useless-call-to-thermal_zone_device_s.patch34
-rw-r--r--target/linux/mediatek/patches/0013-thermal-Use-IS_ENABLED-instead-of-ifdef.patch106
-rw-r--r--target/linux/mediatek/patches/0014-thermal-Add-comment-explaining-test-for-critical-tem.patch34
-rw-r--r--target/linux/mediatek/patches/0015-thermal-inline-only-once-used-function.patch53
-rw-r--r--target/linux/mediatek/patches/0016-thermal-streamline-get_trend-callbacks.patch123
-rw-r--r--target/linux/mediatek/patches/0017-thermal-Allow-sensor-ops-to-fail-with-ENOSYS.patch90
-rw-r--r--target/linux/mediatek/patches/0018-thermal-of-always-set-sensor-related-callbacks.patch129
-rw-r--r--target/linux/mediatek/patches/0019-thermal-Make-struct-thermal_zone_device_ops-const.patch327
-rw-r--r--target/linux/mediatek/patches/0020-thermal-thermal-Add-support-for-hardware-tracked-tri.patch124
-rw-r--r--target/linux/mediatek/patches/0021-thermal-of-implement-.set_trips-for-device-tree-ther.patch65
-rw-r--r--target/linux/mediatek/patches/0022-dt-bindings-thermal-Add-binding-document-for-Mediate.patch57
-rw-r--r--target/linux/mediatek/patches/0023-thermal-Add-Mediatek-thermal-controller-support.patch785
-rw-r--r--target/linux/mediatek/patches/0024-ARM64-dts-mt8173-Add-thermal-auxadc-device-nodes.patch49
-rw-r--r--target/linux/mediatek/patches/0025-dt-bindings-ARM-Mediatek-Document-devicetree-binding.patch53
-rw-r--r--target/linux/mediatek/patches/0026-spi-mediatek-Add-spi-bus-for-Mediatek-MT8173.patch679
-rw-r--r--target/linux/mediatek/patches/0027-dt-bindings-pwm-add-Mediatek-display-PWM-bindings.patch47
-rw-r--r--target/linux/mediatek/patches/0028-pwm-add-Mediatek-display-PWM-driver-support.patch281
-rw-r--r--target/linux/mediatek/patches/0029-dt-bindings-Add-I2C-bindings-for-mt65xx-mt81xx.patch64
-rw-r--r--target/linux/mediatek/patches/0030-I2C-mediatek-Add-driver-for-MediaTek-I2C-controller.patch760
-rw-r--r--target/linux/mediatek/patches/0031-I2C-mediatek-Add-driver-for-MediaTek-MT8173-I2C-cont.patch244
-rw-r--r--target/linux/mediatek/patches/0032-dt-bindings-mediatek-Add-MT8173-cpufreq-driver-bindi.patch150
-rw-r--r--target/linux/mediatek/patches/0033-cpufreq-mediatek-Add-MT8173-cpufreq-driver.patch604
-rw-r--r--target/linux/mediatek/patches/0034-mmc-dt-bindings-add-Mediatek-MMC-bindings.patch54
-rw-r--r--target/linux/mediatek/patches/0035-mmc-mediatek-Add-Mediatek-MMC-driver.patch1422
-rw-r--r--target/linux/mediatek/patches/0036-mmc-mediatek-Add-PM-support-for-MMC-driver.patch209
-rw-r--r--target/linux/mediatek/patches/0037-arm64-mediatek-Add-Mediatek-MMC-support-in-defconfig.patch28
-rw-r--r--target/linux/mediatek/patches/0038-ARM-multi_v7_defconfig-Enable-Mediatek-MMC-support-m.patch29
-rw-r--r--target/linux/mediatek/patches/0039-clocksource-mediatek-Don-t-run-event_handler-if-it-i.patch32
-rw-r--r--target/linux/mediatek/patches/0040-clocksource-mediatek-Use-GPT-as-sched-clock-source.patch51
-rw-r--r--target/linux/mediatek/patches/0041-arm-mediatek-enable-gpt6-on-boot-up-to-make-arch-tim.patch63
-rw-r--r--target/linux/mediatek/patches/0042-ARM-mediatek-add-smp-bringup-code.patch178
-rw-r--r--target/linux/mediatek/patches/0043-ARM-dts-mt8127-enable-basic-SMP-bringup-for-mt8127.patch53
-rw-r--r--target/linux/mediatek/patches/0044-dt-bindings-Add-usb3.0-phy-binding-for-MT65xx-SoCs.patch60
-rw-r--r--target/linux/mediatek/patches/0045-dt-bindings-Add-a-binding-for-Mediatek-xHCI-host-con.patch43
-rw-r--r--target/linux/mediatek/patches/0046-usb-phy-add-usb3.0-phy-driver-for-mt65xx-SoCs.patch779
-rw-r--r--target/linux/mediatek/patches/0047-xhci-mediatek-support-MTK-xHCI-host-controller.patch832
-rw-r--r--target/linux/mediatek/patches/0048-dt-bindings-mediatek-Modify-pinctrl-bindings-for-mt6.patch46
-rw-r--r--target/linux/mediatek/patches/0049-pinctrl-dt-bindings-mt6397-Add-pinfunc-header-file-f.patch279
-rw-r--r--target/linux/mediatek/patches/0050-pinctrl-mediatek-data-struct-optimize-and-remove-unu.patch116
-rw-r--r--target/linux/mediatek/patches/0051-pinctrl-mediatek-add-mtk_pctrl_spec_pull_set_samereg.patch328
-rw-r--r--target/linux/mediatek/patches/0052-pinctrl-mediatek-add-ies-smt-control-to-common-code.patch479
-rw-r--r--target/linux/mediatek/patches/0053-pinctrl-mediatek-Add-Pinctrl-GPIO-driver-for-mt6397.patch654
-rw-r--r--target/linux/mediatek/patches/0054-pinctrl-mediatek-add-pinctrl-GPIO-EINT-driver-for-mt.patch1740
-rw-r--r--target/linux/mediatek/patches/0055-mfd-mediatek-Add-GPIO-sub-module-support-into-mfd.patch30
-rw-r--r--target/linux/mediatek/patches/0056-ARM-dts-mt8127-add-pinctrl-GPIO-EINT-node-for-mt8127.patch809
-rw-r--r--target/linux/mediatek/patches/0057-thermal-oops.patch27
-rw-r--r--target/linux/mediatek/patches/0058-dont-disable-clocks.patch25
-rw-r--r--target/linux/mediatek/patches/0059-arm-mediatek-basic-mt6323-pmic-support.patch1099
-rw-r--r--target/linux/mediatek/patches/0060-arm-mediatek-select-the-arm-timer-by-default.patch26
-rw-r--r--target/linux/mediatek/patches/0061-arm-mediatek-add-mt7623-clock.patch846
-rw-r--r--target/linux/mediatek/patches/0062-arm-mediatek-add-mt7623-pinctrl-supoort.patch2889
-rw-r--r--target/linux/mediatek/patches/0063-arm-mediatek-add-SDK-ethernet.patch20654
-rw-r--r--target/linux/mediatek/patches/0064-arm-mediatek-add-mt7623-pcie-support.patch436
-rw-r--r--target/linux/mediatek/patches/0065-arm-mediatek-add-mt7623-smp-support.patch38
-rw-r--r--target/linux/mediatek/patches/0066-arm-mediatek-add-m7623-devicetree.patch551
-rw-r--r--target/linux/mediatek/patches/0067-arm-mediatek-add-mt7623-support.patch118
-rw-r--r--target/linux/mediatek/patches/0068-SDK_compat.patch1579
-rw-r--r--target/linux/mediatek/patches/0069-arm-mediatek-add-mt7623-support-to-pmic-wrapper.patch554
-rw-r--r--target/linux/mediatek/patches/0070-clk-mediatek-Export-CPU-mux-clocks-for-CPU-frequency.patch199
-rw-r--r--target/linux/mediatek/patches/0071-clk.patch342
-rw-r--r--target/linux/mediatek/patches/0072-mfd.patch1591
-rw-r--r--target/linux/mediatek/patches/0073-clk.patch200
-rw-r--r--target/linux/mediatek/patches/0074-dts.patch182
-rw-r--r--target/linux/mediatek/patches/0075-sd.patch55
-rw-r--r--target/linux/mediatek/patches/0076-reset.patch30
76 files changed, 50121 insertions, 0 deletions
diff --git a/target/linux/mediatek/patches/0001-clk-make-strings-in-parent-name-arrays-const.patch b/target/linux/mediatek/patches/0001-clk-make-strings-in-parent-name-arrays-const.patch
new file mode 100644
index 0000000000..3dca509648
--- /dev/null
+++ b/target/linux/mediatek/patches/0001-clk-make-strings-in-parent-name-arrays-const.patch
@@ -0,0 +1,100 @@
+From a38e86708141d75c643ffd58865c50a925134e4f Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Thu, 23 Apr 2015 10:35:38 +0200
+Subject: [PATCH 01/76] clk: make strings in parent name arrays const
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The clk functions and structs declare the parent_name arrays as
+'const char **parent_names' which means the parent name strings
+are const, but the array itself is not. Use
+'const char * const * parent_names' instead which also makes
+the array const. This allows us to put the parent_name arrays into
+the __initconst section.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
+Tested-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
+Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+---
+ drivers/clk/clk-composite.c | 2 +-
+ drivers/clk/clk-mux.c | 4 ++--
+ include/linux/clk-provider.h | 8 ++++----
+ 3 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
+index 956b7e5..077f4c7 100644
+--- a/drivers/clk/clk-composite.c
++++ b/drivers/clk/clk-composite.c
+@@ -188,7 +188,7 @@ static void clk_composite_disable(struct clk_hw *hw)
+ }
+
+ struct clk *clk_register_composite(struct device *dev, const char *name,
+- const char **parent_names, int num_parents,
++ const char * const *parent_names, int num_parents,
+ struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
+ struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
+ struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
+index 69a094c..1fa2a8d 100644
+--- a/drivers/clk/clk-mux.c
++++ b/drivers/clk/clk-mux.c
+@@ -114,7 +114,7 @@ const struct clk_ops clk_mux_ro_ops = {
+ EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
+
+ struct clk *clk_register_mux_table(struct device *dev, const char *name,
+- const char **parent_names, u8 num_parents, unsigned long flags,
++ const char * const *parent_names, u8 num_parents, unsigned long flags,
+ void __iomem *reg, u8 shift, u32 mask,
+ u8 clk_mux_flags, u32 *table, spinlock_t *lock)
+ {
+@@ -166,7 +166,7 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
+ EXPORT_SYMBOL_GPL(clk_register_mux_table);
+
+ struct clk *clk_register_mux(struct device *dev, const char *name,
+- const char **parent_names, u8 num_parents, unsigned long flags,
++ const char * const *parent_names, u8 num_parents, unsigned long flags,
+ void __iomem *reg, u8 shift, u8 width,
+ u8 clk_mux_flags, spinlock_t *lock)
+ {
+diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
+index df69531..ec609e5 100644
+--- a/include/linux/clk-provider.h
++++ b/include/linux/clk-provider.h
+@@ -209,7 +209,7 @@ struct clk_ops {
+ struct clk_init_data {
+ const char *name;
+ const struct clk_ops *ops;
+- const char **parent_names;
++ const char * const *parent_names;
+ u8 num_parents;
+ unsigned long flags;
+ };
+@@ -426,12 +426,12 @@ extern const struct clk_ops clk_mux_ops;
+ extern const struct clk_ops clk_mux_ro_ops;
+
+ struct clk *clk_register_mux(struct device *dev, const char *name,
+- const char **parent_names, u8 num_parents, unsigned long flags,
++ const char * const *parent_names, u8 num_parents, unsigned long flags,
+ void __iomem *reg, u8 shift, u8 width,
+ u8 clk_mux_flags, spinlock_t *lock);
+
+ struct clk *clk_register_mux_table(struct device *dev, const char *name,
+- const char **parent_names, u8 num_parents, unsigned long flags,
++ const char * const *parent_names, u8 num_parents, unsigned long flags,
+ void __iomem *reg, u8 shift, u32 mask,
+ u8 clk_mux_flags, u32 *table, spinlock_t *lock);
+
+@@ -518,7 +518,7 @@ struct clk_composite {
+ };
+
+ struct clk *clk_register_composite(struct device *dev, const char *name,
+- const char **parent_names, int num_parents,
++ const char * const *parent_names, int num_parents,
+ struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
+ struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
+ struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0002-clk-mediatek-Add-initial-common-clock-support-for-Me.patch b/target/linux/mediatek/patches/0002-clk-mediatek-Add-initial-common-clock-support-for-Me.patch
new file mode 100644
index 0000000000..d5f52d15e8
--- /dev/null
+++ b/target/linux/mediatek/patches/0002-clk-mediatek-Add-initial-common-clock-support-for-Me.patch
@@ -0,0 +1,977 @@
+From f851b4ea6cae9fd5875036b6d3968375882ce56b Mon Sep 17 00:00:00 2001
+From: James Liao <jamesjj.liao@mediatek.com>
+Date: Thu, 23 Apr 2015 10:35:39 +0200
+Subject: [PATCH 02/76] clk: mediatek: Add initial common clock support for
+ Mediatek SoCs.
+
+This patch adds common clock support for Mediatek SoCs, including plls,
+muxes and clock gates.
+
+Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
+Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/clk/Makefile | 1 +
+ drivers/clk/mediatek/Makefile | 1 +
+ drivers/clk/mediatek/clk-gate.c | 137 ++++++++++++++++
+ drivers/clk/mediatek/clk-gate.h | 49 ++++++
+ drivers/clk/mediatek/clk-mtk.c | 220 ++++++++++++++++++++++++++
+ drivers/clk/mediatek/clk-mtk.h | 159 +++++++++++++++++++
+ drivers/clk/mediatek/clk-pll.c | 332 +++++++++++++++++++++++++++++++++++++++
+ 7 files changed, 899 insertions(+)
+ create mode 100644 drivers/clk/mediatek/Makefile
+ create mode 100644 drivers/clk/mediatek/clk-gate.c
+ create mode 100644 drivers/clk/mediatek/clk-gate.h
+ create mode 100644 drivers/clk/mediatek/clk-mtk.c
+ create mode 100644 drivers/clk/mediatek/clk-mtk.h
+ create mode 100644 drivers/clk/mediatek/clk-pll.c
+
+diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
+index 3d00c25..d965b3f 100644
+--- a/drivers/clk/Makefile
++++ b/drivers/clk/Makefile
+@@ -51,6 +51,7 @@ obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/
+ obj-$(CONFIG_ARCH_HIP04) += hisilicon/
+ obj-$(CONFIG_ARCH_HIX5HD2) += hisilicon/
+ obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/
++obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
+ ifeq ($(CONFIG_COMMON_CLK), y)
+ obj-$(CONFIG_ARCH_MMP) += mmp/
+ endif
+diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
+new file mode 100644
+index 0000000..c384e97
+--- /dev/null
++++ b/drivers/clk/mediatek/Makefile
+@@ -0,0 +1 @@
++obj-y += clk-mtk.o clk-pll.o clk-gate.o
+diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
+new file mode 100644
+index 0000000..9d77ee3
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-gate.c
+@@ -0,0 +1,137 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/of.h>
++#include <linux/of_address.h>
++
++#include <linux/io.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/clkdev.h>
++
++#include "clk-mtk.h"
++#include "clk-gate.h"
++
++static int mtk_cg_bit_is_cleared(struct clk_hw *hw)
++{
++ struct mtk_clk_gate *cg = to_clk_gate(hw);
++ u32 val;
++
++ regmap_read(cg->regmap, cg->sta_ofs, &val);
++
++ val &= BIT(cg->bit);
++
++ return val == 0;
++}
++
++static int mtk_cg_bit_is_set(struct clk_hw *hw)
++{
++ struct mtk_clk_gate *cg = to_clk_gate(hw);
++ u32 val;
++
++ regmap_read(cg->regmap, cg->sta_ofs, &val);
++
++ val &= BIT(cg->bit);
++
++ return val != 0;
++}
++
++static void mtk_cg_set_bit(struct clk_hw *hw)
++{
++ struct mtk_clk_gate *cg = to_clk_gate(hw);
++
++ regmap_write(cg->regmap, cg->set_ofs, BIT(cg->bit));
++}
++
++static void mtk_cg_clr_bit(struct clk_hw *hw)
++{
++ struct mtk_clk_gate *cg = to_clk_gate(hw);
++
++ regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit));
++}
++
++static int mtk_cg_enable(struct clk_hw *hw)
++{
++ mtk_cg_clr_bit(hw);
++
++ return 0;
++}
++
++static void mtk_cg_disable(struct clk_hw *hw)
++{
++ mtk_cg_set_bit(hw);
++}
++
++static int mtk_cg_enable_inv(struct clk_hw *hw)
++{
++ mtk_cg_set_bit(hw);
++
++ return 0;
++}
++
++static void mtk_cg_disable_inv(struct clk_hw *hw)
++{
++ mtk_cg_clr_bit(hw);
++}
++
++const struct clk_ops mtk_clk_gate_ops_setclr = {
++ .is_enabled = mtk_cg_bit_is_cleared,
++ .enable = mtk_cg_enable,
++ .disable = mtk_cg_disable,
++};
++
++const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
++ .is_enabled = mtk_cg_bit_is_set,
++ .enable = mtk_cg_enable_inv,
++ .disable = mtk_cg_disable_inv,
++};
++
++struct clk *mtk_clk_register_gate(
++ const char *name,
++ const char *parent_name,
++ struct regmap *regmap,
++ int set_ofs,
++ int clr_ofs,
++ int sta_ofs,
++ u8 bit,
++ const struct clk_ops *ops)
++{
++ struct mtk_clk_gate *cg;
++ struct clk *clk;
++ struct clk_init_data init;
++
++ cg = kzalloc(sizeof(*cg), GFP_KERNEL);
++ if (!cg)
++ return ERR_PTR(-ENOMEM);
++
++ init.name = name;
++ init.flags = CLK_SET_RATE_PARENT;
++ init.parent_names = parent_name ? &parent_name : NULL;
++ init.num_parents = parent_name ? 1 : 0;
++ init.ops = ops;
++
++ cg->regmap = regmap;
++ cg->set_ofs = set_ofs;
++ cg->clr_ofs = clr_ofs;
++ cg->sta_ofs = sta_ofs;
++ cg->bit = bit;
++
++ cg->hw.init = &init;
++
++ clk = clk_register(NULL, &cg->hw);
++ if (IS_ERR(clk))
++ kfree(cg);
++
++ return clk;
++}
+diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h
+new file mode 100644
+index 0000000..6b6780b
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-gate.h
+@@ -0,0 +1,49 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#ifndef __DRV_CLK_GATE_H
++#define __DRV_CLK_GATE_H
++
++#include <linux/regmap.h>
++#include <linux/clk.h>
++#include <linux/clk-provider.h>
++
++struct mtk_clk_gate {
++ struct clk_hw hw;
++ struct regmap *regmap;
++ int set_ofs;
++ int clr_ofs;
++ int sta_ofs;
++ u8 bit;
++};
++
++static inline struct mtk_clk_gate *to_clk_gate(struct clk_hw *hw)
++{
++ return container_of(hw, struct mtk_clk_gate, hw);
++}
++
++extern const struct clk_ops mtk_clk_gate_ops_setclr;
++extern const struct clk_ops mtk_clk_gate_ops_setclr_inv;
++
++struct clk *mtk_clk_register_gate(
++ const char *name,
++ const char *parent_name,
++ struct regmap *regmap,
++ int set_ofs,
++ int clr_ofs,
++ int sta_ofs,
++ u8 bit,
++ const struct clk_ops *ops);
++
++#endif /* __DRV_CLK_GATE_H */
+diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
+new file mode 100644
+index 0000000..18444ae
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-mtk.c
+@@ -0,0 +1,220 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/of.h>
++#include <linux/of_address.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/clkdev.h>
++#include <linux/mfd/syscon.h>
++
++#include "clk-mtk.h"
++#include "clk-gate.h"
++
++struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num)
++{
++ int i;
++ struct clk_onecell_data *clk_data;
++
++ clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
++ if (!clk_data)
++ return NULL;
++
++ clk_data->clks = kcalloc(clk_num, sizeof(*clk_data->clks), GFP_KERNEL);
++ if (!clk_data->clks)
++ goto err_out;
++
++ clk_data->clk_num = clk_num;
++
++ for (i = 0; i < clk_num; i++)
++ clk_data->clks[i] = ERR_PTR(-ENOENT);
++
++ return clk_data;
++err_out:
++ kfree(clk_data);
++
++ return NULL;
++}
++
++void mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num,
++ struct clk_onecell_data *clk_data)
++{
++ int i;
++ struct clk *clk;
++
++ for (i = 0; i < num; i++) {
++ const struct mtk_fixed_factor *ff = &clks[i];
++
++ clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name,
++ CLK_SET_RATE_PARENT, ff->mult, ff->div);
++
++ if (IS_ERR(clk)) {
++ pr_err("Failed to register clk %s: %ld\n",
++ ff->name, PTR_ERR(clk));
++ continue;
++ }
++
++ if (clk_data)
++ clk_data->clks[ff->id] = clk;
++ }
++}
++
++int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
++ int num, struct clk_onecell_data *clk_data)
++{
++ int i;
++ struct clk *clk;
++ struct regmap *regmap;
++
++ if (!clk_data)
++ return -ENOMEM;
++
++ regmap = syscon_node_to_regmap(node);
++ if (IS_ERR(regmap)) {
++ pr_err("Cannot find regmap for %s: %ld\n", node->full_name,
++ PTR_ERR(regmap));
++ return PTR_ERR(regmap);
++ }
++
++ for (i = 0; i < num; i++) {
++ const struct mtk_gate *gate = &clks[i];
++
++ clk = mtk_clk_register_gate(gate->name, gate->parent_name,
++ regmap,
++ gate->regs->set_ofs,
++ gate->regs->clr_ofs,
++ gate->regs->sta_ofs,
++ gate->shift, gate->ops);
++
++ if (IS_ERR(clk)) {
++ pr_err("Failed to register clk %s: %ld\n",
++ gate->name, PTR_ERR(clk));
++ continue;
++ }
++
++ clk_data->clks[gate->id] = clk;
++ }
++
++ return 0;
++}
++
++struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
++ void __iomem *base, spinlock_t *lock)
++{
++ struct clk *clk;
++ struct clk_mux *mux = NULL;
++ struct clk_gate *gate = NULL;
++ struct clk_divider *div = NULL;
++ struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL;
++ const struct clk_ops *mux_ops = NULL, *gate_ops = NULL, *div_ops = NULL;
++ const char * const *parent_names;
++ const char *parent;
++ int num_parents;
++ int ret;
++
++ if (mc->mux_shift >= 0) {
++ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
++ if (!mux)
++ return ERR_PTR(-ENOMEM);
++
++ mux->reg = base + mc->mux_reg;
++ mux->mask = BIT(mc->mux_width) - 1;
++ mux->shift = mc->mux_shift;
++ mux->lock = lock;
++
++ mux_hw = &mux->hw;
++ mux_ops = &clk_mux_ops;
++
++ parent_names = mc->parent_names;
++ num_parents = mc->num_parents;
++ } else {
++ parent = mc->parent;
++ parent_names = &parent;
++ num_parents = 1;
++ }
++
++ if (mc->gate_shift >= 0) {
++ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
++ if (!gate) {
++ ret = -ENOMEM;
++ goto err_out;
++ }
++
++ gate->reg = base + mc->gate_reg;
++ gate->bit_idx = mc->gate_shift;
++ gate->flags = CLK_GATE_SET_TO_DISABLE;
++ gate->lock = lock;
++
++ gate_hw = &gate->hw;
++ gate_ops = &clk_gate_ops;
++ }
++
++ if (mc->divider_shift >= 0) {
++ div = kzalloc(sizeof(*div), GFP_KERNEL);
++ if (!div) {
++ ret = -ENOMEM;
++ goto err_out;
++ }
++
++ div->reg = base + mc->divider_reg;
++ div->shift = mc->divider_shift;
++ div->width = mc->divider_width;
++ div->lock = lock;
++
++ div_hw = &div->hw;
++ div_ops = &clk_divider_ops;
++ }
++
++ clk = clk_register_composite(NULL, mc->name, parent_names, num_parents,
++ mux_hw, mux_ops,
++ div_hw, div_ops,
++ gate_hw, gate_ops,
++ mc->flags);
++
++ if (IS_ERR(clk)) {
++ kfree(gate);
++ kfree(mux);
++ }
++
++ return clk;
++err_out:
++ kfree(mux);
++
++ return ERR_PTR(ret);
++}
++
++void mtk_clk_register_composites(const struct mtk_composite *mcs,
++ int num, void __iomem *base, spinlock_t *lock,
++ struct clk_onecell_data *clk_data)
++{
++ struct clk *clk;
++ int i;
++
++ for (i = 0; i < num; i++) {
++ const struct mtk_composite *mc = &mcs[i];
++
++ clk = mtk_clk_register_composite(mc, base, lock);
++
++ if (IS_ERR(clk)) {
++ pr_err("Failed to register clk %s: %ld\n",
++ mc->name, PTR_ERR(clk));
++ continue;
++ }
++
++ if (clk_data)
++ clk_data->clks[mc->id] = clk;
++ }
++}
+diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
+new file mode 100644
+index 0000000..694fc39
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-mtk.h
+@@ -0,0 +1,159 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#ifndef __DRV_CLK_MTK_H
++#define __DRV_CLK_MTK_H
++
++#include <linux/regmap.h>
++#include <linux/bitops.h>
++#include <linux/clk.h>
++#include <linux/clk-provider.h>
++
++#define MAX_MUX_GATE_BIT 31
++#define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1)
++
++#define MHZ (1000 * 1000)
++
++struct mtk_fixed_factor {
++ int id;
++ const char *name;
++ const char *parent_name;
++ int mult;
++ int div;
++};
++
++#define FACTOR(_id, _name, _parent, _mult, _div) { \
++ .id = _id, \
++ .name = _name, \
++ .parent_name = _parent, \
++ .mult = _mult, \
++ .div = _div, \
++ }
++
++extern void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
++ int num, struct clk_onecell_data *clk_data);
++
++struct mtk_composite {
++ int id;
++ const char *name;
++ const char * const * parent_names;
++ const char *parent;
++ unsigned flags;
++
++ uint32_t mux_reg;
++ uint32_t divider_reg;
++ uint32_t gate_reg;
++
++ signed char mux_shift;
++ signed char mux_width;
++ signed char gate_shift;
++
++ signed char divider_shift;
++ signed char divider_width;
++
++ signed char num_parents;
++};
++
++#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) { \
++ .id = _id, \
++ .name = _name, \
++ .mux_reg = _reg, \
++ .mux_shift = _shift, \
++ .mux_width = _width, \
++ .gate_reg = _reg, \
++ .gate_shift = _gate, \
++ .divider_shift = -1, \
++ .parent_names = _parents, \
++ .num_parents = ARRAY_SIZE(_parents), \
++ .flags = CLK_SET_RATE_PARENT, \
++ }
++
++#define MUX(_id, _name, _parents, _reg, _shift, _width) { \
++ .id = _id, \
++ .name = _name, \
++ .mux_reg = _reg, \
++ .mux_shift = _shift, \
++ .mux_width = _width, \
++ .gate_shift = -1, \
++ .divider_shift = -1, \
++ .parent_names = _parents, \
++ .num_parents = ARRAY_SIZE(_parents), \
++ .flags = CLK_SET_RATE_PARENT, \
++ }
++
++#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, _div_width, _div_shift) { \
++ .id = _id, \
++ .parent = _parent, \
++ .name = _name, \
++ .divider_reg = _div_reg, \
++ .divider_shift = _div_shift, \
++ .divider_width = _div_width, \
++ .gate_reg = _gate_reg, \
++ .gate_shift = _gate_shift, \
++ .mux_shift = -1, \
++ .flags = 0, \
++ }
++
++struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
++ void __iomem *base, spinlock_t *lock);
++
++void mtk_clk_register_composites(const struct mtk_composite *mcs,
++ int num, void __iomem *base, spinlock_t *lock,
++ struct clk_onecell_data *clk_data);
++
++struct mtk_gate_regs {
++ u32 sta_ofs;
++ u32 clr_ofs;
++ u32 set_ofs;
++};
++
++struct mtk_gate {
++ int id;
++ const char *name;
++ const char *parent_name;
++ const struct mtk_gate_regs *regs;
++ int shift;
++ const struct clk_ops *ops;
++};
++
++int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
++ int num, struct clk_onecell_data *clk_data);
++
++struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
++
++#define HAVE_RST_BAR BIT(0)
++
++struct mtk_pll_data {
++ int id;
++ const char *name;
++ uint32_t reg;
++ uint32_t pwr_reg;
++ uint32_t en_mask;
++ uint32_t pd_reg;
++ uint32_t tuner_reg;
++ int pd_shift;
++ unsigned int flags;
++ const struct clk_ops *ops;
++ u32 rst_bar_mask;
++ unsigned long fmax;
++ int pcwbits;
++ uint32_t pcw_reg;
++ int pcw_shift;
++};
++
++void __init mtk_clk_register_plls(struct device_node *node,
++ const struct mtk_pll_data *plls, int num_plls,
++ struct clk_onecell_data *clk_data);
++
++#endif /* __DRV_CLK_MTK_H */
+diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
+new file mode 100644
+index 0000000..66154ca
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-pll.c
+@@ -0,0 +1,332 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/of.h>
++#include <linux/of_address.h>
++#include <linux/io.h>
++#include <linux/slab.h>
++#include <linux/clkdev.h>
++#include <linux/delay.h>
++
++#include "clk-mtk.h"
++
++#define REG_CON0 0
++#define REG_CON1 4
++
++#define CON0_BASE_EN BIT(0)
++#define CON0_PWR_ON BIT(0)
++#define CON0_ISO_EN BIT(1)
++#define CON0_PCW_CHG BIT(31)
++
++#define AUDPLL_TUNER_EN BIT(31)
++
++#define POSTDIV_MASK 0x7
++#define INTEGER_BITS 7
++
++/*
++ * MediaTek PLLs are configured through their pcw value. The pcw value describes
++ * a divider in the PLL feedback loop which consists of 7 bits for the integer
++ * part and the remaining bits (if present) for the fractional part. Also they
++ * have a 3 bit power-of-two post divider.
++ */
++
++struct mtk_clk_pll {
++ struct clk_hw hw;
++ void __iomem *base_addr;
++ void __iomem *pd_addr;
++ void __iomem *pwr_addr;
++ void __iomem *tuner_addr;
++ void __iomem *pcw_addr;
++ const struct mtk_pll_data *data;
++};
++
++static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw)
++{
++ return container_of(hw, struct mtk_clk_pll, hw);
++}
++
++static int mtk_pll_is_prepared(struct clk_hw *hw)
++{
++ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
++
++ return (readl(pll->base_addr + REG_CON0) & CON0_BASE_EN) != 0;
++}
++
++static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin,
++ u32 pcw, int postdiv)
++{
++ int pcwbits = pll->data->pcwbits;
++ int pcwfbits;
++ u64 vco;
++ u8 c = 0;
++
++ /* The fractional part of the PLL divider. */
++ pcwfbits = pcwbits > INTEGER_BITS ? pcwbits - INTEGER_BITS : 0;
++
++ vco = (u64)fin * pcw;
++
++ if (pcwfbits && (vco & GENMASK(pcwfbits - 1, 0)))
++ c = 1;
++
++ vco >>= pcwfbits;
++
++ if (c)
++ vco++;
++
++ return ((unsigned long)vco + postdiv - 1) / postdiv;
++}
++
++static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
++ int postdiv)
++{
++ u32 con1, pd, val;
++ int pll_en;
++
++ /* set postdiv */
++ pd = readl(pll->pd_addr);
++ pd &= ~(POSTDIV_MASK << pll->data->pd_shift);
++ pd |= (ffs(postdiv) - 1) << pll->data->pd_shift;
++ writel(pd, pll->pd_addr);
++
++ pll_en = readl(pll->base_addr + REG_CON0) & CON0_BASE_EN;
++
++ /* set pcw */
++ val = readl(pll->pcw_addr);
++
++ val &= ~GENMASK(pll->data->pcw_shift + pll->data->pcwbits - 1,
++ pll->data->pcw_shift);
++ val |= pcw << pll->data->pcw_shift;
++ writel(val, pll->pcw_addr);
++
++ con1 = readl(pll->base_addr + REG_CON1);
++
++ if (pll_en)
++ con1 |= CON0_PCW_CHG;
++
++ writel(con1, pll->base_addr + REG_CON1);
++ if (pll->tuner_addr)
++ writel(con1 + 1, pll->tuner_addr);
++
++ if (pll_en)
++ udelay(20);
++}
++
++/*
++ * mtk_pll_calc_values - calculate good values for a given input frequency.
++ * @pll: The pll
++ * @pcw: The pcw value (output)
++ * @postdiv: The post divider (output)
++ * @freq: The desired target frequency
++ * @fin: The input frequency
++ *
++ */
++static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
++ u32 freq, u32 fin)
++{
++ unsigned long fmin = 1000 * MHZ;
++ u64 _pcw;
++ u32 val;
++
++ if (freq > pll->data->fmax)
++ freq = pll->data->fmax;
++
++ for (val = 0; val < 4; val++) {
++ *postdiv = 1 << val;
++ if (freq * *postdiv >= fmin)
++ break;
++ }
++
++ /* _pcw = freq * postdiv / fin * 2^pcwfbits */
++ _pcw = ((u64)freq << val) << (pll->data->pcwbits - INTEGER_BITS);
++ do_div(_pcw, fin);
++
++ *pcw = (u32)_pcw;
++}
++
++static int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
++ unsigned long parent_rate)
++{
++ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
++ u32 pcw = 0;
++ u32 postdiv;
++
++ mtk_pll_calc_values(pll, &pcw, &postdiv, rate, parent_rate);
++ mtk_pll_set_rate_regs(pll, pcw, postdiv);
++
++ return 0;
++}
++
++static unsigned long mtk_pll_recalc_rate(struct clk_hw *hw,
++ unsigned long parent_rate)
++{
++ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
++ u32 postdiv;
++ u32 pcw;
++
++ postdiv = (readl(pll->pd_addr) >> pll->data->pd_shift) & POSTDIV_MASK;
++ postdiv = 1 << postdiv;
++
++ pcw = readl(pll->pcw_addr) >> pll->data->pcw_shift;
++ pcw &= GENMASK(pll->data->pcwbits - 1, 0);
++
++ return __mtk_pll_recalc_rate(pll, parent_rate, pcw, postdiv);
++}
++
++static long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
++ unsigned long *prate)
++{
++ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
++ u32 pcw = 0;
++ int postdiv;
++
++ mtk_pll_calc_values(pll, &pcw, &postdiv, rate, *prate);
++
++ return __mtk_pll_recalc_rate(pll, *prate, pcw, postdiv);
++}
++
++static int mtk_pll_prepare(struct clk_hw *hw)
++{
++ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
++ u32 r;
++
++ r = readl(pll->pwr_addr) | CON0_PWR_ON;
++ writel(r, pll->pwr_addr);
++ udelay(1);
++
++ r = readl(pll->pwr_addr) & ~CON0_ISO_EN;
++ writel(r, pll->pwr_addr);
++ udelay(1);
++
++ r = readl(pll->base_addr + REG_CON0);
++ r |= pll->data->en_mask;
++ writel(r, pll->base_addr + REG_CON0);
++
++ if (pll->tuner_addr) {
++ r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN;
++ writel(r, pll->tuner_addr);
++ }
++
++ udelay(20);
++
++ if (pll->data->flags & HAVE_RST_BAR) {
++ r = readl(pll->base_addr + REG_CON0);
++ r |= pll->data->rst_bar_mask;
++ writel(r, pll->base_addr + REG_CON0);
++ }
++
++ return 0;
++}
++
++static void mtk_pll_unprepare(struct clk_hw *hw)
++{
++ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
++ u32 r;
++
++ if (pll->data->flags & HAVE_RST_BAR) {
++ r = readl(pll->base_addr + REG_CON0);
++ r &= ~pll->data->rst_bar_mask;
++ writel(r, pll->base_addr + REG_CON0);
++ }
++
++ if (pll->tuner_addr) {
++ r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN;
++ writel(r, pll->tuner_addr);
++ }
++
++ r = readl(pll->base_addr + REG_CON0);
++ r &= ~CON0_BASE_EN;
++ writel(r, pll->base_addr + REG_CON0);
++
++ r = readl(pll->pwr_addr) | CON0_ISO_EN;
++ writel(r, pll->pwr_addr);
++
++ r = readl(pll->pwr_addr) & ~CON0_PWR_ON;
++ writel(r, pll->pwr_addr);
++}
++
++static const struct clk_ops mtk_pll_ops = {
++ .is_prepared = mtk_pll_is_prepared,
++ .prepare = mtk_pll_prepare,
++ .unprepare = mtk_pll_unprepare,
++ .recalc_rate = mtk_pll_recalc_rate,
++ .round_rate = mtk_pll_round_rate,
++ .set_rate = mtk_pll_set_rate,
++};
++
++static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
++ void __iomem *base)
++{
++ struct mtk_clk_pll *pll;
++ struct clk_init_data init;
++ struct clk *clk;
++ const char *parent_name = "clk26m";
++
++ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
++ if (!pll)
++ return ERR_PTR(-ENOMEM);
++
++ pll->base_addr = base + data->reg;
++ pll->pwr_addr = base + data->pwr_reg;
++ pll->pd_addr = base + data->pd_reg;
++ pll->pcw_addr = base + data->pcw_reg;
++ if (data->tuner_reg)
++ pll->tuner_addr = base + data->tuner_reg;
++ pll->hw.init = &init;
++ pll->data = data;
++
++ init.name = data->name;
++ init.ops = &mtk_pll_ops;
++ init.parent_names = &parent_name;
++ init.num_parents = 1;
++
++ clk = clk_register(NULL, &pll->hw);
++
++ if (IS_ERR(clk))
++ kfree(pll);
++
++ return clk;
++}
++
++void __init mtk_clk_register_plls(struct device_node *node,
++ const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data)
++{
++ void __iomem *base;
++ int r, i;
++ struct clk *clk;
++
++ base = of_iomap(node, 0);
++ if (!base) {
++ pr_err("%s(): ioremap failed\n", __func__);
++ return;
++ }
++
++ for (i = 0; i < num_plls; i++) {
++ const struct mtk_pll_data *pll = &plls[i];
++
++ clk = mtk_clk_register_pll(pll, base);
++
++ if (IS_ERR(clk)) {
++ pr_err("Failed to register clk %s: %ld\n",
++ pll->name, PTR_ERR(clk));
++ continue;
++ }
++
++ clk_data->clks[pll->id] = clk;
++ }
++
++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++ if (r)
++ pr_err("%s(): could not register clock provider: %d\n",
++ __func__, r);
++}
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0003-clk-mediatek-Add-reset-controller-support.patch b/target/linux/mediatek/patches/0003-clk-mediatek-Add-reset-controller-support.patch
new file mode 100644
index 0000000000..bb6f64b9b2
--- /dev/null
+++ b/target/linux/mediatek/patches/0003-clk-mediatek-Add-reset-controller-support.patch
@@ -0,0 +1,155 @@
+From c91e8490e45c68ea517f70f24568034b7735e8b9 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Thu, 23 Apr 2015 10:35:40 +0200
+Subject: [PATCH 03/76] clk: mediatek: Add reset controller support
+
+The pericfg and infracfg units also provide reset lines to several
+other SoC internal units. This adds a function which can be called
+from the pericfg and infracfg initialization functions which will
+register the reset controller using reset_controller_register. The
+reset controller will provide support for resetting the units
+connected to the pericfg and infracfg controller. The units resetted
+by this controller can use the standard reset device tree binding
+to gain access to the reset lines.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
+---
+ drivers/clk/mediatek/Makefile | 1 +
+ drivers/clk/mediatek/clk-mtk.h | 10 +++++
+ drivers/clk/mediatek/reset.c | 97 ++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 108 insertions(+)
+ create mode 100644 drivers/clk/mediatek/reset.c
+
+diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
+index c384e97..0b6f1c3 100644
+--- a/drivers/clk/mediatek/Makefile
++++ b/drivers/clk/mediatek/Makefile
+@@ -1 +1,2 @@
+ obj-y += clk-mtk.o clk-pll.o clk-gate.o
++obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
+index 694fc39..61035b9 100644
+--- a/drivers/clk/mediatek/clk-mtk.h
++++ b/drivers/clk/mediatek/clk-mtk.h
+@@ -156,4 +156,14 @@ void __init mtk_clk_register_plls(struct device_node *node,
+ const struct mtk_pll_data *plls, int num_plls,
+ struct clk_onecell_data *clk_data);
+
++#ifdef CONFIG_RESET_CONTROLLER
++void mtk_register_reset_controller(struct device_node *np,
++ unsigned int num_regs, int regofs);
++#else
++static inline void mtk_register_reset_controller(struct device_node *np,
++ unsigned int num_regs, int regofs)
++{
++}
++#endif
++
+ #endif /* __DRV_CLK_MTK_H */
+diff --git a/drivers/clk/mediatek/reset.c b/drivers/clk/mediatek/reset.c
+new file mode 100644
+index 0000000..9e9fe4b
+--- /dev/null
++++ b/drivers/clk/mediatek/reset.c
+@@ -0,0 +1,97 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/mfd/syscon.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++#include <linux/regmap.h>
++#include <linux/reset-controller.h>
++#include <linux/slab.h>
++
++#include "clk-mtk.h"
++
++struct mtk_reset {
++ struct regmap *regmap;
++ int regofs;
++ struct reset_controller_dev rcdev;
++};
++
++static int mtk_reset_assert(struct reset_controller_dev *rcdev,
++ unsigned long id)
++{
++ struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
++
++ return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
++ BIT(id % 32), ~0);
++}
++
++static int mtk_reset_deassert(struct reset_controller_dev *rcdev,
++ unsigned long id)
++{
++ struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
++
++ return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
++ BIT(id % 32), 0);
++}
++
++static int mtk_reset(struct reset_controller_dev *rcdev,
++ unsigned long id)
++{
++ int ret;
++
++ ret = mtk_reset_assert(rcdev, id);
++ if (ret)
++ return ret;
++
++ return mtk_reset_deassert(rcdev, id);
++}
++
++static struct reset_control_ops mtk_reset_ops = {
++ .assert = mtk_reset_assert,
++ .deassert = mtk_reset_deassert,
++ .reset = mtk_reset,
++};
++
++void mtk_register_reset_controller(struct device_node *np,
++ unsigned int num_regs, int regofs)
++{
++ struct mtk_reset *data;
++ int ret;
++ struct regmap *regmap;
++
++ regmap = syscon_node_to_regmap(np);
++ if (IS_ERR(regmap)) {
++ pr_err("Cannot find regmap for %s: %ld\n", np->full_name,
++ PTR_ERR(regmap));
++ return;
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return;
++
++ data->regmap = regmap;
++ data->regofs = regofs;
++ data->rcdev.owner = THIS_MODULE;
++ data->rcdev.nr_resets = num_regs * 32;
++ data->rcdev.ops = &mtk_reset_ops;
++ data->rcdev.of_node = np;
++
++ ret = reset_controller_register(&data->rcdev);
++ if (ret) {
++ pr_err("could not register reset controller: %d\n", ret);
++ kfree(data);
++ return;
++ }
++}
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0004-clk-mediatek-Add-basic-clocks-for-Mediatek-MT8135.patch b/target/linux/mediatek/patches/0004-clk-mediatek-Add-basic-clocks-for-Mediatek-MT8135.patch
new file mode 100644
index 0000000000..8666128ddc
--- /dev/null
+++ b/target/linux/mediatek/patches/0004-clk-mediatek-Add-basic-clocks-for-Mediatek-MT8135.patch
@@ -0,0 +1,952 @@
+From 242572135fdb513cba0506415c7e26a0909eb4b5 Mon Sep 17 00:00:00 2001
+From: James Liao <jamesjj.liao@mediatek.com>
+Date: Thu, 23 Apr 2015 10:35:41 +0200
+Subject: [PATCH 04/76] clk: mediatek: Add basic clocks for Mediatek MT8135.
+
+This patch adds basic clocks for MT8135, including TOPCKGEN, PLLs,
+INFRA and PERI clocks.
+
+Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
+Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/clk/mediatek/Makefile | 1 +
+ drivers/clk/mediatek/clk-mt8135.c | 644 ++++++++++++++++++++
+ include/dt-bindings/clock/mt8135-clk.h | 194 ++++++
+ .../dt-bindings/reset-controller/mt8135-resets.h | 64 ++
+ 4 files changed, 903 insertions(+)
+ create mode 100644 drivers/clk/mediatek/clk-mt8135.c
+ create mode 100644 include/dt-bindings/clock/mt8135-clk.h
+ create mode 100644 include/dt-bindings/reset-controller/mt8135-resets.h
+
+diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
+index 0b6f1c3..12ce576 100644
+--- a/drivers/clk/mediatek/Makefile
++++ b/drivers/clk/mediatek/Makefile
+@@ -1,2 +1,3 @@
+ obj-y += clk-mtk.o clk-pll.o clk-gate.o
+ obj-$(CONFIG_RESET_CONTROLLER) += reset.o
++obj-y += clk-mt8135.o
+diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c
+new file mode 100644
+index 0000000..a63435b
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-mt8135.c
+@@ -0,0 +1,644 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/of.h>
++#include <linux/of_address.h>
++#include <linux/slab.h>
++#include <linux/mfd/syscon.h>
++#include <dt-bindings/clock/mt8135-clk.h>
++
++#include "clk-mtk.h"
++#include "clk-gate.h"
++
++static DEFINE_SPINLOCK(mt8135_clk_lock);
++
++static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
++ FACTOR(CLK_TOP_DSI0_LNTC_DSICLK, "dsi0_lntc_dsiclk", "clk_null", 1, 1),
++ FACTOR(CLK_TOP_HDMITX_CLKDIG_CTS, "hdmitx_clkdig_cts", "clk_null", 1, 1),
++ FACTOR(CLK_TOP_CLKPH_MCK, "clkph_mck", "clk_null", 1, 1),
++ FACTOR(CLK_TOP_CPUM_TCK_IN, "cpum_tck_in", "clk_null", 1, 1),
++};
++
++static const struct mtk_fixed_factor top_divs[] __initconst = {
++ FACTOR(CLK_TOP_MAINPLL_806M, "mainpll_806m", "mainpll", 1, 2),
++ FACTOR(CLK_TOP_MAINPLL_537P3M, "mainpll_537p3m", "mainpll", 1, 3),
++ FACTOR(CLK_TOP_MAINPLL_322P4M, "mainpll_322p4m", "mainpll", 1, 5),
++ FACTOR(CLK_TOP_MAINPLL_230P3M, "mainpll_230p3m", "mainpll", 1, 7),
++
++ FACTOR(CLK_TOP_UNIVPLL_624M, "univpll_624m", "univpll", 1, 2),
++ FACTOR(CLK_TOP_UNIVPLL_416M, "univpll_416m", "univpll", 1, 3),
++ FACTOR(CLK_TOP_UNIVPLL_249P6M, "univpll_249p6m", "univpll", 1, 5),
++ FACTOR(CLK_TOP_UNIVPLL_178P3M, "univpll_178p3m", "univpll", 1, 7),
++ FACTOR(CLK_TOP_UNIVPLL_48M, "univpll_48m", "univpll", 1, 26),
++
++ FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
++ FACTOR(CLK_TOP_MMPLL_D3, "mmpll_d3", "mmpll", 1, 3),
++ FACTOR(CLK_TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5),
++ FACTOR(CLK_TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7),
++ FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll_d2", 1, 2),
++ FACTOR(CLK_TOP_MMPLL_D6, "mmpll_d6", "mmpll_d3", 1, 2),
++
++ FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll_806m", 1, 1),
++ FACTOR(CLK_TOP_SYSPLL_D4, "syspll_d4", "mainpll_806m", 1, 2),
++ FACTOR(CLK_TOP_SYSPLL_D6, "syspll_d6", "mainpll_806m", 1, 3),
++ FACTOR(CLK_TOP_SYSPLL_D8, "syspll_d8", "mainpll_806m", 1, 4),
++ FACTOR(CLK_TOP_SYSPLL_D10, "syspll_d10", "mainpll_806m", 1, 5),
++ FACTOR(CLK_TOP_SYSPLL_D12, "syspll_d12", "mainpll_806m", 1, 6),
++ FACTOR(CLK_TOP_SYSPLL_D16, "syspll_d16", "mainpll_806m", 1, 8),
++ FACTOR(CLK_TOP_SYSPLL_D24, "syspll_d24", "mainpll_806m", 1, 12),
++
++ FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll_537p3m", 1, 1),
++
++ FACTOR(CLK_TOP_SYSPLL_D2P5, "syspll_d2p5", "mainpll_322p4m", 2, 1),
++ FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll_322p4m", 1, 1),
++
++ FACTOR(CLK_TOP_SYSPLL_D3P5, "syspll_d3p5", "mainpll_230p3m", 2, 1),
++
++ FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_624m", 1, 2),
++ FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_624m", 1, 4),
++ FACTOR(CLK_TOP_UNIVPLL1_D6, "univpll1_d6", "univpll_624m", 1, 6),
++ FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_624m", 1, 8),
++ FACTOR(CLK_TOP_UNIVPLL1_D10, "univpll1_d10", "univpll_624m", 1, 10),
++
++ FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_416m", 1, 2),
++ FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_416m", 1, 4),
++ FACTOR(CLK_TOP_UNIVPLL2_D6, "univpll2_d6", "univpll_416m", 1, 6),
++ FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_416m", 1, 8),
++
++ FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll_416m", 1, 1),
++ FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll_249p6m", 1, 1),
++ FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll_178p3m", 1, 1),
++ FACTOR(CLK_TOP_UNIVPLL_D10, "univpll_d10", "univpll_249p6m", 1, 2),
++ FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll_48m", 1, 1),
++
++ FACTOR(CLK_TOP_APLL, "apll_ck", "audpll", 1, 1),
++ FACTOR(CLK_TOP_APLL_D4, "apll_d4", "audpll", 1, 4),
++ FACTOR(CLK_TOP_APLL_D8, "apll_d8", "audpll", 1, 8),
++ FACTOR(CLK_TOP_APLL_D16, "apll_d16", "audpll", 1, 16),
++ FACTOR(CLK_TOP_APLL_D24, "apll_d24", "audpll", 1, 24),
++
++ FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
++ FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
++ FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
++
++ FACTOR(CLK_TOP_LVDSTX_CLKDIG_CT, "lvdstx_clkdig_cts", "lvdspll", 1, 1),
++ FACTOR(CLK_TOP_VPLL_DPIX, "vpll_dpix_ck", "lvdspll", 1, 1),
++
++ FACTOR(CLK_TOP_TVHDMI_H, "tvhdmi_h_ck", "tvdpll", 1, 1),
++
++ FACTOR(CLK_TOP_HDMITX_CLKDIG_D2, "hdmitx_clkdig_d2", "hdmitx_clkdig_cts", 1, 2),
++ FACTOR(CLK_TOP_HDMITX_CLKDIG_D3, "hdmitx_clkdig_d3", "hdmitx_clkdig_cts", 1, 3),
++
++ FACTOR(CLK_TOP_TVHDMI_D2, "tvhdmi_d2", "tvhdmi_h_ck", 1, 2),
++ FACTOR(CLK_TOP_TVHDMI_D4, "tvhdmi_d4", "tvhdmi_h_ck", 1, 4),
++
++ FACTOR(CLK_TOP_MEMPLL_MCK_D4, "mempll_mck_d4", "clkph_mck", 1, 4),
++};
++
++static const char * const axi_parents[] __initconst = {
++ "clk26m",
++ "syspll_d3",
++ "syspll_d4",
++ "syspll_d6",
++ "univpll_d5",
++ "univpll2_d2",
++ "syspll_d3p5"
++};
++
++static const char * const smi_parents[] __initconst = {
++ "clk26m",
++ "clkph_mck",
++ "syspll_d2p5",
++ "syspll_d3",
++ "syspll_d8",
++ "univpll_d5",
++ "univpll1_d2",
++ "univpll1_d6",
++ "mmpll_d3",
++ "mmpll_d4",
++ "mmpll_d5",
++ "mmpll_d6",
++ "mmpll_d7",
++ "vdecpll",
++ "lvdspll"
++};
++
++static const char * const mfg_parents[] __initconst = {
++ "clk26m",
++ "univpll1_d4",
++ "syspll_d2",
++ "syspll_d2p5",
++ "syspll_d3",
++ "univpll_d5",
++ "univpll1_d2",
++ "mmpll_d2",
++ "mmpll_d3",
++ "mmpll_d4",
++ "mmpll_d5",
++ "mmpll_d6",
++ "mmpll_d7"
++};
++
++static const char * const irda_parents[] __initconst = {
++ "clk26m",
++ "univpll2_d8",
++ "univpll1_d6"
++};
++
++static const char * const cam_parents[] __initconst = {
++ "clk26m",
++ "syspll_d3",
++ "syspll_d3p5",
++ "syspll_d4",
++ "univpll_d5",
++ "univpll2_d2",
++ "univpll_d7",
++ "univpll1_d4"
++};
++
++static const char * const aud_intbus_parents[] __initconst = {
++ "clk26m",
++ "syspll_d6",
++ "univpll_d10"
++};
++
++static const char * const jpg_parents[] __initconst = {
++ "clk26m",
++ "syspll_d5",
++ "syspll_d4",
++ "syspll_d3",
++ "univpll_d7",
++ "univpll2_d2",
++ "univpll_d5"
++};
++
++static const char * const disp_parents[] __initconst = {
++ "clk26m",
++ "syspll_d3p5",
++ "syspll_d3",
++ "univpll2_d2",
++ "univpll_d5",
++ "univpll1_d2",
++ "lvdspll",
++ "vdecpll"
++};
++
++static const char * const msdc30_parents[] __initconst = {
++ "clk26m",
++ "syspll_d6",
++ "syspll_d5",
++ "univpll1_d4",
++ "univpll2_d4",
++ "msdcpll"
++};
++
++static const char * const usb20_parents[] __initconst = {
++ "clk26m",
++ "univpll2_d6",
++ "univpll1_d10"
++};
++
++static const char * const venc_parents[] __initconst = {
++ "clk26m",
++ "syspll_d3",
++ "syspll_d8",
++ "univpll_d5",
++ "univpll1_d6",
++ "mmpll_d4",
++ "mmpll_d5",
++ "mmpll_d6"
++};
++
++static const char * const spi_parents[] __initconst = {
++ "clk26m",
++ "syspll_d6",
++ "syspll_d8",
++ "syspll_d10",
++ "univpll1_d6",
++ "univpll1_d8"
++};
++
++static const char * const uart_parents[] __initconst = {
++ "clk26m",
++ "univpll2_d8"
++};
++
++static const char * const mem_parents[] __initconst = {
++ "clk26m",
++ "clkph_mck"
++};
++
++static const char * const camtg_parents[] __initconst = {
++ "clk26m",
++ "univpll_d26",
++ "univpll1_d6",
++ "syspll_d16",
++ "syspll_d8"
++};
++
++static const char * const audio_parents[] __initconst = {
++ "clk26m",
++ "syspll_d24"
++};
++
++static const char * const fix_parents[] __initconst = {
++ "rtc32k",
++ "clk26m",
++ "univpll_d5",
++ "univpll_d7",
++ "univpll1_d2",
++ "univpll1_d4",
++ "univpll1_d6",
++ "univpll1_d8"
++};
++
++static const char * const vdec_parents[] __initconst = {
++ "clk26m",
++ "vdecpll",
++ "clkph_mck",
++ "syspll_d2p5",
++ "syspll_d3",
++ "syspll_d3p5",
++ "syspll_d4",
++ "syspll_d5",
++ "syspll_d6",
++ "syspll_d8",
++ "univpll1_d2",
++ "univpll2_d2",
++ "univpll_d7",
++ "univpll_d10",
++ "univpll2_d4",
++ "lvdspll"
++};
++
++static const char * const ddrphycfg_parents[] __initconst = {
++ "clk26m",
++ "axi_sel",
++ "syspll_d12"
++};
++
++static const char * const dpilvds_parents[] __initconst = {
++ "clk26m",
++ "lvdspll",
++ "lvdspll_d2",
++ "lvdspll_d4",
++ "lvdspll_d8"
++};
++
++static const char * const pmicspi_parents[] __initconst = {
++ "clk26m",
++ "univpll2_d6",
++ "syspll_d8",
++ "syspll_d10",
++ "univpll1_d10",
++ "mempll_mck_d4",
++ "univpll_d26",
++ "syspll_d24"
++};
++
++static const char * const smi_mfg_as_parents[] __initconst = {
++ "clk26m",
++ "smi_sel",
++ "mfg_sel",
++ "mem_sel"
++};
++
++static const char * const gcpu_parents[] __initconst = {
++ "clk26m",
++ "syspll_d4",
++ "univpll_d7",
++ "syspll_d5",
++ "syspll_d6"
++};
++
++static const char * const dpi1_parents[] __initconst = {
++ "clk26m",
++ "tvhdmi_h_ck",
++ "tvhdmi_d2",
++ "tvhdmi_d4"
++};
++
++static const char * const cci_parents[] __initconst = {
++ "clk26m",
++ "mainpll_537p3m",
++ "univpll_d3",
++ "syspll_d2p5",
++ "syspll_d3",
++ "syspll_d5"
++};
++
++static const char * const apll_parents[] __initconst = {
++ "clk26m",
++ "apll_ck",
++ "apll_d4",
++ "apll_d8",
++ "apll_d16",
++ "apll_d24"
++};
++
++static const char * const hdmipll_parents[] __initconst = {
++ "clk26m",
++ "hdmitx_clkdig_cts",
++ "hdmitx_clkdig_d2",
++ "hdmitx_clkdig_d3"
++};
++
++static const struct mtk_composite top_muxes[] __initconst = {
++ /* CLK_CFG_0 */
++ MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
++ 0x0140, 0, 3, INVALID_MUX_GATE_BIT),
++ MUX_GATE(CLK_TOP_SMI_SEL, "smi_sel", smi_parents, 0x0140, 8, 4, 15),
++ MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0140, 16, 4, 23),
++ MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", irda_parents, 0x0140, 24, 2, 31),
++ /* CLK_CFG_1 */
++ MUX_GATE(CLK_TOP_CAM_SEL, "cam_sel", cam_parents, 0x0144, 0, 3, 7),
++ MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents,
++ 0x0144, 8, 2, 15),
++ MUX_GATE(CLK_TOP_JPG_SEL, "jpg_sel", jpg_parents, 0x0144, 16, 3, 23),
++ MUX_GATE(CLK_TOP_DISP_SEL, "disp_sel", disp_parents, 0x0144, 24, 3, 31),
++ /* CLK_CFG_2 */
++ MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_parents, 0x0148, 0, 3, 7),
++ MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_parents, 0x0148, 8, 3, 15),
++ MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_parents, 0x0148, 16, 3, 23),
++ MUX_GATE(CLK_TOP_MSDC30_4_SEL, "msdc30_4_sel", msdc30_parents, 0x0148, 24, 3, 31),
++ /* CLK_CFG_3 */
++ MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x014c, 0, 2, 7),
++ /* CLK_CFG_4 */
++ MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", venc_parents, 0x0150, 8, 3, 15),
++ MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0150, 16, 3, 23),
++ MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0150, 24, 2, 31),
++ /* CLK_CFG_6 */
++ MUX_GATE(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0158, 0, 2, 7),
++ MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0158, 8, 3, 15),
++ MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0158, 24, 2, 31),
++ /* CLK_CFG_7 */
++ MUX_GATE(CLK_TOP_FIX_SEL, "fix_sel", fix_parents, 0x015c, 0, 3, 7),
++ MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x015c, 8, 4, 15),
++ MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents,
++ 0x015c, 16, 2, 23),
++ MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x015c, 24, 3, 31),
++ /* CLK_CFG_8 */
++ MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0164, 0, 3, 7),
++ MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_parents, 0x0164, 8, 3, 15),
++ MUX_GATE(CLK_TOP_SMI_MFG_AS_SEL, "smi_mfg_as_sel", smi_mfg_as_parents,
++ 0x0164, 16, 2, 23),
++ MUX_GATE(CLK_TOP_GCPU_SEL, "gcpu_sel", gcpu_parents, 0x0164, 24, 3, 31),
++ /* CLK_CFG_9 */
++ MUX_GATE(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents, 0x0168, 0, 2, 7),
++ MUX_GATE(CLK_TOP_CCI_SEL, "cci_sel", cci_parents, 0x0168, 8, 3, 15),
++ MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents, 0x0168, 16, 3, 23),
++ MUX_GATE(CLK_TOP_HDMIPLL_SEL, "hdmipll_sel", hdmipll_parents, 0x0168, 24, 2, 31),
++};
++
++static const struct mtk_gate_regs infra_cg_regs = {
++ .set_ofs = 0x0040,
++ .clr_ofs = 0x0044,
++ .sta_ofs = 0x0048,
++};
++
++#define GATE_ICG(_id, _name, _parent, _shift) { \
++ .id = _id, \
++ .name = _name, \
++ .parent_name = _parent, \
++ .regs = &infra_cg_regs, \
++ .shift = _shift, \
++ .ops = &mtk_clk_gate_ops_setclr, \
++ }
++
++static const struct mtk_gate infra_clks[] __initconst = {
++ GATE_ICG(CLK_INFRA_PMIC_WRAP, "pmic_wrap_ck", "axi_sel", 23),
++ GATE_ICG(CLK_INFRA_PMICSPI, "pmicspi_ck", "pmicspi_sel", 22),
++ GATE_ICG(CLK_INFRA_CCIF1_AP_CTRL, "ccif1_ap_ctrl", "axi_sel", 21),
++ GATE_ICG(CLK_INFRA_CCIF0_AP_CTRL, "ccif0_ap_ctrl", "axi_sel", 20),
++ GATE_ICG(CLK_INFRA_KP, "kp_ck", "axi_sel", 16),
++ GATE_ICG(CLK_INFRA_CPUM, "cpum_ck", "cpum_tck_in", 15),
++ GATE_ICG(CLK_INFRA_M4U, "m4u_ck", "mem_sel", 8),
++ GATE_ICG(CLK_INFRA_MFGAXI, "mfgaxi_ck", "axi_sel", 7),
++ GATE_ICG(CLK_INFRA_DEVAPC, "devapc_ck", "axi_sel", 6),
++ GATE_ICG(CLK_INFRA_AUDIO, "audio_ck", "aud_intbus_sel", 5),
++ GATE_ICG(CLK_INFRA_MFG_BUS, "mfg_bus_ck", "axi_sel", 2),
++ GATE_ICG(CLK_INFRA_SMI, "smi_ck", "smi_sel", 1),
++ GATE_ICG(CLK_INFRA_DBGCLK, "dbgclk_ck", "axi_sel", 0),
++};
++
++static const struct mtk_gate_regs peri0_cg_regs = {
++ .set_ofs = 0x0008,
++ .clr_ofs = 0x0010,
++ .sta_ofs = 0x0018,
++};
++
++static const struct mtk_gate_regs peri1_cg_regs = {
++ .set_ofs = 0x000c,
++ .clr_ofs = 0x0014,
++ .sta_ofs = 0x001c,
++};
++
++#define GATE_PERI0(_id, _name, _parent, _shift) { \
++ .id = _id, \
++ .name = _name, \
++ .parent_name = _parent, \
++ .regs = &peri0_cg_regs, \
++ .shift = _shift, \
++ .ops = &mtk_clk_gate_ops_setclr, \
++ }
++
++#define GATE_PERI1(_id, _name, _parent, _shift) { \
++ .id = _id, \
++ .name = _name, \
++ .parent_name = _parent, \
++ .regs = &peri1_cg_regs, \
++ .shift = _shift, \
++ .ops = &mtk_clk_gate_ops_setclr, \
++ }
++
++static const struct mtk_gate peri_gates[] __initconst = {
++ /* PERI0 */
++ GATE_PERI0(CLK_PERI_I2C5, "i2c5_ck", "axi_sel", 31),
++ GATE_PERI0(CLK_PERI_I2C4, "i2c4_ck", "axi_sel", 30),
++ GATE_PERI0(CLK_PERI_I2C3, "i2c3_ck", "axi_sel", 29),
++ GATE_PERI0(CLK_PERI_I2C2, "i2c2_ck", "axi_sel", 28),
++ GATE_PERI0(CLK_PERI_I2C1, "i2c1_ck", "axi_sel", 27),
++ GATE_PERI0(CLK_PERI_I2C0, "i2c0_ck", "axi_sel", 26),
++ GATE_PERI0(CLK_PERI_UART3, "uart3_ck", "axi_sel", 25),
++ GATE_PERI0(CLK_PERI_UART2, "uart2_ck", "axi_sel", 24),
++ GATE_PERI0(CLK_PERI_UART1, "uart1_ck", "axi_sel", 23),
++ GATE_PERI0(CLK_PERI_UART0, "uart0_ck", "axi_sel", 22),
++ GATE_PERI0(CLK_PERI_IRDA, "irda_ck", "irda_sel", 21),
++ GATE_PERI0(CLK_PERI_NLI, "nli_ck", "axi_sel", 20),
++ GATE_PERI0(CLK_PERI_MD_HIF, "md_hif_ck", "axi_sel", 19),
++ GATE_PERI0(CLK_PERI_AP_HIF, "ap_hif_ck", "axi_sel", 18),
++ GATE_PERI0(CLK_PERI_MSDC30_3, "msdc30_3_ck", "msdc30_4_sel", 17),
++ GATE_PERI0(CLK_PERI_MSDC30_2, "msdc30_2_ck", "msdc30_3_sel", 16),
++ GATE_PERI0(CLK_PERI_MSDC30_1, "msdc30_1_ck", "msdc30_2_sel", 15),
++ GATE_PERI0(CLK_PERI_MSDC20_2, "msdc20_2_ck", "msdc30_1_sel", 14),
++ GATE_PERI0(CLK_PERI_MSDC20_1, "msdc20_1_ck", "msdc30_0_sel", 13),
++ GATE_PERI0(CLK_PERI_AP_DMA, "ap_dma_ck", "axi_sel", 12),
++ GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11),
++ GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10),
++ GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9),
++ GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axi_sel", 8),
++ GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axi_sel", 7),
++ GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axi_sel", 6),
++ GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axi_sel", 5),
++ GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axi_sel", 4),
++ GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axi_sel", 3),
++ GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axi_sel", 2),
++ GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1),
++ GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "axi_sel", 0),
++ /* PERI1 */
++ GATE_PERI1(CLK_PERI_USBSLV, "usbslv_ck", "axi_sel", 8),
++ GATE_PERI1(CLK_PERI_USB1_MCU, "usb1_mcu_ck", "axi_sel", 7),
++ GATE_PERI1(CLK_PERI_USB0_MCU, "usb0_mcu_ck", "axi_sel", 6),
++ GATE_PERI1(CLK_PERI_GCPU, "gcpu_ck", "gcpu_sel", 5),
++ GATE_PERI1(CLK_PERI_FHCTL, "fhctl_ck", "clk26m", 4),
++ GATE_PERI1(CLK_PERI_SPI1, "spi1_ck", "spi_sel", 3),
++ GATE_PERI1(CLK_PERI_AUXADC, "auxadc_ck", "clk26m", 2),
++ GATE_PERI1(CLK_PERI_PERI_PWRAP, "peri_pwrap_ck", "axi_sel", 1),
++ GATE_PERI1(CLK_PERI_I2C6, "i2c6_ck", "axi_sel", 0),
++};
++
++static const char * const uart_ck_sel_parents[] __initconst = {
++ "clk26m",
++ "uart_sel",
++};
++
++static const struct mtk_composite peri_clks[] __initconst = {
++ MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1),
++ MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1),
++ MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1),
++ MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
++};
++
++static void __init mtk_topckgen_init(struct device_node *node)
++{
++ struct clk_onecell_data *clk_data;
++ void __iomem *base;
++ int r;
++
++ base = of_iomap(node, 0);
++ if (!base) {
++ pr_err("%s(): ioremap failed\n", __func__);
++ return;
++ }
++
++ clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
++
++ mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
++ mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
++ mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
++ &mt8135_clk_lock, clk_data);
++
++ clk_prepare_enable(clk_data->clks[CLK_TOP_CCI_SEL]);
++
++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++ if (r)
++ pr_err("%s(): could not register clock provider: %d\n",
++ __func__, r);
++}
++CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8135-topckgen", mtk_topckgen_init);
++
++static void __init mtk_infrasys_init(struct device_node *node)
++{
++ struct clk_onecell_data *clk_data;
++ int r;
++
++ clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
++
++ mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
++ clk_data);
++
++ clk_prepare_enable(clk_data->clks[CLK_INFRA_M4U]);
++
++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++ if (r)
++ pr_err("%s(): could not register clock provider: %d\n",
++ __func__, r);
++
++ mtk_register_reset_controller(node, 2, 0x30);
++}
++CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8135-infracfg", mtk_infrasys_init);
++
++static void __init mtk_pericfg_init(struct device_node *node)
++{
++ struct clk_onecell_data *clk_data;
++ int r;
++ void __iomem *base;
++
++ base = of_iomap(node, 0);
++ if (!base) {
++ pr_err("%s(): ioremap failed\n", __func__);
++ return;
++ }
++
++ clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
++
++ mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates),
++ clk_data);
++ mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base,
++ &mt8135_clk_lock, clk_data);
++
++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++ if (r)
++ pr_err("%s(): could not register clock provider: %d\n",
++ __func__, r);
++
++ mtk_register_reset_controller(node, 2, 0);
++}
++CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8135-pericfg", mtk_pericfg_init);
++
++#define MT8135_PLL_FMAX (2000 * MHZ)
++#define CON0_MT8135_RST_BAR BIT(27)
++
++#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \
++ .id = _id, \
++ .name = _name, \
++ .reg = _reg, \
++ .pwr_reg = _pwr_reg, \
++ .en_mask = _en_mask, \
++ .flags = _flags, \
++ .rst_bar_mask = CON0_MT8135_RST_BAR, \
++ .fmax = MT8135_PLL_FMAX, \
++ .pcwbits = _pcwbits, \
++ .pd_reg = _pd_reg, \
++ .pd_shift = _pd_shift, \
++ .tuner_reg = _tuner_reg, \
++ .pcw_reg = _pcw_reg, \
++ .pcw_shift = _pcw_shift, \
++ }
++
++static const struct mtk_pll_data plls[] = {
++ PLL(CLK_APMIXED_ARMPLL1, "armpll1", 0x200, 0x218, 0x80000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
++ PLL(CLK_APMIXED_ARMPLL2, "armpll2", 0x2cc, 0x2e4, 0x80000001, 0, 21, 0x2d0, 24, 0x0, 0x2d0, 0),
++ PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x21c, 0x234, 0xf0000001, HAVE_RST_BAR, 21, 0x21c, 6, 0x0, 0x220, 0),
++ PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x238, 0x250, 0xf3000001, HAVE_RST_BAR, 7, 0x238, 6, 0x0, 0x238, 9),
++ PLL(CLK_APMIXED_MMPLL, "mmpll", 0x254, 0x26c, 0xf0000001, HAVE_RST_BAR, 21, 0x254, 6, 0x0, 0x258, 0),
++ PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x278, 0x290, 0x80000001, 0, 21, 0x278, 6, 0x0, 0x27c, 0),
++ PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x294, 0x2ac, 0x80000001, 0, 31, 0x294, 6, 0x0, 0x298, 0),
++ PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2b0, 0x2c8, 0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x2b4, 0),
++ PLL(CLK_APMIXED_AUDPLL, "audpll", 0x2e8, 0x300, 0x80000001, 0, 31, 0x2e8, 6, 0x2f8, 0x2ec, 0),
++ PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x304, 0x31c, 0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x308, 0),
++};
++
++static void __init mtk_apmixedsys_init(struct device_node *node)
++{
++ struct clk_onecell_data *clk_data;
++
++ clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls));
++ if (!clk_data)
++ return;
++
++ mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
++}
++CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8135-apmixedsys",
++ mtk_apmixedsys_init);
+diff --git a/include/dt-bindings/clock/mt8135-clk.h b/include/dt-bindings/clock/mt8135-clk.h
+new file mode 100644
+index 0000000..6dac6c0
+--- /dev/null
++++ b/include/dt-bindings/clock/mt8135-clk.h
+@@ -0,0 +1,194 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#ifndef _DT_BINDINGS_CLK_MT8135_H
++#define _DT_BINDINGS_CLK_MT8135_H
++
++/* TOPCKGEN */
++
++#define CLK_TOP_DSI0_LNTC_DSICLK 1
++#define CLK_TOP_HDMITX_CLKDIG_CTS 2
++#define CLK_TOP_CLKPH_MCK 3
++#define CLK_TOP_CPUM_TCK_IN 4
++#define CLK_TOP_MAINPLL_806M 5
++#define CLK_TOP_MAINPLL_537P3M 6
++#define CLK_TOP_MAINPLL_322P4M 7
++#define CLK_TOP_MAINPLL_230P3M 8
++#define CLK_TOP_UNIVPLL_624M 9
++#define CLK_TOP_UNIVPLL_416M 10
++#define CLK_TOP_UNIVPLL_249P6M 11
++#define CLK_TOP_UNIVPLL_178P3M 12
++#define CLK_TOP_UNIVPLL_48M 13
++#define CLK_TOP_MMPLL_D2 14
++#define CLK_TOP_MMPLL_D3 15
++#define CLK_TOP_MMPLL_D5 16
++#define CLK_TOP_MMPLL_D7 17
++#define CLK_TOP_MMPLL_D4 18
++#define CLK_TOP_MMPLL_D6 19
++#define CLK_TOP_SYSPLL_D2 20
++#define CLK_TOP_SYSPLL_D4 21
++#define CLK_TOP_SYSPLL_D6 22
++#define CLK_TOP_SYSPLL_D8 23
++#define CLK_TOP_SYSPLL_D10 24
++#define CLK_TOP_SYSPLL_D12 25
++#define CLK_TOP_SYSPLL_D16 26
++#define CLK_TOP_SYSPLL_D24 27
++#define CLK_TOP_SYSPLL_D3 28
++#define CLK_TOP_SYSPLL_D2P5 29
++#define CLK_TOP_SYSPLL_D5 30
++#define CLK_TOP_SYSPLL_D3P5 31
++#define CLK_TOP_UNIVPLL1_D2 32
++#define CLK_TOP_UNIVPLL1_D4 33
++#define CLK_TOP_UNIVPLL1_D6 34
++#define CLK_TOP_UNIVPLL1_D8 35
++#define CLK_TOP_UNIVPLL1_D10 36
++#define CLK_TOP_UNIVPLL2_D2 37
++#define CLK_TOP_UNIVPLL2_D4 38
++#define CLK_TOP_UNIVPLL2_D6 39
++#define CLK_TOP_UNIVPLL2_D8 40
++#define CLK_TOP_UNIVPLL_D3 41
++#define CLK_TOP_UNIVPLL_D5 42
++#define CLK_TOP_UNIVPLL_D7 43
++#define CLK_TOP_UNIVPLL_D10 44
++#define CLK_TOP_UNIVPLL_D26 45
++#define CLK_TOP_APLL 46
++#define CLK_TOP_APLL_D4 47
++#define CLK_TOP_APLL_D8 48
++#define CLK_TOP_APLL_D16 49
++#define CLK_TOP_APLL_D24 50
++#define CLK_TOP_LVDSPLL_D2 51
++#define CLK_TOP_LVDSPLL_D4 52
++#define CLK_TOP_LVDSPLL_D8 53
++#define CLK_TOP_LVDSTX_CLKDIG_CT 54
++#define CLK_TOP_VPLL_DPIX 55
++#define CLK_TOP_TVHDMI_H 56
++#define CLK_TOP_HDMITX_CLKDIG_D2 57
++#define CLK_TOP_HDMITX_CLKDIG_D3 58
++#define CLK_TOP_TVHDMI_D2 59
++#define CLK_TOP_TVHDMI_D4 60
++#define CLK_TOP_MEMPLL_MCK_D4 61
++#define CLK_TOP_AXI_SEL 62
++#define CLK_TOP_SMI_SEL 63
++#define CLK_TOP_MFG_SEL 64
++#define CLK_TOP_IRDA_SEL 65
++#define CLK_TOP_CAM_SEL 66
++#define CLK_TOP_AUD_INTBUS_SEL 67
++#define CLK_TOP_JPG_SEL 68
++#define CLK_TOP_DISP_SEL 69
++#define CLK_TOP_MSDC30_1_SEL 70
++#define CLK_TOP_MSDC30_2_SEL 71
++#define CLK_TOP_MSDC30_3_SEL 72
++#define CLK_TOP_MSDC30_4_SEL 73
++#define CLK_TOP_USB20_SEL 74
++#define CLK_TOP_VENC_SEL 75
++#define CLK_TOP_SPI_SEL 76
++#define CLK_TOP_UART_SEL 77
++#define CLK_TOP_MEM_SEL 78
++#define CLK_TOP_CAMTG_SEL 79
++#define CLK_TOP_AUDIO_SEL 80
++#define CLK_TOP_FIX_SEL 81
++#define CLK_TOP_VDEC_SEL 82
++#define CLK_TOP_DDRPHYCFG_SEL 83
++#define CLK_TOP_DPILVDS_SEL 84
++#define CLK_TOP_PMICSPI_SEL 85
++#define CLK_TOP_MSDC30_0_SEL 86
++#define CLK_TOP_SMI_MFG_AS_SEL 87
++#define CLK_TOP_GCPU_SEL 88
++#define CLK_TOP_DPI1_SEL 89
++#define CLK_TOP_CCI_SEL 90
++#define CLK_TOP_APLL_SEL 91
++#define CLK_TOP_HDMIPLL_SEL 92
++#define CLK_TOP_NR_CLK 93
++
++/* APMIXED_SYS */
++
++#define CLK_APMIXED_ARMPLL1 1
++#define CLK_APMIXED_ARMPLL2 2
++#define CLK_APMIXED_MAINPLL 3
++#define CLK_APMIXED_UNIVPLL 4
++#define CLK_APMIXED_MMPLL 5
++#define CLK_APMIXED_MSDCPLL 6
++#define CLK_APMIXED_TVDPLL 7
++#define CLK_APMIXED_LVDSPLL 8
++#define CLK_APMIXED_AUDPLL 9
++#define CLK_APMIXED_VDECPLL 10
++#define CLK_APMIXED_NR_CLK 11
++
++/* INFRA_SYS */
++
++#define CLK_INFRA_PMIC_WRAP 1
++#define CLK_INFRA_PMICSPI 2
++#define CLK_INFRA_CCIF1_AP_CTRL 3
++#define CLK_INFRA_CCIF0_AP_CTRL 4
++#define CLK_INFRA_KP 5
++#define CLK_INFRA_CPUM 6
++#define CLK_INFRA_M4U 7
++#define CLK_INFRA_MFGAXI 8
++#define CLK_INFRA_DEVAPC 9
++#define CLK_INFRA_AUDIO 10
++#define CLK_INFRA_MFG_BUS 11
++#define CLK_INFRA_SMI 12
++#define CLK_INFRA_DBGCLK 13
++#define CLK_INFRA_NR_CLK 14
++
++/* PERI_SYS */
++
++#define CLK_PERI_I2C5 1
++#define CLK_PERI_I2C4 2
++#define CLK_PERI_I2C3 3
++#define CLK_PERI_I2C2 4
++#define CLK_PERI_I2C1 5
++#define CLK_PERI_I2C0 6
++#define CLK_PERI_UART3 7
++#define CLK_PERI_UART2 8
++#define CLK_PERI_UART1 9
++#define CLK_PERI_UART0 10
++#define CLK_PERI_IRDA 11
++#define CLK_PERI_NLI 12
++#define CLK_PERI_MD_HIF 13
++#define CLK_PERI_AP_HIF 14
++#define CLK_PERI_MSDC30_3 15
++#define CLK_PERI_MSDC30_2 16
++#define CLK_PERI_MSDC30_1 17
++#define CLK_PERI_MSDC20_2 18
++#define CLK_PERI_MSDC20_1 19
++#define CLK_PERI_AP_DMA 20
++#define CLK_PERI_USB1 21
++#define CLK_PERI_USB0 22
++#define CLK_PERI_PWM 23
++#define CLK_PERI_PWM7 24
++#define CLK_PERI_PWM6 25
++#define CLK_PERI_PWM5 26
++#define CLK_PERI_PWM4 27
++#define CLK_PERI_PWM3 28
++#define CLK_PERI_PWM2 29
++#define CLK_PERI_PWM1 30
++#define CLK_PERI_THERM 31
++#define CLK_PERI_NFI 32
++#define CLK_PERI_USBSLV 33
++#define CLK_PERI_USB1_MCU 34
++#define CLK_PERI_USB0_MCU 35
++#define CLK_PERI_GCPU 36
++#define CLK_PERI_FHCTL 37
++#define CLK_PERI_SPI1 38
++#define CLK_PERI_AUXADC 39
++#define CLK_PERI_PERI_PWRAP 40
++#define CLK_PERI_I2C6 41
++#define CLK_PERI_UART0_SEL 42
++#define CLK_PERI_UART1_SEL 43
++#define CLK_PERI_UART2_SEL 44
++#define CLK_PERI_UART3_SEL 45
++#define CLK_PERI_NR_CLK 46
++
++#endif /* _DT_BINDINGS_CLK_MT8135_H */
+diff --git a/include/dt-bindings/reset-controller/mt8135-resets.h b/include/dt-bindings/reset-controller/mt8135-resets.h
+new file mode 100644
+index 0000000..1fb6295
+--- /dev/null
++++ b/include/dt-bindings/reset-controller/mt8135-resets.h
+@@ -0,0 +1,64 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Flora Fu, MediaTek
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8135
++#define _DT_BINDINGS_RESET_CONTROLLER_MT8135
++
++/* INFRACFG resets */
++#define MT8135_INFRA_EMI_REG_RST 0
++#define MT8135_INFRA_DRAMC0_A0_RST 1
++#define MT8135_INFRA_CCIF0_RST 2
++#define MT8135_INFRA_APCIRQ_EINT_RST 3
++#define MT8135_INFRA_APXGPT_RST 4
++#define MT8135_INFRA_SCPSYS_RST 5
++#define MT8135_INFRA_CCIF1_RST 6
++#define MT8135_INFRA_PMIC_WRAP_RST 7
++#define MT8135_INFRA_KP_RST 8
++#define MT8135_INFRA_EMI_RST 32
++#define MT8135_INFRA_DRAMC0_RST 34
++#define MT8135_INFRA_SMI_RST 35
++#define MT8135_INFRA_M4U_RST 36
++
++/* PERICFG resets */
++#define MT8135_PERI_UART0_SW_RST 0
++#define MT8135_PERI_UART1_SW_RST 1
++#define MT8135_PERI_UART2_SW_RST 2
++#define MT8135_PERI_UART3_SW_RST 3
++#define MT8135_PERI_IRDA_SW_RST 4
++#define MT8135_PERI_PTP_SW_RST 5
++#define MT8135_PERI_AP_HIF_SW_RST 6
++#define MT8135_PERI_GPCU_SW_RST 7
++#define MT8135_PERI_MD_HIF_SW_RST 8
++#define MT8135_PERI_NLI_SW_RST 9
++#define MT8135_PERI_AUXADC_SW_RST 10
++#define MT8135_PERI_DMA_SW_RST 11
++#define MT8135_PERI_NFI_SW_RST 14
++#define MT8135_PERI_PWM_SW_RST 15
++#define MT8135_PERI_THERM_SW_RST 16
++#define MT8135_PERI_MSDC0_SW_RST 17
++#define MT8135_PERI_MSDC1_SW_RST 18
++#define MT8135_PERI_MSDC2_SW_RST 19
++#define MT8135_PERI_MSDC3_SW_RST 20
++#define MT8135_PERI_I2C0_SW_RST 22
++#define MT8135_PERI_I2C1_SW_RST 23
++#define MT8135_PERI_I2C2_SW_RST 24
++#define MT8135_PERI_I2C3_SW_RST 25
++#define MT8135_PERI_I2C4_SW_RST 26
++#define MT8135_PERI_I2C5_SW_RST 27
++#define MT8135_PERI_I2C6_SW_RST 28
++#define MT8135_PERI_USB_SW_RST 29
++#define MT8135_PERI_SPI1_SW_RST 33
++#define MT8135_PERI_PWRAP_BRIDGE_SW_RST 34
++
++#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8135 */
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0005-clk-mediatek-Add-basic-clocks-for-Mediatek-MT8173.patch b/target/linux/mediatek/patches/0005-clk-mediatek-Add-basic-clocks-for-Mediatek-MT8173.patch
new file mode 100644
index 0000000000..9c0e2891a7
--- /dev/null
+++ b/target/linux/mediatek/patches/0005-clk-mediatek-Add-basic-clocks-for-Mediatek-MT8173.patch
@@ -0,0 +1,1179 @@
+From 0efcd47787019284a334186fce134ee475c79211 Mon Sep 17 00:00:00 2001
+From: James Liao <jamesjj.liao@mediatek.com>
+Date: Thu, 23 Apr 2015 10:35:42 +0200
+Subject: [PATCH 05/76] clk: mediatek: Add basic clocks for Mediatek MT8173.
+
+This patch adds basic clocks for MT8173, including TOPCKGEN, PLLs,
+INFRA and PERI clocks.
+
+Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
+Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/clk/mediatek/Makefile | 1 +
+ drivers/clk/mediatek/clk-mt8173.c | 830 ++++++++++++++++++++
+ include/dt-bindings/clock/mt8173-clk.h | 235 ++++++
+ .../dt-bindings/reset-controller/mt8173-resets.h | 63 ++
+ 4 files changed, 1129 insertions(+)
+ create mode 100644 drivers/clk/mediatek/clk-mt8173.c
+ create mode 100644 include/dt-bindings/clock/mt8173-clk.h
+ create mode 100644 include/dt-bindings/reset-controller/mt8173-resets.h
+
+diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
+index 12ce576..8e4b2a4 100644
+--- a/drivers/clk/mediatek/Makefile
++++ b/drivers/clk/mediatek/Makefile
+@@ -1,3 +1,4 @@
+ obj-y += clk-mtk.o clk-pll.o clk-gate.o
+ obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+ obj-y += clk-mt8135.o
++obj-y += clk-mt8173.o
+diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
+new file mode 100644
+index 0000000..357b080
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-mt8173.c
+@@ -0,0 +1,830 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/of.h>
++#include <linux/of_address.h>
++#include <linux/slab.h>
++#include <linux/mfd/syscon.h>
++
++#include "clk-mtk.h"
++#include "clk-gate.h"
++
++#include <dt-bindings/clock/mt8173-clk.h>
++
++static DEFINE_SPINLOCK(mt8173_clk_lock);
++
++static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
++ FACTOR(CLK_TOP_CLKPH_MCK_O, "clkph_mck_o", "clk_null", 1, 1),
++ FACTOR(CLK_TOP_DPI, "dpi_ck", "clk_null", 1, 1),
++ FACTOR(CLK_TOP_USB_SYSPLL_125M, "usb_syspll_125m", "clk_null", 1, 1),
++ FACTOR(CLK_TOP_HDMITX_DIG_CTS, "hdmitx_dig_cts", "clk_null", 1, 1),
++};
++
++static const struct mtk_fixed_factor top_divs[] __initconst = {
++ FACTOR(CLK_TOP_ARMCA7PLL_754M, "armca7pll_754m", "armca7pll", 1, 2),
++ FACTOR(CLK_TOP_ARMCA7PLL_502M, "armca7pll_502m", "armca7pll", 1, 3),
++
++ FACTOR(CLK_TOP_MAIN_H546M, "main_h546m", "mainpll", 1, 2),
++ FACTOR(CLK_TOP_MAIN_H364M, "main_h364m", "mainpll", 1, 3),
++ FACTOR(CLK_TOP_MAIN_H218P4M, "main_h218p4m", "mainpll", 1, 5),
++ FACTOR(CLK_TOP_MAIN_H156M, "main_h156m", "mainpll", 1, 7),
++
++ FACTOR(CLK_TOP_TVDPLL_445P5M, "tvdpll_445p5m", "tvdpll", 1, 4),
++ FACTOR(CLK_TOP_TVDPLL_594M, "tvdpll_594m", "tvdpll", 1, 3),
++
++ FACTOR(CLK_TOP_UNIV_624M, "univ_624m", "univpll", 1, 2),
++ FACTOR(CLK_TOP_UNIV_416M, "univ_416m", "univpll", 1, 3),
++ FACTOR(CLK_TOP_UNIV_249P6M, "univ_249p6m", "univpll", 1, 5),
++ FACTOR(CLK_TOP_UNIV_178P3M, "univ_178p3m", "univpll", 1, 7),
++ FACTOR(CLK_TOP_UNIV_48M, "univ_48m", "univpll", 1, 26),
++
++ FACTOR(CLK_TOP_CLKRTC_EXT, "clkrtc_ext", "clk32k", 1, 1),
++ FACTOR(CLK_TOP_CLKRTC_INT, "clkrtc_int", "clk26m", 1, 793),
++ FACTOR(CLK_TOP_FPC, "fpc_ck", "clk26m", 1, 1),
++
++ FACTOR(CLK_TOP_HDMITXPLL_D2, "hdmitxpll_d2", "hdmitx_dig_cts", 1, 2),
++ FACTOR(CLK_TOP_HDMITXPLL_D3, "hdmitxpll_d3", "hdmitx_dig_cts", 1, 3),
++
++ FACTOR(CLK_TOP_ARMCA7PLL_D2, "armca7pll_d2", "armca7pll_754m", 1, 1),
++ FACTOR(CLK_TOP_ARMCA7PLL_D3, "armca7pll_d3", "armca7pll_502m", 1, 1),
++
++ FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, 1),
++ FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, 1),
++
++ FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "clkph_mck_o", 1, 1),
++ FACTOR(CLK_TOP_DMPLL_D2, "dmpll_d2", "clkph_mck_o", 1, 2),
++ FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "clkph_mck_o", 1, 4),
++ FACTOR(CLK_TOP_DMPLL_D8, "dmpll_d8", "clkph_mck_o", 1, 8),
++ FACTOR(CLK_TOP_DMPLL_D16, "dmpll_d16", "clkph_mck_o", 1, 16),
++
++ FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
++ FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
++ FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
++
++ FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1),
++ FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
++
++ FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1),
++ FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
++ FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4),
++ FACTOR(CLK_TOP_MSDCPLL2, "msdcpll2_ck", "msdcpll2", 1, 1),
++ FACTOR(CLK_TOP_MSDCPLL2_D2, "msdcpll2_d2", "msdcpll2", 1, 2),
++ FACTOR(CLK_TOP_MSDCPLL2_D4, "msdcpll2_d4", "msdcpll2", 1, 4),
++
++ FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "main_h546m", 1, 1),
++ FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "main_h546m", 1, 2),
++ FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "main_h546m", 1, 4),
++ FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "main_h546m", 1, 8),
++ FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "main_h546m", 1, 16),
++ FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "main_h364m", 1, 1),
++ FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "main_h364m", 1, 2),
++ FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "main_h364m", 1, 4),
++ FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "main_h218p4m", 1, 1),
++ FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "main_h218p4m", 1, 2),
++ FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "main_h218p4m", 1, 4),
++ FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "main_h156m", 1, 1),
++ FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "main_h156m", 1, 2),
++ FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "main_h156m", 1, 4),
++
++ FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll_594m", 1, 1),
++ FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_594m", 1, 2),
++ FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_594m", 1, 4),
++ FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_594m", 1, 8),
++ FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_594m", 1, 16),
++
++ FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univ_624m", 1, 1),
++ FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univ_624m", 1, 2),
++ FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univ_624m", 1, 4),
++ FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univ_624m", 1, 8),
++ FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univ_416m", 1, 1),
++ FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univ_416m", 1, 2),
++ FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univ_416m", 1, 4),
++ FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univ_416m", 1, 8),
++ FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univ_249p6m", 1, 1),
++ FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univ_249p6m", 1, 2),
++ FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univ_249p6m", 1, 4),
++ FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univ_249p6m", 1, 8),
++ FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univ_178p3m", 1, 1),
++ FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univ_48m", 1, 1),
++ FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univ_48m", 1, 2),
++
++ FACTOR(CLK_TOP_VCODECPLL, "vcodecpll_ck", "vcodecpll", 1, 3),
++ FACTOR(CLK_TOP_VCODECPLL_370P5, "vcodecpll_370p5", "vcodecpll", 1, 4),
++
++ FACTOR(CLK_TOP_VENCPLL, "vencpll_ck", "vencpll", 1, 1),
++ FACTOR(CLK_TOP_VENCPLL_D2, "vencpll_d2", "vencpll", 1, 2),
++ FACTOR(CLK_TOP_VENCPLL_D4, "vencpll_d4", "vencpll", 1, 4),
++};
++
++static const char * const axi_parents[] __initconst = {
++ "clk26m",
++ "syspll1_d2",
++ "syspll_d5",
++ "syspll1_d4",
++ "univpll_d5",
++ "univpll2_d2",
++ "dmpll_d2",
++ "dmpll_d4"
++};
++
++static const char * const mem_parents[] __initconst = {
++ "clk26m",
++ "dmpll_ck"
++};
++
++static const char * const ddrphycfg_parents[] __initconst = {
++ "clk26m",
++ "syspll1_d8"
++};
++
++static const char * const mm_parents[] __initconst = {
++ "clk26m",
++ "vencpll_d2",
++ "main_h364m",
++ "syspll1_d2",
++ "syspll_d5",
++ "syspll1_d4",
++ "univpll1_d2",
++ "univpll2_d2",
++ "dmpll_d2"
++};
++
++static const char * const pwm_parents[] __initconst = {
++ "clk26m",
++ "univpll2_d4",
++ "univpll3_d2",
++ "univpll1_d4"
++};
++
++static const char * const vdec_parents[] __initconst = {
++ "clk26m",
++ "vcodecpll_ck",
++ "tvdpll_445p5m",
++ "univpll_d3",
++ "vencpll_d2",
++ "syspll_d3",
++ "univpll1_d2",
++ "mmpll_d2",
++ "dmpll_d2",
++ "dmpll_d4"
++};
++
++static const char * const venc_parents[] __initconst = {
++ "clk26m",
++ "vcodecpll_ck",
++ "tvdpll_445p5m",
++ "univpll_d3",
++ "vencpll_d2",
++ "syspll_d3",
++ "univpll1_d2",
++ "univpll2_d2",
++ "dmpll_d2",
++ "dmpll_d4"
++};
++
++static const char * const mfg_parents[] __initconst = {
++ "clk26m",
++ "mmpll_ck",
++ "dmpll_ck",
++ "clk26m",
++ "clk26m",
++ "clk26m",
++ "clk26m",
++ "clk26m",
++ "clk26m",
++ "syspll_d3",
++ "syspll1_d2",
++ "syspll_d5",
++ "univpll_d3",
++ "univpll1_d2",
++ "univpll_d5",
++ "univpll2_d2"
++};
++
++static const char * const camtg_parents[] __initconst = {
++ "clk26m",
++ "univpll_d26",
++ "univpll2_d2",
++ "syspll3_d2",
++ "syspll3_d4",
++ "univpll1_d4"
++};
++
++static const char * const uart_parents[] __initconst = {
++ "clk26m",
++ "univpll2_d8"
++};
++
++static const char * const spi_parents[] __initconst = {
++ "clk26m",
++ "syspll3_d2",
++ "syspll1_d4",
++ "syspll4_d2",
++ "univpll3_d2",
++ "univpll2_d4",
++ "univpll1_d8"
++};
++
++static const char * const usb20_parents[] __initconst = {
++ "clk26m",
++ "univpll1_d8",
++ "univpll3_d4"
++};
++
++static const char * const usb30_parents[] __initconst = {
++ "clk26m",
++ "univpll3_d2",
++ "usb_syspll_125m",
++ "univpll2_d4"
++};
++
++static const char * const msdc50_0_h_parents[] __initconst = {
++ "clk26m",
++ "syspll1_d2",
++ "syspll2_d2",
++ "syspll4_d2",
++ "univpll_d5",
++ "univpll1_d4"
++};
++
++static const char * const msdc50_0_parents[] __initconst = {
++ "clk26m",
++ "msdcpll_ck",
++ "msdcpll_d2",
++ "univpll1_d4",
++ "syspll2_d2",
++ "syspll_d7",
++ "msdcpll_d4",
++ "vencpll_d4",
++ "tvdpll_ck",
++ "univpll_d2",
++ "univpll1_d2",
++ "mmpll_ck",
++ "msdcpll2_ck",
++ "msdcpll2_d2",
++ "msdcpll2_d4"
++};
++
++static const char * const msdc30_1_parents[] __initconst = {
++ "clk26m",
++ "univpll2_d2",
++ "msdcpll_d4",
++ "univpll1_d4",
++ "syspll2_d2",
++ "syspll_d7",
++ "univpll_d7",
++ "vencpll_d4"
++};
++
++static const char * const msdc30_2_parents[] __initconst = {
++ "clk26m",
++ "univpll2_d2",
++ "msdcpll_d4",
++ "univpll1_d4",
++ "syspll2_d2",
++ "syspll_d7",
++ "univpll_d7",
++ "vencpll_d2"
++};
++
++static const char * const msdc30_3_parents[] __initconst = {
++ "clk26m",
++ "msdcpll2_ck",
++ "msdcpll2_d2",
++ "univpll2_d2",
++ "msdcpll2_d4",
++ "msdcpll_d4",
++ "univpll1_d4",
++ "syspll2_d2",
++ "syspll_d7",
++ "univpll_d7",
++ "vencpll_d4",
++ "msdcpll_ck",
++ "msdcpll_d2",
++ "msdcpll_d4"
++};
++
++static const char * const audio_parents[] __initconst = {
++ "clk26m",
++ "syspll3_d4",
++ "syspll4_d4",
++ "syspll1_d16"
++};
++
++static const char * const aud_intbus_parents[] __initconst = {
++ "clk26m",
++ "syspll1_d4",
++ "syspll4_d2",
++ "univpll3_d2",
++ "univpll2_d8",
++ "dmpll_d4",
++ "dmpll_d8"
++};
++
++static const char * const pmicspi_parents[] __initconst = {
++ "clk26m",
++ "syspll1_d8",
++ "syspll3_d4",
++ "syspll1_d16",
++ "univpll3_d4",
++ "univpll_d26",
++ "dmpll_d8",
++ "dmpll_d16"
++};
++
++static const char * const scp_parents[] __initconst = {
++ "clk26m",
++ "syspll1_d2",
++ "univpll_d5",
++ "syspll_d5",
++ "dmpll_d2",
++ "dmpll_d4"
++};
++
++static const char * const atb_parents[] __initconst = {
++ "clk26m",
++ "syspll1_d2",
++ "univpll_d5",
++ "dmpll_d2"
++};
++
++static const char * const venc_lt_parents[] __initconst = {
++ "clk26m",
++ "univpll_d3",
++ "vcodecpll_ck",
++ "tvdpll_445p5m",
++ "vencpll_d2",
++ "syspll_d3",
++ "univpll1_d2",
++ "univpll2_d2",
++ "syspll1_d2",
++ "univpll_d5",
++ "vcodecpll_370p5",
++ "dmpll_ck"
++};
++
++static const char * const dpi0_parents[] __initconst = {
++ "clk26m",
++ "tvdpll_d2",
++ "tvdpll_d4",
++ "clk26m",
++ "clk26m",
++ "tvdpll_d8",
++ "tvdpll_d16"
++};
++
++static const char * const irda_parents[] __initconst = {
++ "clk26m",
++ "univpll2_d4",
++ "syspll2_d4"
++};
++
++static const char * const cci400_parents[] __initconst = {
++ "clk26m",
++ "vencpll_ck",
++ "armca7pll_754m",
++ "armca7pll_502m",
++ "univpll_d2",
++ "syspll_d2",
++ "msdcpll_ck",
++ "dmpll_ck"
++};
++
++static const char * const aud_1_parents[] __initconst = {
++ "clk26m",
++ "apll1_ck",
++ "univpll2_d4",
++ "univpll2_d8"
++};
++
++static const char * const aud_2_parents[] __initconst = {
++ "clk26m",
++ "apll2_ck",
++ "univpll2_d4",
++ "univpll2_d8"
++};
++
++static const char * const mem_mfg_in_parents[] __initconst = {
++ "clk26m",
++ "mmpll_ck",
++ "dmpll_ck",
++ "clk26m"
++};
++
++static const char * const axi_mfg_in_parents[] __initconst = {
++ "clk26m",
++ "axi_sel",
++ "dmpll_d2"
++};
++
++static const char * const scam_parents[] __initconst = {
++ "clk26m",
++ "syspll3_d2",
++ "univpll2_d4",
++ "dmpll_d4"
++};
++
++static const char * const spinfi_ifr_parents[] __initconst = {
++ "clk26m",
++ "univpll2_d8",
++ "univpll3_d4",
++ "syspll4_d2",
++ "univpll2_d4",
++ "univpll3_d2",
++ "syspll1_d4",
++ "univpll1_d4"
++};
++
++static const char * const hdmi_parents[] __initconst = {
++ "clk26m",
++ "hdmitx_dig_cts",
++ "hdmitxpll_d2",
++ "hdmitxpll_d3"
++};
++
++static const char * const dpilvds_parents[] __initconst = {
++ "clk26m",
++ "lvdspll",
++ "lvdspll_d2",
++ "lvdspll_d4",
++ "lvdspll_d8",
++ "fpc_ck"
++};
++
++static const char * const msdc50_2_h_parents[] __initconst = {
++ "clk26m",
++ "syspll1_d2",
++ "syspll2_d2",
++ "syspll4_d2",
++ "univpll_d5",
++ "univpll1_d4"
++};
++
++static const char * const hdcp_parents[] __initconst = {
++ "clk26m",
++ "syspll4_d2",
++ "syspll3_d4",
++ "univpll2_d4"
++};
++
++static const char * const hdcp_24m_parents[] __initconst = {
++ "clk26m",
++ "univpll_d26",
++ "univpll_d52",
++ "univpll2_d8"
++};
++
++static const char * const rtc_parents[] __initconst = {
++ "clkrtc_int",
++ "clkrtc_ext",
++ "clk26m",
++ "univpll3_d8"
++};
++
++static const char * const i2s0_m_ck_parents[] __initconst = {
++ "apll1_div1",
++ "apll2_div1"
++};
++
++static const char * const i2s1_m_ck_parents[] __initconst = {
++ "apll1_div2",
++ "apll2_div2"
++};
++
++static const char * const i2s2_m_ck_parents[] __initconst = {
++ "apll1_div3",
++ "apll2_div3"
++};
++
++static const char * const i2s3_m_ck_parents[] __initconst = {
++ "apll1_div4",
++ "apll2_div4"
++};
++
++static const char * const i2s3_b_ck_parents[] __initconst = {
++ "apll1_div5",
++ "apll2_div5"
++};
++
++static const struct mtk_composite top_muxes[] __initconst = {
++ /* CLK_CFG_0 */
++ MUX(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x0040, 0, 3),
++ MUX(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0040, 8, 1),
++ MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, 0x0040, 16, 1, 23),
++ MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", mm_parents, 0x0040, 24, 4, 31),
++ /* CLK_CFG_1 */
++ MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x0050, 0, 2, 7),
++ MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x0050, 8, 4, 15),
++ MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", venc_parents, 0x0050, 16, 4, 23),
++ MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0050, 24, 4, 31),
++ /* CLK_CFG_2 */
++ MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0060, 0, 3, 7),
++ MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0060, 8, 1, 15),
++ MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0060, 16, 3, 23),
++ MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x0060, 24, 2, 31),
++ /* CLK_CFG_3 */
++ MUX_GATE(CLK_TOP_USB30_SEL, "usb30_sel", usb30_parents, 0x0070, 0, 2, 7),
++ MUX_GATE(CLK_TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel", msdc50_0_h_parents, 0x0070, 8, 3, 15),
++ MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_parents, 0x0070, 16, 4, 23),
++ MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_parents, 0x0070, 24, 3, 31),
++ /* CLK_CFG_4 */
++ MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_2_parents, 0x0080, 0, 3, 7),
++ MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_3_parents, 0x0080, 8, 4, 15),
++ MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0080, 16, 2, 23),
++ MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, 0x0080, 24, 3, 31),
++ /* CLK_CFG_5 */
++ MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0090, 0, 3, 7 /* 7:5 */),
++ MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, 0x0090, 8, 3, 15),
++ MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, 0x0090, 16, 2, 23),
++ MUX_GATE(CLK_TOP_VENC_LT_SEL, "venclt_sel", venc_lt_parents, 0x0090, 24, 4, 31),
++ /* CLK_CFG_6 */
++ MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x00a0, 0, 3, 7),
++ MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", irda_parents, 0x00a0, 8, 2, 15),
++ MUX_GATE(CLK_TOP_CCI400_SEL, "cci400_sel", cci400_parents, 0x00a0, 16, 3, 23),
++ MUX_GATE(CLK_TOP_AUD_1_SEL, "aud_1_sel", aud_1_parents, 0x00a0, 24, 2, 31),
++ /* CLK_CFG_7 */
++ MUX_GATE(CLK_TOP_AUD_2_SEL, "aud_2_sel", aud_2_parents, 0x00b0, 0, 2, 7),
++ MUX_GATE(CLK_TOP_MEM_MFG_IN_SEL, "mem_mfg_in_sel", mem_mfg_in_parents, 0x00b0, 8, 2, 15),
++ MUX_GATE(CLK_TOP_AXI_MFG_IN_SEL, "axi_mfg_in_sel", axi_mfg_in_parents, 0x00b0, 16, 2, 23),
++ MUX_GATE(CLK_TOP_SCAM_SEL, "scam_sel", scam_parents, 0x00b0, 24, 2, 31),
++ /* CLK_CFG_12 */
++ MUX_GATE(CLK_TOP_SPINFI_IFR_SEL, "spinfi_ifr_sel", spinfi_ifr_parents, 0x00c0, 0, 3, 7),
++ MUX_GATE(CLK_TOP_HDMI_SEL, "hdmi_sel", hdmi_parents, 0x00c0, 8, 2, 15),
++ MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x00c0, 24, 3, 31),
++ /* CLK_CFG_13 */
++ MUX_GATE(CLK_TOP_MSDC50_2_H_SEL, "msdc50_2_h_sel", msdc50_2_h_parents, 0x00d0, 0, 3, 7),
++ MUX_GATE(CLK_TOP_HDCP_SEL, "hdcp_sel", hdcp_parents, 0x00d0, 8, 2, 15),
++ MUX_GATE(CLK_TOP_HDCP_24M_SEL, "hdcp_24m_sel", hdcp_24m_parents, 0x00d0, 16, 2, 23),
++ MUX(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x00d0, 24, 2),
++
++ DIV_GATE(CLK_TOP_APLL1_DIV0, "apll1_div0", "aud_1_sel", 0x12c, 8, 0x120, 4, 24),
++ DIV_GATE(CLK_TOP_APLL1_DIV1, "apll1_div1", "aud_1_sel", 0x12c, 9, 0x124, 8, 0),
++ DIV_GATE(CLK_TOP_APLL1_DIV2, "apll1_div2", "aud_1_sel", 0x12c, 10, 0x124, 8, 8),
++ DIV_GATE(CLK_TOP_APLL1_DIV3, "apll1_div3", "aud_1_sel", 0x12c, 11, 0x124, 8, 16),
++ DIV_GATE(CLK_TOP_APLL1_DIV4, "apll1_div4", "aud_1_sel", 0x12c, 12, 0x124, 8, 24),
++ DIV_GATE(CLK_TOP_APLL1_DIV5, "apll1_div5", "apll1_div4", 0x12c, 13, 0x12c, 4, 0),
++
++ DIV_GATE(CLK_TOP_APLL2_DIV0, "apll2_div0", "aud_2_sel", 0x12c, 16, 0x120, 4, 28),
++ DIV_GATE(CLK_TOP_APLL2_DIV1, "apll2_div1", "aud_2_sel", 0x12c, 17, 0x128, 8, 0),
++ DIV_GATE(CLK_TOP_APLL2_DIV2, "apll2_div2", "aud_2_sel", 0x12c, 18, 0x128, 8, 8),
++ DIV_GATE(CLK_TOP_APLL2_DIV3, "apll2_div3", "aud_2_sel", 0x12c, 19, 0x128, 8, 16),
++ DIV_GATE(CLK_TOP_APLL2_DIV4, "apll2_div4", "aud_2_sel", 0x12c, 20, 0x128, 8, 24),
++ DIV_GATE(CLK_TOP_APLL2_DIV5, "apll2_div5", "apll2_div4", 0x12c, 21, 0x12c, 4, 4),
++
++ MUX(CLK_TOP_I2S0_M_SEL, "i2s0_m_ck_sel", i2s0_m_ck_parents, 0x120, 4, 1),
++ MUX(CLK_TOP_I2S1_M_SEL, "i2s1_m_ck_sel", i2s1_m_ck_parents, 0x120, 5, 1),
++ MUX(CLK_TOP_I2S2_M_SEL, "i2s2_m_ck_sel", i2s2_m_ck_parents, 0x120, 6, 1),
++ MUX(CLK_TOP_I2S3_M_SEL, "i2s3_m_ck_sel", i2s3_m_ck_parents, 0x120, 7, 1),
++ MUX(CLK_TOP_I2S3_B_SEL, "i2s3_b_ck_sel", i2s3_b_ck_parents, 0x120, 8, 1),
++};
++
++static const struct mtk_gate_regs infra_cg_regs = {
++ .set_ofs = 0x0040,
++ .clr_ofs = 0x0044,
++ .sta_ofs = 0x0048,
++};
++
++#define GATE_ICG(_id, _name, _parent, _shift) { \
++ .id = _id, \
++ .name = _name, \
++ .parent_name = _parent, \
++ .regs = &infra_cg_regs, \
++ .shift = _shift, \
++ .ops = &mtk_clk_gate_ops_setclr, \
++ }
++
++static const struct mtk_gate infra_clks[] __initconst = {
++ GATE_ICG(CLK_INFRA_DBGCLK, "infra_dbgclk", "axi_sel", 0),
++ GATE_ICG(CLK_INFRA_SMI, "infra_smi", "mm_sel", 1),
++ GATE_ICG(CLK_INFRA_AUDIO, "infra_audio", "aud_intbus_sel", 5),
++ GATE_ICG(CLK_INFRA_GCE, "infra_gce", "axi_sel", 6),
++ GATE_ICG(CLK_INFRA_L2C_SRAM, "infra_l2c_sram", "axi_sel", 7),
++ GATE_ICG(CLK_INFRA_M4U, "infra_m4u", "mem_sel", 8),
++ GATE_ICG(CLK_INFRA_CPUM, "infra_cpum", "clk_null", 15),
++ GATE_ICG(CLK_INFRA_KP, "infra_kp", "axi_sel", 16),
++ GATE_ICG(CLK_INFRA_CEC, "infra_cec", "clk26m", 18),
++ GATE_ICG(CLK_INFRA_PMICSPI, "infra_pmicspi", "pmicspi_sel", 22),
++ GATE_ICG(CLK_INFRA_PMICWRAP, "infra_pmicwrap", "axi_sel", 23),
++};
++
++static const struct mtk_gate_regs peri0_cg_regs = {
++ .set_ofs = 0x0008,
++ .clr_ofs = 0x0010,
++ .sta_ofs = 0x0018,
++};
++
++static const struct mtk_gate_regs peri1_cg_regs = {
++ .set_ofs = 0x000c,
++ .clr_ofs = 0x0014,
++ .sta_ofs = 0x001c,
++};
++
++#define GATE_PERI0(_id, _name, _parent, _shift) { \
++ .id = _id, \
++ .name = _name, \
++ .parent_name = _parent, \
++ .regs = &peri0_cg_regs, \
++ .shift = _shift, \
++ .ops = &mtk_clk_gate_ops_setclr, \
++ }
++
++#define GATE_PERI1(_id, _name, _parent, _shift) { \
++ .id = _id, \
++ .name = _name, \
++ .parent_name = _parent, \
++ .regs = &peri1_cg_regs, \
++ .shift = _shift, \
++ .ops = &mtk_clk_gate_ops_setclr, \
++ }
++
++static const struct mtk_gate peri_gates[] __initconst = {
++ /* PERI0 */
++ GATE_PERI0(CLK_PERI_NFI, "peri_nfi", "axi_sel", 0),
++ GATE_PERI0(CLK_PERI_THERM, "peri_therm", "axi_sel", 1),
++ GATE_PERI0(CLK_PERI_PWM1, "peri_pwm1", "axi_sel", 2),
++ GATE_PERI0(CLK_PERI_PWM2, "peri_pwm2", "axi_sel", 3),
++ GATE_PERI0(CLK_PERI_PWM3, "peri_pwm3", "axi_sel", 4),
++ GATE_PERI0(CLK_PERI_PWM4, "peri_pwm4", "axi_sel", 5),
++ GATE_PERI0(CLK_PERI_PWM5, "peri_pwm5", "axi_sel", 6),
++ GATE_PERI0(CLK_PERI_PWM6, "peri_pwm6", "axi_sel", 7),
++ GATE_PERI0(CLK_PERI_PWM7, "peri_pwm7", "axi_sel", 8),
++ GATE_PERI0(CLK_PERI_PWM, "peri_pwm", "axi_sel", 9),
++ GATE_PERI0(CLK_PERI_USB0, "peri_usb0", "usb20_sel", 10),
++ GATE_PERI0(CLK_PERI_USB1, "peri_usb1", "usb20_sel", 11),
++ GATE_PERI0(CLK_PERI_AP_DMA, "peri_ap_dma", "axi_sel", 12),
++ GATE_PERI0(CLK_PERI_MSDC30_0, "peri_msdc30_0", "msdc50_0_sel", 13),
++ GATE_PERI0(CLK_PERI_MSDC30_1, "peri_msdc30_1", "msdc30_1_sel", 14),
++ GATE_PERI0(CLK_PERI_MSDC30_2, "peri_msdc30_2", "msdc30_2_sel", 15),
++ GATE_PERI0(CLK_PERI_MSDC30_3, "peri_msdc30_3", "msdc30_3_sel", 16),
++ GATE_PERI0(CLK_PERI_NLI_ARB, "peri_nli_arb", "axi_sel", 17),
++ GATE_PERI0(CLK_PERI_IRDA, "peri_irda", "irda_sel", 18),
++ GATE_PERI0(CLK_PERI_UART0, "peri_uart0", "axi_sel", 19),
++ GATE_PERI0(CLK_PERI_UART1, "peri_uart1", "axi_sel", 20),
++ GATE_PERI0(CLK_PERI_UART2, "peri_uart2", "axi_sel", 21),
++ GATE_PERI0(CLK_PERI_UART3, "peri_uart3", "axi_sel", 22),
++ GATE_PERI0(CLK_PERI_I2C0, "peri_i2c0", "axi_sel", 23),
++ GATE_PERI0(CLK_PERI_I2C1, "peri_i2c1", "axi_sel", 24),
++ GATE_PERI0(CLK_PERI_I2C2, "peri_i2c2", "axi_sel", 25),
++ GATE_PERI0(CLK_PERI_I2C3, "peri_i2c3", "axi_sel", 26),
++ GATE_PERI0(CLK_PERI_I2C4, "peri_i2c4", "axi_sel", 27),
++ GATE_PERI0(CLK_PERI_AUXADC, "peri_auxadc", "clk26m", 28),
++ GATE_PERI0(CLK_PERI_SPI0, "peri_spi0", "spi_sel", 29),
++ GATE_PERI0(CLK_PERI_I2C5, "peri_i2c5", "axi_sel", 30),
++ GATE_PERI0(CLK_PERI_NFIECC, "peri_nfiecc", "axi_sel", 31),
++ /* PERI1 */
++ GATE_PERI1(CLK_PERI_SPI, "peri_spi", "spi_sel", 0),
++ GATE_PERI1(CLK_PERI_IRRX, "peri_irrx", "spi_sel", 1),
++ GATE_PERI1(CLK_PERI_I2C6, "peri_i2c6", "axi_sel", 2),
++};
++
++static const char * const uart_ck_sel_parents[] __initconst = {
++ "clk26m",
++ "uart_sel",
++};
++
++static const struct mtk_composite peri_clks[] __initconst = {
++ MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1),
++ MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1),
++ MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1),
++ MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
++};
++
++static void __init mtk_topckgen_init(struct device_node *node)
++{
++ struct clk_onecell_data *clk_data;
++ void __iomem *base;
++ int r;
++
++ base = of_iomap(node, 0);
++ if (!base) {
++ pr_err("%s(): ioremap failed\n", __func__);
++ return;
++ }
++
++ clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
++
++ mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
++ mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
++ mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
++ &mt8173_clk_lock, clk_data);
++
++ clk_prepare_enable(clk_data->clks[CLK_TOP_CCI400_SEL]);
++
++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++ if (r)
++ pr_err("%s(): could not register clock provider: %d\n",
++ __func__, r);
++}
++CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init);
++
++static void __init mtk_infrasys_init(struct device_node *node)
++{
++ struct clk_onecell_data *clk_data;
++ int r;
++
++ clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
++
++ mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
++ clk_data);
++
++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++ if (r)
++ pr_err("%s(): could not register clock provider: %d\n",
++ __func__, r);
++
++ mtk_register_reset_controller(node, 2, 0x30);
++}
++CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8173-infracfg", mtk_infrasys_init);
++
++static void __init mtk_pericfg_init(struct device_node *node)
++{
++ struct clk_onecell_data *clk_data;
++ int r;
++ void __iomem *base;
++
++ base = of_iomap(node, 0);
++ if (!base) {
++ pr_err("%s(): ioremap failed\n", __func__);
++ return;
++ }
++
++ clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
++
++ mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates),
++ clk_data);
++ mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base,
++ &mt8173_clk_lock, clk_data);
++
++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++ if (r)
++ pr_err("%s(): could not register clock provider: %d\n",
++ __func__, r);
++
++ mtk_register_reset_controller(node, 2, 0);
++}
++CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init);
++
++#define MT8173_PLL_FMAX (3000UL * MHZ)
++
++#define CON0_MT8173_RST_BAR BIT(24)
++
++#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, \
++ _tuner_reg, _pcw_reg, _pcw_shift) { \
++ .id = _id, \
++ .name = _name, \
++ .reg = _reg, \
++ .pwr_reg = _pwr_reg, \
++ .en_mask = _en_mask, \
++ .flags = _flags, \
++ .rst_bar_mask = CON0_MT8173_RST_BAR, \
++ .fmax = MT8173_PLL_FMAX, \
++ .pcwbits = _pcwbits, \
++ .pd_reg = _pd_reg, \
++ .pd_shift = _pd_shift, \
++ .tuner_reg = _tuner_reg, \
++ .pcw_reg = _pcw_reg, \
++ .pcw_shift = _pcw_shift, \
++ }
++
++static const struct mtk_pll_data plls[] = {
++ PLL(CLK_APMIXED_ARMCA15PLL, "armca15pll", 0x200, 0x20c, 0x00000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
++ PLL(CLK_APMIXED_ARMCA7PLL, "armca7pll", 0x210, 0x21c, 0x00000001, 0, 21, 0x214, 24, 0x0, 0x214, 0),
++ PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x220, 0x22c, 0xf0000101, HAVE_RST_BAR, 21, 0x220, 4, 0x0, 0x224, 0),
++ PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x230, 0x23c, 0xfe000001, HAVE_RST_BAR, 7, 0x230, 4, 0x0, 0x234, 14),
++ PLL(CLK_APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 24, 0x0, 0x244, 0),
++ PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x250, 0x25c, 0x00000001, 0, 21, 0x250, 4, 0x0, 0x254, 0),
++ PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x260, 0x26c, 0x00000001, 0, 21, 0x260, 4, 0x0, 0x264, 0),
++ PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x270, 0x27c, 0x00000001, 0, 21, 0x270, 4, 0x0, 0x274, 0),
++ PLL(CLK_APMIXED_MPLL, "mpll", 0x280, 0x28c, 0x00000001, 0, 21, 0x280, 4, 0x0, 0x284, 0),
++ PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x290, 0x29c, 0x00000001, 0, 21, 0x290, 4, 0x0, 0x294, 0),
++ PLL(CLK_APMIXED_APLL1, "apll1", 0x2a0, 0x2b0, 0x00000001, 0, 31, 0x2a0, 4, 0x2a4, 0x2a4, 0),
++ PLL(CLK_APMIXED_APLL2, "apll2", 0x2b4, 0x2c4, 0x00000001, 0, 31, 0x2b4, 4, 0x2b8, 0x2b8, 0),
++ PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2d0, 0x2dc, 0x00000001, 0, 21, 0x2d0, 4, 0x0, 0x2d4, 0),
++ PLL(CLK_APMIXED_MSDCPLL2, "msdcpll2", 0x2f0, 0x2fc, 0x00000001, 0, 21, 0x2f0, 4, 0x0, 0x2f4, 0),
++};
++
++static void __init mtk_apmixedsys_init(struct device_node *node)
++{
++ struct clk_onecell_data *clk_data;
++
++ clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls));
++ if (!clk_data)
++ return;
++
++ mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
++
++ clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMCA15PLL]);
++}
++CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys",
++ mtk_apmixedsys_init);
+diff --git a/include/dt-bindings/clock/mt8173-clk.h b/include/dt-bindings/clock/mt8173-clk.h
+new file mode 100644
+index 0000000..4ad76ed
+--- /dev/null
++++ b/include/dt-bindings/clock/mt8173-clk.h
+@@ -0,0 +1,235 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#ifndef _DT_BINDINGS_CLK_MT8173_H
++#define _DT_BINDINGS_CLK_MT8173_H
++
++/* TOPCKGEN */
++
++#define CLK_TOP_CLKPH_MCK_O 1
++#define CLK_TOP_DPI 2
++#define CLK_TOP_USB_SYSPLL_125M 3
++#define CLK_TOP_HDMITX_DIG_CTS 4
++#define CLK_TOP_ARMCA7PLL_754M 5
++#define CLK_TOP_ARMCA7PLL_502M 6
++#define CLK_TOP_MAIN_H546M 7
++#define CLK_TOP_MAIN_H364M 8
++#define CLK_TOP_MAIN_H218P4M 9
++#define CLK_TOP_MAIN_H156M 10
++#define CLK_TOP_TVDPLL_445P5M 11
++#define CLK_TOP_TVDPLL_594M 12
++#define CLK_TOP_UNIV_624M 13
++#define CLK_TOP_UNIV_416M 14
++#define CLK_TOP_UNIV_249P6M 15
++#define CLK_TOP_UNIV_178P3M 16
++#define CLK_TOP_UNIV_48M 17
++#define CLK_TOP_CLKRTC_EXT 18
++#define CLK_TOP_CLKRTC_INT 19
++#define CLK_TOP_FPC 20
++#define CLK_TOP_HDMITXPLL_D2 21
++#define CLK_TOP_HDMITXPLL_D3 22
++#define CLK_TOP_ARMCA7PLL_D2 23
++#define CLK_TOP_ARMCA7PLL_D3 24
++#define CLK_TOP_APLL1 25
++#define CLK_TOP_APLL2 26
++#define CLK_TOP_DMPLL 27
++#define CLK_TOP_DMPLL_D2 28
++#define CLK_TOP_DMPLL_D4 29
++#define CLK_TOP_DMPLL_D8 30
++#define CLK_TOP_DMPLL_D16 31
++#define CLK_TOP_LVDSPLL_D2 32
++#define CLK_TOP_LVDSPLL_D4 33
++#define CLK_TOP_LVDSPLL_D8 34
++#define CLK_TOP_MMPLL 35
++#define CLK_TOP_MMPLL_D2 36
++#define CLK_TOP_MSDCPLL 37
++#define CLK_TOP_MSDCPLL_D2 38
++#define CLK_TOP_MSDCPLL_D4 39
++#define CLK_TOP_MSDCPLL2 40
++#define CLK_TOP_MSDCPLL2_D2 41
++#define CLK_TOP_MSDCPLL2_D4 42
++#define CLK_TOP_SYSPLL_D2 43
++#define CLK_TOP_SYSPLL1_D2 44
++#define CLK_TOP_SYSPLL1_D4 45
++#define CLK_TOP_SYSPLL1_D8 46
++#define CLK_TOP_SYSPLL1_D16 47
++#define CLK_TOP_SYSPLL_D3 48
++#define CLK_TOP_SYSPLL2_D2 49
++#define CLK_TOP_SYSPLL2_D4 50
++#define CLK_TOP_SYSPLL_D5 51
++#define CLK_TOP_SYSPLL3_D2 52
++#define CLK_TOP_SYSPLL3_D4 53
++#define CLK_TOP_SYSPLL_D7 54
++#define CLK_TOP_SYSPLL4_D2 55
++#define CLK_TOP_SYSPLL4_D4 56
++#define CLK_TOP_TVDPLL 57
++#define CLK_TOP_TVDPLL_D2 58
++#define CLK_TOP_TVDPLL_D4 59
++#define CLK_TOP_TVDPLL_D8 60
++#define CLK_TOP_TVDPLL_D16 61
++#define CLK_TOP_UNIVPLL_D2 62
++#define CLK_TOP_UNIVPLL1_D2 63
++#define CLK_TOP_UNIVPLL1_D4 64
++#define CLK_TOP_UNIVPLL1_D8 65
++#define CLK_TOP_UNIVPLL_D3 66
++#define CLK_TOP_UNIVPLL2_D2 67
++#define CLK_TOP_UNIVPLL2_D4 68
++#define CLK_TOP_UNIVPLL2_D8 69
++#define CLK_TOP_UNIVPLL_D5 70
++#define CLK_TOP_UNIVPLL3_D2 71
++#define CLK_TOP_UNIVPLL3_D4 72
++#define CLK_TOP_UNIVPLL3_D8 73
++#define CLK_TOP_UNIVPLL_D7 74
++#define CLK_TOP_UNIVPLL_D26 75
++#define CLK_TOP_UNIVPLL_D52 76
++#define CLK_TOP_VCODECPLL 77
++#define CLK_TOP_VCODECPLL_370P5 78
++#define CLK_TOP_VENCPLL 79
++#define CLK_TOP_VENCPLL_D2 80
++#define CLK_TOP_VENCPLL_D4 81
++#define CLK_TOP_AXI_SEL 82
++#define CLK_TOP_MEM_SEL 83
++#define CLK_TOP_DDRPHYCFG_SEL 84
++#define CLK_TOP_MM_SEL 85
++#define CLK_TOP_PWM_SEL 86
++#define CLK_TOP_VDEC_SEL 87
++#define CLK_TOP_VENC_SEL 88
++#define CLK_TOP_MFG_SEL 89
++#define CLK_TOP_CAMTG_SEL 90
++#define CLK_TOP_UART_SEL 91
++#define CLK_TOP_SPI_SEL 92
++#define CLK_TOP_USB20_SEL 93
++#define CLK_TOP_USB30_SEL 94
++#define CLK_TOP_MSDC50_0_H_SEL 95
++#define CLK_TOP_MSDC50_0_SEL 96
++#define CLK_TOP_MSDC30_1_SEL 97
++#define CLK_TOP_MSDC30_2_SEL 98
++#define CLK_TOP_MSDC30_3_SEL 99
++#define CLK_TOP_AUDIO_SEL 100
++#define CLK_TOP_AUD_INTBUS_SEL 101
++#define CLK_TOP_PMICSPI_SEL 102
++#define CLK_TOP_SCP_SEL 103
++#define CLK_TOP_ATB_SEL 104
++#define CLK_TOP_VENC_LT_SEL 105
++#define CLK_TOP_DPI0_SEL 106
++#define CLK_TOP_IRDA_SEL 107
++#define CLK_TOP_CCI400_SEL 108
++#define CLK_TOP_AUD_1_SEL 109
++#define CLK_TOP_AUD_2_SEL 110
++#define CLK_TOP_MEM_MFG_IN_SEL 111
++#define CLK_TOP_AXI_MFG_IN_SEL 112
++#define CLK_TOP_SCAM_SEL 113
++#define CLK_TOP_SPINFI_IFR_SEL 114
++#define CLK_TOP_HDMI_SEL 115
++#define CLK_TOP_DPILVDS_SEL 116
++#define CLK_TOP_MSDC50_2_H_SEL 117
++#define CLK_TOP_HDCP_SEL 118
++#define CLK_TOP_HDCP_24M_SEL 119
++#define CLK_TOP_RTC_SEL 120
++#define CLK_TOP_APLL1_DIV0 121
++#define CLK_TOP_APLL1_DIV1 122
++#define CLK_TOP_APLL1_DIV2 123
++#define CLK_TOP_APLL1_DIV3 124
++#define CLK_TOP_APLL1_DIV4 125
++#define CLK_TOP_APLL1_DIV5 126
++#define CLK_TOP_APLL2_DIV0 127
++#define CLK_TOP_APLL2_DIV1 128
++#define CLK_TOP_APLL2_DIV2 129
++#define CLK_TOP_APLL2_DIV3 130
++#define CLK_TOP_APLL2_DIV4 131
++#define CLK_TOP_APLL2_DIV5 132
++#define CLK_TOP_I2S0_M_SEL 133
++#define CLK_TOP_I2S1_M_SEL 134
++#define CLK_TOP_I2S2_M_SEL 135
++#define CLK_TOP_I2S3_M_SEL 136
++#define CLK_TOP_I2S3_B_SEL 137
++#define CLK_TOP_NR_CLK 138
++
++/* APMIXED_SYS */
++
++#define CLK_APMIXED_ARMCA15PLL 1
++#define CLK_APMIXED_ARMCA7PLL 2
++#define CLK_APMIXED_MAINPLL 3
++#define CLK_APMIXED_UNIVPLL 4
++#define CLK_APMIXED_MMPLL 5
++#define CLK_APMIXED_MSDCPLL 6
++#define CLK_APMIXED_VENCPLL 7
++#define CLK_APMIXED_TVDPLL 8
++#define CLK_APMIXED_MPLL 9
++#define CLK_APMIXED_VCODECPLL 10
++#define CLK_APMIXED_APLL1 11
++#define CLK_APMIXED_APLL2 12
++#define CLK_APMIXED_LVDSPLL 13
++#define CLK_APMIXED_MSDCPLL2 14
++#define CLK_APMIXED_NR_CLK 15
++
++/* INFRA_SYS */
++
++#define CLK_INFRA_DBGCLK 1
++#define CLK_INFRA_SMI 2
++#define CLK_INFRA_AUDIO 3
++#define CLK_INFRA_GCE 4
++#define CLK_INFRA_L2C_SRAM 5
++#define CLK_INFRA_M4U 6
++#define CLK_INFRA_CPUM 7
++#define CLK_INFRA_KP 8
++#define CLK_INFRA_CEC 9
++#define CLK_INFRA_PMICSPI 10
++#define CLK_INFRA_PMICWRAP 11
++#define CLK_INFRA_NR_CLK 12
++
++/* PERI_SYS */
++
++#define CLK_PERI_NFI 1
++#define CLK_PERI_THERM 2
++#define CLK_PERI_PWM1 3
++#define CLK_PERI_PWM2 4
++#define CLK_PERI_PWM3 5
++#define CLK_PERI_PWM4 6
++#define CLK_PERI_PWM5 7
++#define CLK_PERI_PWM6 8
++#define CLK_PERI_PWM7 9
++#define CLK_PERI_PWM 10
++#define CLK_PERI_USB0 11
++#define CLK_PERI_USB1 12
++#define CLK_PERI_AP_DMA 13
++#define CLK_PERI_MSDC30_0 14
++#define CLK_PERI_MSDC30_1 15
++#define CLK_PERI_MSDC30_2 16
++#define CLK_PERI_MSDC30_3 17
++#define CLK_PERI_NLI_ARB 18
++#define CLK_PERI_IRDA 19
++#define CLK_PERI_UART0 20
++#define CLK_PERI_UART1 21
++#define CLK_PERI_UART2 22
++#define CLK_PERI_UART3 23
++#define CLK_PERI_I2C0 24
++#define CLK_PERI_I2C1 25
++#define CLK_PERI_I2C2 26
++#define CLK_PERI_I2C3 27
++#define CLK_PERI_I2C4 28
++#define CLK_PERI_AUXADC 29
++#define CLK_PERI_SPI0 30
++#define CLK_PERI_I2C5 31
++#define CLK_PERI_NFIECC 32
++#define CLK_PERI_SPI 33
++#define CLK_PERI_IRRX 34
++#define CLK_PERI_I2C6 35
++#define CLK_PERI_UART0_SEL 36
++#define CLK_PERI_UART1_SEL 37
++#define CLK_PERI_UART2_SEL 38
++#define CLK_PERI_UART3_SEL 39
++#define CLK_PERI_NR_CLK 40
++
++#endif /* _DT_BINDINGS_CLK_MT8173_H */
+diff --git a/include/dt-bindings/reset-controller/mt8173-resets.h b/include/dt-bindings/reset-controller/mt8173-resets.h
+new file mode 100644
+index 0000000..9464b37
+--- /dev/null
++++ b/include/dt-bindings/reset-controller/mt8173-resets.h
+@@ -0,0 +1,63 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Flora Fu, MediaTek
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8173
++#define _DT_BINDINGS_RESET_CONTROLLER_MT8173
++
++/* INFRACFG resets */
++#define MT8173_INFRA_EMI_REG_RST 0
++#define MT8173_INFRA_DRAMC0_A0_RST 1
++#define MT8173_INFRA_APCIRQ_EINT_RST 3
++#define MT8173_INFRA_APXGPT_RST 4
++#define MT8173_INFRA_SCPSYS_RST 5
++#define MT8173_INFRA_KP_RST 6
++#define MT8173_INFRA_PMIC_WRAP_RST 7
++#define MT8173_INFRA_MPIP_RST 8
++#define MT8173_INFRA_CEC_RST 9
++#define MT8173_INFRA_EMI_RST 32
++#define MT8173_INFRA_DRAMC0_RST 34
++#define MT8173_INFRA_APMIXEDSYS_RST 35
++#define MT8173_INFRA_MIPI_DSI_RST 36
++#define MT8173_INFRA_TRNG_RST 37
++#define MT8173_INFRA_SYSIRQ_RST 38
++#define MT8173_INFRA_MIPI_CSI_RST 39
++#define MT8173_INFRA_GCE_FAXI_RST 40
++#define MT8173_INFRA_MMIOMMURST 47
++
++
++/* PERICFG resets */
++#define MT8173_PERI_UART0_SW_RST 0
++#define MT8173_PERI_UART1_SW_RST 1
++#define MT8173_PERI_UART2_SW_RST 2
++#define MT8173_PERI_UART3_SW_RST 3
++#define MT8173_PERI_IRRX_SW_RST 4
++#define MT8173_PERI_PWM_SW_RST 8
++#define MT8173_PERI_AUXADC_SW_RST 10
++#define MT8173_PERI_DMA_SW_RST 11
++#define MT8173_PERI_I2C6_SW_RST 13
++#define MT8173_PERI_NFI_SW_RST 14
++#define MT8173_PERI_THERM_SW_RST 16
++#define MT8173_PERI_MSDC2_SW_RST 17
++#define MT8173_PERI_MSDC3_SW_RST 18
++#define MT8173_PERI_MSDC0_SW_RST 19
++#define MT8173_PERI_MSDC1_SW_RST 20
++#define MT8173_PERI_I2C0_SW_RST 22
++#define MT8173_PERI_I2C1_SW_RST 23
++#define MT8173_PERI_I2C2_SW_RST 24
++#define MT8173_PERI_I2C3_SW_RST 25
++#define MT8173_PERI_I2C4_SW_RST 26
++#define MT8173_PERI_HDMI_SW_RST 29
++#define MT8173_PERI_SPI0_SW_RST 33
++
++#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8173 */
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0006-soc-mediatek-Add-infracfg-misc-driver-support.patch b/target/linux/mediatek/patches/0006-soc-mediatek-Add-infracfg-misc-driver-support.patch
new file mode 100644
index 0000000000..f47c19373e
--- /dev/null
+++ b/target/linux/mediatek/patches/0006-soc-mediatek-Add-infracfg-misc-driver-support.patch
@@ -0,0 +1,179 @@
+From d6d7a7dc1b7db2e3d496bf67b30abc894edbc4bd Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Tue, 9 Jun 2015 10:46:59 +0200
+Subject: [PATCH 06/76] soc: mediatek: Add infracfg misc driver support
+
+This adds support for some miscellaneous bits of the infracfg controller.
+The mtk_infracfg_set/clear_bus_protection functions are necessary for
+the scpsys power domain driver to handle the bus protection bits which
+are contained in the infacfg register space.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/soc/mediatek/Kconfig | 9 ++++
+ drivers/soc/mediatek/Makefile | 1 +
+ drivers/soc/mediatek/mtk-infracfg.c | 91 +++++++++++++++++++++++++++++++++
+ include/linux/soc/mediatek/infracfg.h | 26 ++++++++++
+ 4 files changed, 127 insertions(+)
+ create mode 100644 drivers/soc/mediatek/mtk-infracfg.c
+ create mode 100644 include/linux/soc/mediatek/infracfg.h
+
+diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
+index 3c18503..09da41e 100644
+--- a/drivers/soc/mediatek/Kconfig
++++ b/drivers/soc/mediatek/Kconfig
+@@ -1,6 +1,15 @@
+ #
+ # MediaTek SoC drivers
+ #
++config MTK_INFRACFG
++ bool "MediaTek INFRACFG Support"
++ depends on ARCH_MEDIATEK
++ select REGMAP
++ help
++ Say yes here to add support for the MediaTek INFRACFG controller. The
++ INFRACFG controller contains various infrastructure registers not
++ directly associated to any device.
++
+ config MTK_PMIC_WRAP
+ tristate "MediaTek PMIC Wrapper Support"
+ depends on ARCH_MEDIATEK
+diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
+index ecaf4de..3fa940f 100644
+--- a/drivers/soc/mediatek/Makefile
++++ b/drivers/soc/mediatek/Makefile
+@@ -1 +1,2 @@
++obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
+ obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
+diff --git a/drivers/soc/mediatek/mtk-infracfg.c b/drivers/soc/mediatek/mtk-infracfg.c
+new file mode 100644
+index 0000000..ca786e0
+--- /dev/null
++++ b/drivers/soc/mediatek/mtk-infracfg.c
+@@ -0,0 +1,91 @@
++/*
++ * Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/export.h>
++#include <linux/jiffies.h>
++#include <linux/regmap.h>
++#include <linux/soc/mediatek/infracfg.h>
++#include <asm/processor.h>
++
++#define INFRA_TOPAXI_PROTECTEN 0x0220
++#define INFRA_TOPAXI_PROTECTSTA1 0x0228
++
++/**
++ * mtk_infracfg_set_bus_protection - enable bus protection
++ * @regmap: The infracfg regmap
++ * @mask: The mask containing the protection bits to be enabled.
++ *
++ * This function enables the bus protection bits for disabled power
++ * domains so that the system does not hanf when some unit accesses the
++ * bus while in power down.
++ */
++int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask)
++{
++ unsigned long expired;
++ u32 val;
++ int ret;
++
++ regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, mask);
++
++ expired = jiffies + HZ;
++
++ while (1) {
++ ret = regmap_read(infracfg, INFRA_TOPAXI_PROTECTSTA1, &val);
++ if (ret)
++ return ret;
++
++ if ((val & mask) == mask)
++ break;
++
++ cpu_relax();
++ if (time_after(jiffies, expired))
++ return -EIO;
++ }
++
++ return 0;
++}
++
++/**
++ * mtk_infracfg_clear_bus_protection - disable bus protection
++ * @regmap: The infracfg regmap
++ * @mask: The mask containing the protection bits to be disabled.
++ *
++ * This function disables the bus protection bits previously enabled with
++ * mtk_infracfg_set_bus_protection.
++ */
++int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask)
++{
++ unsigned long expired;
++ int ret;
++
++ regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 0);
++
++ expired = jiffies + HZ;
++
++ while (1) {
++ u32 val;
++
++ ret = regmap_read(infracfg, INFRA_TOPAXI_PROTECTSTA1, &val);
++ if (ret)
++ return ret;
++
++ if (!(val & mask))
++ break;
++
++ cpu_relax();
++ if (time_after(jiffies, expired))
++ return -EIO;
++ }
++
++ return 0;
++}
+diff --git a/include/linux/soc/mediatek/infracfg.h b/include/linux/soc/mediatek/infracfg.h
+new file mode 100644
+index 0000000..a5714e9
+--- /dev/null
++++ b/include/linux/soc/mediatek/infracfg.h
+@@ -0,0 +1,26 @@
++#ifndef __SOC_MEDIATEK_INFRACFG_H
++#define __SOC_MEDIATEK_INFRACFG_H
++
++#define MT8173_TOP_AXI_PROT_EN_MCI_M2 BIT(0)
++#define MT8173_TOP_AXI_PROT_EN_MM_M0 BIT(1)
++#define MT8173_TOP_AXI_PROT_EN_MM_M1 BIT(2)
++#define MT8173_TOP_AXI_PROT_EN_MMAPB_S BIT(6)
++#define MT8173_TOP_AXI_PROT_EN_L2C_M2 BIT(9)
++#define MT8173_TOP_AXI_PROT_EN_L2SS_SMI BIT(11)
++#define MT8173_TOP_AXI_PROT_EN_L2SS_ADD BIT(12)
++#define MT8173_TOP_AXI_PROT_EN_CCI_M2 BIT(13)
++#define MT8173_TOP_AXI_PROT_EN_MFG_S BIT(14)
++#define MT8173_TOP_AXI_PROT_EN_PERI_M0 BIT(15)
++#define MT8173_TOP_AXI_PROT_EN_PERI_M1 BIT(16)
++#define MT8173_TOP_AXI_PROT_EN_DEBUGSYS BIT(17)
++#define MT8173_TOP_AXI_PROT_EN_CQ_DMA BIT(18)
++#define MT8173_TOP_AXI_PROT_EN_GCPU BIT(19)
++#define MT8173_TOP_AXI_PROT_EN_IOMMU BIT(20)
++#define MT8173_TOP_AXI_PROT_EN_MFG_M0 BIT(21)
++#define MT8173_TOP_AXI_PROT_EN_MFG_M1 BIT(22)
++#define MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT BIT(23)
++
++int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask);
++int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask);
++
++#endif /* __SOC_MEDIATEK_INFRACFG_H */
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0007-dt-bindings-soc-Add-documentation-for-the-MediaTek-S.patch b/target/linux/mediatek/patches/0007-dt-bindings-soc-Add-documentation-for-the-MediaTek-S.patch
new file mode 100644
index 0000000000..f7bdbd6e0c
--- /dev/null
+++ b/target/linux/mediatek/patches/0007-dt-bindings-soc-Add-documentation-for-the-MediaTek-S.patch
@@ -0,0 +1,57 @@
+From 06a1fd8a198771abc7c5badcf43a49a715ba4c76 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Tue, 9 Jun 2015 10:47:00 +0200
+Subject: [PATCH 07/76] dt-bindings: soc: Add documentation for the MediaTek
+ SCPSYS unit
+
+This adds documentation for the MediaTek SCPSYS unit found in MT8173 SoCs.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ .../devicetree/bindings/soc/mediatek/scpsys.txt | 34 ++++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
+
+diff --git a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
+new file mode 100644
+index 0000000..87f2091
+--- /dev/null
++++ b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
+@@ -0,0 +1,34 @@
++MediaTek SCPSYS
++===============
++
++The System Control Processor System (SCPSYS) has several power management
++related tasks in the system. The tasks include thermal measurement, dynamic
++voltage frequency scaling (DVFS), interrupt filter and lowlevel sleep control.
++The System Power Manager (SPM) inside the SCPSYS is for the MTCMOS power
++domain control.
++
++The driver implements the Generic PM domain bindings described in
++power/power_domain.txt. It provides the power domains defined in
++include/dt-bindings/power/mt8173-power.h.
++
++Required properties:
++- compatible: Must be "mediatek,mt8173-scpsys"
++- #power-domain-cells: Must be 1
++- reg: Address range of the SCPSYS unit
++- infracfg: must contain a phandle to the infracfg controller
++
++Example:
++
++ scpsys: scpsys@10006000 {
++ #power-domain-cells = <1>;
++ compatible = "mediatek,mt8173-scpsys";
++ reg = <0 0x10006000 0 0x1000>;
++ infracfg = <&infracfg>;
++ };
++
++Example consumer:
++
++ afe: mt8173-afe-pcm@11220000 {
++ compatible = "mediatek,mt8173-afe-pcm";
++ power-domains = <&scpsys MT8173_POWER_DOMAIN_AUDIO>;
++ };
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0008-soc-Mediatek-Add-SCPSYS-power-domain-driver.patch b/target/linux/mediatek/patches/0008-soc-Mediatek-Add-SCPSYS-power-domain-driver.patch
new file mode 100644
index 0000000000..bbf5ad135e
--- /dev/null
+++ b/target/linux/mediatek/patches/0008-soc-Mediatek-Add-SCPSYS-power-domain-driver.patch
@@ -0,0 +1,573 @@
+From 04e2e2a895a95dc9e75403c2e8ea190dce9dc387 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Tue, 9 Jun 2015 10:47:01 +0200
+Subject: [PATCH 08/76] soc: Mediatek: Add SCPSYS power domain driver
+
+This adds a power domain driver for the Mediatek SCPSYS unit.
+
+The System Control Processor System (SCPSYS) has several power
+management related tasks in the system. The tasks include thermal
+measurement, dynamic voltage frequency scaling (DVFS), interrupt
+filter and lowlevel sleep control. The System Power Manager (SPM)
+inside the SCPSYS is for the MTCMOS power domain control.
+
+For now this driver only adds power domain support, the more
+advanced features are not yet supported. The driver implements
+the generic PM domain device tree bindings, the first user will
+most likely be the Mediatek AFE audio driver.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/soc/mediatek/Kconfig | 9 +
+ drivers/soc/mediatek/Makefile | 1 +
+ drivers/soc/mediatek/mtk-scpsys.c | 490 ++++++++++++++++++++++++++++++
+ include/dt-bindings/power/mt8173-power.h | 15 +
+ 4 files changed, 515 insertions(+)
+ create mode 100644 drivers/soc/mediatek/mtk-scpsys.c
+ create mode 100644 include/dt-bindings/power/mt8173-power.h
+
+diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
+index 09da41e..2dc5d90 100644
+--- a/drivers/soc/mediatek/Kconfig
++++ b/drivers/soc/mediatek/Kconfig
+@@ -19,3 +19,12 @@ config MTK_PMIC_WRAP
+ Say yes here to add support for MediaTek PMIC Wrapper found
+ on different MediaTek SoCs. The PMIC wrapper is a proprietary
+ hardware to connect the PMIC.
++
++config MTK_SCPSYS
++ bool "MediaTek SCPSYS Support"
++ depends on ARCH_MEDIATEK || COMPILE_TEST
++ select REGMAP
++ select MTK_INFRACFG
++ help
++ Say yes here to add support for the MediaTek SCPSYS power domain
++ driver.
+diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
+index 3fa940f..12998b0 100644
+--- a/drivers/soc/mediatek/Makefile
++++ b/drivers/soc/mediatek/Makefile
+@@ -1,2 +1,3 @@
+ obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
+ obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
++obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
+diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
+new file mode 100644
+index 0000000..b9eed37
+--- /dev/null
++++ b/drivers/soc/mediatek/mtk-scpsys.c
+@@ -0,0 +1,490 @@
++/*
++ * Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/mfd/syscon.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/pm_domain.h>
++#include <linux/regmap.h>
++#include <linux/soc/mediatek/infracfg.h>
++#include <dt-bindings/power/mt8173-power.h>
++
++#define SPM_VDE_PWR_CON 0x0210
++#define SPM_MFG_PWR_CON 0x0214
++#define SPM_VEN_PWR_CON 0x0230
++#define SPM_ISP_PWR_CON 0x0238
++#define SPM_DIS_PWR_CON 0x023c
++#define SPM_VEN2_PWR_CON 0x0298
++#define SPM_AUDIO_PWR_CON 0x029c
++#define SPM_MFG_2D_PWR_CON 0x02c0
++#define SPM_MFG_ASYNC_PWR_CON 0x02c4
++#define SPM_USB_PWR_CON 0x02cc
++#define SPM_PWR_STATUS 0x060c
++#define SPM_PWR_STATUS_2ND 0x0610
++
++#define PWR_RST_B_BIT BIT(0)
++#define PWR_ISO_BIT BIT(1)
++#define PWR_ON_BIT BIT(2)
++#define PWR_ON_2ND_BIT BIT(3)
++#define PWR_CLK_DIS_BIT BIT(4)
++
++#define PWR_STATUS_DISP BIT(3)
++#define PWR_STATUS_MFG BIT(4)
++#define PWR_STATUS_ISP BIT(5)
++#define PWR_STATUS_VDEC BIT(7)
++#define PWR_STATUS_VENC_LT BIT(20)
++#define PWR_STATUS_VENC BIT(21)
++#define PWR_STATUS_MFG_2D BIT(22)
++#define PWR_STATUS_MFG_ASYNC BIT(23)
++#define PWR_STATUS_AUDIO BIT(24)
++#define PWR_STATUS_USB BIT(25)
++
++enum clk_id {
++ MT8173_CLK_NONE,
++ MT8173_CLK_MM,
++ MT8173_CLK_MFG,
++ MT8173_CLK_MAX = MT8173_CLK_MFG,
++};
++
++struct scp_domain_data {
++ const char *name;
++ u32 sta_mask;
++ int ctl_offs;
++ u32 sram_pdn_bits;
++ u32 sram_pdn_ack_bits;
++ u32 bus_prot_mask;
++ enum clk_id clk_id;
++};
++
++static const struct scp_domain_data scp_domain_data[] __initconst = {
++ [MT8173_POWER_DOMAIN_VDEC] = {
++ .name = "vdec",
++ .sta_mask = PWR_STATUS_VDEC,
++ .ctl_offs = SPM_VDE_PWR_CON,
++ .sram_pdn_bits = GENMASK(11, 8),
++ .sram_pdn_ack_bits = GENMASK(12, 12),
++ .clk_id = MT8173_CLK_MM,
++ },
++ [MT8173_POWER_DOMAIN_VENC] = {
++ .name = "venc",
++ .sta_mask = PWR_STATUS_VENC,
++ .ctl_offs = SPM_VEN_PWR_CON,
++ .sram_pdn_bits = GENMASK(11, 8),
++ .sram_pdn_ack_bits = GENMASK(15, 12),
++ .clk_id = MT8173_CLK_MM,
++ },
++ [MT8173_POWER_DOMAIN_ISP] = {
++ .name = "isp",
++ .sta_mask = PWR_STATUS_ISP,
++ .ctl_offs = SPM_ISP_PWR_CON,
++ .sram_pdn_bits = GENMASK(11, 8),
++ .sram_pdn_ack_bits = GENMASK(13, 12),
++ .clk_id = MT8173_CLK_MM,
++ },
++ [MT8173_POWER_DOMAIN_MM] = {
++ .name = "mm",
++ .sta_mask = PWR_STATUS_DISP,
++ .ctl_offs = SPM_DIS_PWR_CON,
++ .sram_pdn_bits = GENMASK(11, 8),
++ .sram_pdn_ack_bits = GENMASK(12, 12),
++ .clk_id = MT8173_CLK_MM,
++ .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 |
++ MT8173_TOP_AXI_PROT_EN_MM_M1,
++ },
++ [MT8173_POWER_DOMAIN_VENC_LT] = {
++ .name = "venc_lt",
++ .sta_mask = PWR_STATUS_VENC_LT,
++ .ctl_offs = SPM_VEN2_PWR_CON,
++ .sram_pdn_bits = GENMASK(11, 8),
++ .sram_pdn_ack_bits = GENMASK(15, 12),
++ .clk_id = MT8173_CLK_MM,
++ },
++ [MT8173_POWER_DOMAIN_AUDIO] = {
++ .name = "audio",
++ .sta_mask = PWR_STATUS_AUDIO,
++ .ctl_offs = SPM_AUDIO_PWR_CON,
++ .sram_pdn_bits = GENMASK(11, 8),
++ .sram_pdn_ack_bits = GENMASK(15, 12),
++ .clk_id = MT8173_CLK_NONE,
++ },
++ [MT8173_POWER_DOMAIN_USB] = {
++ .name = "usb",
++ .sta_mask = PWR_STATUS_USB,
++ .ctl_offs = SPM_USB_PWR_CON,
++ .sram_pdn_bits = GENMASK(11, 8),
++ .sram_pdn_ack_bits = GENMASK(15, 12),
++ .clk_id = MT8173_CLK_NONE,
++ },
++ [MT8173_POWER_DOMAIN_MFG_ASYNC] = {
++ .name = "mfg_async",
++ .sta_mask = PWR_STATUS_MFG_ASYNC,
++ .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
++ .sram_pdn_bits = GENMASK(11, 8),
++ .sram_pdn_ack_bits = 0,
++ .clk_id = MT8173_CLK_MFG,
++ },
++ [MT8173_POWER_DOMAIN_MFG_2D] = {
++ .name = "mfg_2d",
++ .sta_mask = PWR_STATUS_MFG_2D,
++ .ctl_offs = SPM_MFG_2D_PWR_CON,
++ .sram_pdn_bits = GENMASK(11, 8),
++ .sram_pdn_ack_bits = GENMASK(13, 12),
++ .clk_id = MT8173_CLK_NONE,
++ },
++ [MT8173_POWER_DOMAIN_MFG] = {
++ .name = "mfg",
++ .sta_mask = PWR_STATUS_MFG,
++ .ctl_offs = SPM_MFG_PWR_CON,
++ .sram_pdn_bits = GENMASK(13, 8),
++ .sram_pdn_ack_bits = GENMASK(21, 16),
++ .clk_id = MT8173_CLK_NONE,
++ .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S |
++ MT8173_TOP_AXI_PROT_EN_MFG_M0 |
++ MT8173_TOP_AXI_PROT_EN_MFG_M1 |
++ MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT,
++ },
++};
++
++#define NUM_DOMAINS ARRAY_SIZE(scp_domain_data)
++
++struct scp;
++
++struct scp_domain {
++ struct generic_pm_domain genpd;
++ struct scp *scp;
++ struct clk *clk;
++ u32 sta_mask;
++ void __iomem *ctl_addr;
++ u32 sram_pdn_bits;
++ u32 sram_pdn_ack_bits;
++ u32 bus_prot_mask;
++};
++
++struct scp {
++ struct scp_domain domains[NUM_DOMAINS];
++ struct genpd_onecell_data pd_data;
++ struct device *dev;
++ void __iomem *base;
++ struct regmap *infracfg;
++ struct clk *clk[MT8173_CLK_MAX];
++};
++
++static int scpsys_domain_is_on(struct scp_domain *scpd)
++{
++ struct scp *scp = scpd->scp;
++
++ u32 status = readl(scp->base + SPM_PWR_STATUS) & scpd->sta_mask;
++ u32 status2 = readl(scp->base + SPM_PWR_STATUS_2ND) & scpd->sta_mask;
++
++ /*
++ * A domain is on when both status bits are set. If only one is set
++ * return an error. This happens while powering up a domain
++ */
++
++ if (status && status2)
++ return true;
++ if (!status && !status2)
++ return false;
++
++ return -EINVAL;
++}
++
++static int scpsys_power_on(struct generic_pm_domain *genpd)
++{
++ struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
++ struct scp *scp = scpd->scp;
++ unsigned long timeout;
++ bool expired;
++ void __iomem *ctl_addr = scpd->ctl_addr;
++ u32 sram_pdn_ack = scpd->sram_pdn_ack_bits;
++ u32 val;
++ int ret;
++
++ if (scpd->clk) {
++ ret = clk_prepare_enable(scpd->clk);
++ if (ret)
++ return ret;
++ }
++
++ val = readl(ctl_addr);
++ val |= PWR_ON_BIT;
++ writel(val, ctl_addr);
++ val |= PWR_ON_2ND_BIT;
++ writel(val, ctl_addr);
++
++ /* wait until PWR_ACK = 1 */
++ timeout = jiffies + HZ;
++ expired = false;
++ while (1) {
++ ret = scpsys_domain_is_on(scpd);
++ if (ret > 0)
++ break;
++
++ if (expired) {
++ ret = -ETIMEDOUT;
++ goto out;
++ }
++
++ cpu_relax();
++
++ if (time_after(jiffies, timeout))
++ expired = true;
++ }
++
++ val &= ~PWR_CLK_DIS_BIT;
++ writel(val, ctl_addr);
++
++ val &= ~PWR_ISO_BIT;
++ writel(val, ctl_addr);
++
++ val |= PWR_RST_B_BIT;
++ writel(val, ctl_addr);
++
++ val &= ~scpd->sram_pdn_bits;
++ writel(val, ctl_addr);
++
++ /* wait until SRAM_PDN_ACK all 0 */
++ timeout = jiffies + HZ;
++ expired = false;
++ while (sram_pdn_ack && (readl(ctl_addr) & sram_pdn_ack)) {
++
++ if (expired) {
++ ret = -ETIMEDOUT;
++ goto out;
++ }
++
++ cpu_relax();
++
++ if (time_after(jiffies, timeout))
++ expired = true;
++ }
++
++ if (scpd->bus_prot_mask) {
++ ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
++ scpd->bus_prot_mask);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++out:
++ dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
++
++ return ret;
++}
++
++static int scpsys_power_off(struct generic_pm_domain *genpd)
++{
++ struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
++ struct scp *scp = scpd->scp;
++ unsigned long timeout;
++ bool expired;
++ void __iomem *ctl_addr = scpd->ctl_addr;
++ u32 pdn_ack = scpd->sram_pdn_ack_bits;
++ u32 val;
++ int ret;
++
++ if (scpd->bus_prot_mask) {
++ ret = mtk_infracfg_set_bus_protection(scp->infracfg,
++ scpd->bus_prot_mask);
++ if (ret)
++ return ret;
++ }
++
++ val = readl(ctl_addr);
++ val |= scpd->sram_pdn_bits;
++ writel(val, ctl_addr);
++
++ /* wait until SRAM_PDN_ACK all 1 */
++ timeout = jiffies + HZ;
++ expired = false;
++ while (pdn_ack && (readl(ctl_addr) & pdn_ack) != pdn_ack) {
++ if (expired) {
++ ret = -ETIMEDOUT;
++ goto out;
++ }
++
++ cpu_relax();
++
++ if (time_after(jiffies, timeout))
++ expired = true;
++ }
++
++ val |= PWR_ISO_BIT;
++ writel(val, ctl_addr);
++
++ val &= ~PWR_RST_B_BIT;
++ writel(val, ctl_addr);
++
++ val |= PWR_CLK_DIS_BIT;
++ writel(val, ctl_addr);
++
++ val &= ~PWR_ON_BIT;
++ writel(val, ctl_addr);
++
++ val &= ~PWR_ON_2ND_BIT;
++ writel(val, ctl_addr);
++
++ /* wait until PWR_ACK = 0 */
++ timeout = jiffies + HZ;
++ expired = false;
++ while (1) {
++ ret = scpsys_domain_is_on(scpd);
++ if (ret == 0)
++ break;
++
++ if (expired) {
++ ret = -ETIMEDOUT;
++ goto out;
++ }
++
++ cpu_relax();
++
++ if (time_after(jiffies, timeout))
++ expired = true;
++ }
++
++ if (scpd->clk)
++ clk_disable_unprepare(scpd->clk);
++
++ return 0;
++
++out:
++ dev_err(scp->dev, "Failed to power off domain %s\n", genpd->name);
++
++ return ret;
++}
++
++static int __init scpsys_probe(struct platform_device *pdev)
++{
++ struct genpd_onecell_data *pd_data;
++ struct resource *res;
++ int i, ret;
++ struct scp *scp;
++
++ scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL);
++ if (!scp)
++ return -ENOMEM;
++
++ scp->dev = &pdev->dev;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ scp->base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(scp->base))
++ return PTR_ERR(scp->base);
++
++ pd_data = &scp->pd_data;
++
++ pd_data->domains = devm_kzalloc(&pdev->dev,
++ sizeof(*pd_data->domains) * NUM_DOMAINS, GFP_KERNEL);
++ if (!pd_data->domains)
++ return -ENOMEM;
++
++ scp->clk[MT8173_CLK_MM] = devm_clk_get(&pdev->dev, "mm");
++ if (IS_ERR(scp->clk[MT8173_CLK_MM])) {
++ dev_err(&pdev->dev, "Failed to get mm clk: %ld\n",
++ PTR_ERR(scp->clk[MT8173_CLK_MM]));
++ return PTR_ERR(scp->clk[MT8173_CLK_MM]);
++ }
++
++ scp->clk[MT8173_CLK_MFG] = devm_clk_get(&pdev->dev, "mfg");
++ if (IS_ERR(scp->clk[MT8173_CLK_MFG])) {
++ dev_err(&pdev->dev, "Failed to get mfg clk: %ld\n",
++ PTR_ERR(scp->clk[MT8173_CLK_MFG]));
++ return PTR_ERR(scp->clk[MT8173_CLK_MFG]);
++ }
++
++ scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
++ "infracfg");
++ if (IS_ERR(scp->infracfg)) {
++ dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n",
++ PTR_ERR(scp->infracfg));
++ return PTR_ERR(scp->infracfg);
++ }
++
++ pd_data->num_domains = NUM_DOMAINS;
++
++ for (i = 0; i < NUM_DOMAINS; i++) {
++ struct scp_domain *scpd = &scp->domains[i];
++ struct generic_pm_domain *genpd = &scpd->genpd;
++ const struct scp_domain_data *data = &scp_domain_data[i];
++
++ pd_data->domains[i] = genpd;
++ scpd->scp = scp;
++
++ scpd->sta_mask = data->sta_mask;
++ scpd->ctl_addr = scp->base + data->ctl_offs;
++ scpd->sram_pdn_bits = data->sram_pdn_bits;
++ scpd->sram_pdn_ack_bits = data->sram_pdn_ack_bits;
++ scpd->bus_prot_mask = data->bus_prot_mask;
++ if (data->clk_id != MT8173_CLK_NONE)
++ scpd->clk = scp->clk[data->clk_id];
++
++ genpd->name = data->name;
++ genpd->power_off = scpsys_power_off;
++ genpd->power_on = scpsys_power_on;
++
++ /*
++ * Initially turn on all domains to make the domains usable
++ * with !CONFIG_PM and to get the hardware in sync with the
++ * software. The unused domains will be switched off during
++ * late_init time.
++ */
++ genpd->power_on(genpd);
++
++ pm_genpd_init(genpd, NULL, false);
++ }
++
++ /*
++ * We are not allowed to fail here since there is no way to unregister
++ * a power domain. Once registered above we have to keep the domains
++ * valid.
++ */
++
++ ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_ASYNC],
++ pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D]);
++ if (ret && IS_ENABLED(CONFIG_PM))
++ dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
++
++ ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D],
++ pd_data->domains[MT8173_POWER_DOMAIN_MFG]);
++ if (ret && IS_ENABLED(CONFIG_PM))
++ dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
++
++ ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data);
++ if (ret)
++ dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret);
++
++ return 0;
++}
++
++static const struct of_device_id of_scpsys_match_tbl[] = {
++ {
++ .compatible = "mediatek,mt8173-scpsys",
++ }, {
++ /* sentinel */
++ }
++};
++
++static struct platform_driver scpsys_drv = {
++ .driver = {
++ .name = "mtk-scpsys",
++ .owner = THIS_MODULE,
++ .of_match_table = of_match_ptr(of_scpsys_match_tbl),
++ },
++};
++
++module_platform_driver_probe(scpsys_drv, scpsys_probe);
+diff --git a/include/dt-bindings/power/mt8173-power.h b/include/dt-bindings/power/mt8173-power.h
+new file mode 100644
+index 0000000..b34cee9
+--- /dev/null
++++ b/include/dt-bindings/power/mt8173-power.h
+@@ -0,0 +1,15 @@
++#ifndef _DT_BINDINGS_POWER_MT8183_POWER_H
++#define _DT_BINDINGS_POWER_MT8183_POWER_H
++
++#define MT8173_POWER_DOMAIN_VDEC 0
++#define MT8173_POWER_DOMAIN_VENC 1
++#define MT8173_POWER_DOMAIN_ISP 2
++#define MT8173_POWER_DOMAIN_MM 3
++#define MT8173_POWER_DOMAIN_VENC_LT 4
++#define MT8173_POWER_DOMAIN_AUDIO 5
++#define MT8173_POWER_DOMAIN_USB 6
++#define MT8173_POWER_DOMAIN_MFG_ASYNC 7
++#define MT8173_POWER_DOMAIN_MFG_2D 8
++#define MT8173_POWER_DOMAIN_MFG 9
++
++#endif /* _DT_BINDINGS_POWER_MT8183_POWER_H */
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0009-dt-bindings-ARM-Mediatek-Document-devicetree-binding.patch b/target/linux/mediatek/patches/0009-dt-bindings-ARM-Mediatek-Document-devicetree-binding.patch
new file mode 100644
index 0000000000..6d7fd47577
--- /dev/null
+++ b/target/linux/mediatek/patches/0009-dt-bindings-ARM-Mediatek-Document-devicetree-binding.patch
@@ -0,0 +1,154 @@
+From 87043a64dd5185dc076b3c3ab2e421b3a8c47798 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Thu, 23 Apr 2015 10:35:43 +0200
+Subject: [PATCH 09/76] dt-bindings: ARM: Mediatek: Document devicetree
+ bindings for clock/reset controllers
+
+This adds the binding documentation for the apmixedsys, perisys and
+infracfg controllers found on Mediatek SoCs.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ .../bindings/arm/mediatek/mediatek,apmixedsys.txt | 23 +++++++++++++++
+ .../bindings/arm/mediatek/mediatek,infracfg.txt | 30 ++++++++++++++++++++
+ .../bindings/arm/mediatek/mediatek,pericfg.txt | 30 ++++++++++++++++++++
+ .../bindings/arm/mediatek/mediatek,topckgen.txt | 23 +++++++++++++++
+ 4 files changed, 106 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
+
+diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
+new file mode 100644
+index 0000000..5af6d73
+--- /dev/null
++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
+@@ -0,0 +1,23 @@
++Mediatek apmixedsys controller
++==============================
++
++The Mediatek apmixedsys controller provides the PLLs to the system.
++
++Required Properties:
++
++- compatible: Should be:
++ - "mediatek,mt8135-apmixedsys"
++ - "mediatek,mt8173-apmixedsys"
++- #clock-cells: Must be 1
++
++The apmixedsys controller uses the common clk binding from
++Documentation/devicetree/bindings/clock/clock-bindings.txt
++The available clocks are defined in dt-bindings/clock/mt*-clk.h.
++
++Example:
++
++apmixedsys: apmixedsys@10209000 {
++ compatible = "mediatek,mt8173-apmixedsys";
++ reg = <0 0x10209000 0 0x1000>;
++ #clock-cells = <1>;
++};
+diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
+new file mode 100644
+index 0000000..684da473
+--- /dev/null
++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
+@@ -0,0 +1,30 @@
++Mediatek infracfg controller
++============================
++
++The Mediatek infracfg controller provides various clocks and reset
++outputs to the system.
++
++Required Properties:
++
++- compatible: Should be:
++ - "mediatek,mt8135-infracfg", "syscon"
++ - "mediatek,mt8173-infracfg", "syscon"
++- #clock-cells: Must be 1
++- #reset-cells: Must be 1
++
++The infracfg controller uses the common clk binding from
++Documentation/devicetree/bindings/clock/clock-bindings.txt
++The available clocks are defined in dt-bindings/clock/mt*-clk.h.
++Also it uses the common reset controller binding from
++Documentation/devicetree/bindings/reset/reset.txt.
++The available reset outputs are defined in
++dt-bindings/reset-controller/mt*-resets.h
++
++Example:
++
++infracfg: infracfg@10001000 {
++ compatible = "mediatek,mt8173-infracfg", "syscon";
++ reg = <0 0x10001000 0 0x1000>;
++ #clock-cells = <1>;
++ #reset-cells = <1>;
++};
+diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
+new file mode 100644
+index 0000000..fdb45c6
+--- /dev/null
++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
+@@ -0,0 +1,30 @@
++Mediatek pericfg controller
++===========================
++
++The Mediatek pericfg controller provides various clocks and reset
++outputs to the system.
++
++Required Properties:
++
++- compatible: Should be:
++ - "mediatek,mt8135-pericfg", "syscon"
++ - "mediatek,mt8173-pericfg", "syscon"
++- #clock-cells: Must be 1
++- #reset-cells: Must be 1
++
++The pericfg controller uses the common clk binding from
++Documentation/devicetree/bindings/clock/clock-bindings.txt
++The available clocks are defined in dt-bindings/clock/mt*-clk.h.
++Also it uses the common reset controller binding from
++Documentation/devicetree/bindings/reset/reset.txt.
++The available reset outputs are defined in
++dt-bindings/reset-controller/mt*-resets.h
++
++Example:
++
++pericfg: pericfg@10003000 {
++ compatible = "mediatek,mt8173-pericfg", "syscon";
++ reg = <0 0x10003000 0 0x1000>;
++ #clock-cells = <1>;
++ #reset-cells = <1>;
++};
+diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
+new file mode 100644
+index 0000000..a425248
+--- /dev/null
++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
+@@ -0,0 +1,23 @@
++Mediatek topckgen controller
++============================
++
++The Mediatek topckgen controller provides various clocks to the system.
++
++Required Properties:
++
++- compatible: Should be:
++ - "mediatek,mt8135-topckgen"
++ - "mediatek,mt8173-topckgen"
++- #clock-cells: Must be 1
++
++The topckgen controller uses the common clk binding from
++Documentation/devicetree/bindings/clock/clock-bindings.txt
++The available clocks are defined in dt-bindings/clock/mt*-clk.h.
++
++Example:
++
++topckgen: topckgen@10000000 {
++ compatible = "mediatek,mt8173-topckgen";
++ reg = <0 0x10000000 0 0x1000>;
++ #clock-cells = <1>;
++};
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0010-thermal-consistently-use-int-for-temperatures.patch b/target/linux/mediatek/patches/0010-thermal-consistently-use-int-for-temperatures.patch
new file mode 100644
index 0000000000..2aa83abb93
--- /dev/null
+++ b/target/linux/mediatek/patches/0010-thermal-consistently-use-int-for-temperatures.patch
@@ -0,0 +1,1155 @@
+From 29e6031548373b9e7ec0c17e85da6a4cf4fee7f5 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:29 +0200
+Subject: [PATCH 10/76] thermal: consistently use int for temperatures
+
+The thermal code uses int, long and unsigned long for temperatures
+in different places. Using an unsigned type limits the thermal framework
+to positive temperatures without need. 'long' is 64bit on several
+architectures which is not needed. Consistently use a plain 'int'
+for temperatures.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/acpi/thermal.c | 12 ++++-----
+ drivers/hwmon/lm75.c | 2 +-
+ drivers/hwmon/ntc_thermistor.c | 2 +-
+ drivers/hwmon/tmp102.c | 2 +-
+ drivers/input/touchscreen/sun4i-ts.c | 8 +++---
+ drivers/platform/x86/acerhdf.c | 9 +++----
+ drivers/power/power_supply_core.c | 2 +-
+ drivers/thermal/armada_thermal.c | 2 +-
+ drivers/thermal/db8500_thermal.c | 7 +++--
+ drivers/thermal/dove_thermal.c | 2 +-
+ drivers/thermal/fair_share.c | 2 +-
+ drivers/thermal/gov_bang_bang.c | 5 ++--
+ drivers/thermal/imx_thermal.c | 27 ++++++++++----------
+ .../thermal/int340x_thermal/int340x_thermal_zone.c | 10 ++++----
+ .../thermal/int340x_thermal/int340x_thermal_zone.h | 8 +++---
+ drivers/thermal/intel_soc_dts_thermal.c | 7 +++--
+ drivers/thermal/of-thermal.c | 14 +++++-----
+ drivers/thermal/rcar_thermal.c | 7 +++--
+ drivers/thermal/rockchip_thermal.c | 10 ++++----
+ drivers/thermal/samsung/exynos_tmu.c | 19 +++++++-------
+ drivers/thermal/spear_thermal.c | 2 +-
+ drivers/thermal/st/st_thermal.c | 5 ++--
+ drivers/thermal/step_wise.c | 4 +--
+ drivers/thermal/tegra_soctherm.c | 4 +--
+ drivers/thermal/thermal_core.c | 26 +++++++++----------
+ drivers/thermal/thermal_hwmon.c | 10 ++++----
+ drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 10 ++++----
+ drivers/thermal/x86_pkg_temp_thermal.c | 10 ++++----
+ include/linux/thermal.h | 26 ++++++++-----------
+ 29 files changed, 120 insertions(+), 134 deletions(-)
+
+diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
+index d24fa19..68bff60 100644
+--- a/drivers/acpi/thermal.c
++++ b/drivers/acpi/thermal.c
+@@ -529,8 +529,7 @@ static void acpi_thermal_check(void *data)
+
+ /* sys I/F for generic thermal sysfs support */
+
+-static int thermal_get_temp(struct thermal_zone_device *thermal,
+- unsigned long *temp)
++static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp)
+ {
+ struct acpi_thermal *tz = thermal->devdata;
+ int result;
+@@ -637,7 +636,7 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal,
+ }
+
+ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
+- int trip, unsigned long *temp)
++ int trip, int *temp)
+ {
+ struct acpi_thermal *tz = thermal->devdata;
+ int i;
+@@ -690,7 +689,8 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
+ }
+
+ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
+- unsigned long *temperature) {
++ int *temperature)
++{
+ struct acpi_thermal *tz = thermal->devdata;
+
+ if (tz->trips.critical.flags.valid) {
+@@ -713,8 +713,8 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
+ return -EINVAL;
+
+ if (type == THERMAL_TRIP_ACTIVE) {
+- unsigned long trip_temp;
+- unsigned long temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
++ int trip_temp;
++ int temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
+ tz->temperature, tz->kelvin_offset);
+ if (thermal_get_trip_temp(thermal, trip, &trip_temp))
+ return -EINVAL;
+diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
+index fe41d5a..e4e57bb 100644
+--- a/drivers/hwmon/lm75.c
++++ b/drivers/hwmon/lm75.c
+@@ -104,7 +104,7 @@ static inline long lm75_reg_to_mc(s16 temp, u8 resolution)
+
+ /* sysfs attributes for hwmon */
+
+-static int lm75_read_temp(void *dev, long *temp)
++static int lm75_read_temp(void *dev, int *temp)
+ {
+ struct lm75_data *data = lm75_update_device(dev);
+
+diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
+index 6880011..3d9eab9 100644
+--- a/drivers/hwmon/ntc_thermistor.c
++++ b/drivers/hwmon/ntc_thermistor.c
+@@ -439,7 +439,7 @@ static int ntc_thermistor_get_ohm(struct ntc_data *data)
+ return -EINVAL;
+ }
+
+-static int ntc_read_temp(void *dev, long *temp)
++static int ntc_read_temp(void *dev, int *temp)
+ {
+ struct ntc_data *data = dev_get_drvdata(dev);
+ int ohm;
+diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
+index 9da2735..6548262 100644
+--- a/drivers/hwmon/tmp102.c
++++ b/drivers/hwmon/tmp102.c
+@@ -98,7 +98,7 @@ static struct tmp102 *tmp102_update_device(struct device *dev)
+ return tmp102;
+ }
+
+-static int tmp102_read_temp(void *dev, long *temp)
++static int tmp102_read_temp(void *dev, int *temp)
+ {
+ struct tmp102 *tmp102 = tmp102_update_device(dev);
+
+diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c
+index c011699..4857943 100644
+--- a/drivers/input/touchscreen/sun4i-ts.c
++++ b/drivers/input/touchscreen/sun4i-ts.c
+@@ -191,7 +191,7 @@ static void sun4i_ts_close(struct input_dev *dev)
+ writel(TEMP_IRQ_EN(1), ts->base + TP_INT_FIFOC);
+ }
+
+-static int sun4i_get_temp(const struct sun4i_ts_data *ts, long *temp)
++static int sun4i_get_temp(const struct sun4i_ts_data *ts, int *temp)
+ {
+ /* No temp_data until the first irq */
+ if (ts->temp_data == -1)
+@@ -202,7 +202,7 @@ static int sun4i_get_temp(const struct sun4i_ts_data *ts, long *temp)
+ return 0;
+ }
+
+-static int sun4i_get_tz_temp(void *data, long *temp)
++static int sun4i_get_tz_temp(void *data, int *temp)
+ {
+ return sun4i_get_temp(data, temp);
+ }
+@@ -215,14 +215,14 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+ {
+ struct sun4i_ts_data *ts = dev_get_drvdata(dev);
+- long temp;
++ int temp;
+ int error;
+
+ error = sun4i_get_temp(ts, &temp);
+ if (error)
+ return error;
+
+- return sprintf(buf, "%ld\n", temp);
++ return sprintf(buf, "%d\n", temp);
+ }
+
+ static ssize_t show_temp_label(struct device *dev,
+diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
+index 594c918..f2ce63c 100644
+--- a/drivers/platform/x86/acerhdf.c
++++ b/drivers/platform/x86/acerhdf.c
+@@ -346,8 +346,7 @@ static void acerhdf_check_param(struct thermal_zone_device *thermal)
+ * as late as the polling interval is since we can't do that in the respective
+ * accessors of the module parameters.
+ */
+-static int acerhdf_get_ec_temp(struct thermal_zone_device *thermal,
+- unsigned long *t)
++static int acerhdf_get_ec_temp(struct thermal_zone_device *thermal, int *t)
+ {
+ int temp, err = 0;
+
+@@ -452,7 +451,7 @@ static int acerhdf_get_trip_type(struct thermal_zone_device *thermal, int trip,
+ }
+
+ static int acerhdf_get_trip_hyst(struct thermal_zone_device *thermal, int trip,
+- unsigned long *temp)
++ int *temp)
+ {
+ if (trip != 0)
+ return -EINVAL;
+@@ -463,7 +462,7 @@ static int acerhdf_get_trip_hyst(struct thermal_zone_device *thermal, int trip,
+ }
+
+ static int acerhdf_get_trip_temp(struct thermal_zone_device *thermal, int trip,
+- unsigned long *temp)
++ int *temp)
+ {
+ if (trip == 0)
+ *temp = fanon;
+@@ -476,7 +475,7 @@ static int acerhdf_get_trip_temp(struct thermal_zone_device *thermal, int trip,
+ }
+
+ static int acerhdf_get_crit_temp(struct thermal_zone_device *thermal,
+- unsigned long *temperature)
++ int *temperature)
+ {
+ *temperature = ACERHDF_TEMP_CRIT;
+ return 0;
+diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
+index 2ed4a4a..87e2fd1 100644
+--- a/drivers/power/power_supply_core.c
++++ b/drivers/power/power_supply_core.c
+@@ -492,7 +492,7 @@ EXPORT_SYMBOL_GPL(power_supply_unreg_notifier);
+
+ #ifdef CONFIG_THERMAL
+ static int power_supply_read_temp(struct thermal_zone_device *tzd,
+- unsigned long *temp)
++ int *temp)
+ {
+ struct power_supply *psy;
+ union power_supply_propval val;
+diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
+index 01255fd..26b8d32 100644
+--- a/drivers/thermal/armada_thermal.c
++++ b/drivers/thermal/armada_thermal.c
+@@ -155,7 +155,7 @@ static bool armada_is_valid(struct armada_thermal_priv *priv)
+ }
+
+ static int armada_get_temp(struct thermal_zone_device *thermal,
+- unsigned long *temp)
++ int *temp)
+ {
+ struct armada_thermal_priv *priv = thermal->devdata;
+ unsigned long reg;
+diff --git a/drivers/thermal/db8500_thermal.c b/drivers/thermal/db8500_thermal.c
+index 20adfbe..b3eca71 100644
+--- a/drivers/thermal/db8500_thermal.c
++++ b/drivers/thermal/db8500_thermal.c
+@@ -107,8 +107,7 @@ static int db8500_cdev_unbind(struct thermal_zone_device *thermal,
+ }
+
+ /* Callback to get current temperature */
+-static int db8500_sys_get_temp(struct thermal_zone_device *thermal,
+- unsigned long *temp)
++static int db8500_sys_get_temp(struct thermal_zone_device *thermal, int *temp)
+ {
+ struct db8500_thermal_zone *pzone = thermal->devdata;
+
+@@ -180,7 +179,7 @@ static int db8500_sys_get_trip_type(struct thermal_zone_device *thermal,
+
+ /* Callback to get trip point temperature */
+ static int db8500_sys_get_trip_temp(struct thermal_zone_device *thermal,
+- int trip, unsigned long *temp)
++ int trip, int *temp)
+ {
+ struct db8500_thermal_zone *pzone = thermal->devdata;
+ struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
+@@ -195,7 +194,7 @@ static int db8500_sys_get_trip_temp(struct thermal_zone_device *thermal,
+
+ /* Callback to get critical trip point temperature */
+ static int db8500_sys_get_crit_temp(struct thermal_zone_device *thermal,
+- unsigned long *temp)
++ int *temp)
+ {
+ struct db8500_thermal_zone *pzone = thermal->devdata;
+ struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
+diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c
+index 09f6e30..a0bc9de 100644
+--- a/drivers/thermal/dove_thermal.c
++++ b/drivers/thermal/dove_thermal.c
+@@ -93,7 +93,7 @@ static int dove_init_sensor(const struct dove_thermal_priv *priv)
+ }
+
+ static int dove_get_temp(struct thermal_zone_device *thermal,
+- unsigned long *temp)
++ int *temp)
+ {
+ unsigned long reg;
+ struct dove_thermal_priv *priv = thermal->devdata;
+diff --git a/drivers/thermal/fair_share.c b/drivers/thermal/fair_share.c
+index 6e0a3fb..efad70e 100644
+--- a/drivers/thermal/fair_share.c
++++ b/drivers/thermal/fair_share.c
+@@ -34,7 +34,7 @@
+ static int get_trip_level(struct thermal_zone_device *tz)
+ {
+ int count = 0;
+- unsigned long trip_temp;
++ int trip_temp;
+ enum thermal_trip_type trip_type;
+
+ if (tz->trips == 0 || !tz->ops->get_trip_temp)
+diff --git a/drivers/thermal/gov_bang_bang.c b/drivers/thermal/gov_bang_bang.c
+index c5dd76b..70836c5 100644
+--- a/drivers/thermal/gov_bang_bang.c
++++ b/drivers/thermal/gov_bang_bang.c
+@@ -25,14 +25,13 @@
+
+ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
+ {
+- long trip_temp;
+- unsigned long trip_hyst;
++ int trip_temp, trip_hyst;
+ struct thermal_instance *instance;
+
+ tz->ops->get_trip_temp(tz, trip, &trip_temp);
+ tz->ops->get_trip_hyst(tz, trip, &trip_hyst);
+
+- dev_dbg(&tz->device, "Trip%d[temp=%ld]:temp=%d:hyst=%ld\n",
++ dev_dbg(&tz->device, "Trip%d[temp=%d]:temp=%d:hyst=%d\n",
+ trip, trip_temp, tz->temperature,
+ trip_hyst);
+
+diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
+index 2ccbc07..f1424f0 100644
+--- a/drivers/thermal/imx_thermal.c
++++ b/drivers/thermal/imx_thermal.c
+@@ -98,10 +98,10 @@ struct imx_thermal_data {
+ enum thermal_device_mode mode;
+ struct regmap *tempmon;
+ u32 c1, c2; /* See formula in imx_get_sensor_data() */
+- unsigned long temp_passive;
+- unsigned long temp_critical;
+- unsigned long alarm_temp;
+- unsigned long last_temp;
++ int temp_passive;
++ int temp_critical;
++ int alarm_temp;
++ int last_temp;
+ bool irq_enabled;
+ int irq;
+ struct clk *thermal_clk;
+@@ -109,7 +109,7 @@ struct imx_thermal_data {
+ };
+
+ static void imx_set_panic_temp(struct imx_thermal_data *data,
+- signed long panic_temp)
++ int panic_temp)
+ {
+ struct regmap *map = data->tempmon;
+ int critical_value;
+@@ -121,7 +121,7 @@ static void imx_set_panic_temp(struct imx_thermal_data *data,
+ }
+
+ static void imx_set_alarm_temp(struct imx_thermal_data *data,
+- signed long alarm_temp)
++ int alarm_temp)
+ {
+ struct regmap *map = data->tempmon;
+ int alarm_value;
+@@ -133,7 +133,7 @@ static void imx_set_alarm_temp(struct imx_thermal_data *data,
+ TEMPSENSE0_ALARM_VALUE_SHIFT);
+ }
+
+-static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
++static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
+ {
+ struct imx_thermal_data *data = tz->devdata;
+ struct regmap *map = data->tempmon;
+@@ -189,13 +189,13 @@ static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
+ if (data->alarm_temp == data->temp_critical &&
+ *temp < data->temp_passive) {
+ imx_set_alarm_temp(data, data->temp_passive);
+- dev_dbg(&tz->device, "thermal alarm off: T < %lu\n",
++ dev_dbg(&tz->device, "thermal alarm off: T < %d\n",
+ data->alarm_temp / 1000);
+ }
+ }
+
+ if (*temp != data->last_temp) {
+- dev_dbg(&tz->device, "millicelsius: %ld\n", *temp);
++ dev_dbg(&tz->device, "millicelsius: %d\n", *temp);
+ data->last_temp = *temp;
+ }
+
+@@ -262,8 +262,7 @@ static int imx_get_trip_type(struct thermal_zone_device *tz, int trip,
+ return 0;
+ }
+
+-static int imx_get_crit_temp(struct thermal_zone_device *tz,
+- unsigned long *temp)
++static int imx_get_crit_temp(struct thermal_zone_device *tz, int *temp)
+ {
+ struct imx_thermal_data *data = tz->devdata;
+
+@@ -272,7 +271,7 @@ static int imx_get_crit_temp(struct thermal_zone_device *tz,
+ }
+
+ static int imx_get_trip_temp(struct thermal_zone_device *tz, int trip,
+- unsigned long *temp)
++ int *temp)
+ {
+ struct imx_thermal_data *data = tz->devdata;
+
+@@ -282,7 +281,7 @@ static int imx_get_trip_temp(struct thermal_zone_device *tz, int trip,
+ }
+
+ static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
+- unsigned long temp)
++ int temp)
+ {
+ struct imx_thermal_data *data = tz->devdata;
+
+@@ -433,7 +432,7 @@ static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev)
+ {
+ struct imx_thermal_data *data = dev;
+
+- dev_dbg(&data->tz->device, "THERMAL ALARM: T > %lu\n",
++ dev_dbg(&data->tz->device, "THERMAL ALARM: T > %d\n",
+ data->alarm_temp / 1000);
+
+ thermal_zone_device_update(data->tz);
+diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
+index 1e25133..b9b2666 100644
+--- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
++++ b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
+@@ -20,7 +20,7 @@
+ #include "int340x_thermal_zone.h"
+
+ static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone,
+- unsigned long *temp)
++ int *temp)
+ {
+ struct int34x_thermal_zone *d = zone->devdata;
+ unsigned long long tmp;
+@@ -49,7 +49,7 @@ static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone,
+ }
+
+ static int int340x_thermal_get_trip_temp(struct thermal_zone_device *zone,
+- int trip, unsigned long *temp)
++ int trip, int *temp)
+ {
+ struct int34x_thermal_zone *d = zone->devdata;
+ int i;
+@@ -114,7 +114,7 @@ static int int340x_thermal_get_trip_type(struct thermal_zone_device *zone,
+ }
+
+ static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone,
+- int trip, unsigned long temp)
++ int trip, int temp)
+ {
+ struct int34x_thermal_zone *d = zone->devdata;
+ acpi_status status;
+@@ -136,7 +136,7 @@ static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone,
+
+
+ static int int340x_thermal_get_trip_hyst(struct thermal_zone_device *zone,
+- int trip, unsigned long *temp)
++ int trip, int *temp)
+ {
+ struct int34x_thermal_zone *d = zone->devdata;
+ acpi_status status;
+@@ -163,7 +163,7 @@ static struct thermal_zone_device_ops int340x_thermal_zone_ops = {
+ };
+
+ static int int340x_thermal_get_trip_config(acpi_handle handle, char *name,
+- unsigned long *temp)
++ int *temp)
+ {
+ unsigned long long r;
+ acpi_status status;
+diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.h b/drivers/thermal/int340x_thermal/int340x_thermal_zone.h
+index 9f38ab7..aaadf72 100644
+--- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.h
++++ b/drivers/thermal/int340x_thermal/int340x_thermal_zone.h
+@@ -21,7 +21,7 @@
+ #define INT340X_THERMAL_MAX_ACT_TRIP_COUNT 10
+
+ struct active_trip {
+- unsigned long temp;
++ int temp;
+ int id;
+ bool valid;
+ };
+@@ -31,11 +31,11 @@ struct int34x_thermal_zone {
+ struct active_trip act_trips[INT340X_THERMAL_MAX_ACT_TRIP_COUNT];
+ unsigned long *aux_trips;
+ int aux_trip_nr;
+- unsigned long psv_temp;
++ int psv_temp;
+ int psv_trip_id;
+- unsigned long crt_temp;
++ int crt_temp;
+ int crt_trip_id;
+- unsigned long hot_temp;
++ int hot_temp;
+ int hot_trip_id;
+ struct thermal_zone_device *zone;
+ struct thermal_zone_device_ops *override_ops;
+diff --git a/drivers/thermal/intel_soc_dts_thermal.c b/drivers/thermal/intel_soc_dts_thermal.c
+index 9013505..fd550b9 100644
+--- a/drivers/thermal/intel_soc_dts_thermal.c
++++ b/drivers/thermal/intel_soc_dts_thermal.c
+@@ -106,7 +106,7 @@ err_ret:
+ }
+
+ static int sys_get_trip_temp(struct thermal_zone_device *tzd,
+- int trip, unsigned long *temp)
++ int trip, int *temp)
+ {
+ int status;
+ u32 out;
+@@ -224,7 +224,7 @@ err_restore_ptps:
+ }
+
+ static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
+- unsigned long temp)
++ int temp)
+ {
+ struct soc_sensor_entry *aux_entry = tzd->devdata;
+ int status;
+@@ -250,8 +250,7 @@ static int sys_get_trip_type(struct thermal_zone_device *thermal,
+ return 0;
+ }
+
+-static int sys_get_curr_temp(struct thermal_zone_device *tzd,
+- unsigned long *temp)
++static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
+ {
+ int status;
+ u32 out;
+diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
+index 668fb1b..03839df 100644
+--- a/drivers/thermal/of-thermal.c
++++ b/drivers/thermal/of-thermal.c
+@@ -87,7 +87,7 @@ struct __thermal_zone {
+ /*** DT thermal zone device callbacks ***/
+
+ static int of_thermal_get_temp(struct thermal_zone_device *tz,
+- unsigned long *temp)
++ int *temp)
+ {
+ struct __thermal_zone *data = tz->devdata;
+
+@@ -173,7 +173,7 @@ EXPORT_SYMBOL_GPL(of_thermal_get_trip_points);
+ * Return: zero on success, error code otherwise
+ */
+ static int of_thermal_set_emul_temp(struct thermal_zone_device *tz,
+- unsigned long temp)
++ int temp)
+ {
+ struct __thermal_zone *data = tz->devdata;
+
+@@ -306,7 +306,7 @@ static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
+ }
+
+ static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
+- unsigned long *temp)
++ int *temp)
+ {
+ struct __thermal_zone *data = tz->devdata;
+
+@@ -319,7 +319,7 @@ static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
+ }
+
+ static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
+- unsigned long temp)
++ int temp)
+ {
+ struct __thermal_zone *data = tz->devdata;
+
+@@ -333,7 +333,7 @@ static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
+ }
+
+ static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
+- unsigned long *hyst)
++ int *hyst)
+ {
+ struct __thermal_zone *data = tz->devdata;
+
+@@ -346,7 +346,7 @@ static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
+ }
+
+ static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
+- unsigned long hyst)
++ int hyst)
+ {
+ struct __thermal_zone *data = tz->devdata;
+
+@@ -360,7 +360,7 @@ static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
+ }
+
+ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
+- unsigned long *temp)
++ int *temp)
+ {
+ struct __thermal_zone *data = tz->devdata;
+ int i;
+diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c
+index fe4e767..5d4ae7d 100644
+--- a/drivers/thermal/rcar_thermal.c
++++ b/drivers/thermal/rcar_thermal.c
+@@ -200,8 +200,7 @@ err_out_unlock:
+ return ret;
+ }
+
+-static int rcar_thermal_get_temp(struct thermal_zone_device *zone,
+- unsigned long *temp)
++static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp)
+ {
+ struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
+
+@@ -235,7 +234,7 @@ static int rcar_thermal_get_trip_type(struct thermal_zone_device *zone,
+ }
+
+ static int rcar_thermal_get_trip_temp(struct thermal_zone_device *zone,
+- int trip, unsigned long *temp)
++ int trip, int *temp)
+ {
+ struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
+ struct device *dev = rcar_priv_to_dev(priv);
+@@ -299,7 +298,7 @@ static void _rcar_thermal_irq_ctrl(struct rcar_thermal_priv *priv, int enable)
+ static void rcar_thermal_work(struct work_struct *work)
+ {
+ struct rcar_thermal_priv *priv;
+- unsigned long cctemp, nctemp;
++ int cctemp, nctemp;
+
+ priv = container_of(work, struct rcar_thermal_priv, work.work);
+
+diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
+index cd8f5f93..c89ffb2 100644
+--- a/drivers/thermal/rockchip_thermal.c
++++ b/drivers/thermal/rockchip_thermal.c
+@@ -64,7 +64,7 @@ struct rockchip_tsadc_chip {
+ void (*control)(void __iomem *reg, bool on);
+
+ /* Per-sensor methods */
+- int (*get_temp)(int chn, void __iomem *reg, long *temp);
++ int (*get_temp)(int chn, void __iomem *reg, int *temp);
+ void (*set_tshut_temp)(int chn, void __iomem *reg, long temp);
+ void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m);
+ };
+@@ -191,7 +191,7 @@ static u32 rk_tsadcv2_temp_to_code(long temp)
+ return 0;
+ }
+
+-static long rk_tsadcv2_code_to_temp(u32 code)
++static int rk_tsadcv2_code_to_temp(u32 code)
+ {
+ unsigned int low = 0;
+ unsigned int high = ARRAY_SIZE(v2_code_table) - 1;
+@@ -277,7 +277,7 @@ static void rk_tsadcv2_control(void __iomem *regs, bool enable)
+ writel_relaxed(val, regs + TSADCV2_AUTO_CON);
+ }
+
+-static int rk_tsadcv2_get_temp(int chn, void __iomem *regs, long *temp)
++static int rk_tsadcv2_get_temp(int chn, void __iomem *regs, int *temp)
+ {
+ u32 val;
+
+@@ -366,7 +366,7 @@ static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
+ return IRQ_HANDLED;
+ }
+
+-static int rockchip_thermal_get_temp(void *_sensor, long *out_temp)
++static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
+ {
+ struct rockchip_thermal_sensor *sensor = _sensor;
+ struct rockchip_thermal_data *thermal = sensor->thermal;
+@@ -374,7 +374,7 @@ static int rockchip_thermal_get_temp(void *_sensor, long *out_temp)
+ int retval;
+
+ retval = tsadc->get_temp(sensor->id, thermal->regs, out_temp);
+- dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %ld, retval: %d\n",
++ dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %d, retval: %d\n",
+ sensor->id, *out_temp, retval);
+
+ return retval;
+diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
+index 1d30b09..29eaf4d 100644
+--- a/drivers/thermal/samsung/exynos_tmu.c
++++ b/drivers/thermal/samsung/exynos_tmu.c
+@@ -181,8 +181,7 @@ struct exynos_tmu_data {
+ int (*tmu_initialize)(struct platform_device *pdev);
+ void (*tmu_control)(struct platform_device *pdev, bool on);
+ int (*tmu_read)(struct exynos_tmu_data *data);
+- void (*tmu_set_emulation)(struct exynos_tmu_data *data,
+- unsigned long temp);
++ void (*tmu_set_emulation)(struct exynos_tmu_data *data, int temp);
+ void (*tmu_clear_irqs)(struct exynos_tmu_data *data);
+ };
+
+@@ -190,7 +189,7 @@ static void exynos_report_trigger(struct exynos_tmu_data *p)
+ {
+ char data[10], *envp[] = { data, NULL };
+ struct thermal_zone_device *tz = p->tzd;
+- unsigned long temp;
++ int temp;
+ unsigned int i;
+
+ if (!tz) {
+@@ -489,7 +488,7 @@ static int exynos5440_tmu_initialize(struct platform_device *pdev)
+ struct exynos_tmu_data *data = platform_get_drvdata(pdev);
+ unsigned int trim_info = 0, con, rising_threshold;
+ int ret = 0, threshold_code;
+- unsigned long crit_temp = 0;
++ int crit_temp = 0;
+
+ /*
+ * For exynos5440 soc triminfo value is swapped between TMU0 and
+@@ -542,7 +541,7 @@ static int exynos7_tmu_initialize(struct platform_device *pdev)
+ unsigned int status, trim_info;
+ unsigned int rising_threshold = 0, falling_threshold = 0;
+ int ret = 0, threshold_code, i;
+- unsigned long temp, temp_hist;
++ int temp, temp_hist;
+ unsigned int reg_off, bit_off;
+
+ status = readb(data->base + EXYNOS_TMU_REG_STATUS);
+@@ -713,7 +712,7 @@ static void exynos7_tmu_control(struct platform_device *pdev, bool on)
+ writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
+ }
+
+-static int exynos_get_temp(void *p, long *temp)
++static int exynos_get_temp(void *p, int *temp)
+ {
+ struct exynos_tmu_data *data = p;
+
+@@ -733,7 +732,7 @@ static int exynos_get_temp(void *p, long *temp)
+
+ #ifdef CONFIG_THERMAL_EMULATION
+ static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val,
+- unsigned long temp)
++ int temp)
+ {
+ if (temp) {
+ temp /= MCELSIUS;
+@@ -763,7 +762,7 @@ static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val,
+ }
+
+ static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data,
+- unsigned long temp)
++ int temp)
+ {
+ unsigned int val;
+ u32 emul_con;
+@@ -781,7 +780,7 @@ static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data,
+ }
+
+ static void exynos5440_tmu_set_emulation(struct exynos_tmu_data *data,
+- unsigned long temp)
++ int temp)
+ {
+ unsigned int val;
+
+@@ -790,7 +789,7 @@ static void exynos5440_tmu_set_emulation(struct exynos_tmu_data *data,
+ writel(val, data->base + EXYNOS5440_TMU_S0_7_DEBUG);
+ }
+
+-static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
++static int exynos_tmu_set_emulation(void *drv_data, int temp)
+ {
+ struct exynos_tmu_data *data = drv_data;
+ int ret = -EINVAL;
+diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c
+index bddb717..534dd91 100644
+--- a/drivers/thermal/spear_thermal.c
++++ b/drivers/thermal/spear_thermal.c
+@@ -38,7 +38,7 @@ struct spear_thermal_dev {
+ };
+
+ static inline int thermal_get_temp(struct thermal_zone_device *thermal,
+- unsigned long *temp)
++ int *temp)
+ {
+ struct spear_thermal_dev *stdev = thermal->devdata;
+
+diff --git a/drivers/thermal/st/st_thermal.c b/drivers/thermal/st/st_thermal.c
+index 76c515d..44cbba9 100644
+--- a/drivers/thermal/st/st_thermal.c
++++ b/drivers/thermal/st/st_thermal.c
+@@ -111,8 +111,7 @@ static int st_thermal_calibration(struct st_thermal_sensor *sensor)
+ }
+
+ /* Callback to get temperature from HW*/
+-static int st_thermal_get_temp(struct thermal_zone_device *th,
+- unsigned long *temperature)
++static int st_thermal_get_temp(struct thermal_zone_device *th, int *temperature)
+ {
+ struct st_thermal_sensor *sensor = th->devdata;
+ struct device *dev = sensor->dev;
+@@ -159,7 +158,7 @@ static int st_thermal_get_trip_type(struct thermal_zone_device *th,
+ }
+
+ static int st_thermal_get_trip_temp(struct thermal_zone_device *th,
+- int trip, unsigned long *temp)
++ int trip, int *temp)
+ {
+ struct st_thermal_sensor *sensor = th->devdata;
+ struct device *dev = sensor->dev;
+diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c
+index 5a0f12d..2f9f708 100644
+--- a/drivers/thermal/step_wise.c
++++ b/drivers/thermal/step_wise.c
+@@ -113,7 +113,7 @@ static void update_passive_instance(struct thermal_zone_device *tz,
+
+ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
+ {
+- long trip_temp;
++ int trip_temp;
+ enum thermal_trip_type trip_type;
+ enum thermal_trend trend;
+ struct thermal_instance *instance;
+@@ -135,7 +135,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
+ trace_thermal_zone_trip(tz, trip, trip_type);
+ }
+
+- dev_dbg(&tz->device, "Trip%d[type=%d,temp=%ld]:trend=%d,throttle=%d\n",
++ dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n",
+ trip, trip_type, trip_temp, trend, throttle);
+
+ mutex_lock(&tz->lock);
+diff --git a/drivers/thermal/tegra_soctherm.c b/drivers/thermal/tegra_soctherm.c
+index 9197fc0..74ea576 100644
+--- a/drivers/thermal/tegra_soctherm.c
++++ b/drivers/thermal/tegra_soctherm.c
+@@ -293,7 +293,7 @@ static int enable_tsensor(struct tegra_soctherm *tegra,
+ * H denotes an addition of 0.5 Celsius and N denotes negation
+ * of the final value.
+ */
+-static long translate_temp(u16 val)
++static int translate_temp(u16 val)
+ {
+ long t;
+
+@@ -306,7 +306,7 @@ static long translate_temp(u16 val)
+ return t;
+ }
+
+-static int tegra_thermctl_get_temp(void *data, long *out_temp)
++static int tegra_thermctl_get_temp(void *data, int *out_temp)
+ {
+ struct tegra_thermctl_zone *zone = data;
+ u32 val;
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index 4108db7..62cc82a 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -363,7 +363,7 @@ static void handle_non_critical_trips(struct thermal_zone_device *tz,
+ static void handle_critical_trips(struct thermal_zone_device *tz,
+ int trip, enum thermal_trip_type trip_type)
+ {
+- long trip_temp;
++ int trip_temp;
+
+ tz->ops->get_trip_temp(tz, trip, &trip_temp);
+
+@@ -411,12 +411,12 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
+ *
+ * Return: On success returns 0, an error code otherwise
+ */
+-int thermal_zone_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
++int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
+ {
+ int ret = -EINVAL;
+ #ifdef CONFIG_THERMAL_EMULATION
+ int count;
+- unsigned long crit_temp = -1UL;
++ int crit_temp = INT_MAX;
+ enum thermal_trip_type type;
+ #endif
+
+@@ -453,8 +453,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
+
+ static void update_temperature(struct thermal_zone_device *tz)
+ {
+- long temp;
+- int ret;
++ int temp, ret;
+
+ ret = thermal_zone_get_temp(tz, &temp);
+ if (ret) {
+@@ -514,15 +513,14 @@ static ssize_t
+ temp_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+- long temperature;
+- int ret;
++ int temperature, ret;
+
+ ret = thermal_zone_get_temp(tz, &temperature);
+
+ if (ret)
+ return ret;
+
+- return sprintf(buf, "%ld\n", temperature);
++ return sprintf(buf, "%d\n", temperature);
+ }
+
+ static ssize_t
+@@ -626,7 +624,7 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
+ {
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int trip, ret;
+- long temperature;
++ int temperature;
+
+ if (!tz->ops->get_trip_temp)
+ return -EPERM;
+@@ -639,7 +637,7 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
+ if (ret)
+ return ret;
+
+- return sprintf(buf, "%ld\n", temperature);
++ return sprintf(buf, "%d\n", temperature);
+ }
+
+ static ssize_t
+@@ -648,7 +646,7 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
+ {
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int trip, ret;
+- unsigned long temperature;
++ int temperature;
+
+ if (!tz->ops->set_trip_hyst)
+ return -EPERM;
+@@ -656,7 +654,7 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
+ if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip))
+ return -EINVAL;
+
+- if (kstrtoul(buf, 10, &temperature))
++ if (kstrtoint(buf, 10, &temperature))
+ return -EINVAL;
+
+ /*
+@@ -675,7 +673,7 @@ trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
+ {
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int trip, ret;
+- unsigned long temperature;
++ int temperature;
+
+ if (!tz->ops->get_trip_hyst)
+ return -EPERM;
+@@ -685,7 +683,7 @@ trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
+
+ ret = tz->ops->get_trip_hyst(tz, trip, &temperature);
+
+- return ret ? ret : sprintf(buf, "%ld\n", temperature);
++ return ret ? ret : sprintf(buf, "%d\n", temperature);
+ }
+
+ static ssize_t
+diff --git a/drivers/thermal/thermal_hwmon.c b/drivers/thermal/thermal_hwmon.c
+index 1967bee..06fd2ed9 100644
+--- a/drivers/thermal/thermal_hwmon.c
++++ b/drivers/thermal/thermal_hwmon.c
+@@ -69,7 +69,7 @@ static DEVICE_ATTR(name, 0444, name_show, NULL);
+ static ssize_t
+ temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+- long temperature;
++ int temperature;
+ int ret;
+ struct thermal_hwmon_attr *hwmon_attr
+ = container_of(attr, struct thermal_hwmon_attr, attr);
+@@ -83,7 +83,7 @@ temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
+ if (ret)
+ return ret;
+
+- return sprintf(buf, "%ld\n", temperature);
++ return sprintf(buf, "%d\n", temperature);
+ }
+
+ static ssize_t
+@@ -95,14 +95,14 @@ temp_crit_show(struct device *dev, struct device_attribute *attr, char *buf)
+ = container_of(hwmon_attr, struct thermal_hwmon_temp,
+ temp_crit);
+ struct thermal_zone_device *tz = temp->tz;
+- long temperature;
++ int temperature;
+ int ret;
+
+ ret = tz->ops->get_trip_temp(tz, 0, &temperature);
+ if (ret)
+ return ret;
+
+- return sprintf(buf, "%ld\n", temperature);
++ return sprintf(buf, "%d\n", temperature);
+ }
+
+
+@@ -142,7 +142,7 @@ thermal_hwmon_lookup_temp(const struct thermal_hwmon_device *hwmon,
+
+ static bool thermal_zone_crit_temp_valid(struct thermal_zone_device *tz)
+ {
+- unsigned long temp;
++ int temp;
+ return tz->ops->get_crit_temp && !tz->ops->get_crit_temp(tz, &temp);
+ }
+
+diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+index a38c175..d3a42bf 100644
+--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
++++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+@@ -76,14 +76,14 @@ static inline int ti_thermal_hotspot_temperature(int t, int s, int c)
+
+ /* thermal zone ops */
+ /* Get temperature callback function for thermal zone*/
+-static inline int __ti_thermal_get_temp(void *devdata, long *temp)
++static inline int __ti_thermal_get_temp(void *devdata, int *temp)
+ {
+ struct thermal_zone_device *pcb_tz = NULL;
+ struct ti_thermal_data *data = devdata;
+ struct ti_bandgap *bgp;
+ const struct ti_temp_sensor *s;
+ int ret, tmp, slope, constant;
+- unsigned long pcb_temp;
++ int pcb_temp;
+
+ if (!data)
+ return 0;
+@@ -119,7 +119,7 @@ static inline int __ti_thermal_get_temp(void *devdata, long *temp)
+ }
+
+ static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
+- unsigned long *temp)
++ int *temp)
+ {
+ struct ti_thermal_data *data = thermal->devdata;
+
+@@ -228,7 +228,7 @@ static int ti_thermal_get_trip_type(struct thermal_zone_device *thermal,
+
+ /* Get trip temperature callback functions for thermal zone */
+ static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal,
+- int trip, unsigned long *temp)
++ int trip, int *temp)
+ {
+ if (!ti_thermal_is_valid_trip(trip))
+ return -EINVAL;
+@@ -279,7 +279,7 @@ static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
+
+ /* Get critical temperature callback functions for thermal zone */
+ static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal,
+- unsigned long *temp)
++ int *temp)
+ {
+ /* shutdown zone */
+ return ti_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp);
+diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c
+index 9ea3d9d..054c6d45 100644
+--- a/drivers/thermal/x86_pkg_temp_thermal.c
++++ b/drivers/thermal/x86_pkg_temp_thermal.c
+@@ -164,7 +164,7 @@ err_ret:
+ return err;
+ }
+
+-static int sys_get_curr_temp(struct thermal_zone_device *tzd, unsigned long *temp)
++static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
+ {
+ u32 eax, edx;
+ struct phy_dev_entry *phy_dev_entry;
+@@ -175,7 +175,7 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, unsigned long *tem
+ if (eax & 0x80000000) {
+ *temp = phy_dev_entry->tj_max -
+ ((eax >> 16) & 0x7f) * 1000;
+- pr_debug("sys_get_curr_temp %ld\n", *temp);
++ pr_debug("sys_get_curr_temp %d\n", *temp);
+ return 0;
+ }
+
+@@ -183,7 +183,7 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, unsigned long *tem
+ }
+
+ static int sys_get_trip_temp(struct thermal_zone_device *tzd,
+- int trip, unsigned long *temp)
++ int trip, int *temp)
+ {
+ u32 eax, edx;
+ struct phy_dev_entry *phy_dev_entry;
+@@ -214,13 +214,13 @@ static int sys_get_trip_temp(struct thermal_zone_device *tzd,
+ *temp = phy_dev_entry->tj_max - thres_reg_value * 1000;
+ else
+ *temp = 0;
+- pr_debug("sys_get_trip_temp %ld\n", *temp);
++ pr_debug("sys_get_trip_temp %d\n", *temp);
+
+ return 0;
+ }
+
+ static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
+- unsigned long temp)
++ int temp)
+ {
+ u32 l, h;
+ struct phy_dev_entry *phy_dev_entry;
+diff --git a/include/linux/thermal.h b/include/linux/thermal.h
+index 5eac316..e9f2863 100644
+--- a/include/linux/thermal.h
++++ b/include/linux/thermal.h
+@@ -86,23 +86,19 @@ struct thermal_zone_device_ops {
+ struct thermal_cooling_device *);
+ int (*unbind) (struct thermal_zone_device *,
+ struct thermal_cooling_device *);
+- int (*get_temp) (struct thermal_zone_device *, unsigned long *);
++ int (*get_temp) (struct thermal_zone_device *, int *);
+ int (*get_mode) (struct thermal_zone_device *,
+ enum thermal_device_mode *);
+ int (*set_mode) (struct thermal_zone_device *,
+ enum thermal_device_mode);
+ int (*get_trip_type) (struct thermal_zone_device *, int,
+ enum thermal_trip_type *);
+- int (*get_trip_temp) (struct thermal_zone_device *, int,
+- unsigned long *);
+- int (*set_trip_temp) (struct thermal_zone_device *, int,
+- unsigned long);
+- int (*get_trip_hyst) (struct thermal_zone_device *, int,
+- unsigned long *);
+- int (*set_trip_hyst) (struct thermal_zone_device *, int,
+- unsigned long);
+- int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
+- int (*set_emul_temp) (struct thermal_zone_device *, unsigned long);
++ int (*get_trip_temp) (struct thermal_zone_device *, int, int *);
++ int (*set_trip_temp) (struct thermal_zone_device *, int, int);
++ int (*get_trip_hyst) (struct thermal_zone_device *, int, int *);
++ int (*set_trip_hyst) (struct thermal_zone_device *, int, int);
++ int (*get_crit_temp) (struct thermal_zone_device *, int *);
++ int (*set_emul_temp) (struct thermal_zone_device *, int);
+ int (*get_trend) (struct thermal_zone_device *, int,
+ enum thermal_trend *);
+ int (*notify) (struct thermal_zone_device *, int,
+@@ -272,9 +268,9 @@ struct thermal_genl_event {
+ * temperature.
+ */
+ struct thermal_zone_of_device_ops {
+- int (*get_temp)(void *, long *);
++ int (*get_temp)(void *, int *);
+ int (*get_trend)(void *, long *);
+- int (*set_emul_temp)(void *, unsigned long);
++ int (*set_emul_temp)(void *, int);
+ };
+
+ /**
+@@ -335,7 +331,7 @@ thermal_of_cooling_device_register(struct device_node *np, char *, void *,
+ const struct thermal_cooling_device_ops *);
+ void thermal_cooling_device_unregister(struct thermal_cooling_device *);
+ struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name);
+-int thermal_zone_get_temp(struct thermal_zone_device *tz, unsigned long *temp);
++int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp);
+
+ int get_tz_trend(struct thermal_zone_device *, int);
+ struct thermal_instance *get_thermal_instance(struct thermal_zone_device *,
+@@ -378,7 +374,7 @@ static inline struct thermal_zone_device *thermal_zone_get_zone_by_name(
+ const char *name)
+ { return ERR_PTR(-ENODEV); }
+ static inline int thermal_zone_get_temp(
+- struct thermal_zone_device *tz, unsigned long *temp)
++ struct thermal_zone_device *tz, int *temp)
+ { return -ENODEV; }
+ static inline int get_tz_trend(struct thermal_zone_device *tz, int trip)
+ { return -ENODEV; }
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0011-thermal-trivial-fix-typo-in-comment.patch b/target/linux/mediatek/patches/0011-thermal-trivial-fix-typo-in-comment.patch
new file mode 100644
index 0000000000..4b9e0f9514
--- /dev/null
+++ b/target/linux/mediatek/patches/0011-thermal-trivial-fix-typo-in-comment.patch
@@ -0,0 +1,27 @@
+From a2214b951a1102ad2a2a72b6ae6e71c148f8249f Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:30 +0200
+Subject: [PATCH 11/76] thermal: trivial: fix typo in comment
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+Acked-by: Eduardo Valentin <edubezval@gmail.com>
+---
+ drivers/thermal/thermal_core.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index 62cc82a..244784f 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -402,7 +402,7 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
+ }
+
+ /**
+- * thermal_zone_get_temp() - returns its the temperature of thermal zone
++ * thermal_zone_get_temp() - returns the temperature of a thermal zone
+ * @tz: a valid pointer to a struct thermal_zone_device
+ * @temp: a valid pointer to where to store the resulting temperature.
+ *
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0012-thermal-remove-useless-call-to-thermal_zone_device_s.patch b/target/linux/mediatek/patches/0012-thermal-remove-useless-call-to-thermal_zone_device_s.patch
new file mode 100644
index 0000000000..2d64f4949c
--- /dev/null
+++ b/target/linux/mediatek/patches/0012-thermal-remove-useless-call-to-thermal_zone_device_s.patch
@@ -0,0 +1,34 @@
+From 41adcc8cf217dfb4b70c2da061e70034b3c9add0 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:31 +0200
+Subject: [PATCH 12/76] thermal: remove useless call to
+ thermal_zone_device_set_polling
+
+When the thermal zone has no get_temp callback then thermal_zone_device_register()
+calls thermal_zone_device_set_polling() with a polling delay of 0. This
+only cancels the poll_queue. Since the poll_queue hasn't been scheduled this
+is a no-op. Remove it.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+Acked-by: Eduardo Valentin <edubezval@gmail.com>
+---
+ drivers/thermal/thermal_core.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index 244784f..1b68d20 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -1571,9 +1571,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
+
+ INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
+
+- if (!tz->ops->get_temp)
+- thermal_zone_device_set_polling(tz, 0);
+-
+ thermal_zone_device_update(tz);
+
+ return tz;
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0013-thermal-Use-IS_ENABLED-instead-of-ifdef.patch b/target/linux/mediatek/patches/0013-thermal-Use-IS_ENABLED-instead-of-ifdef.patch
new file mode 100644
index 0000000000..0b033d65e1
--- /dev/null
+++ b/target/linux/mediatek/patches/0013-thermal-Use-IS_ENABLED-instead-of-ifdef.patch
@@ -0,0 +1,106 @@
+From bddcae2b66a23bfb6d381d089b0b862235480a9b Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:32 +0200
+Subject: [PATCH 13/76] thermal: Use IS_ENABLED instead of #ifdef
+
+Use IS_ENABLED(CONFIG_THERMAL_EMULATION) to make the code more readable
+and to get rid of the addtional #ifdef around the variable definitions
+in thermal_zone_get_temp().
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/thermal/thermal_core.c | 45 +++++++++++++++++-----------------------
+ 1 file changed, 19 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index 1b68d20..3e0fe55 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -414,11 +414,9 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
+ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
+ {
+ int ret = -EINVAL;
+-#ifdef CONFIG_THERMAL_EMULATION
+ int count;
+ int crit_temp = INT_MAX;
+ enum thermal_trip_type type;
+-#endif
+
+ if (!tz || IS_ERR(tz) || !tz->ops->get_temp)
+ goto exit;
+@@ -426,25 +424,21 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
+ mutex_lock(&tz->lock);
+
+ ret = tz->ops->get_temp(tz, temp);
+-#ifdef CONFIG_THERMAL_EMULATION
+- if (!tz->emul_temperature)
+- goto skip_emul;
+-
+- for (count = 0; count < tz->trips; count++) {
+- ret = tz->ops->get_trip_type(tz, count, &type);
+- if (!ret && type == THERMAL_TRIP_CRITICAL) {
+- ret = tz->ops->get_trip_temp(tz, count, &crit_temp);
+- break;
+- }
+- }
+
+- if (ret)
+- goto skip_emul;
++ if (IS_ENABLED(CONFIG_THERMAL_EMULATION) && tz->emul_temperature) {
++ for (count = 0; count < tz->trips; count++) {
++ ret = tz->ops->get_trip_type(tz, count, &type);
++ if (!ret && type == THERMAL_TRIP_CRITICAL) {
++ ret = tz->ops->get_trip_temp(tz, count,
++ &crit_temp);
++ break;
++ }
++ }
+
+- if (*temp < crit_temp)
+- *temp = tz->emul_temperature;
+-skip_emul:
+-#endif
++ if (!ret && *temp < crit_temp)
++ *temp = tz->emul_temperature;
++ }
++
+ mutex_unlock(&tz->lock);
+ exit:
+ return ret;
+@@ -780,7 +774,6 @@ policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
+ return sprintf(buf, "%s\n", tz->governor->name);
+ }
+
+-#ifdef CONFIG_THERMAL_EMULATION
+ static ssize_t
+ emul_temp_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+@@ -806,7 +799,6 @@ emul_temp_store(struct device *dev, struct device_attribute *attr,
+ return ret ? ret : count;
+ }
+ static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);
+-#endif/*CONFIG_THERMAL_EMULATION*/
+
+ static DEVICE_ATTR(type, 0444, type_show, NULL);
+ static DEVICE_ATTR(temp, 0444, temp_show, NULL);
+@@ -1536,11 +1528,12 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
+ goto unregister;
+ }
+
+-#ifdef CONFIG_THERMAL_EMULATION
+- result = device_create_file(&tz->device, &dev_attr_emul_temp);
+- if (result)
+- goto unregister;
+-#endif
++ if (IS_ENABLED(CONFIG_THERMAL_EMULATION)) {
++ result = device_create_file(&tz->device, &dev_attr_emul_temp);
++ if (result)
++ goto unregister;
++ }
++
+ /* Create policy attribute */
+ result = device_create_file(&tz->device, &dev_attr_policy);
+ if (result)
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0014-thermal-Add-comment-explaining-test-for-critical-tem.patch b/target/linux/mediatek/patches/0014-thermal-Add-comment-explaining-test-for-critical-tem.patch
new file mode 100644
index 0000000000..56d3e4f21e
--- /dev/null
+++ b/target/linux/mediatek/patches/0014-thermal-Add-comment-explaining-test-for-critical-tem.patch
@@ -0,0 +1,34 @@
+From 18f50eae474edc716b01959fad6898c8553b131c Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:33 +0200
+Subject: [PATCH 14/76] thermal: Add comment explaining test for critical
+ temperature
+
+The code testing if a temperature should be emulated or not is
+not obvious. Add a comment explaining why this test is done.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
+---
+ drivers/thermal/thermal_core.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index 3e0fe55..e204deb 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -435,6 +435,11 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
+ }
+ }
+
++ /*
++ * Only allow emulating a temperature when the real temperature
++ * is below the critical temperature so that the emulation code
++ * cannot hide critical conditions.
++ */
+ if (!ret && *temp < crit_temp)
+ *temp = tz->emul_temperature;
+ }
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0015-thermal-inline-only-once-used-function.patch b/target/linux/mediatek/patches/0015-thermal-inline-only-once-used-function.patch
new file mode 100644
index 0000000000..e050ae763a
--- /dev/null
+++ b/target/linux/mediatek/patches/0015-thermal-inline-only-once-used-function.patch
@@ -0,0 +1,53 @@
+From 0b729a98127ef045096edf20dfe5c4eadac21d44 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:34 +0200
+Subject: [PATCH 15/76] thermal: inline only once used function
+
+Inline update_temperature into its only caller to make the code
+more readable.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
+---
+ drivers/thermal/thermal_core.c | 17 +++++------------
+ 1 file changed, 5 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index e204deb..19da022 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -450,9 +450,12 @@ exit:
+ }
+ EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
+
+-static void update_temperature(struct thermal_zone_device *tz)
++void thermal_zone_device_update(struct thermal_zone_device *tz)
+ {
+- int temp, ret;
++ int temp, ret, count;
++
++ if (!tz->ops->get_temp)
++ return;
+
+ ret = thermal_zone_get_temp(tz, &temp);
+ if (ret) {
+@@ -471,16 +474,6 @@ static void update_temperature(struct thermal_zone_device *tz)
+ trace_thermal_temperature(tz);
+ dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
+ tz->last_temperature, tz->temperature);
+-}
+-
+-void thermal_zone_device_update(struct thermal_zone_device *tz)
+-{
+- int count;
+-
+- if (!tz->ops->get_temp)
+- return;
+-
+- update_temperature(tz);
+
+ for (count = 0; count < tz->trips; count++)
+ handle_thermal_trip(tz, count);
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0016-thermal-streamline-get_trend-callbacks.patch b/target/linux/mediatek/patches/0016-thermal-streamline-get_trend-callbacks.patch
new file mode 100644
index 0000000000..99d490f2bb
--- /dev/null
+++ b/target/linux/mediatek/patches/0016-thermal-streamline-get_trend-callbacks.patch
@@ -0,0 +1,123 @@
+From 5da86f6a2b4c2c318e153649dc8fd34fe73f8292 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:35 +0200
+Subject: [PATCH 16/76] thermal: streamline get_trend callbacks
+
+The .get_trend callback in struct thermal_zone_device_ops has the prototype:
+
+ int (*get_trend) (struct thermal_zone_device *, int,
+ enum thermal_trend *);
+
+whereas the .get_trend callback in struct thermal_zone_of_device_ops has:
+
+ int (*get_trend)(void *, long *);
+
+Streamline both prototypes and add the trip argument to the OF callback
+aswell and use enum thermal_trend * instead of an integer pointer.
+
+While the OF prototype may be the better one, this should be decided at
+framework level and not on OF level.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/thermal/of-thermal.c | 11 +--------
+ drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 25 +++++++-------------
+ include/linux/thermal.h | 2 +-
+ 3 files changed, 10 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
+index 03839df..c84404d 100644
+--- a/drivers/thermal/of-thermal.c
++++ b/drivers/thermal/of-thermal.c
+@@ -187,24 +187,15 @@ static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip,
+ enum thermal_trend *trend)
+ {
+ struct __thermal_zone *data = tz->devdata;
+- long dev_trend;
+ int r;
+
+ if (!data->ops->get_trend)
+ return -EINVAL;
+
+- r = data->ops->get_trend(data->sensor_data, &dev_trend);
++ r = data->ops->get_trend(data->sensor_data, trip, trend);
+ if (r)
+ return r;
+
+- /* TODO: These intervals might have some thresholds, but in core code */
+- if (dev_trend > 0)
+- *trend = THERMAL_TREND_RAISING;
+- else if (dev_trend < 0)
+- *trend = THERMAL_TREND_DROPPING;
+- else
+- *trend = THERMAL_TREND_STABLE;
+-
+ return 0;
+ }
+
+diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+index d3a42bf..ade78eb 100644
+--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
++++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+@@ -238,7 +238,7 @@ static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal,
+ return 0;
+ }
+
+-static int __ti_thermal_get_trend(void *p, long *trend)
++static int __ti_thermal_get_trend(void *p, int trip, enum thermal_trend *trend)
+ {
+ struct ti_thermal_data *data = p;
+ struct ti_bandgap *bgp;
+@@ -251,22 +251,6 @@ static int __ti_thermal_get_trend(void *p, long *trend)
+ if (ret)
+ return ret;
+
+- *trend = tr;
+-
+- return 0;
+-}
+-
+-/* Get the temperature trend callback functions for thermal zone */
+-static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
+- int trip, enum thermal_trend *trend)
+-{
+- int ret;
+- long tr;
+-
+- ret = __ti_thermal_get_trend(thermal->devdata, &tr);
+- if (ret)
+- return ret;
+-
+ if (tr > 0)
+ *trend = THERMAL_TREND_RAISING;
+ else if (tr < 0)
+@@ -277,6 +261,13 @@ static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
+ return 0;
+ }
+
++/* Get the temperature trend callback functions for thermal zone */
++static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
++ int trip, enum thermal_trend *trend)
++{
++ return __ti_thermal_get_trend(thermal->devdata, trip, trend);
++}
++
+ /* Get critical temperature callback functions for thermal zone */
+ static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal,
+ int *temp)
+diff --git a/include/linux/thermal.h b/include/linux/thermal.h
+index e9f2863..5c6a589 100644
+--- a/include/linux/thermal.h
++++ b/include/linux/thermal.h
+@@ -269,7 +269,7 @@ struct thermal_genl_event {
+ */
+ struct thermal_zone_of_device_ops {
+ int (*get_temp)(void *, int *);
+- int (*get_trend)(void *, long *);
++ int (*get_trend)(void *, int, enum thermal_trend *);
+ int (*set_emul_temp)(void *, int);
+ };
+
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0017-thermal-Allow-sensor-ops-to-fail-with-ENOSYS.patch b/target/linux/mediatek/patches/0017-thermal-Allow-sensor-ops-to-fail-with-ENOSYS.patch
new file mode 100644
index 0000000000..f533a88319
--- /dev/null
+++ b/target/linux/mediatek/patches/0017-thermal-Allow-sensor-ops-to-fail-with-ENOSYS.patch
@@ -0,0 +1,90 @@
+From 5b622cb2d6ff44b1fb0750beee61f93f2c00548a Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:36 +0200
+Subject: [PATCH 17/76] thermal: Allow sensor ops to fail with -ENOSYS
+
+The thermal core uses the existence of the .get_temp, .get_trend and
+.set_emul_temp to detect whether this operation exists and should be
+used or whether it should be emulated in software. This makes problems
+for of-thermal which has to modify the struct thermal_zone_device_ops
+during runtime whenever a sensor is registered or unregistered.
+
+Let the core test for -ENOSYS from these callbacks and treat it like
+if the callbacks were not present.
+
+This allows of-thermal to always set the sensor related callbacks and
+to make struct thermal_zone_device_ops const again.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/thermal/thermal_core.c | 24 +++++++++++++++++-------
+ 1 file changed, 17 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index 19da022..3d8f9f9 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -413,13 +413,16 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
+ */
+ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
+ {
+- int ret = -EINVAL;
++ int ret;
+ int count;
+ int crit_temp = INT_MAX;
+ enum thermal_trip_type type;
+
+- if (!tz || IS_ERR(tz) || !tz->ops->get_temp)
+- goto exit;
++ if (!tz || IS_ERR(tz))
++ return -EINVAL;
++
++ if (!tz->ops->get_temp)
++ return -ENOSYS;
+
+ mutex_lock(&tz->lock);
+
+@@ -445,7 +448,7 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
+ }
+
+ mutex_unlock(&tz->lock);
+-exit:
++
+ return ret;
+ }
+ EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
+@@ -454,10 +457,11 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
+ {
+ int temp, ret, count;
+
+- if (!tz->ops->get_temp)
++ ret = thermal_zone_get_temp(tz, &temp);
++
++ if (ret == -ENOSYS)
+ return;
+
+- ret = thermal_zone_get_temp(tz, &temp);
+ if (ret) {
+ if (ret != -EAGAIN)
+ dev_warn(&tz->device,
+@@ -783,10 +787,16 @@ emul_temp_store(struct device *dev, struct device_attribute *attr,
+ if (kstrtoul(buf, 10, &temperature))
+ return -EINVAL;
+
+- if (!tz->ops->set_emul_temp) {
++ if (tz->ops->set_emul_temp)
++ ret = tz->ops->set_emul_temp(tz, temperature);
++ else
++ ret = -ENOSYS;
++
++ if (ret == -ENOSYS) {
+ mutex_lock(&tz->lock);
+ tz->emul_temperature = temperature;
+ mutex_unlock(&tz->lock);
++ ret = 0;
+ } else {
+ ret = tz->ops->set_emul_temp(tz, temperature);
+ }
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0018-thermal-of-always-set-sensor-related-callbacks.patch b/target/linux/mediatek/patches/0018-thermal-of-always-set-sensor-related-callbacks.patch
new file mode 100644
index 0000000000..e47e8a27f0
--- /dev/null
+++ b/target/linux/mediatek/patches/0018-thermal-of-always-set-sensor-related-callbacks.patch
@@ -0,0 +1,129 @@
+From 8c9c4ed500e92c10dc4965dcd00692b3102a328a Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:37 +0200
+Subject: [PATCH 18/76] thermal: of: always set sensor related callbacks
+
+Now that the thermal core treats -ENOSYS like the callbacks were
+not present at all we no longer have to overwrite the ops during
+runtime but instead can always set them and return -ENOSYS if no
+sensor is registered.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/thermal/of-thermal.c | 33 +++++++++++++--------------------
+ 1 file changed, 13 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
+index c84404d..b9c35bd 100644
+--- a/drivers/thermal/of-thermal.c
++++ b/drivers/thermal/of-thermal.c
+@@ -91,7 +91,7 @@ static int of_thermal_get_temp(struct thermal_zone_device *tz,
+ {
+ struct __thermal_zone *data = tz->devdata;
+
+- if (!data->ops->get_temp)
++ if (!data->ops)
+ return -EINVAL;
+
+ return data->ops->get_temp(data->sensor_data, temp);
+@@ -178,7 +178,7 @@ static int of_thermal_set_emul_temp(struct thermal_zone_device *tz,
+ struct __thermal_zone *data = tz->devdata;
+
+ if (!data->ops || !data->ops->set_emul_temp)
+- return -EINVAL;
++ return -ENOSYS;
+
+ return data->ops->set_emul_temp(data->sensor_data, temp);
+ }
+@@ -189,8 +189,8 @@ static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip,
+ struct __thermal_zone *data = tz->devdata;
+ int r;
+
+- if (!data->ops->get_trend)
+- return -EINVAL;
++ if (!data->ops || !data->ops->get_trend)
++ return -ENOSYS;
+
+ r = data->ops->get_trend(data->sensor_data, trip, trend);
+ if (r)
+@@ -366,6 +366,10 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
+ }
+
+ static struct thermal_zone_device_ops of_thermal_ops = {
++ .get_temp = of_thermal_get_temp,
++ .get_trend = of_thermal_get_trend,
++ .set_emul_temp = of_thermal_set_emul_temp,
++
+ .get_mode = of_thermal_get_mode,
+ .set_mode = of_thermal_set_mode,
+
+@@ -399,13 +403,13 @@ thermal_zone_of_add_sensor(struct device_node *zone,
+ if (!ops)
+ return ERR_PTR(-EINVAL);
+
++ if (!ops->get_temp)
++ return ERR_PTR(-EINVAL);
++
+ mutex_lock(&tzd->lock);
+ tz->ops = ops;
+ tz->sensor_data = data;
+
+- tzd->ops->get_temp = of_thermal_get_temp;
+- tzd->ops->get_trend = of_thermal_get_trend;
+- tzd->ops->set_emul_temp = of_thermal_set_emul_temp;
+ mutex_unlock(&tzd->lock);
+
+ return tzd;
+@@ -535,9 +539,6 @@ void thermal_zone_of_sensor_unregister(struct device *dev,
+ return;
+
+ mutex_lock(&tzd->lock);
+- tzd->ops->get_temp = NULL;
+- tzd->ops->get_trend = NULL;
+- tzd->ops->set_emul_temp = NULL;
+
+ tz->ops = NULL;
+ tz->sensor_data = NULL;
+@@ -845,7 +846,6 @@ int __init of_parse_thermal_zones(void)
+ {
+ struct device_node *np, *child;
+ struct __thermal_zone *tz;
+- struct thermal_zone_device_ops *ops;
+
+ np = of_find_node_by_name(NULL, "thermal-zones");
+ if (!np) {
+@@ -869,29 +869,22 @@ int __init of_parse_thermal_zones(void)
+ continue;
+ }
+
+- ops = kmemdup(&of_thermal_ops, sizeof(*ops), GFP_KERNEL);
+- if (!ops)
+- goto exit_free;
+-
+ tzp = kzalloc(sizeof(*tzp), GFP_KERNEL);
+- if (!tzp) {
+- kfree(ops);
++ if (!tzp)
+ goto exit_free;
+- }
+
+ /* No hwmon because there might be hwmon drivers registering */
+ tzp->no_hwmon = true;
+
+ zone = thermal_zone_device_register(child->name, tz->ntrips,
+ 0, tz,
+- ops, tzp,
++ &of_thermal_ops, tzp,
+ tz->passive_delay,
+ tz->polling_delay);
+ if (IS_ERR(zone)) {
+ pr_err("Failed to build %s zone %ld\n", child->name,
+ PTR_ERR(zone));
+ kfree(tzp);
+- kfree(ops);
+ of_thermal_free_zone(tz);
+ /* attempting to build remaining zones still */
+ }
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0019-thermal-Make-struct-thermal_zone_device_ops-const.patch b/target/linux/mediatek/patches/0019-thermal-Make-struct-thermal_zone_device_ops-const.patch
new file mode 100644
index 0000000000..1ca9ab8c2f
--- /dev/null
+++ b/target/linux/mediatek/patches/0019-thermal-Make-struct-thermal_zone_device_ops-const.patch
@@ -0,0 +1,327 @@
+From 7cbee588bc6eee59c025f89cf9324943fda98934 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:38 +0200
+Subject: [PATCH 19/76] thermal: Make struct thermal_zone_device_ops const
+
+Now that the of thermal support no longer changes the
+thermal_zone_device_ops it can be const again.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ Documentation/thermal/sysfs-api.txt | 2 +-
+ drivers/acpi/thermal.c | 2 +-
+ drivers/platform/x86/acerhdf.c | 2 +-
+ drivers/platform/x86/intel_mid_thermal.c | 2 +-
+ drivers/power/power_supply_core.c | 2 +-
+ drivers/thermal/armada_thermal.c | 2 +-
+ drivers/thermal/db8500_thermal.c | 2 +-
+ drivers/thermal/dove_thermal.c | 2 +-
+ drivers/thermal/imx_thermal.c | 2 +-
+ drivers/thermal/int340x_thermal/int3400_thermal.c | 2 +-
+ drivers/thermal/int340x_thermal/int340x_thermal_zone.c | 2 +-
+ drivers/thermal/intel_soc_dts_thermal.c | 2 +-
+ drivers/thermal/kirkwood_thermal.c | 2 +-
+ drivers/thermal/of-thermal.c | 2 +-
+ drivers/thermal/rcar_thermal.c | 2 +-
+ drivers/thermal/spear_thermal.c | 2 +-
+ drivers/thermal/st/st_thermal.c | 2 +-
+ drivers/thermal/thermal_core.c | 2 +-
+ drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 2 +-
+ drivers/thermal/x86_pkg_temp_thermal.c | 2 +-
+ include/linux/thermal.h | 6 +++---
+ 21 files changed, 23 insertions(+), 23 deletions(-)
+
+diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
+index 87519cb..bb346a2 100644
+--- a/Documentation/thermal/sysfs-api.txt
++++ b/Documentation/thermal/sysfs-api.txt
+@@ -33,7 +33,7 @@ temperature) and throttle appropriate devices.
+ 1.1 thermal zone device interface
+ 1.1.1 struct thermal_zone_device *thermal_zone_device_register(char *type,
+ int trips, int mask, void *devdata,
+- struct thermal_zone_device_ops *ops,
++ const struct thermal_zone_device_ops *ops,
+ const struct thermal_zone_params *tzp,
+ int passive_delay, int polling_delay))
+
+diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
+index 68bff60..6b11462 100644
+--- a/drivers/acpi/thermal.c
++++ b/drivers/acpi/thermal.c
+@@ -869,7 +869,7 @@ acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
+ return acpi_thermal_cooling_device_cb(thermal, cdev, false);
+ }
+
+-static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
++static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
+ .bind = acpi_thermal_bind_cooling_device,
+ .unbind = acpi_thermal_unbind_cooling_device,
+ .get_temp = thermal_get_temp,
+diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
+index f2ce63c..bae9ca0 100644
+--- a/drivers/platform/x86/acerhdf.c
++++ b/drivers/platform/x86/acerhdf.c
+@@ -482,7 +482,7 @@ static int acerhdf_get_crit_temp(struct thermal_zone_device *thermal,
+ }
+
+ /* bind callback functions to thermalzone */
+-static struct thermal_zone_device_ops acerhdf_dev_ops = {
++static const struct thermal_zone_device_ops acerhdf_dev_ops = {
+ .bind = acerhdf_bind,
+ .unbind = acerhdf_unbind,
+ .get_temp = acerhdf_get_ec_temp,
+diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c
+index 0944e83..069d36b 100644
+--- a/drivers/platform/x86/intel_mid_thermal.c
++++ b/drivers/platform/x86/intel_mid_thermal.c
+@@ -460,7 +460,7 @@ static int read_curr_temp(struct thermal_zone_device *tzd, unsigned long *temp)
+ }
+
+ /* Can't be const */
+-static struct thermal_zone_device_ops tzd_ops = {
++static const struct thermal_zone_device_ops tzd_ops = {
+ .get_temp = read_curr_temp,
+ };
+
+diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
+index 87e2fd1..878cb4e 100644
+--- a/drivers/power/power_supply_core.c
++++ b/drivers/power/power_supply_core.c
+@@ -509,7 +509,7 @@ static int power_supply_read_temp(struct thermal_zone_device *tzd,
+ return ret;
+ }
+
+-static struct thermal_zone_device_ops psy_tzd_ops = {
++static const struct thermal_zone_device_ops psy_tzd_ops = {
+ .get_temp = power_supply_read_temp,
+ };
+
+diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
+index 26b8d32..3f59c8b 100644
+--- a/drivers/thermal/armada_thermal.c
++++ b/drivers/thermal/armada_thermal.c
+@@ -183,7 +183,7 @@ static int armada_get_temp(struct thermal_zone_device *thermal,
+ return 0;
+ }
+
+-static struct thermal_zone_device_ops ops = {
++static const struct thermal_zone_device_ops ops = {
+ .get_temp = armada_get_temp,
+ };
+
+diff --git a/drivers/thermal/db8500_thermal.c b/drivers/thermal/db8500_thermal.c
+index b3eca71..38d6aab9 100644
+--- a/drivers/thermal/db8500_thermal.c
++++ b/drivers/thermal/db8500_thermal.c
+@@ -210,7 +210,7 @@ static int db8500_sys_get_crit_temp(struct thermal_zone_device *thermal,
+ return -EINVAL;
+ }
+
+-static struct thermal_zone_device_ops thdev_ops = {
++static const struct thermal_zone_device_ops thdev_ops = {
+ .bind = db8500_cdev_bind,
+ .unbind = db8500_cdev_unbind,
+ .get_temp = db8500_sys_get_temp,
+diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c
+index a0bc9de..e8fd627 100644
+--- a/drivers/thermal/dove_thermal.c
++++ b/drivers/thermal/dove_thermal.c
+@@ -118,7 +118,7 @@ static int dove_get_temp(struct thermal_zone_device *thermal,
+ return 0;
+ }
+
+-static struct thermal_zone_device_ops ops = {
++static const struct thermal_zone_device_ops ops = {
+ .get_temp = dove_get_temp,
+ };
+
+diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
+index f1424f0..8a3cfed 100644
+--- a/drivers/thermal/imx_thermal.c
++++ b/drivers/thermal/imx_thermal.c
+@@ -332,7 +332,7 @@ static int imx_unbind(struct thermal_zone_device *tz,
+ return 0;
+ }
+
+-static struct thermal_zone_device_ops imx_tz_ops = {
++static const struct thermal_zone_device_ops imx_tz_ops = {
+ .bind = imx_bind,
+ .unbind = imx_unbind,
+ .get_temp = imx_get_temp,
+diff --git a/drivers/thermal/int340x_thermal/int3400_thermal.c b/drivers/thermal/int340x_thermal/int3400_thermal.c
+index 031018e..96bdf8a 100644
+--- a/drivers/thermal/int340x_thermal/int3400_thermal.c
++++ b/drivers/thermal/int340x_thermal/int3400_thermal.c
+@@ -231,7 +231,7 @@ static int int3400_thermal_set_mode(struct thermal_zone_device *thermal,
+ return result;
+ }
+
+-static struct thermal_zone_device_ops int3400_thermal_ops = {
++static const struct thermal_zone_device_ops int3400_thermal_ops = {
+ .get_temp = int3400_thermal_get_temp,
+ };
+
+diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
+index b9b2666..bd9f9e8 100644
+--- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
++++ b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
+@@ -154,7 +154,7 @@ static int int340x_thermal_get_trip_hyst(struct thermal_zone_device *zone,
+ return 0;
+ }
+
+-static struct thermal_zone_device_ops int340x_thermal_zone_ops = {
++static const struct thermal_zone_device_ops int340x_thermal_zone_ops = {
+ .get_temp = int340x_thermal_get_zone_temp,
+ .get_trip_temp = int340x_thermal_get_trip_temp,
+ .get_trip_type = int340x_thermal_get_trip_type,
+diff --git a/drivers/thermal/intel_soc_dts_thermal.c b/drivers/thermal/intel_soc_dts_thermal.c
+index fd550b9..625ba6f 100644
+--- a/drivers/thermal/intel_soc_dts_thermal.c
++++ b/drivers/thermal/intel_soc_dts_thermal.c
+@@ -270,7 +270,7 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
+ return 0;
+ }
+
+-static struct thermal_zone_device_ops tzone_ops = {
++static const struct thermal_zone_device_ops tzone_ops = {
+ .get_temp = sys_get_curr_temp,
+ .get_trip_temp = sys_get_trip_temp,
+ .get_trip_type = sys_get_trip_type,
+diff --git a/drivers/thermal/kirkwood_thermal.c b/drivers/thermal/kirkwood_thermal.c
+index 11041fe..abba3e2 100644
+--- a/drivers/thermal/kirkwood_thermal.c
++++ b/drivers/thermal/kirkwood_thermal.c
+@@ -60,7 +60,7 @@ static int kirkwood_get_temp(struct thermal_zone_device *thermal,
+ return 0;
+ }
+
+-static struct thermal_zone_device_ops ops = {
++static const struct thermal_zone_device_ops ops = {
+ .get_temp = kirkwood_get_temp,
+ };
+
+diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
+index b9c35bd..bd3185e 100644
+--- a/drivers/thermal/of-thermal.c
++++ b/drivers/thermal/of-thermal.c
+@@ -365,7 +365,7 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
+ return -EINVAL;
+ }
+
+-static struct thermal_zone_device_ops of_thermal_ops = {
++static const struct thermal_zone_device_ops of_thermal_ops = {
+ .get_temp = of_thermal_get_temp,
+ .get_trend = of_thermal_get_trend,
+ .set_emul_temp = of_thermal_set_emul_temp,
+diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c
+index 5d4ae7d..320ceac 100644
+--- a/drivers/thermal/rcar_thermal.c
++++ b/drivers/thermal/rcar_thermal.c
+@@ -270,7 +270,7 @@ static int rcar_thermal_notify(struct thermal_zone_device *zone,
+ return 0;
+ }
+
+-static struct thermal_zone_device_ops rcar_thermal_zone_ops = {
++static const struct thermal_zone_device_ops rcar_thermal_zone_ops = {
+ .get_temp = rcar_thermal_get_temp,
+ .get_trip_type = rcar_thermal_get_trip_type,
+ .get_trip_temp = rcar_thermal_get_trip_temp,
+diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c
+index 534dd91..ec07743 100644
+--- a/drivers/thermal/spear_thermal.c
++++ b/drivers/thermal/spear_thermal.c
+@@ -50,7 +50,7 @@ static inline int thermal_get_temp(struct thermal_zone_device *thermal,
+ return 0;
+ }
+
+-static struct thermal_zone_device_ops ops = {
++static const struct thermal_zone_device_ops ops = {
+ .get_temp = thermal_get_temp,
+ };
+
+diff --git a/drivers/thermal/st/st_thermal.c b/drivers/thermal/st/st_thermal.c
+index 44cbba9..0cb5c19 100644
+--- a/drivers/thermal/st/st_thermal.c
++++ b/drivers/thermal/st/st_thermal.c
+@@ -175,7 +175,7 @@ static int st_thermal_get_trip_temp(struct thermal_zone_device *th,
+ return 0;
+ }
+
+-static struct thermal_zone_device_ops st_tz_ops = {
++static const struct thermal_zone_device_ops st_tz_ops = {
+ .get_temp = st_thermal_get_temp,
+ .get_trip_type = st_thermal_get_trip_type,
+ .get_trip_temp = st_thermal_get_trip_temp,
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index 3d8f9f9..6bbf61f 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -1451,7 +1451,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
+ */
+ struct thermal_zone_device *thermal_zone_device_register(const char *type,
+ int trips, int mask, void *devdata,
+- struct thermal_zone_device_ops *ops,
++ const struct thermal_zone_device_ops *ops,
+ const struct thermal_zone_params *tzp,
+ int passive_delay, int polling_delay)
+ {
+diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+index ade78eb..e9c82fc 100644
+--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
++++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+@@ -281,7 +281,7 @@ static const struct thermal_zone_of_device_ops ti_of_thermal_ops = {
+ .get_trend = __ti_thermal_get_trend,
+ };
+
+-static struct thermal_zone_device_ops ti_thermal_ops = {
++static const struct thermal_zone_device_ops ti_thermal_ops = {
+ .get_temp = ti_thermal_get_temp,
+ .get_trend = ti_thermal_get_trend,
+ .bind = ti_thermal_bind,
+diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c
+index 054c6d45..bb2b975 100644
+--- a/drivers/thermal/x86_pkg_temp_thermal.c
++++ b/drivers/thermal/x86_pkg_temp_thermal.c
+@@ -274,7 +274,7 @@ static int sys_get_trip_type(struct thermal_zone_device *thermal,
+ }
+
+ /* Thermal zone callback registry */
+-static struct thermal_zone_device_ops tzone_ops = {
++static const struct thermal_zone_device_ops tzone_ops = {
+ .get_temp = sys_get_curr_temp,
+ .get_trip_temp = sys_get_trip_temp,
+ .get_trip_type = sys_get_trip_type,
+diff --git a/include/linux/thermal.h b/include/linux/thermal.h
+index 5c6a589..07bd5e8 100644
+--- a/include/linux/thermal.h
++++ b/include/linux/thermal.h
+@@ -181,7 +181,7 @@ struct thermal_zone_device {
+ int emul_temperature;
+ int passive;
+ unsigned int forced_passive;
+- struct thermal_zone_device_ops *ops;
++ const struct thermal_zone_device_ops *ops;
+ const struct thermal_zone_params *tzp;
+ struct thermal_governor *governor;
+ struct list_head thermal_instances;
+@@ -313,7 +313,7 @@ void thermal_zone_of_sensor_unregister(struct device *dev,
+
+ #if IS_ENABLED(CONFIG_THERMAL)
+ struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
+- void *, struct thermal_zone_device_ops *,
++ void *, const struct thermal_zone_device_ops *,
+ const struct thermal_zone_params *, int, int);
+ void thermal_zone_device_unregister(struct thermal_zone_device *);
+
+@@ -341,7 +341,7 @@ void thermal_notify_framework(struct thermal_zone_device *, int);
+ #else
+ static inline struct thermal_zone_device *thermal_zone_device_register(
+ const char *type, int trips, int mask, void *devdata,
+- struct thermal_zone_device_ops *ops,
++ const struct thermal_zone_device_ops *ops,
+ const struct thermal_zone_params *tzp,
+ int passive_delay, int polling_delay)
+ { return ERR_PTR(-ENODEV); }
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0020-thermal-thermal-Add-support-for-hardware-tracked-tri.patch b/target/linux/mediatek/patches/0020-thermal-thermal-Add-support-for-hardware-tracked-tri.patch
new file mode 100644
index 0000000000..6a48350039
--- /dev/null
+++ b/target/linux/mediatek/patches/0020-thermal-thermal-Add-support-for-hardware-tracked-tri.patch
@@ -0,0 +1,124 @@
+From 346632bc00fe71c269709702fecb474bb22e933e Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:39 +0200
+Subject: [PATCH 20/76] thermal: thermal: Add support for hardware-tracked
+ trip points
+
+This adds support for hardware-tracked trip points to the device tree
+thermal sensor framework.
+
+The framework supports an arbitrary number of trip points. Whenever
+the current temperature is updated, the trip points immediately
+below and above the current temperature are found. A .set_trips
+callback is then called with the temperatures. If there is no trip
+point above or below the current temperature, the passed trip
+temperature will be -INT_MAX or INT_MAX respectively. In this callback,
+the driver should program the hardware such that it is notified
+when either of these trip points are triggered. When a trip point
+is triggered, the driver should call `thermal_zone_device_update'
+for the respective thermal zone. This will cause the trip points
+to be updated again.
+
+If .set_trips is not implemented, the framework behaves as before.
+
+This patch is based on an earlier version from Mikko Perttunen
+<mikko.perttunen@kapsi.fi>
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/thermal/thermal_core.c | 43 ++++++++++++++++++++++++++++++++++++++++
+ include/linux/thermal.h | 3 +++
+ 2 files changed, 46 insertions(+)
+
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index 6bbf61f..3ae1795 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -453,6 +453,45 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
+ }
+ EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
+
++static void thermal_zone_set_trips(struct thermal_zone_device *tz)
++{
++ int low = -INT_MAX;
++ int high = INT_MAX;
++ int trip_temp, hysteresis;
++ int temp = tz->temperature;
++ int i;
++
++ if (!tz->ops->set_trips)
++ return;
++
++ /* No need to change trip points */
++ if (temp > tz->prev_low_trip && temp < tz->prev_high_trip)
++ return;
++
++ for (i = 0; i < tz->trips; i++) {
++ int trip_low;
++
++ tz->ops->get_trip_temp(tz, i, &trip_temp);
++ tz->ops->get_trip_hyst(tz, i, &hysteresis);
++
++ trip_low = trip_temp - hysteresis;
++
++ if (trip_low < temp && trip_low > low)
++ low = trip_low;
++
++ if (trip_temp > temp && trip_temp < high)
++ high = trip_temp;
++ }
++
++ tz->prev_low_trip = low;
++ tz->prev_high_trip = high;
++
++ dev_dbg(&tz->device, "new temperature boundaries: %d < x < %d\n",
++ low, high);
++
++ tz->ops->set_trips(tz, low, high);
++}
++
+ void thermal_zone_device_update(struct thermal_zone_device *tz)
+ {
+ int temp, ret, count;
+@@ -479,6 +518,8 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
+ dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
+ tz->last_temperature, tz->temperature);
+
++ thermal_zone_set_trips(tz);
++
+ for (count = 0; count < tz->trips; count++)
+ handle_thermal_trip(tz, count);
+ }
+@@ -1494,6 +1535,8 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
+ tz->trips = trips;
+ tz->passive_delay = passive_delay;
+ tz->polling_delay = polling_delay;
++ tz->prev_low_trip = INT_MAX;
++ tz->prev_high_trip = -INT_MAX;
+
+ dev_set_name(&tz->device, "thermal_zone%d", tz->id);
+ result = device_register(&tz->device);
+diff --git a/include/linux/thermal.h b/include/linux/thermal.h
+index 07bd5e8..aef6e13 100644
+--- a/include/linux/thermal.h
++++ b/include/linux/thermal.h
+@@ -87,6 +87,7 @@ struct thermal_zone_device_ops {
+ int (*unbind) (struct thermal_zone_device *,
+ struct thermal_cooling_device *);
+ int (*get_temp) (struct thermal_zone_device *, int *);
++ int (*set_trips) (struct thermal_zone_device *, int, int);
+ int (*get_mode) (struct thermal_zone_device *,
+ enum thermal_device_mode *);
+ int (*set_mode) (struct thermal_zone_device *,
+@@ -180,6 +181,8 @@ struct thermal_zone_device {
+ int last_temperature;
+ int emul_temperature;
+ int passive;
++ int prev_low_trip;
++ int prev_high_trip;
+ unsigned int forced_passive;
+ const struct thermal_zone_device_ops *ops;
+ const struct thermal_zone_params *tzp;
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0021-thermal-of-implement-.set_trips-for-device-tree-ther.patch b/target/linux/mediatek/patches/0021-thermal-of-implement-.set_trips-for-device-tree-ther.patch
new file mode 100644
index 0000000000..81b50431c6
--- /dev/null
+++ b/target/linux/mediatek/patches/0021-thermal-of-implement-.set_trips-for-device-tree-ther.patch
@@ -0,0 +1,65 @@
+From 525f68bb9d9f6334dbcd2b5ec99f9d797ff53618 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:40 +0200
+Subject: [PATCH 21/76] thermal: of: implement .set_trips for device tree
+ thermal zones
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/thermal/of-thermal.c | 12 ++++++++++++
+ include/linux/thermal.h | 3 +++
+ 2 files changed, 15 insertions(+)
+
+diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
+index bd3185e..f8dd847 100644
+--- a/drivers/thermal/of-thermal.c
++++ b/drivers/thermal/of-thermal.c
+@@ -97,6 +97,17 @@ static int of_thermal_get_temp(struct thermal_zone_device *tz,
+ return data->ops->get_temp(data->sensor_data, temp);
+ }
+
++static int of_thermal_set_trips(struct thermal_zone_device *tz,
++ int low, int high)
++{
++ struct __thermal_zone *data = tz->devdata;
++
++ if (!data->ops || !data->ops->set_trips)
++ return -ENOSYS;
++
++ return data->ops->set_trips(data->sensor_data, low, high);
++}
++
+ /**
+ * of_thermal_get_ntrips - function to export number of available trip
+ * points.
+@@ -367,6 +378,7 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
+
+ static const struct thermal_zone_device_ops of_thermal_ops = {
+ .get_temp = of_thermal_get_temp,
++ .set_trips = of_thermal_set_trips,
+ .get_trend = of_thermal_get_trend,
+ .set_emul_temp = of_thermal_set_emul_temp,
+
+diff --git a/include/linux/thermal.h b/include/linux/thermal.h
+index aef6e13..b751f6b 100644
+--- a/include/linux/thermal.h
++++ b/include/linux/thermal.h
+@@ -267,12 +267,15 @@ struct thermal_genl_event {
+ *
+ * Optional:
+ * @get_trend: a pointer to a function that reads the sensor temperature trend.
++ * @set_trips: a pointer to a function that sets a temperature window which shall
++ * trigger an interrupt when it is left.
+ * @set_emul_temp: a pointer to a function that sets sensor emulated
+ * temperature.
+ */
+ struct thermal_zone_of_device_ops {
+ int (*get_temp)(void *, int *);
+ int (*get_trend)(void *, int, enum thermal_trend *);
++ int (*set_trips)(void *, int, int);
+ int (*set_emul_temp)(void *, int);
+ };
+
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0022-dt-bindings-thermal-Add-binding-document-for-Mediate.patch b/target/linux/mediatek/patches/0022-dt-bindings-thermal-Add-binding-document-for-Mediate.patch
new file mode 100644
index 0000000000..c556ac08b5
--- /dev/null
+++ b/target/linux/mediatek/patches/0022-dt-bindings-thermal-Add-binding-document-for-Mediate.patch
@@ -0,0 +1,57 @@
+From 9b799b8a4ecbf560f8fb996e8e5147a8f7b9a1b3 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:41 +0200
+Subject: [PATCH 22/76] dt-bindings: thermal: Add binding document for
+ Mediatek thermal controller
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ .../bindings/thermal/mediatek-thermal.txt | 36 ++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
+
+diff --git a/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
+new file mode 100644
+index 0000000..adf5d2c
+--- /dev/null
++++ b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
+@@ -0,0 +1,36 @@
++* Mediatek Thermal
++
++This describes the device tree binding for the Mediatek thermal controller
++which measures the on-SoC temperatures. This device does not have its own ADC,
++instead it directly controls the AUXADC via AHB bus accesses. For this reason
++this device needs phandles to the AUXADC.
++
++Required properties:
++- compatible: "mediatek,mt8173-thermal"
++- reg: Address range of the thermal controller
++- interrupts: IRQ for the thermal controller
++- clocks, clock-names: Clocks needed for the thermal controller. required
++ clocks are:
++ "therm": Main clock needed for register access
++ "auxadc": The AUXADC clock
++- resets, reset-names: Reference to the reset controller controlling the thermal
++ controller. Required reset-names:
++ "therm": The main reset line
++- auxadc: A phandle to the AUXADC which the thermal controller uses
++- apmixedsys: A phandle to the APMIXEDSYS controller.
++- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description
++
++Example:
++
++ thermal: thermal@1100b000 {
++ #thermal-sensor-cells = <1>;
++ compatible = "mediatek,mt8173-thermal";
++ reg = <0 0x1100b000 0 0x1000>;
++ interrupts = <0 70 IRQ_TYPE_LEVEL_LOW>;
++ clocks = <&pericfg CLK_PERI_THERM>, <&pericfg CLK_PERI_AUXADC>;
++ clock-names = "therm", "auxadc";
++ resets = <&pericfg MT8173_PERI_THERM_SW_RST>;
++ reset-names = "therm";
++ auxadc = <&auxadc>;
++ apmixedsys = <&apmixedsys>;
++ };
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0023-thermal-Add-Mediatek-thermal-controller-support.patch b/target/linux/mediatek/patches/0023-thermal-Add-Mediatek-thermal-controller-support.patch
new file mode 100644
index 0000000000..827d721138
--- /dev/null
+++ b/target/linux/mediatek/patches/0023-thermal-Add-Mediatek-thermal-controller-support.patch
@@ -0,0 +1,785 @@
+From 014330a304100782a26bc7df02778c8c386b2857 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:42 +0200
+Subject: [PATCH 23/76] thermal: Add Mediatek thermal controller support
+
+This adds support for the Mediatek thermal controller found on MT8173
+and likely other SoCs.
+The controller is a bit special. It does not have its own ADC, instead
+it controls the on-SoC AUXADC via AHB bus accesses. For this reason
+we need the physical address of the AUXADC. Also it controls a mux
+using AHB bus accesses, so we need the APMIXEDSYS physical address aswell.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/thermal/Kconfig | 8 +
+ drivers/thermal/Makefile | 1 +
+ drivers/thermal/mtk_thermal.c | 728 +++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 737 insertions(+)
+ create mode 100644 drivers/thermal/mtk_thermal.c
+
+diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
+index af40db0..3aa5500 100644
+--- a/drivers/thermal/Kconfig
++++ b/drivers/thermal/Kconfig
+@@ -285,6 +285,14 @@ config ACPI_THERMAL_REL
+ tristate
+ depends on ACPI
+
++config MTK_THERMAL
++ tristate "Temperature sensor driver for mediatek SoCs"
++ depends on ARCH_MEDIATEK || COMPILE_TEST
++ default y
++ help
++ Enable this option if you want to have support for thermal management
++ controller present in Mediatek SoCs
++
+ menu "Texas Instruments thermal drivers"
+ source "drivers/thermal/ti-soc-thermal/Kconfig"
+ endmenu
+diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
+index fa0dc48..51cfab7 100644
+--- a/drivers/thermal/Makefile
++++ b/drivers/thermal/Makefile
+@@ -39,3 +39,4 @@ obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/
+ obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal/
+ obj-$(CONFIG_ST_THERMAL) += st/
+ obj-$(CONFIG_TEGRA_SOCTHERM) += tegra_soctherm.o
++obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
+diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
+new file mode 100644
+index 0000000..27aab12
+--- /dev/null
++++ b/drivers/thermal/mtk_thermal.c
+@@ -0,0 +1,728 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Hanyi.Wu <hanyi.wu@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/dmi.h>
++#include <linux/thermal.h>
++#include <linux/platform_device.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++#include <linux/slab.h>
++#include <linux/clk.h>
++#include <linux/time.h>
++#include <linux/of.h>
++#include <linux/of_irq.h>
++#include <linux/of_address.h>
++#include <linux/interrupt.h>
++#include <linux/reset.h>
++
++/* AUXADC Registers */
++#define AUXADC_CON0_V 0x000
++#define AUXADC_CON1_V 0x004
++#define AUXADC_CON1_SET_V 0x008
++#define AUXADC_CON1_CLR_V 0x00c
++#define AUXADC_CON2_V 0x010
++#define AUXADC_DATA(channel) (0x14 + (channel) * 4)
++#define AUXADC_MISC_V 0x094
++
++#define AUXADC_CON1_CHANNEL(x) (1 << (x))
++
++/* Thermal Controller Registers */
++#define TEMPMONCTL0 0x000
++#define TEMPMONCTL1 0x004
++#define TEMPMONCTL2 0x008
++#define TEMPMONINT 0x00c
++#define TEMPMONINTSTS 0x010
++#define TEMPMONIDET0 0x014
++#define TEMPMONIDET1 0x018
++#define TEMPMONIDET2 0x01c
++#define TEMPH2NTHRE 0x024
++#define TEMPHTHRE 0x028
++#define TEMPCTHRE 0x02c
++#define TEMPOFFSETH 0x030
++#define TEMPOFFSETL 0x034
++#define TEMPMSRCTL0 0x038
++#define TEMPMSRCTL1 0x03c
++#define TEMPAHBPOLL 0x040
++#define TEMPAHBTO 0x044
++#define TEMPADCPNP0 0x048
++#define TEMPADCPNP1 0x04c
++#define TEMPADCPNP2 0x050
++#define TEMPADCPNP3 0x0b4
++
++#define TEMPADCMUX 0x054
++#define TEMPADCEXT 0x058
++#define TEMPADCEXT1 0x05c
++#define TEMPADCEN 0x060
++#define TEMPPNPMUXADDR 0x064
++#define TEMPADCMUXADDR 0x068
++#define TEMPADCEXTADDR 0x06c
++#define TEMPADCEXT1ADDR 0x070
++#define TEMPADCENADDR 0x074
++#define TEMPADCVALIDADDR 0x078
++#define TEMPADCVOLTADDR 0x07c
++#define TEMPRDCTRL 0x080
++#define TEMPADCVALIDMASK 0x084
++#define TEMPADCVOLTAGESHIFT 0x088
++#define TEMPADCWRITECTRL 0x08c
++#define TEMPMSR0 0x090
++#define TEMPMSR1 0x094
++#define TEMPMSR2 0x098
++#define TEMPMSR3 0x0B8
++
++#define TEMPIMMD0 0x0a0
++#define TEMPIMMD1 0x0a4
++#define TEMPIMMD2 0x0a8
++
++#define TEMPPROTCTL 0x0c0
++#define TEMPPROTTA 0x0c4
++#define TEMPPROTTB 0x0c8
++#define TEMPPROTTC 0x0cc
++
++#define TEMPSPARE0 0x0f0
++#define TEMPSPARE1 0x0f4
++#define TEMPSPARE2 0x0f8
++#define TEMPSPARE3 0x0fc
++
++#define PTPCORESEL 0x400
++#define THERMINTST 0x404
++#define PTPODINTST 0x408
++#define THSTAGE0ST 0x40c
++#define THSTAGE1ST 0x410
++#define THSTAGE2ST 0x414
++#define THAHBST0 0x418
++#define THAHBST1 0x41c /* Only for DE debug */
++#define PTPSPARE0 0x420
++#define PTPSPARE1 0x424
++#define PTPSPARE2 0x428
++#define PTPSPARE3 0x42c
++#define THSLPEVEB 0x430
++
++#define TEMPMONINT_COLD(sp) ((1 << 0) << ((sp) * 5))
++#define TEMPMONINT_HOT(sp) ((1 << 1) << ((sp) * 5))
++#define TEMPMONINT_LOW_OFS(sp) ((1 << 2) << ((sp) * 5))
++#define TEMPMONINT_HIGH_OFS(sp) ((1 << 3) << ((sp) * 5))
++#define TEMPMONINT_HOT_TO_NORM(sp) ((1 << 4) << ((sp) * 5))
++#define TEMPMONINT_TIMEOUT (1 << 15)
++#define TEMPMONINT_IMMEDIATE_SENSE(sp) (1 << (16 + (sp)))
++#define TEMPMONINT_FILTER_SENSE(sp) (1 << (19 + (sp)))
++
++#define TEMPADCWRITECTRL_ADC_PNP_WRITE (1 << 0)
++#define TEMPADCWRITECTRL_ADC_MUX_WRITE (1 << 1)
++#define TEMPADCWRITECTRL_ADC_EXTRA_WRITE (1 << 2)
++#define TEMPADCWRITECTRL_ADC_EXTRA1_WRITE (1 << 3)
++
++#define TEMPADCVALIDMASK_VALID_HIGH (1 << 5)
++#define TEMPADCVALIDMASK_VALID_POS(bit) (bit)
++
++#define TEMPPROTCTL_AVERAGE (0 << 16)
++#define TEMPPROTCTL_MAXIMUM (1 << 16)
++#define TEMPPROTCTL_SELECTED (2 << 16)
++
++#define MT8173_THERMAL_ZONE_CA57 0
++#define MT8173_THERMAL_ZONE_CA53 1
++#define MT8173_THERMAL_ZONE_GPU 2
++#define MT8173_THERMAL_ZONE_CORE 3
++
++#define MT8173_TS1 0
++#define MT8173_TS2 1
++#define MT8173_TS3 2
++#define MT8173_TS4 3
++#define MT8173_TSABB 4
++
++/* AUXADC channel 11 is used for the temperature sensors */
++#define MT8173_TEMP_AUXADC_CHANNEL 11
++
++/* The total number of temperature sensors in the MT8173 */
++#define MT8173_NUM_SENSORS 5
++
++/* The number of banks in the MT8173 */
++#define MT8173_NUM_BANKS 4
++
++/* The number of sensing points per bank */
++#define MT8173_NUM_SENSING_POINTS 4
++
++#define THERMAL_NAME "mtk-thermal"
++
++struct mtk_thermal;
++
++struct mtk_thermal_bank {
++ struct mtk_thermal *mt;
++ struct thermal_zone_device *tz;
++ int id;
++};
++
++struct mtk_thermal {
++ struct device *dev;
++ void __iomem *thermal_base;
++ void __iomem *auxadc_base;
++
++ u64 auxadc_phys_base;
++ u64 apmixed_phys_base;
++ struct reset_control *reset;
++ struct clk *clk_peri_therm;
++ struct clk *clk_auxadc;
++
++ struct mtk_thermal_bank banks[MT8173_NUM_BANKS];
++
++ struct mutex lock;
++
++ /* Calibration values */
++ s32 adc_ge;
++ s32 adc_oe;
++ s32 degc_cali;
++ s32 o_slope;
++ s32 vts;
++};
++
++struct mtk_thermal_bank_cfg {
++ unsigned int enable_mask;
++ unsigned int sensors[4];
++};
++
++static int sensor_mux_values[MT8173_NUM_SENSORS] = { 0, 1, 2, 3, 16 };
++
++/*
++ * The MT8173 thermal controller has four banks. Each bank can read up to
++ * four temperature sensors simultaneously. The MT8173 has a total of 5
++ * temperature sensors. We use each bank to measure a certain area of the
++ * SoC. Since TS2 is located centrally in the SoC it is influenced by multiple
++ * areas, hence is used in different banks.
++ */
++static struct mtk_thermal_bank_cfg bank_data[] = {
++ {
++ .enable_mask = 3,
++ .sensors = { MT8173_TS2, MT8173_TS3 },
++ }, {
++ .enable_mask = 3,
++ .sensors = { MT8173_TS2, MT8173_TS4 },
++ }, {
++ .enable_mask = 7,
++ .sensors = { MT8173_TS1, MT8173_TS2, MT8173_TSABB },
++ }, {
++ .enable_mask = 1,
++ .sensors = { MT8173_TS2 },
++ },
++};
++
++static int tempmsr_ofs[MT8173_NUM_SENSING_POINTS] = {
++ TEMPMSR0, TEMPMSR1, TEMPMSR2, TEMPMSR3
++};
++
++static int tempadcpnp_ofs[MT8173_NUM_SENSING_POINTS] = {
++ TEMPADCPNP0, TEMPADCPNP1, TEMPADCPNP2, TEMPADCPNP3
++};
++
++/**
++ * raw_to_mcelsius - convert a raw ADC value to mcelsius
++ * @mt: The thermal controller
++ * @raw: raw ADC value
++ *
++ * This converts the raw ADC value to mcelsius using the SoC specific
++ * calibration constants
++ */
++static int raw_to_mcelsius(struct mtk_thermal *mt, u32 raw)
++{
++ s32 format_1, format_2, format_3, format_4;
++ s32 xtoomt;
++ s32 gain;
++
++ raw &= 0xfff;
++
++ gain = (10000 + mt->adc_ge);
++
++ xtoomt = ((((mt->vts + 3350 - mt->adc_oe) * 10000) / 4096) * 10000) /
++ gain;
++
++ format_1 = ((mt->degc_cali * 10) >> 1);
++ format_2 = (raw - mt->adc_oe);
++ format_3 = (((((format_2) * 10000) >> 12) * 10000) / gain) - xtoomt;
++ format_3 = format_3 * 15 / 18;
++ format_4 = ((format_3 * 100) / (165 + mt->o_slope));
++ format_4 = format_4 - (format_4 << 1);
++
++ return (format_1 + format_4) * 100;
++}
++
++/**
++ * mcelsius_to_raw - convert mcelsius to raw ADC value
++ * @mt: The thermal controller
++ * @temp: The temperature in mcelsius
++ *
++ * This converts a temperature in mcelsius to a raw ADC value, needed to
++ * calculate the trigger values for interrupt generation.
++ */
++static u32 mcelsius_to_raw(struct mtk_thermal *mt, int temp)
++{
++ s32 format_1, format_2, format_3, format_4;
++ s32 xtoomt;
++ s32 gain;
++
++ gain = (10000 + mt->adc_ge);
++
++ xtoomt = ((((mt->vts + 3350 - mt->adc_oe) * 10000) / 4096) * 10000) /
++ gain;
++
++ format_1 = temp - (mt->degc_cali * 1000 / 2);
++ format_2 = format_1 * (165 + mt->o_slope) * 18 / 15;
++ format_2 = format_2 - 2 * format_2;
++ format_3 = format_2 / 1000 + xtoomt * 10;
++ format_4 = (format_3 * 4096 / 10000 * gain) / 100000 + mt->adc_oe;
++
++ return format_4;
++}
++
++/**
++ * mtk_thermal_get_bank - get bank
++ * @bank: The bank
++ *
++ * The bank registers are banked, we have to select a bank in the
++ * PTPCORESEL register to access it.
++ */
++static void mtk_thermal_get_bank(struct mtk_thermal_bank *bank)
++{
++ struct mtk_thermal *mt = bank->mt;
++ u32 val;
++
++ mutex_lock(&mt->lock);
++
++ val = readl(mt->thermal_base + PTPCORESEL);
++ val &= ~0xf;
++ val |= bank->id;
++ writel(val, mt->thermal_base + PTPCORESEL);
++}
++
++/**
++ * mtk_thermal_put_bank - release bank
++ * @bank: The bank
++ *
++ * release a bank previously taken with mtk_thermal_get_bank,
++ */
++static void mtk_thermal_put_bank(struct mtk_thermal_bank *bank)
++{
++ struct mtk_thermal *mt = bank->mt;
++
++ mutex_unlock(&mt->lock);
++}
++
++/**
++ * mtk_thermal_bank_temperature - get the temperature of a bank
++ * @bank: The bank
++ *
++ * The temperature of a bank is considered the maximum temperature of
++ * the sensors associated to the bank.
++ */
++static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
++{
++ struct mtk_thermal *mt = bank->mt;
++ int temp, i, max;
++ u32 raw;
++
++ temp = max = -INT_MAX;
++
++ for (i = 0; i < 4; i++) {
++ int sensno;
++
++ if (!(bank_data[bank->id].enable_mask & (1 << i)))
++ continue;
++
++ raw = readl(mt->thermal_base + tempmsr_ofs[i]);
++
++ sensno = bank_data[bank->id].sensors[i];
++ temp = raw_to_mcelsius(mt, raw);
++
++ if (temp > max)
++ max = temp;
++ }
++
++ return max;
++}
++
++static void mtk_thermal_irq_bank(struct mtk_thermal_bank *bank)
++{
++ struct mtk_thermal *mt = bank->mt;
++ int sp;
++ u32 irqstat;
++ bool update = false;
++
++ mtk_thermal_get_bank(bank);
++
++ irqstat = readl(mt->thermal_base + TEMPMONINTSTS);
++
++ mtk_thermal_put_bank(bank);
++
++ for (sp = 0; sp < 3; sp++) {
++ if (irqstat & TEMPMONINT_LOW_OFS(sp)) {
++ update = true;
++ dev_vdbg(mt->dev, "bank %d sensor %d low offset interrupt\n",
++ bank->id, sp);
++ }
++
++ if (irqstat & TEMPMONINT_HIGH_OFS(sp)) {
++ update = true;
++ dev_vdbg(mt->dev, "bank %d sensor %d high offset interrupt\n",
++ bank->id, sp);
++ }
++ }
++
++ if (update)
++ thermal_zone_device_update(bank->tz);
++}
++
++static irqreturn_t mtk_thermal_irq(int irq, void *dev_id)
++{
++ struct mtk_thermal *mt = dev_id;
++ u32 irqstat = 0;
++ int i;
++
++ irqstat = readl(mt->thermal_base + THERMINTST);
++
++ dev_vdbg(mt->dev, "thermal_interrupt_handler : THERMINTST = 0x%x\n",
++ irqstat);
++
++ for (i = 0; i < MT8173_NUM_BANKS; i++) {
++ if (!(irqstat & (1 << i)))
++ mtk_thermal_irq_bank(&mt->banks[i]);
++ }
++
++ return IRQ_HANDLED;
++}
++
++static int mtk_read_temp(void *data, int *temp)
++{
++ struct mtk_thermal_bank *bank = data;
++
++ mtk_thermal_get_bank(bank);
++
++ *temp = mtk_thermal_bank_temperature(bank);
++
++ mtk_thermal_put_bank(bank);
++
++ return 0;
++}
++
++static int mtk_set_trips(void *data, int low, int high)
++{
++ struct mtk_thermal_bank *bank = data;
++ struct mtk_thermal *mt = bank->mt;
++ int i;
++ u32 val, enable_mask;
++ u32 raw_low, raw_high;
++
++ raw_low = mcelsius_to_raw(mt, low);
++ raw_high = mcelsius_to_raw(mt, high);
++
++ mtk_thermal_get_bank(bank);
++
++ writel(0x0, mt->thermal_base + TEMPMONINT);
++
++ writel(TEMPPROTCTL_SELECTED, mt->thermal_base + TEMPPROTCTL);
++
++ writel(raw_low, mt->thermal_base + TEMPOFFSETL);
++ writel(raw_high, mt->thermal_base + TEMPOFFSETH);
++
++ enable_mask = readl(mt->thermal_base + TEMPMONCTL0);
++
++ val = 0;
++ for (i = 0; i < MT8173_NUM_SENSING_POINTS; i++)
++ if (enable_mask & (1 << i))
++ val |= TEMPMONINT_LOW_OFS(i) | TEMPMONINT_HIGH_OFS(i);
++
++ writel(val, mt->thermal_base + TEMPMONINT);
++
++ mtk_thermal_put_bank(bank);
++
++ dev_dbg(mt->dev, "new boundaries: %d (0x%04x) < x < %d (0x%04x)\n",
++ low, mcelsius_to_raw(mt, low),
++ high, mcelsius_to_raw(mt, high));
++
++ return 0;
++}
++
++static const struct thermal_zone_of_device_ops mtk_thermal_ops = {
++ .get_temp = mtk_read_temp,
++ .set_trips = mtk_set_trips,
++};
++
++static void mtk_thermal_init_bank(struct mtk_thermal_bank *bank)
++{
++ struct mtk_thermal *mt = bank->mt;
++ struct mtk_thermal_bank_cfg *cfg = &bank_data[bank->id];
++ int i;
++
++ mtk_thermal_get_bank(bank);
++
++ /* bus clock 66M counting unit is 12 * 15.15ns * 256 = 46.540us */
++ writel(0x0000000c, mt->thermal_base + TEMPMONCTL1);
++
++ /*
++ * filt interval is 1 * 46.540us = 46.54us,
++ * sen interval is 429 * 46.540us = 19.96ms
++ */
++ writel(0x000101ad, mt->thermal_base + TEMPMONCTL2);
++
++ /* poll is set to 10u */
++ writel(0x00000300, mt->thermal_base + TEMPAHBPOLL);
++
++ /* temperature sampling control, 1 sample */
++ writel(0x00000000, mt->thermal_base + TEMPMSRCTL0);
++
++ /* exceed this polling time, IRQ would be inserted */
++ writel(0xffffffff, mt->thermal_base + TEMPAHBTO);
++
++ /* number of interrupts per event, 1 is enough */
++ writel(0x0, mt->thermal_base + TEMPMONIDET0);
++ writel(0x0, mt->thermal_base + TEMPMONIDET1);
++
++ /*
++ * The MT8173 thermal controller does not have its own ADC. Instead it
++ * uses AHB bus accesses to control the AUXADC. To do this the thermal
++ * controller has to be programmed with the physical addresses of the
++ * AUXADC registers and with the various bit positions in the AUXADC.
++ * Also the thermal controller controls a mux in the APMIXEDSYS register
++ * space.
++ */
++
++ /*
++ * this value will be stored to TEMPPNPMUXADDR (TEMPSPARE0)
++ * automatically by hw
++ */
++ writel(1 << MT8173_TEMP_AUXADC_CHANNEL, mt->thermal_base + TEMPADCMUX);
++
++ /* AHB address for auxadc mux selection */
++ writel(mt->auxadc_phys_base + 0x00c,
++ mt->thermal_base + TEMPADCMUXADDR);
++
++ /* AHB address for pnp sensor mux selection */
++ writel(mt->apmixed_phys_base + 0x0604,
++ mt->thermal_base + TEMPPNPMUXADDR);
++
++ /* AHB value for auxadc enable */
++ writel(1 << MT8173_TEMP_AUXADC_CHANNEL, mt->thermal_base + TEMPADCEN);
++
++ /* AHB address for auxadc enable (channel 0 immediate mode selected) */
++ writel(mt->auxadc_phys_base + AUXADC_CON1_SET_V,
++ mt->thermal_base + TEMPADCENADDR);
++
++ /* AHB address for auxadc valid bit */
++ writel(mt->auxadc_phys_base + AUXADC_DATA(MT8173_TEMP_AUXADC_CHANNEL),
++ mt->thermal_base + TEMPADCVALIDADDR);
++
++ /* AHB address for auxadc voltage output */
++ writel(mt->auxadc_phys_base + AUXADC_DATA(MT8173_TEMP_AUXADC_CHANNEL),
++ mt->thermal_base + TEMPADCVOLTADDR);
++
++ /* read valid & voltage are at the same register */
++ writel(0x0, mt->thermal_base + TEMPRDCTRL);
++
++ /* indicate where the valid bit is */
++ writel(TEMPADCVALIDMASK_VALID_HIGH | TEMPADCVALIDMASK_VALID_POS(12),
++ mt->thermal_base + TEMPADCVALIDMASK);
++
++ /* no shift */
++ writel(0x0, mt->thermal_base + TEMPADCVOLTAGESHIFT);
++
++ /* enable auxadc mux write transaction */
++ writel(TEMPADCWRITECTRL_ADC_MUX_WRITE,
++ mt->thermal_base + TEMPADCWRITECTRL);
++
++ for (i = 0; i < MT8173_NUM_SENSING_POINTS; i++)
++ writel(sensor_mux_values[cfg->sensors[i]],
++ mt->thermal_base + tempadcpnp_ofs[i]);
++
++ writel(cfg->enable_mask, mt->thermal_base + TEMPMONCTL0);
++
++ writel(TEMPADCWRITECTRL_ADC_PNP_WRITE | TEMPADCWRITECTRL_ADC_MUX_WRITE,
++ mt->thermal_base + TEMPADCWRITECTRL);
++
++ mtk_thermal_put_bank(bank);
++}
++
++static u64 of_get_phys_base(struct device_node *np)
++{
++ u64 size64;
++ const __be32 *regaddr_p;
++
++ regaddr_p = of_get_address(np, 0, &size64, NULL);
++ if (!regaddr_p)
++ return OF_BAD_ADDR;
++
++ return of_translate_address(np, regaddr_p);
++}
++
++static int mtk_thermal_probe(struct platform_device *pdev)
++{
++ int ret, i;
++ struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node;
++ int irq;
++ struct mtk_thermal *mt;
++ struct resource *res;
++
++ mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
++ if (!mt)
++ return -ENOMEM;
++
++ mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm");
++ if (IS_ERR(mt->clk_peri_therm))
++ return PTR_ERR(mt->clk_peri_therm);
++
++ mt->clk_auxadc = devm_clk_get(&pdev->dev, "auxadc");
++ if (IS_ERR(mt->clk_auxadc))
++ return PTR_ERR(mt->clk_auxadc);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ mt->thermal_base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(mt->thermal_base))
++ return PTR_ERR(mt->thermal_base);
++
++ mt->reset = devm_reset_control_get(&pdev->dev, "therm");
++ if (IS_ERR(mt->reset)) {
++ ret = PTR_ERR(mt->reset);
++ dev_err(&pdev->dev, "cannot get reset: %d\n", ret);
++ return ret;
++ }
++
++ mutex_init(&mt->lock);
++
++ mt->dev = &pdev->dev;
++
++ auxadc = of_parse_phandle(np, "auxadc", 0);
++ if (!auxadc) {
++ dev_err(&pdev->dev, "missing auxadc node\n");
++ return -ENODEV;
++ }
++
++ mt->auxadc_phys_base = of_get_phys_base(auxadc);
++ if (mt->auxadc_phys_base == OF_BAD_ADDR) {
++ dev_err(&pdev->dev, "Can't get auxadc phys address\n");
++ return -EINVAL;
++ }
++
++ apmixedsys = of_parse_phandle(np, "apmixedsys", 0);
++ if (!apmixedsys) {
++ dev_err(&pdev->dev, "missing apmixedsys node\n");
++ return -ENODEV;
++ }
++
++ mt->apmixed_phys_base = of_get_phys_base(apmixedsys);
++ if (mt->apmixed_phys_base == OF_BAD_ADDR) {
++ dev_err(&pdev->dev, "Can't get auxadc phys address\n");
++ return -EINVAL;
++ }
++
++ irq = platform_get_irq(pdev, 0);
++ if (!irq) {
++ dev_err(&pdev->dev, "Can't find irq\n");
++ return -EINVAL;
++ }
++
++ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, mtk_thermal_irq,
++ IRQF_ONESHOT, THERMAL_NAME, mt);
++ if (ret) {
++ dev_err(&pdev->dev, "Can't request irq %d: %d\n", irq, ret);
++ return ret;
++ }
++
++ ret = clk_prepare_enable(mt->clk_auxadc);
++ if (ret) {
++ dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
++ return ret;
++ }
++
++ reset_control_reset(mt->reset);
++
++ ret = clk_prepare_enable(mt->clk_peri_therm);
++ if (ret) {
++ dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
++ goto err_enable_clk;
++ }
++
++ /*
++ * These calibration values should finally be provided by the
++ * firmware or fuses. For now use default values.
++ */
++ mt->adc_ge = ((512 - 512) * 10000) / 4096;
++ mt->adc_oe = 512 - 512;
++ mt->degc_cali = 40;
++ mt->o_slope = 0;
++ mt->vts = 260;
++
++ for (i = 0; i < MT8173_NUM_BANKS; i++) {
++ struct mtk_thermal_bank *bank = &mt->banks[i];
++
++ bank->id = i;
++ bank->mt = mt;
++ mtk_thermal_init_bank(&mt->banks[i]);
++ }
++
++ platform_set_drvdata(pdev, mt);
++
++ /*
++ * This is needed after initialising the banks because otherwise
++ * the first temperature read contains bogus high temperatures which
++ * immediately cause a system shutdown.
++ */
++ msleep(100);
++
++ for (i = 0; i < MT8173_NUM_BANKS; i++) {
++ struct mtk_thermal_bank *bank = &mt->banks[i];
++
++ bank->tz = thermal_zone_of_sensor_register(&pdev->dev, i, bank,
++ &mtk_thermal_ops);
++ }
++
++ return 0;
++
++err_enable_clk:
++ clk_disable_unprepare(mt->clk_peri_therm);
++
++ return ret;
++}
++
++static int mtk_thermal_remove(struct platform_device *pdev)
++{
++ struct mtk_thermal *mt = platform_get_drvdata(pdev);
++ int i;
++
++ for (i = 0; i < MT8173_NUM_BANKS; i++) {
++ struct mtk_thermal_bank *bank = &mt->banks[i];
++
++ if (!IS_ERR(bank))
++ thermal_zone_of_sensor_unregister(&pdev->dev, bank->tz);
++ }
++
++ clk_disable_unprepare(mt->clk_peri_therm);
++ clk_disable_unprepare(mt->clk_auxadc);
++
++ return 0;
++}
++
++static const struct of_device_id mtk_thermal_of_match[] = {
++ {
++ .compatible = "mediatek,mt8173-thermal",
++ }, {
++ },
++};
++
++static struct platform_driver mtk_thermal_driver = {
++ .probe = mtk_thermal_probe,
++ .remove = mtk_thermal_remove,
++ .driver = {
++ .name = THERMAL_NAME,
++ .of_match_table = mtk_thermal_of_match,
++ },
++};
++
++module_platform_driver(mtk_thermal_driver);
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0024-ARM64-dts-mt8173-Add-thermal-auxadc-device-nodes.patch b/target/linux/mediatek/patches/0024-ARM64-dts-mt8173-Add-thermal-auxadc-device-nodes.patch
new file mode 100644
index 0000000000..ef80497cec
--- /dev/null
+++ b/target/linux/mediatek/patches/0024-ARM64-dts-mt8173-Add-thermal-auxadc-device-nodes.patch
@@ -0,0 +1,49 @@
+From 720e25e5c821336f7fa0c5fb564475c791c00340 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:43 +0200
+Subject: [PATCH 24/76] ARM64: dts: mt8173: Add thermal/auxadc device nodes
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ arch/arm64/boot/dts/mediatek/mt8173.dtsi | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+index 924fdb6..50d424f 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+@@ -147,6 +147,11 @@
+ (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ };
+
++ auxadc: auxadc@11001000 {
++ compatible = "mediatek,mt8173-auxadc";
++ reg = <0 0x11001000 0 0x1000>;
++ };
++
+ uart0: serial@11002000 {
+ compatible = "mediatek,mt8173-uart",
+ "mediatek,mt6577-uart";
+@@ -182,6 +187,19 @@
+ clocks = <&uart_clk>;
+ status = "disabled";
+ };
++
++ thermal: thermal@1100b000 {
++ #thermal-sensor-cells = <1>;
++ compatible = "mediatek,mt8173-thermal";
++ reg = <0 0x1100b000 0 0x1000>;
++ interrupts = <0 70 IRQ_TYPE_LEVEL_LOW>;
++ clocks = <&pericfg CLK_PERI_THERM>, <&pericfg CLK_PERI_AUXADC>;
++ clock-names = "therm", "auxadc";
++ resets = <&pericfg MT8173_PERI_THERM_SW_RST>;
++ reset-names = "therm";
++ auxadc = <&auxadc>;
++ apmixedsys = <&apmixedsys>;
++ };
+ };
+
+ };
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0025-dt-bindings-ARM-Mediatek-Document-devicetree-binding.patch b/target/linux/mediatek/patches/0025-dt-bindings-ARM-Mediatek-Document-devicetree-binding.patch
new file mode 100644
index 0000000000..ab8f2d5cee
--- /dev/null
+++ b/target/linux/mediatek/patches/0025-dt-bindings-ARM-Mediatek-Document-devicetree-binding.patch
@@ -0,0 +1,53 @@
+From a6de66d3cf5add25f2b8913332117f3334db506e Mon Sep 17 00:00:00 2001
+From: Leilk Liu <leilk.liu@mediatek.com>
+Date: Fri, 8 May 2015 16:55:41 +0800
+Subject: [PATCH 25/76] dt-bindings: ARM: Mediatek: Document devicetree
+ bindings for spi bus
+
+Signed-off-by: Leilk Liu <leilk.liu@mediatek.com>
+---
+ .../devicetree/bindings/spi/spi-mt65xx.txt | 32 ++++++++++++++++++++
+ 1 file changed, 32 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/spi/spi-mt65xx.txt
+
+diff --git a/Documentation/devicetree/bindings/spi/spi-mt65xx.txt b/Documentation/devicetree/bindings/spi/spi-mt65xx.txt
+new file mode 100644
+index 0000000..04c28fd
+--- /dev/null
++++ b/Documentation/devicetree/bindings/spi/spi-mt65xx.txt
+@@ -0,0 +1,32 @@
++MTK SPI device
++
++Required properties:
++- compatible: should be one of the following.
++ - mediatek,mt8173-spi: for mt8173 platforms
++ - mediatek,mt8135-spi: for mt8135 platforms
++ - mediatek,mt6589-spi: for mt6589 platforms
++
++- reg: Address and length of the register set for the device
++
++- interrupts: Should contain spi interrupt
++
++- clock-names: tuple listing input clock names.
++ Required elements: "main"
++
++- clocks: phandles to input clocks.
++
++- pad-select: should specify spi pad used, only required for MT8173.
++ This value should be 0~3.
++
++Example:
++
++- SoC Specific Portion:
++spi: spi@1100a000 {
++ compatible = "mediatek,mt8173-spi";
++ reg = <0 0x1100a000 0 0x1000>;
++ interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_LOW>;
++ clocks = <&pericfg PERI_SPI0>;
++ clock-names = "main";
++ pad-select = <1>;
++ status = "disabled";
++};
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0026-spi-mediatek-Add-spi-bus-for-Mediatek-MT8173.patch b/target/linux/mediatek/patches/0026-spi-mediatek-Add-spi-bus-for-Mediatek-MT8173.patch
new file mode 100644
index 0000000000..3466581e04
--- /dev/null
+++ b/target/linux/mediatek/patches/0026-spi-mediatek-Add-spi-bus-for-Mediatek-MT8173.patch
@@ -0,0 +1,679 @@
+From 047222cfefe97ef8706f03117bc8deada4cb4ddd Mon Sep 17 00:00:00 2001
+From: Leilk Liu <leilk.liu@mediatek.com>
+Date: Fri, 8 May 2015 16:55:42 +0800
+Subject: [PATCH 26/76] spi: mediatek: Add spi bus for Mediatek MT8173
+
+This patch adds basic spi bus for MT8173.
+
+Signed-off-by: Leilk Liu <leilk.liu@mediatek.com>
+---
+ drivers/spi/Kconfig | 10 +
+ drivers/spi/Makefile | 1 +
+ drivers/spi/spi-mt65xx.c | 622 ++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 633 insertions(+)
+ create mode 100644 drivers/spi/spi-mt65xx.c
+
+diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
+index 72b0590..53dbea3 100644
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -325,6 +325,16 @@ config SPI_MESON_SPIFC
+ This enables master mode support for the SPIFC (SPI flash
+ controller) available in Amlogic Meson SoCs.
+
++config SPI_MT65XX
++ tristate "MediaTek SPI controller"
++ depends on ARCH_MEDIATEK || COMPILE_TEST
++ select SPI_BITBANG
++ help
++ This selects the MediaTek(R) SPI bus driver.
++ If you want to use MediaTek(R) SPI interface,
++ say Y or M here.If you are not sure, say N.
++ SPI drivers for Mediatek mt65XX series ARM SoCs.
++
+ config SPI_OC_TINY
+ tristate "OpenCores tiny SPI"
+ depends on GPIOLIB
+diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
+index d8cbf65..ab332ef 100644
+--- a/drivers/spi/Makefile
++++ b/drivers/spi/Makefile
+@@ -48,6 +48,7 @@ obj-$(CONFIG_SPI_MESON_SPIFC) += spi-meson-spifc.o
+ obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o
+ obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o
+ obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o
++obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o
+ obj-$(CONFIG_SPI_MXS) += spi-mxs.o
+ obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o
+ obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o
+diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
+new file mode 100644
+index 0000000..92c119d
+--- /dev/null
++++ b/drivers/spi/spi-mt65xx.c
+@@ -0,0 +1,622 @@
++/*
++ * Copyright (c) 2015 MediaTek Inc.
++ * Author: Leilk Liu <leilk.liu@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/ioport.h>
++#include <linux/errno.h>
++#include <linux/spi/spi.h>
++#include <linux/workqueue.h>
++#include <linux/dma-mapping.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/irqreturn.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++#include <linux/clk.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/sched.h>
++#include <linux/of.h>
++#include <linux/of_irq.h>
++#include <linux/of_address.h>
++#include <linux/kernel.h>
++#include <linux/spi/spi_bitbang.h>
++#include <linux/gpio.h>
++#include <linux/module.h>
++#include <linux/of_gpio.h>
++
++#define SPI_CFG0_REG 0x0000
++#define SPI_CFG1_REG 0x0004
++#define SPI_TX_SRC_REG 0x0008
++#define SPI_RX_DST_REG 0x000c
++#define SPI_CMD_REG 0x0018
++#define SPI_STATUS0_REG 0x001c
++#define SPI_PAD_SEL_REG 0x0024
++
++#define SPI_CFG0_SCK_HIGH_OFFSET 0
++#define SPI_CFG0_SCK_LOW_OFFSET 8
++#define SPI_CFG0_CS_HOLD_OFFSET 16
++#define SPI_CFG0_CS_SETUP_OFFSET 24
++
++#define SPI_CFG0_SCK_HIGH_MASK 0xff
++#define SPI_CFG0_SCK_LOW_MASK 0xff00
++#define SPI_CFG0_CS_HOLD_MASK 0xff0000
++#define SPI_CFG0_CS_SETUP_MASK 0xff000000
++
++#define SPI_CFG1_CS_IDLE_OFFSET 0
++#define SPI_CFG1_PACKET_LOOP_OFFSET 8
++#define SPI_CFG1_PACKET_LENGTH_OFFSET 16
++#define SPI_CFG1_GET_TICK_DLY_OFFSET 30
++
++#define SPI_CFG1_CS_IDLE_MASK 0xff
++#define SPI_CFG1_PACKET_LOOP_MASK 0xff00
++#define SPI_CFG1_PACKET_LENGTH_MASK 0x3ff0000
++#define SPI_CFG1_GET_TICK_DLY_MASK 0xc0000000
++
++#define SPI_CMD_ACT_OFFSET 0
++#define SPI_CMD_RESUME_OFFSET 1
++#define SPI_CMD_RST_OFFSET 2
++#define SPI_CMD_PAUSE_EN_OFFSET 4
++#define SPI_CMD_DEASSERT_OFFSET 5
++#define SPI_CMD_CPHA_OFFSET 8
++#define SPI_CMD_CPOL_OFFSET 9
++#define SPI_CMD_RX_DMA_OFFSET 10
++#define SPI_CMD_TX_DMA_OFFSET 11
++#define SPI_CMD_TXMSBF_OFFSET 12
++#define SPI_CMD_RXMSBF_OFFSET 13
++#define SPI_CMD_RX_ENDIAN_OFFSET 14
++#define SPI_CMD_TX_ENDIAN_OFFSET 15
++#define SPI_CMD_FINISH_IE_OFFSET 16
++#define SPI_CMD_PAUSE_IE_OFFSET 17
++
++#define SPI_CMD_RESUME_MASK 0x2
++#define SPI_CMD_RST_MASK 0x4
++#define SPI_CMD_PAUSE_EN_MASK 0x10
++#define SPI_CMD_DEASSERT_MASK 0x20
++#define SPI_CMD_CPHA_MASK 0x100
++#define SPI_CMD_CPOL_MASK 0x200
++#define SPI_CMD_RX_DMA_MASK 0x400
++#define SPI_CMD_TX_DMA_MASK 0x800
++#define SPI_CMD_TXMSBF_MASK 0x1000
++#define SPI_CMD_RXMSBF_MASK 0x2000
++#define SPI_CMD_RX_ENDIAN_MASK 0x4000
++#define SPI_CMD_TX_ENDIAN_MASK 0x8000
++#define SPI_CMD_FINISH_IE_MASK 0x10000
++
++#define COMPAT_MT6589 (0x1 << 0)
++#define COMPAT_MT8173 (0x1 << 1)
++
++#define MT8173_MAX_PAD_SEL 3
++
++#define IDLE 0
++#define INPROGRESS 1
++#define PAUSED 2
++
++#define PACKET_SIZE 1024
++
++struct mtk_chip_config {
++ u32 setuptime;
++ u32 holdtime;
++ u32 high_time;
++ u32 low_time;
++ u32 cs_idletime;
++ u32 tx_mlsb;
++ u32 rx_mlsb;
++ u32 tx_endian;
++ u32 rx_endian;
++ u32 pause;
++ u32 finish_intr;
++ u32 deassert;
++ u32 tckdly;
++};
++
++struct mtk_spi_ddata {
++ struct spi_bitbang bitbang;
++ void __iomem *base;
++ u32 irq;
++ u32 state;
++ u32 platform_compat;
++ u32 pad_sel;
++ struct clk *clk;
++
++ const u8 *tx_buf;
++ u8 *rx_buf;
++ u32 tx_len, rx_len;
++ struct completion done;
++};
++
++/*
++ * A piece of default chip info unless the platform
++ * supplies it.
++ */
++static const struct mtk_chip_config mtk_default_chip_info = {
++ .setuptime = 10,
++ .holdtime = 12,
++ .high_time = 6,
++ .low_time = 6,
++ .cs_idletime = 12,
++ .rx_mlsb = 1,
++ .tx_mlsb = 1,
++ .tx_endian = 0,
++ .rx_endian = 0,
++ .pause = 0,
++ .finish_intr = 1,
++ .deassert = 0,
++ .tckdly = 0,
++};
++
++static const struct of_device_id mtk_spi_of_match[] = {
++ { .compatible = "mediatek,mt6589-spi", .data = (void *)COMPAT_MT6589},
++ { .compatible = "mediatek,mt8173-spi", .data = (void *)COMPAT_MT8173},
++ {}
++};
++MODULE_DEVICE_TABLE(of, mtk_spi_of_match);
++
++static void mtk_spi_reset(struct mtk_spi_ddata *mdata)
++{
++ u32 reg_val;
++
++ /*set the software reset bit in SPI_CMD_REG.*/
++ reg_val = readl(mdata->base + SPI_CMD_REG);
++ reg_val &= ~SPI_CMD_RST_MASK;
++ reg_val |= 1 << SPI_CMD_RST_OFFSET;
++ writel(reg_val, mdata->base + SPI_CMD_REG);
++ reg_val = readl(mdata->base + SPI_CMD_REG);
++ reg_val &= ~SPI_CMD_RST_MASK;
++ writel(reg_val, mdata->base + SPI_CMD_REG);
++}
++
++static void mtk_set_pause_bit(struct mtk_spi_ddata *mdata)
++{
++ u32 reg_val;
++
++ reg_val = readl(mdata->base + SPI_CMD_REG);
++ reg_val |= 1 << SPI_CMD_PAUSE_EN_OFFSET;
++ reg_val |= 1 << SPI_CMD_PAUSE_IE_OFFSET;
++ writel(reg_val, mdata->base + SPI_CMD_REG);
++}
++
++static void mtk_clear_pause_bit(struct mtk_spi_ddata *mdata)
++{
++ u32 reg_val;
++
++ reg_val = readl(mdata->base + SPI_CMD_REG);
++ reg_val &= ~SPI_CMD_PAUSE_EN_MASK;
++ writel(reg_val, mdata->base + SPI_CMD_REG);
++}
++
++static int mtk_spi_config(struct mtk_spi_ddata *mdata,
++ struct mtk_chip_config *chip_config)
++{
++ u32 reg_val;
++
++ /* set the timing */
++ reg_val = readl(mdata->base + SPI_CFG0_REG);
++ reg_val &= ~(SPI_CFG0_SCK_HIGH_MASK | SPI_CFG0_SCK_LOW_MASK);
++ reg_val &= ~(SPI_CFG0_CS_HOLD_MASK | SPI_CFG0_CS_SETUP_MASK);
++ reg_val |= ((chip_config->high_time - 1) << SPI_CFG0_SCK_HIGH_OFFSET);
++ reg_val |= ((chip_config->low_time - 1) << SPI_CFG0_SCK_LOW_OFFSET);
++ reg_val |= ((chip_config->holdtime - 1) << SPI_CFG0_CS_HOLD_OFFSET);
++ reg_val |= ((chip_config->setuptime - 1) << SPI_CFG0_CS_SETUP_OFFSET);
++ writel(reg_val, mdata->base + SPI_CFG0_REG);
++
++ reg_val = readl(mdata->base + SPI_CFG1_REG);
++ reg_val &= ~SPI_CFG1_CS_IDLE_MASK;
++ reg_val |= ((chip_config->cs_idletime - 1) << SPI_CFG1_CS_IDLE_OFFSET);
++ reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK;
++ reg_val |= ((chip_config->tckdly) << SPI_CFG1_GET_TICK_DLY_OFFSET);
++ writel(reg_val, mdata->base + SPI_CFG1_REG);
++
++ /* set the mlsbx and mlsbtx */
++ reg_val = readl(mdata->base + SPI_CMD_REG);
++ reg_val &= ~(SPI_CMD_TX_ENDIAN_MASK | SPI_CMD_RX_ENDIAN_MASK);
++ reg_val &= ~(SPI_CMD_TXMSBF_MASK | SPI_CMD_RXMSBF_MASK);
++ reg_val |= (chip_config->tx_mlsb << SPI_CMD_TXMSBF_OFFSET);
++ reg_val |= (chip_config->rx_mlsb << SPI_CMD_RXMSBF_OFFSET);
++ reg_val |= (chip_config->tx_endian << SPI_CMD_TX_ENDIAN_OFFSET);
++ reg_val |= (chip_config->rx_endian << SPI_CMD_RX_ENDIAN_OFFSET);
++ writel(reg_val, mdata->base + SPI_CMD_REG);
++
++ /* set finish and pause interrupt always enable */
++ reg_val = readl(mdata->base + SPI_CMD_REG);
++ reg_val &= ~SPI_CMD_FINISH_IE_MASK;
++ reg_val |= (chip_config->finish_intr << SPI_CMD_FINISH_IE_OFFSET);
++ writel(reg_val, mdata->base + SPI_CMD_REG);
++
++ reg_val = readl(mdata->base + SPI_CMD_REG);
++ reg_val |= 1 << SPI_CMD_TX_DMA_OFFSET;
++ reg_val |= 1 << SPI_CMD_RX_DMA_OFFSET;
++ writel(reg_val, mdata->base + SPI_CMD_REG);
++
++ /* set deassert mode */
++ reg_val = readl(mdata->base + SPI_CMD_REG);
++ reg_val &= ~SPI_CMD_DEASSERT_MASK;
++ reg_val |= (chip_config->deassert << SPI_CMD_DEASSERT_OFFSET);
++ writel(reg_val, mdata->base + SPI_CMD_REG);
++
++ /* pad select */
++ if (mdata->platform_compat & COMPAT_MT8173)
++ writel(mdata->pad_sel, mdata->base + SPI_PAD_SEL_REG);
++
++ return 0;
++}
++
++static int mtk_spi_setup_transfer(struct spi_device *spi,
++ struct spi_transfer *t)
++{
++ u32 reg_val;
++ struct spi_master *master = spi->master;
++ struct mtk_spi_ddata *mdata = spi_master_get_devdata(master);
++ struct spi_message *m = master->cur_msg;
++ struct mtk_chip_config *chip_config;
++
++ u8 cpha = spi->mode & SPI_CPHA ? 1 : 0;
++ u8 cpol = spi->mode & SPI_CPOL ? 1 : 0;
++
++ reg_val = readl(mdata->base + SPI_CMD_REG);
++ reg_val &= ~(SPI_CMD_CPHA_MASK | SPI_CMD_CPOL_MASK);
++ reg_val |= (cpha << SPI_CMD_CPHA_OFFSET);
++ reg_val |= (cpol << SPI_CMD_CPOL_OFFSET);
++ writel(reg_val, mdata->base + SPI_CMD_REG);
++
++ if (t->cs_change) {
++ if (!(list_is_last(&t->transfer_list, &m->transfers)))
++ mdata->state = IDLE;
++ } else {
++ mdata->state = IDLE;
++ mtk_spi_reset(mdata);
++ }
++
++ chip_config = (struct mtk_chip_config *)spi->controller_data;
++ if (!chip_config) {
++ chip_config = (void *)&mtk_default_chip_info;
++ spi->controller_data = chip_config;
++ mdata->state = IDLE;
++ }
++
++ mtk_spi_config(mdata, chip_config);
++
++ return 0;
++}
++
++static void mtk_spi_chipselect(struct spi_device *spi, int is_on)
++{
++ struct mtk_spi_ddata *mdata = spi_master_get_devdata(spi->master);
++
++ switch (is_on) {
++ case BITBANG_CS_ACTIVE:
++ mtk_set_pause_bit(mdata);
++ break;
++ case BITBANG_CS_INACTIVE:
++ mtk_clear_pause_bit(mdata);
++ break;
++ }
++}
++
++static void mtk_spi_start_transfer(struct mtk_spi_ddata *mdata)
++{
++ u32 reg_val;
++
++ reg_val = readl(mdata->base + SPI_CMD_REG);
++ reg_val |= 1 << SPI_CMD_ACT_OFFSET;
++ writel(reg_val, mdata->base + SPI_CMD_REG);
++}
++
++static void mtk_spi_resume_transfer(struct mtk_spi_ddata *mdata)
++{
++ u32 reg_val;
++
++ reg_val = readl(mdata->base + SPI_CMD_REG);
++ reg_val &= ~SPI_CMD_RESUME_MASK;
++ reg_val |= 1 << SPI_CMD_RESUME_OFFSET;
++ writel(reg_val, mdata->base + SPI_CMD_REG);
++}
++
++static int mtk_spi_setup_packet(struct mtk_spi_ddata *mdata,
++ struct spi_transfer *xfer)
++{
++ struct device *dev = &mdata->bitbang.master->dev;
++ u32 packet_size, packet_loop, reg_val;
++
++ packet_size = min_t(unsigned, xfer->len, PACKET_SIZE);
++
++ /* mtk hw has the restriction that xfer len must be a multiple of 1024,
++ * when it is greater than 1024bytes.
++ */
++ if (xfer->len % packet_size) {
++ dev_err(dev, "ERROR!The lens must be a multiple of %d, your len %d\n",
++ PACKET_SIZE, xfer->len);
++ return -EINVAL;
++ }
++
++ packet_loop = xfer->len / packet_size;
++
++ reg_val = readl(mdata->base + SPI_CFG1_REG);
++ reg_val &= ~(SPI_CFG1_PACKET_LENGTH_MASK + SPI_CFG1_PACKET_LOOP_MASK);
++ reg_val |= (packet_size - 1) << SPI_CFG1_PACKET_LENGTH_OFFSET;
++ reg_val |= (packet_loop - 1) << SPI_CFG1_PACKET_LOOP_OFFSET;
++ writel(reg_val, mdata->base + SPI_CFG1_REG);
++
++ return 0;
++}
++
++static int mtk_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *xfer)
++{
++ struct spi_master *master = spi->master;
++ struct mtk_spi_ddata *mdata = spi_master_get_devdata(master);
++ struct device *dev = &mdata->bitbang.master->dev;
++ int cmd, ret;
++
++ /* mtk spi hw tx/rx have 4bytes aligned restriction,
++ * so kmalloc tx/rx buffer to workaround here.
++ */
++ mdata->tx_buf = NULL;
++ mdata->rx_buf = NULL;
++ if (xfer->tx_buf) {
++ mdata->tx_buf = kmalloc(xfer->len, GFP_KERNEL);
++ if (!mdata->tx_buf) {
++ dev_err(dev, "malloc tx_buf failed.\n");
++ ret = -ENOMEM;
++ goto err_free;
++ }
++ memcpy((void *)mdata->tx_buf, xfer->tx_buf, xfer->len);
++ }
++ if (xfer->rx_buf) {
++ mdata->rx_buf = kmalloc(xfer->len, GFP_KERNEL);
++ if (!mdata->rx_buf) {
++ dev_err(dev, "malloc rx_buf failed.\n");
++ ret = -ENOMEM;
++ goto err_free;
++ }
++ }
++
++ reinit_completion(&mdata->done);
++
++ xfer->tx_dma = DMA_ERROR_CODE;
++ xfer->rx_dma = DMA_ERROR_CODE;
++ if (xfer->tx_buf) {
++ xfer->tx_dma = dma_map_single(dev, (void *)mdata->tx_buf,
++ xfer->len, DMA_TO_DEVICE);
++ if (dma_mapping_error(dev, xfer->tx_dma)) {
++ dev_err(dev, "dma mapping tx_buf error.\n");
++ ret = -ENOMEM;
++ goto err_free;
++ }
++ }
++ if (xfer->rx_buf) {
++ xfer->rx_dma = dma_map_single(dev, mdata->rx_buf,
++ xfer->len, DMA_FROM_DEVICE);
++ if (dma_mapping_error(dev, xfer->rx_dma)) {
++ if (xfer->tx_buf)
++ dma_unmap_single(dev, xfer->tx_dma,
++ xfer->len, DMA_TO_DEVICE);
++ dev_err(dev, "dma mapping rx_buf error.\n");
++ ret = -ENOMEM;
++ goto err_free;
++ }
++ }
++
++ ret = mtk_spi_setup_packet(mdata, xfer);
++ if (ret != 0)
++ goto err_free;
++
++ /* Here is mt8173 HW issue: RX must enable TX, then TX transfer
++ * dummy data; TX don't need to enable RX. so enable TX dma for
++ * RX to workaround.
++ */
++ cmd = readl(mdata->base + SPI_CMD_REG);
++ if (xfer->tx_buf || (mdata->platform_compat & COMPAT_MT8173))
++ cmd |= 1 << SPI_CMD_TX_DMA_OFFSET;
++ if (xfer->rx_buf)
++ cmd |= 1 << SPI_CMD_RX_DMA_OFFSET;
++ writel(cmd, mdata->base + SPI_CMD_REG);
++
++ /* set up the DMA bus address */
++ if (xfer->tx_dma != DMA_ERROR_CODE)
++ writel(cpu_to_le32(xfer->tx_dma), mdata->base + SPI_TX_SRC_REG);
++ if (xfer->rx_dma != DMA_ERROR_CODE)
++ writel(cpu_to_le32(xfer->rx_dma), mdata->base + SPI_RX_DST_REG);
++
++ if (mdata->state == IDLE)
++ mtk_spi_start_transfer(mdata);
++ else if (mdata->state == PAUSED)
++ mtk_spi_resume_transfer(mdata);
++ else
++ mdata->state = INPROGRESS;
++
++ wait_for_completion(&mdata->done);
++
++ if (xfer->tx_dma != DMA_ERROR_CODE) {
++ dma_unmap_single(dev, xfer->tx_dma, xfer->len, DMA_TO_DEVICE);
++ xfer->tx_dma = DMA_ERROR_CODE;
++ }
++ if (xfer->rx_dma != DMA_ERROR_CODE) {
++ dma_unmap_single(dev, xfer->rx_dma, xfer->len, DMA_FROM_DEVICE);
++ xfer->rx_dma = DMA_ERROR_CODE;
++ }
++
++ /* spi disable dma */
++ cmd = readl(mdata->base + SPI_CMD_REG);
++ cmd &= ~SPI_CMD_TX_DMA_MASK;
++ cmd &= ~SPI_CMD_RX_DMA_MASK;
++ writel(cmd, mdata->base + SPI_CMD_REG);
++
++ if (xfer->rx_buf)
++ memcpy(xfer->rx_buf, mdata->rx_buf, xfer->len);
++
++ ret = xfer->len;
++
++err_free:
++ kfree(mdata->tx_buf);
++ kfree(mdata->rx_buf);
++ return ret;
++}
++
++static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
++{
++ struct mtk_spi_ddata *mdata = dev_id;
++ u32 reg_val;
++
++ reg_val = readl(mdata->base + SPI_STATUS0_REG);
++ if (reg_val & 0x2)
++ mdata->state = PAUSED;
++ else
++ mdata->state = IDLE;
++ complete(&mdata->done);
++
++ return IRQ_HANDLED;
++}
++
++static unsigned long mtk_get_device_prop(struct platform_device *pdev)
++{
++ const struct of_device_id *match;
++
++ match = of_match_node(mtk_spi_of_match, pdev->dev.of_node);
++ return (unsigned long)match->data;
++}
++
++static int mtk_spi_probe(struct platform_device *pdev)
++{
++ struct spi_master *master;
++ struct mtk_spi_ddata *mdata;
++ struct resource *res;
++ int ret;
++
++ master = spi_alloc_master(&pdev->dev, sizeof(struct mtk_spi_ddata));
++ if (!master) {
++ dev_err(&pdev->dev, "failed to alloc spi master\n");
++ return -ENOMEM;
++ }
++
++ platform_set_drvdata(pdev, master);
++
++ master->dev.of_node = pdev->dev.of_node;
++ master->bus_num = pdev->id;
++ master->num_chipselect = 1;
++ master->mode_bits = SPI_CPOL | SPI_CPHA;
++
++ mdata = spi_master_get_devdata(master);
++
++ mdata->bitbang.master = master;
++ mdata->bitbang.chipselect = mtk_spi_chipselect;
++ mdata->bitbang.setup_transfer = mtk_spi_setup_transfer;
++ mdata->bitbang.txrx_bufs = mtk_spi_txrx_bufs;
++ mdata->platform_compat = mtk_get_device_prop(pdev);
++
++ if (mdata->platform_compat & COMPAT_MT8173) {
++ ret = of_property_read_u32(pdev->dev.of_node, "pad-select",
++ &mdata->pad_sel);
++ if (ret) {
++ dev_err(&pdev->dev, "failed to read pad select: %d\n",
++ ret);
++ goto err;
++ }
++
++ if (mdata->pad_sel > MT8173_MAX_PAD_SEL) {
++ dev_err(&pdev->dev, "wrong pad-select: %u\n",
++ mdata->pad_sel);
++ goto err;
++ }
++ }
++
++ init_completion(&mdata->done);
++
++ mdata->clk = devm_clk_get(&pdev->dev, "main");
++ if (IS_ERR(mdata->clk)) {
++ ret = PTR_ERR(mdata->clk);
++ dev_err(&pdev->dev, "failed to get clock: %d\n", ret);
++ goto err;
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ ret = -ENODEV;
++ dev_err(&pdev->dev, "failed to determine base address\n");
++ goto err;
++ }
++
++ mdata->base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(mdata->base)) {
++ ret = PTR_ERR(mdata->base);
++ goto err;
++ }
++
++ ret = platform_get_irq(pdev, 0);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "failed to get irq (%d)\n", ret);
++ goto err;
++ }
++
++ mdata->irq = ret;
++
++ if (!pdev->dev.dma_mask)
++ pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
++
++ mdata->bitbang.master->dev.dma_mask = pdev->dev.dma_mask;
++
++ ret = clk_prepare_enable(mdata->clk);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "failed to enable clock (%d)\n", ret);
++ goto err;
++ }
++
++ ret = devm_request_irq(&pdev->dev, mdata->irq, mtk_spi_interrupt,
++ IRQF_TRIGGER_NONE, dev_name(&pdev->dev), mdata);
++ if (ret) {
++ dev_err(&pdev->dev, "failed to register irq (%d)\n", ret);
++ goto err_disable_clk;
++ }
++
++ ret = spi_bitbang_start(&mdata->bitbang);
++ if (ret) {
++ dev_err(&pdev->dev, "spi_bitbang_start failed (%d)\n", ret);
++err_disable_clk:
++ clk_disable_unprepare(mdata->clk);
++err:
++ spi_master_put(master);
++ }
++
++ return ret;
++}
++
++static int mtk_spi_remove(struct platform_device *pdev)
++{
++ struct spi_master *master = platform_get_drvdata(pdev);
++ struct mtk_spi_ddata *mdata = spi_master_get_devdata(master);
++
++ spi_bitbang_stop(&mdata->bitbang);
++ mtk_spi_reset(mdata);
++ clk_disable_unprepare(mdata->clk);
++ spi_master_put(master);
++
++ return 0;
++}
++
++struct platform_driver mtk_spi_driver = {
++ .driver = {
++ .name = "mtk-spi",
++ .of_match_table = mtk_spi_of_match,
++ },
++ .probe = mtk_spi_probe,
++ .remove = mtk_spi_remove,
++};
++
++module_platform_driver(mtk_spi_driver);
++
++MODULE_DESCRIPTION("MTK SPI Controller driver");
++MODULE_AUTHOR("Leilk Liu <leilk.liu@mediatek.com>");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform: mtk_spi");
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0027-dt-bindings-pwm-add-Mediatek-display-PWM-bindings.patch b/target/linux/mediatek/patches/0027-dt-bindings-pwm-add-Mediatek-display-PWM-bindings.patch
new file mode 100644
index 0000000000..1236a96782
--- /dev/null
+++ b/target/linux/mediatek/patches/0027-dt-bindings-pwm-add-Mediatek-display-PWM-bindings.patch
@@ -0,0 +1,47 @@
+From 908a87b47af8303c9aa8fb6aa183ca9f8b544d78 Mon Sep 17 00:00:00 2001
+From: YH Huang <yh.huang@mediatek.com>
+Date: Mon, 11 May 2015 17:26:21 +0800
+Subject: [PATCH 27/76] dt-bindings: pwm: add Mediatek display PWM bindings
+
+Document the device-tree binding of Mediatek display PWM.
+
+Signed-off-by: YH Huang <yh.huang@mediatek.com>
+---
+ .../devicetree/bindings/pwm/pwm-disp-mediatek.txt | 25 ++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/pwm/pwm-disp-mediatek.txt
+
+diff --git a/Documentation/devicetree/bindings/pwm/pwm-disp-mediatek.txt b/Documentation/devicetree/bindings/pwm/pwm-disp-mediatek.txt
+new file mode 100644
+index 0000000..ef54e9d
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pwm/pwm-disp-mediatek.txt
+@@ -0,0 +1,25 @@
++Mediatek display PWM controller
++
++Required properties:
++ - compatible: should be "mediatek,<name>-disp-pwm"
++ - "mediatek,mt8173-disp-pwm": found on mt8173 SoC
++ - "mediatek,mt6595-disp-pwm": found on mt6595 SoC
++ - reg: physical base address and length of the controller's registers
++ - #pwm-cells: must be 2. See pwm.txt in this directory
++ for a description of the cell format
++ - clocks: phandle and clock specifier of the PWM reference clock
++ - clock-names: must contain the following
++ - "main": clock used to generate PWM signals
++ - "mm": sync signals from the modules of mmsys
++
++Example:
++ pwm0: pwm@1401e000 {
++ compatible = "mediatek,mt8173-disp-pwm",
++ "mediatek,mt6595-disp-pwm";
++ reg = <0 0x1401e000 0 0x1000>;
++ #pwm-cells = <2>;
++ clocks = <&mmsys MM_DISP_PWM026M>,
++ <&mmsys MM_DISP_PWM0MM>;
++ clock-names = "main",
++ "mm";
++ };
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0028-pwm-add-Mediatek-display-PWM-driver-support.patch b/target/linux/mediatek/patches/0028-pwm-add-Mediatek-display-PWM-driver-support.patch
new file mode 100644
index 0000000000..dbcca3e160
--- /dev/null
+++ b/target/linux/mediatek/patches/0028-pwm-add-Mediatek-display-PWM-driver-support.patch
@@ -0,0 +1,281 @@
+From 77e664940f6daa86965d16a2047188519341a31a Mon Sep 17 00:00:00 2001
+From: YH Huang <yh.huang@mediatek.com>
+Date: Mon, 11 May 2015 17:26:22 +0800
+Subject: [PATCH 28/76] pwm: add Mediatek display PWM driver support
+
+Add display PWM driver support to modify backlight for MT8173/MT6595.
+
+Signed-off-by: YH Huang <yh.huang@mediatek.com>
+---
+ drivers/pwm/Kconfig | 9 ++
+ drivers/pwm/Makefile | 1 +
+ drivers/pwm/pwm-disp-mediatek.c | 225 +++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 235 insertions(+)
+ create mode 100644 drivers/pwm/pwm-disp-mediatek.c
+
+diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
+index b1541f4..9edbb5a 100644
+--- a/drivers/pwm/Kconfig
++++ b/drivers/pwm/Kconfig
+@@ -111,6 +111,15 @@ config PWM_CLPS711X
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-clps711x.
+
++config PWM_DISP_MEDIATEK
++ tristate "MEDIATEK display PWM driver"
++ depends on OF
++ help
++ Generic PWM framework driver for mediatek disp-pwm device.
++
++ To compile this driver as a module, choose M here: the module
++ will be called pwm-disp-mediatek.
++
+ config PWM_EP93XX
+ tristate "Cirrus Logic EP93xx PWM support"
+ depends on ARCH_EP93XX
+diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
+index ec50eb5..c5ff72a 100644
+--- a/drivers/pwm/Makefile
++++ b/drivers/pwm/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_PWM_BCM_KONA) += pwm-bcm-kona.o
+ obj-$(CONFIG_PWM_BCM2835) += pwm-bcm2835.o
+ obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o
+ obj-$(CONFIG_PWM_CLPS711X) += pwm-clps711x.o
++obj-$(CONFIG_PWM_DISP_MEDIATEK) += pwm-disp-mediatek.o
+ obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o
+ obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o
+ obj-$(CONFIG_PWM_IMG) += pwm-img.o
+diff --git a/drivers/pwm/pwm-disp-mediatek.c b/drivers/pwm/pwm-disp-mediatek.c
+new file mode 100644
+index 0000000..38293af
+--- /dev/null
++++ b/drivers/pwm/pwm-disp-mediatek.c
+@@ -0,0 +1,225 @@
++/*
++ * Mediatek display pulse-width-modulation controller driver.
++ * Copyright (c) 2015 MediaTek Inc.
++ * Author: YH Huang <yh.huang@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/clk.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/pwm.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++
++#define DISP_PWM_EN_OFF (0x0)
++#define PWM_ENABLE_SHIFT (0x0)
++#define PWM_ENABLE_MASK (0x1 << PWM_ENABLE_SHIFT)
++
++#define DISP_PWM_COMMIT_OFF (0x08)
++#define PWM_COMMIT_SHIFT (0x0)
++#define PWM_COMMIT_MASK (0x1 << PWM_COMMIT_SHIFT)
++
++#define DISP_PWM_CON_0_OFF (0x10)
++#define PWM_CLKDIV_SHIFT (0x10)
++#define PWM_CLKDIV_MASK (0x3ff << PWM_CLKDIV_SHIFT)
++#define PWM_CLKDIV_MAX (0x000003ff)
++
++#define DISP_PWM_CON_1_OFF (0x14)
++#define PWM_PERIOD_SHIFT (0x0)
++#define PWM_PERIOD_MASK (0xfff << PWM_PERIOD_SHIFT)
++#define PWM_PERIOD_MAX (0x00000fff)
++/* Shift log2(PWM_PERIOD_MAX + 1) as divisor */
++#define PWM_PERIOD_BIT_SHIFT 12
++
++#define PWM_HIGH_WIDTH_SHIFT (0x10)
++#define PWM_HIGH_WIDTH_MASK (0x1fff << PWM_HIGH_WIDTH_SHIFT)
++
++#define NUM_PWM 1
++
++struct mtk_disp_pwm_chip {
++ struct pwm_chip chip;
++ struct device *dev;
++ struct clk *clk_main;
++ struct clk *clk_mm;
++ void __iomem *mmio_base;
++};
++
++static void mtk_disp_pwm_setting(void __iomem *address, u32 value, u32 mask)
++{
++ u32 val;
++
++ val = readl(address);
++ val &= ~mask;
++ val |= value;
++ writel(val, address);
++}
++
++static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
++ int duty_ns, int period_ns)
++{
++ struct mtk_disp_pwm_chip *mpc;
++ u64 div, rate;
++ u32 clk_div, period, high_width, rem;
++
++ /*
++ * Find period, high_width and clk_div to suit duty_ns and period_ns.
++ * Calculate proper div value to keep period value in the bound.
++ *
++ * period_ns = 10^9 * (clk_div + 1) * (period +1) / PWM_CLK_RATE
++ * duty_ns = 10^9 * (clk_div + 1) * (high_width + 1) / PWM_CLK_RATE
++ *
++ * period = (PWM_CLK_RATE * period_ns) / (10^9 * (clk_div + 1)) - 1
++ * high_width = (PWM_CLK_RATE * duty_ns) / (10^9 * (clk_div + 1)) - 1
++ */
++ mpc = container_of(chip, struct mtk_disp_pwm_chip, chip);
++ rate = clk_get_rate(mpc->clk_main);
++ clk_div = div_u64_rem(rate * period_ns, NSEC_PER_SEC, &rem) >>
++ PWM_PERIOD_BIT_SHIFT;
++ if (clk_div > PWM_CLKDIV_MAX)
++ return -EINVAL;
++
++ div = clk_div + 1;
++ period = div64_u64(rate * period_ns, NSEC_PER_SEC * div);
++ if (period > 0)
++ period--;
++ high_width = div64_u64(rate * duty_ns, NSEC_PER_SEC * div);
++ if (high_width > 0)
++ high_width--;
++
++ mtk_disp_pwm_setting(mpc->mmio_base + DISP_PWM_CON_0_OFF,
++ clk_div << PWM_CLKDIV_SHIFT, PWM_CLKDIV_MASK);
++ mtk_disp_pwm_setting(mpc->mmio_base + DISP_PWM_CON_1_OFF,
++ (period << PWM_PERIOD_SHIFT) |
++ (high_width << PWM_HIGH_WIDTH_SHIFT),
++ PWM_PERIOD_MASK | PWM_HIGH_WIDTH_MASK);
++
++ mtk_disp_pwm_setting(mpc->mmio_base + DISP_PWM_COMMIT_OFF,
++ 1 << PWM_COMMIT_SHIFT, PWM_COMMIT_MASK);
++ mtk_disp_pwm_setting(mpc->mmio_base + DISP_PWM_COMMIT_OFF,
++ 0 << PWM_COMMIT_SHIFT, PWM_COMMIT_MASK);
++
++ return 0;
++}
++
++static int mtk_disp_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
++{
++ struct mtk_disp_pwm_chip *mpc;
++
++ mpc = container_of(chip, struct mtk_disp_pwm_chip, chip);
++ mtk_disp_pwm_setting(mpc->mmio_base + DISP_PWM_EN_OFF,
++ 1 << PWM_ENABLE_SHIFT, PWM_ENABLE_MASK);
++
++ return 0;
++}
++
++static void mtk_disp_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
++{
++ struct mtk_disp_pwm_chip *mpc;
++
++ mpc = container_of(chip, struct mtk_disp_pwm_chip, chip);
++ mtk_disp_pwm_setting(mpc->mmio_base + DISP_PWM_EN_OFF,
++ 0 << PWM_ENABLE_SHIFT, PWM_ENABLE_MASK);
++}
++
++static const struct pwm_ops mtk_disp_pwm_ops = {
++ .config = mtk_disp_pwm_config,
++ .enable = mtk_disp_pwm_enable,
++ .disable = mtk_disp_pwm_disable,
++ .owner = THIS_MODULE,
++};
++
++static int mtk_disp_pwm_probe(struct platform_device *pdev)
++{
++ struct mtk_disp_pwm_chip *pwm;
++ struct resource *r;
++ int ret;
++
++ pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
++ if (!pwm)
++ return -ENOMEM;
++
++ pwm->dev = &pdev->dev;
++
++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ pwm->mmio_base = devm_ioremap_resource(&pdev->dev, r);
++ if (IS_ERR(pwm->mmio_base))
++ return PTR_ERR(pwm->mmio_base);
++
++ pwm->clk_main = devm_clk_get(&pdev->dev, "main");
++ if (IS_ERR(pwm->clk_main))
++ return PTR_ERR(pwm->clk_main);
++ pwm->clk_mm = devm_clk_get(&pdev->dev, "mm");
++ if (IS_ERR(pwm->clk_mm))
++ return PTR_ERR(pwm->clk_mm);
++
++ ret = clk_prepare_enable(pwm->clk_main);
++ if (ret < 0)
++ return ret;
++ ret = clk_prepare_enable(pwm->clk_mm);
++ if (ret < 0) {
++ clk_disable_unprepare(pwm->clk_main);
++ return ret;
++ }
++
++ platform_set_drvdata(pdev, pwm);
++
++ pwm->chip.dev = &pdev->dev;
++ pwm->chip.ops = &mtk_disp_pwm_ops;
++ pwm->chip.base = -1;
++ pwm->chip.npwm = NUM_PWM;
++
++ ret = pwmchip_add(&pwm->chip);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
++ return ret;
++ }
++
++ return 0;
++}
++
++static int mtk_disp_pwm_remove(struct platform_device *pdev)
++{
++ struct mtk_disp_pwm_chip *pc = platform_get_drvdata(pdev);
++
++ if (WARN_ON(!pc))
++ return -ENODEV;
++
++ clk_disable_unprepare(pc->clk_main);
++ clk_disable_unprepare(pc->clk_mm);
++
++ return pwmchip_remove(&pc->chip);
++}
++
++static const struct of_device_id mtk_disp_pwm_of_match[] = {
++ { .compatible = "mediatek,mt6595-disp-pwm" },
++ { }
++};
++
++MODULE_DEVICE_TABLE(of, mtk_disp_pwm_of_match);
++
++static struct platform_driver mtk_disp_pwm_driver = {
++ .driver = {
++ .name = "mediatek-disp-pwm",
++ .owner = THIS_MODULE,
++ .of_match_table = mtk_disp_pwm_of_match,
++ },
++ .probe = mtk_disp_pwm_probe,
++ .remove = mtk_disp_pwm_remove,
++};
++
++module_platform_driver(mtk_disp_pwm_driver);
++
++MODULE_AUTHOR("YH Huang <yh.huang@mediatek.com>");
++MODULE_DESCRIPTION("MediaTek SoC display PWM driver");
++MODULE_LICENSE("GPL v2");
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0029-dt-bindings-Add-I2C-bindings-for-mt65xx-mt81xx.patch b/target/linux/mediatek/patches/0029-dt-bindings-Add-I2C-bindings-for-mt65xx-mt81xx.patch
new file mode 100644
index 0000000000..03f03fb1dc
--- /dev/null
+++ b/target/linux/mediatek/patches/0029-dt-bindings-Add-I2C-bindings-for-mt65xx-mt81xx.patch
@@ -0,0 +1,64 @@
+From d1447a6815913823ef5e75d70efc6f08f288ee40 Mon Sep 17 00:00:00 2001
+From: Xudong Chen <xudong.chen@mediatek.com>
+Date: Wed, 6 May 2015 16:37:05 +0800
+Subject: [PATCH 29/76] dt-bindings: Add I2C bindings for mt65xx/mt81xx.
+
+Add devicetree bindings for Mediatek Soc I2C driver.
+
+Signed-off-by: Xudong Chen <xudong.chen@mediatek.com>
+Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
+---
+ .../devicetree/bindings/i2c/i2c-mt6577.txt | 41 ++++++++++++++++++++
+ 1 file changed, 41 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
+
+diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
+new file mode 100644
+index 0000000..0ce6fa3
+--- /dev/null
++++ b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
+@@ -0,0 +1,41 @@
++* Mediatek's I2C controller
++
++The Mediatek's I2C controller is used to interface with I2C devices.
++
++Required properties:
++ - compatible: value should be either of the following.
++ (a) "mediatek,mt6577-i2c", for i2c compatible with mt6577 i2c.
++ (b) "mediatek,mt6589-i2c", for i2c compatible with mt6589 i2c.
++ (c) "mediatek,mt8127-i2c", for i2c compatible with mt8127 i2c.
++ (d) "mediatek,mt8135-i2c", for i2c compatible with mt8135 i2c.
++ (e) "mediatek,mt8173-i2c", for i2c compatible with mt8173 i2c.
++ - reg: physical base address of the controller and dma base, length of memory
++ mapped region.
++ - interrupts: interrupt number to the cpu.
++ - clock-div: the fixed value for frequency divider of clock source in i2c
++ module. Each IC may be different.
++ - clocks: clock name from clock manager
++ - clock-names: Must include "main" and "dma", if enable have-pmic need include
++ "pmic" extra.
++
++Optional properties:
++ - clock-frequency: Frequency in Hz of the bus when transfer, the default value
++ is 100000.
++ - mediatek,have-pmic: platform can control i2c form special pmic side.
++ Only mt6589 and mt8135 support this feature.
++ - mediatek,use-push-pull: IO config use push-pull mode.
++
++Example:
++
++ i2c0: i2c@1100d000 {
++ compatible = "mediatek,mt6577-i2c";
++ reg = <0x1100d000 0x70>,
++ <0x11000300 0x80>;
++ interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_LOW>;
++ clock-frequency = <400000>;
++ mediatek,have-pmic;
++ clock-div = <16>;
++ clocks = <&i2c0_ck>, <&ap_dma_ck>;
++ clock-names = "main", "dma";
++ };
++
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0030-I2C-mediatek-Add-driver-for-MediaTek-I2C-controller.patch b/target/linux/mediatek/patches/0030-I2C-mediatek-Add-driver-for-MediaTek-I2C-controller.patch
new file mode 100644
index 0000000000..df22f08764
--- /dev/null
+++ b/target/linux/mediatek/patches/0030-I2C-mediatek-Add-driver-for-MediaTek-I2C-controller.patch
@@ -0,0 +1,760 @@
+From 2471bc43c6079ab956a04f29ffd1ab8371b7bd73 Mon Sep 17 00:00:00 2001
+From: Xudong Chen <xudong.chen@mediatek.com>
+Date: Wed, 6 May 2015 16:37:06 +0800
+Subject: [PATCH 30/76] I2C: mediatek: Add driver for MediaTek I2C controller
+
+The mediatek SoCs have I2C controller that handle I2C transfer.
+This patch include common I2C bus driver.
+This driver is compatible with I2C controller on mt65xx/mt81xx.
+
+Signed-off-by: Xudong Chen <xudong.chen@mediatek.com>
+Signed-off-by: Liguo Zhang <liguo.zhang@mediatek.com>
+Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
+---
+ drivers/i2c/busses/Kconfig | 9 +
+ drivers/i2c/busses/Makefile | 1 +
+ drivers/i2c/busses/i2c-mt65xx.c | 700 +++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 710 insertions(+)
+ create mode 100644 drivers/i2c/busses/i2c-mt65xx.c
+
+diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
+index 2255af2..14c7266 100644
+--- a/drivers/i2c/busses/Kconfig
++++ b/drivers/i2c/busses/Kconfig
+@@ -620,6 +620,15 @@ config I2C_MPC
+ This driver can also be built as a module. If so, the module
+ will be called i2c-mpc.
+
++config I2C_MT65XX
++ tristate "MediaTek I2C adapter"
++ depends on ARCH_MEDIATEK || COMPILE_TEST
++ help
++ This selects the MediaTek(R) Integrated Inter Circuit bus driver
++ for MT65xx and MT81xx.
++ If you want to use MediaTek(R) I2C interface, say Y or M here.
++ If unsure, say N.
++
+ config I2C_MV64XXX
+ tristate "Marvell mv64xxx I2C Controller"
+ depends on MV64X60 || PLAT_ORION || ARCH_SUNXI
+diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
+index cdf941d..abbf422 100644
+--- a/drivers/i2c/busses/Makefile
++++ b/drivers/i2c/busses/Makefile
+@@ -60,6 +60,7 @@ obj-$(CONFIG_I2C_JZ4780) += i2c-jz4780.o
+ obj-$(CONFIG_I2C_KEMPLD) += i2c-kempld.o
+ obj-$(CONFIG_I2C_MESON) += i2c-meson.o
+ obj-$(CONFIG_I2C_MPC) += i2c-mpc.o
++obj-$(CONFIG_I2C_MT65XX) += i2c-mt65xx.o
+ obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
+ obj-$(CONFIG_I2C_MXS) += i2c-mxs.o
+ obj-$(CONFIG_I2C_NOMADIK) += i2c-nomadik.o
+diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
+new file mode 100644
+index 0000000..faecf7e
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -0,0 +1,700 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Xudong.chen <xudong.chen@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/sched.h>
++#include <linux/delay.h>
++#include <linux/errno.h>
++#include <linux/err.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/mm.h>
++#include <linux/dma-mapping.h>
++#include <linux/scatterlist.h>
++#include <linux/io.h>
++#include <linux/of_address.h>
++#include <linux/of_irq.h>
++#include <linux/clk.h>
++#include <linux/completion.h>
++
++#define I2C_HS_NACKERR (1 << 2)
++#define I2C_ACKERR (1 << 1)
++#define I2C_TRANSAC_COMP (1 << 0)
++#define I2C_TRANSAC_START (1 << 0)
++#define I2C_TIMING_STEP_DIV_MASK (0x3f << 0)
++#define I2C_TIMING_SAMPLE_COUNT_MASK (0x7 << 0)
++#define I2C_TIMING_SAMPLE_DIV_MASK (0x7 << 8)
++#define I2C_TIMING_DATA_READ_MASK (0x7 << 12)
++#define I2C_DCM_DISABLE 0x0000
++#define I2C_IO_CONFIG_OPEN_DRAIN 0x0003
++#define I2C_IO_CONFIG_PUSH_PULL 0x0000
++#define I2C_SOFT_RST 0x0001
++#define I2C_FIFO_ADDR_CLR 0x0001
++#define I2C_DELAY_LEN 0x0002
++#define I2C_ST_START_CON 0x8001
++#define I2C_FS_START_CON 0x1800
++#define I2C_TIME_CLR_VALUE 0x0000
++#define I2C_TIME_DEFAULT_VALUE 0x0003
++#define I2C_FS_TIME_INIT_VALUE 0x1303
++#define I2C_WRRD_TRANAC_VALUE 0x0002
++#define I2C_RD_TRANAC_VALUE 0x0001
++
++#define I2C_DMA_CON_TX 0x0000
++#define I2C_DMA_CON_RX 0x0001
++#define I2C_DMA_START_EN 0x0001
++#define I2C_DMA_INT_FLAG_NONE 0x0000
++#define I2C_DMA_CLR_FLAG 0x0000
++
++#define I2C_DEFAUT_SPEED 100000 /* hz */
++#define MAX_FS_MODE_SPEED 400000
++#define MAX_HS_MODE_SPEED 3400000
++#define MAX_MSG_NUM_MT6577 1
++#define MAX_DMA_TRANS_SIZE_MT6577 255
++#define MAX_WRRD_TRANS_SIZE_MT6577 31
++#define MAX_SAMPLE_CNT_DIV 8
++#define MAX_STEP_CNT_DIV 64
++#define MAX_HS_STEP_CNT_DIV 8
++
++#define I2C_CONTROL_RS (0x1 << 1)
++#define I2C_CONTROL_DMA_EN (0x1 << 2)
++#define I2C_CONTROL_CLK_EXT_EN (0x1 << 3)
++#define I2C_CONTROL_DIR_CHANGE (0x1 << 4)
++#define I2C_CONTROL_ACKERR_DET_EN (0x1 << 5)
++#define I2C_CONTROL_TRANSFER_LEN_CHANGE (0x1 << 6)
++#define I2C_CONTROL_WRAPPER (0x1 << 0)
++
++#define I2C_DRV_NAME "mt-i2c"
++
++enum DMA_REGS_OFFSET {
++ OFFSET_INT_FLAG = 0x0,
++ OFFSET_INT_EN = 0x04,
++ OFFSET_EN = 0x08,
++ OFFSET_CON = 0x18,
++ OFFSET_TX_MEM_ADDR = 0x1c,
++ OFFSET_RX_MEM_ADDR = 0x20,
++ OFFSET_TX_LEN = 0x24,
++ OFFSET_RX_LEN = 0x28,
++};
++
++enum i2c_trans_st_rs {
++ I2C_TRANS_STOP = 0,
++ I2C_TRANS_REPEATED_START,
++};
++
++enum mtk_trans_op {
++ I2C_MASTER_WR = 1,
++ I2C_MASTER_RD,
++ I2C_MASTER_WRRD,
++};
++
++enum I2C_REGS_OFFSET {
++ OFFSET_DATA_PORT = 0x0,
++ OFFSET_SLAVE_ADDR = 0x04,
++ OFFSET_INTR_MASK = 0x08,
++ OFFSET_INTR_STAT = 0x0c,
++ OFFSET_CONTROL = 0x10,
++ OFFSET_TRANSFER_LEN = 0x14,
++ OFFSET_TRANSAC_LEN = 0x18,
++ OFFSET_DELAY_LEN = 0x1c,
++ OFFSET_TIMING = 0x20,
++ OFFSET_START = 0x24,
++ OFFSET_EXT_CONF = 0x28,
++ OFFSET_FIFO_STAT = 0x30,
++ OFFSET_FIFO_THRESH = 0x34,
++ OFFSET_FIFO_ADDR_CLR = 0x38,
++ OFFSET_IO_CONFIG = 0x40,
++ OFFSET_RSV_DEBUG = 0x44,
++ OFFSET_HS = 0x48,
++ OFFSET_SOFTRESET = 0x50,
++ OFFSET_DCM_EN = 0x54,
++ OFFSET_PATH_DIR = 0x60,
++ OFFSET_DEBUGSTAT = 0x64,
++ OFFSET_DEBUGCTRL = 0x68,
++ OFFSET_TRANSFER_LEN_AUX = 0x6c,
++};
++
++struct mtk_i2c_data {
++ unsigned int clk_frequency; /* bus speed in Hz */
++ unsigned int flags;
++ unsigned int clk_src_div;
++};
++
++struct mtk_i2c_compatible {
++ const struct i2c_adapter_quirks *quirks;
++ unsigned char pmic_i2c;
++ unsigned char dcm;
++};
++
++struct mtk_i2c {
++ struct i2c_adapter adap; /* i2c host adapter */
++ struct device *dev;
++ struct completion msg_complete;
++
++ /* set in i2c probe */
++ void __iomem *base; /* i2c base addr */
++ void __iomem *pdmabase; /* dma base address*/
++ struct clk *clk_main; /* main clock for i2c bus */
++ struct clk *clk_dma; /* DMA clock for i2c via DMA */
++ struct clk *clk_pmic; /* PMIC clock for i2c from PMIC */
++ bool have_pmic; /* can use i2c pins from PMIC */
++ bool use_push_pull; /* IO config push-pull mode */
++
++ u16 irq_stat; /* interrupt status */
++ unsigned int speed_hz; /* The speed in transfer */
++ enum mtk_trans_op op;
++ u16 timing_reg;
++ u16 high_speed_reg;
++ const struct mtk_i2c_compatible *dev_comp;
++};
++
++static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
++ .flags = I2C_AQ_COMB_WRITE_THEN_READ,
++ .max_num_msgs = MAX_MSG_NUM_MT6577,
++ .max_write_len = MAX_DMA_TRANS_SIZE_MT6577,
++ .max_read_len = MAX_DMA_TRANS_SIZE_MT6577,
++ .max_comb_1st_msg_len = MAX_DMA_TRANS_SIZE_MT6577,
++ .max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT6577,
++};
++
++static const struct mtk_i2c_compatible mt6577_compat = {
++ .quirks = &mt6577_i2c_quirks,
++ .pmic_i2c = 0,
++ .dcm = 1,
++};
++
++static const struct mtk_i2c_compatible mt6589_compat = {
++ .quirks = &mt6577_i2c_quirks,
++ .pmic_i2c = 1,
++ .dcm = 0,
++};
++
++static const struct of_device_id mtk_i2c_of_match[] = {
++ { .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
++ { .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
++ {}
++};
++MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
++
++static inline void mtk_i2c_writew(u16 value, struct mtk_i2c *i2c, u8 offset)
++{
++ writew(value, i2c->base + offset);
++}
++
++static inline u16 mtk_i2c_readw(struct mtk_i2c *i2c, u8 offset)
++{
++ return readw(i2c->base + offset);
++}
++
++static inline void mtk_i2c_writel_dma(u32 value, struct mtk_i2c *i2c, u8 offset)
++{
++ writel(value, i2c->pdmabase + offset);
++}
++
++static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
++{
++ int ret;
++
++ ret = clk_prepare_enable(i2c->clk_dma);
++ if (ret)
++ return ret;
++
++ ret = clk_prepare_enable(i2c->clk_main);
++ if (ret)
++ goto err_main;
++
++ if (i2c->have_pmic) {
++ ret = clk_prepare_enable(i2c->clk_pmic);
++ if (ret)
++ goto err_pmic;
++ }
++ return 0;
++
++err_pmic:
++ clk_disable_unprepare(i2c->clk_main);
++err_main:
++ clk_disable_unprepare(i2c->clk_dma);
++
++ return ret;
++}
++
++static void mtk_i2c_clock_disable(struct mtk_i2c *i2c)
++{
++ if (i2c->have_pmic)
++ clk_disable_unprepare(i2c->clk_pmic);
++
++ clk_disable_unprepare(i2c->clk_main);
++ clk_disable_unprepare(i2c->clk_dma);
++}
++
++static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
++{
++ u16 control_reg;
++
++ mtk_i2c_writew(I2C_SOFT_RST, i2c, OFFSET_SOFTRESET);
++ /* Set ioconfig */
++ if (i2c->use_push_pull)
++ mtk_i2c_writew(I2C_IO_CONFIG_PUSH_PULL, i2c, OFFSET_IO_CONFIG);
++ else
++ mtk_i2c_writew(I2C_IO_CONFIG_OPEN_DRAIN, i2c, OFFSET_IO_CONFIG);
++
++ if (i2c->dev_comp->dcm)
++ mtk_i2c_writew(I2C_DCM_DISABLE, i2c, OFFSET_DCM_EN);
++
++ mtk_i2c_writew(i2c->timing_reg, i2c, OFFSET_TIMING);
++ mtk_i2c_writew(i2c->high_speed_reg, i2c, OFFSET_HS);
++
++ /* If use i2c pin from PMIC mt6397 side, need set PATH_DIR first */
++ if (i2c->have_pmic)
++ mtk_i2c_writew(I2C_CONTROL_WRAPPER, i2c, OFFSET_PATH_DIR);
++
++ control_reg = I2C_CONTROL_ACKERR_DET_EN |
++ I2C_CONTROL_CLK_EXT_EN | I2C_CONTROL_DMA_EN;
++ mtk_i2c_writew(control_reg, i2c, OFFSET_CONTROL);
++ mtk_i2c_writew(I2C_DELAY_LEN, i2c, OFFSET_DELAY_LEN);
++}
++
++/* calculate i2c port speed */
++static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int clk_src_in_hz)
++{
++ unsigned int khz;
++ unsigned int step_cnt;
++ unsigned int sample_cnt;
++ unsigned int sclk;
++ unsigned int hclk;
++ unsigned int max_step_cnt;
++ unsigned int sample_div = MAX_SAMPLE_CNT_DIV;
++ unsigned int step_div;
++ unsigned int min_div;
++ unsigned int best_mul;
++ unsigned int cnt_mul;
++
++ if (i2c->speed_hz > MAX_HS_MODE_SPEED)
++ return -EINVAL;
++ else if (i2c->speed_hz > MAX_FS_MODE_SPEED)
++ max_step_cnt = MAX_HS_STEP_CNT_DIV;
++ else
++ max_step_cnt = MAX_STEP_CNT_DIV;
++
++ step_div = max_step_cnt;
++ /* Find the best combination */
++ khz = i2c->speed_hz / 1000;
++ hclk = clk_src_in_hz / 1000;
++ min_div = ((hclk >> 1) + khz - 1) / khz;
++ best_mul = MAX_SAMPLE_CNT_DIV * max_step_cnt;
++
++ for (sample_cnt = 1; sample_cnt <= MAX_SAMPLE_CNT_DIV; sample_cnt++) {
++ step_cnt = (min_div + sample_cnt - 1) / sample_cnt;
++ cnt_mul = step_cnt * sample_cnt;
++ if (step_cnt > max_step_cnt)
++ continue;
++
++ if (cnt_mul < best_mul) {
++ best_mul = cnt_mul;
++ sample_div = sample_cnt;
++ step_div = step_cnt;
++ if (best_mul == min_div)
++ break;
++ }
++ }
++
++ sample_cnt = sample_div;
++ step_cnt = step_div;
++ sclk = hclk / (2 * sample_cnt * step_cnt);
++ if (sclk > khz) {
++ dev_dbg(i2c->dev, "%s mode: unsupported speed (%ldkhz)\n",
++ (i2c->speed_hz > MAX_HS_MODE_SPEED) ? "HS" : "ST/FT",
++ (long int)khz);
++ return -ENOTSUPP;
++ }
++
++ step_cnt--;
++ sample_cnt--;
++
++ if (i2c->speed_hz > MAX_FS_MODE_SPEED) {
++ /* Set the hign speed mode register */
++ i2c->timing_reg = I2C_FS_TIME_INIT_VALUE;
++ i2c->high_speed_reg = I2C_TIME_DEFAULT_VALUE |
++ (sample_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 12 |
++ (step_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 8;
++ } else {
++ i2c->timing_reg =
++ (sample_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 8 |
++ (step_cnt & I2C_TIMING_STEP_DIV_MASK) << 0;
++ /* Disable the high speed transaction */
++ i2c->high_speed_reg = I2C_TIME_CLR_VALUE;
++ }
++
++ return 0;
++}
++
++static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
++{
++ u16 addr_reg;
++ u16 control_reg;
++ dma_addr_t rpaddr = 0;
++ dma_addr_t wpaddr = 0;
++ int ret;
++
++ i2c->irq_stat = 0;
++
++ reinit_completion(&i2c->msg_complete);
++
++ control_reg = mtk_i2c_readw(i2c, OFFSET_CONTROL) &
++ ~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS);
++ if (i2c->speed_hz > 400000)
++ control_reg |= I2C_CONTROL_RS;
++ if (i2c->op == I2C_MASTER_WRRD)
++ control_reg |= I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS;
++ mtk_i2c_writew(control_reg, i2c, OFFSET_CONTROL);
++
++ /* set start condition */
++ if (i2c->speed_hz <= 100000)
++ mtk_i2c_writew(I2C_ST_START_CON, i2c, OFFSET_EXT_CONF);
++ else
++ mtk_i2c_writew(I2C_FS_START_CON, i2c, OFFSET_EXT_CONF);
++
++ addr_reg = msgs->addr << 1;
++ if (i2c->op == I2C_MASTER_RD)
++ addr_reg |= 0x1;
++ mtk_i2c_writew(addr_reg, i2c, OFFSET_SLAVE_ADDR);
++
++ /* Clear interrupt status */
++ mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
++ i2c, OFFSET_INTR_STAT);
++ mtk_i2c_writew(I2C_FIFO_ADDR_CLR, i2c, OFFSET_FIFO_ADDR_CLR);
++
++ /* Enable interrupt */
++ mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
++ i2c, OFFSET_INTR_MASK);
++
++ /* Set transfer and transaction len */
++ if (i2c->op == I2C_MASTER_WRRD) {
++ mtk_i2c_writew(msgs->len | ((msgs + 1)->len) << 8,
++ i2c, OFFSET_TRANSFER_LEN);
++ mtk_i2c_writew(I2C_WRRD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
++ } else {
++ mtk_i2c_writew(msgs->len, i2c, OFFSET_TRANSFER_LEN);
++ mtk_i2c_writew(I2C_RD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
++ }
++
++ /* Prepare buffer data to start transfer */
++ if (i2c->op == I2C_MASTER_RD) {
++ mtk_i2c_writel_dma(I2C_DMA_INT_FLAG_NONE, i2c, OFFSET_INT_FLAG);
++ mtk_i2c_writel_dma(I2C_DMA_CON_RX, i2c, OFFSET_CON);
++ rpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
++ msgs->len, DMA_FROM_DEVICE);
++ if (dma_mapping_error(i2c->adap.dev.parent, rpaddr))
++ return -ENOMEM;
++ mtk_i2c_writel_dma((u32)rpaddr, i2c, OFFSET_RX_MEM_ADDR);
++ mtk_i2c_writel_dma(msgs->len, i2c, OFFSET_RX_LEN);
++ } else if (i2c->op == I2C_MASTER_WR) {
++ mtk_i2c_writel_dma(I2C_DMA_INT_FLAG_NONE, i2c, OFFSET_INT_FLAG);
++ mtk_i2c_writel_dma(I2C_DMA_CON_TX, i2c, OFFSET_CON);
++ wpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
++ msgs->len, DMA_TO_DEVICE);
++ if (dma_mapping_error(i2c->adap.dev.parent, wpaddr))
++ return -ENOMEM;
++ mtk_i2c_writel_dma((u32)wpaddr, i2c, OFFSET_TX_MEM_ADDR);
++ mtk_i2c_writel_dma(msgs->len, i2c, OFFSET_TX_LEN);
++ } else {
++ mtk_i2c_writel_dma(I2C_DMA_CLR_FLAG, i2c, OFFSET_INT_FLAG);
++ mtk_i2c_writel_dma(I2C_DMA_CLR_FLAG, i2c, OFFSET_CON);
++ wpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
++ msgs->len, DMA_TO_DEVICE);
++ if (dma_mapping_error(i2c->adap.dev.parent, wpaddr))
++ return -ENOMEM;
++ rpaddr = dma_map_single(i2c->adap.dev.parent, (msgs + 1)->buf,
++ (msgs + 1)->len,
++ DMA_FROM_DEVICE);
++ if (dma_mapping_error(i2c->adap.dev.parent, rpaddr)) {
++ dma_unmap_single(i2c->adap.dev.parent, wpaddr,
++ msgs->len, DMA_TO_DEVICE);
++ return -ENOMEM;
++ }
++ mtk_i2c_writel_dma((u32)wpaddr, i2c, OFFSET_TX_MEM_ADDR);
++ mtk_i2c_writel_dma((u32)rpaddr, i2c, OFFSET_RX_MEM_ADDR);
++ mtk_i2c_writel_dma(msgs->len, i2c, OFFSET_TX_LEN);
++ mtk_i2c_writel_dma((msgs + 1)->len, i2c, OFFSET_RX_LEN);
++ }
++
++ /* flush before sending start */
++ mb();
++ mtk_i2c_writel_dma(I2C_DMA_START_EN, i2c, OFFSET_EN);
++ mtk_i2c_writew(I2C_TRANSAC_START, i2c, OFFSET_START);
++
++ ret = wait_for_completion_timeout(&i2c->msg_complete,
++ i2c->adap.timeout);
++
++ /* Clear interrupt mask */
++ mtk_i2c_writew(~(I2C_HS_NACKERR | I2C_ACKERR
++ | I2C_TRANSAC_COMP), i2c, OFFSET_INTR_MASK);
++
++ if (i2c->op == I2C_MASTER_WR) {
++ dma_unmap_single(i2c->adap.dev.parent, wpaddr,
++ msgs->len, DMA_TO_DEVICE);
++ } else if (i2c->op == I2C_MASTER_RD) {
++ dma_unmap_single(i2c->adap.dev.parent, rpaddr,
++ msgs->len, DMA_FROM_DEVICE);
++ } else {
++ dma_unmap_single(i2c->adap.dev.parent, wpaddr, msgs->len,
++ DMA_TO_DEVICE);
++ dma_unmap_single(i2c->adap.dev.parent, rpaddr, (msgs + 1)->len,
++ DMA_FROM_DEVICE);
++ }
++
++ if (ret == 0) {
++ dev_dbg(i2c->dev, "addr: %x, transfer timeout\n", msgs->addr);
++ mtk_i2c_init_hw(i2c);
++ return -ETIMEDOUT;
++ }
++
++ completion_done(&i2c->msg_complete);
++
++ if (i2c->irq_stat & (I2C_HS_NACKERR | I2C_ACKERR)) {
++ dev_dbg(i2c->dev, "addr: %x, transfer ACK error\n", msgs->addr);
++ mtk_i2c_init_hw(i2c);
++ return -EREMOTEIO;
++ }
++
++ return 0;
++}
++
++static int mtk_i2c_transfer(struct i2c_adapter *adap,
++ struct i2c_msg msgs[], int num)
++{
++ int ret;
++ int left_num = num;
++ struct mtk_i2c *i2c = i2c_get_adapdata(adap);
++
++ ret = mtk_i2c_clock_enable(i2c);
++ if (ret)
++ return ret;
++
++ if (msgs->buf == NULL) {
++ dev_dbg(i2c->dev, "data buffer is NULL.\n");
++ ret = -EINVAL;
++ goto err_exit;
++ }
++
++ if (msgs->flags & I2C_M_RD)
++ i2c->op = I2C_MASTER_RD;
++ else
++ i2c->op = I2C_MASTER_WR;
++
++ if (num > 1) {
++ /* combined two messages into one transaction */
++ i2c->op = I2C_MASTER_WRRD;
++ left_num--;
++ }
++
++ /* always use DMA mode. */
++ ret = mtk_i2c_do_transfer(i2c, msgs);
++ if (ret < 0)
++ goto err_exit;
++
++ /* the return value is number of executed messages */
++ ret = num;
++
++err_exit:
++ mtk_i2c_clock_disable(i2c);
++ return ret;
++}
++
++static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
++{
++ struct mtk_i2c *i2c = dev_id;
++
++ i2c->irq_stat = mtk_i2c_readw(i2c, OFFSET_INTR_STAT);
++ mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR
++ | I2C_TRANSAC_COMP, i2c, OFFSET_INTR_STAT);
++
++ complete(&i2c->msg_complete);
++
++ return IRQ_HANDLED;
++}
++
++static u32 mtk_i2c_functionality(struct i2c_adapter *adap)
++{
++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
++}
++
++static const struct i2c_algorithm mtk_i2c_algorithm = {
++ .master_xfer = mtk_i2c_transfer,
++ .functionality = mtk_i2c_functionality,
++};
++
++static int mtk_i2c_parse_dt(struct device_node *np, struct mtk_i2c *i2c,
++ unsigned int *clk_src_div)
++{
++ int ret;
++
++ ret = of_property_read_u32(np, "clock-frequency", &i2c->speed_hz);
++ if (ret < 0)
++ i2c->speed_hz = I2C_DEFAUT_SPEED;
++
++ ret = of_property_read_u32(np, "clock-div", clk_src_div);
++ if (ret < 0)
++ return ret;
++
++ if (*clk_src_div == 0)
++ return -EINVAL;
++
++ i2c->have_pmic = of_property_read_bool(np, "mediatek,have-pmic");
++ i2c->use_push_pull =
++ of_property_read_bool(np, "mediatek,use-push-pull");
++
++ return 0;
++}
++
++static int mtk_i2c_probe(struct platform_device *pdev)
++{
++ const struct of_device_id *of_id;
++ int ret = 0;
++ struct mtk_i2c *i2c;
++ struct clk *clk;
++ unsigned int clk_src_in_hz;
++ unsigned int clk_src_div;
++ struct resource *res;
++ int irq;
++
++ i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
++ if (i2c == NULL)
++ return -ENOMEM;
++
++ ret = mtk_i2c_parse_dt(pdev->dev.of_node, i2c, &clk_src_div);
++ if (ret)
++ return -EINVAL;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ i2c->base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(i2c->base))
++ return PTR_ERR(i2c->base);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++ i2c->pdmabase = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(i2c->pdmabase))
++ return PTR_ERR(i2c->pdmabase);
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq <= 0)
++ return irq;
++
++ init_completion(&i2c->msg_complete);
++
++ of_id = of_match_node(mtk_i2c_of_match, pdev->dev.of_node);
++ if (!of_id)
++ return -EINVAL;
++
++ i2c->dev_comp = of_id->data;
++ i2c->adap.dev.of_node = pdev->dev.of_node;
++ i2c->dev = &i2c->adap.dev;
++ i2c->adap.dev.parent = &pdev->dev;
++ i2c->adap.owner = THIS_MODULE;
++ i2c->adap.algo = &mtk_i2c_algorithm;
++ i2c->adap.quirks = i2c->dev_comp->quirks;
++ i2c->adap.timeout = 2 * HZ;
++ i2c->adap.retries = 1;
++
++ if (i2c->have_pmic && !i2c->dev_comp->pmic_i2c)
++ return -EINVAL;
++
++ i2c->clk_main = devm_clk_get(&pdev->dev, "main");
++ if (IS_ERR(i2c->clk_main)) {
++ dev_err(&pdev->dev, "cannot get main clock\n");
++ return PTR_ERR(i2c->clk_main);
++ }
++
++ i2c->clk_dma = devm_clk_get(&pdev->dev, "dma");
++ if (IS_ERR(i2c->clk_dma)) {
++ dev_err(&pdev->dev, "cannot get dma clock\n");
++ return PTR_ERR(i2c->clk_dma);
++ }
++
++ clk = i2c->clk_main;
++ if (i2c->have_pmic) {
++ i2c->clk_pmic = devm_clk_get(&pdev->dev, "pmic");
++ if (IS_ERR(i2c->clk_pmic)) {
++ dev_err(&pdev->dev, "cannot get pmic clock\n");
++ return PTR_ERR(i2c->clk_pmic);
++ }
++ clk = i2c->clk_pmic;
++ }
++ clk_src_in_hz = clk_get_rate(clk) / clk_src_div;
++
++ dev_dbg(&pdev->dev, "clock source %p,clock src frequency %d\n",
++ i2c->clk_main, clk_src_in_hz);
++ strlcpy(i2c->adap.name, I2C_DRV_NAME, sizeof(i2c->adap.name));
++
++ ret = mtk_i2c_set_speed(i2c, clk_src_in_hz);
++ if (ret) {
++ dev_err(&pdev->dev, "Failed to set the speed.\n");
++ return -EINVAL;
++ }
++
++ ret = mtk_i2c_clock_enable(i2c);
++ if (ret) {
++ dev_err(&pdev->dev, "clock enable failed!\n");
++ return ret;
++ }
++ mtk_i2c_init_hw(i2c);
++ mtk_i2c_clock_disable(i2c);
++
++ ret = devm_request_irq(&pdev->dev, irq, mtk_i2c_irq,
++ IRQF_TRIGGER_NONE, I2C_DRV_NAME, i2c);
++ if (ret < 0) {
++ dev_err(&pdev->dev,
++ "Request I2C IRQ %d fail\n", irq);
++ return ret;
++ }
++
++ i2c_set_adapdata(&i2c->adap, i2c);
++ ret = i2c_add_adapter(&i2c->adap);
++ if (ret) {
++ dev_err(&pdev->dev, "Failed to add i2c bus to i2c core\n");
++ return ret;
++ }
++
++ platform_set_drvdata(pdev, i2c);
++
++ return 0;
++}
++
++static int mtk_i2c_remove(struct platform_device *pdev)
++{
++ struct mtk_i2c *i2c = platform_get_drvdata(pdev);
++
++ i2c_del_adapter(&i2c->adap);
++
++ return 0;
++}
++
++static struct platform_driver mtk_i2c_driver = {
++ .probe = mtk_i2c_probe,
++ .remove = mtk_i2c_remove,
++ .driver = {
++ .name = I2C_DRV_NAME,
++ .of_match_table = of_match_ptr(mtk_i2c_of_match),
++ },
++};
++
++module_platform_driver(mtk_i2c_driver);
++
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("MediaTek I2C Bus Driver");
++MODULE_AUTHOR("Xudong Chen <xudong.chen@mediatek.com>");
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0031-I2C-mediatek-Add-driver-for-MediaTek-MT8173-I2C-cont.patch b/target/linux/mediatek/patches/0031-I2C-mediatek-Add-driver-for-MediaTek-MT8173-I2C-cont.patch
new file mode 100644
index 0000000000..25ea23ef23
--- /dev/null
+++ b/target/linux/mediatek/patches/0031-I2C-mediatek-Add-driver-for-MediaTek-MT8173-I2C-cont.patch
@@ -0,0 +1,244 @@
+From 5f33206ebe4fb4a2cc8634f29c3e3c9bc01e3416 Mon Sep 17 00:00:00 2001
+From: Eddie Huang <eddie.huang@mediatek.com>
+Date: Wed, 6 May 2015 16:37:07 +0800
+Subject: [PATCH 31/76] I2C: mediatek: Add driver for MediaTek MT8173 I2C
+ controller
+
+Add mediatek MT8173 I2C controller driver. Compare to I2C controller
+of earlier mediatek SoC, MT8173 fix write-then-read limitation, and
+also increase message size to 64kb.
+
+Signed-off-by: Xudong Chen <xudong.chen@mediatek.com>
+Signed-off-by: Liguo Zhang <liguo.zhang@mediatek.com>
+Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
+---
+ drivers/i2c/busses/i2c-mt65xx.c | 104 ++++++++++++++++++++++++++++-----------
+ 1 file changed, 76 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
+index faecf7e..c501421 100644
+--- a/drivers/i2c/busses/i2c-mt65xx.c
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -33,10 +33,13 @@
+ #include <linux/clk.h>
+ #include <linux/completion.h>
+
++#define I2C_RS_TRANSFER (1 << 4)
+ #define I2C_HS_NACKERR (1 << 2)
+ #define I2C_ACKERR (1 << 1)
+ #define I2C_TRANSAC_COMP (1 << 0)
+ #define I2C_TRANSAC_START (1 << 0)
++#define I2C_RS_MUL_CNFG (1 << 15)
++#define I2C_RS_MUL_TRIG (1 << 14)
+ #define I2C_TIMING_STEP_DIV_MASK (0x3f << 0)
+ #define I2C_TIMING_SAMPLE_COUNT_MASK (0x7 << 0)
+ #define I2C_TIMING_SAMPLE_DIV_MASK (0x7 << 8)
+@@ -67,6 +70,9 @@
+ #define MAX_MSG_NUM_MT6577 1
+ #define MAX_DMA_TRANS_SIZE_MT6577 255
+ #define MAX_WRRD_TRANS_SIZE_MT6577 31
++#define MAX_MSG_NUM_MT8173 65535
++#define MAX_DMA_TRANS_SIZE_MT8173 65535
++#define MAX_WRRD_TRANS_SIZE_MT8173 65535
+ #define MAX_SAMPLE_CNT_DIV 8
+ #define MAX_STEP_CNT_DIV 64
+ #define MAX_HS_STEP_CNT_DIV 8
+@@ -139,6 +145,7 @@ struct mtk_i2c_compatible {
+ const struct i2c_adapter_quirks *quirks;
+ unsigned char pmic_i2c;
+ unsigned char dcm;
++ unsigned char auto_restart;
+ };
+
+ struct mtk_i2c {
+@@ -172,21 +179,39 @@ static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
+ .max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT6577,
+ };
+
++static const struct i2c_adapter_quirks mt8173_i2c_quirks = {
++ .max_num_msgs = MAX_MSG_NUM_MT8173,
++ .max_write_len = MAX_DMA_TRANS_SIZE_MT8173,
++ .max_read_len = MAX_DMA_TRANS_SIZE_MT8173,
++ .max_comb_1st_msg_len = MAX_DMA_TRANS_SIZE_MT8173,
++ .max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT8173,
++};
++
+ static const struct mtk_i2c_compatible mt6577_compat = {
+ .quirks = &mt6577_i2c_quirks,
+ .pmic_i2c = 0,
+ .dcm = 1,
++ .auto_restart = 0,
+ };
+
+ static const struct mtk_i2c_compatible mt6589_compat = {
+ .quirks = &mt6577_i2c_quirks,
+ .pmic_i2c = 1,
+ .dcm = 0,
++ .auto_restart = 0,
++};
++
++static const struct mtk_i2c_compatible mt8173_compat = {
++ .quirks = &mt8173_i2c_quirks,
++ .pmic_i2c = 0,
++ .dcm = 1,
++ .auto_restart = 1,
+ };
+
+ static const struct of_device_id mtk_i2c_of_match[] = {
+ { .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
+ { .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
++ { .compatible = "mediatek,mt8173-i2c", .data = (void *)&mt8173_compat },
+ {}
+ };
+ MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
+@@ -343,9 +368,11 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int clk_src_in_hz)
+ return 0;
+ }
+
+-static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
++static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
++ int num, int left_num)
+ {
+ u16 addr_reg;
++ u16 start_reg;
+ u16 control_reg;
+ dma_addr_t rpaddr = 0;
+ dma_addr_t wpaddr = 0;
+@@ -361,6 +388,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
+ control_reg |= I2C_CONTROL_RS;
+ if (i2c->op == I2C_MASTER_WRRD)
+ control_reg |= I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS;
++ if (left_num >= 1)
++ control_reg |= I2C_CONTROL_RS;
+ mtk_i2c_writew(control_reg, i2c, OFFSET_CONTROL);
+
+ /* set start condition */
+@@ -375,13 +404,13 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
+ mtk_i2c_writew(addr_reg, i2c, OFFSET_SLAVE_ADDR);
+
+ /* Clear interrupt status */
+- mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
+- i2c, OFFSET_INTR_STAT);
++ mtk_i2c_writew(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
++ | I2C_TRANSAC_COMP, i2c, OFFSET_INTR_STAT);
+ mtk_i2c_writew(I2C_FIFO_ADDR_CLR, i2c, OFFSET_FIFO_ADDR_CLR);
+
+ /* Enable interrupt */
+- mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
+- i2c, OFFSET_INTR_MASK);
++ mtk_i2c_writew(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
++ | I2C_TRANSAC_COMP, i2c, OFFSET_INTR_MASK);
+
+ /* Set transfer and transaction len */
+ if (i2c->op == I2C_MASTER_WRRD) {
+@@ -390,7 +419,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
+ mtk_i2c_writew(I2C_WRRD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
+ } else {
+ mtk_i2c_writew(msgs->len, i2c, OFFSET_TRANSFER_LEN);
+- mtk_i2c_writew(I2C_RD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
++ mtk_i2c_writew(num, i2c, OFFSET_TRANSAC_LEN);
+ }
+
+ /* Prepare buffer data to start transfer */
+@@ -436,13 +465,23 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
+ /* flush before sending start */
+ mb();
+ mtk_i2c_writel_dma(I2C_DMA_START_EN, i2c, OFFSET_EN);
+- mtk_i2c_writew(I2C_TRANSAC_START, i2c, OFFSET_START);
++
++ if (!i2c->dev_comp->auto_restart) {
++ start_reg = I2C_TRANSAC_START;
++ } else {
++ if (left_num >= 1)
++ start_reg = I2C_TRANSAC_START | I2C_RS_MUL_CNFG
++ | I2C_RS_MUL_TRIG;
++ else
++ start_reg = I2C_TRANSAC_START | I2C_RS_MUL_TRIG;
++ }
++ mtk_i2c_writew(start_reg, i2c, OFFSET_START);
+
+ ret = wait_for_completion_timeout(&i2c->msg_complete,
+ i2c->adap.timeout);
+
+ /* Clear interrupt mask */
+- mtk_i2c_writew(~(I2C_HS_NACKERR | I2C_ACKERR
++ mtk_i2c_writew(~(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
+ | I2C_TRANSAC_COMP), i2c, OFFSET_INTR_MASK);
+
+ if (i2c->op == I2C_MASTER_WR) {
+@@ -472,6 +511,10 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
+ return -EREMOTEIO;
+ }
+
++ if (i2c->irq_stat & I2C_RS_TRANSFER)
++ dev_dbg(i2c->dev, "addr: %x, restart transfer interrupt.\n",
++ msgs->addr);
++
+ return 0;
+ }
+
+@@ -486,28 +529,33 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
+ if (ret)
+ return ret;
+
+- if (msgs->buf == NULL) {
+- dev_dbg(i2c->dev, "data buffer is NULL.\n");
+- ret = -EINVAL;
+- goto err_exit;
+- }
+-
+- if (msgs->flags & I2C_M_RD)
+- i2c->op = I2C_MASTER_RD;
+- else
+- i2c->op = I2C_MASTER_WR;
++ while (left_num--) {
++ if (msgs->buf == NULL) {
++ dev_dbg(i2c->dev, "data buffer is NULL.\n");
++ ret = -EINVAL;
++ goto err_exit;
++ }
+
+- if (num > 1) {
+- /* combined two messages into one transaction */
+- i2c->op = I2C_MASTER_WRRD;
+- left_num--;
+- }
++ if (msgs->flags & I2C_M_RD)
++ i2c->op = I2C_MASTER_RD;
++ else
++ i2c->op = I2C_MASTER_WR;
++
++ if (!i2c->dev_comp->auto_restart) {
++ if (num > 1) {
++ /* combined two messages into one transaction */
++ i2c->op = I2C_MASTER_WRRD;
++ left_num--;
++ }
++ }
+
+- /* always use DMA mode. */
+- ret = mtk_i2c_do_transfer(i2c, msgs);
+- if (ret < 0)
+- goto err_exit;
++ /* always use DMA mode. */
++ ret = mtk_i2c_do_transfer(i2c, msgs, num, left_num);
++ if (ret < 0)
++ goto err_exit;
+
++ msgs++;
++ }
+ /* the return value is number of executed messages */
+ ret = num;
+
+@@ -521,7 +569,7 @@ static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
+ struct mtk_i2c *i2c = dev_id;
+
+ i2c->irq_stat = mtk_i2c_readw(i2c, OFFSET_INTR_STAT);
+- mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR
++ mtk_i2c_writew(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
+ | I2C_TRANSAC_COMP, i2c, OFFSET_INTR_STAT);
+
+ complete(&i2c->msg_complete);
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0032-dt-bindings-mediatek-Add-MT8173-cpufreq-driver-bindi.patch b/target/linux/mediatek/patches/0032-dt-bindings-mediatek-Add-MT8173-cpufreq-driver-bindi.patch
new file mode 100644
index 0000000000..7f3b249a05
--- /dev/null
+++ b/target/linux/mediatek/patches/0032-dt-bindings-mediatek-Add-MT8173-cpufreq-driver-bindi.patch
@@ -0,0 +1,150 @@
+From d83532fe7eb9cc7b8cc39dd9f2bbd9873d4e390b Mon Sep 17 00:00:00 2001
+From: "pi-cheng.chen" <pi-cheng.chen@linaro.org>
+Date: Mon, 8 Jun 2015 20:29:20 +0800
+Subject: [PATCH 32/76] dt-bindings: mediatek: Add MT8173 cpufreq driver
+ binding
+
+This patch adds device tree binding document for MT8173 cpufreq driver.
+
+Signed-off-by: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
+---
+ .../devicetree/bindings/cpufreq/cpufreq-mt8173.txt | 127 ++++++++++++++++++++
+ 1 file changed, 127 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/cpufreq/cpufreq-mt8173.txt
+
+diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-mt8173.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-mt8173.txt
+new file mode 100644
+index 0000000..7708a65
+--- /dev/null
++++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-mt8173.txt
+@@ -0,0 +1,127 @@
++
++Mediatek MT8173 cpufreq driver
++-------------------
++
++Mediatek MT8173 cpufreq driver for CPU frequency scaling.
++
++Required properties:
++- clocks: A list of phandle + clock-specifier pairs for the clocks listed in clock names.
++- clock-names: Should contain the following:
++ "cpu" - The multiplexer for clock input of CPU cluster.
++ "intermediate" - A parent of "cpu" clock which is used as "intermediate" clock
++ source (usually MAINPLL) when the original CPU PLL is under
++ transition and not stable yet.
++- operating-points: Table of frequencies and voltage CPU could be transitioned into,
++ Frequency should be in KHz units and voltage should be in microvolts.
++- proc-supply: Regulator for Vproc of CPU cluster.
++
++Optional properties:
++- sram-supply: Regulator for Vsram of CPU cluster. When present, the cpufreq driver
++ needs to do "voltage trace" to step by step scale up/down Vproc and
++ Vsram to fit SoC specific needs. When absent, the voltage scaling
++ flow is handled by hardware, hence no software "voltage trace" is
++ needed.
++
++Example:
++--------
++ cpu0: cpu@0 {
++ device_type = "cpu";
++ compatible = "arm,cortex-a53";
++ reg = <0x000>;
++ enable-method = "psci";
++ cpu-idle-states = <&CPU_SLEEP_0>;
++ clocks = <&infracfg CLK_INFRA_CA53SEL>,
++ <&apmixedsys CLK_APMIXED_MAINPLL>;
++ clock-names = "cpu", "intermediate";
++ operating-points = <
++ 507000 859000
++ 702000 908000
++ 1001000 983000
++ 1105000 1009000
++ 1183000 1028000
++ 1404000 1083000
++ 1508000 1109000
++ 1573000 1125000
++ >;
++ };
++
++ cpu1: cpu@1 {
++ device_type = "cpu";
++ compatible = "arm,cortex-a53";
++ reg = <0x001>;
++ enable-method = "psci";
++ cpu-idle-states = <&CPU_SLEEP_0>;
++ clocks = <&infracfg CLK_INFRA_CA53SEL>,
++ <&apmixedsys CLK_APMIXED_MAINPLL>;
++ clock-names = "cpu", "intermediate";
++ operating-points = <
++ 507000 859000
++ 702000 908000
++ 1001000 983000
++ 1105000 1009000
++ 1183000 1028000
++ 1404000 1083000
++ 1508000 1109000
++ 1573000 1125000
++ >;
++ };
++
++ cpu2: cpu@100 {
++ device_type = "cpu";
++ compatible = "arm,cortex-a57";
++ reg = <0x100>;
++ enable-method = "psci";
++ cpu-idle-states = <&CPU_SLEEP_0>;
++ clocks = <&infracfg CLK_INFRA_CA57SEL>,
++ <&apmixedsys CLK_APMIXED_MAINPLL>;
++ clock-names = "cpu", "intermediate";
++ operating-points = <
++ 507000 828000
++ 702000 867000
++ 1001000 927000
++ 1209000 968000
++ 1404000 1007000
++ 1612000 1049000
++ 1807000 1089000
++ 1989000 1125000
++ >;
++ };
++
++ cpu3: cpu@101 {
++ device_type = "cpu";
++ compatible = "arm,cortex-a57";
++ reg = <0x101>;
++ enable-method = "psci";
++ cpu-idle-states = <&CPU_SLEEP_0>;
++ clocks = <&infracfg CLK_INFRA_CA57SEL>,
++ <&apmixedsys CLK_APMIXED_MAINPLL>;
++ clock-names = "cpu", "intermediate";
++ operating-points = <
++ 507000 828000
++ 702000 867000
++ 1001000 927000
++ 1209000 968000
++ 1404000 1007000
++ 1612000 1049000
++ 1807000 1089000
++ 1989000 1125000
++ >;
++ };
++
++ &cpu0 {
++ proc-supply = <&mt6397_vpca15_reg>;
++ };
++
++ &cpu1 {
++ proc-supply = <&mt6397_vpca15_reg>;
++ };
++
++ &cpu2 {
++ proc-supply = <&da9211_vcpu_reg>;
++ sram-supply = <&mt6397_vsramca7_reg>;
++ };
++
++ &cpu3 {
++ proc-supply = <&da9211_vcpu_reg>;
++ sram-supply = <&mt6397_vsramca7_reg>;
++ };
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0033-cpufreq-mediatek-Add-MT8173-cpufreq-driver.patch b/target/linux/mediatek/patches/0033-cpufreq-mediatek-Add-MT8173-cpufreq-driver.patch
new file mode 100644
index 0000000000..81ae4f8275
--- /dev/null
+++ b/target/linux/mediatek/patches/0033-cpufreq-mediatek-Add-MT8173-cpufreq-driver.patch
@@ -0,0 +1,604 @@
+From 2028cb37c941014f6a817d27a867ee1d37ccf2b6 Mon Sep 17 00:00:00 2001
+From: "pi-cheng.chen" <pi-cheng.chen@linaro.org>
+Date: Mon, 8 Jun 2015 20:29:21 +0800
+Subject: [PATCH 33/76] cpufreq: mediatek: Add MT8173 cpufreq driver
+
+This patch implements MT8173 cpufreq driver.
+
+Signed-off-by: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
+---
+ drivers/cpufreq/Kconfig.arm | 7 +
+ drivers/cpufreq/Makefile | 1 +
+ drivers/cpufreq/mt8173-cpufreq.c | 550 ++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 558 insertions(+)
+ create mode 100644 drivers/cpufreq/mt8173-cpufreq.c
+
+diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
+index 4f3dbc8..350752b 100644
+--- a/drivers/cpufreq/Kconfig.arm
++++ b/drivers/cpufreq/Kconfig.arm
+@@ -141,6 +141,13 @@ config ARM_KIRKWOOD_CPUFREQ
+ This adds the CPUFreq driver for Marvell Kirkwood
+ SoCs.
+
++config ARM_MT8173_CPUFREQ
++ bool "Mediatek MT8173 CPUFreq support"
++ depends on ARCH_MEDIATEK && REGULATOR
++ select PM_OPP
++ help
++ This adds the CPUFreq driver support for Mediatek MT8173 SoC.
++
+ config ARM_OMAP2PLUS_CPUFREQ
+ bool "TI OMAP2+"
+ depends on ARCH_OMAP2PLUS
+diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
+index cdce92a..97f9a9b 100644
+--- a/drivers/cpufreq/Makefile
++++ b/drivers/cpufreq/Makefile
+@@ -63,6 +63,7 @@ obj-$(CONFIG_ARM_HISI_ACPU_CPUFREQ) += hisi-acpu-cpufreq.o
+ obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o
+ obj-$(CONFIG_ARM_INTEGRATOR) += integrator-cpufreq.o
+ obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o
++obj-$(CONFIG_ARM_MT8173_CPUFREQ) += mt8173-cpufreq.o
+ obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o
+ obj-$(CONFIG_ARM_PXA2xx_CPUFREQ) += pxa2xx-cpufreq.o
+ obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o
+diff --git a/drivers/cpufreq/mt8173-cpufreq.c b/drivers/cpufreq/mt8173-cpufreq.c
+new file mode 100644
+index 0000000..d539e7b
+--- /dev/null
++++ b/drivers/cpufreq/mt8173-cpufreq.c
+@@ -0,0 +1,550 @@
++/*
++ * Copyright (c) 2015 Linaro Ltd.
++ * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/clk.h>
++#include <linux/cpu.h>
++#include <linux/cpufreq.h>
++#include <linux/cpumask.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++#include <linux/pm_opp.h>
++#include <linux/regulator/consumer.h>
++#include <linux/slab.h>
++
++#define MIN_VOLT_SHIFT (100000)
++#define MAX_VOLT_SHIFT (200000)
++#define MAX_VOLT_LIMIT (1150000)
++#define VOLT_TOL (10000)
++
++/*
++ * The struct mtk_cpu_dvfs_info holds necessary information for doing CPU DVFS
++ * on each CPU power/clock domain of Mediatek SoCs. Each CPU cluster in
++ * Mediatek SoCs has two voltage inputs, Vproc and Vsram. In some cases the two
++ * voltage inputs need to be controlled under a hardware limitation:
++ * 100mV < Vsram - Vproc < 200mV
++ *
++ * When scaling the clock frequency of a CPU clock domain, the clock source
++ * needs to be switched to another stable PLL clock temporarily until
++ * the original PLL becomes stable at target frequency.
++ */
++struct mtk_cpu_dvfs_info {
++ struct list_head node;
++ cpumask_var_t cpus;
++ struct cpufreq_frequency_table *freq_table;
++ struct device *cpu_dev;
++ struct regulator *proc_reg;
++ struct regulator *sram_reg;
++ struct clk *cpu_clk;
++ struct clk *inter_clk;
++ int intermediate_voltage;
++ bool need_voltage_trace;
++};
++
++static LIST_HEAD(cpu_dvfs_info_list);
++
++static inline struct mtk_cpu_dvfs_info *to_mtk_cpu_dvfs_info(
++ struct list_head *list)
++{
++ return list_entry(list, struct mtk_cpu_dvfs_info, node);
++}
++
++static inline void mtk_cpu_dvfs_info_add(struct mtk_cpu_dvfs_info *info)
++{
++ list_add(&info->node, &cpu_dvfs_info_list);
++}
++
++static struct mtk_cpu_dvfs_info *mtk_cpu_dvfs_info_get(int cpu)
++{
++ struct mtk_cpu_dvfs_info *info;
++ struct list_head *list;
++
++ list_for_each(list, &cpu_dvfs_info_list) {
++ info = to_mtk_cpu_dvfs_info(list);
++
++ if (cpumask_test_cpu(cpu, info->cpus))
++ return info;
++ }
++
++ return NULL;
++}
++
++static void mtk_cpu_dvfs_info_release(void)
++{
++ struct list_head *list, *tmp;
++ struct mtk_cpu_dvfs_info *info;
++
++ list_for_each_safe(list, tmp, &cpu_dvfs_info_list) {
++ info = to_mtk_cpu_dvfs_info(list);
++
++ dev_pm_opp_free_cpufreq_table(info->cpu_dev,
++ &info->freq_table);
++
++ if (!IS_ERR(info->proc_reg))
++ regulator_put(info->proc_reg);
++ if (!IS_ERR(info->sram_reg))
++ regulator_put(info->sram_reg);
++ if (!IS_ERR(info->cpu_clk))
++ clk_put(info->cpu_clk);
++ if (!IS_ERR(info->inter_clk))
++ clk_put(info->inter_clk);
++
++ of_free_opp_table(info->cpu_dev);
++
++ list_del(list);
++ kfree(info);
++ }
++}
++
++#define MIN(a, b) ((a) < (b) ? (a) : (b))
++#define MAX(a, b) ((a) > (b) ? (a) : (b))
++
++static int mtk_cpufreq_voltage_trace(struct mtk_cpu_dvfs_info *info,
++ int new_vproc)
++{
++ struct regulator *proc_reg = info->proc_reg;
++ struct regulator *sram_reg = info->sram_reg;
++ int old_vproc, old_vsram, new_vsram, vsram, vproc, ret;
++
++ old_vproc = regulator_get_voltage(proc_reg);
++ old_vsram = regulator_get_voltage(sram_reg);
++ /* Vsram should not exceed the maximum allowed voltage of SoC. */
++ new_vsram = min(new_vproc + MIN_VOLT_SHIFT, MAX_VOLT_LIMIT);
++
++ if (old_vproc < new_vproc) {
++ /*
++ * When scaling up voltages, Vsram and Vproc scale up step
++ * by step. At each step, set Vsram to (Vproc + 200mV) first,
++ * then set Vproc to (Vsram - 100mV).
++ * Keep doing it until Vsram and Vproc hit target voltages.
++ */
++ do {
++ old_vsram = regulator_get_voltage(sram_reg);
++ old_vproc = regulator_get_voltage(proc_reg);
++
++ vsram = MIN(new_vsram, old_vproc + MAX_VOLT_SHIFT);
++
++ if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) {
++ vsram = MAX_VOLT_LIMIT;
++
++ /*
++ * If the target Vsram hits the maximum voltage,
++ * try to set the exact voltage value first.
++ */
++ ret = regulator_set_voltage(sram_reg, vsram,
++ vsram);
++ if (ret)
++ ret = regulator_set_voltage(sram_reg,
++ vsram - VOLT_TOL,
++ vsram);
++
++ vproc = new_vproc;
++ } else {
++ ret = regulator_set_voltage(sram_reg, vsram,
++ vsram + VOLT_TOL);
++
++ vproc = vsram - MIN_VOLT_SHIFT;
++ }
++ if (ret)
++ return ret;
++
++ ret = regulator_set_voltage(proc_reg, vproc,
++ vproc + VOLT_TOL);
++ if (ret) {
++ regulator_set_voltage(sram_reg, old_vsram,
++ old_vsram);
++ return ret;
++ }
++ } while (vproc < new_vproc || vsram < new_vsram);
++ } else if (old_vproc > new_vproc) {
++ /*
++ * When scaling down voltages, Vsram and Vproc scale down step
++ * by step. At each step, set Vproc to (Vsram - 200mV) first,
++ * then set Vproc to (Vproc + 100mV).
++ * Keep doing it until Vsram and Vproc hit target voltages.
++ */
++ do {
++ old_vproc = regulator_get_voltage(proc_reg);
++ old_vsram = regulator_get_voltage(sram_reg);
++
++ vproc = MAX(new_vproc, old_vsram - MAX_VOLT_SHIFT);
++ ret = regulator_set_voltage(proc_reg, vproc,
++ vproc + VOLT_TOL);
++ if (ret)
++ return ret;
++
++ if (vproc == new_vproc)
++ vsram = new_vsram;
++ else
++ vsram = MAX(new_vsram, vproc + MIN_VOLT_SHIFT);
++
++ if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) {
++ vsram = MAX_VOLT_LIMIT;
++
++ /*
++ * If the target Vsram hits the maximum voltage,
++ * try to set the exact voltage value first.
++ */
++ ret = regulator_set_voltage(sram_reg, vsram,
++ vsram);
++ if (ret)
++ ret = regulator_set_voltage(sram_reg,
++ vsram - VOLT_TOL,
++ vsram);
++ } else {
++ ret = regulator_set_voltage(sram_reg, vsram,
++ vsram + VOLT_TOL);
++ }
++
++ if (ret) {
++ regulator_set_voltage(proc_reg, old_vproc,
++ old_vproc);
++ return ret;
++ }
++ } while (vproc > new_vproc + VOLT_TOL ||
++ vsram > new_vsram + VOLT_TOL);
++ }
++
++ return 0;
++}
++
++static int mtk_cpufreq_set_voltage(struct mtk_cpu_dvfs_info *info, int vproc)
++{
++ if (info->need_voltage_trace)
++ return mtk_cpufreq_voltage_trace(info, vproc);
++ else
++ return regulator_set_voltage(info->proc_reg, vproc,
++ vproc + VOLT_TOL);
++}
++
++static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
++ unsigned int index)
++{
++ struct cpufreq_frequency_table *freq_table = policy->freq_table;
++ struct clk *cpu_clk = policy->clk;
++ struct clk *armpll = clk_get_parent(cpu_clk);
++ struct mtk_cpu_dvfs_info *info = policy->driver_data;
++ struct device *cpu_dev = info->cpu_dev;
++ struct dev_pm_opp *opp;
++ long freq_hz, old_freq_hz;
++ int vproc, old_vproc, inter_vproc, target_vproc, ret;
++
++ inter_vproc = info->intermediate_voltage;
++
++ old_freq_hz = clk_get_rate(cpu_clk);
++ old_vproc = regulator_get_voltage(info->proc_reg);
++
++ freq_hz = freq_table[index].frequency * 1000;
++ rcu_read_lock();
++ opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
++ if (IS_ERR(opp)) {
++ rcu_read_unlock();
++ pr_err("cpu%d: failed to find OPP for %ld\n",
++ policy->cpu, freq_hz);
++ return PTR_ERR(opp);
++ }
++ vproc = dev_pm_opp_get_voltage(opp);
++ rcu_read_unlock();
++
++ /*
++ * If the new voltage or the intermediate voltage is higher than the
++ * current voltage, scale up voltage first.
++ */
++ target_vproc = (inter_vproc > vproc) ? inter_vproc : vproc;
++ if (old_vproc < target_vproc) {
++ ret = mtk_cpufreq_set_voltage(info, target_vproc);
++ if (ret) {
++ pr_err("cpu%d: failed to scale up voltage!\n",
++ policy->cpu);
++ mtk_cpufreq_set_voltage(info, old_vproc);
++ return ret;
++ }
++ }
++
++ /* Reparent the CPU clock to intermediate clock. */
++ ret = clk_set_parent(cpu_clk, info->inter_clk);
++ if (ret) {
++ pr_err("cpu%d: failed to re-parent cpu clock!\n",
++ policy->cpu);
++ mtk_cpufreq_set_voltage(info, old_vproc);
++ WARN_ON(1);
++ return ret;
++ }
++
++ /* Set the original PLL to target rate. */
++ ret = clk_set_rate(armpll, freq_hz);
++ if (ret) {
++ pr_err("cpu%d: failed to scale cpu clock rate!\n",
++ policy->cpu);
++ clk_set_parent(cpu_clk, armpll);
++ mtk_cpufreq_set_voltage(info, old_vproc);
++ return ret;
++ }
++
++ /* Set parent of CPU clock back to the original PLL. */
++ ret = clk_set_parent(cpu_clk, armpll);
++ if (ret) {
++ pr_err("cpu%d: failed to re-parent cpu clock!\n",
++ policy->cpu);
++ mtk_cpufreq_set_voltage(info, inter_vproc);
++ WARN_ON(1);
++ return ret;
++ }
++
++ /*
++ * If the new voltage is lower than the intermediate voltage or the
++ * original voltage, scale down to the new voltage.
++ */
++ if (vproc < inter_vproc || vproc < old_vproc) {
++ ret = mtk_cpufreq_set_voltage(info, vproc);
++ if (ret) {
++ pr_err("cpu%d: failed to scale down voltage!\n",
++ policy->cpu);
++ clk_set_parent(cpu_clk, info->inter_clk);
++ clk_set_rate(armpll, old_freq_hz);
++ clk_set_parent(cpu_clk, armpll);
++ return ret;
++ }
++ }
++
++ return 0;
++}
++
++static int mtk_cpufreq_init(struct cpufreq_policy *policy)
++{
++ struct mtk_cpu_dvfs_info *info;
++ int ret;
++
++ info = mtk_cpu_dvfs_info_get(policy->cpu);
++ if (!info) {
++ pr_err("%s: mtk cpu dvfs info for cpu%d is not initialized\n",
++ __func__, policy->cpu);
++ return -ENODEV;
++ }
++
++ ret = cpufreq_table_validate_and_show(policy, info->freq_table);
++ if (ret) {
++ pr_err("%s: invalid frequency table: %d\n", __func__, ret);
++ return ret;
++ }
++
++ cpumask_copy(policy->cpus, info->cpus);
++ policy->driver_data = info;
++ policy->clk = info->cpu_clk;
++
++ return 0;
++}
++
++static struct cpufreq_driver mt8173_cpufreq_driver = {
++ .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
++ .verify = cpufreq_generic_frequency_table_verify,
++ .target_index = mtk_cpufreq_set_target,
++ .get = cpufreq_generic_get,
++ .init = mtk_cpufreq_init,
++ .name = "mtk-cpufreq",
++ .attr = cpufreq_generic_attr,
++};
++
++static int mtk_cpu_dvfs_info_init(int cpu)
++{
++ struct device *cpu_dev;
++ struct regulator *proc_reg = ERR_PTR(-ENODEV);
++ struct regulator *sram_reg = ERR_PTR(-ENODEV);
++ struct clk *cpu_clk = ERR_PTR(-ENODEV);
++ struct clk *inter_clk = ERR_PTR(-ENODEV);
++ struct mtk_cpu_dvfs_info *info;
++ struct cpufreq_frequency_table *freq_table;
++ struct dev_pm_opp *opp;
++ unsigned long rate;
++ int ret;
++
++ cpu_dev = get_cpu_device(cpu);
++ if (!cpu_dev) {
++ pr_err("failed to get cpu%d device\n", cpu);
++ return -ENODEV;
++ }
++
++ ret = of_init_opp_table(cpu_dev);
++ if (ret) {
++ pr_warn("no OPP table for cpu%d\n", cpu);
++ return ret;
++ }
++
++ cpu_clk = clk_get(cpu_dev, "cpu");
++ if (IS_ERR(cpu_clk)) {
++ if (PTR_ERR(cpu_clk) == -EPROBE_DEFER)
++ pr_warn("cpu clk for cpu%d not ready, retry.\n", cpu);
++ else
++ pr_err("failed to get cpu clk for cpu%d\n", cpu);
++
++ ret = PTR_ERR(cpu_clk);
++ goto out_free_opp_table;
++ }
++
++ inter_clk = clk_get(cpu_dev, "intermediate");
++ if (IS_ERR(inter_clk)) {
++ if (PTR_ERR(inter_clk) == -EPROBE_DEFER)
++ pr_warn("intermediate clk for cpu%d not ready, retry.\n",
++ cpu);
++ else
++ pr_err("failed to get intermediate clk for cpu%d\n",
++ cpu);
++
++ ret = PTR_ERR(cpu_clk);
++ goto out_free_resources;
++ }
++
++ proc_reg = regulator_get_exclusive(cpu_dev, "proc");
++ if (IS_ERR(proc_reg)) {
++ if (PTR_ERR(proc_reg) == -EPROBE_DEFER)
++ pr_warn("proc regulator for cpu%d not ready, retry.\n",
++ cpu);
++ else
++ pr_err("failed to get proc regulator for cpu%d\n",
++ cpu);
++
++ ret = PTR_ERR(proc_reg);
++ goto out_free_resources;
++ }
++
++ /* Both presence and absence of sram regulator are valid cases. */
++ sram_reg = regulator_get_exclusive(cpu_dev, "sram");
++
++ info = kzalloc(sizeof(*info), GFP_KERNEL);
++ if (!info) {
++ ret = -ENOMEM;
++ goto out_free_resources;
++ }
++
++ ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
++ if (ret) {
++ pr_err("failed to init cpufreq table for cpu%d: %d\n",
++ cpu, ret);
++ goto out_free_mtk_cpu_dvfs_info;
++ }
++
++ if (!alloc_cpumask_var(&info->cpus, GFP_KERNEL))
++ goto out_free_cpufreq_table;
++
++ /* Search a safe voltage for intermediate frequency. */
++ rate = clk_get_rate(inter_clk);
++ rcu_read_lock();
++ opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
++ if (IS_ERR(opp)) {
++ pr_err("failed to get intermediate opp for cpu%d\n", cpu);
++ ret = PTR_ERR(opp);
++ goto out_free_cpumask;
++ }
++ info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
++ rcu_read_unlock();
++
++ /* CPUs in the same cluster share a clock and power domain. */
++ cpumask_copy(info->cpus, &cpu_topology[cpu].core_sibling);
++
++ info->cpu_dev = cpu_dev;
++ info->proc_reg = proc_reg;
++ info->sram_reg = IS_ERR(sram_reg) ? NULL : sram_reg;
++ info->cpu_clk = cpu_clk;
++ info->inter_clk = inter_clk;
++ info->freq_table = freq_table;
++
++ /*
++ * If SRAM regulator is present, software "voltage trace" is needed
++ * for this CPU power domain.
++ */
++ info->need_voltage_trace = !IS_ERR(sram_reg);
++
++ mtk_cpu_dvfs_info_add(info);
++
++ return 0;
++
++out_free_cpumask:
++ free_cpumask_var(info->cpus);
++
++out_free_cpufreq_table:
++ dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
++
++out_free_mtk_cpu_dvfs_info:
++ kfree(info);
++
++out_free_resources:
++ if (!IS_ERR(proc_reg))
++ regulator_put(proc_reg);
++ if (!IS_ERR(sram_reg))
++ regulator_put(sram_reg);
++ if (!IS_ERR(cpu_clk))
++ clk_put(cpu_clk);
++ if (!IS_ERR(inter_clk))
++ clk_put(inter_clk);
++
++out_free_opp_table:
++ of_free_opp_table(cpu_dev);
++
++ return ret;
++}
++
++static int mt8173_cpufreq_probe(struct platform_device *pdev)
++{
++ int cpu, ret;
++
++ for_each_possible_cpu(cpu) {
++ /*
++ * If the struct mtk_cpu_dvfs_info for the cpu power domain
++ * is already initialized, skip this CPU.
++ */
++ if (!mtk_cpu_dvfs_info_get(cpu)) {
++ ret = mtk_cpu_dvfs_info_init(cpu);
++ if (ret) {
++ if (ret != -EPROBE_DEFER)
++ pr_err("%s probe fail\n", __func__);
++
++ mtk_cpu_dvfs_info_release();
++ return ret;
++ }
++ }
++ }
++
++ ret = cpufreq_register_driver(&mt8173_cpufreq_driver);
++ if (ret) {
++ pr_err("failed to register mtk cpufreq driver\n");
++ mtk_cpu_dvfs_info_release();
++ }
++
++ return ret;
++}
++
++static struct platform_driver mt8173_cpufreq_platdrv = {
++ .driver = {
++ .name = "mt8173-cpufreq",
++ },
++ .probe = mt8173_cpufreq_probe,
++};
++module_platform_driver(mt8173_cpufreq_platdrv);
++
++static int mt8173_cpufreq_driver_init(void)
++{
++ struct platform_device *pdev;
++
++ if (!of_machine_is_compatible("mediatek,mt8173"))
++ return -ENODEV;
++
++ pdev = platform_device_register_simple("mt8173-cpufreq", -1, NULL, 0);
++ if (IS_ERR(pdev)) {
++ pr_err("failed to register mtk-cpufreq platform device\n");
++ return PTR_ERR(pdev);
++ }
++
++ return 0;
++}
++module_init(mt8173_cpufreq_driver_init);
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0034-mmc-dt-bindings-add-Mediatek-MMC-bindings.patch b/target/linux/mediatek/patches/0034-mmc-dt-bindings-add-Mediatek-MMC-bindings.patch
new file mode 100644
index 0000000000..02a153d7da
--- /dev/null
+++ b/target/linux/mediatek/patches/0034-mmc-dt-bindings-add-Mediatek-MMC-bindings.patch
@@ -0,0 +1,54 @@
+From fe43da8836dbf8e48377d208000877a17e465f3f Mon Sep 17 00:00:00 2001
+From: Chaotian Jing <chaotian.jing@mediatek.com>
+Date: Mon, 15 Jun 2015 19:20:47 +0800
+Subject: [PATCH 34/76] mmc: dt-bindings: add Mediatek MMC bindings
+
+Document the device-tree binding of Mediatek MMC host
+
+Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
+---
+ Documentation/devicetree/bindings/mmc/mtk-sd.txt | 32 ++++++++++++++++++++++
+ 1 file changed, 32 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/mmc/mtk-sd.txt
+
+diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.txt b/Documentation/devicetree/bindings/mmc/mtk-sd.txt
+new file mode 100644
+index 0000000..a1adfa4
+--- /dev/null
++++ b/Documentation/devicetree/bindings/mmc/mtk-sd.txt
+@@ -0,0 +1,32 @@
++* MTK MMC controller
++
++The MTK MSDC can act as a MMC controller
++to support MMC, SD, and SDIO types of memory cards.
++
++This file documents differences between the core properties in mmc.txt
++and the properties used by the msdc driver.
++
++Required properties:
++- compatible: Should be "mediatek,mt8173-mmc","mediatek,mt8135-mmc"
++- interrupts: Should contain MSDC interrupt number
++- clocks: MSDC source clock, HCLK
++- clock-names: "source", "hclk"
++- pinctrl-names: should be "default", "state_uhs"
++- pinctrl-0: should contain default/high speed pin ctrl
++- pinctrl-1: should contain uhs mode pin ctrl
++- vmmc-supply: power to the Core
++- vqmmc-supply: power to the IO
++
++Examples:
++mmc0: mmc@11230000 {
++ compatible = "mediatek,mt8173-mmc", "mediatek,mt8135-mmc";
++ reg = <0 0x11230000 0 0x108>;
++ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_LOW>;
++ vmmc-supply = <&mt6397_vemc_3v3_reg>;
++ vqmmc-supply = <&mt6397_vio18_reg>;
++ clocks = <&pericfg CLK_PERI_MSDC30_0>, <&topckgen CLK_TOP_MSDC50_0_H_SEL>;
++ clock-names = "source", "hclk";
++ pinctrl-names = "default", "state_uhs";
++ pinctrl-0 = <&mmc0_pins_default>;
++ pinctrl-1 = <&mmc0_pins_uhs>;
++};
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0035-mmc-mediatek-Add-Mediatek-MMC-driver.patch b/target/linux/mediatek/patches/0035-mmc-mediatek-Add-Mediatek-MMC-driver.patch
new file mode 100644
index 0000000000..d135ad0432
--- /dev/null
+++ b/target/linux/mediatek/patches/0035-mmc-mediatek-Add-Mediatek-MMC-driver.patch
@@ -0,0 +1,1422 @@
+From 0b71d2f1ee40313f58a3c6e9ed95add6f5a8192d Mon Sep 17 00:00:00 2001
+From: Chaotian Jing <chaotian.jing@mediatek.com>
+Date: Mon, 15 Jun 2015 19:20:48 +0800
+Subject: [PATCH 35/76] mmc: mediatek: Add Mediatek MMC driver
+
+Add Mediatek MMC driver code
+Support eMMC/SD/SDIO
+
+Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
+---
+ drivers/mmc/host/Kconfig | 8 +
+ drivers/mmc/host/Makefile | 1 +
+ drivers/mmc/host/mtk-sd.c | 1378 +++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/mmc/core.h | 1 +
+ 4 files changed, 1388 insertions(+)
+ create mode 100644 drivers/mmc/host/mtk-sd.c
+
+--- a/drivers/mmc/host/Kconfig
++++ b/drivers/mmc/host/Kconfig
+@@ -800,3 +800,11 @@
+ tristate "Toshiba Type A SD/MMC Card Interface Driver"
+ depends on PCI
+ help
++
++config MMC_MTK
++ tristate "MediaTek SD/MMC Card Interface support"
++ help
++ This selects the MediaTek(R) Secure digital and Multimedia card Interface.
++ If you have a machine with a integrated SD/MMC card reader, say Y or M here.
++ This is needed if support for any SD/SDIO/MMC devices is required.
++ If unsure, say N.
+--- a/drivers/mmc/host/Makefile
++++ b/drivers/mmc/host/Makefile
+@@ -20,6 +20,7 @@
+ obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o
+ obj-$(CONFIG_MMC_WBSD) += wbsd.o
+ obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
++obj-$(CONFIG_MMC_MTK) += mtk-sd.o
+ obj-$(CONFIG_MMC_OMAP) += omap.o
+ obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc.o
+ obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o
+--- /dev/null
++++ b/drivers/mmc/host/mtk-sd.c
+@@ -0,0 +1,1378 @@
++/*
++ * Copyright (c) 2014-2015 MediaTek Inc.
++ * Author: Chaotian.Jing <chaotian.jing@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/ioport.h>
++#include <linux/irq.h>
++#include <linux/of_address.h>
++#include <linux/of_irq.h>
++#include <linux/of_gpio.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/platform_device.h>
++#include <linux/regulator/consumer.h>
++#include <linux/spinlock.h>
++
++#include <linux/mmc/card.h>
++#include <linux/mmc/core.h>
++#include <linux/mmc/host.h>
++#include <linux/mmc/mmc.h>
++#include <linux/mmc/sd.h>
++#include <linux/mmc/sdio.h>
++
++#define MAX_BD_NUM 1024
++
++/*--------------------------------------------------------------------------*/
++/* Common Definition */
++/*--------------------------------------------------------------------------*/
++#define MSDC_BUS_1BITS 0x0
++#define MSDC_BUS_4BITS 0x1
++#define MSDC_BUS_8BITS 0x2
++
++#define MSDC_BURST_64B 0x6
++
++/*--------------------------------------------------------------------------*/
++/* Register Offset */
++/*--------------------------------------------------------------------------*/
++#define MSDC_CFG 0x0
++#define MSDC_IOCON 0x04
++#define MSDC_PS 0x08
++#define MSDC_INT 0x0c
++#define MSDC_INTEN 0x10
++#define MSDC_FIFOCS 0x14
++#define SDC_CFG 0x30
++#define SDC_CMD 0x34
++#define SDC_ARG 0x38
++#define SDC_STS 0x3c
++#define SDC_RESP0 0x40
++#define SDC_RESP1 0x44
++#define SDC_RESP2 0x48
++#define SDC_RESP3 0x4c
++#define SDC_BLK_NUM 0x50
++#define SDC_ACMD_RESP 0x80
++#define MSDC_DMA_SA 0x90
++#define MSDC_DMA_CTRL 0x98
++#define MSDC_DMA_CFG 0x9c
++#define MSDC_PATCH_BIT 0xb0
++#define MSDC_PATCH_BIT1 0xb4
++#define MSDC_PAD_TUNE 0xec
++
++/*--------------------------------------------------------------------------*/
++/* Register Mask */
++/*--------------------------------------------------------------------------*/
++
++/* MSDC_CFG mask */
++#define MSDC_CFG_MODE (0x1 << 0) /* RW */
++#define MSDC_CFG_CKPDN (0x1 << 1) /* RW */
++#define MSDC_CFG_RST (0x1 << 2) /* RW */
++#define MSDC_CFG_PIO (0x1 << 3) /* RW */
++#define MSDC_CFG_CKDRVEN (0x1 << 4) /* RW */
++#define MSDC_CFG_BV18SDT (0x1 << 5) /* RW */
++#define MSDC_CFG_BV18PSS (0x1 << 6) /* R */
++#define MSDC_CFG_CKSTB (0x1 << 7) /* R */
++#define MSDC_CFG_CKDIV (0xff << 8) /* RW */
++#define MSDC_CFG_CKMOD (0x3 << 16) /* RW */
++
++/* MSDC_IOCON mask */
++#define MSDC_IOCON_SDR104CKS (0x1 << 0) /* RW */
++#define MSDC_IOCON_RSPL (0x1 << 1) /* RW */
++#define MSDC_IOCON_DSPL (0x1 << 2) /* RW */
++#define MSDC_IOCON_DDLSEL (0x1 << 3) /* RW */
++#define MSDC_IOCON_DDR50CKD (0x1 << 4) /* RW */
++#define MSDC_IOCON_DSPLSEL (0x1 << 5) /* RW */
++#define MSDC_IOCON_W_DSPL (0x1 << 8) /* RW */
++#define MSDC_IOCON_D0SPL (0x1 << 16) /* RW */
++#define MSDC_IOCON_D1SPL (0x1 << 17) /* RW */
++#define MSDC_IOCON_D2SPL (0x1 << 18) /* RW */
++#define MSDC_IOCON_D3SPL (0x1 << 19) /* RW */
++#define MSDC_IOCON_D4SPL (0x1 << 20) /* RW */
++#define MSDC_IOCON_D5SPL (0x1 << 21) /* RW */
++#define MSDC_IOCON_D6SPL (0x1 << 22) /* RW */
++#define MSDC_IOCON_D7SPL (0x1 << 23) /* RW */
++#define MSDC_IOCON_RISCSZ (0x3 << 24) /* RW */
++
++/* MSDC_PS mask */
++#define MSDC_PS_CDEN (0x1 << 0) /* RW */
++#define MSDC_PS_CDSTS (0x1 << 1) /* R */
++#define MSDC_PS_CDDEBOUNCE (0xf << 12) /* RW */
++#define MSDC_PS_DAT (0xff << 16) /* R */
++#define MSDC_PS_CMD (0x1 << 24) /* R */
++#define MSDC_PS_WP (0x1 << 31) /* R */
++
++/* MSDC_INT mask */
++#define MSDC_INT_MMCIRQ (0x1 << 0) /* W1C */
++#define MSDC_INT_CDSC (0x1 << 1) /* W1C */
++#define MSDC_INT_ACMDRDY (0x1 << 3) /* W1C */
++#define MSDC_INT_ACMDTMO (0x1 << 4) /* W1C */
++#define MSDC_INT_ACMDCRCERR (0x1 << 5) /* W1C */
++#define MSDC_INT_DMAQ_EMPTY (0x1 << 6) /* W1C */
++#define MSDC_INT_SDIOIRQ (0x1 << 7) /* W1C */
++#define MSDC_INT_CMDRDY (0x1 << 8) /* W1C */
++#define MSDC_INT_CMDTMO (0x1 << 9) /* W1C */
++#define MSDC_INT_RSPCRCERR (0x1 << 10) /* W1C */
++#define MSDC_INT_CSTA (0x1 << 11) /* R */
++#define MSDC_INT_XFER_COMPL (0x1 << 12) /* W1C */
++#define MSDC_INT_DXFER_DONE (0x1 << 13) /* W1C */
++#define MSDC_INT_DATTMO (0x1 << 14) /* W1C */
++#define MSDC_INT_DATCRCERR (0x1 << 15) /* W1C */
++#define MSDC_INT_ACMD19_DONE (0x1 << 16) /* W1C */
++#define MSDC_INT_DMA_BDCSERR (0x1 << 17) /* W1C */
++#define MSDC_INT_DMA_GPDCSERR (0x1 << 18) /* W1C */
++#define MSDC_INT_DMA_PROTECT (0x1 << 19) /* W1C */
++
++/* MSDC_INTEN mask */
++#define MSDC_INTEN_MMCIRQ (0x1 << 0) /* RW */
++#define MSDC_INTEN_CDSC (0x1 << 1) /* RW */
++#define MSDC_INTEN_ACMDRDY (0x1 << 3) /* RW */
++#define MSDC_INTEN_ACMDTMO (0x1 << 4) /* RW */
++#define MSDC_INTEN_ACMDCRCERR (0x1 << 5) /* RW */
++#define MSDC_INTEN_DMAQ_EMPTY (0x1 << 6) /* RW */
++#define MSDC_INTEN_SDIOIRQ (0x1 << 7) /* RW */
++#define MSDC_INTEN_CMDRDY (0x1 << 8) /* RW */
++#define MSDC_INTEN_CMDTMO (0x1 << 9) /* RW */
++#define MSDC_INTEN_RSPCRCERR (0x1 << 10) /* RW */
++#define MSDC_INTEN_CSTA (0x1 << 11) /* RW */
++#define MSDC_INTEN_XFER_COMPL (0x1 << 12) /* RW */
++#define MSDC_INTEN_DXFER_DONE (0x1 << 13) /* RW */
++#define MSDC_INTEN_DATTMO (0x1 << 14) /* RW */
++#define MSDC_INTEN_DATCRCERR (0x1 << 15) /* RW */
++#define MSDC_INTEN_ACMD19_DONE (0x1 << 16) /* RW */
++#define MSDC_INTEN_DMA_BDCSERR (0x1 << 17) /* RW */
++#define MSDC_INTEN_DMA_GPDCSERR (0x1 << 18) /* RW */
++#define MSDC_INTEN_DMA_PROTECT (0x1 << 19) /* RW */
++
++/* MSDC_FIFOCS mask */
++#define MSDC_FIFOCS_RXCNT (0xff << 0) /* R */
++#define MSDC_FIFOCS_TXCNT (0xff << 16) /* R */
++#define MSDC_FIFOCS_CLR (0x1 << 31) /* RW */
++
++/* SDC_CFG mask */
++#define SDC_CFG_SDIOINTWKUP (0x1 << 0) /* RW */
++#define SDC_CFG_INSWKUP (0x1 << 1) /* RW */
++#define SDC_CFG_BUSWIDTH (0x3 << 16) /* RW */
++#define SDC_CFG_SDIO (0x1 << 19) /* RW */
++#define SDC_CFG_SDIOIDE (0x1 << 20) /* RW */
++#define SDC_CFG_INTATGAP (0x1 << 21) /* RW */
++#define SDC_CFG_DTOC (0xff << 24) /* RW */
++
++/* SDC_STS mask */
++#define SDC_STS_SDCBUSY (0x1 << 0) /* RW */
++#define SDC_STS_CMDBUSY (0x1 << 1) /* RW */
++#define SDC_STS_SWR_COMPL (0x1 << 31) /* RW */
++
++/* MSDC_DMA_CTRL mask */
++#define MSDC_DMA_CTRL_START (0x1 << 0) /* W */
++#define MSDC_DMA_CTRL_STOP (0x1 << 1) /* W */
++#define MSDC_DMA_CTRL_RESUME (0x1 << 2) /* W */
++#define MSDC_DMA_CTRL_MODE (0x1 << 8) /* RW */
++#define MSDC_DMA_CTRL_LASTBUF (0x1 << 10) /* RW */
++#define MSDC_DMA_CTRL_BRUSTSZ (0x7 << 12) /* RW */
++
++/* MSDC_DMA_CFG mask */
++#define MSDC_DMA_CFG_STS (0x1 << 0) /* R */
++#define MSDC_DMA_CFG_DECSEN (0x1 << 1) /* RW */
++#define MSDC_DMA_CFG_AHBHPROT2 (0x2 << 8) /* RW */
++#define MSDC_DMA_CFG_ACTIVEEN (0x2 << 12) /* RW */
++#define MSDC_DMA_CFG_CS12B16B (0x1 << 16) /* RW */
++
++/* MSDC_PATCH_BIT mask */
++#define MSDC_PATCH_BIT_ODDSUPP (0x1 << 1) /* RW */
++#define MSDC_INT_DAT_LATCH_CK_SEL (0x7 << 7)
++#define MSDC_CKGEN_MSDC_DLY_SEL (0x1f << 10)
++#define MSDC_PATCH_BIT_IODSSEL (0x1 << 16) /* RW */
++#define MSDC_PATCH_BIT_IOINTSEL (0x1 << 17) /* RW */
++#define MSDC_PATCH_BIT_BUSYDLY (0xf << 18) /* RW */
++#define MSDC_PATCH_BIT_WDOD (0xf << 22) /* RW */
++#define MSDC_PATCH_BIT_IDRTSEL (0x1 << 26) /* RW */
++#define MSDC_PATCH_BIT_CMDFSEL (0x1 << 27) /* RW */
++#define MSDC_PATCH_BIT_INTDLSEL (0x1 << 28) /* RW */
++#define MSDC_PATCH_BIT_SPCPUSH (0x1 << 29) /* RW */
++#define MSDC_PATCH_BIT_DECRCTMO (0x1 << 30) /* RW */
++
++#define REQ_CMD_EIO (0x1 << 0)
++#define REQ_CMD_TMO (0x1 << 1)
++#define REQ_DAT_ERR (0x1 << 2)
++#define REQ_STOP_EIO (0x1 << 3)
++#define REQ_STOP_TMO (0x1 << 4)
++#define REQ_CMD_BUSY (0x1 << 5)
++
++#define MSDC_PREPARE_FLAG (0x1 << 0)
++#define MSDC_ASYNC_FLAG (0x1 << 1)
++#define MSDC_MMAP_FLAG (0x1 << 2)
++
++#define CMD_TIMEOUT (HZ/10 * 5) /* 100ms x5 */
++#define DAT_TIMEOUT (HZ * 5) /* 1000ms x5 */
++
++/*--------------------------------------------------------------------------*/
++/* Descriptor Structure */
++/*--------------------------------------------------------------------------*/
++struct mt_gpdma_desc {
++ u32 gpd_info;
++#define GPDMA_DESC_HWO (0x1 << 0)
++#define GPDMA_DESC_BDP (0x1 << 1)
++#define GPDMA_DESC_CHECKSUM (0xff << 8) /* bit8 ~ bit15 */
++#define GPDMA_DESC_INT (0x1 << 16)
++ u32 next;
++ u32 ptr;
++ u32 gpd_data_len;
++#define GPDMA_DESC_BUFLEN (0xffff) /* bit0 ~ bit15 */
++#define GPDMA_DESC_EXTLEN (0xff << 16) /* bit16 ~ bit23 */
++ u32 arg;
++ u32 blknum;
++ u32 cmd;
++};
++
++struct mt_bdma_desc {
++ u32 bd_info;
++#define BDMA_DESC_EOL (0x1 << 0)
++#define BDMA_DESC_CHECKSUM (0xff << 8) /* bit8 ~ bit15 */
++#define BDMA_DESC_BLKPAD (0x1 << 17)
++#define BDMA_DESC_DWPAD (0x1 << 18)
++ u32 next;
++ u32 ptr;
++ u32 bd_data_len;
++#define BDMA_DESC_BUFLEN (0xffff) /* bit0 ~ bit15 */
++};
++
++struct msdc_dma {
++ struct scatterlist *sg; /* I/O scatter list */
++ struct mt_gpdma_desc *gpd; /* pointer to gpd array */
++ struct mt_bdma_desc *bd; /* pointer to bd array */
++ dma_addr_t gpd_addr; /* the physical address of gpd array */
++ dma_addr_t bd_addr; /* the physical address of bd array */
++};
++
++struct msdc_host {
++ struct device *dev;
++ struct mmc_host *mmc; /* mmc structure */
++ int cmd_rsp;
++
++ spinlock_t lock;
++ struct mmc_request *mrq;
++ struct mmc_command *cmd;
++ struct mmc_data *data;
++ int error;
++
++ void __iomem *base; /* host base address */
++
++ struct msdc_dma dma; /* dma channel */
++ u64 dma_mask;
++
++ u32 timeout_ns; /* data timeout ns */
++ u32 timeout_clks; /* data timeout clks */
++
++ struct pinctrl *pinctrl;
++ struct pinctrl_state *pins_default;
++ struct pinctrl_state *pins_uhs;
++ struct delayed_work req_timeout;
++ int irq; /* host interrupt */
++
++ struct clk *src_clk; /* msdc source clock */
++ struct clk *h_clk; /* msdc h_clk */
++ u32 mclk; /* mmc subsystem clock frequency */
++ u32 src_clk_freq; /* source clock frequency */
++ u32 sclk; /* SD/MS bus clock frequency */
++ bool ddr;
++ bool vqmmc_enabled;
++};
++
++static void sdr_set_bits(void __iomem *reg, u32 bs)
++{
++ u32 val = readl(reg);
++
++ val |= bs;
++ writel(val, reg);
++}
++
++static void sdr_clr_bits(void __iomem *reg, u32 bs)
++{
++ u32 val = readl(reg);
++
++ val &= ~bs;
++ writel(val, reg);
++}
++
++static void sdr_set_field(void __iomem *reg, u32 field, u32 val)
++{
++ unsigned int tv = readl(reg);
++
++ tv &= ~field;
++ tv |= ((val) << (ffs((unsigned int)field) - 1));
++ writel(tv, reg);
++}
++
++static void sdr_get_field(void __iomem *reg, u32 field, u32 *val)
++{
++ unsigned int tv = readl(reg);
++
++ *val = ((tv & field) >> (ffs((unsigned int)field) - 1));
++}
++
++static void msdc_reset_hw(struct msdc_host *host)
++{
++ u32 val;
++
++ sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_RST);
++ while (readl(host->base + MSDC_CFG) & MSDC_CFG_RST)
++ cpu_relax();
++
++ sdr_set_bits(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR);
++ while (readl(host->base + MSDC_FIFOCS) & MSDC_FIFOCS_CLR)
++ cpu_relax();
++
++ val = readl(host->base + MSDC_INT);
++ writel(val, host->base + MSDC_INT);
++}
++
++static void msdc_cmd_next(struct msdc_host *host,
++ struct mmc_request *mrq, struct mmc_command *cmd);
++
++static u32 data_ints_mask = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO |
++ MSDC_INTEN_DATCRCERR | MSDC_INTEN_DMA_BDCSERR |
++ MSDC_INTEN_DMA_GPDCSERR | MSDC_INTEN_DMA_PROTECT;
++
++static u8 msdc_dma_calcs(u8 *buf, u32 len)
++{
++ u32 i, sum = 0;
++
++ for (i = 0; i < len; i++)
++ sum += buf[i];
++ return 0xff - (u8) sum;
++}
++
++static inline void msdc_dma_setup(struct msdc_host *host, struct msdc_dma *dma,
++ struct mmc_data *data)
++{
++ unsigned int j, dma_len;
++ dma_addr_t dma_address;
++ u32 dma_ctrl;
++ struct scatterlist *sg;
++ struct mt_gpdma_desc *gpd;
++ struct mt_bdma_desc *bd;
++
++ sg = data->sg;
++
++ gpd = dma->gpd;
++ bd = dma->bd;
++
++ /* modify gpd */
++ gpd->gpd_info |= GPDMA_DESC_HWO;
++ gpd->gpd_info |= GPDMA_DESC_BDP;
++ /* need to clear first. use these bits to calc checksum */
++ gpd->gpd_info &= ~GPDMA_DESC_CHECKSUM;
++ gpd->gpd_info |= msdc_dma_calcs((u8 *) gpd, 16) << 8;
++
++ /* modify bd */
++ for_each_sg(data->sg, sg, data->sg_count, j) {
++ dma_address = sg_dma_address(sg);
++ dma_len = sg_dma_len(sg);
++
++ /* init bd */
++ bd[j].bd_info &= ~BDMA_DESC_BLKPAD;
++ bd[j].bd_info &= ~BDMA_DESC_DWPAD;
++ bd[j].ptr = (u32)dma_address;
++ bd[j].bd_data_len &= ~BDMA_DESC_BUFLEN;
++ bd[j].bd_data_len |= (dma_len & BDMA_DESC_BUFLEN);
++
++ if (j == data->sg_count - 1) /* the last bd */
++ bd[j].bd_info |= BDMA_DESC_EOL;
++ else
++ bd[j].bd_info &= ~BDMA_DESC_EOL;
++
++ /* checksume need to clear first */
++ bd[j].bd_info &= ~BDMA_DESC_CHECKSUM;
++ bd[j].bd_info |= msdc_dma_calcs((u8 *)(&bd[j]), 16) << 8;
++ }
++
++ sdr_set_field(host->base + MSDC_DMA_CFG, MSDC_DMA_CFG_DECSEN, 1);
++ dma_ctrl = readl_relaxed(host->base + MSDC_DMA_CTRL);
++ dma_ctrl &= ~(MSDC_DMA_CTRL_BRUSTSZ | MSDC_DMA_CTRL_MODE);
++ dma_ctrl |= (MSDC_BURST_64B << 12 | 1 << 8);
++ writel_relaxed(dma_ctrl, host->base + MSDC_DMA_CTRL);
++ writel((u32)dma->gpd_addr, host->base + MSDC_DMA_SA);
++}
++
++static void msdc_prepare_data(struct msdc_host *host, struct mmc_request *mrq)
++{
++ struct mmc_data *data = mrq->data;
++
++ if (!(data->host_cookie & MSDC_PREPARE_FLAG)) {
++ bool read = (data->flags & MMC_DATA_READ) != 0;
++
++ data->host_cookie |= MSDC_PREPARE_FLAG;
++ data->sg_count = dma_map_sg(host->dev, data->sg, data->sg_len,
++ read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
++ }
++}
++
++static void msdc_unprepare_data(struct msdc_host *host, struct mmc_request *mrq)
++{
++ struct mmc_data *data = mrq->data;
++
++ if (data->host_cookie & MSDC_ASYNC_FLAG)
++ return;
++
++ if (data->host_cookie & MSDC_PREPARE_FLAG) {
++ bool read = (data->flags & MMC_DATA_READ) != 0;
++
++ dma_unmap_sg(host->dev, data->sg, data->sg_len,
++ read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
++ data->host_cookie &= ~MSDC_PREPARE_FLAG;
++ }
++}
++
++/* clock control primitives */
++static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks)
++{
++ u32 timeout, clk_ns;
++ u32 mode = 0;
++
++ host->timeout_ns = ns;
++ host->timeout_clks = clks;
++ if (host->sclk == 0) {
++ timeout = 0;
++ } else {
++ clk_ns = 1000000000UL / host->sclk;
++ timeout = (ns + clk_ns - 1) / clk_ns + clks;
++ /* in 1048576 sclk cycle unit */
++ timeout = (timeout + (0x1 << 20) - 1) >> 20;
++ sdr_get_field(host->base + MSDC_CFG, MSDC_CFG_CKMOD, &mode);
++ /*DDR mode will double the clk cycles for data timeout */
++ timeout = mode >= 2 ? timeout * 2 : timeout;
++ timeout = timeout > 1 ? timeout - 1 : 0;
++ timeout = timeout > 255 ? 255 : timeout;
++ }
++ sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, timeout);
++}
++
++static void msdc_gate_clock(struct msdc_host *host)
++{
++ clk_disable_unprepare(host->src_clk);
++ clk_disable_unprepare(host->h_clk);
++}
++
++static void msdc_ungate_clock(struct msdc_host *host)
++{
++ clk_prepare_enable(host->h_clk);
++ clk_prepare_enable(host->src_clk);
++ while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
++ cpu_relax();
++}
++
++static void msdc_set_mclk(struct msdc_host *host, int ddr, u32 hz)
++{
++ u32 mode;
++ u32 flags;
++ u32 div;
++ u32 sclk;
++
++ if (!hz) {
++ dev_dbg(host->dev, "set mclk to 0\n");
++ host->mclk = 0;
++ sdr_clr_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
++ return;
++ }
++
++ flags = readl(host->base + MSDC_INTEN);
++ sdr_clr_bits(host->base + MSDC_INTEN, flags);
++ if (ddr) { /* may need to modify later */
++ mode = 0x2; /* ddr mode and use divisor */
++ if (hz >= (host->src_clk_freq >> 2)) {
++ div = 0; /* mean div = 1/4 */
++ sclk = host->src_clk_freq >> 2; /* sclk = clk / 4 */
++ } else {
++ div = (host->src_clk_freq + ((hz << 2) - 1)) / (hz << 2);
++ sclk = (host->src_clk_freq >> 2) / div;
++ div = (div >> 1);
++ }
++ } else if (hz >= host->src_clk_freq) {
++ mode = 0x1; /* no divisor */
++ div = 0;
++ sclk = host->src_clk_freq;
++ } else {
++ mode = 0x0; /* use divisor */
++ if (hz >= (host->src_clk_freq >> 1)) {
++ div = 0; /* mean div = 1/2 */
++ sclk = host->src_clk_freq >> 1; /* sclk = clk / 2 */
++ } else {
++ div = (host->src_clk_freq + ((hz << 2) - 1)) / (hz << 2);
++ sclk = (host->src_clk_freq >> 2) / div;
++ }
++ }
++ sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_CKMOD | MSDC_CFG_CKDIV,
++ (mode << 8) | (div % 0xff));
++ sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
++ while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
++ cpu_relax();
++ host->sclk = sclk;
++ host->mclk = hz;
++ host->ddr = ddr;
++ /* need because clk changed. */
++ msdc_set_timeout(host, host->timeout_ns, host->timeout_clks);
++ sdr_set_bits(host->base + MSDC_INTEN, flags);
++
++ dev_dbg(host->dev, "sclk: %d, ddr: %d\n", host->sclk, ddr);
++}
++
++static inline u32 msdc_cmd_find_resp(struct msdc_host *host,
++ struct mmc_request *mrq, struct mmc_command *cmd)
++{
++ u32 resp;
++
++ switch (mmc_resp_type(cmd)) {
++ /* Actually, R1, R5, R6, R7 are the same */
++ case MMC_RSP_R1:
++ resp = 0x1;
++ break;
++ case MMC_RSP_R1B:
++ resp = 0x7;
++ break;
++ case MMC_RSP_R2:
++ resp = 0x2;
++ break;
++ case MMC_RSP_R3:
++ resp = 0x3;
++ break;
++ case MMC_RSP_NONE:
++ default:
++ resp = 0x0;
++ break;
++ }
++
++ return resp;
++}
++
++static inline u32 msdc_cmd_prepare_raw_cmd(struct msdc_host *host,
++ struct mmc_request *mrq, struct mmc_command *cmd)
++{
++ /* rawcmd :
++ * vol_swt << 30 | auto_cmd << 28 | blklen << 16 | go_irq << 15 |
++ * stop << 14 | rw << 13 | dtype << 11 | rsptyp << 7 | brk << 6 | opcode
++ */
++ u32 opcode = cmd->opcode;
++ u32 resp = msdc_cmd_find_resp(host, mrq, cmd);
++ u32 rawcmd = (opcode & 0x3f) | ((resp & 0x7) << 7);
++
++ host->cmd_rsp = resp;
++
++ if ((opcode == SD_IO_RW_DIRECT && cmd->flags == (unsigned int) -1) ||
++ opcode == MMC_STOP_TRANSMISSION)
++ rawcmd |= (0x1 << 14);
++ else if (opcode == SD_SWITCH_VOLTAGE)
++ rawcmd |= (0x1 << 30);
++ else if (opcode == SD_APP_SEND_SCR ||
++ opcode == SD_APP_SEND_NUM_WR_BLKS ||
++ (opcode == SD_SWITCH && mmc_cmd_type(cmd) == MMC_CMD_ADTC) ||
++ (opcode == SD_APP_SD_STATUS && mmc_cmd_type(cmd) == MMC_CMD_ADTC) ||
++ (opcode == MMC_SEND_EXT_CSD && mmc_cmd_type(cmd) == MMC_CMD_ADTC))
++ rawcmd |= (0x1 << 11);
++
++ if (cmd->data) {
++ struct mmc_data *data = cmd->data;
++
++ if (mmc_op_multi(opcode)) {
++ if (mmc_card_mmc(host->mmc->card) && mrq->sbc &&
++ !(mrq->sbc->arg & 0xFFFF0000))
++ rawcmd |= 0x2 << 28; /* AutoCMD23 */
++ }
++
++ rawcmd |= ((data->blksz & 0xFFF) << 16);
++ if (data->flags & MMC_DATA_WRITE)
++ rawcmd |= (0x1 << 13);
++ if (data->blocks > 1)
++ rawcmd |= (0x2 << 11);
++ else
++ rawcmd |= (0x1 << 11);
++ /* Always use dma mode */
++ sdr_clr_bits(host->base + MSDC_CFG, MSDC_CFG_PIO);
++
++ if (host->timeout_ns != data->timeout_ns ||
++ host->timeout_clks != data->timeout_clks)
++ msdc_set_timeout(host, data->timeout_ns,
++ data->timeout_clks);
++
++ writel(data->blocks, host->base + SDC_BLK_NUM);
++ }
++ return rawcmd;
++}
++
++static void msdc_start_data(struct msdc_host *host, struct mmc_request *mrq,
++ struct mmc_command *cmd, struct mmc_data *data)
++{
++ bool read;
++
++ WARN_ON(host->data);
++ host->data = data;
++ read = data->flags & MMC_DATA_READ;
++
++ mod_delayed_work(system_wq, &host->req_timeout, DAT_TIMEOUT);
++ msdc_dma_setup(host, &host->dma, data);
++ sdr_set_bits(host->base + MSDC_INTEN, data_ints_mask);
++ sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_START, 1);
++ dev_dbg(host->dev, "DMA start\n");
++ dev_dbg(host->dev, "%s: cmd=%d DMA data: %d blocks; read=%d\n",
++ __func__, cmd->opcode, data->blocks, read);
++}
++
++static int msdc_auto_cmd_done(struct msdc_host *host, int events,
++ struct mmc_command *cmd)
++{
++ u32 *rsp = cmd->resp;
++
++ rsp[0] = readl(host->base + SDC_ACMD_RESP);
++
++ if (events & MSDC_INT_ACMDRDY) {
++ cmd->error = 0;
++ } else {
++ msdc_reset_hw(host);
++ if (events & MSDC_INT_ACMDCRCERR) {
++ cmd->error = -EILSEQ;
++ host->error |= REQ_STOP_EIO;
++ } else if (events & MSDC_INT_ACMDTMO) {
++ cmd->error = -ETIMEDOUT;
++ host->error |= REQ_STOP_TMO;
++ }
++ dev_err(host->dev,
++ "%s: AUTO_CMD%d arg=%08X; rsp %08X; cmd_error=%d\n",
++ __func__, cmd->opcode, cmd->arg, rsp[0], cmd->error);
++ }
++ return cmd->error;
++}
++
++static void msdc_track_cmd_data(struct msdc_host *host,
++ struct mmc_command *cmd, struct mmc_data *data)
++{
++ if (host->error)
++ dev_dbg(host->dev, "%s: cmd=%d arg=%08X; host->error=0x%08X\n",
++ __func__, cmd->opcode, cmd->arg, host->error);
++}
++
++static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq)
++{
++ unsigned long flags;
++ bool ret;
++
++ ret = cancel_delayed_work(&host->req_timeout);
++ if (!ret) {
++ /* delay work already running */
++ return;
++ }
++ spin_lock_irqsave(&host->lock, flags);
++ host->mrq = NULL;
++ spin_unlock_irqrestore(&host->lock, flags);
++
++ msdc_track_cmd_data(host, mrq->cmd, mrq->data);
++ if (mrq->data)
++ msdc_unprepare_data(host, mrq);
++ mmc_request_done(host->mmc, mrq);
++}
++
++/* returns true if command is fully handled; returns false otherwise */
++static bool msdc_cmd_done(struct msdc_host *host, int events,
++ struct mmc_request *mrq, struct mmc_command *cmd)
++{
++ bool done = false;
++ bool sbc_error;
++ unsigned long flags;
++ u32 *rsp = cmd->resp;
++
++ if (mrq->sbc && cmd == mrq->cmd &&
++ (events & (MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR
++ | MSDC_INT_ACMDTMO)))
++ msdc_auto_cmd_done(host, events, mrq->sbc);
++
++ sbc_error = mrq->sbc && mrq->sbc->error;
++
++ if (!sbc_error && !(events & (MSDC_INT_CMDRDY
++ | MSDC_INT_RSPCRCERR
++ | MSDC_INT_CMDTMO)))
++ return done;
++
++ spin_lock_irqsave(&host->lock, flags);
++ done = !host->cmd;
++ host->cmd = NULL;
++ spin_unlock_irqrestore(&host->lock, flags);
++
++ if (done)
++ return true;
++
++ sdr_clr_bits(host->base + MSDC_INTEN, MSDC_INTEN_CMDRDY |
++ MSDC_INTEN_RSPCRCERR | MSDC_INTEN_CMDTMO |
++ MSDC_INTEN_ACMDRDY | MSDC_INTEN_ACMDCRCERR |
++ MSDC_INTEN_ACMDTMO);
++ writel(cmd->arg, host->base + SDC_ARG);
++
++ if (cmd->flags & MMC_RSP_PRESENT) {
++ if (cmd->flags & MMC_RSP_136) {
++ rsp[0] = readl(host->base + SDC_RESP3);
++ rsp[1] = readl(host->base + SDC_RESP2);
++ rsp[2] = readl(host->base + SDC_RESP1);
++ rsp[3] = readl(host->base + SDC_RESP0);
++ } else {
++ rsp[0] = readl(host->base + SDC_RESP0);
++ }
++ }
++
++ if (!sbc_error && !(events & MSDC_INT_CMDRDY)) {
++ msdc_reset_hw(host);
++ if (events & MSDC_INT_RSPCRCERR) {
++ cmd->error = -EILSEQ;
++ host->error |= REQ_CMD_EIO;
++ } else if (events & MSDC_INT_CMDTMO) {
++ cmd->error = -ETIMEDOUT;
++ host->error |= REQ_CMD_TMO;
++ }
++ }
++ if (cmd->error)
++ dev_dbg(host->dev,
++ "%s: cmd=%d arg=%08X; rsp %08X; cmd_error=%d\n",
++ __func__, cmd->opcode, cmd->arg, rsp[0],
++ cmd->error);
++
++ msdc_cmd_next(host, mrq, cmd);
++ return true;
++}
++
++/* It is the core layer's responsibility to ensure card status
++ * is correct before issue a request. but host design do below
++ * checks recommended.
++ */
++static inline bool msdc_cmd_is_ready(struct msdc_host *host,
++ struct mmc_request *mrq, struct mmc_command *cmd)
++{
++ /* The max busy time we can endure is 20ms */
++ unsigned long tmo = jiffies + msecs_to_jiffies(20);
++
++ while ((readl(host->base + SDC_STS) & SDC_STS_CMDBUSY) &&
++ time_before(jiffies, tmo))
++ cpu_relax();
++ if (readl(host->base + SDC_STS) & SDC_STS_CMDBUSY) {
++ dev_err(host->dev, "CMD bus busy detected\n");
++ host->error |= REQ_CMD_BUSY;
++ msdc_cmd_done(host, MSDC_INT_CMDTMO, mrq, cmd);
++ return false;
++ }
++
++ if (mmc_resp_type(cmd) == MMC_RSP_R1B || cmd->data) {
++ tmo = jiffies + msecs_to_jiffies(20);
++ /* R1B or with data, should check SDCBUSY */
++ while ((readl(host->base + SDC_STS) & SDC_STS_SDCBUSY) &&
++ time_before(jiffies, tmo))
++ cpu_relax();
++ if (readl(host->base + SDC_STS) & SDC_STS_SDCBUSY) {
++ dev_err(host->dev, "Controller busy detected\n");
++ host->error |= REQ_CMD_BUSY;
++ msdc_cmd_done(host, MSDC_INT_CMDTMO, mrq, cmd);
++ return false;
++ }
++ }
++ return true;
++}
++
++static void msdc_start_command(struct msdc_host *host,
++ struct mmc_request *mrq, struct mmc_command *cmd)
++{
++ u32 rawcmd;
++
++ WARN_ON(host->cmd);
++ host->cmd = cmd;
++
++ if (!msdc_cmd_is_ready(host, mrq, cmd))
++ return;
++
++ if ((readl(host->base + MSDC_FIFOCS) & MSDC_FIFOCS_TXCNT) >> 16 ||
++ readl(host->base + MSDC_FIFOCS) & MSDC_FIFOCS_RXCNT) {
++ dev_err(host->dev, "TX/RX FIFO non-empty before start of IO. Reset\n");
++ msdc_reset_hw(host);
++ }
++
++ cmd->error = 0;
++ rawcmd = msdc_cmd_prepare_raw_cmd(host, mrq, cmd);
++ mod_delayed_work(system_wq, &host->req_timeout, DAT_TIMEOUT);
++
++ sdr_set_bits(host->base + MSDC_INTEN, MSDC_INTEN_CMDRDY |
++ MSDC_INTEN_RSPCRCERR | MSDC_INTEN_CMDTMO |
++ MSDC_INTEN_ACMDRDY | MSDC_INTEN_ACMDCRCERR |
++ MSDC_INTEN_ACMDTMO);
++ writel(cmd->arg, host->base + SDC_ARG);
++ writel(rawcmd, host->base + SDC_CMD);
++}
++
++static void msdc_cmd_next(struct msdc_host *host,
++ struct mmc_request *mrq, struct mmc_command *cmd)
++{
++ if (cmd->error || (mrq->sbc && mrq->sbc->error))
++ msdc_request_done(host, mrq);
++ else if (cmd == mrq->sbc)
++ msdc_start_command(host, mrq, mrq->cmd);
++ else if (!cmd->data)
++ msdc_request_done(host, mrq);
++ else
++ msdc_start_data(host, mrq, cmd, cmd->data);
++}
++
++static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq)
++{
++ struct msdc_host *host = mmc_priv(mmc);
++
++ host->error = 0;
++ WARN_ON(host->mrq);
++ host->mrq = mrq;
++
++ if (mrq->data)
++ msdc_prepare_data(host, mrq);
++
++ /* if SBC is required, we have HW option and SW option.
++ * if HW option is enabled, and SBC does not have "special" flags,
++ * use HW option, otherwise use SW option
++ */
++ if (mrq->sbc && (!mmc_card_mmc(mmc->card) ||
++ (mrq->sbc->arg & 0xFFFF0000)))
++ msdc_start_command(host, mrq, mrq->sbc);
++ else
++ msdc_start_command(host, mrq, mrq->cmd);
++}
++
++static void msdc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
++ bool is_first_req)
++{
++ struct msdc_host *host = mmc_priv(mmc);
++ struct mmc_data *data = mrq->data;
++
++ if (!data)
++ return;
++
++ msdc_prepare_data(host, mrq);
++ data->host_cookie |= MSDC_ASYNC_FLAG;
++}
++
++static void msdc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
++ int err)
++{
++ struct msdc_host *host = mmc_priv(mmc);
++ struct mmc_data *data;
++
++ data = mrq->data;
++ if (!data)
++ return;
++ if (data->host_cookie) {
++ data->host_cookie &= ~MSDC_ASYNC_FLAG;
++ msdc_unprepare_data(host, mrq);
++ }
++}
++
++static void msdc_data_xfer_next(struct msdc_host *host,
++ struct mmc_request *mrq, struct mmc_data *data)
++{
++ if (mmc_op_multi(mrq->cmd->opcode) && mrq->stop && !mrq->stop->error &&
++ (!data->bytes_xfered || !mrq->sbc))
++ msdc_start_command(host, mrq, mrq->stop);
++ else
++ msdc_request_done(host, mrq);
++}
++
++static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
++ struct mmc_request *mrq, struct mmc_data *data)
++{
++ struct mmc_command *stop = data->stop;
++ unsigned long flags;
++ bool done;
++ unsigned int check_data = events &
++ (MSDC_INT_XFER_COMPL | MSDC_INT_DATCRCERR | MSDC_INT_DATTMO
++ | MSDC_INT_DMA_BDCSERR | MSDC_INT_DMA_GPDCSERR
++ | MSDC_INT_DMA_PROTECT);
++
++ spin_lock_irqsave(&host->lock, flags);
++ done = !host->data;
++ if (check_data)
++ host->data = NULL;
++ spin_unlock_irqrestore(&host->lock, flags);
++
++ if (done)
++ return true;
++
++ if (check_data || (stop && stop->error)) {
++ dev_dbg(host->dev, "DMA status: 0x%8X\n",
++ readl(host->base + MSDC_DMA_CFG));
++ sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP,
++ 1);
++ while (readl(host->base + MSDC_DMA_CFG) & MSDC_DMA_CFG_STS)
++ cpu_relax();
++ sdr_clr_bits(host->base + MSDC_INTEN, data_ints_mask);
++ dev_dbg(host->dev, "DMA stop\n");
++
++ if ((events & MSDC_INT_XFER_COMPL) && (!stop || !stop->error)) {
++ data->bytes_xfered = data->blocks * data->blksz;
++ } else {
++ dev_err(host->dev, "interrupt events: %x\n", events);
++ msdc_reset_hw(host);
++ host->error |= REQ_DAT_ERR;
++ data->bytes_xfered = 0;
++
++ if (events & MSDC_INT_DATTMO)
++ data->error = -ETIMEDOUT;
++
++ dev_err(host->dev, "%s: cmd=%d; blocks=%d",
++ __func__, mrq->cmd->opcode, data->blocks);
++ dev_err(host->dev, "data_error=%d xfer_size=%d\n",
++ (int)data->error, data->bytes_xfered);
++ }
++
++ msdc_data_xfer_next(host, mrq, data);
++ done = true;
++ }
++ return done;
++}
++
++static void msdc_set_buswidth(struct msdc_host *host, u32 width)
++{
++ u32 val = readl(host->base + SDC_CFG);
++
++ val &= ~SDC_CFG_BUSWIDTH;
++
++ switch (width) {
++ default:
++ case MMC_BUS_WIDTH_1:
++ val |= (MSDC_BUS_1BITS << 16);
++ break;
++ case MMC_BUS_WIDTH_4:
++ val |= (MSDC_BUS_4BITS << 16);
++ break;
++ case MMC_BUS_WIDTH_8:
++ val |= (MSDC_BUS_8BITS << 16);
++ break;
++ }
++
++ writel(val, host->base + SDC_CFG);
++ dev_dbg(host->dev, "Bus Width = %d", width);
++}
++
++static int msdc_ops_switch_volt(struct mmc_host *mmc, struct mmc_ios *ios)
++{
++ struct msdc_host *host = mmc_priv(mmc);
++ int min_uv, max_uv;
++ int ret = 0;
++
++ if (!IS_ERR(mmc->supply.vqmmc)) {
++ if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
++ min_uv = 3300000;
++ max_uv = 3300000;
++ } else if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
++ min_uv = 1800000;
++ max_uv = 1800000;
++ } else {
++ dev_err(host->dev, "Unsupported signal voltage!\n");
++ return -EINVAL;
++ }
++
++ ret = regulator_set_voltage(mmc->supply.vqmmc, min_uv, max_uv);
++ if (ret) {
++ dev_err(host->dev,
++ "Regulator set error %d: %d - %d\n",
++ ret, min_uv, max_uv);
++ } else {
++ /* Apply different pinctrl settings for different signal voltage */
++ if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
++ pinctrl_select_state(host->pinctrl, host->pins_uhs);
++ else
++ pinctrl_select_state(host->pinctrl, host->pins_default);
++ }
++ }
++ return ret;
++}
++
++static int msdc_card_busy(struct mmc_host *mmc)
++{
++ struct msdc_host *host = mmc_priv(mmc);
++ u32 status = readl(host->base + MSDC_PS);
++
++ /* check if any pin between dat[0:3] is low */
++ if (((status >> 16) & 0xf) != 0xf)
++ return 1;
++
++ return 0;
++}
++
++static void msdc_request_timeout(struct work_struct *work)
++{
++ struct msdc_host *host = container_of(work, struct msdc_host,
++ req_timeout.work);
++
++ /* simulate HW timeout status */
++ dev_err(host->dev, "%s: aborting cmd/data/mrq\n", __func__);
++ if (host->mrq) {
++ dev_err(host->dev, "%s: aborting mrq=%p cmd=%d\n", __func__,
++ host->mrq, host->mrq->cmd->opcode);
++ if (host->cmd) {
++ dev_err(host->dev, "%s: aborting cmd=%d\n",
++ __func__, host->cmd->opcode);
++ msdc_cmd_done(host, MSDC_INT_CMDTMO, host->mrq,
++ host->cmd);
++ } else if (host->data) {
++ dev_err(host->dev, "%s: abort data: cmd%d; %d blocks\n",
++ __func__, host->mrq->cmd->opcode,
++ host->data->blocks);
++ msdc_data_xfer_done(host, MSDC_INT_DATTMO, host->mrq,
++ host->data);
++ }
++ }
++}
++
++static irqreturn_t msdc_irq(int irq, void *dev_id)
++{
++ struct msdc_host *host = (struct msdc_host *) dev_id;
++
++ while (true) {
++ unsigned long flags;
++ struct mmc_request *mrq;
++ struct mmc_command *cmd;
++ struct mmc_data *data;
++ u32 events, event_mask;
++
++ spin_lock_irqsave(&host->lock, flags);
++ events = readl(host->base + MSDC_INT);
++ event_mask = readl(host->base + MSDC_INTEN);
++ /* clear interrupts */
++ writel(events & event_mask, host->base + MSDC_INT);
++
++ mrq = host->mrq;
++ cmd = host->cmd;
++ data = host->data;
++ spin_unlock_irqrestore(&host->lock, flags);
++
++ if (!(events & event_mask))
++ break;
++
++ if (!mrq) {
++ dev_err(host->dev,
++ "%s: MRQ=NULL; events=%08X; event_mask=%08X\n",
++ __func__, events, event_mask);
++ WARN_ON(1);
++ break;
++ }
++
++ dev_dbg(host->dev, "%s: events=%08X\n", __func__, events);
++
++ if (cmd)
++ msdc_cmd_done(host, events, mrq, cmd);
++ else if (data)
++ msdc_data_xfer_done(host, events, mrq, data);
++ }
++
++ return IRQ_HANDLED;
++}
++
++static void msdc_init_hw(struct msdc_host *host)
++{
++ u32 val;
++
++ /* Configure to MMC/SD mode, clock free running */
++ sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_MODE | MSDC_CFG_CKPDN);
++
++ /* Reset */
++ msdc_reset_hw(host);
++
++ /* Disable card detection */
++ sdr_clr_bits(host->base + MSDC_PS, MSDC_PS_CDEN);
++
++ /* Disable and clear all interrupts */
++ writel(0, host->base + MSDC_INTEN);
++ val = readl(host->base + MSDC_INT);
++ writel(val, host->base + MSDC_INT);
++
++ writel(0, host->base + MSDC_PAD_TUNE);
++ writel(0, host->base + MSDC_IOCON);
++ sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL, 1);
++ writel(0x403c004f, host->base + MSDC_PATCH_BIT);
++ sdr_set_field(host->base + MSDC_PATCH_BIT, MSDC_CKGEN_MSDC_DLY_SEL, 1);
++ writel(0xffff0089, host->base + MSDC_PATCH_BIT1);
++ /* Configure to enable SDIO mode.
++ * it's must otherwise sdio cmd5 failed
++ */
++ sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIO);
++
++ /* disable detect SDIO device interrupt function */
++ sdr_clr_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
++
++ /* Configure to default data timeout */
++ sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, 3);
++
++ dev_dbg(host->dev, "init hardware done!");
++}
++
++static void msdc_deinit_hw(struct msdc_host *host)
++{
++ u32 val;
++ /* Disable and clear all interrupts */
++ writel(0, host->base + MSDC_INTEN);
++
++ val = readl(host->base + MSDC_INT);
++ writel(val, host->base + MSDC_INT);
++}
++
++/* init gpd and bd list in msdc_drv_probe */
++static void msdc_init_gpd_bd(struct msdc_host *host, struct msdc_dma *dma)
++{
++ struct mt_gpdma_desc *gpd = dma->gpd;
++ struct mt_bdma_desc *bd = dma->bd;
++ int i;
++
++ memset(gpd, 0, sizeof(struct mt_gpdma_desc));
++
++ gpd->gpd_info = GPDMA_DESC_BDP; /* hwo, cs, bd pointer */
++ gpd->ptr = (u32)dma->bd_addr; /* physical address */
++
++ memset(bd, 0, sizeof(struct mt_bdma_desc) * MAX_BD_NUM);
++ for (i = 0; i < (MAX_BD_NUM - 1); i++)
++ bd[i].next = (u32)dma->bd_addr + sizeof(*bd) * (i + 1);
++}
++
++static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
++{
++ struct msdc_host *host = mmc_priv(mmc);
++ int ret;
++ u32 ddr = 0;
++
++ if (ios->timing == MMC_TIMING_UHS_DDR50 ||
++ ios->timing == MMC_TIMING_MMC_DDR52)
++ ddr = 1;
++
++ msdc_set_buswidth(host, ios->bus_width);
++
++ /* Suspend/Resume will do power off/on */
++ switch (ios->power_mode) {
++ case MMC_POWER_UP:
++ if (!IS_ERR(mmc->supply.vmmc)) {
++ ret = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
++ ios->vdd);
++ if (ret) {
++ dev_err(host->dev, "Failed to set vmmc power!\n");
++ return;
++ }
++ }
++ break;
++ case MMC_POWER_ON:
++ if (!IS_ERR(mmc->supply.vqmmc) && !host->vqmmc_enabled) {
++ ret = regulator_enable(mmc->supply.vqmmc);
++ if (ret)
++ dev_err(host->dev, "Failed to set vqmmc power!\n");
++ else
++ host->vqmmc_enabled = true;
++ }
++ break;
++ case MMC_POWER_OFF:
++ if (!IS_ERR(mmc->supply.vmmc))
++ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
++
++ if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) {
++ regulator_disable(mmc->supply.vqmmc);
++ host->vqmmc_enabled = false;
++ }
++ break;
++ default:
++ break;
++ }
++
++ if (host->mclk != ios->clock || host->ddr != ddr)
++ msdc_set_mclk(host, ddr, ios->clock);
++}
++
++static struct mmc_host_ops mt_msdc_ops = {
++ .post_req = msdc_post_req,
++ .pre_req = msdc_pre_req,
++ .request = msdc_ops_request,
++ .set_ios = msdc_ops_set_ios,
++ .start_signal_voltage_switch = msdc_ops_switch_volt,
++ .card_busy = msdc_card_busy,
++};
++
++static int msdc_drv_probe(struct platform_device *pdev)
++{
++ struct mmc_host *mmc;
++ struct msdc_host *host;
++ struct resource *res;
++ int ret;
++
++ if (!pdev->dev.of_node) {
++ dev_err(&pdev->dev, "No DT found\n");
++ return -EINVAL;
++ }
++ /* Allocate MMC host for this device */
++ mmc = mmc_alloc_host(sizeof(struct msdc_host), &pdev->dev);
++ if (!mmc)
++ return -ENOMEM;
++
++ host = mmc_priv(mmc);
++ ret = mmc_of_parse(mmc);
++ if (ret)
++ goto host_free;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ host->base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(host->base)) {
++ ret = PTR_ERR(host->base);
++ goto host_free;
++ }
++
++ ret = mmc_regulator_get_supply(mmc);
++ if (ret == -EPROBE_DEFER)
++ goto host_free;
++
++ host->src_clk = devm_clk_get(&pdev->dev, "source");
++ if (IS_ERR(host->src_clk)) {
++ ret = PTR_ERR(host->src_clk);
++ goto host_free;
++ }
++
++ host->h_clk = devm_clk_get(&pdev->dev, "hclk");
++ if (IS_ERR(host->h_clk)) {
++ ret = PTR_ERR(host->h_clk);
++ goto host_free;
++ }
++
++ host->irq = platform_get_irq(pdev, 0);
++ if (host->irq < 0) {
++ ret = -EINVAL;
++ goto host_free;
++ }
++
++ host->pinctrl = devm_pinctrl_get(&pdev->dev);
++ if (IS_ERR(host->pinctrl)) {
++ ret = PTR_ERR(host->pinctrl);
++ dev_err(&pdev->dev, "Cannot find pinctrl!\n");
++ goto host_free;
++ }
++
++ host->pins_default = pinctrl_lookup_state(host->pinctrl, "default");
++ if (IS_ERR(host->pins_default)) {
++ ret = PTR_ERR(host->pins_default);
++ dev_err(&pdev->dev, "Cannot find pinctrl default!\n");
++ goto host_free;
++ }
++
++ host->pins_uhs = pinctrl_lookup_state(host->pinctrl, "state_uhs");
++ if (IS_ERR(host->pins_uhs)) {
++ ret = PTR_ERR(host->pins_uhs);
++ dev_err(&pdev->dev, "Cannot find pinctrl uhs!\n");
++ goto host_free;
++ }
++
++ host->dev = &pdev->dev;
++ host->mmc = mmc;
++ host->src_clk_freq = clk_get_rate(host->src_clk);
++ /* Set host parameters to mmc */
++ mmc->ops = &mt_msdc_ops;
++ mmc->f_min = host->src_clk_freq / (4 * 255);
++
++ mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23;
++ /* MMC core transfer sizes tunable parameters */
++ mmc->max_segs = MAX_BD_NUM;
++ mmc->max_seg_size = BDMA_DESC_BUFLEN;
++ mmc->max_blk_size = 2048;
++ mmc->max_req_size = 512 * 1024;
++ mmc->max_blk_count = mmc->max_req_size / 512;
++ host->dma_mask = DMA_BIT_MASK(32);
++ mmc_dev(mmc)->dma_mask = &host->dma_mask;
++
++ host->timeout_clks = 3 * 1048576;
++ host->dma.gpd = dma_alloc_coherent(&pdev->dev,
++ sizeof(struct mt_gpdma_desc),
++ &host->dma.gpd_addr, GFP_KERNEL);
++ host->dma.bd = dma_alloc_coherent(&pdev->dev,
++ MAX_BD_NUM * sizeof(struct mt_bdma_desc),
++ &host->dma.bd_addr, GFP_KERNEL);
++ if (!host->dma.gpd || !host->dma.bd) {
++ ret = -ENOMEM;
++ goto release_mem;
++ }
++ msdc_init_gpd_bd(host, &host->dma);
++ INIT_DELAYED_WORK(&host->req_timeout, msdc_request_timeout);
++ spin_lock_init(&host->lock);
++
++ platform_set_drvdata(pdev, mmc);
++ msdc_ungate_clock(host);
++ msdc_init_hw(host);
++
++ ret = devm_request_irq(&pdev->dev, host->irq, msdc_irq,
++ IRQF_TRIGGER_LOW | IRQF_ONESHOT, pdev->name, host);
++ if (ret)
++ goto release;
++
++ ret = mmc_add_host(mmc);
++ if (ret)
++ goto release;
++
++ return 0;
++
++release:
++ platform_set_drvdata(pdev, NULL);
++ msdc_deinit_hw(host);
++ msdc_gate_clock(host);
++release_mem:
++ if (host->dma.gpd)
++ dma_free_coherent(&pdev->dev,
++ sizeof(struct mt_gpdma_desc),
++ host->dma.gpd, host->dma.gpd_addr);
++ if (host->dma.bd)
++ dma_free_coherent(&pdev->dev,
++ MAX_BD_NUM * sizeof(struct mt_bdma_desc),
++ host->dma.bd, host->dma.bd_addr);
++host_free:
++ mmc_free_host(mmc);
++
++ return ret;
++}
++
++static int msdc_drv_remove(struct platform_device *pdev)
++{
++ struct mmc_host *mmc;
++ struct msdc_host *host;
++
++ mmc = platform_get_drvdata(pdev);
++ host = mmc_priv(mmc);
++
++ platform_set_drvdata(pdev, NULL);
++ mmc_remove_host(host->mmc);
++ msdc_deinit_hw(host);
++ msdc_gate_clock(host);
++
++ dma_free_coherent(&pdev->dev,
++ sizeof(struct mt_gpdma_desc),
++ host->dma.gpd, host->dma.gpd_addr);
++ dma_free_coherent(&pdev->dev, MAX_BD_NUM * sizeof(struct mt_bdma_desc),
++ host->dma.bd, host->dma.bd_addr);
++
++ mmc_free_host(host->mmc);
++
++ return 0;
++}
++
++static const struct of_device_id msdc_of_ids[] = {
++ { .compatible = "mediatek,mt8135-mmc", },
++ {}
++};
++
++static struct platform_driver mt_msdc_driver = {
++ .probe = msdc_drv_probe,
++ .remove = msdc_drv_remove,
++ .driver = {
++ .name = "mtk-msdc",
++ .of_match_table = msdc_of_ids,
++ },
++};
++
++module_platform_driver(mt_msdc_driver);
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("MediaTek SD/MMC Card Driver");
diff --git a/target/linux/mediatek/patches/0036-mmc-mediatek-Add-PM-support-for-MMC-driver.patch b/target/linux/mediatek/patches/0036-mmc-mediatek-Add-PM-support-for-MMC-driver.patch
new file mode 100644
index 0000000000..e9ba31d76f
--- /dev/null
+++ b/target/linux/mediatek/patches/0036-mmc-mediatek-Add-PM-support-for-MMC-driver.patch
@@ -0,0 +1,209 @@
+From 4ca0e8a959569852b520b607d39ce6ceeeb0f518 Mon Sep 17 00:00:00 2001
+From: Chaotian Jing <chaotian.jing@mediatek.com>
+Date: Mon, 15 Jun 2015 19:20:49 +0800
+Subject: [PATCH 36/76] mmc: mediatek: Add PM support for MMC driver
+
+Add PM support for Mediatek MMC driver
+Save/restore registers when PM
+
+Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
+---
+ drivers/mmc/host/mtk-sd.c | 89 +++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 86 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
+index 952be2e..7c20f28 100644
+--- a/drivers/mmc/host/mtk-sd.c
++++ b/drivers/mmc/host/mtk-sd.c
+@@ -22,6 +22,8 @@
+ #include <linux/of_gpio.h>
+ #include <linux/pinctrl/consumer.h>
+ #include <linux/platform_device.h>
++#include <linux/pm.h>
++#include <linux/pm_runtime.h>
+ #include <linux/regulator/consumer.h>
+ #include <linux/spinlock.h>
+
+@@ -212,6 +214,7 @@
+ #define MSDC_ASYNC_FLAG (0x1 << 1)
+ #define MSDC_MMAP_FLAG (0x1 << 2)
+
++#define MTK_MMC_AUTOSUSPEND_DELAY 50
+ #define CMD_TIMEOUT (HZ/10 * 5) /* 100ms x5 */
+ #define DAT_TIMEOUT (HZ * 5) /* 1000ms x5 */
+
+@@ -254,6 +257,15 @@ struct msdc_dma {
+ dma_addr_t bd_addr; /* the physical address of bd array */
+ };
+
++struct msdc_save_para {
++ u32 msdc_cfg;
++ u32 iocon;
++ u32 sdc_cfg;
++ u32 pad_tune;
++ u32 patch_bit0;
++ u32 patch_bit1;
++};
++
+ struct msdc_host {
+ struct device *dev;
+ struct mmc_host *mmc; /* mmc structure */
+@@ -286,6 +298,7 @@ struct msdc_host {
+ u32 sclk; /* SD/MS bus clock frequency */
+ bool ddr;
+ bool vqmmc_enabled;
++ struct msdc_save_para save_para; /* used when gate HCLK */
+ };
+
+ static void sdr_set_bits(void __iomem *reg, u32 bs)
+@@ -677,6 +690,9 @@ static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq)
+ if (mrq->data)
+ msdc_unprepare_data(host, mrq);
+ mmc_request_done(host->mmc, mrq);
++
++ pm_runtime_mark_last_busy(host->dev);
++ pm_runtime_put_autosuspend(host->dev);
+ }
+
+ /* returns true if command is fully handled; returns false otherwise */
+@@ -831,6 +847,8 @@ static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq)
+ WARN_ON(host->mrq);
+ host->mrq = mrq;
+
++ pm_runtime_get_sync(host->dev);
++
+ if (mrq->data)
+ msdc_prepare_data(host, mrq);
+
+@@ -1145,6 +1163,8 @@ static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+ int ret;
+ u32 ddr = 0;
+
++ pm_runtime_get_sync(host->dev);
++
+ if (ios->timing == MMC_TIMING_UHS_DDR50 ||
+ ios->timing == MMC_TIMING_MMC_DDR52)
+ ddr = 1;
+@@ -1159,7 +1179,7 @@ static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+ ios->vdd);
+ if (ret) {
+ dev_err(host->dev, "Failed to set vmmc power!\n");
+- return;
++ goto end;
+ }
+ }
+ break;
+@@ -1187,6 +1207,10 @@ static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+
+ if (host->mclk != ios->clock || host->ddr != ddr)
+ msdc_set_mclk(host, ddr, ios->clock);
++
++end:
++ pm_runtime_mark_last_busy(host->dev);
++ pm_runtime_put_autosuspend(host->dev);
+ }
+
+ static struct mmc_host_ops mt_msdc_ops = {
+@@ -1310,12 +1334,18 @@ static int msdc_drv_probe(struct platform_device *pdev)
+ if (ret)
+ goto release;
+
++ pm_runtime_set_active(host->dev);
++ pm_runtime_set_autosuspend_delay(host->dev, MTK_MMC_AUTOSUSPEND_DELAY);
++ pm_runtime_use_autosuspend(host->dev);
++ pm_runtime_enable(host->dev);
+ ret = mmc_add_host(mmc);
++
+ if (ret)
+- goto release;
++ goto end;
+
+ return 0;
+-
++end:
++ pm_runtime_disable(host->dev);
+ release:
+ platform_set_drvdata(pdev, NULL);
+ msdc_deinit_hw(host);
+@@ -1343,11 +1373,15 @@ static int msdc_drv_remove(struct platform_device *pdev)
+ mmc = platform_get_drvdata(pdev);
+ host = mmc_priv(mmc);
+
++ pm_runtime_get_sync(host->dev);
++
+ platform_set_drvdata(pdev, NULL);
+ mmc_remove_host(host->mmc);
+ msdc_deinit_hw(host);
+ msdc_gate_clock(host);
+
++ pm_runtime_disable(host->dev);
++ pm_runtime_put_noidle(host->dev);
+ dma_free_coherent(&pdev->dev,
+ sizeof(struct mt_gpdma_desc),
+ host->dma.gpd, host->dma.gpd_addr);
+@@ -1359,6 +1393,54 @@ static int msdc_drv_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++#ifdef CONFIG_PM
++static void msdc_save_reg(struct msdc_host *host)
++{
++ host->save_para.msdc_cfg = readl(host->base + MSDC_CFG);
++ host->save_para.iocon = readl(host->base + MSDC_IOCON);
++ host->save_para.sdc_cfg = readl(host->base + SDC_CFG);
++ host->save_para.pad_tune = readl(host->base + MSDC_PAD_TUNE);
++ host->save_para.patch_bit0 = readl(host->base + MSDC_PATCH_BIT);
++ host->save_para.patch_bit1 = readl(host->base + MSDC_PATCH_BIT1);
++}
++
++static void msdc_restore_reg(struct msdc_host *host)
++{
++ writel(host->save_para.msdc_cfg, host->base + MSDC_CFG);
++ writel(host->save_para.iocon, host->base + MSDC_IOCON);
++ writel(host->save_para.sdc_cfg, host->base + SDC_CFG);
++ writel(host->save_para.pad_tune, host->base + MSDC_PAD_TUNE);
++ writel(host->save_para.patch_bit0, host->base + MSDC_PATCH_BIT);
++ writel(host->save_para.patch_bit1, host->base + MSDC_PATCH_BIT1);
++}
++
++static int msdc_runtime_suspend(struct device *dev)
++{
++ struct mmc_host *mmc = dev_get_drvdata(dev);
++ struct msdc_host *host = mmc_priv(mmc);
++
++ msdc_save_reg(host);
++ msdc_gate_clock(host);
++ return 0;
++}
++
++static int msdc_runtime_resume(struct device *dev)
++{
++ struct mmc_host *mmc = dev_get_drvdata(dev);
++ struct msdc_host *host = mmc_priv(mmc);
++
++ msdc_ungate_clock(host);
++ msdc_restore_reg(host);
++ return 0;
++}
++#endif
++
++static const struct dev_pm_ops msdc_dev_pm_ops = {
++ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
++ pm_runtime_force_resume)
++ SET_RUNTIME_PM_OPS(msdc_runtime_suspend, msdc_runtime_resume, NULL)
++};
++
+ static const struct of_device_id msdc_of_ids[] = {
+ { .compatible = "mediatek,mt8135-mmc", },
+ {}
+@@ -1370,6 +1452,7 @@ static struct platform_driver mt_msdc_driver = {
+ .driver = {
+ .name = "mtk-msdc",
+ .of_match_table = msdc_of_ids,
++ .pm = &msdc_dev_pm_ops,
+ },
+ };
+
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0037-arm64-mediatek-Add-Mediatek-MMC-support-in-defconfig.patch b/target/linux/mediatek/patches/0037-arm64-mediatek-Add-Mediatek-MMC-support-in-defconfig.patch
new file mode 100644
index 0000000000..7d9143f2f6
--- /dev/null
+++ b/target/linux/mediatek/patches/0037-arm64-mediatek-Add-Mediatek-MMC-support-in-defconfig.patch
@@ -0,0 +1,28 @@
+From 0435517df474d830711b7e1dc56e2d47ae5083b5 Mon Sep 17 00:00:00 2001
+From: Eddie Huang <eddie.huang@mediatek.com>
+Date: Mon, 15 Jun 2015 19:20:52 +0800
+Subject: [PATCH 37/76] arm64: mediatek: Add Mediatek MMC support in defconfig
+
+Add CONFIG_MMC_MTK=y in defconfig
+
+Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
+Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
+---
+ arch/arm64/configs/defconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
+index 2ed7449..e03288a 100644
+--- a/arch/arm64/configs/defconfig
++++ b/arch/arm64/configs/defconfig
+@@ -138,6 +138,7 @@ CONFIG_MMC_ARMMMCI=y
+ CONFIG_MMC_SDHCI=y
+ CONFIG_MMC_SDHCI_PLTFM=y
+ CONFIG_MMC_SPI=y
++CONFIG_MMC_MTK=y
+ CONFIG_RTC_CLASS=y
+ CONFIG_RTC_DRV_EFI=y
+ CONFIG_RTC_DRV_XGENE=y
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0038-ARM-multi_v7_defconfig-Enable-Mediatek-MMC-support-m.patch b/target/linux/mediatek/patches/0038-ARM-multi_v7_defconfig-Enable-Mediatek-MMC-support-m.patch
new file mode 100644
index 0000000000..35dc99faf9
--- /dev/null
+++ b/target/linux/mediatek/patches/0038-ARM-multi_v7_defconfig-Enable-Mediatek-MMC-support-m.patch
@@ -0,0 +1,29 @@
+From 3069c2bfe0da7c6c13a61b0e1d457fd0e021e27b Mon Sep 17 00:00:00 2001
+From: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Date: Mon, 15 Jun 2015 19:20:53 +0800
+Subject: [PATCH 38/76] ARM: multi_v7_defconfig: Enable Mediatek MMC support
+ multi-v7
+
+Add CONFIG_MMC_MTK=y in defconfig
+
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
+---
+ arch/arm/configs/multi_v7_defconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
+index fbbb191..bfa09ab 100644
+--- a/arch/arm/configs/multi_v7_defconfig
++++ b/arch/arm/configs/multi_v7_defconfig
+@@ -477,6 +477,7 @@ CONFIG_MMC_DW_EXYNOS=y
+ CONFIG_MMC_DW_ROCKCHIP=y
+ CONFIG_MMC_SH_MMCIF=y
+ CONFIG_MMC_SUNXI=y
++CONFIG_MMC_MTK=y
+ CONFIG_NEW_LEDS=y
+ CONFIG_LEDS_CLASS=y
+ CONFIG_LEDS_GPIO=y
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0039-clocksource-mediatek-Don-t-run-event_handler-if-it-i.patch b/target/linux/mediatek/patches/0039-clocksource-mediatek-Don-t-run-event_handler-if-it-i.patch
new file mode 100644
index 0000000000..aabe8497f3
--- /dev/null
+++ b/target/linux/mediatek/patches/0039-clocksource-mediatek-Don-t-run-event_handler-if-it-i.patch
@@ -0,0 +1,32 @@
+From 9d4cba66a74cbdf25f43a7a8cc360370214ba5fc Mon Sep 17 00:00:00 2001
+From: "Joe.C" <yingjoe.chen@mediatek.com>
+Date: Fri, 1 May 2015 15:43:24 +0800
+Subject: [PATCH 39/76] clocksource: mediatek: Don't run event_handler if it
+ is NULL
+
+Spurious timer interrupt is noticed in mtk timer and cause kernel
+crash. In mtk_timer_interrupt(), only run event_handler if it is
+not NULL.
+
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+---
+ drivers/clocksource/mtk_timer.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c
+index 68ab423..85e0ab5 100644
+--- a/drivers/clocksource/mtk_timer.c
++++ b/drivers/clocksource/mtk_timer.c
+@@ -143,7 +143,8 @@ static irqreturn_t mtk_timer_interrupt(int irq, void *dev_id)
+
+ /* Acknowledge timer0 irq */
+ writel(GPT_IRQ_ACK(GPT_CLK_EVT), evt->gpt_base + GPT_IRQ_ACK_REG);
+- evt->dev.event_handler(&evt->dev);
++ if (evt->dev.event_handler)
++ evt->dev.event_handler(&evt->dev);
+
+ return IRQ_HANDLED;
+ }
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0040-clocksource-mediatek-Use-GPT-as-sched-clock-source.patch b/target/linux/mediatek/patches/0040-clocksource-mediatek-Use-GPT-as-sched-clock-source.patch
new file mode 100644
index 0000000000..c6b66afc05
--- /dev/null
+++ b/target/linux/mediatek/patches/0040-clocksource-mediatek-Use-GPT-as-sched-clock-source.patch
@@ -0,0 +1,51 @@
+From 3b3c2406dd9797bc806e0ce756142a33d209c4e8 Mon Sep 17 00:00:00 2001
+From: "Joe.C" <yingjoe.chen@mediatek.com>
+Date: Fri, 1 May 2015 15:43:25 +0800
+Subject: [PATCH 40/76] clocksource: mediatek: Use GPT as sched clock source
+
+When cpu is in deep idle, arch timer will stop counting. Setup GPT as
+sched clock source so it can keep counting in idle.
+
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+---
+ drivers/clocksource/mtk_timer.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c
+index 85e0ab5..9a90c7b 100644
+--- a/drivers/clocksource/mtk_timer.c
++++ b/drivers/clocksource/mtk_timer.c
+@@ -24,6 +24,7 @@
+ #include <linux/of.h>
+ #include <linux/of_address.h>
+ #include <linux/of_irq.h>
++#include <linux/sched_clock.h>
+ #include <linux/slab.h>
+
+ #define GPT_IRQ_EN_REG 0x00
+@@ -59,6 +60,13 @@ struct mtk_clock_event_device {
+ struct clock_event_device dev;
+ };
+
++static void __iomem *gpt_base __read_mostly;
++
++static u64 notrace mtk_read_sched_clock(void)
++{
++ return readl_relaxed(gpt_base + TIMER_CNT_REG(GPT_CLK_SRC));
++}
++
+ static inline struct mtk_clock_event_device *to_mtk_clk(
+ struct clock_event_device *c)
+ {
+@@ -239,6 +247,8 @@ static void __init mtk_timer_init(struct device_node *node)
+ mtk_timer_setup(evt, GPT_CLK_SRC, TIMER_CTRL_OP_FREERUN);
+ clocksource_mmio_init(evt->gpt_base + TIMER_CNT_REG(GPT_CLK_SRC),
+ node->name, rate, 300, 32, clocksource_mmio_readl_up);
++ gpt_base = evt->gpt_base;
++ sched_clock_register(mtk_read_sched_clock, 32, rate);
+
+ /* Configure clock event */
+ mtk_timer_setup(evt, GPT_CLK_EVT, TIMER_CTRL_OP_REPEAT);
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0041-arm-mediatek-enable-gpt6-on-boot-up-to-make-arch-tim.patch b/target/linux/mediatek/patches/0041-arm-mediatek-enable-gpt6-on-boot-up-to-make-arch-tim.patch
new file mode 100644
index 0000000000..728792c2a8
--- /dev/null
+++ b/target/linux/mediatek/patches/0041-arm-mediatek-enable-gpt6-on-boot-up-to-make-arch-tim.patch
@@ -0,0 +1,63 @@
+From eec99287ace37015ed313b4fc27ba205a158b66c Mon Sep 17 00:00:00 2001
+From: Matthias Brugger <matthias.bgg@gmail.com>
+Date: Fri, 1 May 2015 15:43:26 +0800
+Subject: [PATCH 41/76] arm: mediatek: enable gpt6 on boot up to make arch
+ timer working
+
+We enable GTP6 which ungates the arch timer clock.
+In the future this should be done in the bootloader.
+
+Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+---
+ arch/arm/mach-mediatek/mediatek.c | 29 +++++++++++++++++++++++++++++
+ 1 file changed, 29 insertions(+)
+
+diff --git a/arch/arm/mach-mediatek/mediatek.c b/arch/arm/mach-mediatek/mediatek.c
+index a954900..6b38d67 100644
+--- a/arch/arm/mach-mediatek/mediatek.c
++++ b/arch/arm/mach-mediatek/mediatek.c
+@@ -16,6 +16,34 @@
+ */
+ #include <linux/init.h>
+ #include <asm/mach/arch.h>
++#include <linux/of.h>
++#include <linux/clk-provider.h>
++#include <linux/clocksource.h>
++
++
++#define GPT6_CON_MT65xx 0x10008060
++#define GPT_ENABLE 0x31
++
++static void __init mediatek_timer_init(void)
++{
++ void __iomem *gpt_base = 0;
++
++ if (of_machine_is_compatible("mediatek,mt6589") ||
++ of_machine_is_compatible("mediatek,mt8135") ||
++ of_machine_is_compatible("mediatek,mt8127")) {
++ /* turn on GPT6 which ungates arch timer clocks */
++ gpt_base = ioremap(GPT6_CON_MT65xx, 0x04);
++ }
++
++ /* enabel clock and set to free-run */
++ if (gpt_base) {
++ writel(GPT_ENABLE, gpt_base);
++ iounmap(gpt_base);
++ }
++
++ of_clk_init(NULL);
++ clocksource_of_init();
++};
+
+ static const char * const mediatek_board_dt_compat[] = {
+ "mediatek,mt6589",
+@@ -27,4 +55,5 @@ static const char * const mediatek_board_dt_compat[] = {
+
+ DT_MACHINE_START(MEDIATEK_DT, "Mediatek Cortex-A7 (Device Tree)")
+ .dt_compat = mediatek_board_dt_compat,
++ .init_time = mediatek_timer_init,
+ MACHINE_END
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0042-ARM-mediatek-add-smp-bringup-code.patch b/target/linux/mediatek/patches/0042-ARM-mediatek-add-smp-bringup-code.patch
new file mode 100644
index 0000000000..8910532e18
--- /dev/null
+++ b/target/linux/mediatek/patches/0042-ARM-mediatek-add-smp-bringup-code.patch
@@ -0,0 +1,178 @@
+From daa2c1f9202f08628d4f91a1cf4dafb44c9bcafe Mon Sep 17 00:00:00 2001
+From: "Joe.C" <yingjoe.chen@mediatek.com>
+Date: Fri, 1 May 2015 15:43:28 +0800
+Subject: [PATCH 42/76] ARM: mediatek: add smp bringup code
+
+Add support for booting secondary CPUs on mt6589, mt8127
+and mt8135.
+
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+---
+ arch/arm/mach-mediatek/Makefile | 3 +
+ arch/arm/mach-mediatek/platsmp.c | 145 ++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 148 insertions(+)
+ create mode 100644 arch/arm/mach-mediatek/platsmp.c
+
+diff --git a/arch/arm/mach-mediatek/Makefile b/arch/arm/mach-mediatek/Makefile
+index 43e619f..2116460 100644
+--- a/arch/arm/mach-mediatek/Makefile
++++ b/arch/arm/mach-mediatek/Makefile
+@@ -1 +1,4 @@
++ifeq ($(CONFIG_SMP),y)
++obj-$(CONFIG_ARCH_MEDIATEK) += platsmp.o
++endif
+ obj-$(CONFIG_ARCH_MEDIATEK) += mediatek.o
+diff --git a/arch/arm/mach-mediatek/platsmp.c b/arch/arm/mach-mediatek/platsmp.c
+new file mode 100644
+index 0000000..e266b3d
+--- /dev/null
++++ b/arch/arm/mach-mediatek/platsmp.c
+@@ -0,0 +1,145 @@
++/*
++ * arch/arm/mach-mediatek/platsmp.c
++ *
++ * Copyright (c) 2014 Mediatek Inc.
++ * Author: Shunli Wang <shunli.wang@mediatek.com>
++ * Yingjoe Chen <yingjoe.chen@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ *
++ */
++#include <linux/io.h>
++#include <linux/memblock.h>
++#include <linux/of.h>
++#include <linux/of_address.h>
++#include <linux/string.h>
++#include <linux/threads.h>
++
++#define MTK_MAX_CPU 8
++#define MTK_SMP_REG_SIZE 0x1000
++
++struct mtk_smp_boot_info {
++ unsigned long smp_base;
++ unsigned int jump_reg;
++ unsigned int boot_reg;
++ unsigned int core_keys[MTK_MAX_CPU - 1];
++ unsigned int core_regs[MTK_MAX_CPU - 1];
++};
++
++static const struct mtk_smp_boot_info mtk_mt8135_tz_boot = {
++ 0x80002000, 1020, 1012,
++ { 0x534c4131, 0x4c415332, 0x41534c33 },
++ { 1016, 1016, 1016},
++};
++
++static const struct mtk_smp_boot_info mtk_mt6589_boot = {
++ 0x10002000, 0x34, 0x30,
++ { 0x534c4131, 0x4c415332, 0x41534c33 },
++ { 0x38, 0x3c, 0x40 },
++};
++
++static const struct of_device_id mtk_tz_smp_boot_infos[] __initconst = {
++ { .compatible = "mediatek,mt8135", .data = &mtk_mt8135_tz_boot },
++ { .compatible = "mediatek,mt8127", .data = &mtk_mt8135_tz_boot },
++};
++
++static const struct of_device_id mtk_smp_boot_infos[] __initconst = {
++ { .compatible = "mediatek,mt6589", .data = &mtk_mt6589_boot },
++};
++
++static void __iomem *mtk_smp_base;
++static const struct mtk_smp_boot_info *mtk_smp_info;
++
++static int mtk_boot_secondary(unsigned int cpu, struct task_struct *idle)
++{
++ if (!mtk_smp_base)
++ return -EINVAL;
++
++ if (!mtk_smp_info->core_keys[cpu-1])
++ return -EINVAL;
++
++ writel_relaxed(mtk_smp_info->core_keys[cpu-1],
++ mtk_smp_base + mtk_smp_info->core_regs[cpu-1]);
++
++ arch_send_wakeup_ipi_mask(cpumask_of(cpu));
++
++ return 0;
++}
++
++static void __init __mtk_smp_prepare_cpus(unsigned int max_cpus, int trustzone)
++{
++ int i, num;
++ const struct of_device_id *infos;
++
++ if (trustzone) {
++ num = ARRAY_SIZE(mtk_tz_smp_boot_infos);
++ infos = mtk_tz_smp_boot_infos;
++ } else {
++ num = ARRAY_SIZE(mtk_smp_boot_infos);
++ infos = mtk_smp_boot_infos;
++ }
++
++ /* Find smp boot info for this SoC */
++ for (i = 0; i < num; i++) {
++ if (of_machine_is_compatible(infos[i].compatible)) {
++ mtk_smp_info = infos[i].data;
++ break;
++ }
++ }
++
++ if (!mtk_smp_info) {
++ pr_err("%s: Device is not supported\n", __func__);
++ return;
++ }
++
++ if (trustzone) {
++ if (memblock_reserve(mtk_smp_info->smp_base, MTK_SMP_REG_SIZE)) {
++ pr_err("%s: Can't reserve smp memory\n", __func__);
++ return;
++ }
++ mtk_smp_base = phys_to_virt(mtk_smp_info->smp_base);
++ } else {
++ mtk_smp_base = ioremap(mtk_smp_info->smp_base, MTK_SMP_REG_SIZE);
++ if (!mtk_smp_base) {
++ pr_err("%s: Can't remap %lx\n", __func__,
++ mtk_smp_info->smp_base);
++ return;
++ }
++ }
++
++ /*
++ * write the address of slave startup address into the system-wide
++ * jump register
++ */
++ writel_relaxed(virt_to_phys(secondary_startup),
++ mtk_smp_base + mtk_smp_info->jump_reg);
++}
++
++static void __init mtk_tz_smp_prepare_cpus(unsigned int max_cpus)
++{
++ __mtk_smp_prepare_cpus(max_cpus, 1);
++}
++
++static void __init mtk_smp_prepare_cpus(unsigned int max_cpus)
++{
++ __mtk_smp_prepare_cpus(max_cpus, 0);
++}
++
++static struct smp_operations mt81xx_tz_smp_ops __initdata = {
++ .smp_prepare_cpus = mtk_tz_smp_prepare_cpus,
++ .smp_boot_secondary = mtk_boot_secondary,
++};
++CPU_METHOD_OF_DECLARE(mt81xx_tz_smp, "mediatek,mt81xx-tz-smp", &mt81xx_tz_smp_ops);
++
++static struct smp_operations mt65xx_smp_ops __initdata = {
++ .smp_prepare_cpus = mtk_smp_prepare_cpus,
++ .smp_boot_secondary = mtk_boot_secondary,
++};
++CPU_METHOD_OF_DECLARE(mt65xx_smp, "mediatek,mt65xx-smp", &mt65xx_smp_ops);
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0043-ARM-dts-mt8127-enable-basic-SMP-bringup-for-mt8127.patch b/target/linux/mediatek/patches/0043-ARM-dts-mt8127-enable-basic-SMP-bringup-for-mt8127.patch
new file mode 100644
index 0000000000..60990c3282
--- /dev/null
+++ b/target/linux/mediatek/patches/0043-ARM-dts-mt8127-enable-basic-SMP-bringup-for-mt8127.patch
@@ -0,0 +1,53 @@
+From e75f8b666c976aff2aa30b967f74df021d800993 Mon Sep 17 00:00:00 2001
+From: "Joe.C" <yingjoe.chen@mediatek.com>
+Date: Fri, 1 May 2015 15:43:30 +0800
+Subject: [PATCH 43/76] ARM: dts: mt8127: enable basic SMP bringup for mt8127
+
+Add arch timer node to enable arch-timer support. MT8127 firmware
+doesn't correctly setup arch-timer frequency and CNTVOFF, add
+properties to workaround this.
+
+This also set cpu enable-method to enable SMP.
+
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+---
+ arch/arm/boot/dts/mt8127.dtsi | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/arch/arm/boot/dts/mt8127.dtsi b/arch/arm/boot/dts/mt8127.dtsi
+index aaa7862..7c2090d 100644
+--- a/arch/arm/boot/dts/mt8127.dtsi
++++ b/arch/arm/boot/dts/mt8127.dtsi
+@@ -23,6 +23,7 @@
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
++ enable-method = "mediatek,mt81xx-tz-smp";
+
+ cpu@0 {
+ device_type = "cpu";
+@@ -72,6 +73,21 @@
+ };
+ };
+
++ timer {
++ compatible = "arm,armv7-timer";
++ interrupt-parent = <&gic>;
++ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) |
++ IRQ_TYPE_LEVEL_LOW)>,
++ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) |
++ IRQ_TYPE_LEVEL_LOW)>,
++ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
++ IRQ_TYPE_LEVEL_LOW)>,
++ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
++ IRQ_TYPE_LEVEL_LOW)>;
++ clock-frequency = <13000000>;
++ arm,cpu-registers-not-fw-configured;
++ };
++
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0044-dt-bindings-Add-usb3.0-phy-binding-for-MT65xx-SoCs.patch b/target/linux/mediatek/patches/0044-dt-bindings-Add-usb3.0-phy-binding-for-MT65xx-SoCs.patch
new file mode 100644
index 0000000000..1783e089ae
--- /dev/null
+++ b/target/linux/mediatek/patches/0044-dt-bindings-Add-usb3.0-phy-binding-for-MT65xx-SoCs.patch
@@ -0,0 +1,60 @@
+From 8d61eb953496aba51b94dac07c31c7e069c784bd Mon Sep 17 00:00:00 2001
+From: Chunfeng Yun <chunfeng.yun@mediatek.com>
+Date: Wed, 27 May 2015 19:47:58 +0800
+Subject: [PATCH 44/76] dt-bindings: Add usb3.0 phy binding for MT65xx SoCs
+
+add a DT binding documentation of usb3.0 phy for MT65xx
+SoCs from Mediatek.
+
+Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
+---
+ .../devicetree/bindings/usb/mt65xx-u3phy.txt | 37 ++++++++++++++++++++
+ 1 file changed, 37 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/usb/mt65xx-u3phy.txt
+
+diff --git a/Documentation/devicetree/bindings/usb/mt65xx-u3phy.txt b/Documentation/devicetree/bindings/usb/mt65xx-u3phy.txt
+new file mode 100644
+index 0000000..b0b91b0
+--- /dev/null
++++ b/Documentation/devicetree/bindings/usb/mt65xx-u3phy.txt
+@@ -0,0 +1,37 @@
++MT65xx U3PHY
++
++The device node for Mediatek SOC usb3.0 phy
++
++Required properties:
++ - compatible : Should be "mediatek,mt8173-u3phy"
++ - reg : Offset and length of registers, the first is for mac domain,
++ another for phy domain
++ - power-domains: to enable usb's mtcmos
++ - reg-vusb33-supply: regulator of usb avdd3.3v
++ - clocks : must support all clocks that phy need
++ - clock-names: should be "wakeup_deb_p0", "wakeup_deb_p1" for wakeup
++ debounce control clocks, "sys_mac" for sys and mac clocks and
++ "u3phya_ref" for u3phya reference clock.
++
++Optional properties:
++ - disable-usb2-p1 : disable port1 of usb2.0 which has two ports.
++ - reg-p1-vbus-supply : regulator of port1's vbus;
++
++Example:
++
++u3phy: usb-phy@11271000 {
++ compatible = "mediatek,mt8173-u3phy";
++ reg = <0 0x11271000 0 0x3000>,
++ <0 0x11280000 0 0x20000>;
++ power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
++ reg-vusb33-supply = <&mt6397_usb_reg>;
++ clocks = <&perisys PERI_USB0>,
++ <&perisys PERI_USB1>,
++ <&topckgen CLK_TOP_USB30_SEL>,
++ <&apmixedsys CLK_APMIXED_REF2USB_TX>;
++ clock-names = "wakeup_deb_p0",
++ "wakeup_deb_p1",
++ "sys_mac",
++ "u3phya_ref";
++ disable-usb2-p1;
++};
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0045-dt-bindings-Add-a-binding-for-Mediatek-xHCI-host-con.patch b/target/linux/mediatek/patches/0045-dt-bindings-Add-a-binding-for-Mediatek-xHCI-host-con.patch
new file mode 100644
index 0000000000..6c1d7b3759
--- /dev/null
+++ b/target/linux/mediatek/patches/0045-dt-bindings-Add-a-binding-for-Mediatek-xHCI-host-con.patch
@@ -0,0 +1,43 @@
+From 8629bcb28208ef5b9f5eeb6d4b669651c9521b30 Mon Sep 17 00:00:00 2001
+From: Chunfeng Yun <chunfeng.yun@mediatek.com>
+Date: Wed, 27 May 2015 19:47:59 +0800
+Subject: [PATCH 45/76] dt-bindings: Add a binding for Mediatek xHCI host
+ controller
+
+add a DT binding documentation of xHCI host controller for
+the MT8173 SoC from Mediatek.
+
+Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
+---
+ .../devicetree/bindings/usb/mt8173-xhci.txt | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/usb/mt8173-xhci.txt
+
+diff --git a/Documentation/devicetree/bindings/usb/mt8173-xhci.txt b/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
+new file mode 100644
+index 0000000..da28570
+--- /dev/null
++++ b/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
+@@ -0,0 +1,19 @@
++MT65XX xhci
++
++The device node for Mediatek SOC usb3.0 host controller
++
++Required properties:
++ - compatible : supports "mediatek,mt8173-xhci", "generic-xhci"
++ - reg : Offset and length of registers
++ - interrupts : Interrupt; mode, number and trigger
++ - usb-phy : the phy that xhci will bind
++ - usb3-lpm-capable: suppots USB3 LPM
++
++Example:
++usb: usb30@11270000 {
++ compatible = "mediatek,mt8173-xhci", "generic-xhci";
++ reg = <0 0x11270000 0 0x1000>;
++ interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
++ usb-phy = <&u3phy>;
++ usb3-lpm-capable;
++};
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0046-usb-phy-add-usb3.0-phy-driver-for-mt65xx-SoCs.patch b/target/linux/mediatek/patches/0046-usb-phy-add-usb3.0-phy-driver-for-mt65xx-SoCs.patch
new file mode 100644
index 0000000000..40ba24d552
--- /dev/null
+++ b/target/linux/mediatek/patches/0046-usb-phy-add-usb3.0-phy-driver-for-mt65xx-SoCs.patch
@@ -0,0 +1,779 @@
+From cee7c5a343bdecf407c876289327c567bfd34fd4 Mon Sep 17 00:00:00 2001
+From: Chunfeng Yun <chunfeng.yun@mediatek.com>
+Date: Wed, 27 May 2015 19:48:01 +0800
+Subject: [PATCH 46/76] usb: phy: add usb3.0 phy driver for mt65xx SoCs
+
+Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
+---
+ drivers/usb/phy/Kconfig | 10 +
+ drivers/usb/phy/Makefile | 1 +
+ drivers/usb/phy/phy-mt65xx-usb3.c | 724 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 735 insertions(+)
+ create mode 100644 drivers/usb/phy/phy-mt65xx-usb3.c
+
+diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
+index 2175678..dfca566 100644
+--- a/drivers/usb/phy/Kconfig
++++ b/drivers/usb/phy/Kconfig
+@@ -151,6 +151,16 @@ config USB_MSM_OTG
+ This driver is not supported on boards like trout which
+ has an external PHY.
+
++config USB_MT65XX_USB3_PHY
++ tristate "Mediatek USB3.0 PHY controller Driver"
++ depends on ARCH_MEDIATEK || COMPILE_TEST
++ select USB_PHY
++ help
++ Say 'Y' here to add support for Mediatek USB3.0 PHY driver
++ for mt65xx SoCs. it supports two usb2.0 ports and
++ one usb3.0 port.
++ To compile this driver as a module, choose M here
++
+ config USB_MV_OTG
+ tristate "Marvell USB OTG support"
+ depends on USB_EHCI_MV && USB_MV_UDC && PM
+diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
+index 75f2bba..d6113a4 100644
+--- a/drivers/usb/phy/Makefile
++++ b/drivers/usb/phy/Makefile
+@@ -20,6 +20,7 @@ obj-$(CONFIG_USB_EHCI_TEGRA) += phy-tegra-usb.o
+ obj-$(CONFIG_USB_GPIO_VBUS) += phy-gpio-vbus-usb.o
+ obj-$(CONFIG_USB_ISP1301) += phy-isp1301.o
+ obj-$(CONFIG_USB_MSM_OTG) += phy-msm-usb.o
++obj-$(CONFIG_USB_MT65XX_USB3_PHY) += phy-mt65xx-usb3.o
+ obj-$(CONFIG_USB_MV_OTG) += phy-mv-usb.o
+ obj-$(CONFIG_USB_MXS_PHY) += phy-mxs-usb.o
+ obj-$(CONFIG_USB_RCAR_PHY) += phy-rcar-usb.o
+diff --git a/drivers/usb/phy/phy-mt65xx-usb3.c b/drivers/usb/phy/phy-mt65xx-usb3.c
+new file mode 100644
+index 0000000..ec5cf24
+--- /dev/null
++++ b/drivers/usb/phy/phy-mt65xx-usb3.c
+@@ -0,0 +1,724 @@
++/*
++ * Copyright (c) 2015 MediaTek Inc.
++ * Author: Chunfeng.Yun <chunfeng.yun@mediatek.com>
++ *
++ * This software is licensed under the terms of the GNU General Public
++ * License version 2, as published by the Free Software Foundation, and
++ * may be copied, distributed, and modified under those terms.
++ *
++ * 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.
++ *
++ */
++
++#include <linux/resource.h>
++#include <linux/delay.h>
++#include <linux/slab.h>
++#include <linux/err.h>
++#include <linux/export.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/regulator/consumer.h>
++#include <linux/pm_runtime.h>
++#include <linux/io.h>
++#include <linux/gpio.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_gpio.h>
++#include <linux/of_address.h>
++#include <linux/usb/otg.h>
++#include <linux/usb/of.h>
++#include <linux/usb/phy.h>
++#include <linux/clk.h>
++#include <linux/iopoll.h>
++
++/*
++ * relative to MAC base address
++ */
++#define SSUSB_USB3_MAC_CSR_BASE (0x1400)
++#define SSUSB_USB3_SYS_CSR_BASE (0x1400)
++#define SSUSB_USB2_CSR_BASE (0x2400)
++
++/*
++ * for sifslv1 register
++ * relative to USB3_SIF_BASE base address
++ */
++#define SSUSB_SIFSLV_IPPC_BASE (0x700)
++
++/*
++ * for sifslv2 register
++ * relative to USB3_SIF_BASE base address
++ */
++#define SSUSB_SIFSLV_U2PHY_COM_BASE (0x10800)
++#define SSUSB_SIFSLV_U3PHYD_BASE (0x10900)
++#define SSUSB_SIFSLV_U2FREQ_BASE (0x10f00)
++#define SSUSB_USB30_PHYA_SIV_B_BASE (0x10b00)
++#define SSUSB_SIFSLV_U3PHYA_DA_BASE (0x10c00)
++#define SSUSB_SIFSLV_SPLLC (0x10000)
++
++/*port1 refs. +0x800(refer to port0)*/
++#define U3P_PORT_OFFSET (0x800) /*based on port0 */
++#define U3P_PHY_BASE(index) ((U3P_PORT_OFFSET) * (index))
++
++#define U3P_IP_PW_CTRL0 (SSUSB_SIFSLV_IPPC_BASE+0x0000)
++#define CTRL0_IP_SW_RST (0x1<<0)
++
++#define U3P_IP_PW_CTRL1 (SSUSB_SIFSLV_IPPC_BASE+0x0004)
++#define CTRL1_IP_HOST_PDN (0x1<<0)
++
++#define U3P_IP_PW_STS1 (SSUSB_SIFSLV_IPPC_BASE+0x0010)
++#define STS1_U3_MAC_RST (0x1 << 16)
++#define STS1_SYS125_RST (0x1 << 10)
++#define STS1_REF_RST (0x1 << 8)
++#define STS1_SYSPLL_STABLE (0x1 << 0)
++
++#define U3P_IP_PW_STS2 (SSUSB_SIFSLV_IPPC_BASE+0x0014)
++#define STS2_U2_MAC_RST (0x1 << 0)
++
++#define U3P_IP_XHCI_CAP (SSUSB_SIFSLV_IPPC_BASE + 0x24)
++#define CAP_U3_PORT_NUM(p) ((p) & 0xff)
++#define CAP_U2_PORT_NUM(p) (((p) >> 8) & 0xff)
++
++#define U3P_U3_CTRL_0P (SSUSB_SIFSLV_IPPC_BASE+0x0030)
++#define CTRL_U3_PORT_HOST_SEL (0x1<<2)
++#define CTRL_U3_PORT_PDN (0x1<<1)
++#define CTRL_U3_PORT_DIS (0x1<<0)
++
++#define U3P_U2_CTRL_0P (SSUSB_SIFSLV_IPPC_BASE+0x0050)
++#define CTRL_U2_PORT_HOST_SEL (0x1<<2)
++#define CTRL_U2_PORT_PDN (0x1<<1)
++#define CTRL_U2_PORT_DIS (0x1<<0)
++
++#define U3P_U3_CTRL(p) (U3P_U3_CTRL_0P + ((p) * 0x08))
++#define U3P_U2_CTRL(p) (U3P_U2_CTRL_0P + ((p) * 0x08))
++
++#define U3P_USBPHYACR5 (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0014)
++#define PA5_RG_U2_HSTX_SRCTRL (0x7<<12)
++#define PA5_RG_U2_HSTX_SRCTRL_VAL(x) ((0x7 & (x)) << 12)
++#define PA5_RG_U2_HS_100U_U3_EN (0x1<<11)
++
++#define U3P_USBPHYACR6 (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0018)
++#define PA6_RG_U2_ISO_EN (0x1<<31)
++#define PA6_RG_U2_BC11_SW_EN (0x1<<23)
++#define PA6_RG_U2_OTG_VBUSCMP_EN (0x1<<20)
++
++#define U3P_U2PHYACR4 (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0020)
++#define P2C_RG_USB20_GPIO_CTL (0x1<<9)
++#define P2C_USB20_GPIO_MODE (0x1<<8)
++#define P2C_U2_GPIO_CTR_MSK (P2C_RG_USB20_GPIO_CTL | P2C_USB20_GPIO_MODE)
++
++#define U3P_U2PHYDTM0 (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0068)
++#define P2C_FORCE_UART_EN (0x1<<26)
++#define P2C_FORCE_DATAIN (0x1<<23)
++#define P2C_FORCE_DM_PULLDOWN (0x1<<21)
++#define P2C_FORCE_DP_PULLDOWN (0x1<<20)
++#define P2C_FORCE_XCVRSEL (0x1<<19)
++#define P2C_FORCE_SUSPENDM (0x1<<18)
++#define P2C_FORCE_TERMSEL (0x1<<17)
++#define P2C_RG_DATAIN (0xf<<10)
++#define P2C_RG_DATAIN_VAL(x) ((0xf & (x)) << 10)
++#define P2C_RG_DMPULLDOWN (0x1<<7)
++#define P2C_RG_DPPULLDOWN (0x1<<6)
++#define P2C_RG_XCVRSEL (0x3<<4)
++#define P2C_RG_XCVRSEL_VAL(x) ((0x3 & (x)) << 4)
++#define P2C_RG_SUSPENDM (0x1<<3)
++#define P2C_RG_TERMSEL (0x1<<2)
++#define P2C_DTM0_PART_MASK \
++ (P2C_FORCE_DATAIN | P2C_FORCE_DM_PULLDOWN | \
++ P2C_FORCE_DP_PULLDOWN | P2C_FORCE_XCVRSEL | \
++ P2C_FORCE_TERMSEL | P2C_RG_DMPULLDOWN | \
++ P2C_RG_TERMSEL)
++
++#define U3P_U2PHYDTM1 (SSUSB_SIFSLV_U2PHY_COM_BASE+0x006C)
++#define P2C_RG_UART_EN (0x1<<16)
++#define P2C_RG_VBUSVALID (0x1<<5)
++#define P2C_RG_SESSEND (0x1<<4)
++#define P2C_RG_AVALID (0x1<<2)
++
++#define U3P_U3_PHYA_REG0 (SSUSB_USB30_PHYA_SIV_B_BASE+0x0000)
++#define P3A_RG_U3_VUSB10_ON (1<<5)
++
++#define U3P_U3_PHYA_REG6 (SSUSB_USB30_PHYA_SIV_B_BASE+0x0018)
++#define P3A_RG_TX_EIDLE_CM (0xf<<28)
++#define P3A_RG_TX_EIDLE_CM_VAL(x) ((0xf & (x)) << 28)
++
++#define U3P_U3_PHYA_REG9 (SSUSB_USB30_PHYA_SIV_B_BASE+0x0024)
++#define P3A_RG_RX_DAC_MUX (0x1f<<1)
++#define P3A_RG_RX_DAC_MUX_VAL(x) ((0x1f & (x)) << 1)
++
++#define U3P_U3PHYA_DA_REG0 (SSUSB_SIFSLV_U3PHYA_DA_BASE + 0x0)
++#define P3A_RG_XTAL_EXT_EN_U3 (0x3<<10)
++#define P3A_RG_XTAL_EXT_EN_U3_VAL(x) ((0x3 & (x)) << 10)
++
++#define U3P_PHYD_CDR1 (SSUSB_SIFSLV_U3PHYD_BASE+0x5c)
++#define P3D_RG_CDR_BIR_LTD1 (0x1f<<24)
++#define P3D_RG_CDR_BIR_LTD1_VAL(x) ((0x1f & (x)) << 24)
++#define P3D_RG_CDR_BIR_LTD0 (0x1f<<8)
++#define P3D_RG_CDR_BIR_LTD0_VAL(x) ((0x1f & (x)) << 8)
++
++#define U3P_XTALCTL3 (SSUSB_SIFSLV_SPLLC + 0x18)
++#define XC3_RG_U3_XTAL_RX_PWD (0x1<<9)
++#define XC3_RG_U3_FRC_XTAL_RX_PWD (0x1<<8)
++
++#define U3P_UX_EXIT_LFPS_PARAM (SSUSB_USB3_MAC_CSR_BASE+0x00A0)
++#define RX_UX_EXIT_REF (0xff<<8)
++#define RX_UX_EXIT_REF_VAL (0x3 << 8)
++
++#define U3P_REF_CLK_PARAM (SSUSB_USB3_MAC_CSR_BASE+0x00B0)
++#define REF_CLK_1000NS (0xff << 0)
++#define REF_CLK_VAL_DEF (0xa << 0)
++
++#define U3P_LINK_PM_TIMER (SSUSB_USB3_SYS_CSR_BASE+0x0208)
++#define PM_LC_TIMEOUT (0xf<<0)
++#define PM_LC_TIMEOUT_VAL (0x3 << 0)
++
++#define U3P_TIMING_PULSE_CTRL (SSUSB_USB3_SYS_CSR_BASE+0x02B4)
++#define U3T_CNT_1US (0xff << 0)
++#define U3T_CNT_1US_VAL (0x3f << 0) /* 62.5MHz: 63 */
++
++#define U3P_U2_TIMING_PARAM (SSUSB_USB2_CSR_BASE+0x0040)
++#define U2T_VAL_1US (0xff<<0)
++#define U2T_VAL_1US_VAL (0x3f << 0) /* 62.5MHz: 63 */
++
++
++struct mt65xx_u3phy {
++ struct usb_phy phy;
++ struct device *dev;
++ struct regulator *vusb33;
++ struct regulator *p1_vbus;
++ void __iomem *mac_base; /* only device-mac regs, exclude xhci's */
++ void __iomem *sif_base; /* include sif & sif2 */
++ struct clk *wk_deb_p0; /* port0's wakeup debounce clock */
++ struct clk *wk_deb_p1;
++ struct clk *sys_mac; /* sys and mac clock */
++ struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */
++ bool enable_usb2_p1;
++};
++
++
++static void u3p_writel(void __iomem *base, u32 offset, u32 data)
++{
++ writel(data, base + offset);
++}
++
++static u32 u3p_readl(void __iomem *base, u32 offset)
++{
++ return readl(base + offset);
++}
++
++static void u3p_setmsk(void __iomem *base, u32 offset, u32 msk)
++{
++ void __iomem *addr = base + offset;
++
++ writel((readl(addr) | msk), addr);
++}
++
++static void u3p_clrmsk(void __iomem *base, u32 offset, u32 msk)
++{
++ void __iomem *addr = base + offset;
++
++ writel((readl(addr) & ~msk), addr);
++}
++
++static void u3p_setval(void __iomem *base, u32 offset,
++ u32 mask, u32 value)
++{
++ void __iomem *addr = base + offset;
++ unsigned int new_value;
++
++ new_value = (readl(addr) & ~mask) | value;
++ writel(new_value, addr);
++}
++
++static void phy_index_power_on(struct mt65xx_u3phy *u3phy, int index)
++{
++ void __iomem *sif_base = u3phy->sif_base + U3P_PHY_BASE(index);
++
++ if (!index) {
++ /* Set RG_SSUSB_VUSB10_ON as 1 after VUSB10 ready */
++ u3p_setmsk(sif_base, U3P_U3_PHYA_REG0, P3A_RG_U3_VUSB10_ON);
++ /* power domain iso disable */
++ u3p_clrmsk(sif_base, U3P_USBPHYACR6, PA6_RG_U2_ISO_EN);
++ }
++
++ /* switch to USB function. (system register, force ip into usb mode) */
++ u3p_clrmsk(sif_base, U3P_U2PHYDTM0, P2C_FORCE_UART_EN);
++ u3p_clrmsk(sif_base, U3P_U2PHYDTM1, P2C_RG_UART_EN);
++ if (!index)
++ u3p_clrmsk(sif_base, U3P_U2PHYACR4, P2C_U2_GPIO_CTR_MSK);
++
++ /* (force_suspendm=0) (let suspendm=1, enable usb 480MHz pll) */
++ u3p_clrmsk(sif_base, U3P_U2PHYDTM0, P2C_FORCE_SUSPENDM);
++ u3p_clrmsk(sif_base, U3P_U2PHYDTM0,
++ P2C_RG_XCVRSEL | P2C_RG_DATAIN | P2C_DTM0_PART_MASK);
++
++ /* DP/DM BC1.1 path Disable */
++ u3p_clrmsk(sif_base, U3P_USBPHYACR6, PA6_RG_U2_BC11_SW_EN);
++ /* OTG Enable */
++ u3p_setmsk(sif_base, U3P_USBPHYACR6, PA6_RG_U2_OTG_VBUSCMP_EN);
++ u3p_setval(sif_base, U3P_U3PHYA_DA_REG0, P3A_RG_XTAL_EXT_EN_U3,
++ P3A_RG_XTAL_EXT_EN_U3_VAL(2));
++ u3p_setval(sif_base, U3P_U3_PHYA_REG9, P3A_RG_RX_DAC_MUX,
++ P3A_RG_RX_DAC_MUX_VAL(4));
++
++ if (!index) {
++ u3p_setmsk(sif_base, U3P_XTALCTL3, XC3_RG_U3_XTAL_RX_PWD);
++ u3p_setmsk(sif_base, U3P_XTALCTL3, XC3_RG_U3_FRC_XTAL_RX_PWD);
++ /* [mt8173]disable Change 100uA current from SSUSB */
++ u3p_clrmsk(sif_base, U3P_USBPHYACR5, PA5_RG_U2_HS_100U_U3_EN);
++ }
++ u3p_setval(sif_base, U3P_U3_PHYA_REG6, P3A_RG_TX_EIDLE_CM,
++ P3A_RG_TX_EIDLE_CM_VAL(0xe));
++ u3p_setval(sif_base, U3P_PHYD_CDR1, P3D_RG_CDR_BIR_LTD0,
++ P3D_RG_CDR_BIR_LTD0_VAL(0xc));
++ u3p_setval(sif_base, U3P_PHYD_CDR1, P3D_RG_CDR_BIR_LTD1,
++ P3D_RG_CDR_BIR_LTD1_VAL(0x3));
++
++ udelay(800);
++ u3p_setmsk(sif_base, U3P_U2PHYDTM1, P2C_RG_VBUSVALID | P2C_RG_AVALID);
++ u3p_clrmsk(sif_base, U3P_U2PHYDTM1, P2C_RG_SESSEND);
++
++ /* USB 2.0 slew rate calibration */
++ u3p_setval(sif_base, U3P_USBPHYACR5, PA5_RG_U2_HSTX_SRCTRL,
++ PA5_RG_U2_HSTX_SRCTRL_VAL(4));
++
++ dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
++}
++
++
++static void phy_index_power_off(struct mt65xx_u3phy *u3phy, int index)
++{
++ void __iomem *sif_base = u3phy->sif_base + U3P_PHY_BASE(index);
++
++ /* switch to USB function. (system register, force ip into usb mode) */
++ u3p_clrmsk(sif_base, U3P_U2PHYDTM0, P2C_FORCE_UART_EN);
++ u3p_clrmsk(sif_base, U3P_U2PHYDTM1, P2C_RG_UART_EN);
++ if (!index)
++ u3p_clrmsk(sif_base, U3P_U2PHYACR4, P2C_U2_GPIO_CTR_MSK);
++
++ u3p_setmsk(sif_base, U3P_U2PHYDTM0, P2C_FORCE_SUSPENDM);
++ u3p_setval(sif_base, U3P_U2PHYDTM0,
++ P2C_RG_XCVRSEL, P2C_RG_XCVRSEL_VAL(1));
++ u3p_setval(sif_base, U3P_U2PHYDTM0,
++ P2C_RG_DATAIN, P2C_RG_DATAIN_VAL(0));
++ u3p_setmsk(sif_base, U3P_U2PHYDTM0, P2C_DTM0_PART_MASK);
++ /* DP/DM BC1.1 path Disable */
++ u3p_clrmsk(sif_base, U3P_USBPHYACR6, PA6_RG_U2_BC11_SW_EN);
++ /* OTG Disable */
++ u3p_clrmsk(sif_base, U3P_USBPHYACR6, PA6_RG_U2_OTG_VBUSCMP_EN);
++ if (!index) {
++ /* Change 100uA current switch to USB2.0 */
++ u3p_clrmsk(sif_base, U3P_USBPHYACR5, PA5_RG_U2_HS_100U_U3_EN);
++ }
++ udelay(800);
++
++ /* let suspendm=0, set utmi into analog power down */
++ u3p_clrmsk(sif_base, U3P_U2PHYDTM0, P2C_RG_SUSPENDM);
++ udelay(1);
++
++ u3p_clrmsk(sif_base, U3P_U2PHYDTM1, P2C_RG_VBUSVALID | P2C_RG_AVALID);
++ u3p_setmsk(sif_base, U3P_U2PHYDTM1, P2C_RG_SESSEND);
++ if (!index) {
++ /* Set RG_SSUSB_VUSB10_ON as 1 after VUSB10 ready */
++ u3p_clrmsk(sif_base, U3P_U3_PHYA_REG0, P3A_RG_U3_VUSB10_ON);
++ }
++ dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
++}
++
++
++static int check_ip_clk_status(struct mt65xx_u3phy *u3phy)
++{
++ int ret;
++ int u3_port_num;
++ int u2_port_num;
++ u32 xhci_cap;
++ u32 val;
++ void __iomem *sif_base = u3phy->sif_base;
++
++ xhci_cap = u3p_readl(sif_base, U3P_IP_XHCI_CAP);
++ u3_port_num = CAP_U3_PORT_NUM(xhci_cap);
++ u2_port_num = CAP_U2_PORT_NUM(xhci_cap);
++
++ ret = readl_poll_timeout(sif_base + U3P_IP_PW_STS1, val,
++ (val & STS1_SYSPLL_STABLE), 100, 10000);
++ if (ret) {
++ dev_err(u3phy->dev, "sypll is not stable!!!\n");
++ return ret;
++ }
++
++ ret = readl_poll_timeout(sif_base + U3P_IP_PW_STS1, val,
++ (val & STS1_REF_RST), 100, 10000);
++ if (ret) {
++ dev_err(u3phy->dev, "ref_clk is still active!!!\n");
++ return ret;
++ }
++
++ ret = readl_poll_timeout(sif_base + U3P_IP_PW_STS1, val,
++ (val & STS1_SYS125_RST), 100, 10000);
++ if (ret) {
++ dev_err(u3phy->dev, "sys125_ck is still active!!!\n");
++ return ret;
++ }
++
++ if (u3_port_num) {
++ ret = readl_poll_timeout(sif_base + U3P_IP_PW_STS1, val,
++ (val & STS1_U3_MAC_RST), 100, 10000);
++ if (ret) {
++ dev_err(u3phy->dev, "mac3_mac_ck is still active!!!\n");
++ return ret;
++ }
++ }
++
++ if (u2_port_num) {
++ ret = readl_poll_timeout(sif_base + U3P_IP_PW_STS2, val,
++ (val & STS2_U2_MAC_RST), 100, 10000);
++ if (ret) {
++ dev_err(u3phy->dev, "mac2_sys_ck is still active!!!\n");
++ return ret;
++ }
++ }
++
++ return 0;
++}
++
++static int u3phy_ports_enable(struct mt65xx_u3phy *u3phy)
++{
++ int i;
++ u32 temp;
++ int u3_port_num;
++ int u2_port_num;
++ void __iomem *sif_base = u3phy->sif_base;
++
++ temp = u3p_readl(sif_base, U3P_IP_XHCI_CAP);
++ u3_port_num = CAP_U3_PORT_NUM(temp);
++ u2_port_num = CAP_U2_PORT_NUM(temp);
++ dev_dbg(u3phy->dev, "%s u2p:%d, u3p:%d\n",
++ __func__, u2_port_num, u3_port_num);
++
++ /* power on host ip */
++ u3p_clrmsk(sif_base, U3P_IP_PW_CTRL1, CTRL1_IP_HOST_PDN);
++
++ /* power on and enable all u3 ports */
++ for (i = 0; i < u3_port_num; i++) {
++ temp = u3p_readl(sif_base, U3P_U3_CTRL(i));
++ temp &= ~(CTRL_U3_PORT_PDN | CTRL_U3_PORT_DIS);
++ temp |= CTRL_U3_PORT_HOST_SEL;
++ u3p_writel(sif_base, U3P_U3_CTRL(i), temp);
++ }
++
++ /* power on and enable all u2 ports */
++ for (i = 0; i < u2_port_num; i++) {
++ temp = u3p_readl(sif_base, U3P_U2_CTRL(i));
++ temp &= ~(CTRL_U2_PORT_PDN | CTRL_U2_PORT_DIS);
++ temp |= CTRL_U2_PORT_HOST_SEL;
++ u3p_writel(sif_base, U3P_U2_CTRL(i), temp);
++ }
++ return check_ip_clk_status(u3phy);
++}
++
++
++static void u3phy_timing_init(struct mt65xx_u3phy *u3phy)
++{
++ void __iomem *mbase = u3phy->mac_base;
++ int u3_port_num;
++ u32 temp;
++
++ temp = u3p_readl(u3phy->sif_base, U3P_IP_XHCI_CAP);
++ u3_port_num = CAP_U3_PORT_NUM(temp);
++
++ if (u3_port_num) {
++ /* set MAC reference clock speed */
++ u3p_setval(mbase, U3P_UX_EXIT_LFPS_PARAM,
++ RX_UX_EXIT_REF, RX_UX_EXIT_REF_VAL);
++ /* set REF_CLK */
++ u3p_setval(mbase, U3P_REF_CLK_PARAM,
++ REF_CLK_1000NS, REF_CLK_VAL_DEF);
++ /* set SYS_CLK */
++ u3p_setval(mbase, U3P_TIMING_PULSE_CTRL,
++ U3T_CNT_1US, U3T_CNT_1US_VAL);
++ /* set LINK_PM_TIMER=3 */
++ u3p_setval(mbase, U3P_LINK_PM_TIMER,
++ PM_LC_TIMEOUT, PM_LC_TIMEOUT_VAL);
++ }
++ u3p_setval(mbase, U3P_U2_TIMING_PARAM, U2T_VAL_1US, U2T_VAL_1US_VAL);
++}
++
++
++static int u3phy_clks_enable(struct mt65xx_u3phy *u3phy)
++{
++ int ret;
++
++ ret = clk_prepare_enable(u3phy->sys_mac);
++ if (ret) {
++ dev_err(u3phy->dev, "failed to enable sys_mac\n");
++ goto sys_mac_err;
++ }
++
++ ret = clk_prepare_enable(u3phy->u3phya_ref);
++ if (ret) {
++ dev_err(u3phy->dev, "failed to enable u3phya_ref\n");
++ goto u3phya_ref_err;
++ }
++ ret = clk_prepare_enable(u3phy->wk_deb_p0);
++ if (ret) {
++ dev_err(u3phy->dev, "failed to enable wk_deb_p0\n");
++ goto usb_p0_err;
++ }
++ if (u3phy->enable_usb2_p1) {
++ ret = clk_prepare_enable(u3phy->wk_deb_p1);
++ if (ret) {
++ dev_err(u3phy->dev, "failed to enable wk_deb_p1\n");
++ goto usb_p1_err;
++ }
++ }
++ udelay(50);
++
++ return 0;
++
++usb_p1_err:
++ clk_disable_unprepare(u3phy->wk_deb_p0);
++usb_p0_err:
++ clk_disable_unprepare(u3phy->u3phya_ref);
++u3phya_ref_err:
++ clk_disable_unprepare(u3phy->sys_mac);
++sys_mac_err:
++ return -EINVAL;
++}
++
++static void u3phy_clks_disable(struct mt65xx_u3phy *u3phy)
++{
++ if (u3phy->enable_usb2_p1)
++ clk_disable_unprepare(u3phy->wk_deb_p1);
++ clk_disable_unprepare(u3phy->wk_deb_p0);
++ clk_disable_unprepare(u3phy->u3phya_ref);
++ clk_disable_unprepare(u3phy->sys_mac);
++}
++
++
++static int mt65xx_u3phy_init(struct usb_phy *phy)
++{
++ struct mt65xx_u3phy *u3phy;
++ int ret;
++
++ u3phy = container_of(phy, struct mt65xx_u3phy, phy);
++ dev_dbg(u3phy->dev, "%s+\n", __func__);
++
++ if (u3phy->enable_usb2_p1) {
++ ret = regulator_enable(u3phy->p1_vbus);
++ if (ret) {
++ dev_err(u3phy->dev, "failed to enable p1-vbus\n");
++ goto reg_p1_err;
++ }
++ }
++
++ ret = regulator_enable(u3phy->vusb33);
++ if (ret) {
++ dev_err(u3phy->dev, "failed to enable vusb33\n");
++ goto reg_err;
++ }
++
++ ret = pm_runtime_get_sync(u3phy->dev);
++ if (ret < 0)
++ goto pm_err;
++
++ ret = u3phy_clks_enable(u3phy);
++ if (ret) {
++ dev_err(u3phy->dev, "failed to enable clks\n");
++ goto clks_err;
++ }
++
++ /* reset whole ip */
++ u3p_setmsk(u3phy->sif_base, U3P_IP_PW_CTRL0, CTRL0_IP_SW_RST);
++ u3p_clrmsk(u3phy->sif_base, U3P_IP_PW_CTRL0, CTRL0_IP_SW_RST);
++
++ ret = u3phy_ports_enable(u3phy);
++ if (ret) {
++ dev_err(u3phy->dev, "failed to enable ports\n");
++ goto port_err;
++ }
++ u3phy_timing_init(u3phy);
++ phy_index_power_on(u3phy, 0);
++ if (u3phy->enable_usb2_p1)
++ phy_index_power_on(u3phy, 1);
++
++ return 0;
++
++port_err:
++ u3phy_clks_disable(u3phy);
++clks_err:
++ pm_runtime_put_sync(u3phy->dev);
++pm_err:
++ regulator_disable(u3phy->vusb33);
++reg_err:
++ if (u3phy->enable_usb2_p1)
++ regulator_disable(u3phy->p1_vbus);
++reg_p1_err:
++ return ret;
++}
++
++
++static void mt65xx_u3phy_shutdown(struct usb_phy *phy)
++{
++ struct mt65xx_u3phy *u3phy;
++
++ u3phy = container_of(phy, struct mt65xx_u3phy, phy);
++ dev_dbg(u3phy->dev, "%s+\n", __func__);
++
++ phy_index_power_off(u3phy, 0);
++ if (u3phy->enable_usb2_p1) {
++ phy_index_power_off(u3phy, 1);
++ regulator_disable(u3phy->p1_vbus);
++ }
++ u3phy_clks_disable(u3phy);
++ pm_runtime_put_sync(u3phy->dev);
++ regulator_disable(u3phy->vusb33);
++}
++
++
++static int mt65xx_u3phy_suspend(struct usb_phy *x, int suspend)
++{
++ struct mt65xx_u3phy *u3phy = container_of(x, struct mt65xx_u3phy, phy);
++
++ if (suspend) {
++ mt65xx_u3phy_shutdown(&u3phy->phy);
++ return 0;
++ } else {
++ return mt65xx_u3phy_init(&u3phy->phy);
++ }
++}
++
++
++static const struct of_device_id mt65xx_u3phy_id_table[] = {
++ { .compatible = "mediatek,mt8173-u3phy",},
++ { },
++};
++MODULE_DEVICE_TABLE(of, mt65xx_u3phy_id_table);
++
++
++static int mt65xx_u3phy_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct device_node *np = dev->of_node;
++ struct resource *mac_res;
++ struct resource *sif_res;
++ struct mt65xx_u3phy *u3phy;
++ int retval = -ENOMEM;
++
++ u3phy = devm_kzalloc(&pdev->dev, sizeof(*u3phy), GFP_KERNEL);
++ if (!u3phy)
++ goto err;
++
++ u3phy->dev = &pdev->dev;
++
++ mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ u3phy->mac_base = devm_ioremap_resource(dev, mac_res);
++ if (IS_ERR(u3phy->mac_base)) {
++ dev_err(dev, "failed to remap mac regs\n");
++ retval = PTR_ERR(u3phy->mac_base);
++ goto err;
++ }
++
++ sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++ u3phy->sif_base = devm_ioremap_resource(dev, sif_res);
++ if (IS_ERR(u3phy->sif_base)) {
++ dev_err(dev, "failed to remap sif regs\n");
++ retval = PTR_ERR(u3phy->sif_base);
++ goto err;
++ }
++
++ u3phy->enable_usb2_p1 = !of_property_read_bool(np, "disable-usb2-p1");
++ dev_dbg(dev, "enable_usb2_p1 - %d\n", u3phy->enable_usb2_p1);
++
++ u3phy->sys_mac = devm_clk_get(u3phy->dev, "sys_mac");
++ if (IS_ERR(u3phy->sys_mac)) {
++ dev_err(dev, "error to get sys_mac\n");
++ retval = PTR_ERR(u3phy->sys_mac);
++ goto err;
++ }
++
++ u3phy->u3phya_ref = devm_clk_get(u3phy->dev, "u3phya_ref");
++ if (IS_ERR(u3phy->u3phya_ref)) {
++ dev_err(dev, "error to get u3phya_ref\n");
++ retval = PTR_ERR(u3phy->u3phya_ref);
++ goto err;
++ }
++
++ u3phy->wk_deb_p0 = devm_clk_get(u3phy->dev, "wakeup_deb_p0");
++ if (IS_ERR(u3phy->wk_deb_p0)) {
++ dev_err(dev, "error to get wakeup_deb_p0\n");
++ retval = PTR_ERR(u3phy->wk_deb_p0);
++ goto err;
++ }
++
++ if (u3phy->enable_usb2_p1) {
++ u3phy->wk_deb_p1 = devm_clk_get(u3phy->dev, "wakeup_deb_p1");
++ if (IS_ERR(u3phy->wk_deb_p1)) {
++ dev_err(dev, "error to get wakeup_deb_p1\n");
++ retval = PTR_ERR(u3phy->wk_deb_p1);
++ goto err;
++ }
++
++ u3phy->p1_vbus = devm_regulator_get(u3phy->dev, "reg-p1-vbus");
++ if (IS_ERR_OR_NULL(u3phy->p1_vbus)) {
++ dev_err(dev, "fail to get p1-vbus\n");
++ retval = PTR_ERR(u3phy->p1_vbus);
++ goto err;
++ }
++ }
++
++ u3phy->vusb33 = devm_regulator_get(u3phy->dev, "reg-vusb33");
++ if (IS_ERR_OR_NULL(u3phy->vusb33)) {
++ dev_err(dev, "fail to get vusb33\n");
++ retval = PTR_ERR(u3phy->vusb33);
++ goto err;
++ }
++
++ pm_runtime_enable(dev);
++ u3phy->phy.dev = u3phy->dev;
++ u3phy->phy.label = "mt65xx-usb3phy";
++ u3phy->phy.type = USB_PHY_TYPE_USB3;
++ u3phy->phy.init = mt65xx_u3phy_init;
++ u3phy->phy.shutdown = mt65xx_u3phy_shutdown;
++ u3phy->phy.set_suspend = mt65xx_u3phy_suspend;
++
++ platform_set_drvdata(pdev, u3phy);
++ retval = usb_add_phy_dev(&u3phy->phy);
++ if (retval) {
++ dev_err(dev, "failed to add phy\n");
++ goto add_phy_err;
++ }
++
++ return 0;
++
++add_phy_err:
++ pm_runtime_disable(dev);
++err:
++ return retval;
++}
++
++static int mt65xx_u3phy_remove(struct platform_device *pdev)
++{
++ struct mt65xx_u3phy *u3phy = platform_get_drvdata(pdev);
++
++ mt65xx_u3phy_shutdown(&u3phy->phy);
++ pm_runtime_disable(&pdev->dev);
++ usb_remove_phy(&u3phy->phy);
++
++ return 0;
++}
++
++static struct platform_driver mt65xx_u3phy_driver = {
++ .probe = mt65xx_u3phy_probe,
++ .remove = mt65xx_u3phy_remove,
++ .driver = {
++ .name = "mt65xx-u3phy",
++ .of_match_table = mt65xx_u3phy_id_table,
++ },
++};
++
++module_platform_driver(mt65xx_u3phy_driver);
++
++MODULE_DESCRIPTION("Mt65xx USB PHY driver");
++MODULE_LICENSE("GPL v2");
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0047-xhci-mediatek-support-MTK-xHCI-host-controller.patch b/target/linux/mediatek/patches/0047-xhci-mediatek-support-MTK-xHCI-host-controller.patch
new file mode 100644
index 0000000000..ea3289ed7e
--- /dev/null
+++ b/target/linux/mediatek/patches/0047-xhci-mediatek-support-MTK-xHCI-host-controller.patch
@@ -0,0 +1,832 @@
+From e604b6c864f2e3b6fe0706c4bef886533d92f67a Mon Sep 17 00:00:00 2001
+From: Chunfeng Yun <chunfeng.yun@mediatek.com>
+Date: Wed, 27 May 2015 19:48:02 +0800
+Subject: [PATCH 47/76] xhci: mediatek: support MTK xHCI host controller
+
+MTK xhci host controller defines some extra SW scheduling
+parameters for HW to minimize the scheduling effort for
+synchronous and interrupt endpoints. The parameters are
+put into reseved DWs of slot context and endpoint context.
+
+Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
+---
+ drivers/usb/host/Kconfig | 9 +
+ drivers/usb/host/Makefile | 3 +
+ drivers/usb/host/xhci-mtk.c | 470 ++++++++++++++++++++++++++++++++++++++++++
+ drivers/usb/host/xhci-mtk.h | 119 +++++++++++
+ drivers/usb/host/xhci-plat.c | 22 +-
+ drivers/usb/host/xhci-ring.c | 35 +++-
+ drivers/usb/host/xhci.c | 16 +-
+ drivers/usb/host/xhci.h | 1 +
+ 8 files changed, 667 insertions(+), 8 deletions(-)
+ create mode 100644 drivers/usb/host/xhci-mtk.c
+ create mode 100644 drivers/usb/host/xhci-mtk.h
+
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -41,6 +41,15 @@
+
+ If unsure, say N.
+
++config USB_XHCI_MTK
++ tristate "xHCI support for Mediatek MT65xx"
++ select USB_XHCI_PLATFORM
++ depends on ARCH_MEDIATEK || COMPILE_TEST
++ ---help---
++ Say 'Y' to enable the support for the xHCI host controller
++ found in Mediatek MT65xx SoCs.
++ If unsure, say N.
++
+ config USB_XHCI_MVEBU
+ tristate "xHCI support for Marvell Armada 375/38x"
+ select USB_XHCI_PLATFORM
+--- a/drivers/usb/host/Makefile
++++ b/drivers/usb/host/Makefile
+@@ -15,6 +15,9 @@
+ xhci-hcd-y += xhci-trace.o
+
+ xhci-plat-hcd-y := xhci-plat.o
++ifneq ($(CONFIG_USB_XHCI_MTK), )
++ xhci-plat-hcd-y += xhci-mtk.o
++endif
+ ifneq ($(CONFIG_USB_XHCI_MVEBU), )
+ xhci-plat-hcd-y += xhci-mvebu.o
+ endif
+--- /dev/null
++++ b/drivers/usb/host/xhci-mtk.c
+@@ -0,0 +1,470 @@
++/*
++ * Copyright (c) 2015 MediaTek Inc.
++ * Author:
++ * Zhigang.Wei <zhigang.wei@mediatek.com>
++ * Chunfeng.Yun <chunfeng.yun@mediatek.com>
++ *
++ * This software is licensed under the terms of the GNU General Public
++ * License version 2, as published by the Free Software Foundation, and
++ * may be copied, distributed, and modified under those terms.
++ *
++ * 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.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include "xhci-mtk.h"
++
++
++#define SS_BW_BOUNDARY 51000
++/* table 5-5. High-speed Isoc Transaction Limits in usb_20 spec */
++#define HS_BW_BOUNDARY 6144
++/* usb2 spec section11.18.1: at most 188 FS bytes per microframe */
++#define FS_PAYLOAD_MAX 188
++
++/* mtk scheduler bitmasks */
++#define EP_BPKTS(p) ((p) & 0x3f)
++#define EP_BCSCOUNT(p) (((p) & 0x7) << 8)
++#define EP_BBM(p) ((p) << 11)
++#define EP_BOFFSET(p) ((p) & 0x3fff)
++#define EP_BREPEAT(p) (((p) & 0x7fff) << 16)
++
++static int is_fs_or_ls(enum usb_device_speed speed)
++{
++ return speed == USB_SPEED_FULL || speed == USB_SPEED_LOW;
++}
++
++static int get_bw_index(struct xhci_hcd *xhci, struct usb_device *udev,
++ struct usb_host_endpoint *ep)
++{
++ int bw_index;
++ int port_id;
++ struct xhci_virt_device *virt_dev;
++
++ virt_dev = xhci->devs[udev->slot_id];
++ port_id = virt_dev->real_port;
++
++ if (udev->speed == USB_SPEED_SUPER) {
++ if (usb_endpoint_dir_out(&ep->desc))
++ bw_index = (port_id - 1) * 2;
++ else
++ bw_index = (port_id - 1) * 2 + 1;
++ } else {
++ bw_index = port_id + xhci->num_usb3_ports - 1;
++ }
++
++ return bw_index;
++}
++
++
++static void setup_sch_info(struct usb_device *udev,
++ struct xhci_ep_ctx *ep_ctx, struct mu3h_sch_ep_info *sch_ep)
++{
++ u32 ep_type;
++ u32 ep_interval;
++ u32 max_packet_size;
++ u32 max_burst;
++ u32 mult;
++ u32 esit_pkts;
++
++ ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2));
++ ep_interval = CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx->ep_info));
++ max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
++ max_burst = CTX_TO_MAX_BURST(le32_to_cpu(ep_ctx->ep_info2));
++ mult = CTX_TO_EP_MULT(le32_to_cpu(ep_ctx->ep_info));
++ pr_debug("%s: max_burst = %d, mult = %d\n", __func__, max_burst, mult);
++
++ sch_ep->ep_type = ep_type;
++ sch_ep->max_packet_size = max_packet_size;
++ sch_ep->esit = 1 << ep_interval;
++ sch_ep->offset = 0;
++ sch_ep->burst_mode = 0;
++
++ if (udev->speed == USB_SPEED_HIGH) {
++ sch_ep->cs_count = 0;
++ /*
++ * usb_20 spec section5.9
++ * a single microframe is enough for HS synchromous endpoints
++ * in a interval
++ */
++ sch_ep->num_budget_microframes = 1;
++ sch_ep->repeat = 0;
++ /*
++ * xHCI spec section6.2.3.4
++ * @max_busrt is the number of additional transactions opportunities
++ * per microframe
++ */
++ sch_ep->pkts = max_burst + 1;
++ sch_ep->bw_cost_per_microframe = max_packet_size * sch_ep->pkts;
++ } else if (udev->speed == USB_SPEED_SUPER) {
++ /* usb3_r1 spec section4.4.7 & 4.4.8 */
++ sch_ep->cs_count = 0;
++ esit_pkts = (mult + 1) * (max_burst + 1);
++ if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) {
++ sch_ep->pkts = esit_pkts;
++ sch_ep->num_budget_microframes = 1;
++ sch_ep->repeat = 0;
++ }
++
++ if (ep_type == ISOC_IN_EP || ep_type == ISOC_OUT_EP) {
++ if (esit_pkts <= sch_ep->esit)
++ sch_ep->pkts = 1;
++ else
++ sch_ep->pkts = roundup_pow_of_two(esit_pkts)
++ / sch_ep->esit;
++
++ sch_ep->num_budget_microframes =
++ DIV_ROUND_UP(esit_pkts, sch_ep->pkts);
++
++ if (sch_ep->num_budget_microframes > 1)
++ sch_ep->repeat = 1;
++ else
++ sch_ep->repeat = 0;
++ }
++ sch_ep->bw_cost_per_microframe = max_packet_size * sch_ep->pkts;
++ } else if (is_fs_or_ls(udev->speed)) {
++ /*
++ * usb_20 spec section11.18.4
++ * assume worst cases
++ */
++ sch_ep->repeat = 0;
++ sch_ep->pkts = 1; /* at most one packet for each microframe */
++ if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) {
++ sch_ep->cs_count = 3; /* at most need 3 CS*/
++ /* one for SS and one for budgeted transaction */
++ sch_ep->num_budget_microframes = sch_ep->cs_count + 2;
++ sch_ep->bw_cost_per_microframe = max_packet_size;
++ }
++ if (ep_type == ISOC_OUT_EP) {
++ /* must never schedule a cs ISOC OUT ep */
++ sch_ep->cs_count = 0;
++ /*
++ * the best case FS budget assumes that 188 FS bytes
++ * occur in each microframe
++ */
++ sch_ep->num_budget_microframes = DIV_ROUND_UP(
++ sch_ep->max_packet_size, FS_PAYLOAD_MAX);
++ sch_ep->bw_cost_per_microframe = FS_PAYLOAD_MAX;
++ }
++ if (ep_type == ISOC_IN_EP) {
++ /* at most need additional two CS. */
++ sch_ep->cs_count = DIV_ROUND_UP(
++ sch_ep->max_packet_size, FS_PAYLOAD_MAX) + 2;
++ sch_ep->num_budget_microframes = sch_ep->cs_count + 2;
++ sch_ep->bw_cost_per_microframe = FS_PAYLOAD_MAX;
++ }
++ }
++}
++
++/* Get maximum bandwidth when we schedule at offset slot. */
++static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,
++ struct mu3h_sch_ep_info *sch_ep, u32 offset)
++{
++ u32 num_esit;
++ u32 max_bw = 0;
++ int i;
++ int j;
++
++ num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
++ for (i = 0; i < num_esit; i++) {
++ u32 base = offset + i * sch_ep->esit;
++
++ for (j = 0; j < sch_ep->num_budget_microframes; j++) {
++ if (sch_bw->bus_bw[base + j] > max_bw)
++ max_bw = sch_bw->bus_bw[base + j];
++ }
++ }
++ return max_bw;
++}
++
++static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,
++ struct mu3h_sch_ep_info *sch_ep, int bw_cost)
++{
++ u32 num_esit;
++ u32 base;
++ int i;
++ int j;
++
++ num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
++ for (i = 0; i < num_esit; i++) {
++ base = sch_ep->offset + i * sch_ep->esit;
++ for (j = 0; j < sch_ep->num_budget_microframes; j++)
++ sch_bw->bus_bw[base + j] += bw_cost;
++ }
++
++}
++
++static void debug_sch_ep(struct mu3h_sch_ep_info *sch_ep)
++{
++ pr_debug("sch_ep->ep_type = %d\n", sch_ep->ep_type);
++ pr_debug("sch_ep->max_packet_size = %d\n", sch_ep->max_packet_size);
++ pr_debug("sch_ep->esit = %d\n", sch_ep->esit);
++ pr_debug("sch_ep->num_budget_microframes = %d\n",
++ sch_ep->num_budget_microframes);
++ pr_debug("sch_ep->bw_cost_per_microframe = %d\n",
++ sch_ep->bw_cost_per_microframe);
++ pr_debug("sch_ep->ep = %p\n", sch_ep->ep);
++ pr_debug("sch_ep->offset = %d\n", sch_ep->offset);
++ pr_debug("sch_ep->repeat = %d\n", sch_ep->repeat);
++ pr_debug("sch_ep->pkts = %d\n", sch_ep->pkts);
++ pr_debug("sch_ep->cs_count = %d\n", sch_ep->cs_count);
++}
++
++static int check_sch_bw(struct usb_device *udev,
++ struct mu3h_sch_bw_info *sch_bw, struct mu3h_sch_ep_info *sch_ep)
++{
++ u32 offset;
++ u32 esit;
++ u32 num_budget_microframes;
++ u32 min_bw;
++ u32 min_index;
++ u32 worst_bw;
++ u32 bw_boundary;
++
++ if (sch_ep->esit > XHCI_MTK_MAX_ESIT)
++ sch_ep->esit = XHCI_MTK_MAX_ESIT;
++
++ esit = sch_ep->esit;
++ num_budget_microframes = sch_ep->num_budget_microframes;
++
++ /*
++ * Search through all possible schedule microframes.
++ * and find a microframe where its worst bandwidth is minimum.
++ */
++ min_bw = ~0;
++ min_index = 0;
++ for (offset = 0; offset < esit; offset++) {
++ if ((offset + num_budget_microframes) > sch_ep->esit)
++ break;
++ /*
++ * usb_20 spec section11.18:
++ * must never schedule Start-Split in Y6
++ */
++ if (is_fs_or_ls(udev->speed) && (offset % 8 == 6))
++ continue;
++
++ worst_bw = get_max_bw(sch_bw, sch_ep, offset);
++ if (min_bw > worst_bw) {
++ min_bw = worst_bw;
++ min_index = offset;
++ }
++ if (min_bw == 0)
++ break;
++ }
++ sch_ep->offset = min_index;
++
++ debug_sch_ep(sch_ep);
++
++ bw_boundary = (udev->speed == USB_SPEED_SUPER)
++ ? SS_BW_BOUNDARY : HS_BW_BOUNDARY;
++
++ /* check bandwidth */
++ if (min_bw + sch_ep->bw_cost_per_microframe > bw_boundary)
++ return -1;
++
++ /* update bus bandwidth info */
++ update_bus_bw(sch_bw, sch_ep, sch_ep->bw_cost_per_microframe);
++
++ return 0;
++}
++
++static void debug_sch_bw(struct mu3h_sch_bw_info *sch_bw)
++{
++ int i;
++
++ pr_debug("xhci_mtk_scheduler :bus_bw_info\n");
++ for (i = 0; i < XHCI_MTK_MAX_ESIT; i++)
++ pr_debug("%d ", sch_bw->bus_bw[i]);
++
++ pr_debug("\n");
++}
++
++
++static int need_bw_sch(struct usb_host_endpoint *ep,
++ enum usb_device_speed speed, int has_tt)
++{
++ /* only for synchronous endpoints */
++ if (usb_endpoint_xfer_control(&ep->desc)
++ || usb_endpoint_xfer_bulk(&ep->desc))
++ return 0;
++ /*
++ * for LS & FS synchronous endpoints which its device don't attach
++ * to TT are also ignored, root-hub will schedule them directly
++ */
++ if (is_fs_or_ls(speed) && !has_tt)
++ return 0;
++
++ return 1;
++}
++
++int xhci_mtk_init_quirk(struct xhci_hcd *xhci)
++{
++ struct usb_hcd *hcd = xhci_to_hcd(xhci);
++ struct device *dev = hcd->self.controller;
++ struct mu3h_sch_bw_info *sch_array;
++ size_t array_size;
++ int num_usb_bus;
++ int i;
++
++ /* ss IN and OUT are separated */
++ num_usb_bus = xhci->num_usb3_ports * 2 + xhci->num_usb2_ports;
++ array_size = sizeof(*sch_array) * num_usb_bus;
++
++ sch_array = kzalloc(array_size, GFP_KERNEL);
++ if (sch_array == NULL)
++ return -ENOMEM;
++
++ for (i = 0; i < num_usb_bus; i++)
++ INIT_LIST_HEAD(&sch_array[i].bw_ep_list);
++
++ dev->platform_data = sch_array;
++ xhci->quirks |= XHCI_MTK_HOST;
++ /*
++ * MTK host controller gives a spurious successful event after a
++ * short transfer. Ignore it.
++ */
++ xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
++
++ return 0;
++}
++
++
++void xhci_mtk_exit_quirk(struct xhci_hcd *xhci)
++{
++ struct usb_hcd *hcd = xhci_to_hcd(xhci);
++ struct mu3h_sch_bw_info *sch_array;
++
++ sch_array = dev_get_platdata(hcd->self.controller);
++ kfree(sch_array);
++}
++
++
++int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
++ struct usb_host_endpoint *ep)
++{
++ int ret = 0;
++ int port_id;
++ int bw_index;
++ struct xhci_hcd *xhci;
++ unsigned int ep_index;
++ struct xhci_ep_ctx *ep_ctx;
++ struct xhci_slot_ctx *slot_ctx;
++ struct xhci_virt_device *virt_dev;
++ struct mu3h_sch_bw_info *sch_bw;
++ struct mu3h_sch_ep_info *sch_ep;
++ struct mu3h_sch_bw_info *sch_array;
++
++ xhci = hcd_to_xhci(hcd);
++ virt_dev = xhci->devs[udev->slot_id];
++ ep_index = xhci_get_endpoint_index(&ep->desc);
++ slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
++ ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
++ sch_array = dev_get_platdata(hcd->self.controller);
++
++ port_id = virt_dev->real_port;
++ xhci_dbg(xhci, "%s() xfer_type: %d, speed:%d, ep:%p\n", __func__,
++ usb_endpoint_type(&ep->desc), udev->speed, ep);
++
++ if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT))
++ return 0;
++
++ bw_index = get_bw_index(xhci, udev, ep);
++ sch_bw = &sch_array[bw_index];
++
++ sch_ep = kzalloc(sizeof(struct mu3h_sch_ep_info), GFP_KERNEL);
++ if (!sch_ep)
++ return -ENOMEM;
++
++ setup_sch_info(udev, ep_ctx, sch_ep);
++
++ ret = check_sch_bw(udev, sch_bw, sch_ep);
++ if (ret) {
++ xhci_err(xhci, "Not enough bandwidth!\n");
++ kfree(sch_ep);
++ return -ENOSPC;
++ }
++
++ list_add_tail(&sch_ep->endpoint, &sch_bw->bw_ep_list);
++ sch_ep->ep = ep;
++
++ ep_ctx->reserved[0] |= cpu_to_le32(EP_BPKTS(sch_ep->pkts)
++ | EP_BCSCOUNT(sch_ep->cs_count) | EP_BBM(sch_ep->burst_mode));
++ ep_ctx->reserved[1] |= cpu_to_le32(EP_BOFFSET(sch_ep->offset)
++ | EP_BREPEAT(sch_ep->repeat));
++
++ debug_sch_bw(sch_bw);
++ return 0;
++}
++
++void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
++ struct usb_host_endpoint *ep)
++{
++ int bw_index;
++ struct xhci_hcd *xhci;
++ struct xhci_slot_ctx *slot_ctx;
++ struct xhci_virt_device *virt_dev;
++ struct mu3h_sch_bw_info *sch_array;
++ struct mu3h_sch_bw_info *sch_bw;
++ struct mu3h_sch_ep_info *sch_ep;
++
++ xhci = hcd_to_xhci(hcd);
++ virt_dev = xhci->devs[udev->slot_id];
++ slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
++ sch_array = dev_get_platdata(hcd->self.controller);
++
++ xhci_dbg(xhci, "%s() xfer_type: %d, speed:%d, ep:%p\n", __func__,
++ usb_endpoint_type(&ep->desc), udev->speed, ep);
++
++ if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT))
++ return;
++
++ bw_index = get_bw_index(xhci, udev, ep);
++ sch_bw = &sch_array[bw_index];
++
++ list_for_each_entry(sch_ep, &sch_bw->bw_ep_list, endpoint) {
++ if (sch_ep->ep == ep) {
++ update_bus_bw(sch_bw, sch_ep,
++ -sch_ep->bw_cost_per_microframe);
++ list_del(&sch_ep->endpoint);
++ kfree(sch_ep);
++ break;
++ }
++ }
++ debug_sch_bw(sch_bw);
++}
++
++
++/*
++ * The TD size is the number of bytes remaining in the TD (including this TRB),
++ * right shifted by 10.
++ * It must fit in bits 21:17, so it can't be bigger than 31.
++ */
++u32 xhci_mtk_td_remainder_quirk(unsigned int td_running_total,
++ unsigned trb_buffer_length, struct urb *urb)
++{
++ u32 max = 31;
++ int remainder, td_packet_count, packet_transferred;
++ unsigned int td_transfer_size = urb->transfer_buffer_length;
++ unsigned int maxp;
++
++ maxp = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
++
++ /* 0 for the last TRB */
++ if (td_running_total + trb_buffer_length == td_transfer_size)
++ return 0;
++
++ packet_transferred = td_running_total / maxp;
++ td_packet_count = DIV_ROUND_UP(td_transfer_size, maxp);
++ remainder = td_packet_count - packet_transferred;
++
++ if (remainder > max)
++ return max << 17;
++ else
++ return remainder << 17;
++}
++
++
+--- /dev/null
++++ b/drivers/usb/host/xhci-mtk.h
+@@ -0,0 +1,119 @@
++/*
++ * Copyright (c) 2015 MediaTek Inc.
++ * Author:
++ * Zhigang.Wun <zhigang.wei@mediatek.com>
++ * Chunfeng.Yun <chunfeng.yun@mediatek.com>
++ *
++ * This software is licensed under the terms of the GNU General Public
++ * License version 2, as published by the Free Software Foundation, and
++ * may be copied, distributed, and modified under those terms.
++ *
++ * 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.
++ *
++ */
++
++#ifndef _XHCI_MTK_H_
++#define _XHCI_MTK_H_
++
++#include "xhci.h"
++
++/**
++ * To simplify scheduler algorithm, set a upper limit for ESIT,
++ * if a synchromous ep's ESIT is larger than @XHCI_MTK_MAX_ESIT,
++ * round down to the limit value, that means allocating more
++ * bandwidth to it.
++ */
++#define XHCI_MTK_MAX_ESIT 64
++
++/**
++ * struct mu3h_sch_bw_info
++ * @bus_bw: array to keep track of bandwidth already used at each uframes
++ * @bw_ep_list: eps in the bandwidth domain
++ *
++ * treat a HS root port as a bandwidth domain, but treat a SS root port as
++ * two bandwidth domains, one for IN eps and another for OUT eps.
++ */
++struct mu3h_sch_bw_info {
++ u32 bus_bw[XHCI_MTK_MAX_ESIT];
++ struct list_head bw_ep_list;
++};
++
++/**
++ * struct mu3h_sch_ep_info
++ * @esit: unit is 125us, equal to 2 << Interval field in ep-context
++ * @num_budget_microframes: number of continuous uframes
++ * (@repeat==1) scheduled within the interval
++ * @ep: address of usb_host_endpoint
++ * @offset: which uframe of the interval that transfer should be
++ * scheduled first time within the interval
++ * @repeat: the time gap between two uframes that transfers are
++ * scheduled within a interval. in the simple algorithm, only
++ * assign 0 or 1 to it; 0 means using only one uframe in a
++ * interval, and1 means using @num_budget_microframes
++ * continuous uframes
++ * @pkts: number of packets to be transferred in the scheduled uframes
++ * @cs_count: number of CS that host will trigger
++ */
++struct mu3h_sch_ep_info {
++ u32 ep_type;
++ u32 max_packet_size;
++ u32 esit;
++ u32 num_budget_microframes;
++ u32 bw_cost_per_microframe;
++ void *ep;
++ struct list_head endpoint;
++
++ /* mtk xhci scheduling info */
++ u32 offset;
++ u32 repeat;
++ u32 pkts;
++ u32 cs_count;
++ u32 burst_mode;
++};
++
++
++#if IS_ENABLED(CONFIG_USB_XHCI_MTK)
++
++int xhci_mtk_init_quirk(struct xhci_hcd *xhci);
++void xhci_mtk_exit_quirk(struct xhci_hcd *xhci);
++int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
++ struct usb_host_endpoint *ep);
++void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
++ struct usb_host_endpoint *ep);
++u32 xhci_mtk_td_remainder_quirk(unsigned int td_running_total,
++ unsigned trb_buffer_length, struct urb *urb);
++
++#else
++static inline int xhci_mtk_init_quirk(struct xhci_hcd *xhci)
++{
++ return 0;
++}
++
++static inline void xhci_mtk_exit_quirk(struct xhci_hcd *xhci)
++{
++}
++
++static inline int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd,
++ struct usb_device *udev, struct usb_host_endpoint *ep)
++{
++ return 0;
++}
++
++static inline void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd,
++ struct usb_device *udev, struct usb_host_endpoint *ep)
++{
++ return 0;
++}
++
++static inline u32 xhci_mtk_td_remainder_quirk(unsigned int td_running_total,
++ unsigned trb_buffer_length, struct urb *urb)
++{
++ return 0;
++}
++
++#endif
++
++#endif /* _XHCI_MTK_H_ */
+--- a/drivers/usb/host/xhci-plat.c
++++ b/drivers/usb/host/xhci-plat.c
+@@ -23,6 +23,7 @@
+ #include "xhci.h"
+ #include "xhci-mvebu.h"
+ #include "xhci-rcar.h"
++#include "xhci-mtk.h"
+
+ static struct hc_driver __read_mostly xhci_plat_hc_driver;
+
+@@ -49,7 +50,23 @@
+ return ret;
+ }
+
+- return xhci_gen_setup(hcd, xhci_plat_quirks);
++ ret = xhci_gen_setup(hcd, xhci_plat_quirks);
++ if (ret)
++ return ret;
++
++ if (of_device_is_compatible(of_node, "mediatek,mt8173-xhci")) {
++ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
++
++ if (!usb_hcd_is_primary_hcd(hcd))
++ return 0;
++ ret = xhci_mtk_init_quirk(xhci);
++ if (ret) {
++ kfree(xhci);
++ return ret;
++ }
++ }
++
++ return ret;
+ }
+
+ static int xhci_plat_start(struct usb_hcd *hcd)
+@@ -207,6 +224,8 @@
+ if (!IS_ERR(clk))
+ clk_disable_unprepare(clk);
+ usb_put_hcd(hcd);
++ if (xhci->quirks & XHCI_MTK_HOST)
++ xhci_mtk_exit_quirk(xhci);
+ kfree(xhci);
+
+ return 0;
+@@ -253,6 +272,7 @@
+ { .compatible = "marvell,armada-380-xhci"},
+ { .compatible = "renesas,xhci-r8a7790"},
+ { .compatible = "renesas,xhci-r8a7791"},
++ { .compatible = "mediatek,mt8173-xhci"},
+ { },
+ };
+ MODULE_DEVICE_TABLE(of, usb_xhci_of_match);
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -68,6 +68,7 @@
+ #include <linux/slab.h>
+ #include "xhci.h"
+ #include "xhci-trace.h"
++#include "xhci-mtk.h"
+
+ /*
+ * Returns zero if the TRB isn't in this segment, otherwise it returns the DMA
+@@ -3163,9 +3164,14 @@
+
+ /* Set the TRB length, TD size, and interrupter fields. */
+ if (xhci->hci_version < 0x100) {
+- remainder = xhci_td_remainder(
++ if (xhci->quirks & XHCI_MTK_HOST) {
++ remainder = xhci_mtk_td_remainder_quirk(
++ running_total, trb_buff_len, urb);
++ } else {
++ remainder = xhci_td_remainder(
+ urb->transfer_buffer_length -
+ running_total);
++ }
+ } else {
+ remainder = xhci_v1_0_td_remainder(running_total,
+ trb_buff_len, total_packet_count, urb,
+@@ -3336,9 +3342,14 @@
+
+ /* Set the TRB length, TD size, and interrupter fields. */
+ if (xhci->hci_version < 0x100) {
+- remainder = xhci_td_remainder(
++ if (xhci->quirks & XHCI_MTK_HOST) {
++ remainder = xhci_mtk_td_remainder_quirk(
++ running_total, trb_buff_len, urb);
++ } else {
++ remainder = xhci_td_remainder(
+ urb->transfer_buffer_length -
+ running_total);
++ }
+ } else {
+ remainder = xhci_v1_0_td_remainder(running_total,
+ trb_buff_len, total_packet_count, urb,
+@@ -3457,8 +3468,14 @@
+ field = TRB_TYPE(TRB_DATA);
+
+ length_field = TRB_LEN(urb->transfer_buffer_length) |
+- xhci_td_remainder(urb->transfer_buffer_length) |
+ TRB_INTR_TARGET(0);
++
++ if (xhci->quirks & XHCI_MTK_HOST)
++ length_field |= xhci_mtk_td_remainder_quirk(0,
++ urb->transfer_buffer_length, urb);
++ else
++ length_field |= xhci_td_remainder(urb->transfer_buffer_length);
++
+ if (urb->transfer_buffer_length > 0) {
+ if (setup->bRequestType & USB_DIR_IN)
+ field |= TRB_DIR_IN;
+@@ -3682,8 +3699,14 @@
+
+ /* Set the TRB length, TD size, & interrupter fields. */
+ if (xhci->hci_version < 0x100) {
+- remainder = xhci_td_remainder(
+- td_len - running_total);
++ if (xhci->quirks & XHCI_MTK_HOST) {
++ remainder = xhci_mtk_td_remainder_quirk(
++ running_total, trb_buff_len,
++ urb);
++ } else {
++ remainder = xhci_td_remainder(
++ td_len - running_total);
++ }
+ } else {
+ remainder = xhci_v1_0_td_remainder(
+ running_total, trb_buff_len,
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -31,6 +31,7 @@
+
+ #include "xhci.h"
+ #include "xhci-trace.h"
++#include "xhci-mtk.h"
+
+ #define DRIVER_AUTHOR "Sarah Sharp"
+ #define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver"
+@@ -624,7 +625,11 @@
+ "// Set the interrupt modulation register");
+ temp = readl(&xhci->ir_set->irq_control);
+ temp &= ~ER_IRQ_INTERVAL_MASK;
+- temp |= (u32) 160;
++ /*
++ * the increment interval is 8 times as much as that defined
++ * in xHCI spec on MTK's controller
++ */
++ temp |= (u32) ((xhci->quirks & XHCI_MTK_HOST) ? 20 : 160);
+ writel(temp, &xhci->ir_set->irq_control);
+
+ /* Set the HCD state before we enable the irqs */
+@@ -1698,6 +1703,9 @@
+
+ xhci_endpoint_zero(xhci, xhci->devs[udev->slot_id], ep);
+
++ if (xhci->quirks & XHCI_MTK_HOST)
++ xhci_mtk_drop_ep_quirk(hcd, udev, ep);
++
+ xhci_dbg(xhci, "drop ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x\n",
+ (unsigned int) ep->desc.bEndpointAddress,
+ udev->slot_id,
+@@ -1793,6 +1801,12 @@
+ return -ENOMEM;
+ }
+
++ if (xhci->quirks & XHCI_MTK_HOST) {
++ ret = xhci_mtk_add_ep_quirk(hcd, udev, ep);
++ if (ret < 0)
++ return ret;
++ }
++
+ ctrl_ctx->add_flags |= cpu_to_le32(added_ctxs);
+ new_add_flags = le32_to_cpu(ctrl_ctx->add_flags);
+
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1568,6 +1568,7 @@
+ /* For controllers with a broken beyond repair streams implementation */
+ #define XHCI_BROKEN_STREAMS (1 << 19)
+ #define XHCI_PME_STUCK_QUIRK (1 << 20)
++#define XHCI_MTK_HOST (1 << 21)
+ unsigned int num_active_eps;
+ unsigned int limit_active_eps;
+ /* There are two roothubs to keep track of bus suspend info for */
diff --git a/target/linux/mediatek/patches/0048-dt-bindings-mediatek-Modify-pinctrl-bindings-for-mt6.patch b/target/linux/mediatek/patches/0048-dt-bindings-mediatek-Modify-pinctrl-bindings-for-mt6.patch
new file mode 100644
index 0000000000..40303c0e92
--- /dev/null
+++ b/target/linux/mediatek/patches/0048-dt-bindings-mediatek-Modify-pinctrl-bindings-for-mt6.patch
@@ -0,0 +1,46 @@
+From 69b78182d6d7777153323abe3cff8e533ca01143 Mon Sep 17 00:00:00 2001
+From: Hongzhou Yang <hongzhou.yang@mediatek.com>
+Date: Mon, 18 May 2015 23:11:12 -0700
+Subject: [PATCH 48/76] dt-bindings: mediatek: Modify pinctrl bindings for
+ mt6397.
+
+Since 6397 is no need to support interrupt controller,
+moving interrupt controller relate property to optional list.
+Also adding mt8173 and mt8127 to bindings.
+
+Signed-off-by: Hongzhou Yang <hongzhou.yang@mediatek.com>
+---
+ Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt
+index 5868a0f..0480bc3 100644
+--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt
++++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt
+@@ -3,9 +3,11 @@
+ The Mediatek's Pin controller is used to control SoC pins.
+
+ Required properties:
+-- compatible: value should be either of the following.
++- compatible: value should be one of the following.
+ (a) "mediatek,mt8135-pinctrl", compatible with mt8135 pinctrl.
+-- mediatek,pctl-regmap: Should be a phandle of the syscfg node.
++ (b) "mediatek,mt8173-pinctrl", compatible with mt8173 pinctrl.
++ (c) "mediatek,mt6397-pinctrl", compatible with mt6397 pinctrl.
++ (d) "mediatek,mt8127-pinctrl", compatible with mt8127 pinctrl.
+ - pins-are-numbered: Specify the subnodes are using numbered pinmux to
+ specify pins.
+ - gpio-controller : Marks the device node as a gpio controller.
+@@ -24,6 +26,9 @@ Required properties:
+ Only the following flags are supported:
+ 0 - GPIO_ACTIVE_HIGH
+ 1 - GPIO_ACTIVE_LOW
++
++Optional properties:
++- mediatek,pctl-regmap: Should be a phandle of the syscfg node.
+ - reg: physicall address base for EINT registers
+ - interrupt-controller: Marks the device node as an interrupt controller
+ - #interrupt-cells: Should be two.
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0049-pinctrl-dt-bindings-mt6397-Add-pinfunc-header-file-f.patch b/target/linux/mediatek/patches/0049-pinctrl-dt-bindings-mt6397-Add-pinfunc-header-file-f.patch
new file mode 100644
index 0000000000..8178761677
--- /dev/null
+++ b/target/linux/mediatek/patches/0049-pinctrl-dt-bindings-mt6397-Add-pinfunc-header-file-f.patch
@@ -0,0 +1,279 @@
+From 54596fafa4ce2723314d0381c7c1a525bda148ef Mon Sep 17 00:00:00 2001
+From: Hongzhou Yang <hongzhou.yang@mediatek.com>
+Date: Mon, 18 May 2015 23:11:13 -0700
+Subject: [PATCH 49/76] pinctrl: dt bindings: mt6397: Add pinfunc header file
+ for mt6397.
+
+Add pinfunc header file, mt8135/mt8173 relate dts will include it.
+
+Signed-off-by: Hongzhou Yang <hongzhou.yang@mediatek.com>
+---
+ include/dt-bindings/pinctrl/mt6397-pinfunc.h | 256 ++++++++++++++++++++++++++
+ 1 file changed, 256 insertions(+)
+ create mode 100644 include/dt-bindings/pinctrl/mt6397-pinfunc.h
+
+diff --git a/include/dt-bindings/pinctrl/mt6397-pinfunc.h b/include/dt-bindings/pinctrl/mt6397-pinfunc.h
+new file mode 100644
+index 0000000..85739b3
+--- /dev/null
++++ b/include/dt-bindings/pinctrl/mt6397-pinfunc.h
+@@ -0,0 +1,256 @@
++#ifndef __DTS_MT6397_PINFUNC_H
++#define __DTS_MT6397_PINFUNC_H
++
++#include <dt-bindings/pinctrl/mt65xx.h>
++
++#define MT6397_PIN_0_INT__FUNC_GPIO0 (MTK_PIN_NO(0) | 0)
++#define MT6397_PIN_0_INT__FUNC_INT (MTK_PIN_NO(0) | 1)
++
++#define MT6397_PIN_1_SRCVOLTEN__FUNC_GPIO1 (MTK_PIN_NO(1) | 0)
++#define MT6397_PIN_1_SRCVOLTEN__FUNC_SRCVOLTEN (MTK_PIN_NO(1) | 1)
++#define MT6397_PIN_1_SRCVOLTEN__FUNC_TEST_CK1 (MTK_PIN_NO(1) | 6)
++
++#define MT6397_PIN_2_SRCLKEN_PERI__FUNC_GPIO2 (MTK_PIN_NO(2) | 0)
++#define MT6397_PIN_2_SRCLKEN_PERI__FUNC_SRCLKEN_PERI (MTK_PIN_NO(2) | 1)
++#define MT6397_PIN_2_SRCLKEN_PERI__FUNC_TEST_CK2 (MTK_PIN_NO(2) | 6)
++
++#define MT6397_PIN_3_RTC_32K1V8__FUNC_GPIO3 (MTK_PIN_NO(3) | 0)
++#define MT6397_PIN_3_RTC_32K1V8__FUNC_RTC_32K1V8 (MTK_PIN_NO(3) | 1)
++#define MT6397_PIN_3_RTC_32K1V8__FUNC_TEST_CK3 (MTK_PIN_NO(3) | 6)
++
++#define MT6397_PIN_4_WRAP_EVENT__FUNC_GPIO4 (MTK_PIN_NO(4) | 0)
++#define MT6397_PIN_4_WRAP_EVENT__FUNC_WRAP_EVENT (MTK_PIN_NO(4) | 1)
++
++#define MT6397_PIN_5_SPI_CLK__FUNC_GPIO5 (MTK_PIN_NO(5) | 0)
++#define MT6397_PIN_5_SPI_CLK__FUNC_SPI_CLK (MTK_PIN_NO(5) | 1)
++
++#define MT6397_PIN_6_SPI_CSN__FUNC_GPIO6 (MTK_PIN_NO(6) | 0)
++#define MT6397_PIN_6_SPI_CSN__FUNC_SPI_CSN (MTK_PIN_NO(6) | 1)
++
++#define MT6397_PIN_7_SPI_MOSI__FUNC_GPIO7 (MTK_PIN_NO(7) | 0)
++#define MT6397_PIN_7_SPI_MOSI__FUNC_SPI_MOSI (MTK_PIN_NO(7) | 1)
++
++#define MT6397_PIN_8_SPI_MISO__FUNC_GPIO8 (MTK_PIN_NO(8) | 0)
++#define MT6397_PIN_8_SPI_MISO__FUNC_SPI_MISO (MTK_PIN_NO(8) | 1)
++
++#define MT6397_PIN_9_AUD_CLK_MOSI__FUNC_GPIO9 (MTK_PIN_NO(9) | 0)
++#define MT6397_PIN_9_AUD_CLK_MOSI__FUNC_AUD_CLK (MTK_PIN_NO(9) | 1)
++#define MT6397_PIN_9_AUD_CLK_MOSI__FUNC_TEST_IN0 (MTK_PIN_NO(9) | 6)
++#define MT6397_PIN_9_AUD_CLK_MOSI__FUNC_TEST_OUT0 (MTK_PIN_NO(9) | 7)
++
++#define MT6397_PIN_10_AUD_DAT_MISO__FUNC_GPIO10 (MTK_PIN_NO(10) | 0)
++#define MT6397_PIN_10_AUD_DAT_MISO__FUNC_AUD_MISO (MTK_PIN_NO(10) | 1)
++#define MT6397_PIN_10_AUD_DAT_MISO__FUNC_TEST_IN1 (MTK_PIN_NO(10) | 6)
++#define MT6397_PIN_10_AUD_DAT_MISO__FUNC_TEST_OUT1 (MTK_PIN_NO(10) | 7)
++
++#define MT6397_PIN_11_AUD_DAT_MOSI__FUNC_GPIO11 (MTK_PIN_NO(11) | 0)
++#define MT6397_PIN_11_AUD_DAT_MOSI__FUNC_AUD_MOSI (MTK_PIN_NO(11) | 1)
++#define MT6397_PIN_11_AUD_DAT_MOSI__FUNC_TEST_IN2 (MTK_PIN_NO(11) | 6)
++#define MT6397_PIN_11_AUD_DAT_MOSI__FUNC_TEST_OUT2 (MTK_PIN_NO(11) | 7)
++
++#define MT6397_PIN_12_COL0__FUNC_GPIO12 (MTK_PIN_NO(12) | 0)
++#define MT6397_PIN_12_COL0__FUNC_COL0_USBDL (MTK_PIN_NO(12) | 1)
++#define MT6397_PIN_12_COL0__FUNC_EINT10_1X (MTK_PIN_NO(12) | 2)
++#define MT6397_PIN_12_COL0__FUNC_PWM1_3X (MTK_PIN_NO(12) | 3)
++#define MT6397_PIN_12_COL0__FUNC_TEST_IN3 (MTK_PIN_NO(12) | 6)
++#define MT6397_PIN_12_COL0__FUNC_TEST_OUT3 (MTK_PIN_NO(12) | 7)
++
++#define MT6397_PIN_13_COL1__FUNC_GPIO13 (MTK_PIN_NO(13) | 0)
++#define MT6397_PIN_13_COL1__FUNC_COL1 (MTK_PIN_NO(13) | 1)
++#define MT6397_PIN_13_COL1__FUNC_EINT11_1X (MTK_PIN_NO(13) | 2)
++#define MT6397_PIN_13_COL1__FUNC_SCL0_2X (MTK_PIN_NO(13) | 3)
++#define MT6397_PIN_13_COL1__FUNC_TEST_IN4 (MTK_PIN_NO(13) | 6)
++#define MT6397_PIN_13_COL1__FUNC_TEST_OUT4 (MTK_PIN_NO(13) | 7)
++
++#define MT6397_PIN_14_COL2__FUNC_GPIO14 (MTK_PIN_NO(14) | 0)
++#define MT6397_PIN_14_COL2__FUNC_COL2 (MTK_PIN_NO(14) | 1)
++#define MT6397_PIN_14_COL2__FUNC_EINT12_1X (MTK_PIN_NO(14) | 2)
++#define MT6397_PIN_14_COL2__FUNC_SDA0_2X (MTK_PIN_NO(14) | 3)
++#define MT6397_PIN_14_COL2__FUNC_TEST_IN5 (MTK_PIN_NO(14) | 6)
++#define MT6397_PIN_14_COL2__FUNC_TEST_OUT5 (MTK_PIN_NO(14) | 7)
++
++#define MT6397_PIN_15_COL3__FUNC_GPIO15 (MTK_PIN_NO(15) | 0)
++#define MT6397_PIN_15_COL3__FUNC_COL3 (MTK_PIN_NO(15) | 1)
++#define MT6397_PIN_15_COL3__FUNC_EINT13_1X (MTK_PIN_NO(15) | 2)
++#define MT6397_PIN_15_COL3__FUNC_SCL1_2X (MTK_PIN_NO(15) | 3)
++#define MT6397_PIN_15_COL3__FUNC_TEST_IN6 (MTK_PIN_NO(15) | 6)
++#define MT6397_PIN_15_COL3__FUNC_TEST_OUT6 (MTK_PIN_NO(15) | 7)
++
++#define MT6397_PIN_16_COL4__FUNC_GPIO16 (MTK_PIN_NO(16) | 0)
++#define MT6397_PIN_16_COL4__FUNC_COL4 (MTK_PIN_NO(16) | 1)
++#define MT6397_PIN_16_COL4__FUNC_EINT14_1X (MTK_PIN_NO(16) | 2)
++#define MT6397_PIN_16_COL4__FUNC_SDA1_2X (MTK_PIN_NO(16) | 3)
++#define MT6397_PIN_16_COL4__FUNC_TEST_IN7 (MTK_PIN_NO(16) | 6)
++#define MT6397_PIN_16_COL4__FUNC_TEST_OUT7 (MTK_PIN_NO(16) | 7)
++
++#define MT6397_PIN_17_COL5__FUNC_GPIO17 (MTK_PIN_NO(17) | 0)
++#define MT6397_PIN_17_COL5__FUNC_COL5 (MTK_PIN_NO(17) | 1)
++#define MT6397_PIN_17_COL5__FUNC_EINT15_1X (MTK_PIN_NO(17) | 2)
++#define MT6397_PIN_17_COL5__FUNC_SCL2_2X (MTK_PIN_NO(17) | 3)
++#define MT6397_PIN_17_COL5__FUNC_TEST_IN8 (MTK_PIN_NO(17) | 6)
++#define MT6397_PIN_17_COL5__FUNC_TEST_OUT8 (MTK_PIN_NO(17) | 7)
++
++#define MT6397_PIN_18_COL6__FUNC_GPIO18 (MTK_PIN_NO(18) | 0)
++#define MT6397_PIN_18_COL6__FUNC_COL6 (MTK_PIN_NO(18) | 1)
++#define MT6397_PIN_18_COL6__FUNC_EINT16_1X (MTK_PIN_NO(18) | 2)
++#define MT6397_PIN_18_COL6__FUNC_SDA2_2X (MTK_PIN_NO(18) | 3)
++#define MT6397_PIN_18_COL6__FUNC_GPIO32K_0 (MTK_PIN_NO(18) | 4)
++#define MT6397_PIN_18_COL6__FUNC_GPIO26M_0 (MTK_PIN_NO(18) | 5)
++#define MT6397_PIN_18_COL6__FUNC_TEST_IN9 (MTK_PIN_NO(18) | 6)
++#define MT6397_PIN_18_COL6__FUNC_TEST_OUT9 (MTK_PIN_NO(18) | 7)
++
++#define MT6397_PIN_19_COL7__FUNC_GPIO19 (MTK_PIN_NO(19) | 0)
++#define MT6397_PIN_19_COL7__FUNC_COL7 (MTK_PIN_NO(19) | 1)
++#define MT6397_PIN_19_COL7__FUNC_EINT17_1X (MTK_PIN_NO(19) | 2)
++#define MT6397_PIN_19_COL7__FUNC_PWM2_3X (MTK_PIN_NO(19) | 3)
++#define MT6397_PIN_19_COL7__FUNC_GPIO32K_1 (MTK_PIN_NO(19) | 4)
++#define MT6397_PIN_19_COL7__FUNC_GPIO26M_1 (MTK_PIN_NO(19) | 5)
++#define MT6397_PIN_19_COL7__FUNC_TEST_IN10 (MTK_PIN_NO(19) | 6)
++#define MT6397_PIN_19_COL7__FUNC_TEST_OUT10 (MTK_PIN_NO(19) | 7)
++
++#define MT6397_PIN_20_ROW0__FUNC_GPIO20 (MTK_PIN_NO(20) | 0)
++#define MT6397_PIN_20_ROW0__FUNC_ROW0 (MTK_PIN_NO(20) | 1)
++#define MT6397_PIN_20_ROW0__FUNC_EINT18_1X (MTK_PIN_NO(20) | 2)
++#define MT6397_PIN_20_ROW0__FUNC_SCL0_3X (MTK_PIN_NO(20) | 3)
++#define MT6397_PIN_20_ROW0__FUNC_TEST_IN11 (MTK_PIN_NO(20) | 6)
++#define MT6397_PIN_20_ROW0__FUNC_TEST_OUT11 (MTK_PIN_NO(20) | 7)
++
++#define MT6397_PIN_21_ROW1__FUNC_GPIO21 (MTK_PIN_NO(21) | 0)
++#define MT6397_PIN_21_ROW1__FUNC_ROW1 (MTK_PIN_NO(21) | 1)
++#define MT6397_PIN_21_ROW1__FUNC_EINT19_1X (MTK_PIN_NO(21) | 2)
++#define MT6397_PIN_21_ROW1__FUNC_SDA0_3X (MTK_PIN_NO(21) | 3)
++#define MT6397_PIN_21_ROW1__FUNC_AUD_TSTCK (MTK_PIN_NO(21) | 4)
++#define MT6397_PIN_21_ROW1__FUNC_TEST_IN12 (MTK_PIN_NO(21) | 6)
++#define MT6397_PIN_21_ROW1__FUNC_TEST_OUT12 (MTK_PIN_NO(21) | 7)
++
++#define MT6397_PIN_22_ROW2__FUNC_GPIO22 (MTK_PIN_NO(22) | 0)
++#define MT6397_PIN_22_ROW2__FUNC_ROW2 (MTK_PIN_NO(22) | 1)
++#define MT6397_PIN_22_ROW2__FUNC_EINT20_1X (MTK_PIN_NO(22) | 2)
++#define MT6397_PIN_22_ROW2__FUNC_SCL1_3X (MTK_PIN_NO(22) | 3)
++#define MT6397_PIN_22_ROW2__FUNC_TEST_IN13 (MTK_PIN_NO(22) | 6)
++#define MT6397_PIN_22_ROW2__FUNC_TEST_OUT13 (MTK_PIN_NO(22) | 7)
++
++#define MT6397_PIN_23_ROW3__FUNC_GPIO23 (MTK_PIN_NO(23) | 0)
++#define MT6397_PIN_23_ROW3__FUNC_ROW3 (MTK_PIN_NO(23) | 1)
++#define MT6397_PIN_23_ROW3__FUNC_EINT21_1X (MTK_PIN_NO(23) | 2)
++#define MT6397_PIN_23_ROW3__FUNC_SDA1_3X (MTK_PIN_NO(23) | 3)
++#define MT6397_PIN_23_ROW3__FUNC_TEST_IN14 (MTK_PIN_NO(23) | 6)
++#define MT6397_PIN_23_ROW3__FUNC_TEST_OUT14 (MTK_PIN_NO(23) | 7)
++
++#define MT6397_PIN_24_ROW4__FUNC_GPIO24 (MTK_PIN_NO(24) | 0)
++#define MT6397_PIN_24_ROW4__FUNC_ROW4 (MTK_PIN_NO(24) | 1)
++#define MT6397_PIN_24_ROW4__FUNC_EINT22_1X (MTK_PIN_NO(24) | 2)
++#define MT6397_PIN_24_ROW4__FUNC_SCL2_3X (MTK_PIN_NO(24) | 3)
++#define MT6397_PIN_24_ROW4__FUNC_TEST_IN15 (MTK_PIN_NO(24) | 6)
++#define MT6397_PIN_24_ROW4__FUNC_TEST_OUT15 (MTK_PIN_NO(24) | 7)
++
++#define MT6397_PIN_25_ROW5__FUNC_GPIO25 (MTK_PIN_NO(25) | 0)
++#define MT6397_PIN_25_ROW5__FUNC_ROW5 (MTK_PIN_NO(25) | 1)
++#define MT6397_PIN_25_ROW5__FUNC_EINT23_1X (MTK_PIN_NO(25) | 2)
++#define MT6397_PIN_25_ROW5__FUNC_SDA2_3X (MTK_PIN_NO(25) | 3)
++#define MT6397_PIN_25_ROW5__FUNC_TEST_IN16 (MTK_PIN_NO(25) | 6)
++#define MT6397_PIN_25_ROW5__FUNC_TEST_OUT16 (MTK_PIN_NO(25) | 7)
++
++#define MT6397_PIN_26_ROW6__FUNC_GPIO26 (MTK_PIN_NO(26) | 0)
++#define MT6397_PIN_26_ROW6__FUNC_ROW6 (MTK_PIN_NO(26) | 1)
++#define MT6397_PIN_26_ROW6__FUNC_EINT24_1X (MTK_PIN_NO(26) | 2)
++#define MT6397_PIN_26_ROW6__FUNC_PWM3_3X (MTK_PIN_NO(26) | 3)
++#define MT6397_PIN_26_ROW6__FUNC_GPIO32K_2 (MTK_PIN_NO(26) | 4)
++#define MT6397_PIN_26_ROW6__FUNC_GPIO26M_2 (MTK_PIN_NO(26) | 5)
++#define MT6397_PIN_26_ROW6__FUNC_TEST_IN17 (MTK_PIN_NO(26) | 6)
++#define MT6397_PIN_26_ROW6__FUNC_TEST_OUT17 (MTK_PIN_NO(26) | 7)
++
++#define MT6397_PIN_27_ROW7__FUNC_GPIO27 (MTK_PIN_NO(27) | 0)
++#define MT6397_PIN_27_ROW7__FUNC_ROW7 (MTK_PIN_NO(27) | 1)
++#define MT6397_PIN_27_ROW7__FUNC_EINT3_1X (MTK_PIN_NO(27) | 2)
++#define MT6397_PIN_27_ROW7__FUNC_CBUS (MTK_PIN_NO(27) | 3)
++#define MT6397_PIN_27_ROW7__FUNC_GPIO32K_3 (MTK_PIN_NO(27) | 4)
++#define MT6397_PIN_27_ROW7__FUNC_GPIO26M_3 (MTK_PIN_NO(27) | 5)
++#define MT6397_PIN_27_ROW7__FUNC_TEST_IN18 (MTK_PIN_NO(27) | 6)
++#define MT6397_PIN_27_ROW7__FUNC_TEST_OUT18 (MTK_PIN_NO(27) | 7)
++
++#define MT6397_PIN_28_PWM1__FUNC_GPIO28 (MTK_PIN_NO(28) | 0)
++#define MT6397_PIN_28_PWM1__FUNC_PWM1 (MTK_PIN_NO(28) | 1)
++#define MT6397_PIN_28_PWM1__FUNC_EINT4_1X (MTK_PIN_NO(28) | 2)
++#define MT6397_PIN_28_PWM1__FUNC_GPIO32K_4 (MTK_PIN_NO(28) | 4)
++#define MT6397_PIN_28_PWM1__FUNC_GPIO26M_4 (MTK_PIN_NO(28) | 5)
++#define MT6397_PIN_28_PWM1__FUNC_TEST_IN19 (MTK_PIN_NO(28) | 6)
++#define MT6397_PIN_28_PWM1__FUNC_TEST_OUT19 (MTK_PIN_NO(28) | 7)
++
++#define MT6397_PIN_29_PWM2__FUNC_GPIO29 (MTK_PIN_NO(29) | 0)
++#define MT6397_PIN_29_PWM2__FUNC_PWM2 (MTK_PIN_NO(29) | 1)
++#define MT6397_PIN_29_PWM2__FUNC_EINT5_1X (MTK_PIN_NO(29) | 2)
++#define MT6397_PIN_29_PWM2__FUNC_GPIO32K_5 (MTK_PIN_NO(29) | 4)
++#define MT6397_PIN_29_PWM2__FUNC_GPIO26M_5 (MTK_PIN_NO(29) | 5)
++#define MT6397_PIN_29_PWM2__FUNC_TEST_IN20 (MTK_PIN_NO(29) | 6)
++#define MT6397_PIN_29_PWM2__FUNC_TEST_OUT20 (MTK_PIN_NO(29) | 7)
++
++#define MT6397_PIN_30_PWM3__FUNC_GPIO30 (MTK_PIN_NO(30) | 0)
++#define MT6397_PIN_30_PWM3__FUNC_PWM3 (MTK_PIN_NO(30) | 1)
++#define MT6397_PIN_30_PWM3__FUNC_EINT6_1X (MTK_PIN_NO(30) | 2)
++#define MT6397_PIN_30_PWM3__FUNC_COL0 (MTK_PIN_NO(30) | 3)
++#define MT6397_PIN_30_PWM3__FUNC_GPIO32K_6 (MTK_PIN_NO(30) | 4)
++#define MT6397_PIN_30_PWM3__FUNC_GPIO26M_6 (MTK_PIN_NO(30) | 5)
++#define MT6397_PIN_30_PWM3__FUNC_TEST_IN21 (MTK_PIN_NO(30) | 6)
++#define MT6397_PIN_30_PWM3__FUNC_TEST_OUT21 (MTK_PIN_NO(30) | 7)
++
++#define MT6397_PIN_31_SCL0__FUNC_GPIO31 (MTK_PIN_NO(31) | 0)
++#define MT6397_PIN_31_SCL0__FUNC_SCL0 (MTK_PIN_NO(31) | 1)
++#define MT6397_PIN_31_SCL0__FUNC_EINT7_1X (MTK_PIN_NO(31) | 2)
++#define MT6397_PIN_31_SCL0__FUNC_PWM1_2X (MTK_PIN_NO(31) | 3)
++#define MT6397_PIN_31_SCL0__FUNC_TEST_IN22 (MTK_PIN_NO(31) | 6)
++#define MT6397_PIN_31_SCL0__FUNC_TEST_OUT22 (MTK_PIN_NO(31) | 7)
++
++#define MT6397_PIN_32_SDA0__FUNC_GPIO32 (MTK_PIN_NO(32) | 0)
++#define MT6397_PIN_32_SDA0__FUNC_SDA0 (MTK_PIN_NO(32) | 1)
++#define MT6397_PIN_32_SDA0__FUNC_EINT8_1X (MTK_PIN_NO(32) | 2)
++#define MT6397_PIN_32_SDA0__FUNC_TEST_IN23 (MTK_PIN_NO(32) | 6)
++#define MT6397_PIN_32_SDA0__FUNC_TEST_OUT23 (MTK_PIN_NO(32) | 7)
++
++#define MT6397_PIN_33_SCL1__FUNC_GPIO33 (MTK_PIN_NO(33) | 0)
++#define MT6397_PIN_33_SCL1__FUNC_SCL1 (MTK_PIN_NO(33) | 1)
++#define MT6397_PIN_33_SCL1__FUNC_EINT9_1X (MTK_PIN_NO(33) | 2)
++#define MT6397_PIN_33_SCL1__FUNC_PWM2_2X (MTK_PIN_NO(33) | 3)
++#define MT6397_PIN_33_SCL1__FUNC_TEST_IN24 (MTK_PIN_NO(33) | 6)
++#define MT6397_PIN_33_SCL1__FUNC_TEST_OUT24 (MTK_PIN_NO(33) | 7)
++
++#define MT6397_PIN_34_SDA1__FUNC_GPIO34 (MTK_PIN_NO(34) | 0)
++#define MT6397_PIN_34_SDA1__FUNC_SDA1 (MTK_PIN_NO(34) | 1)
++#define MT6397_PIN_34_SDA1__FUNC_EINT0_1X (MTK_PIN_NO(34) | 2)
++#define MT6397_PIN_34_SDA1__FUNC_TEST_IN25 (MTK_PIN_NO(34) | 6)
++#define MT6397_PIN_34_SDA1__FUNC_TEST_OUT25 (MTK_PIN_NO(34) | 7)
++
++#define MT6397_PIN_35_SCL2__FUNC_GPIO35 (MTK_PIN_NO(35) | 0)
++#define MT6397_PIN_35_SCL2__FUNC_SCL2 (MTK_PIN_NO(35) | 1)
++#define MT6397_PIN_35_SCL2__FUNC_EINT1_1X (MTK_PIN_NO(35) | 2)
++#define MT6397_PIN_35_SCL2__FUNC_PWM3_2X (MTK_PIN_NO(35) | 3)
++#define MT6397_PIN_35_SCL2__FUNC_TEST_IN26 (MTK_PIN_NO(35) | 6)
++#define MT6397_PIN_35_SCL2__FUNC_TEST_OUT26 (MTK_PIN_NO(35) | 7)
++
++#define MT6397_PIN_36_SDA2__FUNC_GPIO36 (MTK_PIN_NO(36) | 0)
++#define MT6397_PIN_36_SDA2__FUNC_SDA2 (MTK_PIN_NO(36) | 1)
++#define MT6397_PIN_36_SDA2__FUNC_EINT2_1X (MTK_PIN_NO(36) | 2)
++#define MT6397_PIN_36_SDA2__FUNC_TEST_IN27 (MTK_PIN_NO(36) | 6)
++#define MT6397_PIN_36_SDA2__FUNC_TEST_OUT27 (MTK_PIN_NO(36) | 7)
++
++#define MT6397_PIN_37_HDMISD__FUNC_GPIO37 (MTK_PIN_NO(37) | 0)
++#define MT6397_PIN_37_HDMISD__FUNC_HDMISD (MTK_PIN_NO(37) | 1)
++#define MT6397_PIN_37_HDMISD__FUNC_TEST_IN28 (MTK_PIN_NO(37) | 6)
++#define MT6397_PIN_37_HDMISD__FUNC_TEST_OUT28 (MTK_PIN_NO(37) | 7)
++
++#define MT6397_PIN_38_HDMISCK__FUNC_GPIO38 (MTK_PIN_NO(38) | 0)
++#define MT6397_PIN_38_HDMISCK__FUNC_HDMISCK (MTK_PIN_NO(38) | 1)
++#define MT6397_PIN_38_HDMISCK__FUNC_TEST_IN29 (MTK_PIN_NO(38) | 6)
++#define MT6397_PIN_38_HDMISCK__FUNC_TEST_OUT29 (MTK_PIN_NO(38) | 7)
++
++#define MT6397_PIN_39_HTPLG__FUNC_GPIO39 (MTK_PIN_NO(39) | 0)
++#define MT6397_PIN_39_HTPLG__FUNC_HTPLG (MTK_PIN_NO(39) | 1)
++#define MT6397_PIN_39_HTPLG__FUNC_TEST_IN30 (MTK_PIN_NO(39) | 6)
++#define MT6397_PIN_39_HTPLG__FUNC_TEST_OUT30 (MTK_PIN_NO(39) | 7)
++
++#define MT6397_PIN_40_CEC__FUNC_GPIO40 (MTK_PIN_NO(40) | 0)
++#define MT6397_PIN_40_CEC__FUNC_CEC (MTK_PIN_NO(40) | 1)
++#define MT6397_PIN_40_CEC__FUNC_TEST_IN31 (MTK_PIN_NO(40) | 6)
++#define MT6397_PIN_40_CEC__FUNC_TEST_OUT31 (MTK_PIN_NO(40) | 7)
++
++#endif /* __DTS_MT6397_PINFUNC_H */
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0050-pinctrl-mediatek-data-struct-optimize-and-remove-unu.patch b/target/linux/mediatek/patches/0050-pinctrl-mediatek-data-struct-optimize-and-remove-unu.patch
new file mode 100644
index 0000000000..7399746783
--- /dev/null
+++ b/target/linux/mediatek/patches/0050-pinctrl-mediatek-data-struct-optimize-and-remove-unu.patch
@@ -0,0 +1,116 @@
+From 3eeb897a627e26083472f14e7512f53276a5e7ce Mon Sep 17 00:00:00 2001
+From: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Date: Mon, 18 May 2015 23:11:14 -0700
+Subject: [PATCH 50/76] pinctrl: mediatek: data struct optimize and remove
+ unused member
+
+struct mtk_desc_pin.chip, mtk_pinctrl_devdata.invser_offset
+and mtk_pinctrl_devdata.chip_type are never used in code.
+Remove them.
+
+Some per-pin data are using int for pin number and offsets.
+Change to short and rearrange to reduce const data size.
+
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Signed-off-by: Hongzhou Yang <hongzhou.yang@mediatek.com>
+---
+ drivers/pinctrl/mediatek/pinctrl-mt8135.c | 10 ++++------
+ drivers/pinctrl/mediatek/pinctrl-mtk-common.h | 10 ++--------
+ 2 files changed, 6 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8135.c b/drivers/pinctrl/mediatek/pinctrl-mt8135.c
+index f1e1e18..8e6abd5 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mt8135.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mt8135.c
+@@ -32,12 +32,12 @@
+ #define R1_BASE2 0x250
+
+ struct mtk_spec_pull_set {
+- unsigned int pin;
+- unsigned int pupd_offset;
++ unsigned char pin;
+ unsigned char pupd_bit;
+- unsigned int r0_offset;
++ unsigned short pupd_offset;
++ unsigned short r0_offset;
++ unsigned short r1_offset;
+ unsigned char r0_bit;
+- unsigned int r1_offset;
+ unsigned char r1_bit;
+ };
+
+@@ -305,7 +305,6 @@ static const struct mtk_pinctrl_devdata mt8135_pinctrl_data = {
+ .pullen_offset = 0x0200,
+ .smt_offset = 0x0300,
+ .pullsel_offset = 0x0400,
+- .invser_offset = 0x0600,
+ .dout_offset = 0x0800,
+ .din_offset = 0x0A00,
+ .pinmux_offset = 0x0C00,
+@@ -314,7 +313,6 @@ static const struct mtk_pinctrl_devdata mt8135_pinctrl_data = {
+ .port_shf = 4,
+ .port_mask = 0xf,
+ .port_align = 4,
+- .chip_type = MTK_CHIP_TYPE_BASE,
+ .eint_offsets = {
+ .name = "mt8135_eint",
+ .stat = 0x000,
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+index 375771d..1508849 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+@@ -19,8 +19,6 @@
+ #include <linux/regmap.h>
+
+ #define NO_EINT_SUPPORT 255
+-#define MTK_CHIP_TYPE_BASE 0
+-#define MTK_CHIP_TYPE_PMIC 1
+ #define MT_EDGE_SENSITIVE 0
+ #define MT_LEVEL_SENSITIVE 1
+ #define EINT_DBNC_SET_DBNC_BITS 4
+@@ -39,7 +37,6 @@ struct mtk_desc_eint {
+
+ struct mtk_desc_pin {
+ struct pinctrl_pin_desc pin;
+- const char *chip;
+ const struct mtk_desc_eint eint;
+ const struct mtk_desc_function *functions;
+ };
+@@ -47,7 +44,6 @@ struct mtk_desc_pin {
+ #define MTK_PIN(_pin, _pad, _chip, _eint, ...) \
+ { \
+ .pin = _pin, \
+- .chip = _chip, \
+ .eint = _eint, \
+ .functions = (struct mtk_desc_function[]){ \
+ __VA_ARGS__, { } }, \
+@@ -107,8 +103,8 @@ struct mtk_drv_group_desc {
+ * @grp: The group for this pin belongs to.
+ */
+ struct mtk_pin_drv_grp {
+- unsigned int pin;
+- unsigned int offset;
++ unsigned short pin;
++ unsigned short offset;
+ unsigned char bit;
+ unsigned char grp;
+ };
+@@ -193,7 +189,6 @@ struct mtk_pinctrl_devdata {
+ unsigned int pullen_offset;
+ unsigned int pullsel_offset;
+ unsigned int drv_offset;
+- unsigned int invser_offset;
+ unsigned int dout_offset;
+ unsigned int din_offset;
+ unsigned int pinmux_offset;
+@@ -202,7 +197,6 @@ struct mtk_pinctrl_devdata {
+ unsigned char port_shf;
+ unsigned char port_mask;
+ unsigned char port_align;
+- unsigned char chip_type;
+ struct mtk_eint_offsets eint_offsets;
+ unsigned int ap_num;
+ unsigned int db_cnt;
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0051-pinctrl-mediatek-add-mtk_pctrl_spec_pull_set_samereg.patch b/target/linux/mediatek/patches/0051-pinctrl-mediatek-add-mtk_pctrl_spec_pull_set_samereg.patch
new file mode 100644
index 0000000000..2e9eb60b5b
--- /dev/null
+++ b/target/linux/mediatek/patches/0051-pinctrl-mediatek-add-mtk_pctrl_spec_pull_set_samereg.patch
@@ -0,0 +1,328 @@
+From aefbeb75a32e080445d72ddd4b9ab28c258597d0 Mon Sep 17 00:00:00 2001
+From: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Date: Mon, 18 May 2015 23:11:15 -0700
+Subject: [PATCH 51/76] pinctrl: mediatek: add mtk_pctrl_spec_pull_set_samereg
+ common code
+
+Several mediatek soc use similar pull setting procedure as mt8173,
+the pupd enable and resistance setting are in the same register.
+Add common code mtk_pctrl_spec_pull_set_samereg out of spec_pull_set
+in mt8173 to handle this case, so future soc driver can use it.
+
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Signed-off-by: Hongzhou Yang <hongzhou.yang@mediatek.com>
+---
+ drivers/pinctrl/mediatek/pinctrl-mt8173.c | 166 +++++++------------------
+ drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 60 +++++++++
+ drivers/pinctrl/mediatek/pinctrl-mtk-common.h | 31 +++++
+ 3 files changed, 136 insertions(+), 121 deletions(-)
+
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8173.c b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
+index 412ea84..cc44b27 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mt8173.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
+@@ -47,130 +47,54 @@ struct mtk_pin_ies_smt_set {
+ .offset = _offset, \
+ }
+
+-/**
+- * struct mtk_pin_spec_pupd_set - For special pins' pull up/down setting.
+- * @pin: The pin number.
+- * @offset: The offset of special pull up/down setting register.
+- * @pupd_bit: The pull up/down bit in this register.
+- * @r0_bit: The r0 bit of pull resistor.
+- * @r1_bit: The r1 bit of pull resistor.
+- */
+-struct mtk_pin_spec_pupd_set {
+- unsigned int pin;
+- unsigned int offset;
+- unsigned char pupd_bit;
+- unsigned char r1_bit;
+- unsigned char r0_bit;
+-};
+-
+-#define MTK_PIN_PUPD_SPEC(_pin, _offset, _pupd, _r1, _r0) \
+- { \
+- .pin = _pin, \
+- .offset = _offset, \
+- .pupd_bit = _pupd, \
+- .r1_bit = _r1, \
+- .r0_bit = _r0, \
+- }
+-
+-static const struct mtk_pin_spec_pupd_set mt8173_spec_pupd[] = {
+- MTK_PIN_PUPD_SPEC(119, 0xe00, 2, 1, 0), /* KROW0 */
+- MTK_PIN_PUPD_SPEC(120, 0xe00, 6, 5, 4), /* KROW1 */
+- MTK_PIN_PUPD_SPEC(121, 0xe00, 10, 9, 8), /* KROW2 */
+- MTK_PIN_PUPD_SPEC(122, 0xe10, 2, 1, 0), /* KCOL0 */
+- MTK_PIN_PUPD_SPEC(123, 0xe10, 6, 5, 4), /* KCOL1 */
+- MTK_PIN_PUPD_SPEC(124, 0xe10, 10, 9, 8), /* KCOL2 */
+-
+- MTK_PIN_PUPD_SPEC(67, 0xd10, 2, 1, 0), /* ms0 DS */
+- MTK_PIN_PUPD_SPEC(68, 0xd00, 2, 1, 0), /* ms0 RST */
+- MTK_PIN_PUPD_SPEC(66, 0xc10, 2, 1, 0), /* ms0 cmd */
+- MTK_PIN_PUPD_SPEC(65, 0xc00, 2, 1, 0), /* ms0 clk */
+- MTK_PIN_PUPD_SPEC(57, 0xc20, 2, 1, 0), /* ms0 data0 */
+- MTK_PIN_PUPD_SPEC(58, 0xc20, 2, 1, 0), /* ms0 data1 */
+- MTK_PIN_PUPD_SPEC(59, 0xc20, 2, 1, 0), /* ms0 data2 */
+- MTK_PIN_PUPD_SPEC(60, 0xc20, 2, 1, 0), /* ms0 data3 */
+- MTK_PIN_PUPD_SPEC(61, 0xc20, 2, 1, 0), /* ms0 data4 */
+- MTK_PIN_PUPD_SPEC(62, 0xc20, 2, 1, 0), /* ms0 data5 */
+- MTK_PIN_PUPD_SPEC(63, 0xc20, 2, 1, 0), /* ms0 data6 */
+- MTK_PIN_PUPD_SPEC(64, 0xc20, 2, 1, 0), /* ms0 data7 */
+-
+- MTK_PIN_PUPD_SPEC(78, 0xc50, 2, 1, 0), /* ms1 cmd */
+- MTK_PIN_PUPD_SPEC(73, 0xd20, 2, 1, 0), /* ms1 dat0 */
+- MTK_PIN_PUPD_SPEC(74, 0xd20, 6, 5, 4), /* ms1 dat1 */
+- MTK_PIN_PUPD_SPEC(75, 0xd20, 10, 9, 8), /* ms1 dat2 */
+- MTK_PIN_PUPD_SPEC(76, 0xd20, 14, 13, 12), /* ms1 dat3 */
+- MTK_PIN_PUPD_SPEC(77, 0xc40, 2, 1, 0), /* ms1 clk */
+-
+- MTK_PIN_PUPD_SPEC(100, 0xd40, 2, 1, 0), /* ms2 dat0 */
+- MTK_PIN_PUPD_SPEC(101, 0xd40, 6, 5, 4), /* ms2 dat1 */
+- MTK_PIN_PUPD_SPEC(102, 0xd40, 10, 9, 8), /* ms2 dat2 */
+- MTK_PIN_PUPD_SPEC(103, 0xd40, 14, 13, 12), /* ms2 dat3 */
+- MTK_PIN_PUPD_SPEC(104, 0xc80, 2, 1, 0), /* ms2 clk */
+- MTK_PIN_PUPD_SPEC(105, 0xc90, 2, 1, 0), /* ms2 cmd */
+-
+- MTK_PIN_PUPD_SPEC(22, 0xd60, 2, 1, 0), /* ms3 dat0 */
+- MTK_PIN_PUPD_SPEC(23, 0xd60, 6, 5, 4), /* ms3 dat1 */
+- MTK_PIN_PUPD_SPEC(24, 0xd60, 10, 9, 8), /* ms3 dat2 */
+- MTK_PIN_PUPD_SPEC(25, 0xd60, 14, 13, 12), /* ms3 dat3 */
+- MTK_PIN_PUPD_SPEC(26, 0xcc0, 2, 1, 0), /* ms3 clk */
+- MTK_PIN_PUPD_SPEC(27, 0xcd0, 2, 1, 0) /* ms3 cmd */
++static const struct mtk_pin_spec_pupd_set_samereg mt8173_spec_pupd[] = {
++ MTK_PIN_PUPD_SPEC_SR(119, 0xe00, 2, 1, 0), /* KROW0 */
++ MTK_PIN_PUPD_SPEC_SR(120, 0xe00, 6, 5, 4), /* KROW1 */
++ MTK_PIN_PUPD_SPEC_SR(121, 0xe00, 10, 9, 8), /* KROW2 */
++ MTK_PIN_PUPD_SPEC_SR(122, 0xe10, 2, 1, 0), /* KCOL0 */
++ MTK_PIN_PUPD_SPEC_SR(123, 0xe10, 6, 5, 4), /* KCOL1 */
++ MTK_PIN_PUPD_SPEC_SR(124, 0xe10, 10, 9, 8), /* KCOL2 */
++
++ MTK_PIN_PUPD_SPEC_SR(67, 0xd10, 2, 1, 0), /* ms0 DS */
++ MTK_PIN_PUPD_SPEC_SR(68, 0xd00, 2, 1, 0), /* ms0 RST */
++ MTK_PIN_PUPD_SPEC_SR(66, 0xc10, 2, 1, 0), /* ms0 cmd */
++ MTK_PIN_PUPD_SPEC_SR(65, 0xc00, 2, 1, 0), /* ms0 clk */
++ MTK_PIN_PUPD_SPEC_SR(57, 0xc20, 2, 1, 0), /* ms0 data0 */
++ MTK_PIN_PUPD_SPEC_SR(58, 0xc20, 2, 1, 0), /* ms0 data1 */
++ MTK_PIN_PUPD_SPEC_SR(59, 0xc20, 2, 1, 0), /* ms0 data2 */
++ MTK_PIN_PUPD_SPEC_SR(60, 0xc20, 2, 1, 0), /* ms0 data3 */
++ MTK_PIN_PUPD_SPEC_SR(61, 0xc20, 2, 1, 0), /* ms0 data4 */
++ MTK_PIN_PUPD_SPEC_SR(62, 0xc20, 2, 1, 0), /* ms0 data5 */
++ MTK_PIN_PUPD_SPEC_SR(63, 0xc20, 2, 1, 0), /* ms0 data6 */
++ MTK_PIN_PUPD_SPEC_SR(64, 0xc20, 2, 1, 0), /* ms0 data7 */
++
++ MTK_PIN_PUPD_SPEC_SR(78, 0xc50, 2, 1, 0), /* ms1 cmd */
++ MTK_PIN_PUPD_SPEC_SR(73, 0xd20, 2, 1, 0), /* ms1 dat0 */
++ MTK_PIN_PUPD_SPEC_SR(74, 0xd20, 6, 5, 4), /* ms1 dat1 */
++ MTK_PIN_PUPD_SPEC_SR(75, 0xd20, 10, 9, 8), /* ms1 dat2 */
++ MTK_PIN_PUPD_SPEC_SR(76, 0xd20, 14, 13, 12), /* ms1 dat3 */
++ MTK_PIN_PUPD_SPEC_SR(77, 0xc40, 2, 1, 0), /* ms1 clk */
++
++ MTK_PIN_PUPD_SPEC_SR(100, 0xd40, 2, 1, 0), /* ms2 dat0 */
++ MTK_PIN_PUPD_SPEC_SR(101, 0xd40, 6, 5, 4), /* ms2 dat1 */
++ MTK_PIN_PUPD_SPEC_SR(102, 0xd40, 10, 9, 8), /* ms2 dat2 */
++ MTK_PIN_PUPD_SPEC_SR(103, 0xd40, 14, 13, 12), /* ms2 dat3 */
++ MTK_PIN_PUPD_SPEC_SR(104, 0xc80, 2, 1, 0), /* ms2 clk */
++ MTK_PIN_PUPD_SPEC_SR(105, 0xc90, 2, 1, 0), /* ms2 cmd */
++
++ MTK_PIN_PUPD_SPEC_SR(22, 0xd60, 2, 1, 0), /* ms3 dat0 */
++ MTK_PIN_PUPD_SPEC_SR(23, 0xd60, 6, 5, 4), /* ms3 dat1 */
++ MTK_PIN_PUPD_SPEC_SR(24, 0xd60, 10, 9, 8), /* ms3 dat2 */
++ MTK_PIN_PUPD_SPEC_SR(25, 0xd60, 14, 13, 12), /* ms3 dat3 */
++ MTK_PIN_PUPD_SPEC_SR(26, 0xcc0, 2, 1, 0), /* ms3 clk */
++ MTK_PIN_PUPD_SPEC_SR(27, 0xcd0, 2, 1, 0) /* ms3 cmd */
+ };
+
+-static int spec_pull_set(struct regmap *regmap, unsigned int pin,
++static int mt8173_spec_pull_set(struct regmap *regmap, unsigned int pin,
+ unsigned char align, bool isup, unsigned int r1r0)
+ {
+- unsigned int i;
+- unsigned int reg_pupd, reg_set, reg_rst;
+- unsigned int bit_pupd, bit_r0, bit_r1;
+- const struct mtk_pin_spec_pupd_set *spec_pupd_pin;
+- bool find = false;
+-
+- for (i = 0; i < ARRAY_SIZE(mt8173_spec_pupd); i++) {
+- if (pin == mt8173_spec_pupd[i].pin) {
+- find = true;
+- break;
+- }
+- }
+-
+- if (!find)
+- return -EINVAL;
+-
+- spec_pupd_pin = mt8173_spec_pupd + i;
+- reg_set = spec_pupd_pin->offset + align;
+- reg_rst = spec_pupd_pin->offset + (align << 1);
+-
+- if (isup)
+- reg_pupd = reg_rst;
+- else
+- reg_pupd = reg_set;
+-
+- bit_pupd = BIT(spec_pupd_pin->pupd_bit);
+- regmap_write(regmap, reg_pupd, bit_pupd);
+-
+- bit_r0 = BIT(spec_pupd_pin->r0_bit);
+- bit_r1 = BIT(spec_pupd_pin->r1_bit);
+-
+- switch (r1r0) {
+- case MTK_PUPD_SET_R1R0_00:
+- regmap_write(regmap, reg_rst, bit_r0);
+- regmap_write(regmap, reg_rst, bit_r1);
+- break;
+- case MTK_PUPD_SET_R1R0_01:
+- regmap_write(regmap, reg_set, bit_r0);
+- regmap_write(regmap, reg_rst, bit_r1);
+- break;
+- case MTK_PUPD_SET_R1R0_10:
+- regmap_write(regmap, reg_rst, bit_r0);
+- regmap_write(regmap, reg_set, bit_r1);
+- break;
+- case MTK_PUPD_SET_R1R0_11:
+- regmap_write(regmap, reg_set, bit_r0);
+- regmap_write(regmap, reg_set, bit_r1);
+- break;
+- default:
+- return -EINVAL;
+- }
+-
+- return 0;
++ return mtk_pctrl_spec_pull_set_samereg(regmap, mt8173_spec_pupd,
++ ARRAY_SIZE(mt8173_spec_pupd), pin, align, isup, r1r0);
+ }
+
+ static const struct mtk_pin_ies_smt_set mt8173_ies_smt_set[] = {
+@@ -382,7 +306,7 @@ static const struct mtk_pinctrl_devdata mt8173_pinctrl_data = {
+ .n_grp_cls = ARRAY_SIZE(mt8173_drv_grp),
+ .pin_drv_grp = mt8173_pin_drv,
+ .n_pin_drv_grps = ARRAY_SIZE(mt8173_pin_drv),
+- .spec_pull_set = spec_pull_set,
++ .spec_pull_set = mt8173_spec_pull_set,
+ .spec_ies_smt_set = spec_ies_smt_set,
+ .dir_offset = 0x0000,
+ .pullen_offset = 0x0100,
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+index 474812e..0d51145 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+@@ -186,6 +186,66 @@ static int mtk_pconf_set_driving(struct mtk_pinctrl *pctl,
+ return -EINVAL;
+ }
+
++int mtk_pctrl_spec_pull_set_samereg(struct regmap *regmap,
++ const struct mtk_pin_spec_pupd_set_samereg *pupd_infos,
++ unsigned int info_num, unsigned int pin,
++ unsigned char align, bool isup, unsigned int r1r0)
++{
++ unsigned int i;
++ unsigned int reg_pupd, reg_set, reg_rst;
++ unsigned int bit_pupd, bit_r0, bit_r1;
++ const struct mtk_pin_spec_pupd_set_samereg *spec_pupd_pin;
++ bool find = false;
++
++ for (i = 0; i < info_num; i++) {
++ if (pin == pupd_infos[i].pin) {
++ find = true;
++ break;
++ }
++ }
++
++ if (!find)
++ return -EINVAL;
++
++ spec_pupd_pin = pupd_infos + i;
++ reg_set = spec_pupd_pin->offset + align;
++ reg_rst = spec_pupd_pin->offset + (align << 1);
++
++ if (isup)
++ reg_pupd = reg_rst;
++ else
++ reg_pupd = reg_set;
++
++ bit_pupd = BIT(spec_pupd_pin->pupd_bit);
++ regmap_write(regmap, reg_pupd, bit_pupd);
++
++ bit_r0 = BIT(spec_pupd_pin->r0_bit);
++ bit_r1 = BIT(spec_pupd_pin->r1_bit);
++
++ switch (r1r0) {
++ case MTK_PUPD_SET_R1R0_00:
++ regmap_write(regmap, reg_rst, bit_r0);
++ regmap_write(regmap, reg_rst, bit_r1);
++ break;
++ case MTK_PUPD_SET_R1R0_01:
++ regmap_write(regmap, reg_set, bit_r0);
++ regmap_write(regmap, reg_rst, bit_r1);
++ break;
++ case MTK_PUPD_SET_R1R0_10:
++ regmap_write(regmap, reg_rst, bit_r0);
++ regmap_write(regmap, reg_set, bit_r1);
++ break;
++ case MTK_PUPD_SET_R1R0_11:
++ regmap_write(regmap, reg_set, bit_r0);
++ regmap_write(regmap, reg_set, bit_r1);
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
+ static int mtk_pconf_set_pull_select(struct mtk_pinctrl *pctl,
+ unsigned int pin, bool enable, bool isup, unsigned int arg)
+ {
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+index 1508849..2a4b7be 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+@@ -117,6 +117,32 @@ struct mtk_pin_drv_grp {
+ .grp = _grp, \
+ }
+
++/**
++ * struct mtk_pin_spec_pupd_set_samereg
++ * - For special pins' pull up/down setting which resides in same register
++ * @pin: The pin number.
++ * @offset: The offset of special pull up/down setting register.
++ * @pupd_bit: The pull up/down bit in this register.
++ * @r0_bit: The r0 bit of pull resistor.
++ * @r1_bit: The r1 bit of pull resistor.
++ */
++struct mtk_pin_spec_pupd_set_samereg {
++ unsigned short pin;
++ unsigned short offset;
++ unsigned char pupd_bit;
++ unsigned char r1_bit;
++ unsigned char r0_bit;
++};
++
++#define MTK_PIN_PUPD_SPEC_SR(_pin, _offset, _pupd, _r1, _r0) \
++ { \
++ .pin = _pin, \
++ .offset = _offset, \
++ .pupd_bit = _pupd, \
++ .r1_bit = _r1, \
++ .r0_bit = _r0, \
++ }
++
+ struct mtk_eint_offsets {
+ const char *name;
+ unsigned int stat;
+@@ -220,4 +246,9 @@ struct mtk_pinctrl {
+ int mtk_pctrl_init(struct platform_device *pdev,
+ const struct mtk_pinctrl_devdata *data);
+
++int mtk_pctrl_spec_pull_set_samereg(struct regmap *regmap,
++ const struct mtk_pin_spec_pupd_set_samereg *pupd_infos,
++ unsigned int info_num, unsigned int pin,
++ unsigned char align, bool isup, unsigned int r1r0);
++
+ #endif /* __PINCTRL_MTK_COMMON_H */
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0052-pinctrl-mediatek-add-ies-smt-control-to-common-code.patch b/target/linux/mediatek/patches/0052-pinctrl-mediatek-add-ies-smt-control-to-common-code.patch
new file mode 100644
index 0000000000..5467c216b8
--- /dev/null
+++ b/target/linux/mediatek/patches/0052-pinctrl-mediatek-add-ies-smt-control-to-common-code.patch
@@ -0,0 +1,479 @@
+From 32ea3b91046bea40cd1a7a4f16a24d75f53ca92a Mon Sep 17 00:00:00 2001
+From: Hongzhou Yang <hongzhou.yang@mediatek.com>
+Date: Mon, 18 May 2015 23:11:16 -0700
+Subject: [PATCH 52/76] pinctrl: mediatek: add ies/smt control to common code.
+
+Input enable and smt setting have different register,
+modify code to fix it.
+
+Several mediatek soc use similar input enable/smt setting
+procedure as mt8173, some soc use generic input enable/smt
+setting, some soc has no input enable/smt setting. Adding
+common code to handle all those cases, so future soc driver
+can use it.
+
+Signed-off-by: Hongzhou Yang <hongzhou.yang@mediatek.com>
+---
+ drivers/pinctrl/mediatek/pinctrl-mt8173.c | 201 +++++++++++++------------
+ drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 82 +++++++---
+ drivers/pinctrl/mediatek/pinctrl-mtk-common.h | 31 +++-
+ 3 files changed, 198 insertions(+), 116 deletions(-)
+
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8173.c b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
+index cc44b27..a7e5b24 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mt8173.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
+@@ -18,6 +18,7 @@
+ #include <linux/of_device.h>
+ #include <linux/pinctrl/pinctrl.h>
+ #include <linux/regmap.h>
++#include <linux/pinctrl/pinconf-generic.h>
+ #include <dt-bindings/pinctrl/mt65xx.h>
+
+ #include "pinctrl-mtk-common.h"
+@@ -25,28 +26,6 @@
+
+ #define DRV_BASE 0xb00
+
+-/**
+- * struct mtk_pin_ies_smt_set - For special pins' ies and smt setting.
+- * @start: The start pin number of those special pins.
+- * @end: The end pin number of those special pins.
+- * @offset: The offset of special setting register.
+- * @bit: The bit of special setting register.
+- */
+-struct mtk_pin_ies_smt_set {
+- unsigned int start;
+- unsigned int end;
+- unsigned int offset;
+- unsigned char bit;
+-};
+-
+-#define MTK_PIN_IES_SMT_SET(_start, _end, _offset, _bit) \
+- { \
+- .start = _start, \
+- .end = _end, \
+- .bit = _bit, \
+- .offset = _offset, \
+- }
+-
+ static const struct mtk_pin_spec_pupd_set_samereg mt8173_spec_pupd[] = {
+ MTK_PIN_PUPD_SPEC_SR(119, 0xe00, 2, 1, 0), /* KROW0 */
+ MTK_PIN_PUPD_SPEC_SR(120, 0xe00, 6, 5, 4), /* KROW1 */
+@@ -97,80 +76,114 @@ static int mt8173_spec_pull_set(struct regmap *regmap, unsigned int pin,
+ ARRAY_SIZE(mt8173_spec_pupd), pin, align, isup, r1r0);
+ }
+
+-static const struct mtk_pin_ies_smt_set mt8173_ies_smt_set[] = {
+- MTK_PIN_IES_SMT_SET(0, 4, 0x930, 1),
+- MTK_PIN_IES_SMT_SET(5, 9, 0x930, 2),
+- MTK_PIN_IES_SMT_SET(10, 13, 0x930, 10),
+- MTK_PIN_IES_SMT_SET(14, 15, 0x940, 10),
+- MTK_PIN_IES_SMT_SET(16, 16, 0x930, 0),
+- MTK_PIN_IES_SMT_SET(17, 17, 0x950, 2),
+- MTK_PIN_IES_SMT_SET(18, 21, 0x940, 3),
+- MTK_PIN_IES_SMT_SET(29, 32, 0x930, 3),
+- MTK_PIN_IES_SMT_SET(33, 33, 0x930, 4),
+- MTK_PIN_IES_SMT_SET(34, 36, 0x930, 5),
+- MTK_PIN_IES_SMT_SET(37, 38, 0x930, 6),
+- MTK_PIN_IES_SMT_SET(39, 39, 0x930, 7),
+- MTK_PIN_IES_SMT_SET(40, 41, 0x930, 9),
+- MTK_PIN_IES_SMT_SET(42, 42, 0x940, 0),
+- MTK_PIN_IES_SMT_SET(43, 44, 0x930, 11),
+- MTK_PIN_IES_SMT_SET(45, 46, 0x930, 12),
+- MTK_PIN_IES_SMT_SET(57, 64, 0xc20, 13),
+- MTK_PIN_IES_SMT_SET(65, 65, 0xc10, 13),
+- MTK_PIN_IES_SMT_SET(66, 66, 0xc00, 13),
+- MTK_PIN_IES_SMT_SET(67, 67, 0xd10, 13),
+- MTK_PIN_IES_SMT_SET(68, 68, 0xd00, 13),
+- MTK_PIN_IES_SMT_SET(69, 72, 0x940, 14),
+- MTK_PIN_IES_SMT_SET(73, 76, 0xc60, 13),
+- MTK_PIN_IES_SMT_SET(77, 77, 0xc40, 13),
+- MTK_PIN_IES_SMT_SET(78, 78, 0xc50, 13),
+- MTK_PIN_IES_SMT_SET(79, 82, 0x940, 15),
+- MTK_PIN_IES_SMT_SET(83, 83, 0x950, 0),
+- MTK_PIN_IES_SMT_SET(84, 85, 0x950, 1),
+- MTK_PIN_IES_SMT_SET(86, 91, 0x950, 2),
+- MTK_PIN_IES_SMT_SET(92, 92, 0x930, 13),
+- MTK_PIN_IES_SMT_SET(93, 95, 0x930, 14),
+- MTK_PIN_IES_SMT_SET(96, 99, 0x930, 15),
+- MTK_PIN_IES_SMT_SET(100, 103, 0xca0, 13),
+- MTK_PIN_IES_SMT_SET(104, 104, 0xc80, 13),
+- MTK_PIN_IES_SMT_SET(105, 105, 0xc90, 13),
+- MTK_PIN_IES_SMT_SET(106, 107, 0x940, 4),
+- MTK_PIN_IES_SMT_SET(108, 112, 0x940, 1),
+- MTK_PIN_IES_SMT_SET(113, 116, 0x940, 2),
+- MTK_PIN_IES_SMT_SET(117, 118, 0x940, 5),
+- MTK_PIN_IES_SMT_SET(119, 124, 0x940, 6),
+- MTK_PIN_IES_SMT_SET(125, 126, 0x940, 7),
+- MTK_PIN_IES_SMT_SET(127, 127, 0x940, 0),
+- MTK_PIN_IES_SMT_SET(128, 128, 0x950, 8),
+- MTK_PIN_IES_SMT_SET(129, 130, 0x950, 9),
+- MTK_PIN_IES_SMT_SET(131, 132, 0x950, 8),
+- MTK_PIN_IES_SMT_SET(133, 134, 0x910, 8)
++static const struct mtk_pin_ies_smt_set mt8173_smt_set[] = {
++ MTK_PIN_IES_SMT_SPEC(0, 4, 0x930, 1),
++ MTK_PIN_IES_SMT_SPEC(5, 9, 0x930, 2),
++ MTK_PIN_IES_SMT_SPEC(10, 13, 0x930, 10),
++ MTK_PIN_IES_SMT_SPEC(14, 15, 0x940, 10),
++ MTK_PIN_IES_SMT_SPEC(16, 16, 0x930, 0),
++ MTK_PIN_IES_SMT_SPEC(17, 17, 0x950, 2),
++ MTK_PIN_IES_SMT_SPEC(18, 21, 0x940, 3),
++ MTK_PIN_IES_SMT_SPEC(29, 32, 0x930, 3),
++ MTK_PIN_IES_SMT_SPEC(33, 33, 0x930, 4),
++ MTK_PIN_IES_SMT_SPEC(34, 36, 0x930, 5),
++ MTK_PIN_IES_SMT_SPEC(37, 38, 0x930, 6),
++ MTK_PIN_IES_SMT_SPEC(39, 39, 0x930, 7),
++ MTK_PIN_IES_SMT_SPEC(40, 41, 0x930, 9),
++ MTK_PIN_IES_SMT_SPEC(42, 42, 0x940, 0),
++ MTK_PIN_IES_SMT_SPEC(43, 44, 0x930, 11),
++ MTK_PIN_IES_SMT_SPEC(45, 46, 0x930, 12),
++ MTK_PIN_IES_SMT_SPEC(57, 64, 0xc20, 13),
++ MTK_PIN_IES_SMT_SPEC(65, 65, 0xc10, 13),
++ MTK_PIN_IES_SMT_SPEC(66, 66, 0xc00, 13),
++ MTK_PIN_IES_SMT_SPEC(67, 67, 0xd10, 13),
++ MTK_PIN_IES_SMT_SPEC(68, 68, 0xd00, 13),
++ MTK_PIN_IES_SMT_SPEC(69, 72, 0x940, 14),
++ MTK_PIN_IES_SMT_SPEC(73, 76, 0xc60, 13),
++ MTK_PIN_IES_SMT_SPEC(77, 77, 0xc40, 13),
++ MTK_PIN_IES_SMT_SPEC(78, 78, 0xc50, 13),
++ MTK_PIN_IES_SMT_SPEC(79, 82, 0x940, 15),
++ MTK_PIN_IES_SMT_SPEC(83, 83, 0x950, 0),
++ MTK_PIN_IES_SMT_SPEC(84, 85, 0x950, 1),
++ MTK_PIN_IES_SMT_SPEC(86, 91, 0x950, 2),
++ MTK_PIN_IES_SMT_SPEC(92, 92, 0x930, 13),
++ MTK_PIN_IES_SMT_SPEC(93, 95, 0x930, 14),
++ MTK_PIN_IES_SMT_SPEC(96, 99, 0x930, 15),
++ MTK_PIN_IES_SMT_SPEC(100, 103, 0xca0, 13),
++ MTK_PIN_IES_SMT_SPEC(104, 104, 0xc80, 13),
++ MTK_PIN_IES_SMT_SPEC(105, 105, 0xc90, 13),
++ MTK_PIN_IES_SMT_SPEC(106, 107, 0x940, 4),
++ MTK_PIN_IES_SMT_SPEC(108, 112, 0x940, 1),
++ MTK_PIN_IES_SMT_SPEC(113, 116, 0x940, 2),
++ MTK_PIN_IES_SMT_SPEC(117, 118, 0x940, 5),
++ MTK_PIN_IES_SMT_SPEC(119, 124, 0x940, 6),
++ MTK_PIN_IES_SMT_SPEC(125, 126, 0x940, 7),
++ MTK_PIN_IES_SMT_SPEC(127, 127, 0x940, 0),
++ MTK_PIN_IES_SMT_SPEC(128, 128, 0x950, 8),
++ MTK_PIN_IES_SMT_SPEC(129, 130, 0x950, 9),
++ MTK_PIN_IES_SMT_SPEC(131, 132, 0x950, 8),
++ MTK_PIN_IES_SMT_SPEC(133, 134, 0x910, 8)
+ };
+
+-static int spec_ies_smt_set(struct regmap *regmap, unsigned int pin,
+- unsigned char align, int value)
+-{
+- unsigned int i, reg_addr, bit;
+- bool find = false;
+-
+- for (i = 0; i < ARRAY_SIZE(mt8173_ies_smt_set); i++) {
+- if (pin >= mt8173_ies_smt_set[i].start &&
+- pin <= mt8173_ies_smt_set[i].end) {
+- find = true;
+- break;
+- }
+- }
+-
+- if (!find)
+- return -EINVAL;
+-
+- if (value)
+- reg_addr = mt8173_ies_smt_set[i].offset + align;
+- else
+- reg_addr = mt8173_ies_smt_set[i].offset + (align << 1);
++static const struct mtk_pin_ies_smt_set mt8173_ies_set[] = {
++ MTK_PIN_IES_SMT_SPEC(0, 4, 0x900, 1),
++ MTK_PIN_IES_SMT_SPEC(5, 9, 0x900, 2),
++ MTK_PIN_IES_SMT_SPEC(10, 13, 0x900, 10),
++ MTK_PIN_IES_SMT_SPEC(14, 15, 0x910, 10),
++ MTK_PIN_IES_SMT_SPEC(16, 16, 0x900, 0),
++ MTK_PIN_IES_SMT_SPEC(17, 17, 0x920, 2),
++ MTK_PIN_IES_SMT_SPEC(18, 21, 0x910, 3),
++ MTK_PIN_IES_SMT_SPEC(29, 32, 0x900, 3),
++ MTK_PIN_IES_SMT_SPEC(33, 33, 0x900, 4),
++ MTK_PIN_IES_SMT_SPEC(34, 36, 0x900, 5),
++ MTK_PIN_IES_SMT_SPEC(37, 38, 0x900, 6),
++ MTK_PIN_IES_SMT_SPEC(39, 39, 0x900, 7),
++ MTK_PIN_IES_SMT_SPEC(40, 41, 0x900, 9),
++ MTK_PIN_IES_SMT_SPEC(42, 42, 0x910, 0),
++ MTK_PIN_IES_SMT_SPEC(43, 44, 0x900, 11),
++ MTK_PIN_IES_SMT_SPEC(45, 46, 0x900, 12),
++ MTK_PIN_IES_SMT_SPEC(57, 64, 0xc20, 14),
++ MTK_PIN_IES_SMT_SPEC(65, 65, 0xc10, 14),
++ MTK_PIN_IES_SMT_SPEC(66, 66, 0xc00, 14),
++ MTK_PIN_IES_SMT_SPEC(67, 67, 0xd10, 14),
++ MTK_PIN_IES_SMT_SPEC(68, 68, 0xd00, 14),
++ MTK_PIN_IES_SMT_SPEC(69, 72, 0x910, 14),
++ MTK_PIN_IES_SMT_SPEC(73, 76, 0xc60, 14),
++ MTK_PIN_IES_SMT_SPEC(77, 77, 0xc40, 14),
++ MTK_PIN_IES_SMT_SPEC(78, 78, 0xc50, 14),
++ MTK_PIN_IES_SMT_SPEC(79, 82, 0x910, 15),
++ MTK_PIN_IES_SMT_SPEC(83, 83, 0x920, 0),
++ MTK_PIN_IES_SMT_SPEC(84, 85, 0x920, 1),
++ MTK_PIN_IES_SMT_SPEC(86, 91, 0x920, 2),
++ MTK_PIN_IES_SMT_SPEC(92, 92, 0x900, 13),
++ MTK_PIN_IES_SMT_SPEC(93, 95, 0x900, 14),
++ MTK_PIN_IES_SMT_SPEC(96, 99, 0x900, 15),
++ MTK_PIN_IES_SMT_SPEC(100, 103, 0xca0, 14),
++ MTK_PIN_IES_SMT_SPEC(104, 104, 0xc80, 14),
++ MTK_PIN_IES_SMT_SPEC(105, 105, 0xc90, 14),
++ MTK_PIN_IES_SMT_SPEC(106, 107, 0x91, 4),
++ MTK_PIN_IES_SMT_SPEC(108, 112, 0x910, 1),
++ MTK_PIN_IES_SMT_SPEC(113, 116, 0x910, 2),
++ MTK_PIN_IES_SMT_SPEC(117, 118, 0x910, 5),
++ MTK_PIN_IES_SMT_SPEC(119, 124, 0x910, 6),
++ MTK_PIN_IES_SMT_SPEC(125, 126, 0x910, 7),
++ MTK_PIN_IES_SMT_SPEC(127, 127, 0x910, 0),
++ MTK_PIN_IES_SMT_SPEC(128, 128, 0x920, 8),
++ MTK_PIN_IES_SMT_SPEC(129, 130, 0x920, 9),
++ MTK_PIN_IES_SMT_SPEC(131, 132, 0x920, 8),
++ MTK_PIN_IES_SMT_SPEC(133, 134, 0x910, 8)
++};
+
+- bit = BIT(mt8173_ies_smt_set[i].bit);
+- regmap_write(regmap, reg_addr, bit);
+- return 0;
++static int mt8173_ies_smt_set(struct regmap *regmap, unsigned int pin,
++ unsigned char align, int value, enum pin_config_param arg)
++{
++ if (arg == PIN_CONFIG_INPUT_ENABLE)
++ return mtk_pconf_spec_set_ies_smt_range(regmap, mt8173_ies_set,
++ ARRAY_SIZE(mt8173_ies_set), pin, align, value);
++ else if (arg == PIN_CONFIG_INPUT_SCHMITT_ENABLE)
++ return mtk_pconf_spec_set_ies_smt_range(regmap, mt8173_smt_set,
++ ARRAY_SIZE(mt8173_smt_set), pin, align, value);
++ return -EINVAL;
+ }
+
+ static const struct mtk_drv_group_desc mt8173_drv_grp[] = {
+@@ -307,7 +320,7 @@ static const struct mtk_pinctrl_devdata mt8173_pinctrl_data = {
+ .pin_drv_grp = mt8173_pin_drv,
+ .n_pin_drv_grps = ARRAY_SIZE(mt8173_pin_drv),
+ .spec_pull_set = mt8173_spec_pull_set,
+- .spec_ies_smt_set = spec_ies_smt_set,
++ .spec_ies_smt_set = mt8173_ies_smt_set,
+ .dir_offset = 0x0000,
+ .pullen_offset = 0x0100,
+ .pullsel_offset = 0x0200,
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+index 0d51145..97fe2ab 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+@@ -107,28 +107,38 @@ static void mtk_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+ regmap_write(mtk_get_regmap(pctl, offset), reg_addr, bit);
+ }
+
+-static void mtk_pconf_set_ies_smt(struct mtk_pinctrl *pctl, unsigned pin,
+- int value, enum pin_config_param param)
++static int mtk_pconf_set_ies_smt(struct mtk_pinctrl *pctl, unsigned pin,
++ int value, enum pin_config_param arg)
+ {
+ unsigned int reg_addr, offset;
+ unsigned int bit;
+- int ret;
++
++ /**
++ * Due to some soc are not support ies/smt config, add this special
++ * control to handle it.
++ */
++ if (!pctl->devdata->spec_ies_smt_set &&
++ pctl->devdata->ies_offset == MTK_PINCTRL_NOT_SUPPORT &&
++ arg == PIN_CONFIG_INPUT_ENABLE)
++ return -EINVAL;
++
++ if (!pctl->devdata->spec_ies_smt_set &&
++ pctl->devdata->smt_offset == MTK_PINCTRL_NOT_SUPPORT &&
++ arg == PIN_CONFIG_INPUT_SCHMITT_ENABLE)
++ return -EINVAL;
+
+ /*
+ * Due to some pins are irregular, their input enable and smt
+- * control register are discontinuous, but they are mapping together.
+- * So we need this special handle.
++ * control register are discontinuous, so we need this special handle.
+ */
+ if (pctl->devdata->spec_ies_smt_set) {
+- ret = pctl->devdata->spec_ies_smt_set(mtk_get_regmap(pctl, pin),
+- pin, pctl->devdata->port_align, value);
+- if (!ret)
+- return;
++ return pctl->devdata->spec_ies_smt_set(mtk_get_regmap(pctl, pin),
++ pin, pctl->devdata->port_align, value, arg);
+ }
+
+ bit = BIT(pin & 0xf);
+
+- if (param == PIN_CONFIG_INPUT_ENABLE)
++ if (arg == PIN_CONFIG_INPUT_ENABLE)
+ offset = pctl->devdata->ies_offset;
+ else
+ offset = pctl->devdata->smt_offset;
+@@ -139,6 +149,33 @@ static void mtk_pconf_set_ies_smt(struct mtk_pinctrl *pctl, unsigned pin,
+ reg_addr = CLR_ADDR(mtk_get_port(pctl, pin) + offset, pctl);
+
+ regmap_write(mtk_get_regmap(pctl, pin), reg_addr, bit);
++ return 0;
++}
++
++int mtk_pconf_spec_set_ies_smt_range(struct regmap *regmap,
++ const struct mtk_pin_ies_smt_set *ies_smt_infos, unsigned int info_num,
++ unsigned int pin, unsigned char align, int value)
++{
++ unsigned int i, reg_addr, bit;
++
++ for (i = 0; i < info_num; i++) {
++ if (pin >= ies_smt_infos[i].start &&
++ pin <= ies_smt_infos[i].end) {
++ break;
++ }
++ }
++
++ if (i == info_num)
++ return -EINVAL;
++
++ if (value)
++ reg_addr = ies_smt_infos[i].offset + align;
++ else
++ reg_addr = ies_smt_infos[i].offset + (align << 1);
++
++ bit = BIT(ies_smt_infos[i].bit);
++ regmap_write(regmap, reg_addr, bit);
++ return 0;
+ }
+
+ static const struct mtk_pin_drv_grp *mtk_find_pin_drv_grp_by_pin(
+@@ -295,36 +332,37 @@ static int mtk_pconf_parse_conf(struct pinctrl_dev *pctldev,
+ unsigned int pin, enum pin_config_param param,
+ enum pin_config_param arg)
+ {
++ int ret = 0;
+ struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+- mtk_pconf_set_pull_select(pctl, pin, false, false, arg);
++ ret = mtk_pconf_set_pull_select(pctl, pin, false, false, arg);
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+- mtk_pconf_set_pull_select(pctl, pin, true, true, arg);
++ ret = mtk_pconf_set_pull_select(pctl, pin, true, true, arg);
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+- mtk_pconf_set_pull_select(pctl, pin, true, false, arg);
++ ret = mtk_pconf_set_pull_select(pctl, pin, true, false, arg);
+ break;
+ case PIN_CONFIG_INPUT_ENABLE:
+- mtk_pconf_set_ies_smt(pctl, pin, arg, param);
++ ret = mtk_pconf_set_ies_smt(pctl, pin, arg, param);
+ break;
+ case PIN_CONFIG_OUTPUT:
+ mtk_gpio_set(pctl->chip, pin, arg);
+- mtk_pmx_gpio_set_direction(pctldev, NULL, pin, false);
++ ret = mtk_pmx_gpio_set_direction(pctldev, NULL, pin, false);
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+- mtk_pconf_set_ies_smt(pctl, pin, arg, param);
++ ret = mtk_pconf_set_ies_smt(pctl, pin, arg, param);
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+- mtk_pconf_set_driving(pctl, pin, arg);
++ ret = mtk_pconf_set_driving(pctl, pin, arg);
+ break;
+ default:
+- return -EINVAL;
++ ret = -EINVAL;
+ }
+
+- return 0;
++ return ret;
+ }
+
+ static int mtk_pconf_group_get(struct pinctrl_dev *pctldev,
+@@ -343,12 +381,14 @@ static int mtk_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
+ {
+ struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct mtk_pinctrl_group *g = &pctl->groups[group];
+- int i;
++ int i, ret;
+
+ for (i = 0; i < num_configs; i++) {
+- mtk_pconf_parse_conf(pctldev, g->pin,
++ ret = mtk_pconf_parse_conf(pctldev, g->pin,
+ pinconf_to_config_param(configs[i]),
+ pinconf_to_config_argument(configs[i]));
++ if (ret < 0)
++ return ret;
+
+ g->config = configs[i];
+ }
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+index 2a4b7be..c703e7d 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+@@ -17,6 +17,7 @@
+
+ #include <linux/pinctrl/pinctrl.h>
+ #include <linux/regmap.h>
++#include <linux/pinctrl/pinconf-generic.h>
+
+ #define NO_EINT_SUPPORT 255
+ #define MT_EDGE_SENSITIVE 0
+@@ -25,6 +26,8 @@
+ #define EINT_DBNC_RST_BIT (0x1 << 1)
+ #define EINT_DBNC_SET_EN (0x1 << 0)
+
++#define MTK_PINCTRL_NOT_SUPPORT (0xffff)
++
+ struct mtk_desc_function {
+ const char *name;
+ unsigned char muxval;
+@@ -143,6 +146,28 @@ struct mtk_pin_spec_pupd_set_samereg {
+ .r0_bit = _r0, \
+ }
+
++/**
++ * struct mtk_pin_ies_set - For special pins' ies and smt setting.
++ * @start: The start pin number of those special pins.
++ * @end: The end pin number of those special pins.
++ * @offset: The offset of special setting register.
++ * @bit: The bit of special setting register.
++ */
++struct mtk_pin_ies_smt_set {
++ unsigned short start;
++ unsigned short end;
++ unsigned short offset;
++ unsigned char bit;
++};
++
++#define MTK_PIN_IES_SMT_SPEC(_start, _end, _offset, _bit) \
++ { \
++ .start = _start, \
++ .end = _end, \
++ .bit = _bit, \
++ .offset = _offset, \
++ }
++
+ struct mtk_eint_offsets {
+ const char *name;
+ unsigned int stat;
+@@ -208,7 +233,7 @@ struct mtk_pinctrl_devdata {
+ int (*spec_pull_set)(struct regmap *reg, unsigned int pin,
+ unsigned char align, bool isup, unsigned int arg);
+ int (*spec_ies_smt_set)(struct regmap *reg, unsigned int pin,
+- unsigned char align, int value);
++ unsigned char align, int value, enum pin_config_param arg);
+ unsigned int dir_offset;
+ unsigned int ies_offset;
+ unsigned int smt_offset;
+@@ -251,4 +276,8 @@ int mtk_pctrl_spec_pull_set_samereg(struct regmap *regmap,
+ unsigned int info_num, unsigned int pin,
+ unsigned char align, bool isup, unsigned int r1r0);
+
++int mtk_pconf_spec_set_ies_smt_range(struct regmap *regmap,
++ const struct mtk_pin_ies_smt_set *ies_smt_infos, unsigned int info_num,
++ unsigned int pin, unsigned char align, int value);
++
+ #endif /* __PINCTRL_MTK_COMMON_H */
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0053-pinctrl-mediatek-Add-Pinctrl-GPIO-driver-for-mt6397.patch b/target/linux/mediatek/patches/0053-pinctrl-mediatek-Add-Pinctrl-GPIO-driver-for-mt6397.patch
new file mode 100644
index 0000000000..2813f407d5
--- /dev/null
+++ b/target/linux/mediatek/patches/0053-pinctrl-mediatek-Add-Pinctrl-GPIO-driver-for-mt6397.patch
@@ -0,0 +1,654 @@
+From 3031cefd8cd323e04be11a8058616d8cf21c1313 Mon Sep 17 00:00:00 2001
+From: Hongzhou Yang <hongzhou.yang@mediatek.com>
+Date: Mon, 18 May 2015 23:11:17 -0700
+Subject: [PATCH 53/76] pinctrl: mediatek: Add Pinctrl/GPIO driver for mt6397.
+
+Add mt6397 support using mediatek common pinctrl driver.
+
+mt6397 is a PMIC, and pinctrl/GPIO is part of 6397 chip.
+Pinctrl/GPIO driver should obtain regmap from PMIC,
+so adding this support to common code.
+
+Also, mt6397 is no need to support interrupt controller,
+so changing common code to skip it.
+
+Signed-off-by: Hongzhou Yang <hongzhou.yang@mediatek.com>
+---
+ drivers/pinctrl/mediatek/Kconfig | 6 +
+ drivers/pinctrl/mediatek/Makefile | 1 +
+ drivers/pinctrl/mediatek/pinctrl-mt6397.c | 78 +++++
+ drivers/pinctrl/mediatek/pinctrl-mt8135.c | 2 +-
+ drivers/pinctrl/mediatek/pinctrl-mt8173.c | 2 +-
+ drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 13 +-
+ drivers/pinctrl/mediatek/pinctrl-mtk-common.h | 3 +-
+ drivers/pinctrl/mediatek/pinctrl-mtk-mt6397.h | 424 +++++++++++++++++++++++++
+ 8 files changed, 524 insertions(+), 5 deletions(-)
+ create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt6397.c
+ create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-mt6397.h
+
+diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
+index 6b3551c..ddae479 100644
+--- a/drivers/pinctrl/mediatek/Kconfig
++++ b/drivers/pinctrl/mediatek/Kconfig
+@@ -23,4 +23,10 @@ config PINCTRL_MT8173
+ default ARM64 && ARCH_MEDIATEK
+ select PINCTRL_MTK_COMMON
+
++# For PMIC
++config PINCTRL_MT6397
++ bool "Mediatek MT6397 pin control" if COMPILE_TEST && !MFD_MT6397
++ default MFD_MT6397
++ select PINCTRL_MTK_COMMON
++
+ endif
+diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
+index d8606a2..ad0180c 100644
+--- a/drivers/pinctrl/mediatek/Makefile
++++ b/drivers/pinctrl/mediatek/Makefile
+@@ -4,3 +4,4 @@ obj-$(CONFIG_PINCTRL_MTK_COMMON) += pinctrl-mtk-common.o
+ # SoC Drivers
+ obj-$(CONFIG_PINCTRL_MT8135) += pinctrl-mt8135.o
+ obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o
++obj-$(CONFIG_PINCTRL_MT6397) += pinctrl-mt6397.o
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mt6397.c b/drivers/pinctrl/mediatek/pinctrl-mt6397.c
+new file mode 100644
+index 0000000..767bbdf
+--- /dev/null
++++ b/drivers/pinctrl/mediatek/pinctrl-mt6397.c
+@@ -0,0 +1,78 @@
++/*
++ * Copyright (c) 2015 MediaTek Inc.
++ * Author: Hongzhou.Yang <hongzhou.yang@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/pinctrl/pinconf-generic.h>
++#include <linux/mfd/mt6397/core.h>
++
++#include "pinctrl-mtk-common.h"
++#include "pinctrl-mtk-mt6397.h"
++
++#define MT6397_PIN_REG_BASE 0xc000
++
++static const struct mtk_pinctrl_devdata mt6397_pinctrl_data = {
++ .pins = mtk_pins_mt6397,
++ .npins = ARRAY_SIZE(mtk_pins_mt6397),
++ .dir_offset = (MT6397_PIN_REG_BASE + 0x000),
++ .ies_offset = MTK_PINCTRL_NOT_SUPPORT,
++ .smt_offset = MTK_PINCTRL_NOT_SUPPORT,
++ .pullen_offset = (MT6397_PIN_REG_BASE + 0x020),
++ .pullsel_offset = (MT6397_PIN_REG_BASE + 0x040),
++ .dout_offset = (MT6397_PIN_REG_BASE + 0x080),
++ .din_offset = (MT6397_PIN_REG_BASE + 0x0a0),
++ .pinmux_offset = (MT6397_PIN_REG_BASE + 0x0c0),
++ .type1_start = 41,
++ .type1_end = 41,
++ .port_shf = 3,
++ .port_mask = 0x3,
++ .port_align = 2,
++};
++
++static int mt6397_pinctrl_probe(struct platform_device *pdev)
++{
++ struct mt6397_chip *mt6397;
++
++ mt6397 = dev_get_drvdata(pdev->dev.parent);
++ return mtk_pctrl_init(pdev, &mt6397_pinctrl_data, mt6397->regmap);
++}
++
++static const struct of_device_id mt6397_pctrl_match[] = {
++ { .compatible = "mediatek,mt6397-pinctrl", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, mt6397_pctrl_match);
++
++static struct platform_driver mtk_pinctrl_driver = {
++ .probe = mt6397_pinctrl_probe,
++ .driver = {
++ .name = "mediatek-mt6397-pinctrl",
++ .owner = THIS_MODULE,
++ .of_match_table = mt6397_pctrl_match,
++ },
++};
++
++static int __init mtk_pinctrl_init(void)
++{
++ return platform_driver_register(&mtk_pinctrl_driver);
++}
++
++module_init(mtk_pinctrl_init);
++
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("MediaTek MT6397 Pinctrl Driver");
++MODULE_AUTHOR("Hongzhou Yang <hongzhou.yang@mediatek.com>");
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8135.c b/drivers/pinctrl/mediatek/pinctrl-mt8135.c
+index 8e6abd5..203bd2a 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mt8135.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mt8135.c
+@@ -342,7 +342,7 @@ static const struct mtk_pinctrl_devdata mt8135_pinctrl_data = {
+
+ static int mt8135_pinctrl_probe(struct platform_device *pdev)
+ {
+- return mtk_pctrl_init(pdev, &mt8135_pinctrl_data);
++ return mtk_pctrl_init(pdev, &mt8135_pinctrl_data, NULL);
+ }
+
+ static const struct of_device_id mt8135_pctrl_match[] = {
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8173.c b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
+index a7e5b24..cf4ed6e 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mt8173.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
+@@ -361,7 +361,7 @@ static const struct mtk_pinctrl_devdata mt8173_pinctrl_data = {
+
+ static int mt8173_pinctrl_probe(struct platform_device *pdev)
+ {
+- return mtk_pctrl_init(pdev, &mt8173_pinctrl_data);
++ return mtk_pctrl_init(pdev, &mt8173_pinctrl_data, NULL);
+ }
+
+ static const struct of_device_id mt8173_pctrl_match[] = {
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+index 97fe2ab..e772cef 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+@@ -1209,7 +1209,8 @@ static struct pinctrl_desc mtk_pctrl_desc = {
+ };
+
+ int mtk_pctrl_init(struct platform_device *pdev,
+- const struct mtk_pinctrl_devdata *data)
++ const struct mtk_pinctrl_devdata *data,
++ struct regmap *regmap)
+ {
+ struct pinctrl_pin_desc *pins;
+ struct mtk_pinctrl *pctl;
+@@ -1235,6 +1236,11 @@ int mtk_pctrl_init(struct platform_device *pdev,
+ pctl->regmap1 = syscon_node_to_regmap(node);
+ if (IS_ERR(pctl->regmap1))
+ return PTR_ERR(pctl->regmap1);
++ } else if (regmap) {
++ pctl->regmap1 = regmap;
++ } else {
++ dev_err(&pdev->dev, "Pinctrl node has not register regmap.\n");
++ return -EINVAL;
+ }
+
+ /* Only 8135 has two base addr, other SoCs have only one. */
+@@ -1280,7 +1286,7 @@ int mtk_pctrl_init(struct platform_device *pdev,
+ pctl->chip->ngpio = pctl->devdata->npins;
+ pctl->chip->label = dev_name(&pdev->dev);
+ pctl->chip->dev = &pdev->dev;
+- pctl->chip->base = 0;
++ pctl->chip->base = -1;
+
+ ret = gpiochip_add(pctl->chip);
+ if (ret) {
+@@ -1296,6 +1302,9 @@ int mtk_pctrl_init(struct platform_device *pdev,
+ goto chip_error;
+ }
+
++ if (of_find_property(np, "interrupt-controller", NULL))
++ return 0;
++
+ /* Get EINT register base from dts. */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+index c703e7d..30213e5 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+@@ -269,7 +269,8 @@ struct mtk_pinctrl {
+ };
+
+ int mtk_pctrl_init(struct platform_device *pdev,
+- const struct mtk_pinctrl_devdata *data);
++ const struct mtk_pinctrl_devdata *data,
++ struct regmap *regmap);
+
+ int mtk_pctrl_spec_pull_set_samereg(struct regmap *regmap,
+ const struct mtk_pin_spec_pupd_set_samereg *pupd_infos,
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt6397.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt6397.h
+new file mode 100644
+index 0000000..4eb98dd
+--- /dev/null
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt6397.h
+@@ -0,0 +1,424 @@
++#ifndef __PINCTRL_MTK_MT6397_H
++#define __PINCTRL_MTK_MT6397_H
++
++#include <linux/pinctrl/pinctrl.h>
++#include "pinctrl-mtk-common.h"
++
++static const struct mtk_desc_pin mtk_pins_mt6397[] = {
++ MTK_PIN(
++ PINCTRL_PIN(0, "INT"),
++ "N2", "mt6397",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO0"),
++ MTK_FUNCTION(1, "INT")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(1, "SRCVOLTEN"),
++ "M4", "mt6397",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO1"),
++ MTK_FUNCTION(1, "SRCVOLTEN"),
++ MTK_FUNCTION(6, "TEST_CK1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(2, "SRCLKEN_PERI"),
++ "M2", "mt6397",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO2"),
++ MTK_FUNCTION(1, "SRCLKEN_PERI"),
++ MTK_FUNCTION(6, "TEST_CK2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(3, "RTC_32K1V8"),
++ "K3", "mt6397",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO3"),
++ MTK_FUNCTION(1, "RTC_32K1V8"),
++ MTK_FUNCTION(6, "TEST_CK3")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(4, "WRAP_EVENT"),
++ "J2", "mt6397",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO4"),
++ MTK_FUNCTION(1, "WRAP_EVENT")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(5, "SPI_CLK"),
++ "L4", "mt6397",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO5"),
++ MTK_FUNCTION(1, "SPI_CLK")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(6, "SPI_CSN"),
++ "J3", "mt6397",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO6"),
++ MTK_FUNCTION(1, "SPI_CSN")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(7, "SPI_MOSI"),
++ "J1", "mt6397",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO7"),
++ MTK_FUNCTION(1, "SPI_MOSI")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(8, "SPI_MISO"),
++ "L3", "mt6397",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO8"),
++ MTK_FUNCTION(1, "SPI_MISO")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(9, "AUD_CLK_MOSI"),
++ "H2", "mt6397",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO9"),
++ MTK_FUNCTION(1, "AUD_CLK"),
++ MTK_FUNCTION(6, "TEST_IN0"),
++ MTK_FUNCTION(7, "TEST_OUT0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(10, "AUD_DAT_MISO"),
++ "H3", "mt6397",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO10"),
++ MTK_FUNCTION(1, "AUD_MISO"),
++ MTK_FUNCTION(6, "TEST_IN1"),
++ MTK_FUNCTION(7, "TEST_OUT1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(11, "AUD_DAT_MOSI"),
++ "H1", "mt6397",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO11"),
++ MTK_FUNCTION(1, "AUD_MOSI"),
++ MTK_FUNCTION(6, "TEST_IN2"),
++ MTK_FUNCTION(7, "TEST_OUT2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(12, "COL0"),
++ "F3", "mt6397",
++ MTK_EINT_FUNCTION(2, 10),
++ MTK_FUNCTION(0, "GPIO12"),
++ MTK_FUNCTION(1, "COL0_USBDL"),
++ MTK_FUNCTION(2, "EINT10_1X"),
++ MTK_FUNCTION(3, "PWM1_3X"),
++ MTK_FUNCTION(6, "TEST_IN3"),
++ MTK_FUNCTION(7, "TEST_OUT3")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(13, "COL1"),
++ "G8", "mt6397",
++ MTK_EINT_FUNCTION(2, 11),
++ MTK_FUNCTION(0, "GPIO13"),
++ MTK_FUNCTION(1, "COL1"),
++ MTK_FUNCTION(2, "EINT11_1X"),
++ MTK_FUNCTION(3, "SCL0_2X"),
++ MTK_FUNCTION(6, "TEST_IN4"),
++ MTK_FUNCTION(7, "TEST_OUT4")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(14, "COL2"),
++ "H4", "mt6397",
++ MTK_EINT_FUNCTION(2, 12),
++ MTK_FUNCTION(0, "GPIO14"),
++ MTK_FUNCTION(1, "COL2"),
++ MTK_FUNCTION(2, "EINT12_1X"),
++ MTK_FUNCTION(3, "SDA0_2X"),
++ MTK_FUNCTION(6, "TEST_IN5"),
++ MTK_FUNCTION(7, "TEST_OUT5")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(15, "COL3"),
++ "G2", "mt6397",
++ MTK_EINT_FUNCTION(2, 13),
++ MTK_FUNCTION(0, "GPIO15"),
++ MTK_FUNCTION(1, "COL3"),
++ MTK_FUNCTION(2, "EINT13_1X"),
++ MTK_FUNCTION(3, "SCL1_2X"),
++ MTK_FUNCTION(6, "TEST_IN6"),
++ MTK_FUNCTION(7, "TEST_OUT6")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(16, "COL4"),
++ "F2", "mt6397",
++ MTK_EINT_FUNCTION(2, 14),
++ MTK_FUNCTION(0, "GPIO16"),
++ MTK_FUNCTION(1, "COL4"),
++ MTK_FUNCTION(2, "EINT14_1X"),
++ MTK_FUNCTION(3, "SDA1_2X"),
++ MTK_FUNCTION(6, "TEST_IN7"),
++ MTK_FUNCTION(7, "TEST_OUT7")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(17, "COL5"),
++ "G7", "mt6397",
++ MTK_EINT_FUNCTION(2, 15),
++ MTK_FUNCTION(0, "GPIO17"),
++ MTK_FUNCTION(1, "COL5"),
++ MTK_FUNCTION(2, "EINT15_1X"),
++ MTK_FUNCTION(3, "SCL2_2X"),
++ MTK_FUNCTION(6, "TEST_IN8"),
++ MTK_FUNCTION(7, "TEST_OUT8")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(18, "COL6"),
++ "J6", "mt6397",
++ MTK_EINT_FUNCTION(2, 16),
++ MTK_FUNCTION(0, "GPIO18"),
++ MTK_FUNCTION(1, "COL6"),
++ MTK_FUNCTION(2, "EINT16_1X"),
++ MTK_FUNCTION(3, "SDA2_2X"),
++ MTK_FUNCTION(4, "GPIO32K_0"),
++ MTK_FUNCTION(5, "GPIO26M_0"),
++ MTK_FUNCTION(6, "TEST_IN9"),
++ MTK_FUNCTION(7, "TEST_OUT9")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(19, "COL7"),
++ "J5", "mt6397",
++ MTK_EINT_FUNCTION(2, 17),
++ MTK_FUNCTION(0, "GPIO19"),
++ MTK_FUNCTION(1, "COL7"),
++ MTK_FUNCTION(2, "EINT17_1X"),
++ MTK_FUNCTION(3, "PWM2_3X"),
++ MTK_FUNCTION(4, "GPIO32K_1"),
++ MTK_FUNCTION(5, "GPIO26M_1"),
++ MTK_FUNCTION(6, "TEST_IN10"),
++ MTK_FUNCTION(7, "TEST_OUT10")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(20, "ROW0"),
++ "L7", "mt6397",
++ MTK_EINT_FUNCTION(2, 18),
++ MTK_FUNCTION(0, "GPIO20"),
++ MTK_FUNCTION(1, "ROW0"),
++ MTK_FUNCTION(2, "EINT18_1X"),
++ MTK_FUNCTION(3, "SCL0_3X"),
++ MTK_FUNCTION(6, "TEST_IN11"),
++ MTK_FUNCTION(7, "TEST_OUT11")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(21, "ROW1"),
++ "P1", "mt6397",
++ MTK_EINT_FUNCTION(2, 19),
++ MTK_FUNCTION(0, "GPIO21"),
++ MTK_FUNCTION(1, "ROW1"),
++ MTK_FUNCTION(2, "EINT19_1X"),
++ MTK_FUNCTION(3, "SDA0_3X"),
++ MTK_FUNCTION(4, "AUD_TSTCK"),
++ MTK_FUNCTION(6, "TEST_IN12"),
++ MTK_FUNCTION(7, "TEST_OUT12")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(22, "ROW2"),
++ "J8", "mt6397",
++ MTK_EINT_FUNCTION(2, 20),
++ MTK_FUNCTION(0, "GPIO22"),
++ MTK_FUNCTION(1, "ROW2"),
++ MTK_FUNCTION(2, "EINT20_1X"),
++ MTK_FUNCTION(3, "SCL1_3X"),
++ MTK_FUNCTION(6, "TEST_IN13"),
++ MTK_FUNCTION(7, "TEST_OUT13")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(23, "ROW3"),
++ "J7", "mt6397",
++ MTK_EINT_FUNCTION(2, 21),
++ MTK_FUNCTION(0, "GPIO23"),
++ MTK_FUNCTION(1, "ROW3"),
++ MTK_FUNCTION(2, "EINT21_1X"),
++ MTK_FUNCTION(3, "SDA1_3X"),
++ MTK_FUNCTION(6, "TEST_IN14"),
++ MTK_FUNCTION(7, "TEST_OUT14")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(24, "ROW4"),
++ "L5", "mt6397",
++ MTK_EINT_FUNCTION(2, 22),
++ MTK_FUNCTION(0, "GPIO24"),
++ MTK_FUNCTION(1, "ROW4"),
++ MTK_FUNCTION(2, "EINT22_1X"),
++ MTK_FUNCTION(3, "SCL2_3X"),
++ MTK_FUNCTION(6, "TEST_IN15"),
++ MTK_FUNCTION(7, "TEST_OUT15")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(25, "ROW5"),
++ "N6", "mt6397",
++ MTK_EINT_FUNCTION(2, 23),
++ MTK_FUNCTION(0, "GPIO25"),
++ MTK_FUNCTION(1, "ROW5"),
++ MTK_FUNCTION(2, "EINT23_1X"),
++ MTK_FUNCTION(3, "SDA2_3X"),
++ MTK_FUNCTION(6, "TEST_IN16"),
++ MTK_FUNCTION(7, "TEST_OUT16")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(26, "ROW6"),
++ "L6", "mt6397",
++ MTK_EINT_FUNCTION(2, 24),
++ MTK_FUNCTION(0, "GPIO26"),
++ MTK_FUNCTION(1, "ROW6"),
++ MTK_FUNCTION(2, "EINT24_1X"),
++ MTK_FUNCTION(3, "PWM3_3X"),
++ MTK_FUNCTION(4, "GPIO32K_2"),
++ MTK_FUNCTION(5, "GPIO26M_2"),
++ MTK_FUNCTION(6, "TEST_IN17"),
++ MTK_FUNCTION(7, "TEST_OUT17")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(27, "ROW7"),
++ "P2", "mt6397",
++ MTK_EINT_FUNCTION(2, 3),
++ MTK_FUNCTION(0, "GPIO27"),
++ MTK_FUNCTION(1, "ROW7"),
++ MTK_FUNCTION(2, "EINT3_1X"),
++ MTK_FUNCTION(3, "CBUS"),
++ MTK_FUNCTION(4, "GPIO32K_3"),
++ MTK_FUNCTION(5, "GPIO26M_3"),
++ MTK_FUNCTION(6, "TEST_IN18"),
++ MTK_FUNCTION(7, "TEST_OUT18")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(28, "PWM1(VMSEL1)"),
++ "J4", "mt6397",
++ MTK_EINT_FUNCTION(2, 4),
++ MTK_FUNCTION(0, "GPIO28"),
++ MTK_FUNCTION(1, "PWM1"),
++ MTK_FUNCTION(2, "EINT4_1X"),
++ MTK_FUNCTION(4, "GPIO32K_4"),
++ MTK_FUNCTION(5, "GPIO26M_4"),
++ MTK_FUNCTION(6, "TEST_IN19"),
++ MTK_FUNCTION(7, "TEST_OUT19")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(29, "PWM2(VMSEL2)"),
++ "N5", "mt6397",
++ MTK_EINT_FUNCTION(2, 5),
++ MTK_FUNCTION(0, "GPIO29"),
++ MTK_FUNCTION(1, "PWM2"),
++ MTK_FUNCTION(2, "EINT5_1X"),
++ MTK_FUNCTION(4, "GPIO32K_5"),
++ MTK_FUNCTION(5, "GPIO26M_5"),
++ MTK_FUNCTION(6, "TEST_IN20"),
++ MTK_FUNCTION(7, "TEST_OUT20")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(30, "PWM3(PWM)"),
++ "R3", "mt6397",
++ MTK_EINT_FUNCTION(2, 6),
++ MTK_FUNCTION(0, "GPIO30"),
++ MTK_FUNCTION(1, "PWM3"),
++ MTK_FUNCTION(2, "EINT6_1X"),
++ MTK_FUNCTION(3, "COL0"),
++ MTK_FUNCTION(4, "GPIO32K_6"),
++ MTK_FUNCTION(5, "GPIO26M_6"),
++ MTK_FUNCTION(6, "TEST_IN21"),
++ MTK_FUNCTION(7, "TEST_OUT21")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(31, "SCL0"),
++ "N1", "mt6397",
++ MTK_EINT_FUNCTION(2, 7),
++ MTK_FUNCTION(0, "GPIO31"),
++ MTK_FUNCTION(1, "SCL0"),
++ MTK_FUNCTION(2, "EINT7_1X"),
++ MTK_FUNCTION(3, "PWM1_2X"),
++ MTK_FUNCTION(6, "TEST_IN22"),
++ MTK_FUNCTION(7, "TEST_OUT22")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(32, "SDA0"),
++ "N3", "mt6397",
++ MTK_EINT_FUNCTION(2, 8),
++ MTK_FUNCTION(0, "GPIO32"),
++ MTK_FUNCTION(1, "SDA0"),
++ MTK_FUNCTION(2, "EINT8_1X"),
++ MTK_FUNCTION(6, "TEST_IN23"),
++ MTK_FUNCTION(7, "TEST_OUT23")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(33, "SCL1"),
++ "T1", "mt6397",
++ MTK_EINT_FUNCTION(2, 9),
++ MTK_FUNCTION(0, "GPIO33"),
++ MTK_FUNCTION(1, "SCL1"),
++ MTK_FUNCTION(2, "EINT9_1X"),
++ MTK_FUNCTION(3, "PWM2_2X"),
++ MTK_FUNCTION(6, "TEST_IN24"),
++ MTK_FUNCTION(7, "TEST_OUT24")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(34, "SDA1"),
++ "T2", "mt6397",
++ MTK_EINT_FUNCTION(2, 0),
++ MTK_FUNCTION(0, "GPIO34"),
++ MTK_FUNCTION(1, "SDA1"),
++ MTK_FUNCTION(2, "EINT0_1X"),
++ MTK_FUNCTION(6, "TEST_IN25"),
++ MTK_FUNCTION(7, "TEST_OUT25")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(35, "SCL2"),
++ "T3", "mt6397",
++ MTK_EINT_FUNCTION(2, 1),
++ MTK_FUNCTION(0, "GPIO35"),
++ MTK_FUNCTION(1, "SCL2"),
++ MTK_FUNCTION(2, "EINT1_1X"),
++ MTK_FUNCTION(3, "PWM3_2X"),
++ MTK_FUNCTION(6, "TEST_IN26"),
++ MTK_FUNCTION(7, "TEST_OUT26")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(36, "SDA2"),
++ "U2", "mt6397",
++ MTK_EINT_FUNCTION(2, 2),
++ MTK_FUNCTION(0, "GPIO36"),
++ MTK_FUNCTION(1, "SDA2"),
++ MTK_FUNCTION(2, "EINT2_1X"),
++ MTK_FUNCTION(6, "TEST_IN27"),
++ MTK_FUNCTION(7, "TEST_OUT27")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(37, "HDMISD"),
++ "H6", "mt6397",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO37"),
++ MTK_FUNCTION(1, "HDMISD"),
++ MTK_FUNCTION(6, "TEST_IN28"),
++ MTK_FUNCTION(7, "TEST_OUT28")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(38, "HDMISCK"),
++ "H5", "mt6397",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO38"),
++ MTK_FUNCTION(1, "HDMISCK"),
++ MTK_FUNCTION(6, "TEST_IN29"),
++ MTK_FUNCTION(7, "TEST_OUT29")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(39, "HTPLG"),
++ "H7", "mt6397",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO39"),
++ MTK_FUNCTION(1, "HTPLG"),
++ MTK_FUNCTION(6, "TEST_IN30"),
++ MTK_FUNCTION(7, "TEST_OUT30")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(40, "CEC"),
++ "J9", "mt6397",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO40"),
++ MTK_FUNCTION(1, "CEC"),
++ MTK_FUNCTION(6, "TEST_IN31"),
++ MTK_FUNCTION(7, "TEST_OUT31")
++ ),
++};
++
++#endif /* __PINCTRL_MTK_MT6397_H */
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0054-pinctrl-mediatek-add-pinctrl-GPIO-EINT-driver-for-mt.patch b/target/linux/mediatek/patches/0054-pinctrl-mediatek-add-pinctrl-GPIO-EINT-driver-for-mt.patch
new file mode 100644
index 0000000000..763037ceaa
--- /dev/null
+++ b/target/linux/mediatek/patches/0054-pinctrl-mediatek-add-pinctrl-GPIO-EINT-driver-for-mt.patch
@@ -0,0 +1,1740 @@
+From 0fabcb34ad6506e9d8dadf373f4ebfe1b5129765 Mon Sep 17 00:00:00 2001
+From: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Date: Mon, 18 May 2015 23:11:18 -0700
+Subject: [PATCH 54/76] pinctrl: mediatek: add pinctrl/GPIO/EINT driver for
+ mt8127
+
+MT8127 pinctrl/eint are similar to mt8135 and mt8173, add
+support for mt8127 using mediatek common pinctrl driver.
+
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Signed-off-by: Hongzhou Yang <hongzhou.yang@mediatek.com>
+---
+ drivers/pinctrl/mediatek/Kconfig | 6 +
+ drivers/pinctrl/mediatek/Makefile | 1 +
+ drivers/pinctrl/mediatek/pinctrl-mt8127.c | 359 +++++++
+ drivers/pinctrl/mediatek/pinctrl-mtk-mt8127.h | 1318 +++++++++++++++++++++++++
+ 4 files changed, 1684 insertions(+)
+ create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt8127.c
+ create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-mt8127.h
+
+diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
+index ddae479..0bc84fb 100644
+--- a/drivers/pinctrl/mediatek/Kconfig
++++ b/drivers/pinctrl/mediatek/Kconfig
+@@ -15,6 +15,12 @@ config PINCTRL_MT8135
+ default MACH_MT8135
+ select PINCTRL_MTK_COMMON
+
++config PINCTRL_MT8127
++ bool "Mediatek MT8127 pin control" if COMPILE_TEST && !MACH_MT8127
++ depends on OF
++ default MACH_MT8127
++ select PINCTRL_MTK_COMMON
++
+ # For ARMv8 SoCs
+ config PINCTRL_MT8173
+ bool "Mediatek MT8173 pin control"
+diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
+index ad0180c..eb923d6 100644
+--- a/drivers/pinctrl/mediatek/Makefile
++++ b/drivers/pinctrl/mediatek/Makefile
+@@ -3,5 +3,6 @@ obj-$(CONFIG_PINCTRL_MTK_COMMON) += pinctrl-mtk-common.o
+
+ # SoC Drivers
+ obj-$(CONFIG_PINCTRL_MT8135) += pinctrl-mt8135.o
++obj-$(CONFIG_PINCTRL_MT8127) += pinctrl-mt8127.o
+ obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o
+ obj-$(CONFIG_PINCTRL_MT6397) += pinctrl-mt6397.o
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8127.c b/drivers/pinctrl/mediatek/pinctrl-mt8127.c
+new file mode 100644
+index 0000000..6a26cfa
+--- /dev/null
++++ b/drivers/pinctrl/mediatek/pinctrl-mt8127.c
+@@ -0,0 +1,359 @@
++/*
++ * Copyright (c) 2015 MediaTek Inc.
++ * Author: Hongzhou.Yang <hongzhou.yang@mediatek.com>
++ * Yingjoe Chen <yingjoe.chen@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/regmap.h>
++#include <dt-bindings/pinctrl/mt65xx.h>
++
++#include "pinctrl-mtk-common.h"
++#include "pinctrl-mtk-mt8127.h"
++
++static const struct mtk_drv_group_desc mt8127_drv_grp[] = {
++ /* 0E4E8SR 4/8/12/16 */
++ MTK_DRV_GRP(4, 16, 1, 2, 4),
++ /* 0E2E4SR 2/4/6/8 */
++ MTK_DRV_GRP(2, 8, 1, 2, 2),
++ /* E8E4E2 2/4/6/8/10/12/14/16 */
++ MTK_DRV_GRP(2, 16, 0, 2, 2)
++};
++
++static const struct mtk_pin_drv_grp mt8127_pin_drv[] = {
++ MTK_PIN_DRV_GRP(0, 0xb00, 0, 1),
++ MTK_PIN_DRV_GRP(1, 0xb00, 0, 1),
++ MTK_PIN_DRV_GRP(2, 0xb00, 0, 1),
++ MTK_PIN_DRV_GRP(3, 0xb00, 0, 1),
++ MTK_PIN_DRV_GRP(4, 0xb00, 0, 1),
++ MTK_PIN_DRV_GRP(5, 0xb00, 0, 1),
++ MTK_PIN_DRV_GRP(6, 0xb00, 0, 1),
++ MTK_PIN_DRV_GRP(7, 0xb00, 12, 1),
++ MTK_PIN_DRV_GRP(8, 0xb00, 12, 1),
++ MTK_PIN_DRV_GRP(9, 0xb00, 12, 1),
++ MTK_PIN_DRV_GRP(10, 0xb00, 8, 1),
++ MTK_PIN_DRV_GRP(11, 0xb00, 8, 1),
++ MTK_PIN_DRV_GRP(12, 0xb00, 8, 1),
++ MTK_PIN_DRV_GRP(13, 0xb00, 8, 1),
++ MTK_PIN_DRV_GRP(14, 0xb10, 4, 0),
++ MTK_PIN_DRV_GRP(15, 0xb10, 4, 0),
++ MTK_PIN_DRV_GRP(16, 0xb10, 4, 0),
++ MTK_PIN_DRV_GRP(17, 0xb10, 4, 0),
++ MTK_PIN_DRV_GRP(18, 0xb10, 8, 0),
++ MTK_PIN_DRV_GRP(19, 0xb10, 8, 0),
++ MTK_PIN_DRV_GRP(20, 0xb10, 8, 0),
++ MTK_PIN_DRV_GRP(21, 0xb10, 8, 0),
++ MTK_PIN_DRV_GRP(22, 0xb20, 0, 0),
++ MTK_PIN_DRV_GRP(23, 0xb20, 0, 0),
++ MTK_PIN_DRV_GRP(24, 0xb20, 0, 0),
++ MTK_PIN_DRV_GRP(25, 0xb20, 0, 0),
++ MTK_PIN_DRV_GRP(26, 0xb20, 0, 0),
++ MTK_PIN_DRV_GRP(27, 0xb20, 4, 0),
++ MTK_PIN_DRV_GRP(28, 0xb20, 4, 0),
++ MTK_PIN_DRV_GRP(29, 0xb20, 4, 0),
++ MTK_PIN_DRV_GRP(30, 0xb20, 4, 0),
++ MTK_PIN_DRV_GRP(31, 0xb20, 4, 0),
++ MTK_PIN_DRV_GRP(32, 0xb20, 4, 0),
++ MTK_PIN_DRV_GRP(33, 0xb30, 4, 1),
++ MTK_PIN_DRV_GRP(34, 0xb30, 8, 1),
++ MTK_PIN_DRV_GRP(35, 0xb30, 8, 1),
++ MTK_PIN_DRV_GRP(36, 0xb30, 8, 1),
++ MTK_PIN_DRV_GRP(37, 0xb30, 8, 1),
++ MTK_PIN_DRV_GRP(38, 0xb30, 8, 1),
++ MTK_PIN_DRV_GRP(39, 0xb30, 12, 1),
++ MTK_PIN_DRV_GRP(40, 0xb30, 12, 1),
++ MTK_PIN_DRV_GRP(41, 0xb30, 12, 1),
++ MTK_PIN_DRV_GRP(42, 0xb30, 12, 1),
++ MTK_PIN_DRV_GRP(43, 0xb40, 12, 0),
++ MTK_PIN_DRV_GRP(44, 0xb40, 12, 0),
++ MTK_PIN_DRV_GRP(45, 0xb40, 12, 0),
++ MTK_PIN_DRV_GRP(46, 0xb50, 0, 2),
++ MTK_PIN_DRV_GRP(47, 0xb50, 0, 2),
++ MTK_PIN_DRV_GRP(48, 0xb50, 0, 2),
++ MTK_PIN_DRV_GRP(49, 0xb50, 0, 2),
++ MTK_PIN_DRV_GRP(50, 0xb70, 0, 1),
++ MTK_PIN_DRV_GRP(51, 0xb70, 0, 1),
++ MTK_PIN_DRV_GRP(52, 0xb70, 0, 1),
++ MTK_PIN_DRV_GRP(53, 0xb50, 12, 1),
++ MTK_PIN_DRV_GRP(54, 0xb50, 12, 1),
++ MTK_PIN_DRV_GRP(55, 0xb50, 12, 1),
++ MTK_PIN_DRV_GRP(56, 0xb50, 12, 1),
++ MTK_PIN_DRV_GRP(59, 0xb40, 4, 1),
++ MTK_PIN_DRV_GRP(60, 0xb40, 0, 1),
++ MTK_PIN_DRV_GRP(61, 0xb40, 0, 1),
++ MTK_PIN_DRV_GRP(62, 0xb40, 0, 1),
++ MTK_PIN_DRV_GRP(63, 0xb40, 4, 1),
++ MTK_PIN_DRV_GRP(64, 0xb40, 4, 1),
++ MTK_PIN_DRV_GRP(65, 0xb40, 4, 1),
++ MTK_PIN_DRV_GRP(66, 0xb40, 8, 1),
++ MTK_PIN_DRV_GRP(67, 0xb40, 8, 1),
++ MTK_PIN_DRV_GRP(68, 0xb40, 8, 1),
++ MTK_PIN_DRV_GRP(69, 0xb40, 8, 1),
++ MTK_PIN_DRV_GRP(70, 0xb40, 8, 1),
++ MTK_PIN_DRV_GRP(71, 0xb40, 8, 1),
++ MTK_PIN_DRV_GRP(72, 0xb50, 4, 1),
++ MTK_PIN_DRV_GRP(73, 0xb50, 4, 1),
++ MTK_PIN_DRV_GRP(74, 0xb50, 4, 1),
++ MTK_PIN_DRV_GRP(79, 0xb50, 8, 1),
++ MTK_PIN_DRV_GRP(80, 0xb50, 8, 1),
++ MTK_PIN_DRV_GRP(81, 0xb50, 8, 1),
++ MTK_PIN_DRV_GRP(82, 0xb50, 8, 1),
++ MTK_PIN_DRV_GRP(83, 0xb50, 8, 1),
++ MTK_PIN_DRV_GRP(84, 0xb50, 8, 1),
++ MTK_PIN_DRV_GRP(85, 0xce0, 0, 2),
++ MTK_PIN_DRV_GRP(86, 0xcd0, 0, 2),
++ MTK_PIN_DRV_GRP(87, 0xcf0, 0, 2),
++ MTK_PIN_DRV_GRP(88, 0xcf0, 0, 2),
++ MTK_PIN_DRV_GRP(89, 0xcf0, 0, 2),
++ MTK_PIN_DRV_GRP(90, 0xcf0, 0, 2),
++ MTK_PIN_DRV_GRP(117, 0xb60, 12, 1),
++ MTK_PIN_DRV_GRP(118, 0xb60, 12, 1),
++ MTK_PIN_DRV_GRP(119, 0xb60, 12, 1),
++ MTK_PIN_DRV_GRP(120, 0xb60, 12, 1),
++ MTK_PIN_DRV_GRP(121, 0xc80, 0, 2),
++ MTK_PIN_DRV_GRP(122, 0xc70, 0, 2),
++ MTK_PIN_DRV_GRP(123, 0xc90, 0, 2),
++ MTK_PIN_DRV_GRP(124, 0xc90, 0, 2),
++ MTK_PIN_DRV_GRP(125, 0xc90, 0, 2),
++ MTK_PIN_DRV_GRP(126, 0xc90, 0, 2),
++ MTK_PIN_DRV_GRP(127, 0xc20, 0, 2),
++ MTK_PIN_DRV_GRP(128, 0xc20, 0, 2),
++ MTK_PIN_DRV_GRP(129, 0xc20, 0, 2),
++ MTK_PIN_DRV_GRP(130, 0xc20, 0, 2),
++ MTK_PIN_DRV_GRP(131, 0xc20, 0, 2),
++ MTK_PIN_DRV_GRP(132, 0xc10, 0, 2),
++ MTK_PIN_DRV_GRP(133, 0xc00, 0, 2),
++ MTK_PIN_DRV_GRP(134, 0xc20, 0, 2),
++ MTK_PIN_DRV_GRP(135, 0xc20, 0, 2),
++ MTK_PIN_DRV_GRP(136, 0xc20, 0, 2),
++ MTK_PIN_DRV_GRP(137, 0xc20, 0, 2),
++ MTK_PIN_DRV_GRP(142, 0xb50, 0, 2),
++};
++
++static const struct mtk_pin_spec_pupd_set_samereg mt8127_spec_pupd[] = {
++ MTK_PIN_PUPD_SPEC_SR(33, 0xd90, 2, 0, 1), /* KPROW0 */
++ MTK_PIN_PUPD_SPEC_SR(34, 0xd90, 6, 4, 5), /* KPROW1 */
++ MTK_PIN_PUPD_SPEC_SR(35, 0xd90, 10, 8, 9), /* KPROW2 */
++ MTK_PIN_PUPD_SPEC_SR(36, 0xda0, 2, 0, 1), /* KPCOL0 */
++ MTK_PIN_PUPD_SPEC_SR(37, 0xda0, 6, 4, 5), /* KPCOL1 */
++ MTK_PIN_PUPD_SPEC_SR(38, 0xda0, 10, 8, 9), /* KPCOL2 */
++ MTK_PIN_PUPD_SPEC_SR(46, 0xdb0, 2, 0, 1), /* EINT14 */
++ MTK_PIN_PUPD_SPEC_SR(47, 0xdb0, 6, 4, 5), /* EINT15 */
++ MTK_PIN_PUPD_SPEC_SR(48, 0xdb0, 10, 8, 9), /* EINT16 */
++ MTK_PIN_PUPD_SPEC_SR(49, 0xdb0, 14, 12, 13), /* EINT17 */
++ MTK_PIN_PUPD_SPEC_SR(85, 0xce0, 8, 10, 9), /* MSDC2_CMD */
++ MTK_PIN_PUPD_SPEC_SR(86, 0xcd0, 8, 10, 9), /* MSDC2_CLK */
++ MTK_PIN_PUPD_SPEC_SR(87, 0xd00, 0, 2, 1), /* MSDC2_DAT0 */
++ MTK_PIN_PUPD_SPEC_SR(88, 0xd00, 4, 6, 5), /* MSDC2_DAT1 */
++ MTK_PIN_PUPD_SPEC_SR(89, 0xd00, 8, 10, 9), /* MSDC2_DAT2 */
++ MTK_PIN_PUPD_SPEC_SR(90, 0xd00, 12, 14, 13), /* MSDC2_DAT3 */
++ MTK_PIN_PUPD_SPEC_SR(121, 0xc80, 8, 10, 9), /* MSDC1_CMD */
++ MTK_PIN_PUPD_SPEC_SR(122, 0xc70, 8, 10, 9), /* MSDC1_CLK */
++ MTK_PIN_PUPD_SPEC_SR(123, 0xca0, 0, 2, 1), /* MSDC1_DAT0 */
++ MTK_PIN_PUPD_SPEC_SR(124, 0xca0, 4, 6, 5), /* MSDC1_DAT1 */
++ MTK_PIN_PUPD_SPEC_SR(125, 0xca0, 8, 10, 9), /* MSDC1_DAT2 */
++ MTK_PIN_PUPD_SPEC_SR(126, 0xca0, 12, 14, 13), /* MSDC1_DAT3 */
++ MTK_PIN_PUPD_SPEC_SR(127, 0xc40, 12, 14, 13), /* MSDC0_DAT7 */
++ MTK_PIN_PUPD_SPEC_SR(128, 0xc40, 8, 10, 9), /* MSDC0_DAT6 */
++ MTK_PIN_PUPD_SPEC_SR(129, 0xc40, 4, 6, 5), /* MSDC0_DAT5 */
++ MTK_PIN_PUPD_SPEC_SR(130, 0xc40, 0, 2, 1), /* MSDC0_DAT4 */
++ MTK_PIN_PUPD_SPEC_SR(131, 0xc50, 0, 2, 1), /* MSDC0_RSTB */
++ MTK_PIN_PUPD_SPEC_SR(132, 0xc10, 8, 10, 9), /* MSDC0_CMD */
++ MTK_PIN_PUPD_SPEC_SR(133, 0xc00, 8, 10, 9), /* MSDC0_CLK */
++ MTK_PIN_PUPD_SPEC_SR(134, 0xc30, 12, 14, 13), /* MSDC0_DAT3 */
++ MTK_PIN_PUPD_SPEC_SR(135, 0xc30, 8, 10, 9), /* MSDC0_DAT2 */
++ MTK_PIN_PUPD_SPEC_SR(136, 0xc30, 4, 6, 5), /* MSDC0_DAT1 */
++ MTK_PIN_PUPD_SPEC_SR(137, 0xc30, 0, 2, 1), /* MSDC0_DAT0 */
++ MTK_PIN_PUPD_SPEC_SR(142, 0xdc0, 2, 0, 1), /* EINT21 */
++};
++
++static int mt8127_spec_pull_set(struct regmap *regmap, unsigned int pin,
++ unsigned char align, bool isup, unsigned int r1r0)
++{
++ return mtk_pctrl_spec_pull_set_samereg(regmap, mt8127_spec_pupd,
++ ARRAY_SIZE(mt8127_spec_pupd), pin, align, isup, r1r0);
++}
++
++static const struct mtk_pin_ies_smt_set mt8127_ies_set[] = {
++ MTK_PIN_IES_SMT_SPEC(0, 9, 0x900, 0),
++ MTK_PIN_IES_SMT_SPEC(10, 13, 0x900, 1),
++ MTK_PIN_IES_SMT_SPEC(14, 28, 0x900, 2),
++ MTK_PIN_IES_SMT_SPEC(29, 32, 0x900, 3),
++ MTK_PIN_IES_SMT_SPEC(33, 33, 0x910, 11),
++ MTK_PIN_IES_SMT_SPEC(34, 38, 0x900, 10),
++ MTK_PIN_IES_SMT_SPEC(39, 42, 0x900, 11),
++ MTK_PIN_IES_SMT_SPEC(43, 45, 0x900, 12),
++ MTK_PIN_IES_SMT_SPEC(46, 49, 0x900, 13),
++ MTK_PIN_IES_SMT_SPEC(50, 52, 0x910, 10),
++ MTK_PIN_IES_SMT_SPEC(53, 56, 0x900, 14),
++ MTK_PIN_IES_SMT_SPEC(57, 58, 0x910, 0),
++ MTK_PIN_IES_SMT_SPEC(59, 65, 0x910, 2),
++ MTK_PIN_IES_SMT_SPEC(66, 71, 0x910, 3),
++ MTK_PIN_IES_SMT_SPEC(72, 74, 0x910, 4),
++ MTK_PIN_IES_SMT_SPEC(75, 76, 0x900, 15),
++ MTK_PIN_IES_SMT_SPEC(77, 78, 0x910, 1),
++ MTK_PIN_IES_SMT_SPEC(79, 82, 0x910, 5),
++ MTK_PIN_IES_SMT_SPEC(83, 84, 0x910, 6),
++ MTK_PIN_IES_SMT_SPEC(117, 120, 0x910, 7),
++ MTK_PIN_IES_SMT_SPEC(121, 121, 0xc80, 4),
++ MTK_PIN_IES_SMT_SPEC(122, 122, 0xc70, 4),
++ MTK_PIN_IES_SMT_SPEC(123, 126, 0xc90, 4),
++ MTK_PIN_IES_SMT_SPEC(127, 131, 0xc20, 4),
++ MTK_PIN_IES_SMT_SPEC(132, 132, 0xc10, 4),
++ MTK_PIN_IES_SMT_SPEC(133, 133, 0xc00, 4),
++ MTK_PIN_IES_SMT_SPEC(134, 137, 0xc20, 4),
++ MTK_PIN_IES_SMT_SPEC(138, 141, 0x910, 9),
++ MTK_PIN_IES_SMT_SPEC(142, 142, 0x900, 13),
++};
++
++static const struct mtk_pin_ies_smt_set mt8127_smt_set[] = {
++ MTK_PIN_IES_SMT_SPEC(0, 9, 0x920, 0),
++ MTK_PIN_IES_SMT_SPEC(10, 13, 0x920, 1),
++ MTK_PIN_IES_SMT_SPEC(14, 28, 0x920, 2),
++ MTK_PIN_IES_SMT_SPEC(29, 32, 0x920, 3),
++ MTK_PIN_IES_SMT_SPEC(33, 33, 0x930, 11),
++ MTK_PIN_IES_SMT_SPEC(34, 38, 0x920, 10),
++ MTK_PIN_IES_SMT_SPEC(39, 42, 0x920, 11),
++ MTK_PIN_IES_SMT_SPEC(43, 45, 0x920, 12),
++ MTK_PIN_IES_SMT_SPEC(46, 49, 0x920, 13),
++ MTK_PIN_IES_SMT_SPEC(50, 52, 0x930, 10),
++ MTK_PIN_IES_SMT_SPEC(53, 56, 0x920, 14),
++ MTK_PIN_IES_SMT_SPEC(57, 58, 0x930, 0),
++ MTK_PIN_IES_SMT_SPEC(59, 65, 0x930, 2),
++ MTK_PIN_IES_SMT_SPEC(66, 71, 0x930, 3),
++ MTK_PIN_IES_SMT_SPEC(72, 74, 0x930, 4),
++ MTK_PIN_IES_SMT_SPEC(75, 76, 0x920, 15),
++ MTK_PIN_IES_SMT_SPEC(77, 78, 0x930, 1),
++ MTK_PIN_IES_SMT_SPEC(79, 82, 0x930, 5),
++ MTK_PIN_IES_SMT_SPEC(83, 84, 0x930, 6),
++ MTK_PIN_IES_SMT_SPEC(85, 85, 0xce0, 11),
++ MTK_PIN_IES_SMT_SPEC(86, 86, 0xcd0, 11),
++ MTK_PIN_IES_SMT_SPEC(87, 87, 0xd00, 3),
++ MTK_PIN_IES_SMT_SPEC(88, 88, 0xd00, 7),
++ MTK_PIN_IES_SMT_SPEC(89, 89, 0xd00, 11),
++ MTK_PIN_IES_SMT_SPEC(90, 90, 0xd00, 15),
++ MTK_PIN_IES_SMT_SPEC(117, 120, 0x930, 7),
++ MTK_PIN_IES_SMT_SPEC(121, 121, 0xc80, 11),
++ MTK_PIN_IES_SMT_SPEC(122, 122, 0xc70, 11),
++ MTK_PIN_IES_SMT_SPEC(123, 123, 0xca0, 3),
++ MTK_PIN_IES_SMT_SPEC(124, 124, 0xca0, 7),
++ MTK_PIN_IES_SMT_SPEC(125, 125, 0xca0, 11),
++ MTK_PIN_IES_SMT_SPEC(126, 126, 0xca0, 15),
++ MTK_PIN_IES_SMT_SPEC(127, 127, 0xc40, 15),
++ MTK_PIN_IES_SMT_SPEC(128, 128, 0xc40, 11),
++ MTK_PIN_IES_SMT_SPEC(129, 129, 0xc40, 7),
++ MTK_PIN_IES_SMT_SPEC(130, 130, 0xc40, 3),
++ MTK_PIN_IES_SMT_SPEC(131, 131, 0xc50, 3),
++ MTK_PIN_IES_SMT_SPEC(132, 132, 0xc10, 11),
++ MTK_PIN_IES_SMT_SPEC(133, 133, 0xc00, 11),
++ MTK_PIN_IES_SMT_SPEC(134, 134, 0xc30, 15),
++ MTK_PIN_IES_SMT_SPEC(135, 135, 0xc30, 11),
++ MTK_PIN_IES_SMT_SPEC(136, 136, 0xc30, 7),
++ MTK_PIN_IES_SMT_SPEC(137, 137, 0xc30, 3),
++ MTK_PIN_IES_SMT_SPEC(138, 141, 0x930, 9),
++ MTK_PIN_IES_SMT_SPEC(142, 142, 0x920, 13),
++};
++
++static int mt8127_ies_smt_set(struct regmap *regmap, unsigned int pin,
++ unsigned char align, int value, enum pin_config_param arg)
++{
++ if (arg == PIN_CONFIG_INPUT_ENABLE)
++ return mtk_pconf_spec_set_ies_smt_range(regmap, mt8127_ies_set,
++ ARRAY_SIZE(mt8127_ies_set), pin, align, value);
++ else if (arg == PIN_CONFIG_INPUT_SCHMITT_ENABLE)
++ return mtk_pconf_spec_set_ies_smt_range(regmap, mt8127_smt_set,
++ ARRAY_SIZE(mt8127_smt_set), pin, align, value);
++ return -EINVAL;
++}
++
++
++static const struct mtk_pinctrl_devdata mt8127_pinctrl_data = {
++ .pins = mtk_pins_mt8127,
++ .npins = ARRAY_SIZE(mtk_pins_mt8127),
++ .grp_desc = mt8127_drv_grp,
++ .n_grp_cls = ARRAY_SIZE(mt8127_drv_grp),
++ .pin_drv_grp = mt8127_pin_drv,
++ .n_pin_drv_grps = ARRAY_SIZE(mt8127_pin_drv),
++ .spec_pull_set = mt8127_spec_pull_set,
++ .spec_ies_smt_set = mt8127_ies_smt_set,
++ .dir_offset = 0x0000,
++ .pullen_offset = 0x0100,
++ .pullsel_offset = 0x0200,
++ .dout_offset = 0x0400,
++ .din_offset = 0x0500,
++ .pinmux_offset = 0x0600,
++ .type1_start = 143,
++ .type1_end = 143,
++ .port_shf = 4,
++ .port_mask = 0xf,
++ .port_align = 4,
++ .eint_offsets = {
++ .name = "mt8127_eint",
++ .stat = 0x000,
++ .ack = 0x040,
++ .mask = 0x080,
++ .mask_set = 0x0c0,
++ .mask_clr = 0x100,
++ .sens = 0x140,
++ .sens_set = 0x180,
++ .sens_clr = 0x1c0,
++ .soft = 0x200,
++ .soft_set = 0x240,
++ .soft_clr = 0x280,
++ .pol = 0x300,
++ .pol_set = 0x340,
++ .pol_clr = 0x380,
++ .dom_en = 0x400,
++ .dbnc_ctrl = 0x500,
++ .dbnc_set = 0x600,
++ .dbnc_clr = 0x700,
++ .port_mask = 7,
++ .ports = 6,
++ },
++ .ap_num = 143,
++ .db_cnt = 16,
++};
++
++static int mt8127_pinctrl_probe(struct platform_device *pdev)
++{
++ return mtk_pctrl_init(pdev, &mt8127_pinctrl_data, NULL);
++}
++
++static const struct of_device_id mt8127_pctrl_match[] = {
++ { .compatible = "mediatek,mt8127-pinctrl", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, mt8127_pctrl_match);
++
++static struct platform_driver mtk_pinctrl_driver = {
++ .probe = mt8127_pinctrl_probe,
++ .driver = {
++ .name = "mediatek-mt8127-pinctrl",
++ .owner = THIS_MODULE,
++ .of_match_table = mt8127_pctrl_match,
++ },
++};
++
++static int __init mtk_pinctrl_init(void)
++{
++ return platform_driver_register(&mtk_pinctrl_driver);
++}
++
++module_init(mtk_pinctrl_init);
++
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("MediaTek MT8127 Pinctrl Driver");
++MODULE_AUTHOR("Yingjoe Chen <yingjoe.chen@mediatek.com>");
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt8127.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt8127.h
+new file mode 100644
+index 0000000..212559c
+--- /dev/null
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt8127.h
+@@ -0,0 +1,1318 @@
++#ifndef __PINCTRL_MTK_MT8127_H
++#define __PINCTRL_MTK_MT8127_H
++
++#include <linux/pinctrl/pinctrl.h>
++#include "pinctrl-mtk-common.h"
++
++static const struct mtk_desc_pin mtk_pins_mt8127[] = {
++ MTK_PIN(
++ PINCTRL_PIN(0, "PWRAP_SPI0_MI"),
++ "P22", "mt8127",
++ MTK_EINT_FUNCTION(0, 22),
++ MTK_FUNCTION(0, "GPIO0"),
++ MTK_FUNCTION(1, "PWRAP_SPIDO"),
++ MTK_FUNCTION(2, "PWRAP_SPIDI")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(1, "PWRAP_SPI0_MO"),
++ "M22", "mt8127",
++ MTK_EINT_FUNCTION(0, 23),
++ MTK_FUNCTION(0, "GPIO1"),
++ MTK_FUNCTION(1, "PWRAP_SPIDI"),
++ MTK_FUNCTION(2, "PWRAP_SPIDO")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(2, "PWRAP_INT"),
++ "L23", "mt8127",
++ MTK_EINT_FUNCTION(0, 24),
++ MTK_FUNCTION(0, "GPIO2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(3, "PWRAP_SPI0_CK"),
++ "N23", "mt8127",
++ MTK_EINT_FUNCTION(0, 25),
++ MTK_FUNCTION(0, "GPIO3"),
++ MTK_FUNCTION(1, "PWRAP_SPICK_I")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(4, "PWRAP_SPI0_CSN"),
++ "N22", "mt8127",
++ MTK_EINT_FUNCTION(0, 26),
++ MTK_FUNCTION(0, "GPIO4"),
++ MTK_FUNCTION(1, "PWRAP_SPICS_B_I")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(5, "PWRAP_SPI0_CK2"),
++ "L19", "mt8127",
++ MTK_EINT_FUNCTION(0, 27),
++ MTK_FUNCTION(0, "GPIO5"),
++ MTK_FUNCTION(1, "PWRAP_SPICK2_I"),
++ MTK_FUNCTION(2, "ANT_SEL1"),
++ MTK_FUNCTION(3, "VDEC_TEST_CK"),
++ MTK_FUNCTION(7, "DBG_MON_B[0]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(6, "PWRAP_SPI0_CSN2"),
++ "M23", "mt8127",
++ MTK_EINT_FUNCTION(0, 28),
++ MTK_FUNCTION(0, "GPIO6"),
++ MTK_FUNCTION(1, "PWRAP_SPICS2_B_I"),
++ MTK_FUNCTION(2, "ANT_SEL0"),
++ MTK_FUNCTION(3, "MM_TEST_CK"),
++ MTK_FUNCTION(7, "DBG_MON_B[1]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(7, "AUD_CLK_MOSI"),
++ "K23", "mt8127",
++ MTK_EINT_FUNCTION(0, 29),
++ MTK_FUNCTION(0, "GPIO7"),
++ MTK_FUNCTION(1, "AUD_CLK"),
++ MTK_FUNCTION(2, "ADC_CK")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(8, "AUD_DAT_MISO"),
++ "K24", "mt8127",
++ MTK_EINT_FUNCTION(0, 30),
++ MTK_FUNCTION(0, "GPIO8"),
++ MTK_FUNCTION(1, "AUD_MISO"),
++ MTK_FUNCTION(2, "ADC_DAT_IN"),
++ MTK_FUNCTION(3, "AUD_MOSI")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(9, "AUD_DAT_MOSI"),
++ "K22", "mt8127",
++ MTK_EINT_FUNCTION(0, 31),
++ MTK_FUNCTION(0, "GPIO9"),
++ MTK_FUNCTION(1, "AUD_MOSI"),
++ MTK_FUNCTION(2, "ADC_WS"),
++ MTK_FUNCTION(3, "AUD_MISO")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(10, "RTC32K_CK"),
++ "R21", "mt8127",
++ MTK_EINT_FUNCTION(0, 32),
++ MTK_FUNCTION(0, "GPIO10"),
++ MTK_FUNCTION(1, "RTC32K_CK")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(11, "WATCHDOG"),
++ "P24", "mt8127",
++ MTK_EINT_FUNCTION(0, 33),
++ MTK_FUNCTION(0, "GPIO11"),
++ MTK_FUNCTION(1, "WATCHDOG")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(12, "SRCLKENA"),
++ "R22", "mt8127",
++ MTK_EINT_FUNCTION(0, 34),
++ MTK_FUNCTION(0, "GPIO12"),
++ MTK_FUNCTION(1, "SRCLKENA")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(13, "SRCLKENAI"),
++ "P23", "mt8127",
++ MTK_EINT_FUNCTION(0, 35),
++ MTK_FUNCTION(0, "GPIO13"),
++ MTK_FUNCTION(1, "SRCLKENAI")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(14, "URXD2"),
++ "U19", "mt8127",
++ MTK_EINT_FUNCTION(0, 36),
++ MTK_FUNCTION(0, "GPIO14"),
++ MTK_FUNCTION(1, "URXD2"),
++ MTK_FUNCTION(2, "DPI_D5"),
++ MTK_FUNCTION(3, "UTXD2"),
++ MTK_FUNCTION(5, "SRCCLKENAI2"),
++ MTK_FUNCTION(6, "KROW4")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(15, "UTXD2"),
++ "U20", "mt8127",
++ MTK_EINT_FUNCTION(0, 37),
++ MTK_FUNCTION(0, "GPIO15"),
++ MTK_FUNCTION(1, "UTXD2"),
++ MTK_FUNCTION(2, "DPI_HSYNC"),
++ MTK_FUNCTION(3, "URXD2"),
++ MTK_FUNCTION(6, "KROW5")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(16, "URXD3"),
++ "U18", "mt8127",
++ MTK_EINT_FUNCTION(0, 38),
++ MTK_FUNCTION(0, "GPIO16"),
++ MTK_FUNCTION(1, "URXD3"),
++ MTK_FUNCTION(2, "DPI_DE"),
++ MTK_FUNCTION(3, "UTXD3"),
++ MTK_FUNCTION(4, "UCTS2"),
++ MTK_FUNCTION(5, "PWM3"),
++ MTK_FUNCTION(6, "KROW6")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(17, "UTXD3"),
++ "R18", "mt8127",
++ MTK_EINT_FUNCTION(0, 39),
++ MTK_FUNCTION(0, "GPIO17"),
++ MTK_FUNCTION(1, "UTXD3"),
++ MTK_FUNCTION(2, "DPI_VSYNC"),
++ MTK_FUNCTION(3, "URXD3"),
++ MTK_FUNCTION(4, "URTS2"),
++ MTK_FUNCTION(5, "PWM4"),
++ MTK_FUNCTION(6, "KROW7")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(18, "PCM_CLK"),
++ "U22", "mt8127",
++ MTK_EINT_FUNCTION(0, 40),
++ MTK_FUNCTION(0, "GPIO18"),
++ MTK_FUNCTION(1, "PCM_CLK0"),
++ MTK_FUNCTION(2, "DPI_D4"),
++ MTK_FUNCTION(3, "I2SIN1_BCK0"),
++ MTK_FUNCTION(4, "I2SOUT_BCK"),
++ MTK_FUNCTION(5, "CONN_DSP_JCK"),
++ MTK_FUNCTION(6, "IR"),
++ MTK_FUNCTION(7, "DBG_MON_A[0]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(19, "PCM_SYNC"),
++ "U23", "mt8127",
++ MTK_EINT_FUNCTION(0, 41),
++ MTK_FUNCTION(0, "GPIO19"),
++ MTK_FUNCTION(1, "PCM_SYNC"),
++ MTK_FUNCTION(2, "DPI_D3"),
++ MTK_FUNCTION(3, "I2SIN1_LRCK"),
++ MTK_FUNCTION(4, "I2SOUT_LRCK"),
++ MTK_FUNCTION(5, "CONN_DSP_JINTP"),
++ MTK_FUNCTION(6, "EXT_COL"),
++ MTK_FUNCTION(7, "DBG_MON_A[1]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(20, "PCM_RX"),
++ "V22", "mt8127",
++ MTK_EINT_FUNCTION(0, 42),
++ MTK_FUNCTION(0, "GPIO20"),
++ MTK_FUNCTION(1, "PCM_RX"),
++ MTK_FUNCTION(2, "DPI_D1"),
++ MTK_FUNCTION(3, "I2SIN1_DATA_IN"),
++ MTK_FUNCTION(4, "PCM_TX"),
++ MTK_FUNCTION(5, "CONN_DSP_JDI"),
++ MTK_FUNCTION(6, "EXT_MDIO"),
++ MTK_FUNCTION(7, "DBG_MON_A[2]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(21, "PCM_TX"),
++ "U21", "mt8127",
++ MTK_EINT_FUNCTION(0, 43),
++ MTK_FUNCTION(0, "GPIO21"),
++ MTK_FUNCTION(1, "PCM_TX"),
++ MTK_FUNCTION(2, "DPI_D2"),
++ MTK_FUNCTION(3, "I2SOUT_DATA_OUT"),
++ MTK_FUNCTION(4, "PCM_RX"),
++ MTK_FUNCTION(5, "CONN_DSP_JMS"),
++ MTK_FUNCTION(6, "EXT_MDC"),
++ MTK_FUNCTION(7, "DBG_MON_A[3]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(22, "EINT0"),
++ "AB19", "mt8127",
++ MTK_EINT_FUNCTION(0, 0),
++ MTK_FUNCTION(0, "GPIO22"),
++ MTK_FUNCTION(1, "PWM1"),
++ MTK_FUNCTION(2, "DPI_CK"),
++ MTK_FUNCTION(4, "EXT_TXD0"),
++ MTK_FUNCTION(5, "CONN_DSP_JDO"),
++ MTK_FUNCTION(7, "DBG_MON_A[4]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(23, "EINT1"),
++ "AA21", "mt8127",
++ MTK_EINT_FUNCTION(0, 1),
++ MTK_FUNCTION(0, "GPIO23"),
++ MTK_FUNCTION(1, "PWM2"),
++ MTK_FUNCTION(2, "DPI_D12"),
++ MTK_FUNCTION(4, "EXT_TXD1"),
++ MTK_FUNCTION(5, "CONN_MCU_TDO"),
++ MTK_FUNCTION(7, "DBG_MON_A[5]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(24, "EINT2"),
++ "AA19", "mt8127",
++ MTK_EINT_FUNCTION(0, 2),
++ MTK_FUNCTION(0, "GPIO24"),
++ MTK_FUNCTION(1, "CLKM0"),
++ MTK_FUNCTION(2, "DPI_D13"),
++ MTK_FUNCTION(4, "EXT_TXD2"),
++ MTK_FUNCTION(5, "CONN_MCU_DBGACK_N"),
++ MTK_FUNCTION(6, "KCOL4"),
++ MTK_FUNCTION(7, "DBG_MON_A[6]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(25, "EINT3"),
++ "Y19", "mt8127",
++ MTK_EINT_FUNCTION(0, 3),
++ MTK_FUNCTION(0, "GPIO25"),
++ MTK_FUNCTION(1, "CLKM1"),
++ MTK_FUNCTION(2, "DPI_D14"),
++ MTK_FUNCTION(3, "SPI_MI"),
++ MTK_FUNCTION(4, "EXT_TXD3"),
++ MTK_FUNCTION(5, "CONN_MCU_DBGI_N"),
++ MTK_FUNCTION(6, "KCOL5"),
++ MTK_FUNCTION(7, "DBG_MON_A[7]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(26, "EINT4"),
++ "V21", "mt8127",
++ MTK_EINT_FUNCTION(0, 4),
++ MTK_FUNCTION(0, "GPIO26"),
++ MTK_FUNCTION(1, "CLKM2"),
++ MTK_FUNCTION(2, "DPI_D15"),
++ MTK_FUNCTION(3, "SPI_MO"),
++ MTK_FUNCTION(4, "EXT_TXC"),
++ MTK_FUNCTION(5, "CONN_MCU_TCK0"),
++ MTK_FUNCTION(6, "CONN_MCU_AICE_JCKC"),
++ MTK_FUNCTION(7, "DBG_MON_A[8]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(27, "EINT5"),
++ "AB22", "mt8127",
++ MTK_EINT_FUNCTION(0, 5),
++ MTK_FUNCTION(0, "GPIO27"),
++ MTK_FUNCTION(1, "UCTS2"),
++ MTK_FUNCTION(2, "DPI_D16"),
++ MTK_FUNCTION(3, "SPI_CS"),
++ MTK_FUNCTION(4, "EXT_RXER"),
++ MTK_FUNCTION(5, "CONN_MCU_TDI"),
++ MTK_FUNCTION(6, "KCOL6"),
++ MTK_FUNCTION(7, "DBG_MON_A[9]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(28, "EINT6"),
++ "AA23", "mt8127",
++ MTK_EINT_FUNCTION(0, 6),
++ MTK_FUNCTION(0, "GPIO28"),
++ MTK_FUNCTION(1, "URTS2"),
++ MTK_FUNCTION(2, "DPI_D17"),
++ MTK_FUNCTION(3, "SPI_CK"),
++ MTK_FUNCTION(4, "EXT_RXC"),
++ MTK_FUNCTION(5, "CONN_MCU_TRST_B"),
++ MTK_FUNCTION(6, "KCOL7"),
++ MTK_FUNCTION(7, "DBG_MON_A[10]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(29, "EINT7"),
++ "Y23", "mt8127",
++ MTK_EINT_FUNCTION(0, 7),
++ MTK_FUNCTION(0, "GPIO29"),
++ MTK_FUNCTION(1, "UCTS3"),
++ MTK_FUNCTION(2, "DPI_D6"),
++ MTK_FUNCTION(3, "SDA1"),
++ MTK_FUNCTION(4, "EXT_RXDV"),
++ MTK_FUNCTION(5, "CONN_MCU_TMS"),
++ MTK_FUNCTION(6, "CONN_MCU_AICE_JMSC"),
++ MTK_FUNCTION(7, "DBG_MON_A[11]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(30, "EINT8"),
++ "Y24", "mt8127",
++ MTK_EINT_FUNCTION(0, 8),
++ MTK_FUNCTION(0, "GPIO30"),
++ MTK_FUNCTION(1, "URTS3"),
++ MTK_FUNCTION(2, "CLKM3"),
++ MTK_FUNCTION(3, "SCL1"),
++ MTK_FUNCTION(4, "EXT_RXD0"),
++ MTK_FUNCTION(5, "ANT_SEL0"),
++ MTK_FUNCTION(6, "DPI_D7"),
++ MTK_FUNCTION(7, "DBG_MON_B[2]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(31, "EINT9"),
++ "W23", "mt8127",
++ MTK_EINT_FUNCTION(0, 9),
++ MTK_FUNCTION(0, "GPIO31"),
++ MTK_FUNCTION(1, "CLKM4"),
++ MTK_FUNCTION(2, "SDA2"),
++ MTK_FUNCTION(3, "EXT_FRAME_SYNC"),
++ MTK_FUNCTION(4, "EXT_RXD1"),
++ MTK_FUNCTION(5, "ANT_SEL1"),
++ MTK_FUNCTION(6, "DPI_D8"),
++ MTK_FUNCTION(7, "DBG_MON_B[3]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(32, "EINT10"),
++ "W24", "mt8127",
++ MTK_EINT_FUNCTION(0, 10),
++ MTK_FUNCTION(0, "GPIO32"),
++ MTK_FUNCTION(1, "CLKM5"),
++ MTK_FUNCTION(2, "SCL2"),
++ MTK_FUNCTION(3, "EXT_FRAME_SYNC"),
++ MTK_FUNCTION(4, "EXT_RXD2"),
++ MTK_FUNCTION(5, "ANT_SEL2"),
++ MTK_FUNCTION(6, "DPI_D9"),
++ MTK_FUNCTION(7, "DBG_MON_B[4]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(33, "KPROW0"),
++ "AB24", "mt8127",
++ MTK_EINT_FUNCTION(0, 44),
++ MTK_FUNCTION(0, "GPIO33"),
++ MTK_FUNCTION(1, "KROW0"),
++ MTK_FUNCTION(4, "IMG_TEST_CK"),
++ MTK_FUNCTION(7, "DBG_MON_A[12]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(34, "KPROW1"),
++ "AC24", "mt8127",
++ MTK_EINT_FUNCTION(0, 45),
++ MTK_FUNCTION(0, "GPIO34"),
++ MTK_FUNCTION(1, "KROW1"),
++ MTK_FUNCTION(2, "IDDIG"),
++ MTK_FUNCTION(3, "EXT_FRAME_SYNC"),
++ MTK_FUNCTION(4, "MFG_TEST_CK"),
++ MTK_FUNCTION(7, "DBG_MON_B[5]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(35, "KPROW2"),
++ "AD24", "mt8127",
++ MTK_EINT_FUNCTION(0, 46),
++ MTK_FUNCTION(0, "GPIO35"),
++ MTK_FUNCTION(1, "KROW2"),
++ MTK_FUNCTION(2, "DRV_VBUS"),
++ MTK_FUNCTION(3, "EXT_FRAME_SYNC"),
++ MTK_FUNCTION(4, "CONN_TEST_CK"),
++ MTK_FUNCTION(7, "DBG_MON_B[6]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(36, "KPCOL0"),
++ "AB23", "mt8127",
++ MTK_EINT_FUNCTION(0, 47),
++ MTK_FUNCTION(0, "GPIO36"),
++ MTK_FUNCTION(1, "KCOL0"),
++ MTK_FUNCTION(7, "DBG_MON_A[13]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(37, "KPCOL1"),
++ "AC22", "mt8127",
++ MTK_EINT_FUNCTION(0, 48),
++ MTK_FUNCTION(0, "GPIO37"),
++ MTK_FUNCTION(1, "KCOL1"),
++ MTK_FUNCTION(7, "DBG_MON_B[7]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(38, "KPCOL2"),
++ "AC23", "mt8127",
++ MTK_EINT_FUNCTION(0, 49),
++ MTK_FUNCTION(0, "GPIO38"),
++ MTK_FUNCTION(1, "KCOL2"),
++ MTK_FUNCTION(2, "IDDIG"),
++ MTK_FUNCTION(3, "EXT_FRAME_SYNC"),
++ MTK_FUNCTION(7, "DBG_MON_B[8]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(39, "JTMS"),
++ "V18", "mt8127",
++ MTK_EINT_FUNCTION(0, 50),
++ MTK_FUNCTION(0, "GPIO39"),
++ MTK_FUNCTION(1, "JTMS"),
++ MTK_FUNCTION(2, "CONN_MCU_TMS"),
++ MTK_FUNCTION(3, "CONN_MCU_AICE_JMSC")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(40, "JTCK"),
++ "AA18", "mt8127",
++ MTK_EINT_FUNCTION(0, 51),
++ MTK_FUNCTION(0, "GPIO40"),
++ MTK_FUNCTION(1, "JTCK"),
++ MTK_FUNCTION(2, "CONN_MCU_TCK1"),
++ MTK_FUNCTION(3, "CONN_MCU_AICE_JCKC")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(41, "JTDI"),
++ "W18", "mt8127",
++ MTK_EINT_FUNCTION(0, 52),
++ MTK_FUNCTION(0, "GPIO41"),
++ MTK_FUNCTION(1, "JTDI"),
++ MTK_FUNCTION(2, "CONN_MCU_TDI")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(42, "JTDO"),
++ "Y18", "mt8127",
++ MTK_EINT_FUNCTION(0, 53),
++ MTK_FUNCTION(0, "GPIO42"),
++ MTK_FUNCTION(1, "JTDO"),
++ MTK_FUNCTION(2, "CONN_MCU_TDO")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(43, "EINT11"),
++ "W22", "mt8127",
++ MTK_EINT_FUNCTION(0, 11),
++ MTK_FUNCTION(0, "GPIO43"),
++ MTK_FUNCTION(1, "CLKM4"),
++ MTK_FUNCTION(2, "PWM2"),
++ MTK_FUNCTION(3, "KROW3"),
++ MTK_FUNCTION(4, "ANT_SEL3"),
++ MTK_FUNCTION(5, "DPI_D10"),
++ MTK_FUNCTION(6, "EXT_RXD3"),
++ MTK_FUNCTION(7, "DBG_MON_B[9]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(44, "EINT12"),
++ "V23", "mt8127",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO44"),
++ MTK_FUNCTION(1, "CLKM5"),
++ MTK_FUNCTION(2, "PWM0"),
++ MTK_FUNCTION(3, "KCOL3"),
++ MTK_FUNCTION(4, "ANT_SEL4"),
++ MTK_FUNCTION(5, "DPI_D11"),
++ MTK_FUNCTION(6, "EXT_TXEN"),
++ MTK_FUNCTION(7, "DBG_MON_B[10]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(45, "EINT13"),
++ "Y21", "mt8127",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO45"),
++ MTK_FUNCTION(4, "ANT_SEL5"),
++ MTK_FUNCTION(5, "DPI_D0"),
++ MTK_FUNCTION(6, "SPDIF"),
++ MTK_FUNCTION(7, "DBG_MON_B[11]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(46, "EINT14"),
++ "F23", "mt8127",
++ MTK_EINT_FUNCTION(0, 14),
++ MTK_FUNCTION(0, "GPIO46"),
++ MTK_FUNCTION(2, "DAC_DAT_OUT"),
++ MTK_FUNCTION(4, "ANT_SEL1"),
++ MTK_FUNCTION(5, "CONN_MCU_DBGACK_N"),
++ MTK_FUNCTION(6, "NCLE"),
++ MTK_FUNCTION(7, "DBG_MON_A[14]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(47, "EINT15"),
++ "G23", "mt8127",
++ MTK_EINT_FUNCTION(0, 15),
++ MTK_FUNCTION(0, "GPIO47"),
++ MTK_FUNCTION(2, "DAC_WS"),
++ MTK_FUNCTION(4, "ANT_SEL2"),
++ MTK_FUNCTION(5, "CONN_MCU_DBGI_N"),
++ MTK_FUNCTION(6, "NCEB1"),
++ MTK_FUNCTION(7, "DBG_MON_A[15]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(48, "EINT16"),
++ "H23", "mt8127",
++ MTK_EINT_FUNCTION(0, 16),
++ MTK_FUNCTION(0, "GPIO48"),
++ MTK_FUNCTION(2, "DAC_CK"),
++ MTK_FUNCTION(4, "ANT_SEL3"),
++ MTK_FUNCTION(5, "CONN_MCU_TRST_B"),
++ MTK_FUNCTION(6, "NCEB0"),
++ MTK_FUNCTION(7, "DBG_MON_A[16]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(49, "EINT17"),
++ "J22", "mt8127",
++ MTK_EINT_FUNCTION(0, 17),
++ MTK_FUNCTION(0, "GPIO49"),
++ MTK_FUNCTION(1, "UCTS0"),
++ MTK_FUNCTION(3, "CLKM0"),
++ MTK_FUNCTION(4, "IDDIG"),
++ MTK_FUNCTION(5, "ANT_SEL4"),
++ MTK_FUNCTION(6, "NREB"),
++ MTK_FUNCTION(7, "DBG_MON_A[17]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(50, "EINT18"),
++ "AD20", "mt8127",
++ MTK_EINT_FUNCTION(0, 18),
++ MTK_FUNCTION(0, "GPIO50"),
++ MTK_FUNCTION(1, "URTS0"),
++ MTK_FUNCTION(2, "CLKM3"),
++ MTK_FUNCTION(3, "I2SOUT_LRCK"),
++ MTK_FUNCTION(4, "DRV_VBUS"),
++ MTK_FUNCTION(5, "ANT_SEL3"),
++ MTK_FUNCTION(6, "ADC_CK"),
++ MTK_FUNCTION(7, "DBG_MON_B[12]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(51, "EINT19"),
++ "AC21", "mt8127",
++ MTK_EINT_FUNCTION(0, 19),
++ MTK_FUNCTION(0, "GPIO51"),
++ MTK_FUNCTION(1, "UCTS1"),
++ MTK_FUNCTION(3, "I2SOUT_BCK"),
++ MTK_FUNCTION(4, "CLKM1"),
++ MTK_FUNCTION(5, "ANT_SEL4"),
++ MTK_FUNCTION(6, "ADC_DAT_IN"),
++ MTK_FUNCTION(7, "DBG_MON_B[13]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(52, "EINT20"),
++ "V20", "mt8127",
++ MTK_EINT_FUNCTION(0, 20),
++ MTK_FUNCTION(0, "GPIO52"),
++ MTK_FUNCTION(1, "URTS1"),
++ MTK_FUNCTION(2, "PCM_TX"),
++ MTK_FUNCTION(3, "I2SOUT_DATA_OUT"),
++ MTK_FUNCTION(4, "CLKM2"),
++ MTK_FUNCTION(5, "ANT_SEL5"),
++ MTK_FUNCTION(6, "ADC_WS"),
++ MTK_FUNCTION(7, "DBG_MON_B[14]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(53, "SPI_CS"),
++ "AD19", "mt8127",
++ MTK_EINT_FUNCTION(0, 54),
++ MTK_FUNCTION(0, "GPIO53"),
++ MTK_FUNCTION(1, "SPI_CS"),
++ MTK_FUNCTION(3, "I2SIN1_DATA_IN"),
++ MTK_FUNCTION(4, "ADC_CK"),
++ MTK_FUNCTION(7, "DBG_MON_B[15]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(54, "SPI_CK"),
++ "AC18", "mt8127",
++ MTK_EINT_FUNCTION(0, 55),
++ MTK_FUNCTION(0, "GPIO54"),
++ MTK_FUNCTION(1, "SPI_CK"),
++ MTK_FUNCTION(3, "I2SIN1_LRCK"),
++ MTK_FUNCTION(4, "ADC_DAT_IN"),
++ MTK_FUNCTION(7, "DBG_MON_B[16]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(55, "SPI_MI"),
++ "AC19", "mt8127",
++ MTK_EINT_FUNCTION(0, 56),
++ MTK_FUNCTION(0, "GPIO55"),
++ MTK_FUNCTION(1, "SPI_MI"),
++ MTK_FUNCTION(2, "SPI_MO"),
++ MTK_FUNCTION(3, "I2SIN1_BCK1"),
++ MTK_FUNCTION(4, "ADC_WS"),
++ MTK_FUNCTION(7, "DBG_MON_B[17]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(56, "SPI_MO"),
++ "AD18", "mt8127",
++ MTK_EINT_FUNCTION(0, 57),
++ MTK_FUNCTION(0, "GPIO56"),
++ MTK_FUNCTION(1, "SPI_MO"),
++ MTK_FUNCTION(2, "SPI_MI"),
++ MTK_FUNCTION(7, "DBG_MON_B[18]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(57, "SDA1"),
++ "AE23", "mt8127",
++ MTK_EINT_FUNCTION(0, 58),
++ MTK_FUNCTION(0, "GPIO57"),
++ MTK_FUNCTION(1, "SDA1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(58, "SCL1"),
++ "AD23", "mt8127",
++ MTK_EINT_FUNCTION(0, 59),
++ MTK_FUNCTION(0, "GPIO58"),
++ MTK_FUNCTION(1, "SCL1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(59, "DISP_PWM"),
++ "AC20", "mt8127",
++ MTK_EINT_FUNCTION(0, 60),
++ MTK_FUNCTION(0, "GPIO59"),
++ MTK_FUNCTION(1, "DISP_PWM"),
++ MTK_FUNCTION(2, "PWM1"),
++ MTK_FUNCTION(7, "DBG_MON_A[18]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(60, "WB_RSTB"),
++ "AD7", "mt8127",
++ MTK_EINT_FUNCTION(0, 61),
++ MTK_FUNCTION(0, "GPIO60"),
++ MTK_FUNCTION(1, "WB_RSTB"),
++ MTK_FUNCTION(7, "DBG_MON_A[19]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(61, "F2W_DATA"),
++ "Y10", "mt8127",
++ MTK_EINT_FUNCTION(0, 62),
++ MTK_FUNCTION(0, "GPIO61"),
++ MTK_FUNCTION(1, "F2W_DATA"),
++ MTK_FUNCTION(7, "DBG_MON_A[20]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(62, "F2W_CLK"),
++ "W10", "mt8127",
++ MTK_EINT_FUNCTION(0, 63),
++ MTK_FUNCTION(0, "GPIO62"),
++ MTK_FUNCTION(1, "F2W_CK"),
++ MTK_FUNCTION(7, "DBG_MON_A[21]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(63, "WB_SCLK"),
++ "AB7", "mt8127",
++ MTK_EINT_FUNCTION(0, 64),
++ MTK_FUNCTION(0, "GPIO63"),
++ MTK_FUNCTION(1, "WB_SCLK"),
++ MTK_FUNCTION(7, "DBG_MON_A[22]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(64, "WB_SDATA"),
++ "AA7", "mt8127",
++ MTK_EINT_FUNCTION(0, 65),
++ MTK_FUNCTION(0, "GPIO64"),
++ MTK_FUNCTION(1, "WB_SDATA"),
++ MTK_FUNCTION(7, "DBG_MON_A[23]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(65, "WB_SEN"),
++ "Y7", "mt8127",
++ MTK_EINT_FUNCTION(0, 66),
++ MTK_FUNCTION(0, "GPIO65"),
++ MTK_FUNCTION(1, "WB_SEN"),
++ MTK_FUNCTION(7, "DBG_MON_A[24]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(66, "WB_CRTL0"),
++ "AA1", "mt8127",
++ MTK_EINT_FUNCTION(0, 67),
++ MTK_FUNCTION(0, "GPIO66"),
++ MTK_FUNCTION(1, "WB_CRTL0"),
++ MTK_FUNCTION(2, "DFD_NTRST_XI"),
++ MTK_FUNCTION(7, "DBG_MON_A[25]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(67, "WB_CRTL1"),
++ "AA2", "mt8127",
++ MTK_EINT_FUNCTION(0, 68),
++ MTK_FUNCTION(0, "GPIO67"),
++ MTK_FUNCTION(1, "WB_CRTL1"),
++ MTK_FUNCTION(2, "DFD_TMS_XI"),
++ MTK_FUNCTION(7, "DBG_MON_A[26]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(68, "WB_CRTL2"),
++ "Y1", "mt8127",
++ MTK_EINT_FUNCTION(0, 69),
++ MTK_FUNCTION(0, "GPIO68"),
++ MTK_FUNCTION(1, "WB_CRTL2"),
++ MTK_FUNCTION(2, "DFD_TCK_XI"),
++ MTK_FUNCTION(7, "DBG_MON_A[27]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(69, "WB_CRTL3"),
++ "Y2", "mt8127",
++ MTK_EINT_FUNCTION(0, 70),
++ MTK_FUNCTION(0, "GPIO69"),
++ MTK_FUNCTION(1, "WB_CRTL3"),
++ MTK_FUNCTION(2, "DFD_TDI_XI"),
++ MTK_FUNCTION(7, "DBG_MON_A[28]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(70, "WB_CRTL4"),
++ "Y3", "mt8127",
++ MTK_EINT_FUNCTION(0, 71),
++ MTK_FUNCTION(0, "GPIO70"),
++ MTK_FUNCTION(1, "WB_CRTL4"),
++ MTK_FUNCTION(2, "DFD_TDO"),
++ MTK_FUNCTION(7, "DBG_MON_A[29]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(71, "WB_CRTL5"),
++ "Y4", "mt8127",
++ MTK_EINT_FUNCTION(0, 72),
++ MTK_FUNCTION(0, "GPIO71"),
++ MTK_FUNCTION(1, "WB_CRTL5"),
++ MTK_FUNCTION(7, "DBG_MON_A[30]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(72, "I2S_DATA_IN"),
++ "K21", "mt8127",
++ MTK_EINT_FUNCTION(0, 73),
++ MTK_FUNCTION(0, "GPIO72"),
++ MTK_FUNCTION(1, "I2SIN1_DATA_IN"),
++ MTK_FUNCTION(2, "PCM_RX"),
++ MTK_FUNCTION(3, "I2SOUT_DATA_OUT"),
++ MTK_FUNCTION(4, "DAC_DAT_OUT"),
++ MTK_FUNCTION(5, "PWM0"),
++ MTK_FUNCTION(6, "ADC_CK"),
++ MTK_FUNCTION(7, "DBG_MON_B[19]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(73, "I2S_LRCK"),
++ "L21", "mt8127",
++ MTK_EINT_FUNCTION(0, 74),
++ MTK_FUNCTION(0, "GPIO73"),
++ MTK_FUNCTION(1, "I2SIN1_LRCK"),
++ MTK_FUNCTION(2, "PCM_SYNC"),
++ MTK_FUNCTION(3, "I2SOUT_LRCK"),
++ MTK_FUNCTION(4, "DAC_WS"),
++ MTK_FUNCTION(5, "PWM3"),
++ MTK_FUNCTION(6, "ADC_DAT_IN"),
++ MTK_FUNCTION(7, "DBG_MON_B[20]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(74, "I2S_BCK"),
++ "L20", "mt8127",
++ MTK_EINT_FUNCTION(0, 75),
++ MTK_FUNCTION(0, "GPIO74"),
++ MTK_FUNCTION(1, "I2SIN1_BCK2"),
++ MTK_FUNCTION(2, "PCM_CLK1"),
++ MTK_FUNCTION(3, "I2SOUT_BCK"),
++ MTK_FUNCTION(4, "DAC_CK"),
++ MTK_FUNCTION(5, "PWM4"),
++ MTK_FUNCTION(6, "ADC_WS"),
++ MTK_FUNCTION(7, "DBG_MON_B[21]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(75, "SDA0"),
++ "W3", "mt8127",
++ MTK_EINT_FUNCTION(0, 76),
++ MTK_FUNCTION(0, "GPIO75"),
++ MTK_FUNCTION(1, "SDA0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(76, "SCL0"),
++ "W4", "mt8127",
++ MTK_EINT_FUNCTION(0, 77),
++ MTK_FUNCTION(0, "GPIO76"),
++ MTK_FUNCTION(1, "SCL0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(77, "SDA2"),
++ "K19", "mt8127",
++ MTK_EINT_FUNCTION(0, 78),
++ MTK_FUNCTION(0, "GPIO77"),
++ MTK_FUNCTION(1, "SDA2"),
++ MTK_FUNCTION(2, "PWM1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(78, "SCL2"),
++ "K20", "mt8127",
++ MTK_EINT_FUNCTION(0, 79),
++ MTK_FUNCTION(0, "GPIO78"),
++ MTK_FUNCTION(1, "SCL2"),
++ MTK_FUNCTION(2, "PWM2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(79, "URXD0"),
++ "K18", "mt8127",
++ MTK_EINT_FUNCTION(0, 80),
++ MTK_FUNCTION(0, "GPIO79"),
++ MTK_FUNCTION(1, "URXD0"),
++ MTK_FUNCTION(2, "UTXD0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(80, "UTXD0"),
++ "K17", "mt8127",
++ MTK_EINT_FUNCTION(0, 81),
++ MTK_FUNCTION(0, "GPIO80"),
++ MTK_FUNCTION(1, "UTXD0"),
++ MTK_FUNCTION(2, "URXD0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(81, "URXD1"),
++ "L17", "mt8127",
++ MTK_EINT_FUNCTION(0, 82),
++ MTK_FUNCTION(0, "GPIO81"),
++ MTK_FUNCTION(1, "URXD1"),
++ MTK_FUNCTION(2, "UTXD1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(82, "UTXD1"),
++ "L18", "mt8127",
++ MTK_EINT_FUNCTION(0, 83),
++ MTK_FUNCTION(0, "GPIO82"),
++ MTK_FUNCTION(1, "UTXD1"),
++ MTK_FUNCTION(2, "URXD1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(83, "LCM_RST"),
++ "W5", "mt8127",
++ MTK_EINT_FUNCTION(0, 84),
++ MTK_FUNCTION(0, "GPIO83"),
++ MTK_FUNCTION(1, "LCM_RST"),
++ MTK_FUNCTION(2, "VDAC_CK_XI"),
++ MTK_FUNCTION(7, "DBG_MON_A[31]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(84, "DSI_TE"),
++ "W6", "mt8127",
++ MTK_EINT_FUNCTION(0, 85),
++ MTK_FUNCTION(0, "GPIO84"),
++ MTK_FUNCTION(1, "DSI_TE"),
++ MTK_FUNCTION(7, "DBG_MON_A[32]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(85, "MSDC2_CMD"),
++ "U7", "mt8127",
++ MTK_EINT_FUNCTION(0, 86),
++ MTK_FUNCTION(0, "GPIO85"),
++ MTK_FUNCTION(1, "MSDC2_CMD"),
++ MTK_FUNCTION(2, "ANT_SEL0"),
++ MTK_FUNCTION(3, "SDA1"),
++ MTK_FUNCTION(6, "I2SOUT_BCK"),
++ MTK_FUNCTION(7, "DBG_MON_B[22]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(86, "MSDC2_CLK"),
++ "T8", "mt8127",
++ MTK_EINT_FUNCTION(0, 87),
++ MTK_FUNCTION(0, "GPIO86"),
++ MTK_FUNCTION(1, "MSDC2_CLK"),
++ MTK_FUNCTION(2, "ANT_SEL1"),
++ MTK_FUNCTION(3, "SCL1"),
++ MTK_FUNCTION(6, "I2SOUT_LRCK"),
++ MTK_FUNCTION(7, "DBG_MON_B[23]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(87, "MSDC2_DAT0"),
++ "V3", "mt8127",
++ MTK_EINT_FUNCTION(0, 88),
++ MTK_FUNCTION(0, "GPIO87"),
++ MTK_FUNCTION(1, "MSDC2_DAT0"),
++ MTK_FUNCTION(2, "ANT_SEL2"),
++ MTK_FUNCTION(5, "UTXD0"),
++ MTK_FUNCTION(6, "I2SOUT_DATA_OUT"),
++ MTK_FUNCTION(7, "DBG_MON_B[24]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(88, "MSDC2_DAT1"),
++ "V4", "mt8127",
++ MTK_EINT_FUNCTION(0, 89),
++ MTK_FUNCTION(0, "GPIO88"),
++ MTK_FUNCTION(1, "MSDC2_DAT1"),
++ MTK_FUNCTION(2, "ANT_SEL3"),
++ MTK_FUNCTION(3, "PWM0"),
++ MTK_FUNCTION(5, "URXD0"),
++ MTK_FUNCTION(6, "PWM1"),
++ MTK_FUNCTION(7, "DBG_MON_B[25]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(89, "MSDC2_DAT2"),
++ "U5", "mt8127",
++ MTK_EINT_FUNCTION(0, 90),
++ MTK_FUNCTION(0, "GPIO89"),
++ MTK_FUNCTION(1, "MSDC2_DAT2"),
++ MTK_FUNCTION(2, "ANT_SEL4"),
++ MTK_FUNCTION(3, "SDA2"),
++ MTK_FUNCTION(5, "UTXD1"),
++ MTK_FUNCTION(6, "PWM2"),
++ MTK_FUNCTION(7, "DBG_MON_B[26]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(90, "MSDC2_DAT3"),
++ "U6", "mt8127",
++ MTK_EINT_FUNCTION(0, 91),
++ MTK_FUNCTION(0, "GPIO90"),
++ MTK_FUNCTION(1, "MSDC2_DAT3"),
++ MTK_FUNCTION(2, "ANT_SEL5"),
++ MTK_FUNCTION(3, "SCL2"),
++ MTK_FUNCTION(4, "EXT_FRAME_SYNC"),
++ MTK_FUNCTION(5, "URXD1"),
++ MTK_FUNCTION(6, "PWM3"),
++ MTK_FUNCTION(7, "DBG_MON_B[27]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(91, "TDN3"),
++ "U2", "mt8127",
++ MTK_EINT_FUNCTION(0, 92),
++ MTK_FUNCTION(0, "GPI91"),
++ MTK_FUNCTION(1, "TDN3")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(92, "TDP3"),
++ "U1", "mt8127",
++ MTK_EINT_FUNCTION(0, 93),
++ MTK_FUNCTION(0, "GPI92"),
++ MTK_FUNCTION(1, "TDP3")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(93, "TDN2"),
++ "T2", "mt8127",
++ MTK_EINT_FUNCTION(0, 94),
++ MTK_FUNCTION(0, "GPI93"),
++ MTK_FUNCTION(1, "TDN2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(94, "TDP2"),
++ "T1", "mt8127",
++ MTK_EINT_FUNCTION(0, 95),
++ MTK_FUNCTION(0, "GPI94"),
++ MTK_FUNCTION(1, "TDP2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(95, "TCN"),
++ "R5", "mt8127",
++ MTK_EINT_FUNCTION(0, 96),
++ MTK_FUNCTION(0, "GPI95"),
++ MTK_FUNCTION(1, "TCN")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(96, "TCP"),
++ "R4", "mt8127",
++ MTK_EINT_FUNCTION(0, 97),
++ MTK_FUNCTION(0, "GPI96"),
++ MTK_FUNCTION(1, "TCP")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(97, "TDN1"),
++ "R3", "mt8127",
++ MTK_EINT_FUNCTION(0, 98),
++ MTK_FUNCTION(0, "GPI97"),
++ MTK_FUNCTION(1, "TDN1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(98, "TDP1"),
++ "R2", "mt8127",
++ MTK_EINT_FUNCTION(0, 99),
++ MTK_FUNCTION(0, "GPI98"),
++ MTK_FUNCTION(1, "TDP1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(99, "TDN0"),
++ "P3", "mt8127",
++ MTK_EINT_FUNCTION(0, 100),
++ MTK_FUNCTION(0, "GPI99"),
++ MTK_FUNCTION(1, "TDN0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(100, "TDP0"),
++ "P2", "mt8127",
++ MTK_EINT_FUNCTION(0, 101),
++ MTK_FUNCTION(0, "GPI100"),
++ MTK_FUNCTION(1, "TDP0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(101, "RDN0"),
++ "K1", "mt8127",
++ MTK_EINT_FUNCTION(0, 102),
++ MTK_FUNCTION(0, "GPI101"),
++ MTK_FUNCTION(1, "RDN0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(102, "RDP0"),
++ "K2", "mt8127",
++ MTK_EINT_FUNCTION(0, 103),
++ MTK_FUNCTION(0, "GPI102"),
++ MTK_FUNCTION(1, "RDP0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(103, "RDN1"),
++ "L2", "mt8127",
++ MTK_EINT_FUNCTION(0, 104),
++ MTK_FUNCTION(0, "GPI103"),
++ MTK_FUNCTION(1, "RDN1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(104, "RDP1"),
++ "L3", "mt8127",
++ MTK_EINT_FUNCTION(0, 105),
++ MTK_FUNCTION(0, "GPI104"),
++ MTK_FUNCTION(1, "RDP1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(105, "RCN"),
++ "M4", "mt8127",
++ MTK_EINT_FUNCTION(0, 106),
++ MTK_FUNCTION(0, "GPI105"),
++ MTK_FUNCTION(1, "RCN")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(106, "RCP"),
++ "M5", "mt8127",
++ MTK_EINT_FUNCTION(0, 107),
++ MTK_FUNCTION(0, "GPI106"),
++ MTK_FUNCTION(1, "RCP")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(107, "RDN2"),
++ "M2", "mt8127",
++ MTK_EINT_FUNCTION(0, 108),
++ MTK_FUNCTION(0, "GPI107"),
++ MTK_FUNCTION(1, "RDN2"),
++ MTK_FUNCTION(2, "CMDAT8")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(108, "RDP2"),
++ "M3", "mt8127",
++ MTK_EINT_FUNCTION(0, 109),
++ MTK_FUNCTION(0, "GPI108"),
++ MTK_FUNCTION(1, "RDP2"),
++ MTK_FUNCTION(2, "CMDAT9")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(109, "RDN3"),
++ "N2", "mt8127",
++ MTK_EINT_FUNCTION(0, 110),
++ MTK_FUNCTION(0, "GPI109"),
++ MTK_FUNCTION(1, "RDN3"),
++ MTK_FUNCTION(2, "CMDAT4")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(110, "RDP3"),
++ "N3", "mt8127",
++ MTK_EINT_FUNCTION(0, 111),
++ MTK_FUNCTION(0, "GPI110"),
++ MTK_FUNCTION(1, "RDP3"),
++ MTK_FUNCTION(2, "CMDAT5")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(111, "RCN_A"),
++ "J5", "mt8127",
++ MTK_EINT_FUNCTION(0, 112),
++ MTK_FUNCTION(0, "GPI111"),
++ MTK_FUNCTION(1, "RCN_A"),
++ MTK_FUNCTION(2, "CMDAT6")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(112, "RCP_A"),
++ "J4", "mt8127",
++ MTK_EINT_FUNCTION(0, 113),
++ MTK_FUNCTION(0, "GPI112"),
++ MTK_FUNCTION(1, "RCP_A"),
++ MTK_FUNCTION(2, "CMDAT7")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(113, "RDN1_A"),
++ "J2", "mt8127",
++ MTK_EINT_FUNCTION(0, 114),
++ MTK_FUNCTION(0, "GPI113"),
++ MTK_FUNCTION(1, "RDN1_A"),
++ MTK_FUNCTION(2, "CMDAT2"),
++ MTK_FUNCTION(3, "CMCSD2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(114, "RDP1_A"),
++ "J3", "mt8127",
++ MTK_EINT_FUNCTION(0, 115),
++ MTK_FUNCTION(0, "GPI114"),
++ MTK_FUNCTION(1, "RDP1_A"),
++ MTK_FUNCTION(2, "CMDAT3"),
++ MTK_FUNCTION(3, "CMCSD3")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(115, "RDN0_A"),
++ "H2", "mt8127",
++ MTK_EINT_FUNCTION(0, 116),
++ MTK_FUNCTION(0, "GPI115"),
++ MTK_FUNCTION(1, "RDN0_A"),
++ MTK_FUNCTION(2, "CMHSYNC")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(116, "RDP0_A"),
++ "H3", "mt8127",
++ MTK_EINT_FUNCTION(0, 117),
++ MTK_FUNCTION(0, "GPI116"),
++ MTK_FUNCTION(1, "RDP0_A"),
++ MTK_FUNCTION(2, "CMVSYNC")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(117, "CMDAT0"),
++ "G5", "mt8127",
++ MTK_EINT_FUNCTION(0, 118),
++ MTK_FUNCTION(0, "GPIO117"),
++ MTK_FUNCTION(1, "CMDAT0"),
++ MTK_FUNCTION(2, "CMCSD0"),
++ MTK_FUNCTION(3, "ANT_SEL2"),
++ MTK_FUNCTION(7, "DBG_MON_B[28]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(118, "CMDAT1"),
++ "G4", "mt8127",
++ MTK_EINT_FUNCTION(0, 119),
++ MTK_FUNCTION(0, "GPIO118"),
++ MTK_FUNCTION(1, "CMDAT1"),
++ MTK_FUNCTION(2, "CMCSD1"),
++ MTK_FUNCTION(3, "ANT_SEL3"),
++ MTK_FUNCTION(7, "DBG_MON_B[29]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(119, "CMMCLK"),
++ "F3", "mt8127",
++ MTK_EINT_FUNCTION(0, 120),
++ MTK_FUNCTION(0, "GPIO119"),
++ MTK_FUNCTION(1, "CMMCLK"),
++ MTK_FUNCTION(3, "ANT_SEL4"),
++ MTK_FUNCTION(7, "DBG_MON_B[30]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(120, "CMPCLK"),
++ "G6", "mt8127",
++ MTK_EINT_FUNCTION(0, 121),
++ MTK_FUNCTION(0, "GPIO120"),
++ MTK_FUNCTION(1, "CMPCLK"),
++ MTK_FUNCTION(2, "CMCSK"),
++ MTK_FUNCTION(3, "ANT_SEL5"),
++ MTK_FUNCTION(7, "DBG_MON_B[31]")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(121, "MSDC1_CMD"),
++ "E3", "mt8127",
++ MTK_EINT_FUNCTION(0, 122),
++ MTK_FUNCTION(0, "GPIO121"),
++ MTK_FUNCTION(1, "MSDC1_CMD")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(122, "MSDC1_CLK"),
++ "D1", "mt8127",
++ MTK_EINT_FUNCTION(0, 123),
++ MTK_FUNCTION(0, "GPIO122"),
++ MTK_FUNCTION(1, "MSDC1_CLK")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(123, "MSDC1_DAT0"),
++ "D2", "mt8127",
++ MTK_EINT_FUNCTION(0, 124),
++ MTK_FUNCTION(0, "GPIO123"),
++ MTK_FUNCTION(1, "MSDC1_DAT0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(124, "MSDC1_DAT1"),
++ "D3", "mt8127",
++ MTK_EINT_FUNCTION(0, 125),
++ MTK_FUNCTION(0, "GPIO124"),
++ MTK_FUNCTION(1, "MSDC1_DAT1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(125, "MSDC1_DAT2"),
++ "F2", "mt8127",
++ MTK_EINT_FUNCTION(0, 126),
++ MTK_FUNCTION(0, "GPIO125"),
++ MTK_FUNCTION(1, "MSDC1_DAT2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(126, "MSDC1_DAT3"),
++ "E2", "mt8127",
++ MTK_EINT_FUNCTION(0, 127),
++ MTK_FUNCTION(0, "GPIO126"),
++ MTK_FUNCTION(1, "MSDC1_DAT3")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(127, "MSDC0_DAT7"),
++ "C23", "mt8127",
++ MTK_EINT_FUNCTION(0, 128),
++ MTK_FUNCTION(0, "GPIO127"),
++ MTK_FUNCTION(1, "MSDC0_DAT7"),
++ MTK_FUNCTION(4, "NLD7")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(128, "MSDC0_DAT6"),
++ "C24", "mt8127",
++ MTK_EINT_FUNCTION(0, 129),
++ MTK_FUNCTION(0, "GPIO128"),
++ MTK_FUNCTION(1, "MSDC0_DAT6"),
++ MTK_FUNCTION(4, "NLD6")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(129, "MSDC0_DAT5"),
++ "D22", "mt8127",
++ MTK_EINT_FUNCTION(0, 130),
++ MTK_FUNCTION(0, "GPIO129"),
++ MTK_FUNCTION(1, "MSDC0_DAT5"),
++ MTK_FUNCTION(4, "NLD4")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(130, "MSDC0_DAT4"),
++ "D24", "mt8127",
++ MTK_EINT_FUNCTION(0, 131),
++ MTK_FUNCTION(0, "GPIO130"),
++ MTK_FUNCTION(1, "MSDC0_DAT4"),
++ MTK_FUNCTION(4, "NLD3")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(131, "MSDC0_RSTB"),
++ "F24", "mt8127",
++ MTK_EINT_FUNCTION(0, 132),
++ MTK_FUNCTION(0, "GPIO131"),
++ MTK_FUNCTION(1, "MSDC0_RSTB"),
++ MTK_FUNCTION(4, "NLD0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(132, "MSDC0_CMD"),
++ "G20", "mt8127",
++ MTK_EINT_FUNCTION(0, 133),
++ MTK_FUNCTION(0, "GPIO132"),
++ MTK_FUNCTION(1, "MSDC0_CMD"),
++ MTK_FUNCTION(4, "NALE")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(133, "MSDC0_CLK"),
++ "G21", "mt8127",
++ MTK_EINT_FUNCTION(0, 134),
++ MTK_FUNCTION(0, "GPIO133"),
++ MTK_FUNCTION(1, "MSDC0_CLK"),
++ MTK_FUNCTION(4, "NWEB")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(134, "MSDC0_DAT3"),
++ "D23", "mt8127",
++ MTK_EINT_FUNCTION(0, 135),
++ MTK_FUNCTION(0, "GPIO134"),
++ MTK_FUNCTION(1, "MSDC0_DAT3"),
++ MTK_FUNCTION(4, "NLD1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(135, "MSDC0_DAT2"),
++ "E22", "mt8127",
++ MTK_EINT_FUNCTION(0, 136),
++ MTK_FUNCTION(0, "GPIO135"),
++ MTK_FUNCTION(1, "MSDC0_DAT2"),
++ MTK_FUNCTION(4, "NLD5")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(136, "MSDC0_DAT1"),
++ "E23", "mt8127",
++ MTK_EINT_FUNCTION(0, 137),
++ MTK_FUNCTION(0, "GPIO136"),
++ MTK_FUNCTION(1, "MSDC0_DAT1"),
++ MTK_FUNCTION(4, "NLD8")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(137, "MSDC0_DAT0"),
++ "F22", "mt8127",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO137"),
++ MTK_FUNCTION(1, "MSDC0_DAT0"),
++ MTK_FUNCTION(4, "WATCHDOG"),
++ MTK_FUNCTION(5, "NLD2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(138, "CEC"),
++ "AE21", "mt8127",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO138"),
++ MTK_FUNCTION(1, "CEC")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(139, "HTPLG"),
++ "AD21", "mt8127",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO139"),
++ MTK_FUNCTION(1, "HTPLG")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(140, "HDMISCK"),
++ "AE22", "mt8127",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO140"),
++ MTK_FUNCTION(1, "HDMISCK")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(141, "HDMISD"),
++ "AD22", "mt8127",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO141"),
++ MTK_FUNCTION(1, "HDMISD")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(142, "EINT21"),
++ "J23", "mt8127",
++ MTK_EINT_FUNCTION(0, 21),
++ MTK_FUNCTION(0, "GPIO142"),
++ MTK_FUNCTION(1, "NRNB"),
++ MTK_FUNCTION(2, "ANT_SEL0"),
++ MTK_FUNCTION(7, "DBG_MON_B[32]")
++ ),
++};
++
++#endif /* __PINCTRL_MTK_MT8127_H */
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0055-mfd-mediatek-Add-GPIO-sub-module-support-into-mfd.patch b/target/linux/mediatek/patches/0055-mfd-mediatek-Add-GPIO-sub-module-support-into-mfd.patch
new file mode 100644
index 0000000000..d9c0676c81
--- /dev/null
+++ b/target/linux/mediatek/patches/0055-mfd-mediatek-Add-GPIO-sub-module-support-into-mfd.patch
@@ -0,0 +1,30 @@
+From e5de6556a25d4b2e2d30683d629095bce102c792 Mon Sep 17 00:00:00 2001
+From: Hongzhou Yang <hongzhou.yang@mediatek.com>
+Date: Mon, 18 May 2015 23:11:19 -0700
+Subject: [PATCH 55/76] mfd: mediatek: Add GPIO sub module support into mfd.
+
+Register pinctrl subnode into 6397 mfd cell.
+
+Signed-off-by: Hongzhou Yang <hongzhou.yang@mediatek.com>
+Acked-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/mfd/mt6397-core.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
+index 09bc780..012c620 100644
+--- a/drivers/mfd/mt6397-core.c
++++ b/drivers/mfd/mt6397-core.c
+@@ -34,6 +34,9 @@ static const struct mfd_cell mt6397_devs[] = {
+ }, {
+ .name = "mt6397-clk",
+ .of_compatible = "mediatek,mt6397-clk",
++ }, {
++ .name = "mediatek-mt6397-pinctrl",
++ .of_compatible = "mediatek,mt6397-pinctrl",
+ },
+ };
+
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0056-ARM-dts-mt8127-add-pinctrl-GPIO-EINT-node-for-mt8127.patch b/target/linux/mediatek/patches/0056-ARM-dts-mt8127-add-pinctrl-GPIO-EINT-node-for-mt8127.patch
new file mode 100644
index 0000000000..a59d2c609b
--- /dev/null
+++ b/target/linux/mediatek/patches/0056-ARM-dts-mt8127-add-pinctrl-GPIO-EINT-node-for-mt8127.patch
@@ -0,0 +1,809 @@
+From 619e31dbd73885249f3db545ed0b7678ca98c248 Mon Sep 17 00:00:00 2001
+From: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Date: Mon, 18 May 2015 23:11:20 -0700
+Subject: [PATCH 56/76] ARM: dts: mt8127: add pinctrl/GPIO/EINT node for
+ mt8127
+
+Add pinctrl,GPIO and EINT node to mt8127.dtsi.
+
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Signed-off-by: Hongzhou Yang <hongzhou.yang@mediatek.com>
+Acked-by: Linus Walleij <linus.walleij@linaro.org>
+Acked-by: Matthias Brugger <matthias.bgg@gmail.com>
+---
+ arch/arm/boot/dts/mt8127-pinfunc.h | 742 ++++++++++++++++++++++++++++++++++++
+ arch/arm/boot/dts/mt8127.dtsi | 22 ++
+ 2 files changed, 764 insertions(+)
+ create mode 100644 arch/arm/boot/dts/mt8127-pinfunc.h
+
+diff --git a/arch/arm/boot/dts/mt8127-pinfunc.h b/arch/arm/boot/dts/mt8127-pinfunc.h
+new file mode 100644
+index 0000000..9198331
+--- /dev/null
++++ b/arch/arm/boot/dts/mt8127-pinfunc.h
+@@ -0,0 +1,742 @@
++#ifndef __DTS_MT8127_PINFUNC_H
++#define __DTS_MT8127_PINFUNC_H
++
++#include <dt-bindings/pinctrl/mt65xx.h>
++
++#define MT8127_PIN_0_PWRAP_SPI0_MI__FUNC_GPIO0 (MTK_PIN_NO(0) | 0)
++#define MT8127_PIN_0_PWRAP_SPI0_MI__FUNC_PWRAP_SPIDO (MTK_PIN_NO(0) | 1)
++#define MT8127_PIN_0_PWRAP_SPI0_MI__FUNC_PWRAP_SPIDI (MTK_PIN_NO(0) | 2)
++
++#define MT8127_PIN_1_PWRAP_SPI0_MO__FUNC_GPIO1 (MTK_PIN_NO(1) | 0)
++#define MT8127_PIN_1_PWRAP_SPI0_MO__FUNC_PWRAP_SPIDI (MTK_PIN_NO(1) | 1)
++#define MT8127_PIN_1_PWRAP_SPI0_MO__FUNC_PWRAP_SPIDO (MTK_PIN_NO(1) | 2)
++
++#define MT8127_PIN_2_PWRAP_INT__FUNC_GPIO2 (MTK_PIN_NO(2) | 0)
++
++#define MT8127_PIN_3_PWRAP_SPI0_CK__FUNC_GPIO3 (MTK_PIN_NO(3) | 0)
++#define MT8127_PIN_3_PWRAP_SPI0_CK__FUNC_PWRAP_SPICK_I (MTK_PIN_NO(3) | 1)
++
++#define MT8127_PIN_4_PWRAP_SPI0_CSN__FUNC_GPIO4 (MTK_PIN_NO(4) | 0)
++#define MT8127_PIN_4_PWRAP_SPI0_CSN__FUNC_PWRAP_SPICS_B_I (MTK_PIN_NO(4) | 1)
++
++#define MT8127_PIN_5_PWRAP_SPI0_CK2__FUNC_GPIO5 (MTK_PIN_NO(5) | 0)
++#define MT8127_PIN_5_PWRAP_SPI0_CK2__FUNC_PWRAP_SPICK2_I (MTK_PIN_NO(5) | 1)
++#define MT8127_PIN_5_PWRAP_SPI0_CK2__FUNC_ANT_SEL1 (MTK_PIN_NO(5) | 2)
++#define MT8127_PIN_5_PWRAP_SPI0_CK2__FUNC_VDEC_TEST_CK (MTK_PIN_NO(5) | 3)
++#define MT8127_PIN_5_PWRAP_SPI0_CK2__FUNC_DBG_MON_B_0 (MTK_PIN_NO(5) | 7)
++
++#define MT8127_PIN_6_PWRAP_SPI0_CSN2__FUNC_GPIO6 (MTK_PIN_NO(6) | 0)
++#define MT8127_PIN_6_PWRAP_SPI0_CSN2__FUNC_PWRAP_SPICS2_B_I (MTK_PIN_NO(6) | 1)
++#define MT8127_PIN_6_PWRAP_SPI0_CSN2__FUNC_ANT_SEL0 (MTK_PIN_NO(6) | 2)
++#define MT8127_PIN_6_PWRAP_SPI0_CSN2__FUNC_MM_TEST_CK (MTK_PIN_NO(6) | 3)
++#define MT8127_PIN_6_PWRAP_SPI0_CSN2__FUNC_DBG_MON_B_1 (MTK_PIN_NO(6) | 7)
++
++#define MT8127_PIN_7_AUD_CLK_MOSI__FUNC_GPIO7 (MTK_PIN_NO(7) | 0)
++#define MT8127_PIN_7_AUD_CLK_MOSI__FUNC_AUD_CLK (MTK_PIN_NO(7) | 1)
++#define MT8127_PIN_7_AUD_CLK_MOSI__FUNC_ADC_CK (MTK_PIN_NO(7) | 2)
++
++#define MT8127_PIN_8_AUD_DAT_MISO__FUNC_GPIO8 (MTK_PIN_NO(8) | 0)
++#define MT8127_PIN_8_AUD_DAT_MISO__FUNC_AUD_MISO (MTK_PIN_NO(8) | 1)
++#define MT8127_PIN_8_AUD_DAT_MISO__FUNC_ADC_DAT_IN (MTK_PIN_NO(8) | 2)
++#define MT8127_PIN_8_AUD_DAT_MISO__FUNC_AUD_MOSI (MTK_PIN_NO(8) | 3)
++
++#define MT8127_PIN_9_AUD_DAT_MOSI__FUNC_GPIO9 (MTK_PIN_NO(9) | 0)
++#define MT8127_PIN_9_AUD_DAT_MOSI__FUNC_AUD_MOSI (MTK_PIN_NO(9) | 1)
++#define MT8127_PIN_9_AUD_DAT_MOSI__FUNC_ADC_WS (MTK_PIN_NO(9) | 2)
++#define MT8127_PIN_9_AUD_DAT_MOSI__FUNC_AUD_MISO (MTK_PIN_NO(9) | 3)
++
++#define MT8127_PIN_10_RTC32K_CK__FUNC_GPIO10 (MTK_PIN_NO(10) | 0)
++#define MT8127_PIN_10_RTC32K_CK__FUNC_RTC32K_CK (MTK_PIN_NO(10) | 1)
++
++#define MT8127_PIN_11_WATCHDOG__FUNC_GPIO11 (MTK_PIN_NO(11) | 0)
++#define MT8127_PIN_11_WATCHDOG__FUNC_WATCHDOG (MTK_PIN_NO(11) | 1)
++
++#define MT8127_PIN_12_SRCLKENA__FUNC_GPIO12 (MTK_PIN_NO(12) | 0)
++#define MT8127_PIN_12_SRCLKENA__FUNC_SRCLKENA (MTK_PIN_NO(12) | 1)
++
++#define MT8127_PIN_13_SRCLKENAI__FUNC_GPIO13 (MTK_PIN_NO(13) | 0)
++#define MT8127_PIN_13_SRCLKENAI__FUNC_SRCLKENAI (MTK_PIN_NO(13) | 1)
++
++#define MT8127_PIN_14_URXD2__FUNC_GPIO14 (MTK_PIN_NO(14) | 0)
++#define MT8127_PIN_14_URXD2__FUNC_URXD2 (MTK_PIN_NO(14) | 1)
++#define MT8127_PIN_14_URXD2__FUNC_DPI_D5 (MTK_PIN_NO(14) | 2)
++#define MT8127_PIN_14_URXD2__FUNC_UTXD2 (MTK_PIN_NO(14) | 3)
++#define MT8127_PIN_14_URXD2__FUNC_SRCCLKENAI2 (MTK_PIN_NO(14) | 5)
++#define MT8127_PIN_14_URXD2__FUNC_KROW4 (MTK_PIN_NO(14) | 6)
++
++#define MT8127_PIN_15_UTXD2__FUNC_GPIO15 (MTK_PIN_NO(15) | 0)
++#define MT8127_PIN_15_UTXD2__FUNC_UTXD2 (MTK_PIN_NO(15) | 1)
++#define MT8127_PIN_15_UTXD2__FUNC_DPI_HSYNC (MTK_PIN_NO(15) | 2)
++#define MT8127_PIN_15_UTXD2__FUNC_URXD2 (MTK_PIN_NO(15) | 3)
++#define MT8127_PIN_15_UTXD2__FUNC_KROW5 (MTK_PIN_NO(15) | 6)
++
++#define MT8127_PIN_16_URXD3__FUNC_GPIO16 (MTK_PIN_NO(16) | 0)
++#define MT8127_PIN_16_URXD3__FUNC_URXD3 (MTK_PIN_NO(16) | 1)
++#define MT8127_PIN_16_URXD3__FUNC_DPI_DE (MTK_PIN_NO(16) | 2)
++#define MT8127_PIN_16_URXD3__FUNC_UTXD3 (MTK_PIN_NO(16) | 3)
++#define MT8127_PIN_16_URXD3__FUNC_UCTS2 (MTK_PIN_NO(16) | 4)
++#define MT8127_PIN_16_URXD3__FUNC_PWM3 (MTK_PIN_NO(16) | 5)
++#define MT8127_PIN_16_URXD3__FUNC_KROW6 (MTK_PIN_NO(16) | 6)
++
++#define MT8127_PIN_17_UTXD3__FUNC_GPIO17 (MTK_PIN_NO(17) | 0)
++#define MT8127_PIN_17_UTXD3__FUNC_UTXD3 (MTK_PIN_NO(17) | 1)
++#define MT8127_PIN_17_UTXD3__FUNC_DPI_VSYNC (MTK_PIN_NO(17) | 2)
++#define MT8127_PIN_17_UTXD3__FUNC_URXD3 (MTK_PIN_NO(17) | 3)
++#define MT8127_PIN_17_UTXD3__FUNC_URTS2 (MTK_PIN_NO(17) | 4)
++#define MT8127_PIN_17_UTXD3__FUNC_PWM4 (MTK_PIN_NO(17) | 5)
++#define MT8127_PIN_17_UTXD3__FUNC_KROW7 (MTK_PIN_NO(17) | 6)
++
++#define MT8127_PIN_18_PCM_CLK__FUNC_GPIO18 (MTK_PIN_NO(18) | 0)
++#define MT8127_PIN_18_PCM_CLK__FUNC_PCM_CLK0 (MTK_PIN_NO(18) | 1)
++#define MT8127_PIN_18_PCM_CLK__FUNC_DPI_D4 (MTK_PIN_NO(18) | 2)
++#define MT8127_PIN_18_PCM_CLK__FUNC_I2SIN1_BCK0 (MTK_PIN_NO(18) | 3)
++#define MT8127_PIN_18_PCM_CLK__FUNC_I2SOUT_BCK (MTK_PIN_NO(18) | 4)
++#define MT8127_PIN_18_PCM_CLK__FUNC_CONN_DSP_JCK (MTK_PIN_NO(18) | 5)
++#define MT8127_PIN_18_PCM_CLK__FUNC_IR (MTK_PIN_NO(18) | 6)
++#define MT8127_PIN_18_PCM_CLK__FUNC_DBG_MON_A_0 (MTK_PIN_NO(18) | 7)
++
++#define MT8127_PIN_19_PCM_SYNC__FUNC_GPIO19 (MTK_PIN_NO(19) | 0)
++#define MT8127_PIN_19_PCM_SYNC__FUNC_PCM_SYNC (MTK_PIN_NO(19) | 1)
++#define MT8127_PIN_19_PCM_SYNC__FUNC_DPI_D3 (MTK_PIN_NO(19) | 2)
++#define MT8127_PIN_19_PCM_SYNC__FUNC_I2SIN1_LRCK (MTK_PIN_NO(19) | 3)
++#define MT8127_PIN_19_PCM_SYNC__FUNC_I2SOUT_LRCK (MTK_PIN_NO(19) | 4)
++#define MT8127_PIN_19_PCM_SYNC__FUNC_CONN_DSP_JINTP (MTK_PIN_NO(19) | 5)
++#define MT8127_PIN_19_PCM_SYNC__FUNC_EXT_COL (MTK_PIN_NO(19) | 6)
++#define MT8127_PIN_19_PCM_SYNC__FUNC_DBG_MON_A_1 (MTK_PIN_NO(19) | 7)
++
++#define MT8127_PIN_20_PCM_RX__FUNC_GPIO20 (MTK_PIN_NO(20) | 0)
++#define MT8127_PIN_20_PCM_RX__FUNC_PCM_RX (MTK_PIN_NO(20) | 1)
++#define MT8127_PIN_20_PCM_RX__FUNC_DPI_D1 (MTK_PIN_NO(20) | 2)
++#define MT8127_PIN_20_PCM_RX__FUNC_I2SIN1_DATA_IN (MTK_PIN_NO(20) | 3)
++#define MT8127_PIN_20_PCM_RX__FUNC_PCM_TX (MTK_PIN_NO(20) | 4)
++#define MT8127_PIN_20_PCM_RX__FUNC_CONN_DSP_JDI (MTK_PIN_NO(20) | 5)
++#define MT8127_PIN_20_PCM_RX__FUNC_EXT_MDIO (MTK_PIN_NO(20) | 6)
++#define MT8127_PIN_20_PCM_RX__FUNC_DBG_MON_A_2 (MTK_PIN_NO(20) | 7)
++
++#define MT8127_PIN_21_PCM_TX__FUNC_GPIO21 (MTK_PIN_NO(21) | 0)
++#define MT8127_PIN_21_PCM_TX__FUNC_PCM_TX (MTK_PIN_NO(21) | 1)
++#define MT8127_PIN_21_PCM_TX__FUNC_DPI_D2 (MTK_PIN_NO(21) | 2)
++#define MT8127_PIN_21_PCM_TX__FUNC_I2SOUT_DATA_OUT (MTK_PIN_NO(21) | 3)
++#define MT8127_PIN_21_PCM_TX__FUNC_PCM_RX (MTK_PIN_NO(21) | 4)
++#define MT8127_PIN_21_PCM_TX__FUNC_CONN_DSP_JMS (MTK_PIN_NO(21) | 5)
++#define MT8127_PIN_21_PCM_TX__FUNC_EXT_MDC (MTK_PIN_NO(21) | 6)
++#define MT8127_PIN_21_PCM_TX__FUNC_DBG_MON_A_3 (MTK_PIN_NO(21) | 7)
++
++#define MT8127_PIN_22_EINT0__FUNC_GPIO22 (MTK_PIN_NO(22) | 0)
++#define MT8127_PIN_22_EINT0__FUNC_PWM1 (MTK_PIN_NO(22) | 1)
++#define MT8127_PIN_22_EINT0__FUNC_DPI_CK (MTK_PIN_NO(22) | 2)
++#define MT8127_PIN_22_EINT0__FUNC_EXT_TXD0 (MTK_PIN_NO(22) | 4)
++#define MT8127_PIN_22_EINT0__FUNC_CONN_DSP_JDO (MTK_PIN_NO(22) | 5)
++#define MT8127_PIN_22_EINT0__FUNC_DBG_MON_A_4 (MTK_PIN_NO(22) | 7)
++
++#define MT8127_PIN_23_EINT1__FUNC_GPIO23 (MTK_PIN_NO(23) | 0)
++#define MT8127_PIN_23_EINT1__FUNC_PWM2 (MTK_PIN_NO(23) | 1)
++#define MT8127_PIN_23_EINT1__FUNC_DPI_D12 (MTK_PIN_NO(23) | 2)
++#define MT8127_PIN_23_EINT1__FUNC_EXT_TXD1 (MTK_PIN_NO(23) | 4)
++#define MT8127_PIN_23_EINT1__FUNC_CONN_MCU_TDO (MTK_PIN_NO(23) | 5)
++#define MT8127_PIN_23_EINT1__FUNC_DBG_MON_A_5 (MTK_PIN_NO(23) | 7)
++
++#define MT8127_PIN_24_EINT2__FUNC_GPIO24 (MTK_PIN_NO(24) | 0)
++#define MT8127_PIN_24_EINT2__FUNC_CLKM0 (MTK_PIN_NO(24) | 1)
++#define MT8127_PIN_24_EINT2__FUNC_DPI_D13 (MTK_PIN_NO(24) | 2)
++#define MT8127_PIN_24_EINT2__FUNC_EXT_TXD2 (MTK_PIN_NO(24) | 4)
++#define MT8127_PIN_24_EINT2__FUNC_CONN_MCU_DBGACK_N (MTK_PIN_NO(24) | 5)
++#define MT8127_PIN_24_EINT2__FUNC_KCOL4 (MTK_PIN_NO(24) | 6)
++#define MT8127_PIN_24_EINT2__FUNC_DBG_MON_A_6 (MTK_PIN_NO(24) | 7)
++
++#define MT8127_PIN_25_EINT3__FUNC_GPIO25 (MTK_PIN_NO(25) | 0)
++#define MT8127_PIN_25_EINT3__FUNC_CLKM1 (MTK_PIN_NO(25) | 1)
++#define MT8127_PIN_25_EINT3__FUNC_DPI_D14 (MTK_PIN_NO(25) | 2)
++#define MT8127_PIN_25_EINT3__FUNC_SPI_MI (MTK_PIN_NO(25) | 3)
++#define MT8127_PIN_25_EINT3__FUNC_EXT_TXD3 (MTK_PIN_NO(25) | 4)
++#define MT8127_PIN_25_EINT3__FUNC_CONN_MCU_DBGI_N (MTK_PIN_NO(25) | 5)
++#define MT8127_PIN_25_EINT3__FUNC_KCOL5 (MTK_PIN_NO(25) | 6)
++#define MT8127_PIN_25_EINT3__FUNC_DBG_MON_A_7 (MTK_PIN_NO(25) | 7)
++
++#define MT8127_PIN_26_EINT4__FUNC_GPIO26 (MTK_PIN_NO(26) | 0)
++#define MT8127_PIN_26_EINT4__FUNC_CLKM2 (MTK_PIN_NO(26) | 1)
++#define MT8127_PIN_26_EINT4__FUNC_DPI_D15 (MTK_PIN_NO(26) | 2)
++#define MT8127_PIN_26_EINT4__FUNC_SPI_MO (MTK_PIN_NO(26) | 3)
++#define MT8127_PIN_26_EINT4__FUNC_EXT_TXC (MTK_PIN_NO(26) | 4)
++#define MT8127_PIN_26_EINT4__FUNC_CONN_MCU_TCK0 (MTK_PIN_NO(26) | 5)
++#define MT8127_PIN_26_EINT4__FUNC_CONN_MCU_AICE_JCKC (MTK_PIN_NO(26) | 6)
++#define MT8127_PIN_26_EINT4__FUNC_DBG_MON_A_8 (MTK_PIN_NO(26) | 7)
++
++#define MT8127_PIN_27_EINT5__FUNC_GPIO27 (MTK_PIN_NO(27) | 0)
++#define MT8127_PIN_27_EINT5__FUNC_UCTS2 (MTK_PIN_NO(27) | 1)
++#define MT8127_PIN_27_EINT5__FUNC_DPI_D16 (MTK_PIN_NO(27) | 2)
++#define MT8127_PIN_27_EINT5__FUNC_SPI_CS (MTK_PIN_NO(27) | 3)
++#define MT8127_PIN_27_EINT5__FUNC_EXT_RXER (MTK_PIN_NO(27) | 4)
++#define MT8127_PIN_27_EINT5__FUNC_CONN_MCU_TDI (MTK_PIN_NO(27) | 5)
++#define MT8127_PIN_27_EINT5__FUNC_KCOL6 (MTK_PIN_NO(27) | 6)
++#define MT8127_PIN_27_EINT5__FUNC_DBG_MON_A_9 (MTK_PIN_NO(27) | 7)
++
++#define MT8127_PIN_28_EINT6__FUNC_GPIO28 (MTK_PIN_NO(28) | 0)
++#define MT8127_PIN_28_EINT6__FUNC_URTS2 (MTK_PIN_NO(28) | 1)
++#define MT8127_PIN_28_EINT6__FUNC_DPI_D17 (MTK_PIN_NO(28) | 2)
++#define MT8127_PIN_28_EINT6__FUNC_SPI_CK (MTK_PIN_NO(28) | 3)
++#define MT8127_PIN_28_EINT6__FUNC_EXT_RXC (MTK_PIN_NO(28) | 4)
++#define MT8127_PIN_28_EINT6__FUNC_CONN_MCU_TRST_B (MTK_PIN_NO(28) | 5)
++#define MT8127_PIN_28_EINT6__FUNC_KCOL7 (MTK_PIN_NO(28) | 6)
++#define MT8127_PIN_28_EINT6__FUNC_DBG_MON_A_10 (MTK_PIN_NO(28) | 7)
++
++#define MT8127_PIN_29_EINT7__FUNC_GPIO29 (MTK_PIN_NO(29) | 0)
++#define MT8127_PIN_29_EINT7__FUNC_UCTS3 (MTK_PIN_NO(29) | 1)
++#define MT8127_PIN_29_EINT7__FUNC_DPI_D6 (MTK_PIN_NO(29) | 2)
++#define MT8127_PIN_29_EINT7__FUNC_SDA1 (MTK_PIN_NO(29) | 3)
++#define MT8127_PIN_29_EINT7__FUNC_EXT_RXDV (MTK_PIN_NO(29) | 4)
++#define MT8127_PIN_29_EINT7__FUNC_CONN_MCU_TMS (MTK_PIN_NO(29) | 5)
++#define MT8127_PIN_29_EINT7__FUNC_CONN_MCU_AICE_JMSC (MTK_PIN_NO(29) | 6)
++#define MT8127_PIN_29_EINT7__FUNC_DBG_MON_A_11 (MTK_PIN_NO(29) | 7)
++
++#define MT8127_PIN_30_EINT8__FUNC_GPIO30 (MTK_PIN_NO(30) | 0)
++#define MT8127_PIN_30_EINT8__FUNC_URTS3 (MTK_PIN_NO(30) | 1)
++#define MT8127_PIN_30_EINT8__FUNC_CLKM3 (MTK_PIN_NO(30) | 2)
++#define MT8127_PIN_30_EINT8__FUNC_SCL1 (MTK_PIN_NO(30) | 3)
++#define MT8127_PIN_30_EINT8__FUNC_EXT_RXD0 (MTK_PIN_NO(30) | 4)
++#define MT8127_PIN_30_EINT8__FUNC_ANT_SEL0 (MTK_PIN_NO(30) | 5)
++#define MT8127_PIN_30_EINT8__FUNC_DPI_D7 (MTK_PIN_NO(30) | 6)
++#define MT8127_PIN_30_EINT8__FUNC_DBG_MON_B_2 (MTK_PIN_NO(30) | 7)
++
++#define MT8127_PIN_31_EINT9__FUNC_GPIO31 (MTK_PIN_NO(31) | 0)
++#define MT8127_PIN_31_EINT9__FUNC_CLKM4 (MTK_PIN_NO(31) | 1)
++#define MT8127_PIN_31_EINT9__FUNC_SDA2 (MTK_PIN_NO(31) | 2)
++#define MT8127_PIN_31_EINT9__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(31) | 3)
++#define MT8127_PIN_31_EINT9__FUNC_EXT_RXD1 (MTK_PIN_NO(31) | 4)
++#define MT8127_PIN_31_EINT9__FUNC_ANT_SEL1 (MTK_PIN_NO(31) | 5)
++#define MT8127_PIN_31_EINT9__FUNC_DPI_D8 (MTK_PIN_NO(31) | 6)
++#define MT8127_PIN_31_EINT9__FUNC_DBG_MON_B_3 (MTK_PIN_NO(31) | 7)
++
++#define MT8127_PIN_32_EINT10__FUNC_GPIO32 (MTK_PIN_NO(32) | 0)
++#define MT8127_PIN_32_EINT10__FUNC_CLKM5 (MTK_PIN_NO(32) | 1)
++#define MT8127_PIN_32_EINT10__FUNC_SCL2 (MTK_PIN_NO(32) | 2)
++#define MT8127_PIN_32_EINT10__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(32) | 3)
++#define MT8127_PIN_32_EINT10__FUNC_EXT_RXD2 (MTK_PIN_NO(32) | 4)
++#define MT8127_PIN_32_EINT10__FUNC_ANT_SEL2 (MTK_PIN_NO(32) | 5)
++#define MT8127_PIN_32_EINT10__FUNC_DPI_D9 (MTK_PIN_NO(32) | 6)
++#define MT8127_PIN_32_EINT10__FUNC_DBG_MON_B_4 (MTK_PIN_NO(32) | 7)
++
++#define MT8127_PIN_33_KPROW0__FUNC_GPIO33 (MTK_PIN_NO(33) | 0)
++#define MT8127_PIN_33_KPROW0__FUNC_KROW0 (MTK_PIN_NO(33) | 1)
++#define MT8127_PIN_33_KPROW0__FUNC_IMG_TEST_CK (MTK_PIN_NO(33) | 4)
++#define MT8127_PIN_33_KPROW0__FUNC_DBG_MON_A_12 (MTK_PIN_NO(33) | 7)
++
++#define MT8127_PIN_34_KPROW1__FUNC_GPIO34 (MTK_PIN_NO(34) | 0)
++#define MT8127_PIN_34_KPROW1__FUNC_KROW1 (MTK_PIN_NO(34) | 1)
++#define MT8127_PIN_34_KPROW1__FUNC_IDDIG (MTK_PIN_NO(34) | 2)
++#define MT8127_PIN_34_KPROW1__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(34) | 3)
++#define MT8127_PIN_34_KPROW1__FUNC_MFG_TEST_CK (MTK_PIN_NO(34) | 4)
++#define MT8127_PIN_34_KPROW1__FUNC_DBG_MON_B_5 (MTK_PIN_NO(34) | 7)
++
++#define MT8127_PIN_35_KPROW2__FUNC_GPIO35 (MTK_PIN_NO(35) | 0)
++#define MT8127_PIN_35_KPROW2__FUNC_KROW2 (MTK_PIN_NO(35) | 1)
++#define MT8127_PIN_35_KPROW2__FUNC_DRV_VBUS (MTK_PIN_NO(35) | 2)
++#define MT8127_PIN_35_KPROW2__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(35) | 3)
++#define MT8127_PIN_35_KPROW2__FUNC_CONN_TEST_CK (MTK_PIN_NO(35) | 4)
++#define MT8127_PIN_35_KPROW2__FUNC_DBG_MON_B_6 (MTK_PIN_NO(35) | 7)
++
++#define MT8127_PIN_36_KPCOL0__FUNC_GPIO36 (MTK_PIN_NO(36) | 0)
++#define MT8127_PIN_36_KPCOL0__FUNC_KCOL0 (MTK_PIN_NO(36) | 1)
++#define MT8127_PIN_36_KPCOL0__FUNC_DBG_MON_A_13 (MTK_PIN_NO(36) | 7)
++
++#define MT8127_PIN_37_KPCOL1__FUNC_GPIO37 (MTK_PIN_NO(37) | 0)
++#define MT8127_PIN_37_KPCOL1__FUNC_KCOL1 (MTK_PIN_NO(37) | 1)
++#define MT8127_PIN_37_KPCOL1__FUNC_DBG_MON_B_7 (MTK_PIN_NO(37) | 7)
++
++#define MT8127_PIN_38_KPCOL2__FUNC_GPIO38 (MTK_PIN_NO(38) | 0)
++#define MT8127_PIN_38_KPCOL2__FUNC_KCOL2 (MTK_PIN_NO(38) | 1)
++#define MT8127_PIN_38_KPCOL2__FUNC_IDDIG (MTK_PIN_NO(38) | 2)
++#define MT8127_PIN_38_KPCOL2__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(38) | 3)
++#define MT8127_PIN_38_KPCOL2__FUNC_DBG_MON_B_8 (MTK_PIN_NO(38) | 7)
++
++#define MT8127_PIN_39_JTMS__FUNC_GPIO39 (MTK_PIN_NO(39) | 0)
++#define MT8127_PIN_39_JTMS__FUNC_JTMS (MTK_PIN_NO(39) | 1)
++#define MT8127_PIN_39_JTMS__FUNC_CONN_MCU_TMS (MTK_PIN_NO(39) | 2)
++#define MT8127_PIN_39_JTMS__FUNC_CONN_MCU_AICE_JMSC (MTK_PIN_NO(39) | 3)
++
++#define MT8127_PIN_40_JTCK__FUNC_GPIO40 (MTK_PIN_NO(40) | 0)
++#define MT8127_PIN_40_JTCK__FUNC_JTCK (MTK_PIN_NO(40) | 1)
++#define MT8127_PIN_40_JTCK__FUNC_CONN_MCU_TCK1 (MTK_PIN_NO(40) | 2)
++#define MT8127_PIN_40_JTCK__FUNC_CONN_MCU_AICE_JCKC (MTK_PIN_NO(40) | 3)
++
++#define MT8127_PIN_41_JTDI__FUNC_GPIO41 (MTK_PIN_NO(41) | 0)
++#define MT8127_PIN_41_JTDI__FUNC_JTDI (MTK_PIN_NO(41) | 1)
++#define MT8127_PIN_41_JTDI__FUNC_CONN_MCU_TDI (MTK_PIN_NO(41) | 2)
++
++#define MT8127_PIN_42_JTDO__FUNC_GPIO42 (MTK_PIN_NO(42) | 0)
++#define MT8127_PIN_42_JTDO__FUNC_JTDO (MTK_PIN_NO(42) | 1)
++#define MT8127_PIN_42_JTDO__FUNC_CONN_MCU_TDO (MTK_PIN_NO(42) | 2)
++
++#define MT8127_PIN_43_EINT11__FUNC_GPIO43 (MTK_PIN_NO(43) | 0)
++#define MT8127_PIN_43_EINT11__FUNC_CLKM4 (MTK_PIN_NO(43) | 1)
++#define MT8127_PIN_43_EINT11__FUNC_PWM2 (MTK_PIN_NO(43) | 2)
++#define MT8127_PIN_43_EINT11__FUNC_KROW3 (MTK_PIN_NO(43) | 3)
++#define MT8127_PIN_43_EINT11__FUNC_ANT_SEL3 (MTK_PIN_NO(43) | 4)
++#define MT8127_PIN_43_EINT11__FUNC_DPI_D10 (MTK_PIN_NO(43) | 5)
++#define MT8127_PIN_43_EINT11__FUNC_EXT_RXD3 (MTK_PIN_NO(43) | 6)
++#define MT8127_PIN_43_EINT11__FUNC_DBG_MON_B_9 (MTK_PIN_NO(43) | 7)
++
++#define MT8127_PIN_44_EINT12__FUNC_GPIO44 (MTK_PIN_NO(44) | 0)
++#define MT8127_PIN_44_EINT12__FUNC_CLKM5 (MTK_PIN_NO(44) | 1)
++#define MT8127_PIN_44_EINT12__FUNC_PWM0 (MTK_PIN_NO(44) | 2)
++#define MT8127_PIN_44_EINT12__FUNC_KCOL3 (MTK_PIN_NO(44) | 3)
++#define MT8127_PIN_44_EINT12__FUNC_ANT_SEL4 (MTK_PIN_NO(44) | 4)
++#define MT8127_PIN_44_EINT12__FUNC_DPI_D11 (MTK_PIN_NO(44) | 5)
++#define MT8127_PIN_44_EINT12__FUNC_EXT_TXEN (MTK_PIN_NO(44) | 6)
++#define MT8127_PIN_44_EINT12__FUNC_DBG_MON_B_10 (MTK_PIN_NO(44) | 7)
++
++#define MT8127_PIN_45_EINT13__FUNC_GPIO45 (MTK_PIN_NO(45) | 0)
++#define MT8127_PIN_45_EINT13__FUNC_ANT_SEL5 (MTK_PIN_NO(45) | 4)
++#define MT8127_PIN_45_EINT13__FUNC_DPI_D0 (MTK_PIN_NO(45) | 5)
++#define MT8127_PIN_45_EINT13__FUNC_SPDIF (MTK_PIN_NO(45) | 6)
++#define MT8127_PIN_45_EINT13__FUNC_DBG_MON_B_11 (MTK_PIN_NO(45) | 7)
++
++#define MT8127_PIN_46_EINT14__FUNC_GPIO46 (MTK_PIN_NO(46) | 0)
++#define MT8127_PIN_46_EINT14__FUNC_DAC_DAT_OUT (MTK_PIN_NO(46) | 2)
++#define MT8127_PIN_46_EINT14__FUNC_ANT_SEL1 (MTK_PIN_NO(46) | 4)
++#define MT8127_PIN_46_EINT14__FUNC_CONN_MCU_DBGACK_N (MTK_PIN_NO(46) | 5)
++#define MT8127_PIN_46_EINT14__FUNC_NCLE (MTK_PIN_NO(46) | 6)
++#define MT8127_PIN_46_EINT14__FUNC_DBG_MON_A_14 (MTK_PIN_NO(46) | 7)
++
++#define MT8127_PIN_47_EINT15__FUNC_GPIO47 (MTK_PIN_NO(47) | 0)
++#define MT8127_PIN_47_EINT15__FUNC_DAC_WS (MTK_PIN_NO(47) | 2)
++#define MT8127_PIN_47_EINT15__FUNC_ANT_SEL2 (MTK_PIN_NO(47) | 4)
++#define MT8127_PIN_47_EINT15__FUNC_CONN_MCU_DBGI_N (MTK_PIN_NO(47) | 5)
++#define MT8127_PIN_47_EINT15__FUNC_NCEB1 (MTK_PIN_NO(47) | 6)
++#define MT8127_PIN_47_EINT15__FUNC_DBG_MON_A_15 (MTK_PIN_NO(47) | 7)
++
++#define MT8127_PIN_48_EINT16__FUNC_GPIO48 (MTK_PIN_NO(48) | 0)
++#define MT8127_PIN_48_EINT16__FUNC_DAC_CK (MTK_PIN_NO(48) | 2)
++#define MT8127_PIN_48_EINT16__FUNC_ANT_SEL3 (MTK_PIN_NO(48) | 4)
++#define MT8127_PIN_48_EINT16__FUNC_CONN_MCU_TRST_B (MTK_PIN_NO(48) | 5)
++#define MT8127_PIN_48_EINT16__FUNC_NCEB0 (MTK_PIN_NO(48) | 6)
++#define MT8127_PIN_48_EINT16__FUNC_DBG_MON_A_16 (MTK_PIN_NO(48) | 7)
++
++#define MT8127_PIN_49_EINT17__FUNC_GPIO49 (MTK_PIN_NO(49) | 0)
++#define MT8127_PIN_49_EINT17__FUNC_UCTS0 (MTK_PIN_NO(49) | 1)
++#define MT8127_PIN_49_EINT17__FUNC_CLKM0 (MTK_PIN_NO(49) | 3)
++#define MT8127_PIN_49_EINT17__FUNC_IDDIG (MTK_PIN_NO(49) | 4)
++#define MT8127_PIN_49_EINT17__FUNC_ANT_SEL4 (MTK_PIN_NO(49) | 5)
++#define MT8127_PIN_49_EINT17__FUNC_NREB (MTK_PIN_NO(49) | 6)
++#define MT8127_PIN_49_EINT17__FUNC_DBG_MON_A_17 (MTK_PIN_NO(49) | 7)
++
++#define MT8127_PIN_50_EINT18__FUNC_GPIO50 (MTK_PIN_NO(50) | 0)
++#define MT8127_PIN_50_EINT18__FUNC_URTS0 (MTK_PIN_NO(50) | 1)
++#define MT8127_PIN_50_EINT18__FUNC_CLKM3 (MTK_PIN_NO(50) | 2)
++#define MT8127_PIN_50_EINT18__FUNC_I2SOUT_LRCK (MTK_PIN_NO(50) | 3)
++#define MT8127_PIN_50_EINT18__FUNC_DRV_VBUS (MTK_PIN_NO(50) | 4)
++#define MT8127_PIN_50_EINT18__FUNC_ANT_SEL3 (MTK_PIN_NO(50) | 5)
++#define MT8127_PIN_50_EINT18__FUNC_ADC_CK (MTK_PIN_NO(50) | 6)
++#define MT8127_PIN_50_EINT18__FUNC_DBG_MON_B_12 (MTK_PIN_NO(50) | 7)
++
++#define MT8127_PIN_51_EINT19__FUNC_GPIO51 (MTK_PIN_NO(51) | 0)
++#define MT8127_PIN_51_EINT19__FUNC_UCTS1 (MTK_PIN_NO(51) | 1)
++#define MT8127_PIN_51_EINT19__FUNC_I2SOUT_BCK (MTK_PIN_NO(51) | 3)
++#define MT8127_PIN_51_EINT19__FUNC_CLKM1 (MTK_PIN_NO(51) | 4)
++#define MT8127_PIN_51_EINT19__FUNC_ANT_SEL4 (MTK_PIN_NO(51) | 5)
++#define MT8127_PIN_51_EINT19__FUNC_ADC_DAT_IN (MTK_PIN_NO(51) | 6)
++#define MT8127_PIN_51_EINT19__FUNC_DBG_MON_B_13 (MTK_PIN_NO(51) | 7)
++
++#define MT8127_PIN_52_EINT20__FUNC_GPIO52 (MTK_PIN_NO(52) | 0)
++#define MT8127_PIN_52_EINT20__FUNC_URTS1 (MTK_PIN_NO(52) | 1)
++#define MT8127_PIN_52_EINT20__FUNC_PCM_TX (MTK_PIN_NO(52) | 2)
++#define MT8127_PIN_52_EINT20__FUNC_I2SOUT_DATA_OUT (MTK_PIN_NO(52) | 3)
++#define MT8127_PIN_52_EINT20__FUNC_CLKM2 (MTK_PIN_NO(52) | 4)
++#define MT8127_PIN_52_EINT20__FUNC_ANT_SEL5 (MTK_PIN_NO(52) | 5)
++#define MT8127_PIN_52_EINT20__FUNC_ADC_WS (MTK_PIN_NO(52) | 6)
++#define MT8127_PIN_52_EINT20__FUNC_DBG_MON_B_14 (MTK_PIN_NO(52) | 7)
++
++#define MT8127_PIN_53_SPI_CS__FUNC_GPIO53 (MTK_PIN_NO(53) | 0)
++#define MT8127_PIN_53_SPI_CS__FUNC_SPI_CS (MTK_PIN_NO(53) | 1)
++#define MT8127_PIN_53_SPI_CS__FUNC_I2SIN1_DATA_IN (MTK_PIN_NO(53) | 3)
++#define MT8127_PIN_53_SPI_CS__FUNC_ADC_CK (MTK_PIN_NO(53) | 4)
++#define MT8127_PIN_53_SPI_CS__FUNC_DBG_MON_B_15 (MTK_PIN_NO(53) | 7)
++
++#define MT8127_PIN_54_SPI_CK__FUNC_GPIO54 (MTK_PIN_NO(54) | 0)
++#define MT8127_PIN_54_SPI_CK__FUNC_SPI_CK (MTK_PIN_NO(54) | 1)
++#define MT8127_PIN_54_SPI_CK__FUNC_I2SIN1_LRCK (MTK_PIN_NO(54) | 3)
++#define MT8127_PIN_54_SPI_CK__FUNC_ADC_DAT_IN (MTK_PIN_NO(54) | 4)
++#define MT8127_PIN_54_SPI_CK__FUNC_DBG_MON_B_16 (MTK_PIN_NO(54) | 7)
++
++#define MT8127_PIN_55_SPI_MI__FUNC_GPIO55 (MTK_PIN_NO(55) | 0)
++#define MT8127_PIN_55_SPI_MI__FUNC_SPI_MI (MTK_PIN_NO(55) | 1)
++#define MT8127_PIN_55_SPI_MI__FUNC_SPI_MO (MTK_PIN_NO(55) | 2)
++#define MT8127_PIN_55_SPI_MI__FUNC_I2SIN1_BCK1 (MTK_PIN_NO(55) | 3)
++#define MT8127_PIN_55_SPI_MI__FUNC_ADC_WS (MTK_PIN_NO(55) | 4)
++#define MT8127_PIN_55_SPI_MI__FUNC_DBG_MON_B_17 (MTK_PIN_NO(55) | 7)
++
++#define MT8127_PIN_56_SPI_MO__FUNC_GPIO56 (MTK_PIN_NO(56) | 0)
++#define MT8127_PIN_56_SPI_MO__FUNC_SPI_MO (MTK_PIN_NO(56) | 1)
++#define MT8127_PIN_56_SPI_MO__FUNC_SPI_MI (MTK_PIN_NO(56) | 2)
++#define MT8127_PIN_56_SPI_MO__FUNC_DBG_MON_B_18 (MTK_PIN_NO(56) | 7)
++
++#define MT8127_PIN_57_SDA1__FUNC_GPIO57 (MTK_PIN_NO(57) | 0)
++#define MT8127_PIN_57_SDA1__FUNC_SDA1 (MTK_PIN_NO(57) | 1)
++
++#define MT8127_PIN_58_SCL1__FUNC_GPIO58 (MTK_PIN_NO(58) | 0)
++#define MT8127_PIN_58_SCL1__FUNC_SCL1 (MTK_PIN_NO(58) | 1)
++
++#define MT8127_PIN_59_DISP_PWM__FUNC_GPIO59 (MTK_PIN_NO(59) | 0)
++#define MT8127_PIN_59_DISP_PWM__FUNC_DISP_PWM (MTK_PIN_NO(59) | 1)
++#define MT8127_PIN_59_DISP_PWM__FUNC_PWM1 (MTK_PIN_NO(59) | 2)
++#define MT8127_PIN_59_DISP_PWM__FUNC_DBG_MON_A_18 (MTK_PIN_NO(59) | 7)
++
++#define MT8127_PIN_60_WB_RSTB__FUNC_GPIO60 (MTK_PIN_NO(60) | 0)
++#define MT8127_PIN_60_WB_RSTB__FUNC_WB_RSTB (MTK_PIN_NO(60) | 1)
++#define MT8127_PIN_60_WB_RSTB__FUNC_DBG_MON_A_19 (MTK_PIN_NO(60) | 7)
++
++#define MT8127_PIN_61_F2W_DATA__FUNC_GPIO61 (MTK_PIN_NO(61) | 0)
++#define MT8127_PIN_61_F2W_DATA__FUNC_F2W_DATA (MTK_PIN_NO(61) | 1)
++#define MT8127_PIN_61_F2W_DATA__FUNC_DBG_MON_A_20 (MTK_PIN_NO(61) | 7)
++
++#define MT8127_PIN_62_F2W_CLK__FUNC_GPIO62 (MTK_PIN_NO(62) | 0)
++#define MT8127_PIN_62_F2W_CLK__FUNC_F2W_CK (MTK_PIN_NO(62) | 1)
++#define MT8127_PIN_62_F2W_CLK__FUNC_DBG_MON_A_21 (MTK_PIN_NO(62) | 7)
++
++#define MT8127_PIN_63_WB_SCLK__FUNC_GPIO63 (MTK_PIN_NO(63) | 0)
++#define MT8127_PIN_63_WB_SCLK__FUNC_WB_SCLK (MTK_PIN_NO(63) | 1)
++#define MT8127_PIN_63_WB_SCLK__FUNC_DBG_MON_A_22 (MTK_PIN_NO(63) | 7)
++
++#define MT8127_PIN_64_WB_SDATA__FUNC_GPIO64 (MTK_PIN_NO(64) | 0)
++#define MT8127_PIN_64_WB_SDATA__FUNC_WB_SDATA (MTK_PIN_NO(64) | 1)
++#define MT8127_PIN_64_WB_SDATA__FUNC_DBG_MON_A_23 (MTK_PIN_NO(64) | 7)
++
++#define MT8127_PIN_65_WB_SEN__FUNC_GPIO65 (MTK_PIN_NO(65) | 0)
++#define MT8127_PIN_65_WB_SEN__FUNC_WB_SEN (MTK_PIN_NO(65) | 1)
++#define MT8127_PIN_65_WB_SEN__FUNC_DBG_MON_A_24 (MTK_PIN_NO(65) | 7)
++
++#define MT8127_PIN_66_WB_CRTL0__FUNC_GPIO66 (MTK_PIN_NO(66) | 0)
++#define MT8127_PIN_66_WB_CRTL0__FUNC_WB_CRTL0 (MTK_PIN_NO(66) | 1)
++#define MT8127_PIN_66_WB_CRTL0__FUNC_DFD_NTRST_XI (MTK_PIN_NO(66) | 2)
++#define MT8127_PIN_66_WB_CRTL0__FUNC_DBG_MON_A_25 (MTK_PIN_NO(66) | 7)
++
++#define MT8127_PIN_67_WB_CRTL1__FUNC_GPIO67 (MTK_PIN_NO(67) | 0)
++#define MT8127_PIN_67_WB_CRTL1__FUNC_WB_CRTL1 (MTK_PIN_NO(67) | 1)
++#define MT8127_PIN_67_WB_CRTL1__FUNC_DFD_TMS_XI (MTK_PIN_NO(67) | 2)
++#define MT8127_PIN_67_WB_CRTL1__FUNC_DBG_MON_A_26 (MTK_PIN_NO(67) | 7)
++
++#define MT8127_PIN_68_WB_CRTL2__FUNC_GPIO68 (MTK_PIN_NO(68) | 0)
++#define MT8127_PIN_68_WB_CRTL2__FUNC_WB_CRTL2 (MTK_PIN_NO(68) | 1)
++#define MT8127_PIN_68_WB_CRTL2__FUNC_DFD_TCK_XI (MTK_PIN_NO(68) | 2)
++#define MT8127_PIN_68_WB_CRTL2__FUNC_DBG_MON_A_27 (MTK_PIN_NO(68) | 7)
++
++#define MT8127_PIN_69_WB_CRTL3__FUNC_GPIO69 (MTK_PIN_NO(69) | 0)
++#define MT8127_PIN_69_WB_CRTL3__FUNC_WB_CRTL3 (MTK_PIN_NO(69) | 1)
++#define MT8127_PIN_69_WB_CRTL3__FUNC_DFD_TDI_XI (MTK_PIN_NO(69) | 2)
++#define MT8127_PIN_69_WB_CRTL3__FUNC_DBG_MON_A_28 (MTK_PIN_NO(69) | 7)
++
++#define MT8127_PIN_70_WB_CRTL4__FUNC_GPIO70 (MTK_PIN_NO(70) | 0)
++#define MT8127_PIN_70_WB_CRTL4__FUNC_WB_CRTL4 (MTK_PIN_NO(70) | 1)
++#define MT8127_PIN_70_WB_CRTL4__FUNC_DFD_TDO (MTK_PIN_NO(70) | 2)
++#define MT8127_PIN_70_WB_CRTL4__FUNC_DBG_MON_A_29 (MTK_PIN_NO(70) | 7)
++
++#define MT8127_PIN_71_WB_CRTL5__FUNC_GPIO71 (MTK_PIN_NO(71) | 0)
++#define MT8127_PIN_71_WB_CRTL5__FUNC_WB_CRTL5 (MTK_PIN_NO(71) | 1)
++#define MT8127_PIN_71_WB_CRTL5__FUNC_DBG_MON_A_30 (MTK_PIN_NO(71) | 7)
++
++#define MT8127_PIN_72_I2S_DATA_IN__FUNC_GPIO72 (MTK_PIN_NO(72) | 0)
++#define MT8127_PIN_72_I2S_DATA_IN__FUNC_I2SIN1_DATA_IN (MTK_PIN_NO(72) | 1)
++#define MT8127_PIN_72_I2S_DATA_IN__FUNC_PCM_RX (MTK_PIN_NO(72) | 2)
++#define MT8127_PIN_72_I2S_DATA_IN__FUNC_I2SOUT_DATA_OUT (MTK_PIN_NO(72) | 3)
++#define MT8127_PIN_72_I2S_DATA_IN__FUNC_DAC_DAT_OUT (MTK_PIN_NO(72) | 4)
++#define MT8127_PIN_72_I2S_DATA_IN__FUNC_PWM0 (MTK_PIN_NO(72) | 5)
++#define MT8127_PIN_72_I2S_DATA_IN__FUNC_ADC_CK (MTK_PIN_NO(72) | 6)
++#define MT8127_PIN_72_I2S_DATA_IN__FUNC_DBG_MON_B_19 (MTK_PIN_NO(72) | 7)
++
++#define MT8127_PIN_73_I2S_LRCK__FUNC_GPIO73 (MTK_PIN_NO(73) | 0)
++#define MT8127_PIN_73_I2S_LRCK__FUNC_I2SIN1_LRCK (MTK_PIN_NO(73) | 1)
++#define MT8127_PIN_73_I2S_LRCK__FUNC_PCM_SYNC (MTK_PIN_NO(73) | 2)
++#define MT8127_PIN_73_I2S_LRCK__FUNC_I2SOUT_LRCK (MTK_PIN_NO(73) | 3)
++#define MT8127_PIN_73_I2S_LRCK__FUNC_DAC_WS (MTK_PIN_NO(73) | 4)
++#define MT8127_PIN_73_I2S_LRCK__FUNC_PWM3 (MTK_PIN_NO(73) | 5)
++#define MT8127_PIN_73_I2S_LRCK__FUNC_ADC_DAT_IN (MTK_PIN_NO(73) | 6)
++#define MT8127_PIN_73_I2S_LRCK__FUNC_DBG_MON_B_20 (MTK_PIN_NO(73) | 7)
++
++#define MT8127_PIN_74_I2S_BCK__FUNC_GPIO74 (MTK_PIN_NO(74) | 0)
++#define MT8127_PIN_74_I2S_BCK__FUNC_I2SIN1_BCK2 (MTK_PIN_NO(74) | 1)
++#define MT8127_PIN_74_I2S_BCK__FUNC_PCM_CLK1 (MTK_PIN_NO(74) | 2)
++#define MT8127_PIN_74_I2S_BCK__FUNC_I2SOUT_BCK (MTK_PIN_NO(74) | 3)
++#define MT8127_PIN_74_I2S_BCK__FUNC_DAC_CK (MTK_PIN_NO(74) | 4)
++#define MT8127_PIN_74_I2S_BCK__FUNC_PWM4 (MTK_PIN_NO(74) | 5)
++#define MT8127_PIN_74_I2S_BCK__FUNC_ADC_WS (MTK_PIN_NO(74) | 6)
++#define MT8127_PIN_74_I2S_BCK__FUNC_DBG_MON_B_21 (MTK_PIN_NO(74) | 7)
++
++#define MT8127_PIN_75_SDA0__FUNC_GPIO75 (MTK_PIN_NO(75) | 0)
++#define MT8127_PIN_75_SDA0__FUNC_SDA0 (MTK_PIN_NO(75) | 1)
++
++#define MT8127_PIN_76_SCL0__FUNC_GPIO76 (MTK_PIN_NO(76) | 0)
++#define MT8127_PIN_76_SCL0__FUNC_SCL0 (MTK_PIN_NO(76) | 1)
++
++#define MT8127_PIN_77_SDA2__FUNC_GPIO77 (MTK_PIN_NO(77) | 0)
++#define MT8127_PIN_77_SDA2__FUNC_SDA2 (MTK_PIN_NO(77) | 1)
++#define MT8127_PIN_77_SDA2__FUNC_PWM1 (MTK_PIN_NO(77) | 2)
++
++#define MT8127_PIN_78_SCL2__FUNC_GPIO78 (MTK_PIN_NO(78) | 0)
++#define MT8127_PIN_78_SCL2__FUNC_SCL2 (MTK_PIN_NO(78) | 1)
++#define MT8127_PIN_78_SCL2__FUNC_PWM2 (MTK_PIN_NO(78) | 2)
++
++#define MT8127_PIN_79_URXD0__FUNC_GPIO79 (MTK_PIN_NO(79) | 0)
++#define MT8127_PIN_79_URXD0__FUNC_URXD0 (MTK_PIN_NO(79) | 1)
++#define MT8127_PIN_79_URXD0__FUNC_UTXD0 (MTK_PIN_NO(79) | 2)
++
++#define MT8127_PIN_80_UTXD0__FUNC_GPIO80 (MTK_PIN_NO(80) | 0)
++#define MT8127_PIN_80_UTXD0__FUNC_UTXD0 (MTK_PIN_NO(80) | 1)
++#define MT8127_PIN_80_UTXD0__FUNC_URXD0 (MTK_PIN_NO(80) | 2)
++
++#define MT8127_PIN_81_URXD1__FUNC_GPIO81 (MTK_PIN_NO(81) | 0)
++#define MT8127_PIN_81_URXD1__FUNC_URXD1 (MTK_PIN_NO(81) | 1)
++#define MT8127_PIN_81_URXD1__FUNC_UTXD1 (MTK_PIN_NO(81) | 2)
++
++#define MT8127_PIN_82_UTXD1__FUNC_GPIO82 (MTK_PIN_NO(82) | 0)
++#define MT8127_PIN_82_UTXD1__FUNC_UTXD1 (MTK_PIN_NO(82) | 1)
++#define MT8127_PIN_82_UTXD1__FUNC_URXD1 (MTK_PIN_NO(82) | 2)
++
++#define MT8127_PIN_83_LCM_RST__FUNC_GPIO83 (MTK_PIN_NO(83) | 0)
++#define MT8127_PIN_83_LCM_RST__FUNC_LCM_RST (MTK_PIN_NO(83) | 1)
++#define MT8127_PIN_83_LCM_RST__FUNC_VDAC_CK_XI (MTK_PIN_NO(83) | 2)
++#define MT8127_PIN_83_LCM_RST__FUNC_DBG_MON_A_31 (MTK_PIN_NO(83) | 7)
++
++#define MT8127_PIN_84_DSI_TE__FUNC_GPIO84 (MTK_PIN_NO(84) | 0)
++#define MT8127_PIN_84_DSI_TE__FUNC_DSI_TE (MTK_PIN_NO(84) | 1)
++#define MT8127_PIN_84_DSI_TE__FUNC_DBG_MON_A_32 (MTK_PIN_NO(84) | 7)
++
++#define MT8127_PIN_85_MSDC2_CMD__FUNC_GPIO85 (MTK_PIN_NO(85) | 0)
++#define MT8127_PIN_85_MSDC2_CMD__FUNC_MSDC2_CMD (MTK_PIN_NO(85) | 1)
++#define MT8127_PIN_85_MSDC2_CMD__FUNC_ANT_SEL0 (MTK_PIN_NO(85) | 2)
++#define MT8127_PIN_85_MSDC2_CMD__FUNC_SDA1 (MTK_PIN_NO(85) | 3)
++#define MT8127_PIN_85_MSDC2_CMD__FUNC_I2SOUT_BCK (MTK_PIN_NO(85) | 6)
++#define MT8127_PIN_85_MSDC2_CMD__FUNC_DBG_MON_B_22 (MTK_PIN_NO(85) | 7)
++
++#define MT8127_PIN_86_MSDC2_CLK__FUNC_GPIO86 (MTK_PIN_NO(86) | 0)
++#define MT8127_PIN_86_MSDC2_CLK__FUNC_MSDC2_CLK (MTK_PIN_NO(86) | 1)
++#define MT8127_PIN_86_MSDC2_CLK__FUNC_ANT_SEL1 (MTK_PIN_NO(86) | 2)
++#define MT8127_PIN_86_MSDC2_CLK__FUNC_SCL1 (MTK_PIN_NO(86) | 3)
++#define MT8127_PIN_86_MSDC2_CLK__FUNC_I2SOUT_LRCK (MTK_PIN_NO(86) | 6)
++#define MT8127_PIN_86_MSDC2_CLK__FUNC_DBG_MON_B_23 (MTK_PIN_NO(86) | 7)
++
++#define MT8127_PIN_87_MSDC2_DAT0__FUNC_GPIO87 (MTK_PIN_NO(87) | 0)
++#define MT8127_PIN_87_MSDC2_DAT0__FUNC_MSDC2_DAT0 (MTK_PIN_NO(87) | 1)
++#define MT8127_PIN_87_MSDC2_DAT0__FUNC_ANT_SEL2 (MTK_PIN_NO(87) | 2)
++#define MT8127_PIN_87_MSDC2_DAT0__FUNC_UTXD0 (MTK_PIN_NO(87) | 5)
++#define MT8127_PIN_87_MSDC2_DAT0__FUNC_I2SOUT_DATA_OUT (MTK_PIN_NO(87) | 6)
++#define MT8127_PIN_87_MSDC2_DAT0__FUNC_DBG_MON_B_24 (MTK_PIN_NO(87) | 7)
++
++#define MT8127_PIN_88_MSDC2_DAT1__FUNC_GPIO88 (MTK_PIN_NO(88) | 0)
++#define MT8127_PIN_88_MSDC2_DAT1__FUNC_MSDC2_DAT1 (MTK_PIN_NO(88) | 1)
++#define MT8127_PIN_88_MSDC2_DAT1__FUNC_ANT_SEL3 (MTK_PIN_NO(88) | 2)
++#define MT8127_PIN_88_MSDC2_DAT1__FUNC_PWM0 (MTK_PIN_NO(88) | 3)
++#define MT8127_PIN_88_MSDC2_DAT1__FUNC_URXD0 (MTK_PIN_NO(88) | 5)
++#define MT8127_PIN_88_MSDC2_DAT1__FUNC_PWM1 (MTK_PIN_NO(88) | 6)
++#define MT8127_PIN_88_MSDC2_DAT1__FUNC_DBG_MON_B_25 (MTK_PIN_NO(88) | 7)
++
++#define MT8127_PIN_89_MSDC2_DAT2__FUNC_GPIO89 (MTK_PIN_NO(89) | 0)
++#define MT8127_PIN_89_MSDC2_DAT2__FUNC_MSDC2_DAT2 (MTK_PIN_NO(89) | 1)
++#define MT8127_PIN_89_MSDC2_DAT2__FUNC_ANT_SEL4 (MTK_PIN_NO(89) | 2)
++#define MT8127_PIN_89_MSDC2_DAT2__FUNC_SDA2 (MTK_PIN_NO(89) | 3)
++#define MT8127_PIN_89_MSDC2_DAT2__FUNC_UTXD1 (MTK_PIN_NO(89) | 5)
++#define MT8127_PIN_89_MSDC2_DAT2__FUNC_PWM2 (MTK_PIN_NO(89) | 6)
++#define MT8127_PIN_89_MSDC2_DAT2__FUNC_DBG_MON_B_26 (MTK_PIN_NO(89) | 7)
++
++#define MT8127_PIN_90_MSDC2_DAT3__FUNC_GPIO90 (MTK_PIN_NO(90) | 0)
++#define MT8127_PIN_90_MSDC2_DAT3__FUNC_MSDC2_DAT3 (MTK_PIN_NO(90) | 1)
++#define MT8127_PIN_90_MSDC2_DAT3__FUNC_ANT_SEL5 (MTK_PIN_NO(90) | 2)
++#define MT8127_PIN_90_MSDC2_DAT3__FUNC_SCL2 (MTK_PIN_NO(90) | 3)
++#define MT8127_PIN_90_MSDC2_DAT3__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(90) | 4)
++#define MT8127_PIN_90_MSDC2_DAT3__FUNC_URXD1 (MTK_PIN_NO(90) | 5)
++#define MT8127_PIN_90_MSDC2_DAT3__FUNC_PWM3 (MTK_PIN_NO(90) | 6)
++#define MT8127_PIN_90_MSDC2_DAT3__FUNC_DBG_MON_B_27 (MTK_PIN_NO(90) | 7)
++
++#define MT8127_PIN_91_TDN3__FUNC_GPI91 (MTK_PIN_NO(91) | 0)
++#define MT8127_PIN_91_TDN3__FUNC_TDN3 (MTK_PIN_NO(91) | 1)
++
++#define MT8127_PIN_92_TDP3__FUNC_GPI92 (MTK_PIN_NO(92) | 0)
++#define MT8127_PIN_92_TDP3__FUNC_TDP3 (MTK_PIN_NO(92) | 1)
++
++#define MT8127_PIN_93_TDN2__FUNC_GPI93 (MTK_PIN_NO(93) | 0)
++#define MT8127_PIN_93_TDN2__FUNC_TDN2 (MTK_PIN_NO(93) | 1)
++
++#define MT8127_PIN_94_TDP2__FUNC_GPI94 (MTK_PIN_NO(94) | 0)
++#define MT8127_PIN_94_TDP2__FUNC_TDP2 (MTK_PIN_NO(94) | 1)
++
++#define MT8127_PIN_95_TCN__FUNC_GPI95 (MTK_PIN_NO(95) | 0)
++#define MT8127_PIN_95_TCN__FUNC_TCN (MTK_PIN_NO(95) | 1)
++
++#define MT8127_PIN_96_TCP__FUNC_GPI96 (MTK_PIN_NO(96) | 0)
++#define MT8127_PIN_96_TCP__FUNC_TCP (MTK_PIN_NO(96) | 1)
++
++#define MT8127_PIN_97_TDN1__FUNC_GPI97 (MTK_PIN_NO(97) | 0)
++#define MT8127_PIN_97_TDN1__FUNC_TDN1 (MTK_PIN_NO(97) | 1)
++
++#define MT8127_PIN_98_TDP1__FUNC_GPI98 (MTK_PIN_NO(98) | 0)
++#define MT8127_PIN_98_TDP1__FUNC_TDP1 (MTK_PIN_NO(98) | 1)
++
++#define MT8127_PIN_99_TDN0__FUNC_GPI99 (MTK_PIN_NO(99) | 0)
++#define MT8127_PIN_99_TDN0__FUNC_TDN0 (MTK_PIN_NO(99) | 1)
++
++#define MT8127_PIN_100_TDP0__FUNC_GPI100 (MTK_PIN_NO(100) | 0)
++#define MT8127_PIN_100_TDP0__FUNC_TDP0 (MTK_PIN_NO(100) | 1)
++
++#define MT8127_PIN_101_RDN0__FUNC_GPI101 (MTK_PIN_NO(101) | 0)
++#define MT8127_PIN_101_RDN0__FUNC_RDN0 (MTK_PIN_NO(101) | 1)
++
++#define MT8127_PIN_102_RDP0__FUNC_GPI102 (MTK_PIN_NO(102) | 0)
++#define MT8127_PIN_102_RDP0__FUNC_RDP0 (MTK_PIN_NO(102) | 1)
++
++#define MT8127_PIN_103_RDN1__FUNC_GPI103 (MTK_PIN_NO(103) | 0)
++#define MT8127_PIN_103_RDN1__FUNC_RDN1 (MTK_PIN_NO(103) | 1)
++
++#define MT8127_PIN_104_RDP1__FUNC_GPI104 (MTK_PIN_NO(104) | 0)
++#define MT8127_PIN_104_RDP1__FUNC_RDP1 (MTK_PIN_NO(104) | 1)
++
++#define MT8127_PIN_105_RCN__FUNC_GPI105 (MTK_PIN_NO(105) | 0)
++#define MT8127_PIN_105_RCN__FUNC_RCN (MTK_PIN_NO(105) | 1)
++
++#define MT8127_PIN_106_RCP__FUNC_GPI106 (MTK_PIN_NO(106) | 0)
++#define MT8127_PIN_106_RCP__FUNC_RCP (MTK_PIN_NO(106) | 1)
++
++#define MT8127_PIN_107_RDN2__FUNC_GPI107 (MTK_PIN_NO(107) | 0)
++#define MT8127_PIN_107_RDN2__FUNC_RDN2 (MTK_PIN_NO(107) | 1)
++#define MT8127_PIN_107_RDN2__FUNC_CMDAT8 (MTK_PIN_NO(107) | 2)
++
++#define MT8127_PIN_108_RDP2__FUNC_GPI108 (MTK_PIN_NO(108) | 0)
++#define MT8127_PIN_108_RDP2__FUNC_RDP2 (MTK_PIN_NO(108) | 1)
++#define MT8127_PIN_108_RDP2__FUNC_CMDAT9 (MTK_PIN_NO(108) | 2)
++
++#define MT8127_PIN_109_RDN3__FUNC_GPI109 (MTK_PIN_NO(109) | 0)
++#define MT8127_PIN_109_RDN3__FUNC_RDN3 (MTK_PIN_NO(109) | 1)
++#define MT8127_PIN_109_RDN3__FUNC_CMDAT4 (MTK_PIN_NO(109) | 2)
++
++#define MT8127_PIN_110_RDP3__FUNC_GPI110 (MTK_PIN_NO(110) | 0)
++#define MT8127_PIN_110_RDP3__FUNC_RDP3 (MTK_PIN_NO(110) | 1)
++#define MT8127_PIN_110_RDP3__FUNC_CMDAT5 (MTK_PIN_NO(110) | 2)
++
++#define MT8127_PIN_111_RCN_A__FUNC_GPI111 (MTK_PIN_NO(111) | 0)
++#define MT8127_PIN_111_RCN_A__FUNC_RCN_A (MTK_PIN_NO(111) | 1)
++#define MT8127_PIN_111_RCN_A__FUNC_CMDAT6 (MTK_PIN_NO(111) | 2)
++
++#define MT8127_PIN_112_RCP_A__FUNC_GPI112 (MTK_PIN_NO(112) | 0)
++#define MT8127_PIN_112_RCP_A__FUNC_RCP_A (MTK_PIN_NO(112) | 1)
++#define MT8127_PIN_112_RCP_A__FUNC_CMDAT7 (MTK_PIN_NO(112) | 2)
++
++#define MT8127_PIN_113_RDN1_A__FUNC_GPI113 (MTK_PIN_NO(113) | 0)
++#define MT8127_PIN_113_RDN1_A__FUNC_RDN1_A (MTK_PIN_NO(113) | 1)
++#define MT8127_PIN_113_RDN1_A__FUNC_CMDAT2 (MTK_PIN_NO(113) | 2)
++#define MT8127_PIN_113_RDN1_A__FUNC_CMCSD2 (MTK_PIN_NO(113) | 3)
++
++#define MT8127_PIN_114_RDP1_A__FUNC_GPI114 (MTK_PIN_NO(114) | 0)
++#define MT8127_PIN_114_RDP1_A__FUNC_RDP1_A (MTK_PIN_NO(114) | 1)
++#define MT8127_PIN_114_RDP1_A__FUNC_CMDAT3 (MTK_PIN_NO(114) | 2)
++#define MT8127_PIN_114_RDP1_A__FUNC_CMCSD3 (MTK_PIN_NO(114) | 3)
++
++#define MT8127_PIN_115_RDN0_A__FUNC_GPI115 (MTK_PIN_NO(115) | 0)
++#define MT8127_PIN_115_RDN0_A__FUNC_RDN0_A (MTK_PIN_NO(115) | 1)
++#define MT8127_PIN_115_RDN0_A__FUNC_CMHSYNC (MTK_PIN_NO(115) | 2)
++
++#define MT8127_PIN_116_RDP0_A__FUNC_GPI116 (MTK_PIN_NO(116) | 0)
++#define MT8127_PIN_116_RDP0_A__FUNC_RDP0_A (MTK_PIN_NO(116) | 1)
++#define MT8127_PIN_116_RDP0_A__FUNC_CMVSYNC (MTK_PIN_NO(116) | 2)
++
++#define MT8127_PIN_117_CMDAT0__FUNC_GPIO117 (MTK_PIN_NO(117) | 0)
++#define MT8127_PIN_117_CMDAT0__FUNC_CMDAT0 (MTK_PIN_NO(117) | 1)
++#define MT8127_PIN_117_CMDAT0__FUNC_CMCSD0 (MTK_PIN_NO(117) | 2)
++#define MT8127_PIN_117_CMDAT0__FUNC_ANT_SEL2 (MTK_PIN_NO(117) | 3)
++#define MT8127_PIN_117_CMDAT0__FUNC_DBG_MON_B_28 (MTK_PIN_NO(117) | 7)
++
++#define MT8127_PIN_118_CMDAT1__FUNC_GPIO118 (MTK_PIN_NO(118) | 0)
++#define MT8127_PIN_118_CMDAT1__FUNC_CMDAT1 (MTK_PIN_NO(118) | 1)
++#define MT8127_PIN_118_CMDAT1__FUNC_CMCSD1 (MTK_PIN_NO(118) | 2)
++#define MT8127_PIN_118_CMDAT1__FUNC_ANT_SEL3 (MTK_PIN_NO(118) | 3)
++#define MT8127_PIN_118_CMDAT1__FUNC_DBG_MON_B_29 (MTK_PIN_NO(118) | 7)
++
++#define MT8127_PIN_119_CMMCLK__FUNC_GPIO119 (MTK_PIN_NO(119) | 0)
++#define MT8127_PIN_119_CMMCLK__FUNC_CMMCLK (MTK_PIN_NO(119) | 1)
++#define MT8127_PIN_119_CMMCLK__FUNC_ANT_SEL4 (MTK_PIN_NO(119) | 3)
++#define MT8127_PIN_119_CMMCLK__FUNC_DBG_MON_B_30 (MTK_PIN_NO(119) | 7)
++
++#define MT8127_PIN_120_CMPCLK__FUNC_GPIO120 (MTK_PIN_NO(120) | 0)
++#define MT8127_PIN_120_CMPCLK__FUNC_CMPCLK (MTK_PIN_NO(120) | 1)
++#define MT8127_PIN_120_CMPCLK__FUNC_CMCSK (MTK_PIN_NO(120) | 2)
++#define MT8127_PIN_120_CMPCLK__FUNC_ANT_SEL5 (MTK_PIN_NO(120) | 3)
++#define MT8127_PIN_120_CMPCLK__FUNC_DBG_MON_B_31 (MTK_PIN_NO(120) | 7)
++
++#define MT8127_PIN_121_MSDC1_CMD__FUNC_GPIO121 (MTK_PIN_NO(121) | 0)
++#define MT8127_PIN_121_MSDC1_CMD__FUNC_MSDC1_CMD (MTK_PIN_NO(121) | 1)
++
++#define MT8127_PIN_122_MSDC1_CLK__FUNC_GPIO122 (MTK_PIN_NO(122) | 0)
++#define MT8127_PIN_122_MSDC1_CLK__FUNC_MSDC1_CLK (MTK_PIN_NO(122) | 1)
++
++#define MT8127_PIN_123_MSDC1_DAT0__FUNC_GPIO123 (MTK_PIN_NO(123) | 0)
++#define MT8127_PIN_123_MSDC1_DAT0__FUNC_MSDC1_DAT0 (MTK_PIN_NO(123) | 1)
++
++#define MT8127_PIN_124_MSDC1_DAT1__FUNC_GPIO124 (MTK_PIN_NO(124) | 0)
++#define MT8127_PIN_124_MSDC1_DAT1__FUNC_MSDC1_DAT1 (MTK_PIN_NO(124) | 1)
++
++#define MT8127_PIN_125_MSDC1_DAT2__FUNC_GPIO125 (MTK_PIN_NO(125) | 0)
++#define MT8127_PIN_125_MSDC1_DAT2__FUNC_MSDC1_DAT2 (MTK_PIN_NO(125) | 1)
++
++#define MT8127_PIN_126_MSDC1_DAT3__FUNC_GPIO126 (MTK_PIN_NO(126) | 0)
++#define MT8127_PIN_126_MSDC1_DAT3__FUNC_MSDC1_DAT3 (MTK_PIN_NO(126) | 1)
++
++#define MT8127_PIN_127_MSDC0_DAT7__FUNC_GPIO127 (MTK_PIN_NO(127) | 0)
++#define MT8127_PIN_127_MSDC0_DAT7__FUNC_MSDC0_DAT7 (MTK_PIN_NO(127) | 1)
++#define MT8127_PIN_127_MSDC0_DAT7__FUNC_NLD7 (MTK_PIN_NO(127) | 4)
++
++#define MT8127_PIN_128_MSDC0_DAT6__FUNC_GPIO128 (MTK_PIN_NO(128) | 0)
++#define MT8127_PIN_128_MSDC0_DAT6__FUNC_MSDC0_DAT6 (MTK_PIN_NO(128) | 1)
++#define MT8127_PIN_128_MSDC0_DAT6__FUNC_NLD6 (MTK_PIN_NO(128) | 4)
++
++#define MT8127_PIN_129_MSDC0_DAT5__FUNC_GPIO129 (MTK_PIN_NO(129) | 0)
++#define MT8127_PIN_129_MSDC0_DAT5__FUNC_MSDC0_DAT5 (MTK_PIN_NO(129) | 1)
++#define MT8127_PIN_129_MSDC0_DAT5__FUNC_NLD4 (MTK_PIN_NO(129) | 4)
++
++#define MT8127_PIN_130_MSDC0_DAT4__FUNC_GPIO130 (MTK_PIN_NO(130) | 0)
++#define MT8127_PIN_130_MSDC0_DAT4__FUNC_MSDC0_DAT4 (MTK_PIN_NO(130) | 1)
++#define MT8127_PIN_130_MSDC0_DAT4__FUNC_NLD3 (MTK_PIN_NO(130) | 4)
++
++#define MT8127_PIN_131_MSDC0_RSTB__FUNC_GPIO131 (MTK_PIN_NO(131) | 0)
++#define MT8127_PIN_131_MSDC0_RSTB__FUNC_MSDC0_RSTB (MTK_PIN_NO(131) | 1)
++#define MT8127_PIN_131_MSDC0_RSTB__FUNC_NLD0 (MTK_PIN_NO(131) | 4)
++
++#define MT8127_PIN_132_MSDC0_CMD__FUNC_GPIO132 (MTK_PIN_NO(132) | 0)
++#define MT8127_PIN_132_MSDC0_CMD__FUNC_MSDC0_CMD (MTK_PIN_NO(132) | 1)
++#define MT8127_PIN_132_MSDC0_CMD__FUNC_NALE (MTK_PIN_NO(132) | 4)
++
++#define MT8127_PIN_133_MSDC0_CLK__FUNC_GPIO133 (MTK_PIN_NO(133) | 0)
++#define MT8127_PIN_133_MSDC0_CLK__FUNC_MSDC0_CLK (MTK_PIN_NO(133) | 1)
++#define MT8127_PIN_133_MSDC0_CLK__FUNC_NWEB (MTK_PIN_NO(133) | 4)
++
++#define MT8127_PIN_134_MSDC0_DAT3__FUNC_GPIO134 (MTK_PIN_NO(134) | 0)
++#define MT8127_PIN_134_MSDC0_DAT3__FUNC_MSDC0_DAT3 (MTK_PIN_NO(134) | 1)
++#define MT8127_PIN_134_MSDC0_DAT3__FUNC_NLD1 (MTK_PIN_NO(134) | 4)
++
++#define MT8127_PIN_135_MSDC0_DAT2__FUNC_GPIO135 (MTK_PIN_NO(135) | 0)
++#define MT8127_PIN_135_MSDC0_DAT2__FUNC_MSDC0_DAT2 (MTK_PIN_NO(135) | 1)
++#define MT8127_PIN_135_MSDC0_DAT2__FUNC_NLD5 (MTK_PIN_NO(135) | 4)
++
++#define MT8127_PIN_136_MSDC0_DAT1__FUNC_GPIO136 (MTK_PIN_NO(136) | 0)
++#define MT8127_PIN_136_MSDC0_DAT1__FUNC_MSDC0_DAT1 (MTK_PIN_NO(136) | 1)
++#define MT8127_PIN_136_MSDC0_DAT1__FUNC_NLD8 (MTK_PIN_NO(136) | 4)
++
++#define MT8127_PIN_137_MSDC0_DAT0__FUNC_GPIO137 (MTK_PIN_NO(137) | 0)
++#define MT8127_PIN_137_MSDC0_DAT0__FUNC_MSDC0_DAT0 (MTK_PIN_NO(137) | 1)
++#define MT8127_PIN_137_MSDC0_DAT0__FUNC_WATCHDOG (MTK_PIN_NO(137) | 4)
++#define MT8127_PIN_137_MSDC0_DAT0__FUNC_NLD2 (MTK_PIN_NO(137) | 5)
++
++#define MT8127_PIN_138_CEC__FUNC_GPIO138 (MTK_PIN_NO(138) | 0)
++#define MT8127_PIN_138_CEC__FUNC_CEC (MTK_PIN_NO(138) | 1)
++
++#define MT8127_PIN_139_HTPLG__FUNC_GPIO139 (MTK_PIN_NO(139) | 0)
++#define MT8127_PIN_139_HTPLG__FUNC_HTPLG (MTK_PIN_NO(139) | 1)
++
++#define MT8127_PIN_140_HDMISCK__FUNC_GPIO140 (MTK_PIN_NO(140) | 0)
++#define MT8127_PIN_140_HDMISCK__FUNC_HDMISCK (MTK_PIN_NO(140) | 1)
++
++#define MT8127_PIN_141_HDMISD__FUNC_GPIO141 (MTK_PIN_NO(141) | 0)
++#define MT8127_PIN_141_HDMISD__FUNC_HDMISD (MTK_PIN_NO(141) | 1)
++
++#define MT8127_PIN_142_EINT21__FUNC_GPIO142 (MTK_PIN_NO(142) | 0)
++#define MT8127_PIN_142_EINT21__FUNC_NRNB (MTK_PIN_NO(142) | 1)
++#define MT8127_PIN_142_EINT21__FUNC_ANT_SEL0 (MTK_PIN_NO(142) | 2)
++#define MT8127_PIN_142_EINT21__FUNC_DBG_MON_B_32 (MTK_PIN_NO(142) | 7)
++
++#endif /* __DTS_MT8127_PINFUNC_H */
+diff --git a/arch/arm/boot/dts/mt8127.dtsi b/arch/arm/boot/dts/mt8127.dtsi
+index 7c2090d..1d429ed 100644
+--- a/arch/arm/boot/dts/mt8127.dtsi
++++ b/arch/arm/boot/dts/mt8127.dtsi
+@@ -14,6 +14,7 @@
+
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
++#include "mt8127-pinfunc.h"
+ #include "skeleton64.dtsi"
+
+ / {
+@@ -94,6 +95,27 @@
+ compatible = "simple-bus";
+ ranges;
+
++ /*
++ * Pinctrl access register at 0x10005000 through regmap.
++ * Register 0x1000b000 is used by EINT.
++ */
++ pio: pinctrl@10005000 {
++ compatible = "mediatek,mt8127-pinctrl";
++ reg = <0 0x1000b000 0 0x1000>;
++ mediatek,pctl-regmap = <&syscfg_pctl_a>;
++ pins-are-numbered;
++ gpio-controller;
++ #gpio-cells = <2>;
++ interrupt-controller;
++ #interrupt-cells = <2>;
++ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
++ };
++
++ syscfg_pctl_a: syscfg_pctl_a@10005000 {
++ compatible = "mediatek,mt8127-pctl-a-syscfg", "syscon";
++ reg = <0 0x10005000 0 0x1000>;
++ };
++
+ timer: timer@10008000 {
+ compatible = "mediatek,mt8127-timer",
+ "mediatek,mt6577-timer";
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0057-thermal-oops.patch b/target/linux/mediatek/patches/0057-thermal-oops.patch
new file mode 100644
index 0000000000..e7684f155d
--- /dev/null
+++ b/target/linux/mediatek/patches/0057-thermal-oops.patch
@@ -0,0 +1,27 @@
+From d1a856804b84affae30274b391b3c685e901093f Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 11:35:29 +0200
+Subject: [PATCH 57/76] thermal oops
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/thermal/mtk_thermal.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
+index 27aab12..5fdcbf6 100644
+--- a/drivers/thermal/mtk_thermal.c
++++ b/drivers/thermal/mtk_thermal.c
+@@ -394,7 +394,8 @@ static irqreturn_t mtk_thermal_irq(int irq, void *dev_id)
+
+ for (i = 0; i < MT8173_NUM_BANKS; i++) {
+ if (!(irqstat & (1 << i)))
+- mtk_thermal_irq_bank(&mt->banks[i]);
++ if (!IS_ERR(mt->banks[i].tz))
++ mtk_thermal_irq_bank(&mt->banks[i]);
+ }
+
+ return IRQ_HANDLED;
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0058-dont-disable-clocks.patch b/target/linux/mediatek/patches/0058-dont-disable-clocks.patch
new file mode 100644
index 0000000000..e30d5dc1aa
--- /dev/null
+++ b/target/linux/mediatek/patches/0058-dont-disable-clocks.patch
@@ -0,0 +1,25 @@
+From b1c69201563ae3ff878abf4ba192e73031de8653 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 23 Jun 2015 23:46:00 +0200
+Subject: [PATCH 58/76] dont disable clocks
+
+---
+ drivers/clk/clk.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
+index 5b0f418..360e6e4 100644
+--- a/drivers/clk/clk.c
++++ b/drivers/clk/clk.c
+@@ -541,7 +541,7 @@ unlock_out:
+ clk_enable_unlock(flags);
+ }
+
+-static bool clk_ignore_unused;
++static bool clk_ignore_unused = true;
+ static int __init clk_ignore_unused_setup(char *__unused)
+ {
+ clk_ignore_unused = true;
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0059-arm-mediatek-basic-mt6323-pmic-support.patch b/target/linux/mediatek/patches/0059-arm-mediatek-basic-mt6323-pmic-support.patch
new file mode 100644
index 0000000000..ca28251d2a
--- /dev/null
+++ b/target/linux/mediatek/patches/0059-arm-mediatek-basic-mt6323-pmic-support.patch
@@ -0,0 +1,1099 @@
+From 7f157285f2a01921917e0eed79b5d8cf734f5d27 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Wed, 24 Jun 2015 15:24:45 +0200
+Subject: [PATCH 59/76] arm: mediatek: basic mt6323 pmic support
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/mfd/Kconfig | 10 +
+ drivers/mfd/Makefile | 1 +
+ drivers/mfd/mt6323-core.c | 230 +++++++++++++++++++++
+ drivers/regulator/Kconfig | 9 +
+ drivers/regulator/Makefile | 1 +
+ drivers/regulator/mt6323-regulator.c | 332 +++++++++++++++++++++++++++++++
+ include/linux/mfd/mt6323/core.h | 64 ++++++
+ include/linux/mfd/mt6323/registers.h | 362 ++++++++++++++++++++++++++++++++++
+ 8 files changed, 1009 insertions(+)
+ create mode 100644 drivers/mfd/mt6323-core.c
+ create mode 100644 drivers/regulator/mt6323-regulator.c
+ create mode 100644 include/linux/mfd/mt6323/core.h
+ create mode 100644 include/linux/mfd/mt6323/registers.h
+
+diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
+index d5ad04d..ff2c14e 100644
+--- a/drivers/mfd/Kconfig
++++ b/drivers/mfd/Kconfig
+@@ -529,6 +529,16 @@ config MFD_MAX8998
+ additional drivers must be enabled in order to use the functionality
+ of the device.
+
++config MFD_MT6323
++ tristate "MediaTek MT6323 PMIC Support"
++ select MFD_CORE
++ select IRQ_DOMAIN
++ help
++ Say yes here to add support for MediaTek MT6323 PMIC. This is
++ a Power Management IC. This driver provides common support for
++ accessing the device; additional drivers must be enabled in order
++ to use the functionality of the device.
++
+ config MFD_MT6397
+ tristate "MediaTek MT6397 PMIC Support"
+ select MFD_CORE
+diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
+index 0e5cfeb..6e91123 100644
+--- a/drivers/mfd/Makefile
++++ b/drivers/mfd/Makefile
+@@ -184,4 +184,5 @@ obj-$(CONFIG_MFD_SKY81452) += sky81452.o
+
+ intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o
+ obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
++obj-$(CONFIG_MFD_MT6323) += mt6323-core.o
+ obj-$(CONFIG_MFD_MT6397) += mt6397-core.o
+diff --git a/drivers/mfd/mt6323-core.c b/drivers/mfd/mt6323-core.c
+new file mode 100644
+index 0000000..012c620
+--- /dev/null
++++ b/drivers/mfd/mt6323-core.c
+@@ -0,0 +1,230 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Flora Fu, MediaTek
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/interrupt.h>
++#include <linux/module.h>
++#include <linux/of_device.h>
++#include <linux/of_irq.h>
++#include <linux/regmap.h>
++#include <linux/mfd/core.h>
++#include <linux/mfd/mt6397/core.h>
++#include <linux/mfd/mt6397/registers.h>
++
++static const struct mfd_cell mt6397_devs[] = {
++ {
++ .name = "mt6397-rtc",
++ .of_compatible = "mediatek,mt6397-rtc",
++ }, {
++ .name = "mt6397-regulator",
++ .of_compatible = "mediatek,mt6397-regulator",
++ }, {
++ .name = "mt6397-codec",
++ .of_compatible = "mediatek,mt6397-codec",
++ }, {
++ .name = "mt6397-clk",
++ .of_compatible = "mediatek,mt6397-clk",
++ }, {
++ .name = "mediatek-mt6397-pinctrl",
++ .of_compatible = "mediatek,mt6397-pinctrl",
++ },
++};
++
++static void mt6397_irq_lock(struct irq_data *data)
++{
++ struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
++
++ mutex_lock(&mt6397->irqlock);
++}
++
++static void mt6397_irq_sync_unlock(struct irq_data *data)
++{
++ struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
++
++ regmap_write(mt6397->regmap, MT6397_INT_CON0, mt6397->irq_masks_cur[0]);
++ regmap_write(mt6397->regmap, MT6397_INT_CON1, mt6397->irq_masks_cur[1]);
++
++ mutex_unlock(&mt6397->irqlock);
++}
++
++static void mt6397_irq_disable(struct irq_data *data)
++{
++ struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
++ int shift = data->hwirq & 0xf;
++ int reg = data->hwirq >> 4;
++
++ mt6397->irq_masks_cur[reg] &= ~BIT(shift);
++}
++
++static void mt6397_irq_enable(struct irq_data *data)
++{
++ struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
++ int shift = data->hwirq & 0xf;
++ int reg = data->hwirq >> 4;
++
++ mt6397->irq_masks_cur[reg] |= BIT(shift);
++}
++
++static struct irq_chip mt6397_irq_chip = {
++ .name = "mt6397-irq",
++ .irq_bus_lock = mt6397_irq_lock,
++ .irq_bus_sync_unlock = mt6397_irq_sync_unlock,
++ .irq_enable = mt6397_irq_enable,
++ .irq_disable = mt6397_irq_disable,
++};
++
++static void mt6397_irq_handle_reg(struct mt6397_chip *mt6397, int reg,
++ int irqbase)
++{
++ unsigned int status;
++ int i, irq, ret;
++
++ ret = regmap_read(mt6397->regmap, reg, &status);
++ if (ret) {
++ dev_err(mt6397->dev, "Failed to read irq status: %d\n", ret);
++ return;
++ }
++
++ for (i = 0; i < 16; i++) {
++ if (status & BIT(i)) {
++ irq = irq_find_mapping(mt6397->irq_domain, irqbase + i);
++ if (irq)
++ handle_nested_irq(irq);
++ }
++ }
++
++ regmap_write(mt6397->regmap, reg, status);
++}
++
++static irqreturn_t mt6397_irq_thread(int irq, void *data)
++{
++ struct mt6397_chip *mt6397 = data;
++
++ mt6397_irq_handle_reg(mt6397, MT6397_INT_STATUS0, 0);
++ mt6397_irq_handle_reg(mt6397, MT6397_INT_STATUS1, 16);
++
++ return IRQ_HANDLED;
++}
++
++static int mt6397_irq_domain_map(struct irq_domain *d, unsigned int irq,
++ irq_hw_number_t hw)
++{
++ struct mt6397_chip *mt6397 = d->host_data;
++
++ irq_set_chip_data(irq, mt6397);
++ irq_set_chip_and_handler(irq, &mt6397_irq_chip, handle_level_irq);
++ irq_set_nested_thread(irq, 1);
++#ifdef CONFIG_ARM
++ set_irq_flags(irq, IRQF_VALID);
++#else
++ irq_set_noprobe(irq);
++#endif
++
++ return 0;
++}
++
++static struct irq_domain_ops mt6397_irq_domain_ops = {
++ .map = mt6397_irq_domain_map,
++};
++
++static int mt6397_irq_init(struct mt6397_chip *mt6397)
++{
++ int ret;
++
++ mutex_init(&mt6397->irqlock);
++
++ /* Mask all interrupt sources */
++ regmap_write(mt6397->regmap, MT6397_INT_CON0, 0x0);
++ regmap_write(mt6397->regmap, MT6397_INT_CON1, 0x0);
++
++ mt6397->irq_domain = irq_domain_add_linear(mt6397->dev->of_node,
++ MT6397_IRQ_NR, &mt6397_irq_domain_ops, mt6397);
++ if (!mt6397->irq_domain) {
++ dev_err(mt6397->dev, "could not create irq domain\n");
++ return -ENOMEM;
++ }
++
++ ret = devm_request_threaded_irq(mt6397->dev, mt6397->irq, NULL,
++ mt6397_irq_thread, IRQF_ONESHOT, "mt6397-pmic", mt6397);
++ if (ret) {
++ dev_err(mt6397->dev, "failed to register irq=%d; err: %d\n",
++ mt6397->irq, ret);
++ return ret;
++ }
++
++ return 0;
++}
++
++static int mt6397_probe(struct platform_device *pdev)
++{
++ int ret;
++ struct mt6397_chip *mt6397;
++
++ mt6397 = devm_kzalloc(&pdev->dev, sizeof(*mt6397), GFP_KERNEL);
++ if (!mt6397)
++ return -ENOMEM;
++
++ mt6397->dev = &pdev->dev;
++ /*
++ * mt6397 MFD is child device of soc pmic wrapper.
++ * Regmap is set from its parent.
++ */
++ mt6397->regmap = dev_get_regmap(pdev->dev.parent, NULL);
++ if (!mt6397->regmap)
++ return -ENODEV;
++
++ platform_set_drvdata(pdev, mt6397);
++
++ mt6397->irq = platform_get_irq(pdev, 0);
++ if (mt6397->irq > 0) {
++ ret = mt6397_irq_init(mt6397);
++ if (ret)
++ return ret;
++ }
++
++ ret = mfd_add_devices(&pdev->dev, -1, mt6397_devs,
++ ARRAY_SIZE(mt6397_devs), NULL, 0, NULL);
++ if (ret)
++ dev_err(&pdev->dev, "failed to add child devices: %d\n", ret);
++
++ return ret;
++}
++
++static int mt6397_remove(struct platform_device *pdev)
++{
++ mfd_remove_devices(&pdev->dev);
++
++ return 0;
++}
++
++static const struct of_device_id mt6397_of_match[] = {
++ { .compatible = "mediatek,mt6397" },
++ { }
++};
++MODULE_DEVICE_TABLE(of, mt6397_of_match);
++
++static struct platform_driver mt6397_driver = {
++ .probe = mt6397_probe,
++ .remove = mt6397_remove,
++ .driver = {
++ .name = "mt6397",
++ .of_match_table = of_match_ptr(mt6397_of_match),
++ },
++};
++
++module_platform_driver(mt6397_driver);
++
++MODULE_AUTHOR("Flora Fu, MediaTek");
++MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:mt6397");
+diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
+index a6f116a..336d4c6 100644
+--- a/drivers/regulator/Kconfig
++++ b/drivers/regulator/Kconfig
+@@ -441,6 +441,15 @@ config REGULATOR_MC13892
+ Say y here to support the regulators found on the Freescale MC13892
+ PMIC.
+
++config REGULATOR_MT6323
++ tristate "MediaTek MT6323 PMIC"
++ depends on MFD_MT6323
++ help
++ Say y here to select this option to enable the power regulator of
++ MediaTek MT6323 PMIC.
++ This driver supports the control of different power rails of device
++ through regulator interface.
++
+ config REGULATOR_MT6397
+ tristate "MediaTek MT6397 PMIC"
+ depends on MFD_MT6397
+diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
+index 2c4da15..ac6a9da 100644
+--- a/drivers/regulator/Makefile
++++ b/drivers/regulator/Makefile
+@@ -59,6 +59,7 @@ obj-$(CONFIG_REGULATOR_MAX77843) += max77843.o
+ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
+ obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
+ obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
++obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o
+ obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
+ obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o
+ obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
+diff --git a/drivers/regulator/mt6323-regulator.c b/drivers/regulator/mt6323-regulator.c
+new file mode 100644
+index 0000000..a5b2f47
+--- /dev/null
++++ b/drivers/regulator/mt6323-regulator.c
+@@ -0,0 +1,332 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Flora Fu <flora.fu@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++#include <linux/regmap.h>
++#include <linux/mfd/mt6397/core.h>
++#include <linux/mfd/mt6397/registers.h>
++#include <linux/regulator/driver.h>
++#include <linux/regulator/machine.h>
++#include <linux/regulator/mt6397-regulator.h>
++#include <linux/regulator/of_regulator.h>
++
++/*
++ * MT6397 regulators' information
++ *
++ * @desc: standard fields of regulator description.
++ * @qi: Mask for query enable signal status of regulators
++ * @vselon_reg: Register sections for hardware control mode of bucks
++ * @vselctrl_reg: Register for controlling the buck control mode.
++ * @vselctrl_mask: Mask for query buck's voltage control mode.
++ */
++struct mt6397_regulator_info {
++ struct regulator_desc desc;
++ u32 qi;
++ u32 vselon_reg;
++ u32 vselctrl_reg;
++ u32 vselctrl_mask;
++};
++
++#define MT6397_BUCK(match, vreg, min, max, step, volt_ranges, enreg, \
++ vosel, vosel_mask, voselon, vosel_ctrl) \
++[MT6397_ID_##vreg] = { \
++ .desc = { \
++ .name = #vreg, \
++ .of_match = of_match_ptr(match), \
++ .ops = &mt6397_volt_range_ops, \
++ .type = REGULATOR_VOLTAGE, \
++ .id = MT6397_ID_##vreg, \
++ .owner = THIS_MODULE, \
++ .n_voltages = (max - min)/step + 1, \
++ .linear_ranges = volt_ranges, \
++ .n_linear_ranges = ARRAY_SIZE(volt_ranges), \
++ .vsel_reg = vosel, \
++ .vsel_mask = vosel_mask, \
++ .enable_reg = enreg, \
++ .enable_mask = BIT(0), \
++ }, \
++ .qi = BIT(13), \
++ .vselon_reg = voselon, \
++ .vselctrl_reg = vosel_ctrl, \
++ .vselctrl_mask = BIT(1), \
++}
++
++#define MT6397_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel, \
++ vosel_mask) \
++[MT6397_ID_##vreg] = { \
++ .desc = { \
++ .name = #vreg, \
++ .of_match = of_match_ptr(match), \
++ .ops = &mt6397_volt_table_ops, \
++ .type = REGULATOR_VOLTAGE, \
++ .id = MT6397_ID_##vreg, \
++ .owner = THIS_MODULE, \
++ .n_voltages = ARRAY_SIZE(ldo_volt_table), \
++ .volt_table = ldo_volt_table, \
++ .vsel_reg = vosel, \
++ .vsel_mask = vosel_mask, \
++ .enable_reg = enreg, \
++ .enable_mask = BIT(enbit), \
++ }, \
++ .qi = BIT(15), \
++}
++
++#define MT6397_REG_FIXED(match, vreg, enreg, enbit, volt) \
++[MT6397_ID_##vreg] = { \
++ .desc = { \
++ .name = #vreg, \
++ .of_match = of_match_ptr(match), \
++ .ops = &mt6397_volt_fixed_ops, \
++ .type = REGULATOR_VOLTAGE, \
++ .id = MT6397_ID_##vreg, \
++ .owner = THIS_MODULE, \
++ .n_voltages = 1, \
++ .enable_reg = enreg, \
++ .enable_mask = BIT(enbit), \
++ .min_uV = volt, \
++ }, \
++ .qi = BIT(15), \
++}
++
++static const struct regulator_linear_range buck_volt_range1[] = {
++ REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250),
++};
++
++static const struct regulator_linear_range buck_volt_range2[] = {
++ REGULATOR_LINEAR_RANGE(800000, 0, 0x7f, 6250),
++};
++
++static const struct regulator_linear_range buck_volt_range3[] = {
++ REGULATOR_LINEAR_RANGE(1500000, 0, 0x1f, 20000),
++};
++
++static const u32 ldo_volt_table1[] = {
++ 1500000, 1800000, 2500000, 2800000,
++};
++
++static const u32 ldo_volt_table2[] = {
++ 1800000, 3300000,
++};
++
++static const u32 ldo_volt_table3[] = {
++ 3000000, 3300000,
++};
++
++static const u32 ldo_volt_table4[] = {
++ 1220000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,
++};
++
++static const u32 ldo_volt_table5[] = {
++ 1200000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,
++};
++
++static const u32 ldo_volt_table5_v2[] = {
++ 1200000, 1000000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,
++};
++
++static const u32 ldo_volt_table6[] = {
++ 1200000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 2000000,
++};
++
++static const u32 ldo_volt_table7[] = {
++ 1300000, 1500000, 1800000, 2000000, 2500000, 2800000, 3000000, 3300000,
++};
++
++static int mt6397_get_status(struct regulator_dev *rdev)
++{
++ int ret;
++ u32 regval;
++ struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
++
++ ret = regmap_read(rdev->regmap, info->desc.enable_reg, &regval);
++ if (ret != 0) {
++ dev_err(&rdev->dev, "Failed to get enable reg: %d\n", ret);
++ return ret;
++ }
++
++ return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;
++}
++
++static struct regulator_ops mt6397_volt_range_ops = {
++ .list_voltage = regulator_list_voltage_linear_range,
++ .map_voltage = regulator_map_voltage_linear_range,
++ .set_voltage_sel = regulator_set_voltage_sel_regmap,
++ .get_voltage_sel = regulator_get_voltage_sel_regmap,
++ .set_voltage_time_sel = regulator_set_voltage_time_sel,
++ .enable = regulator_enable_regmap,
++ .disable = regulator_disable_regmap,
++ .is_enabled = regulator_is_enabled_regmap,
++ .get_status = mt6397_get_status,
++};
++
++static struct regulator_ops mt6397_volt_table_ops = {
++ .list_voltage = regulator_list_voltage_table,
++ .map_voltage = regulator_map_voltage_iterate,
++ .set_voltage_sel = regulator_set_voltage_sel_regmap,
++ .get_voltage_sel = regulator_get_voltage_sel_regmap,
++ .set_voltage_time_sel = regulator_set_voltage_time_sel,
++ .enable = regulator_enable_regmap,
++ .disable = regulator_disable_regmap,
++ .is_enabled = regulator_is_enabled_regmap,
++ .get_status = mt6397_get_status,
++};
++
++static struct regulator_ops mt6397_volt_fixed_ops = {
++ .list_voltage = regulator_list_voltage_linear,
++ .enable = regulator_enable_regmap,
++ .disable = regulator_disable_regmap,
++ .is_enabled = regulator_is_enabled_regmap,
++ .get_status = mt6397_get_status,
++};
++
++/* The array is indexed by id(MT6397_ID_XXX) */
++static struct mt6397_regulator_info mt6397_regulators[] = {
++ MT6397_BUCK("buck_vpca15", VPCA15, 700000, 1493750, 6250,
++ buck_volt_range1, MT6397_VCA15_CON7, MT6397_VCA15_CON9, 0x7f,
++ MT6397_VCA15_CON10, MT6397_VCA15_CON5),
++ MT6397_BUCK("buck_vpca7", VPCA7, 700000, 1493750, 6250,
++ buck_volt_range1, MT6397_VPCA7_CON7, MT6397_VPCA7_CON9, 0x7f,
++ MT6397_VPCA7_CON10, MT6397_VPCA7_CON5),
++ MT6397_BUCK("buck_vsramca15", VSRAMCA15, 700000, 1493750, 6250,
++ buck_volt_range1, MT6397_VSRMCA15_CON7, MT6397_VSRMCA15_CON9,
++ 0x7f, MT6397_VSRMCA15_CON10, MT6397_VSRMCA15_CON5),
++ MT6397_BUCK("buck_vsramca7", VSRAMCA7, 700000, 1493750, 6250,
++ buck_volt_range1, MT6397_VSRMCA7_CON7, MT6397_VSRMCA7_CON9,
++ 0x7f, MT6397_VSRMCA7_CON10, MT6397_VSRMCA7_CON5),
++ MT6397_BUCK("buck_vcore", VCORE, 700000, 1493750, 6250,
++ buck_volt_range1, MT6397_VCORE_CON7, MT6397_VCORE_CON9, 0x7f,
++ MT6397_VCORE_CON10, MT6397_VCORE_CON5),
++ MT6397_BUCK("buck_vgpu", VGPU, 700000, 1493750, 6250, buck_volt_range1,
++ MT6397_VGPU_CON7, MT6397_VGPU_CON9, 0x7f,
++ MT6397_VGPU_CON10, MT6397_VGPU_CON5),
++ MT6397_BUCK("buck_vdrm", VDRM, 800000, 1593750, 6250, buck_volt_range2,
++ MT6397_VDRM_CON7, MT6397_VDRM_CON9, 0x7f,
++ MT6397_VDRM_CON10, MT6397_VDRM_CON5),
++ MT6397_BUCK("buck_vio18", VIO18, 1500000, 2120000, 20000,
++ buck_volt_range3, MT6397_VIO18_CON7, MT6397_VIO18_CON9, 0x1f,
++ MT6397_VIO18_CON10, MT6397_VIO18_CON5),
++ MT6397_REG_FIXED("ldo_vtcxo", VTCXO, MT6397_ANALDO_CON0, 10, 2800000),
++ MT6397_REG_FIXED("ldo_va28", VA28, MT6397_ANALDO_CON1, 14, 2800000),
++ MT6397_LDO("ldo_vcama", VCAMA, ldo_volt_table1,
++ MT6397_ANALDO_CON2, 15, MT6397_ANALDO_CON6, 0xC0),
++ MT6397_REG_FIXED("ldo_vio28", VIO28, MT6397_DIGLDO_CON0, 14, 2800000),
++ MT6397_REG_FIXED("ldo_vusb", VUSB, MT6397_DIGLDO_CON1, 14, 3300000),
++ MT6397_LDO("ldo_vmc", VMC, ldo_volt_table2,
++ MT6397_DIGLDO_CON2, 12, MT6397_DIGLDO_CON29, 0x10),
++ MT6397_LDO("ldo_vmch", VMCH, ldo_volt_table3,
++ MT6397_DIGLDO_CON3, 14, MT6397_DIGLDO_CON17, 0x80),
++ MT6397_LDO("ldo_vemc3v3", VEMC3V3, ldo_volt_table3,
++ MT6397_DIGLDO_CON4, 14, MT6397_DIGLDO_CON18, 0x10),
++ MT6397_LDO("ldo_vgp1", VGP1, ldo_volt_table4,
++ MT6397_DIGLDO_CON5, 15, MT6397_DIGLDO_CON19, 0xE0),
++ MT6397_LDO("ldo_vgp2", VGP2, ldo_volt_table5,
++ MT6397_DIGLDO_CON6, 15, MT6397_DIGLDO_CON20, 0xE0),
++ MT6397_LDO("ldo_vgp3", VGP3, ldo_volt_table5,
++ MT6397_DIGLDO_CON7, 15, MT6397_DIGLDO_CON21, 0xE0),
++ MT6397_LDO("ldo_vgp4", VGP4, ldo_volt_table5,
++ MT6397_DIGLDO_CON8, 15, MT6397_DIGLDO_CON22, 0xE0),
++ MT6397_LDO("ldo_vgp5", VGP5, ldo_volt_table6,
++ MT6397_DIGLDO_CON9, 15, MT6397_DIGLDO_CON23, 0xE0),
++ MT6397_LDO("ldo_vgp6", VGP6, ldo_volt_table5,
++ MT6397_DIGLDO_CON10, 15, MT6397_DIGLDO_CON33, 0xE0),
++ MT6397_LDO("ldo_vibr", VIBR, ldo_volt_table7,
++ MT6397_DIGLDO_CON24, 15, MT6397_DIGLDO_CON25, 0xE00),
++};
++
++static int mt6397_set_buck_vosel_reg(struct platform_device *pdev)
++{
++ struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
++ int i;
++ u32 regval;
++
++ for (i = 0; i < MT6397_MAX_REGULATOR; i++) {
++ if (mt6397_regulators[i].vselctrl_reg) {
++ if (regmap_read(mt6397->regmap,
++ mt6397_regulators[i].vselctrl_reg,
++ &regval) < 0) {
++ dev_err(&pdev->dev,
++ "Failed to read buck ctrl\n");
++ return -EIO;
++ }
++
++ if (regval & mt6397_regulators[i].vselctrl_mask) {
++ mt6397_regulators[i].desc.vsel_reg =
++ mt6397_regulators[i].vselon_reg;
++ }
++ }
++ }
++
++ return 0;
++}
++
++static int mt6397_regulator_probe(struct platform_device *pdev)
++{
++ struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
++ struct regulator_config config = {};
++ struct regulator_dev *rdev;
++ int i;
++ u32 reg_value, version;
++
++ /* Query buck controller to select activated voltage register part */
++ if (mt6397_set_buck_vosel_reg(pdev))
++ return -EIO;
++
++ /* Read PMIC chip revision to update constraints and voltage table */
++ if (regmap_read(mt6397->regmap, MT6397_CID, &reg_value) < 0) {
++ dev_err(&pdev->dev, "Failed to read Chip ID\n");
++ return -EIO;
++ }
++ dev_info(&pdev->dev, "Chip ID = 0x%x\n", reg_value);
++
++ version = (reg_value & 0xFF);
++ switch (version) {
++ case MT6397_REGULATOR_ID91:
++ mt6397_regulators[MT6397_ID_VGP2].desc.volt_table =
++ ldo_volt_table5_v2;
++ break;
++ default:
++ break;
++ }
++
++ for (i = 0; i < MT6397_MAX_REGULATOR; i++) {
++ config.dev = &pdev->dev;
++ config.driver_data = &mt6397_regulators[i];
++ config.regmap = mt6397->regmap;
++ rdev = devm_regulator_register(&pdev->dev,
++ &mt6397_regulators[i].desc, &config);
++ if (IS_ERR(rdev)) {
++ dev_err(&pdev->dev, "failed to register %s\n",
++ mt6397_regulators[i].desc.name);
++ return PTR_ERR(rdev);
++ }
++ }
++
++ return 0;
++}
++
++static struct platform_driver mt6397_regulator_driver = {
++ .driver = {
++ .name = "mt6397-regulator",
++ },
++ .probe = mt6397_regulator_probe,
++};
++
++module_platform_driver(mt6397_regulator_driver);
++
++MODULE_AUTHOR("Flora Fu <flora.fu@mediatek.com>");
++MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6397 PMIC");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:mt6397-regulator");
+diff --git a/include/linux/mfd/mt6323/core.h b/include/linux/mfd/mt6323/core.h
+new file mode 100644
+index 0000000..cf5265b
+--- /dev/null
++++ b/include/linux/mfd/mt6323/core.h
+@@ -0,0 +1,64 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Flora Fu, MediaTek
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#ifndef __MFD_MT6397_CORE_H__
++#define __MFD_MT6397_CORE_H__
++
++enum mt6397_irq_numbers {
++ MT6397_IRQ_SPKL_AB = 0,
++ MT6397_IRQ_SPKR_AB,
++ MT6397_IRQ_SPKL,
++ MT6397_IRQ_SPKR,
++ MT6397_IRQ_BAT_L,
++ MT6397_IRQ_BAT_H,
++ MT6397_IRQ_FG_BAT_L,
++ MT6397_IRQ_FG_BAT_H,
++ MT6397_IRQ_WATCHDOG,
++ MT6397_IRQ_PWRKEY,
++ MT6397_IRQ_THR_L,
++ MT6397_IRQ_THR_H,
++ MT6397_IRQ_VBATON_UNDET,
++ MT6397_IRQ_BVALID_DET,
++ MT6397_IRQ_CHRDET,
++ MT6397_IRQ_OV,
++ MT6397_IRQ_LDO,
++ MT6397_IRQ_HOMEKEY,
++ MT6397_IRQ_ACCDET,
++ MT6397_IRQ_AUDIO,
++ MT6397_IRQ_RTC,
++ MT6397_IRQ_PWRKEY_RSTB,
++ MT6397_IRQ_HDMI_SIFM,
++ MT6397_IRQ_HDMI_CEC,
++ MT6397_IRQ_VCA15,
++ MT6397_IRQ_VSRMCA15,
++ MT6397_IRQ_VCORE,
++ MT6397_IRQ_VGPU,
++ MT6397_IRQ_VIO18,
++ MT6397_IRQ_VPCA7,
++ MT6397_IRQ_VSRMCA7,
++ MT6397_IRQ_VDRM,
++ MT6397_IRQ_NR,
++};
++
++struct mt6397_chip {
++ struct device *dev;
++ struct regmap *regmap;
++ int irq;
++ struct irq_domain *irq_domain;
++ struct mutex irqlock;
++ u16 irq_masks_cur[2];
++ u16 irq_masks_cache[2];
++};
++
++#endif /* __MFD_MT6397_CORE_H__ */
+diff --git a/include/linux/mfd/mt6323/registers.h b/include/linux/mfd/mt6323/registers.h
+new file mode 100644
+index 0000000..f23a0a6
+--- /dev/null
++++ b/include/linux/mfd/mt6323/registers.h
+@@ -0,0 +1,362 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Flora Fu, MediaTek
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#ifndef __MFD_MT6397_REGISTERS_H__
++#define __MFD_MT6397_REGISTERS_H__
++
++/* PMIC Registers */
++#define MT6397_CID 0x0100
++#define MT6397_TOP_CKPDN 0x0102
++#define MT6397_TOP_CKPDN_SET 0x0104
++#define MT6397_TOP_CKPDN_CLR 0x0106
++#define MT6397_TOP_CKPDN2 0x0108
++#define MT6397_TOP_CKPDN2_SET 0x010A
++#define MT6397_TOP_CKPDN2_CLR 0x010C
++#define MT6397_TOP_GPIO_CKPDN 0x010E
++#define MT6397_TOP_RST_CON 0x0114
++#define MT6397_WRP_CKPDN 0x011A
++#define MT6397_WRP_RST_CON 0x0120
++#define MT6397_TOP_RST_MISC 0x0126
++#define MT6397_TOP_CKCON1 0x0128
++#define MT6397_TOP_CKCON2 0x012A
++#define MT6397_TOP_CKTST1 0x012C
++#define MT6397_TOP_CKTST2 0x012E
++#define MT6397_OC_DEG_EN 0x0130
++#define MT6397_OC_CTL0 0x0132
++#define MT6397_OC_CTL1 0x0134
++#define MT6397_OC_CTL2 0x0136
++#define MT6397_INT_RSV 0x0138
++#define MT6397_TEST_CON0 0x013A
++#define MT6397_TEST_CON1 0x013C
++#define MT6397_STATUS0 0x013E
++#define MT6397_STATUS1 0x0140
++#define MT6397_PGSTATUS 0x0142
++#define MT6397_CHRSTATUS 0x0144
++#define MT6397_OCSTATUS0 0x0146
++#define MT6397_OCSTATUS1 0x0148
++#define MT6397_OCSTATUS2 0x014A
++#define MT6397_HDMI_PAD_IE 0x014C
++#define MT6397_TEST_OUT_L 0x014E
++#define MT6397_TEST_OUT_H 0x0150
++#define MT6397_TDSEL_CON 0x0152
++#define MT6397_RDSEL_CON 0x0154
++#define MT6397_GPIO_SMT_CON0 0x0156
++#define MT6397_GPIO_SMT_CON1 0x0158
++#define MT6397_GPIO_SMT_CON2 0x015A
++#define MT6397_GPIO_SMT_CON3 0x015C
++#define MT6397_DRV_CON0 0x015E
++#define MT6397_DRV_CON1 0x0160
++#define MT6397_DRV_CON2 0x0162
++#define MT6397_DRV_CON3 0x0164
++#define MT6397_DRV_CON4 0x0166
++#define MT6397_DRV_CON5 0x0168
++#define MT6397_DRV_CON6 0x016A
++#define MT6397_DRV_CON7 0x016C
++#define MT6397_DRV_CON8 0x016E
++#define MT6397_DRV_CON9 0x0170
++#define MT6397_DRV_CON10 0x0172
++#define MT6397_DRV_CON11 0x0174
++#define MT6397_DRV_CON12 0x0176
++#define MT6397_INT_CON0 0x0178
++#define MT6397_INT_CON1 0x017E
++#define MT6397_INT_STATUS0 0x0184
++#define MT6397_INT_STATUS1 0x0186
++#define MT6397_FQMTR_CON0 0x0188
++#define MT6397_FQMTR_CON1 0x018A
++#define MT6397_FQMTR_CON2 0x018C
++#define MT6397_EFUSE_DOUT_0_15 0x01C4
++#define MT6397_EFUSE_DOUT_16_31 0x01C6
++#define MT6397_EFUSE_DOUT_32_47 0x01C8
++#define MT6397_EFUSE_DOUT_48_63 0x01CA
++#define MT6397_SPI_CON 0x01CC
++#define MT6397_TOP_CKPDN3 0x01CE
++#define MT6397_TOP_CKCON3 0x01D4
++#define MT6397_EFUSE_DOUT_64_79 0x01D6
++#define MT6397_EFUSE_DOUT_80_95 0x01D8
++#define MT6397_EFUSE_DOUT_96_111 0x01DA
++#define MT6397_EFUSE_DOUT_112_127 0x01DC
++#define MT6397_EFUSE_DOUT_128_143 0x01DE
++#define MT6397_EFUSE_DOUT_144_159 0x01E0
++#define MT6397_EFUSE_DOUT_160_175 0x01E2
++#define MT6397_EFUSE_DOUT_176_191 0x01E4
++#define MT6397_EFUSE_DOUT_192_207 0x01E6
++#define MT6397_EFUSE_DOUT_208_223 0x01E8
++#define MT6397_EFUSE_DOUT_224_239 0x01EA
++#define MT6397_EFUSE_DOUT_240_255 0x01EC
++#define MT6397_EFUSE_DOUT_256_271 0x01EE
++#define MT6397_EFUSE_DOUT_272_287 0x01F0
++#define MT6397_EFUSE_DOUT_288_300 0x01F2
++#define MT6397_EFUSE_DOUT_304_319 0x01F4
++#define MT6397_BUCK_CON0 0x0200
++#define MT6397_BUCK_CON1 0x0202
++#define MT6397_BUCK_CON2 0x0204
++#define MT6397_BUCK_CON3 0x0206
++#define MT6397_BUCK_CON4 0x0208
++#define MT6397_BUCK_CON5 0x020A
++#define MT6397_BUCK_CON6 0x020C
++#define MT6397_BUCK_CON7 0x020E
++#define MT6397_BUCK_CON8 0x0210
++#define MT6397_BUCK_CON9 0x0212
++#define MT6397_VCA15_CON0 0x0214
++#define MT6397_VCA15_CON1 0x0216
++#define MT6397_VCA15_CON2 0x0218
++#define MT6397_VCA15_CON3 0x021A
++#define MT6397_VCA15_CON4 0x021C
++#define MT6397_VCA15_CON5 0x021E
++#define MT6397_VCA15_CON6 0x0220
++#define MT6397_VCA15_CON7 0x0222
++#define MT6397_VCA15_CON8 0x0224
++#define MT6397_VCA15_CON9 0x0226
++#define MT6397_VCA15_CON10 0x0228
++#define MT6397_VCA15_CON11 0x022A
++#define MT6397_VCA15_CON12 0x022C
++#define MT6397_VCA15_CON13 0x022E
++#define MT6397_VCA15_CON14 0x0230
++#define MT6397_VCA15_CON15 0x0232
++#define MT6397_VCA15_CON16 0x0234
++#define MT6397_VCA15_CON17 0x0236
++#define MT6397_VCA15_CON18 0x0238
++#define MT6397_VSRMCA15_CON0 0x023A
++#define MT6397_VSRMCA15_CON1 0x023C
++#define MT6397_VSRMCA15_CON2 0x023E
++#define MT6397_VSRMCA15_CON3 0x0240
++#define MT6397_VSRMCA15_CON4 0x0242
++#define MT6397_VSRMCA15_CON5 0x0244
++#define MT6397_VSRMCA15_CON6 0x0246
++#define MT6397_VSRMCA15_CON7 0x0248
++#define MT6397_VSRMCA15_CON8 0x024A
++#define MT6397_VSRMCA15_CON9 0x024C
++#define MT6397_VSRMCA15_CON10 0x024E
++#define MT6397_VSRMCA15_CON11 0x0250
++#define MT6397_VSRMCA15_CON12 0x0252
++#define MT6397_VSRMCA15_CON13 0x0254
++#define MT6397_VSRMCA15_CON14 0x0256
++#define MT6397_VSRMCA15_CON15 0x0258
++#define MT6397_VSRMCA15_CON16 0x025A
++#define MT6397_VSRMCA15_CON17 0x025C
++#define MT6397_VSRMCA15_CON18 0x025E
++#define MT6397_VSRMCA15_CON19 0x0260
++#define MT6397_VSRMCA15_CON20 0x0262
++#define MT6397_VSRMCA15_CON21 0x0264
++#define MT6397_VCORE_CON0 0x0266
++#define MT6397_VCORE_CON1 0x0268
++#define MT6397_VCORE_CON2 0x026A
++#define MT6397_VCORE_CON3 0x026C
++#define MT6397_VCORE_CON4 0x026E
++#define MT6397_VCORE_CON5 0x0270
++#define MT6397_VCORE_CON6 0x0272
++#define MT6397_VCORE_CON7 0x0274
++#define MT6397_VCORE_CON8 0x0276
++#define MT6397_VCORE_CON9 0x0278
++#define MT6397_VCORE_CON10 0x027A
++#define MT6397_VCORE_CON11 0x027C
++#define MT6397_VCORE_CON12 0x027E
++#define MT6397_VCORE_CON13 0x0280
++#define MT6397_VCORE_CON14 0x0282
++#define MT6397_VCORE_CON15 0x0284
++#define MT6397_VCORE_CON16 0x0286
++#define MT6397_VCORE_CON17 0x0288
++#define MT6397_VCORE_CON18 0x028A
++#define MT6397_VGPU_CON0 0x028C
++#define MT6397_VGPU_CON1 0x028E
++#define MT6397_VGPU_CON2 0x0290
++#define MT6397_VGPU_CON3 0x0292
++#define MT6397_VGPU_CON4 0x0294
++#define MT6397_VGPU_CON5 0x0296
++#define MT6397_VGPU_CON6 0x0298
++#define MT6397_VGPU_CON7 0x029A
++#define MT6397_VGPU_CON8 0x029C
++#define MT6397_VGPU_CON9 0x029E
++#define MT6397_VGPU_CON10 0x02A0
++#define MT6397_VGPU_CON11 0x02A2
++#define MT6397_VGPU_CON12 0x02A4
++#define MT6397_VGPU_CON13 0x02A6
++#define MT6397_VGPU_CON14 0x02A8
++#define MT6397_VGPU_CON15 0x02AA
++#define MT6397_VGPU_CON16 0x02AC
++#define MT6397_VGPU_CON17 0x02AE
++#define MT6397_VGPU_CON18 0x02B0
++#define MT6397_VIO18_CON0 0x0300
++#define MT6397_VIO18_CON1 0x0302
++#define MT6397_VIO18_CON2 0x0304
++#define MT6397_VIO18_CON3 0x0306
++#define MT6397_VIO18_CON4 0x0308
++#define MT6397_VIO18_CON5 0x030A
++#define MT6397_VIO18_CON6 0x030C
++#define MT6397_VIO18_CON7 0x030E
++#define MT6397_VIO18_CON8 0x0310
++#define MT6397_VIO18_CON9 0x0312
++#define MT6397_VIO18_CON10 0x0314
++#define MT6397_VIO18_CON11 0x0316
++#define MT6397_VIO18_CON12 0x0318
++#define MT6397_VIO18_CON13 0x031A
++#define MT6397_VIO18_CON14 0x031C
++#define MT6397_VIO18_CON15 0x031E
++#define MT6397_VIO18_CON16 0x0320
++#define MT6397_VIO18_CON17 0x0322
++#define MT6397_VIO18_CON18 0x0324
++#define MT6397_VPCA7_CON0 0x0326
++#define MT6397_VPCA7_CON1 0x0328
++#define MT6397_VPCA7_CON2 0x032A
++#define MT6397_VPCA7_CON3 0x032C
++#define MT6397_VPCA7_CON4 0x032E
++#define MT6397_VPCA7_CON5 0x0330
++#define MT6397_VPCA7_CON6 0x0332
++#define MT6397_VPCA7_CON7 0x0334
++#define MT6397_VPCA7_CON8 0x0336
++#define MT6397_VPCA7_CON9 0x0338
++#define MT6397_VPCA7_CON10 0x033A
++#define MT6397_VPCA7_CON11 0x033C
++#define MT6397_VPCA7_CON12 0x033E
++#define MT6397_VPCA7_CON13 0x0340
++#define MT6397_VPCA7_CON14 0x0342
++#define MT6397_VPCA7_CON15 0x0344
++#define MT6397_VPCA7_CON16 0x0346
++#define MT6397_VPCA7_CON17 0x0348
++#define MT6397_VPCA7_CON18 0x034A
++#define MT6397_VSRMCA7_CON0 0x034C
++#define MT6397_VSRMCA7_CON1 0x034E
++#define MT6397_VSRMCA7_CON2 0x0350
++#define MT6397_VSRMCA7_CON3 0x0352
++#define MT6397_VSRMCA7_CON4 0x0354
++#define MT6397_VSRMCA7_CON5 0x0356
++#define MT6397_VSRMCA7_CON6 0x0358
++#define MT6397_VSRMCA7_CON7 0x035A
++#define MT6397_VSRMCA7_CON8 0x035C
++#define MT6397_VSRMCA7_CON9 0x035E
++#define MT6397_VSRMCA7_CON10 0x0360
++#define MT6397_VSRMCA7_CON11 0x0362
++#define MT6397_VSRMCA7_CON12 0x0364
++#define MT6397_VSRMCA7_CON13 0x0366
++#define MT6397_VSRMCA7_CON14 0x0368
++#define MT6397_VSRMCA7_CON15 0x036A
++#define MT6397_VSRMCA7_CON16 0x036C
++#define MT6397_VSRMCA7_CON17 0x036E
++#define MT6397_VSRMCA7_CON18 0x0370
++#define MT6397_VSRMCA7_CON19 0x0372
++#define MT6397_VSRMCA7_CON20 0x0374
++#define MT6397_VSRMCA7_CON21 0x0376
++#define MT6397_VDRM_CON0 0x0378
++#define MT6397_VDRM_CON1 0x037A
++#define MT6397_VDRM_CON2 0x037C
++#define MT6397_VDRM_CON3 0x037E
++#define MT6397_VDRM_CON4 0x0380
++#define MT6397_VDRM_CON5 0x0382
++#define MT6397_VDRM_CON6 0x0384
++#define MT6397_VDRM_CON7 0x0386
++#define MT6397_VDRM_CON8 0x0388
++#define MT6397_VDRM_CON9 0x038A
++#define MT6397_VDRM_CON10 0x038C
++#define MT6397_VDRM_CON11 0x038E
++#define MT6397_VDRM_CON12 0x0390
++#define MT6397_VDRM_CON13 0x0392
++#define MT6397_VDRM_CON14 0x0394
++#define MT6397_VDRM_CON15 0x0396
++#define MT6397_VDRM_CON16 0x0398
++#define MT6397_VDRM_CON17 0x039A
++#define MT6397_VDRM_CON18 0x039C
++#define MT6397_BUCK_K_CON0 0x039E
++#define MT6397_BUCK_K_CON1 0x03A0
++#define MT6397_ANALDO_CON0 0x0400
++#define MT6397_ANALDO_CON1 0x0402
++#define MT6397_ANALDO_CON2 0x0404
++#define MT6397_ANALDO_CON3 0x0406
++#define MT6397_ANALDO_CON4 0x0408
++#define MT6397_ANALDO_CON5 0x040A
++#define MT6397_ANALDO_CON6 0x040C
++#define MT6397_ANALDO_CON7 0x040E
++#define MT6397_DIGLDO_CON0 0x0410
++#define MT6397_DIGLDO_CON1 0x0412
++#define MT6397_DIGLDO_CON2 0x0414
++#define MT6397_DIGLDO_CON3 0x0416
++#define MT6397_DIGLDO_CON4 0x0418
++#define MT6397_DIGLDO_CON5 0x041A
++#define MT6397_DIGLDO_CON6 0x041C
++#define MT6397_DIGLDO_CON7 0x041E
++#define MT6397_DIGLDO_CON8 0x0420
++#define MT6397_DIGLDO_CON9 0x0422
++#define MT6397_DIGLDO_CON10 0x0424
++#define MT6397_DIGLDO_CON11 0x0426
++#define MT6397_DIGLDO_CON12 0x0428
++#define MT6397_DIGLDO_CON13 0x042A
++#define MT6397_DIGLDO_CON14 0x042C
++#define MT6397_DIGLDO_CON15 0x042E
++#define MT6397_DIGLDO_CON16 0x0430
++#define MT6397_DIGLDO_CON17 0x0432
++#define MT6397_DIGLDO_CON18 0x0434
++#define MT6397_DIGLDO_CON19 0x0436
++#define MT6397_DIGLDO_CON20 0x0438
++#define MT6397_DIGLDO_CON21 0x043A
++#define MT6397_DIGLDO_CON22 0x043C
++#define MT6397_DIGLDO_CON23 0x043E
++#define MT6397_DIGLDO_CON24 0x0440
++#define MT6397_DIGLDO_CON25 0x0442
++#define MT6397_DIGLDO_CON26 0x0444
++#define MT6397_DIGLDO_CON27 0x0446
++#define MT6397_DIGLDO_CON28 0x0448
++#define MT6397_DIGLDO_CON29 0x044A
++#define MT6397_DIGLDO_CON30 0x044C
++#define MT6397_DIGLDO_CON31 0x044E
++#define MT6397_DIGLDO_CON32 0x0450
++#define MT6397_DIGLDO_CON33 0x045A
++#define MT6397_SPK_CON0 0x0600
++#define MT6397_SPK_CON1 0x0602
++#define MT6397_SPK_CON2 0x0604
++#define MT6397_SPK_CON3 0x0606
++#define MT6397_SPK_CON4 0x0608
++#define MT6397_SPK_CON5 0x060A
++#define MT6397_SPK_CON6 0x060C
++#define MT6397_SPK_CON7 0x060E
++#define MT6397_SPK_CON8 0x0610
++#define MT6397_SPK_CON9 0x0612
++#define MT6397_SPK_CON10 0x0614
++#define MT6397_SPK_CON11 0x0616
++#define MT6397_AUDDAC_CON0 0x0700
++#define MT6397_AUDBUF_CFG0 0x0702
++#define MT6397_AUDBUF_CFG1 0x0704
++#define MT6397_AUDBUF_CFG2 0x0706
++#define MT6397_AUDBUF_CFG3 0x0708
++#define MT6397_AUDBUF_CFG4 0x070A
++#define MT6397_IBIASDIST_CFG0 0x070C
++#define MT6397_AUDACCDEPOP_CFG0 0x070E
++#define MT6397_AUD_IV_CFG0 0x0710
++#define MT6397_AUDCLKGEN_CFG0 0x0712
++#define MT6397_AUDLDO_CFG0 0x0714
++#define MT6397_AUDLDO_CFG1 0x0716
++#define MT6397_AUDNVREGGLB_CFG0 0x0718
++#define MT6397_AUD_NCP0 0x071A
++#define MT6397_AUDPREAMP_CON0 0x071C
++#define MT6397_AUDADC_CON0 0x071E
++#define MT6397_AUDADC_CON1 0x0720
++#define MT6397_AUDADC_CON2 0x0722
++#define MT6397_AUDADC_CON3 0x0724
++#define MT6397_AUDADC_CON4 0x0726
++#define MT6397_AUDADC_CON5 0x0728
++#define MT6397_AUDADC_CON6 0x072A
++#define MT6397_AUDDIGMI_CON0 0x072C
++#define MT6397_AUDLSBUF_CON0 0x072E
++#define MT6397_AUDLSBUF_CON1 0x0730
++#define MT6397_AUDENCSPARE_CON0 0x0732
++#define MT6397_AUDENCCLKSQ_CON0 0x0734
++#define MT6397_AUDPREAMPGAIN_CON0 0x0736
++#define MT6397_ZCD_CON0 0x0738
++#define MT6397_ZCD_CON1 0x073A
++#define MT6397_ZCD_CON2 0x073C
++#define MT6397_ZCD_CON3 0x073E
++#define MT6397_ZCD_CON4 0x0740
++#define MT6397_ZCD_CON5 0x0742
++#define MT6397_NCP_CLKDIV_CON0 0x0744
++#define MT6397_NCP_CLKDIV_CON1 0x0746
++
++#endif /* __MFD_MT6397_REGISTERS_H__ */
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0060-arm-mediatek-select-the-arm-timer-by-default.patch b/target/linux/mediatek/patches/0060-arm-mediatek-select-the-arm-timer-by-default.patch
new file mode 100644
index 0000000000..2b6418613d
--- /dev/null
+++ b/target/linux/mediatek/patches/0060-arm-mediatek-select-the-arm-timer-by-default.patch
@@ -0,0 +1,26 @@
+From 46c695d8285b73d39b0e16fcfd7da332fd2398d4 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 13:00:27 +0200
+Subject: [PATCH 60/76] arm: mediatek: select the arm timer by default
+
+select ARM_ARCH_TIMER inside the Kconfig
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/arm/mach-mediatek/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig
+index 9f59e58..7704818 100644
+--- a/arch/arm/mach-mediatek/Kconfig
++++ b/arch/arm/mach-mediatek/Kconfig
+@@ -1,5 +1,6 @@
+ menuconfig ARCH_MEDIATEK
+ bool "Mediatek MT65xx & MT81xx SoC" if ARCH_MULTI_V7
++ select ARM_ARCH_TIMER
+ select ARM_GIC
+ select PINCTRL
+ select MTK_TIMER
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0061-arm-mediatek-add-mt7623-clock.patch b/target/linux/mediatek/patches/0061-arm-mediatek-add-mt7623-clock.patch
new file mode 100644
index 0000000000..f12ebb14cf
--- /dev/null
+++ b/target/linux/mediatek/patches/0061-arm-mediatek-add-mt7623-clock.patch
@@ -0,0 +1,846 @@
+From 7342787e992a70443081b9203d2131cbf6bc3562 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 13:12:38 +0200
+Subject: [PATCH 61/76] arm: mediatek: add mt7623 clock
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/clk/mediatek/Makefile | 1 +
+ drivers/clk/mediatek/clk-mt7623.c | 634 ++++++++++++++++++++++++++++++++
+ include/dt-bindings/clock/mt7623-clk.h | 173 +++++++++
+ 3 files changed, 808 insertions(+)
+ create mode 100644 drivers/clk/mediatek/clk-mt7623.c
+ create mode 100644 include/dt-bindings/clock/mt7623-clk.h
+
+diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
+index 8e4b2a4..19a3763 100644
+--- a/drivers/clk/mediatek/Makefile
++++ b/drivers/clk/mediatek/Makefile
+@@ -1,4 +1,5 @@
+ obj-y += clk-mtk.o clk-pll.o clk-gate.o
+ obj-$(CONFIG_RESET_CONTROLLER) += reset.o
++obj-y += clk-mt7623.o
+ obj-y += clk-mt8135.o
+ obj-y += clk-mt8173.o
+diff --git a/drivers/clk/mediatek/clk-mt7623.c b/drivers/clk/mediatek/clk-mt7623.c
+new file mode 100644
+index 0000000..07843bb
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-mt7623.c
+@@ -0,0 +1,634 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/of.h>
++#include <linux/of_address.h>
++#include <linux/slab.h>
++#include <linux/mfd/syscon.h>
++#include <dt-bindings/clock/mt7623-clk.h>
++
++#include "clk-mtk.h"
++#include "clk-gate.h"
++
++static DEFINE_SPINLOCK(mt7623_clk_lock);
++
++static struct clk_onecell_data *mt7623_top_clk_data;
++static struct clk_onecell_data *mt7623_pll_clk_data;
++
++static void mtk_clk_enable_critical(void)
++{
++ if (!mt7623_top_clk_data || !mt7623_pll_clk_data)
++ return;
++
++ clk_prepare_enable(mt7623_pll_clk_data->clks[CLK_APMIXED_ARMPLL]);
++ clk_prepare_enable(mt7623_top_clk_data->clks[CLK_TOP_MEM_SEL]);
++ clk_prepare_enable(mt7623_top_clk_data->clks[CLK_TOP_DDR_SEL]);
++ clk_prepare_enable(mt7623_top_clk_data->clks[CLK_TOP_RTC_SEL]);
++}
++
++static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
++ FACTOR(CLK_TOP_DSI0_LNTC_DSICLK, "dsi0_lntc_dsiclk", "clk_null", 1, 1),
++ FACTOR(CLK_TOP_HDMITX_CLKDIG_CTS, "hdmitx_clkdig_cts", "clk_null", 1, 1),
++ FACTOR(CLK_TOP_CLKPH_MCK, "clkph_mck", "clk_null", 1, 1),
++ FACTOR(CLK_TOP_CPUM_TCK_IN, "cpum_tck_in", "clk_null", 1, 1),
++};
++
++static const struct mtk_fixed_factor top_divs[] __initconst = {
++ FACTOR(CLK_TOP_MAINPLL_806M, "mainpll_650m", "mainpll", 1, 2),
++ FACTOR(CLK_TOP_MAINPLL_537P3M, "mainpll_433p3m", "mainpll", 1, 3),
++ FACTOR(CLK_TOP_MAINPLL_322P4M, "mainpll_260m", "mainpll", 1, 5),
++ FACTOR(CLK_TOP_MAINPLL_230P3M, "mainpll_185p6m", "mainpll", 1, 7),
++
++ FACTOR(CLK_TOP_UNIVPLL_624M, "univpll_624m", "univpll", 1, 2),
++ FACTOR(CLK_TOP_UNIVPLL_416M, "univpll_416m", "univpll", 1, 3),
++ FACTOR(CLK_TOP_UNIVPLL_249P6M, "univpll_249p6m", "univpll", 1, 5),
++ FACTOR(CLK_TOP_UNIVPLL_178P3M, "univpll_178p3m", "univpll", 1, 7),
++ FACTOR(CLK_TOP_UNIVPLL_48M, "univpll_48m", "univpll", 1, 26),
++
++ FACTOR(CLK_TOP_AUDPLL_D4, "audpll_d4", "audpll", 1, 4),
++ FACTOR(CLK_TOP_AUDPLL_D8, "audpll_d8", "audpll", 1, 8),
++ FACTOR(CLK_TOP_AUDPLL_D16, "audpll_d16", "audpll", 1, 16),
++ FACTOR(CLK_TOP_AUDPLL_24, "audpll_d24", "audpll", 1, 24),
++
++ FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
++ FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
++ FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
++ FACTOR(CLK_TOP_LVDS_ETH, "lvdspll_eth", "lvdspll", 1, 16),
++
++ FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
++
++ FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
++
++ FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "mainpll_650m", 1, 2),
++ FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "mainpll_650m", 1, 4),
++ FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "mainpll_650m", 1, 8),
++ FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "mainpll_650m", 1, 16),
++ FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "mainpll_650m", 1, 2),
++ FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "mainpll_650m", 1, 4),
++ FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "mainpll_650m", 1, 8),
++ FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "mainpll_650m", 1, 2),
++ FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "mainpll_650m", 1, 4),
++ FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "mainpll_650m", 1, 2),
++ FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "mainpll_650m", 1, 4),
++ FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll_433p3m", 1, 1),
++ FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll_260m", 1, 1),
++ FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll_185p6m", 1, 1),
++
++ FACTOR(CLK_TOP_TVDPLL_d2, "tvdpll_d2", "tvdpll", 1, 2),
++ FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4),
++
++ FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_624m", 1, 2),
++ FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_624m", 1, 4),
++ FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_624m", 1, 8),
++ FACTOR(CLK_TOP_UNIVPLL1_D10, "univpll1_d10", "univpll_624m", 1, 10),
++
++ FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_416m", 1, 2),
++ FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_416m", 1, 4),
++ FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_416m", 1, 8),
++
++ FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_624m", 1, 2),
++ FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_624m", 1, 4),
++ FACTOR(CLK_TOP_UNIVPLL1_D6, "univpll1_d6", "univpll_624m", 1, 6),
++ FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_624m", 1, 8),
++ FACTOR(CLK_TOP_UNIVPLL1_D10, "univpll1_d10", "univpll_624m", 1, 10),
++
++ FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_416m", 1, 2),
++ FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_416m", 1, 4),
++ FACTOR(CLK_TOP_UNIVPLL2_D6, "univpll2_d6", "univpll_416m", 1, 6),
++ FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_416m", 1, 8),
++
++ FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll_249p6m", 1, 1),
++ FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll_48m", 1, 1),
++
++
++ FACTOR(CLK_TOP_MEMPLL_MCK_D4, "mempll_mck_d4", "clkph_mck", 1, 4),
++};
++
++static const char * const axi_parents[] __initconst = {
++ "clk26m",
++ "syspll1_d2",
++ "syspll_d5",
++ "syspll1_d4",
++ "univpll_d5",
++ "univpll2_d2",
++ "dmpll_ck",
++ "dmpll_d2"
++};
++
++static const char * const mem_parents[] __initconst = {
++ "clk26m",
++ "dmpll_ck",
++};
++
++static const char * const ddr_parents[] __initconst = {
++ "clk26m",
++ "syspll1_d8",
++};
++
++static const char * const mm_parents[] __initconst = {
++ "clk26m",
++ "clk26m",
++ "vencpll_ck",
++ "syspll1_d2",
++ "syspll1_d4",
++ "univpll_d5",
++ "univpll1_d2",
++ "univpll2_d2",
++ "dmpll_ck"
++};
++
++static const char * const pwm_parents[] __initconst = {
++ "clk26m",
++ "univpll2_d4",
++ "univpll3_d2",
++ "univpll1_d4",
++};
++
++static const char * const vdec_parents[] __initconst = {
++ "clk26m",
++ "syspll1_d2",
++ "syspll_d5",
++ "syspll1_d4",
++ "univpll_d5",
++ "univpll2_d2",
++ "univpll2_d4",
++ "msdcpll_d2",
++ "mmpll_d2",
++};
++
++static const char * const mfg_parents[] __initconst = {
++ "clk26m",
++ "mmpll_ck",
++ "dmpll_x2_ck",
++ "msdcpll_ck",
++ "clk26m",
++ "syspll_d3",
++ "univpll_d3",
++ "univpll1_d2",
++};
++
++static const char * const cam_parents[] __initconst = {
++ "clk26m",
++ "univpll_d26",
++ "univpll2_d2",
++ "syspll3_d2",
++ "syspll3_d4",
++ "msdcpll_d2",
++ "mmpll_d2",
++ "clk26m",
++};
++
++static const char * const uart_parents[] __initconst = {
++ "clk26m",
++ "univpll2_d8",
++};
++
++static const char * const spi_parents[] __initconst = {
++ "clk26m",
++ "syspll3_d2",
++ "syspll4_d2",
++ "univpll2_d4",
++ "univpll1_d8",
++};
++
++static const char * const usb20_parents[] __initconst = {
++ "clk26m",
++ "univpll1_d8",
++ "univpll3_d4",
++ "clk26m",
++};
++
++static const char * const msdc_30_0_parents[] __initconst = {
++ "clk26m",
++ "msdcpll_d2",
++ "syspll2_d2",
++ "syspll1_d4",
++ "univpll1_d4",
++ "univpll2_d4",
++ "clk26m",
++ "clk26m",
++};
++
++static const char * const msdc_30_1_parents[] __initconst = {
++ "clk26m",
++ "msdcpll_d2",
++ "syspll2_d2",
++ "syspll1_d4",
++ "univpll1_d4",
++ "univpll2_d4",
++ "clk26m",
++ "clk26m",
++};
++
++static const char * const msdc_30_2_parents[] __initconst = {
++ "clk26m",
++ "msdcpll_d2",
++ "syspll2_d2",
++ "syspll1_d4",
++ "univpll1_d4",
++ "univpll2_d4",
++ "clk26m",
++ "clk26m",
++};
++
++static const char * const audio_parents[] __initconst = {
++ "f_f26m_ck",
++ "syspll1_d16",
++};
++
++static const char * const audio_intbus_parents[] __initconst = {
++ "clk26m",
++ "syspll1_d4",
++ "syspll3_d2",
++ "syspll4_d2",
++ "univpll3_d2",
++ "univpll2_d4",
++};
++
++static const char * const pmic_spi_parents[] __initconst = {
++ "clk26m",
++ "syspll1_d8",
++ "syspll2_d4",
++ "syspll4_d2",
++ "syspll3_d4",
++ "syspll2_d8",
++ "syspll1_d16",
++ "univpll3_d4",
++ "univpll_d26",
++ "dmpll_d2",
++ "dmpll_d4",
++};
++
++static const char * const scp_parents[] __initconst = {
++ "clk26m",
++ "syspll1_d8",
++ "dmpll_d2",
++ "dmpll_d4",
++};
++
++static const char * const dpi0_parents[] __initconst = {
++ "clk26m",
++ "mipipll",
++ "mipipll_d2",
++ "mipipll_d4",
++ "lvdspll",
++ "lvdspll_d2",
++ "lvdspll_d4",
++ "lvdspll_d8",
++};
++
++static const char * const dpi1_parents[] __initconst = {
++ "clk26m",
++ "tvdpll",
++ "tvdpll_d2",
++ "tvdpll_d4",
++};
++
++static const char * const tve_parents[] __initconst = {
++ "clk26m",
++ "mipipll",
++ "mipipll_d2",
++ "mipipll_d4",
++ "clk26m",
++ "tvdpll",
++ "tvdpll_d2",
++ "tvdpll_d4",
++};
++
++static const char * const apll_parents[] __initconst = {
++ "clk26m",
++ "audpll",
++ "audpll_d4",
++ "audpll_d8",
++ "audpll_d16",
++ "audpll_d24",
++ "clk26m",
++ "clk26m",
++};
++
++static const char * const dpilvds_parents[] __initconst = {
++ "clk26m",
++ "lvdspll",
++ "lvdspll_d2",
++ "lvdspll_d4",
++ "lvdspll_d8",
++ "fpc_ck",
++ "clk26m",
++ "clk26m",
++};
++
++static const char * const rtc_parents[] __initconst = {
++ "clk32k",
++ "external_32k",
++ "clk26m",
++ "univpll3_d8",
++};
++
++static const char * const nfi2x_parents[] __initconst = {
++ "clk26m",
++ "syspll2_d2",
++ "syspll_d7",
++ "univpll3_d2",
++ "syspll2_d4",
++ "univpll3_d4",
++ "syspll4_d4",
++ "clk26m",
++};
++
++static const char * const eth_parents[] __initconst = {
++ "clk26m",
++ "syspll3_d4",
++ "univpll2_d8",
++ "lvdspll_eth",
++ "univpll_d26",
++ "syspll2_d8",
++ "syspll4_d4",
++ "univpll3_d8",
++};
++
++static const struct mtk_composite top_muxes[] __initconst = {
++ /* CLK_CFG_0 */
++ MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
++ 0x0140, 0, 3, INVALID_MUX_GATE_BIT),
++ MUX_GATE(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0040, 8, 2, 15),
++ MUX_GATE(CLK_TOP_DDR_SEL, "ddr_sel", ddr_parents, 0x0040, 16, 2, 23),
++ MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", mm_parents,
++ 0x0140, 24, 3, INVALID_MUX_GATE_BIT),
++ /* CLK_CFG_1 */
++ MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x0050, 0, 2, 7),
++ MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x0050, 8, 4, 15),
++ MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0050, 16, 3, 23),
++ MUX_GATE(CLK_TOP_CAM_SEL, "cam_sel", cam_parents, 0x0050, 24, 3, 31),
++ /* CLK_CFG_2 */
++ MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0060, 0, 1, 7),
++ MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0060, 8, 3, 15),
++ MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x0060, 16, 2, 23),
++ MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc_30_0_sel", msdc_30_0_parents, 0x0060, 24, 3, 31),
++ /* CLK_CFG_3 */
++ MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc_30_1_sel", msdc_30_1_parents, 0x0070, 0, 3, 7),
++ MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc_30_2_sel", msdc_30_2_parents, 0x0070, 8, 3, 15),
++ MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0070, 16, 1, 23),
++ MUX_GATE(CLK_TOP_AUDIO_INTBUS_SEL,
++ "audio_intbus_sel", audio_intbus_parents, 0x0070, 24, 3, 31),
++ /* CLK_CFG_4 */
++ MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmic_spi_parents, 0x0080, 0, 4, 7),
++ MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, 0x0080, 8, 2, 15),
++ MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x0080, 16, 3, 23),
++ MUX_GATE(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents, 0x0080, 24, 2, 31),
++ /* CLK_CFG_5 */
++ MUX_GATE(CLK_TOP_TVE_SEL, "tve_sel", tve_parents, 0x0090, 0, 3, 7),
++ MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents, 0x0090, 16, 3, 23),
++ MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x0090, 24, 3, 31),
++ /* CLK_CFG_6 */
++ MUX_GATE(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x00a0, 0, 2, 7),
++ MUX_GATE(CLK_TOP_NFI2X_SEL, "nfi2x_sel", nfi2x_parents, 0x00a0, 8, 3, 15),
++ MUX_GATE(CLK_TOP_ETH_SEL, "eth_sel", eth_parents, 0x00a0, 16, 3, 23),
++};
++
++static const struct mtk_gate_regs infra_cg_regs = {
++ .set_ofs = 0x0040,
++ .clr_ofs = 0x0044,
++ .sta_ofs = 0x0048,
++};
++
++#define GATE_ICG(_id, _name, _parent, _shift) { \
++ .id = _id, \
++ .name = _name, \
++ .parent_name = _parent, \
++ .regs = &infra_cg_regs, \
++ .shift = _shift, \
++ .ops = &mtk_clk_gate_ops_setclr, \
++ }
++
++static const struct mtk_gate infra_clks[] __initconst = {
++ GATE_ICG(CLK_INFRA_DBGCLK, "dbgclk_ck", "axi_sel", 0),
++ GATE_ICG(CLK_INFRA_SMI, "smi_ck", "smi_sel", 1),
++ GATE_ICG(CLK_INFRA_AUDIO, "audio_ck", "aud_intbus_sel", 5),
++ GATE_ICG(CLK_INFRA_EFUSE, "efuse_ck", "axi_sel", 5),
++ GATE_ICG(CLK_INFRA_EFUSE, "l2c_sram_ck", "axi_sel", 5),
++ GATE_ICG(CLK_INFRA_M4U, "m4u_ck", "mem_sel", 8),
++ GATE_ICG(CLK_INFRA_CONNMCU, "connmcu_ck", "axi_sel", 8),
++ GATE_ICG(CLK_INFRA_TRNG, "trng_ck", "axi_sel", 8),
++ GATE_ICG(CLK_INFRA_CPUM, "cpum_ck", "cpum_tck_in", 15),
++ GATE_ICG(CLK_INFRA_KP, "kp_ck", "axi_sel", 16),
++ GATE_ICG(CLK_INFRA_CEC, "cec_ck", "axi_sel", 16),
++ GATE_ICG(CLK_INFRA_IRRX, "irrx_ck", "axi_sel", 16),
++ GATE_ICG(CLK_INFRA_PMICSPI, "pmicspi_ck", "pmicspi_sel", 22),
++ GATE_ICG(CLK_INFRA_PMIC_WRAP, "pmic_wrap_ck", "axi_sel", 23),
++};
++
++static const struct mtk_gate_regs peri0_cg_regs = {
++ .set_ofs = 0x0008,
++ .clr_ofs = 0x0010,
++ .sta_ofs = 0x0018,
++};
++
++static const struct mtk_gate_regs peri1_cg_regs = {
++ .set_ofs = 0x000c,
++ .clr_ofs = 0x0014,
++ .sta_ofs = 0x001c,
++};
++
++#define GATE_PERI0(_id, _name, _parent, _shift) { \
++ .id = _id, \
++ .name = _name, \
++ .parent_name = _parent, \
++ .regs = &peri0_cg_regs, \
++ .shift = _shift, \
++ .ops = &mtk_clk_gate_ops_setclr, \
++ }
++
++#define GATE_PERI1(_id, _name, _parent, _shift) { \
++ .id = _id, \
++ .name = _name, \
++ .parent_name = _parent, \
++ .regs = &peri1_cg_regs, \
++ .shift = _shift, \
++ .ops = &mtk_clk_gate_ops_setclr, \
++ }
++
++static const struct mtk_gate peri_gates[] __initconst = {
++ /* PERI0 */
++ GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "axi_sel", 0),
++ GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1),
++ GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axi_sel", 2),
++ GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axi_sel", 3),
++ GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axi_sel", 4),
++ GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axi_sel", 5),
++ GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axi_sel", 6),
++ GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axi_sel", 7),
++ GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axi_sel", 8),
++ GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9),
++ GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10),
++ GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11),
++ GATE_PERI0(CLK_PERI_AP_DMA, "ap_dma_ck", "axi_sel", 12),
++ GATE_PERI0(CLK_PERI_MSDC20_1, "msdc_20_1_ck", "msdc_30_0_sel", 13),
++ GATE_PERI0(CLK_PERI_MSDC20_2, "msdc_20_2_ck", "msdc_30_1_sel", 14),
++ GATE_PERI0(CLK_PERI_MSDC30_1, "msdc_30_1_ck", "msdc_30_2_sel", 15),
++ GATE_PERI0(CLK_PERI_NLI, "nli_ck", "axi_sel", 16),
++ GATE_PERI0(CLK_PERI_UART0, "uart0_ck", "axi_sel", 17),
++ GATE_PERI0(CLK_PERI_UART1, "uart1_ck", "axi_sel", 18),
++ GATE_PERI0(CLK_PERI_UART2, "uart2_ck", "axi_sel", 19),
++ GATE_PERI0(CLK_PERI_UART3, "uart3_ck", "axi_sel", 20),
++ GATE_PERI0(CLK_PERI_BTIF, "btif_ck", "axi_sel", 21),
++ GATE_PERI0(CLK_PERI_I2C0, "i2c0_ck", "axi_sel", 22),
++ GATE_PERI0(CLK_PERI_I2C1, "i2c1_ck", "axi_sel", 23),
++ GATE_PERI0(CLK_PERI_I2C2, "i2c2_ck", "axi_sel", 24),
++ GATE_PERI0(CLK_PERI_I2C3, "i2c3_ck", "axi_sel", 25),
++ GATE_PERI0(CLK_PERI_AUXADC, "auxadc_ck", "axi_sel", 26),
++ GATE_PERI0(CLK_PERI_SPI0, "spi0_ck", "spi0_sel", 27),
++ GATE_PERI0(CLK_PERI_ETH, "eth_ck", "eth_sel", 28),
++ GATE_PERI0(CLK_PERI_USB0_MCU, "usb0_mcu", "axi_sel", 29),
++ GATE_PERI0(CLK_PERI_USB1_MCU, "usb1_mcu","axi_sel", 30),
++ GATE_PERI0(CLK_PERI_USB_SLV, "usb_slv", "axi_sel", 31),
++
++ /* PERI1 */
++ GATE_PERI1(CLK_PERI_GCPU, "gcpu_ck", "axi_sel", 0),
++ GATE_PERI1(CLK_PERI_NFI_ECC, "nfi_ecc_ck", "axi_sel", 1),
++ GATE_PERI1(CLK_PERI_NFI_PAD, "nfi_pad_ck", "axi_sel", 2),
++};
++
++static const char * const uart_ck_sel_parents[] __initconst = {
++ "clk26m",
++ "uart_sel",
++};
++
++static const struct mtk_composite peri_clks[] __initconst = {
++ MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1),
++ MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1),
++ MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1),
++ MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
++};
++
++static void __init mtk_topckgen_init(struct device_node *node)
++{
++ struct clk_onecell_data *clk_data;
++ void __iomem *base;
++ int r;
++
++ base = of_iomap(node, 0);
++ if (!base) {
++ pr_err("%s(): ioremap failed\n", __func__);
++ return;
++ }
++
++ mt7623_top_clk_data = clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
++
++ mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
++ mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
++ mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
++ &mt7623_clk_lock, clk_data);
++
++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++ if (r)
++ pr_err("%s(): could not register clock provider: %d\n",
++ __func__, r);
++
++ mtk_clk_enable_critical();
++}
++CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt7623-topckgen", mtk_topckgen_init);
++
++static void __init mtk_infrasys_init(struct device_node *node)
++{
++ struct clk_onecell_data *clk_data;
++ int r;
++
++ clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
++
++ mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
++ clk_data);
++
++ clk_prepare_enable(clk_data->clks[CLK_INFRA_M4U]);
++
++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++ if (r)
++ pr_err("%s(): could not register clock provider: %d\n",
++ __func__, r);
++
++ mtk_register_reset_controller(node, 2, 0x30);
++}
++CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt7623-infracfg", mtk_infrasys_init);
++
++static void __init mtk_pericfg_init(struct device_node *node)
++{
++ struct clk_onecell_data *clk_data;
++ int r;
++ void __iomem *base;
++
++ base = of_iomap(node, 0);
++ if (!base) {
++ pr_err("%s(): ioremap failed\n", __func__);
++ return;
++ }
++
++ clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
++
++ mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates),
++ clk_data);
++ mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base,
++ &mt7623_clk_lock, clk_data);
++
++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++ if (r)
++ pr_err("%s(): could not register clock provider: %d\n",
++ __func__, r);
++
++ mtk_register_reset_controller(node, 2, 0);
++}
++CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt7623-pericfg", mtk_pericfg_init);
++
++#define MT7623_PLL_FMAX (2000 * MHZ)
++#define CON0_MT7623_RST_BAR BIT(27)
++
++#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \
++ .id = _id, \
++ .name = _name, \
++ .reg = _reg, \
++ .pwr_reg = _pwr_reg, \
++ .en_mask = _en_mask, \
++ .flags = _flags, \
++ .rst_bar_mask = CON0_MT7623_RST_BAR, \
++ .fmax = MT7623_PLL_FMAX, \
++ .pcwbits = _pcwbits, \
++ .pd_reg = _pd_reg, \
++ .pd_shift = _pd_shift, \
++ .tuner_reg = _tuner_reg, \
++ .pcw_reg = _pcw_reg, \
++ .pcw_shift = _pcw_shift, \
++ }
++
++static const struct mtk_pll_data plls[] = {
++ PLL(CLK_APMIXED_ARMPLL, "armpll", 0x200, 0x20c, 0x00000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
++ PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x210, 0x21c, 0x78000001, HAVE_RST_BAR, 21, 0x214, 6, 0x0, 0x214, 0),
++ PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x220, 0x22c, 0xFC000001, HAVE_RST_BAR, 7, 0x224, 6, 0x0, 0x224, 0),
++ PLL(CLK_APMIXED_MMPLL, "mmpll", 0x230, 0x23c, 0x00000001, 0, 21, 0x254, 6, 0x0, 0x258, 0),
++ PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 6, 0x0, 0x244, 0),
++ PLL(CLK_APMIXED_AUDPLL, "audpll", 0x250, 0x25c, 0x00000001, 0, 31, 0x2e8, 6, 0x2f8, 0x254, 0),
++ PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x260, 0x26c, 0x00000001, 0, 31, 0x294, 6, 0x0, 0x298, 0),
++ PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x270, 0x27c, 0x00000001, 0, 21, 0x2b0, 6, 0x0, 0x2b4, 0),
++};
++
++static void __init mtk_apmixedsys_init(struct device_node *node)
++{
++ struct clk_onecell_data *clk_data;
++
++ mt7623_pll_clk_data = clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls));
++ if (!clk_data)
++ return;
++
++ mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
++ mtk_clk_enable_critical();
++}
++CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt7623-apmixedsys",
++ mtk_apmixedsys_init);
+diff --git a/include/dt-bindings/clock/mt7623-clk.h b/include/dt-bindings/clock/mt7623-clk.h
+new file mode 100644
+index 0000000..cb1e8a9
+--- /dev/null
++++ b/include/dt-bindings/clock/mt7623-clk.h
+@@ -0,0 +1,173 @@
++/*
++ * Copyright c 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#ifndef _DT_BINDINGS_CLK_MT7623_H
++#define _DT_BINDINGS_CLK_MT7623_H
++
++/* TOPCKGEN */
++
++#define CLK_TOP_AUDPLL_24 1
++#define CLK_TOP_AUDPLL_D16 2
++#define CLK_TOP_AUDPLL_D4 3
++#define CLK_TOP_AUDPLL_D8 4
++#define CLK_TOP_CLKPH_MCK 5
++#define CLK_TOP_CPUM_TCK_IN 6
++#define CLK_TOP_DSI0_LNTC_DSICLK 7
++#define CLK_TOP_HDMITX_CLKDIG_CTS 8
++#define CLK_TOP_LVDS_ETH 9
++#define CLK_TOP_LVDSPLL_D2 10
++#define CLK_TOP_LVDSPLL_D4 11
++#define CLK_TOP_LVDSPLL_D8 12
++#define CLK_TOP_MAINPLL_230P3M 13
++#define CLK_TOP_MAINPLL_322P4M 14
++#define CLK_TOP_MAINPLL_537P3M 15
++#define CLK_TOP_MAINPLL_806M 16
++#define CLK_TOP_MEMPLL_MCK_D4 17
++#define CLK_TOP_MMPLL_D2 18
++#define CLK_TOP_MSDCPLL_D2 19
++#define CLK_TOP_SYSPLL1_D16 20
++#define CLK_TOP_SYSPLL1_D2 21
++#define CLK_TOP_SYSPLL1_D4 22
++#define CLK_TOP_SYSPLL1_D8 23
++#define CLK_TOP_SYSPLL2_D2 24
++#define CLK_TOP_SYSPLL2_D4 25
++#define CLK_TOP_SYSPLL2_D8 26
++#define CLK_TOP_SYSPLL3_D2 27
++#define CLK_TOP_SYSPLL3_D4 28
++#define CLK_TOP_SYSPLL4_D2 29
++#define CLK_TOP_SYSPLL4_D4 30
++#define CLK_TOP_SYSPLL_D3 31
++#define CLK_TOP_SYSPLL_D5 32
++#define CLK_TOP_SYSPLL_D7 33
++#define CLK_TOP_TVDPLL_d2 34
++#define CLK_TOP_TVDPLL_D4 35
++#define CLK_TOP_UNIVPLL_178P3M 36
++#define CLK_TOP_UNIVPLL1_D10 37
++#define CLK_TOP_UNIVPLL1_D2 38
++#define CLK_TOP_UNIVPLL1_D4 39
++#define CLK_TOP_UNIVPLL1_D6 40
++#define CLK_TOP_UNIVPLL1_D8 41
++#define CLK_TOP_UNIVPLL_249P6M 42
++#define CLK_TOP_UNIVPLL2_D2 43
++#define CLK_TOP_UNIVPLL2_D4 44
++#define CLK_TOP_UNIVPLL2_D6 45
++#define CLK_TOP_UNIVPLL2_D8 46
++#define CLK_TOP_UNIVPLL_416M 47
++#define CLK_TOP_UNIVPLL_48M 48
++#define CLK_TOP_UNIVPLL_624M 49
++#define CLK_TOP_UNIVPLL_D26 50
++#define CLK_TOP_UNIVPLL_D5 51
++#define CLK_TOP_APLL_SEL 52
++#define CLK_TOP_AUDIO_INTBUS_SEL 53
++#define CLK_TOP_AUDIO_SEL 54
++#define CLK_TOP_AXI_SEL 55
++#define CLK_TOP_CAM_SEL 56
++#define CLK_TOP_DDR_SEL 57
++#define CLK_TOP_DPI0_SEL 58
++#define CLK_TOP_DPI1_SEL 59
++#define CLK_TOP_DPILVDS_SEL 60
++#define CLK_TOP_ETH_SEL 61
++#define CLK_TOP_MEM_SEL 62
++#define CLK_TOP_MFG_SEL 63
++#define CLK_TOP_MM_SEL 64
++#define CLK_TOP_MSDC30_0_SEL 65
++#define CLK_TOP_MSDC30_1_SEL 66
++#define CLK_TOP_MSDC30_2_SEL 67
++#define CLK_TOP_NFI2X_SEL 68
++#define CLK_TOP_PMICSPI_SEL 69
++#define CLK_TOP_PWM_SEL 70
++#define CLK_TOP_RTC_SEL 71
++#define CLK_TOP_SCP_SEL 72
++#define CLK_TOP_SPI_SEL 73
++#define CLK_TOP_TVE_SEL 74
++#define CLK_TOP_UART_SEL 75
++#define CLK_TOP_USB20_SEL 76
++#define CLK_TOP_VDEC_SEL 77
++#define CLK_TOP_NR_CLK 78
++
++/* APMIXED_SYS */
++
++#define CLK_APMIXED_ARMPLL 1
++#define CLK_APMIXED_MAINPLL 2
++#define CLK_APMIXED_MSDCPLL 3
++#define CLK_APMIXED_UNIVPLL 4
++#define CLK_APMIXED_MMPLL 5
++#define CLK_APMIXED_VENCPLL 6
++#define CLK_APMIXED_TVDPLL 7
++#define CLK_APMIXED_LVDSPLL 8
++#define CLK_APMIXED_AUDPLL 9
++
++/* INFRA_SYS */
++
++#define CLK_INFRA_DBGCLK 0
++#define CLK_INFRA_SMI 1
++#define CLK_INFRA_AUDIO 5
++#define CLK_INFRA_EFUSE 6
++#define CLK_INFRA_L2C_SRAM 7
++#define CLK_INFRA_M4U 8
++#define CLK_INFRA_CONNMCU 12
++#define CLK_INFRA_TRNG 13
++#define CLK_INFRA_CPUM 15
++#define CLK_INFRA_KP 16
++#define CLK_INFRA_CEC 18
++#define CLK_INFRA_IRRX 19
++#define CLK_INFRA_PMICSPI 22
++#define CLK_INFRA_PMIC_WRAP 23
++#define CLK_INFRA_NR_CLK 24
++
++/* PERI_SYS */
++
++#define CLK_PERI_NFI 0
++#define CLK_PERI_THERM 1
++#define CLK_PERI_PWM1 2
++#define CLK_PERI_PWM2 3
++#define CLK_PERI_PWM3 4
++#define CLK_PERI_PWM4 5
++#define CLK_PERI_PWM5 6
++#define CLK_PERI_PWM6 7
++#define CLK_PERI_PWM7 8
++#define CLK_PERI_PWM 9
++#define CLK_PERI_USB0 10
++#define CLK_PERI_USB1 11
++#define CLK_PERI_AP_DMA 12
++#define CLK_PERI_MSDC20_1 13
++#define CLK_PERI_MSDC20_2 14
++#define CLK_PERI_MSDC30_1 15
++#define CLK_PERI_NLI 16
++#define CLK_PERI_UART0 17
++#define CLK_PERI_UART1 18
++#define CLK_PERI_UART2 19
++#define CLK_PERI_UART3 20
++#define CLK_PERI_BTIF 21
++#define CLK_PERI_I2C0 22
++#define CLK_PERI_I2C1 23
++#define CLK_PERI_I2C2 24
++#define CLK_PERI_I2C3 25
++#define CLK_PERI_AUXADC 26
++#define CLK_PERI_SPI0 27
++#define CLK_PERI_ETH 28
++#define CLK_PERI_USB0_MCU 29
++#define CLK_PERI_USB1_MCU 30
++#define CLK_PERI_USB_SLV 31
++#define CLK_PERI_GCPU 32
++#define CLK_PERI_NFI_ECC 33
++#define CLK_PERI_NFI_PAD 34
++#define CLK_PERI_UART0_SEL 35
++#define CLK_PERI_UART1_SEL 36
++#define CLK_PERI_UART2_SEL 37
++#define CLK_PERI_UART3_SEL 38
++#define CLK_PERI_NR_CLK 39
++
++#endif /* _DT_BINDINGS_CLK_MT7623_H */
++
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0062-arm-mediatek-add-mt7623-pinctrl-supoort.patch b/target/linux/mediatek/patches/0062-arm-mediatek-add-mt7623-pinctrl-supoort.patch
new file mode 100644
index 0000000000..c9ea40eac9
--- /dev/null
+++ b/target/linux/mediatek/patches/0062-arm-mediatek-add-mt7623-pinctrl-supoort.patch
@@ -0,0 +1,2889 @@
+From 718f377d37a737b133a3d904f5a038d6aa55c23e Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 13:13:05 +0200
+Subject: [PATCH 62/76] arm: mediatek: add mt7623 pinctrl supoort
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/pinctrl/mediatek/Kconfig | 6 +
+ drivers/pinctrl/mediatek/Makefile | 1 +
+ drivers/pinctrl/mediatek/pinctrl-mt7623.c | 368 +++++
+ drivers/pinctrl/mediatek/pinctrl-mtk-mt7623.h | 1926 +++++++++++++++++++++++++
+ include/dt-bindings/pinctrl/mt7623-pinfunc.h | 526 +++++++
+ 5 files changed, 2827 insertions(+)
+ create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7623.c
+ create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-mt7623.h
+ create mode 100644 include/dt-bindings/pinctrl/mt7623-pinfunc.h
+
+diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
+index 0bc84fb..27c5673 100644
+--- a/drivers/pinctrl/mediatek/Kconfig
++++ b/drivers/pinctrl/mediatek/Kconfig
+@@ -9,6 +9,12 @@ config PINCTRL_MTK_COMMON
+ select OF_GPIO
+
+ # For ARMv7 SoCs
++config PINCTRL_MT7623
++ bool "Mediatek MT7623 pin control" if COMPILE_TEST && !MACH_MT7623
++ depends on OF
++ default MACH_MT7623
++ select PINCTRL_MTK_COMMON
++
+ config PINCTRL_MT8135
+ bool "Mediatek MT8135 pin control" if COMPILE_TEST && !MACH_MT8135
+ depends on OF
+diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
+index eb923d6..8998433 100644
+--- a/drivers/pinctrl/mediatek/Makefile
++++ b/drivers/pinctrl/mediatek/Makefile
+@@ -2,6 +2,7 @@
+ obj-$(CONFIG_PINCTRL_MTK_COMMON) += pinctrl-mtk-common.o
+
+ # SoC Drivers
++obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o
+ obj-$(CONFIG_PINCTRL_MT8135) += pinctrl-mt8135.o
+ obj-$(CONFIG_PINCTRL_MT8127) += pinctrl-mt8127.o
+ obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7623.c b/drivers/pinctrl/mediatek/pinctrl-mt7623.c
+new file mode 100644
+index 0000000..77e1a66
+--- /dev/null
++++ b/drivers/pinctrl/mediatek/pinctrl-mt7623.c
+@@ -0,0 +1,368 @@
++/*
++ * Copyright (c) 2014-2015 MediaTek Inc.
++ * Author: Hongzhou.Yang <hongzhou.yang@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/regmap.h>
++#include <linux/pinctrl/pinconf-generic.h>
++#include <dt-bindings/pinctrl/mt65xx.h>
++
++#include "pinctrl-mtk-common.h"
++#include "pinctrl-mtk-mt7623.h"
++
++#define DRV_BASE 0xb00
++
++static const struct mtk_pin_spec_pupd_set_samereg mt7623_spec_pupd[] = {
++ MTK_PIN_PUPD_SPEC_SR(65, 0xcc0, 8, 9, 10), /* ms0 clk */
++ MTK_PIN_PUPD_SPEC_SR(57, 0xcd0, 8, 9, 10), /* ms0 cmd */
++ MTK_PIN_PUPD_SPEC_SR(60, 0xcf0, 0, 1, 2), /* ms0 data0 */
++ MTK_PIN_PUPD_SPEC_SR(59, 0xcf0, 4, 5, 6), /* ms0 data1 */
++ MTK_PIN_PUPD_SPEC_SR(58, 0xcf0, 8, 9, 10), /* ms0 data2 */
++ MTK_PIN_PUPD_SPEC_SR(57, 0xcf0, 12, 13, 14), /* ms0 data3 */
++ MTK_PIN_PUPD_SPEC_SR(61, 0xd00, 0, 1, 2), /* ms0 data4 */
++ MTK_PIN_PUPD_SPEC_SR(62, 0xd00, 4, 5, 6), /* ms0 data5 */
++ MTK_PIN_PUPD_SPEC_SR(63, 0xd00, 8, 9, 10), /* ms0 data6 */
++ MTK_PIN_PUPD_SPEC_SR(64, 0xd00, 12, 13, 14), /* ms0 data7 */
++ MTK_PIN_PUPD_SPEC_SR(67, 0xd10, 0, 1, 2), /* ms0 RST */
++
++ MTK_PIN_PUPD_SPEC_SR(78, 0xc50, 2, 1, 0), /* ms1 cmd */
++ MTK_PIN_PUPD_SPEC_SR(73, 0xd20, 2, 1, 0), /* ms1 dat0 */
++ MTK_PIN_PUPD_SPEC_SR(74, 0xd20, 6, 5, 4), /* ms1 dat1 */
++ MTK_PIN_PUPD_SPEC_SR(75, 0xd20, 10, 9, 8), /* ms1 dat2 */
++ MTK_PIN_PUPD_SPEC_SR(76, 0xd20, 14, 13, 12), /* ms1 dat3 */
++ MTK_PIN_PUPD_SPEC_SR(77, 0xc40, 2, 1, 0), /* ms1 clk */
++};
++
++static int mt7623_spec_pull_set(struct regmap *regmap, unsigned int pin,
++ unsigned char align, bool isup, unsigned int r1r0)
++{
++ return mtk_pctrl_spec_pull_set_samereg(regmap, mt7623_spec_pupd,
++ ARRAY_SIZE(mt7623_spec_pupd), pin, align, isup, r1r0);
++}
++
++/*static const struct mtk_pin_ies_smt_set mt7623_smt_set[] = {
++ MTK_PIN_IES_SMT_SPEC(0, 4, 0x930, 1),
++ MTK_PIN_IES_SMT_SPEC(5, 9, 0x930, 2),
++ MTK_PIN_IES_SMT_SPEC(10, 13, 0x930, 10),
++ MTK_PIN_IES_SMT_SPEC(14, 15, 0x940, 10),
++ MTK_PIN_IES_SMT_SPEC(16, 16, 0x930, 0),
++ MTK_PIN_IES_SMT_SPEC(17, 17, 0x950, 2),
++ MTK_PIN_IES_SMT_SPEC(18, 21, 0x940, 3),
++ MTK_PIN_IES_SMT_SPEC(29, 32, 0x930, 3),
++ MTK_PIN_IES_SMT_SPEC(33, 33, 0x930, 4),
++ MTK_PIN_IES_SMT_SPEC(34, 36, 0x930, 5),
++ MTK_PIN_IES_SMT_SPEC(37, 38, 0x930, 6),
++ MTK_PIN_IES_SMT_SPEC(39, 39, 0x930, 7),
++ MTK_PIN_IES_SMT_SPEC(40, 41, 0x930, 9),
++ MTK_PIN_IES_SMT_SPEC(42, 42, 0x940, 0),
++ MTK_PIN_IES_SMT_SPEC(43, 44, 0x930, 11),
++ MTK_PIN_IES_SMT_SPEC(45, 46, 0x930, 12),
++ MTK_PIN_IES_SMT_SPEC(57, 64, 0xc20, 13),
++ MTK_PIN_IES_SMT_SPEC(65, 65, 0xc10, 13),
++ MTK_PIN_IES_SMT_SPEC(66, 66, 0xc00, 13),
++ MTK_PIN_IES_SMT_SPEC(67, 67, 0xd10, 13),
++ MTK_PIN_IES_SMT_SPEC(68, 68, 0xd00, 13),
++ MTK_PIN_IES_SMT_SPEC(69, 72, 0x940, 14),
++ MTK_PIN_IES_SMT_SPEC(73, 76, 0xc60, 13),
++ MTK_PIN_IES_SMT_SPEC(77, 77, 0xc40, 13),
++ MTK_PIN_IES_SMT_SPEC(78, 78, 0xc50, 13),
++ MTK_PIN_IES_SMT_SPEC(79, 82, 0x940, 15),
++ MTK_PIN_IES_SMT_SPEC(83, 83, 0x950, 0),
++ MTK_PIN_IES_SMT_SPEC(84, 85, 0x950, 1),
++ MTK_PIN_IES_SMT_SPEC(86, 91, 0x950, 2),
++ MTK_PIN_IES_SMT_SPEC(92, 92, 0x930, 13),
++ MTK_PIN_IES_SMT_SPEC(93, 95, 0x930, 14),
++ MTK_PIN_IES_SMT_SPEC(96, 99, 0x930, 15),
++ MTK_PIN_IES_SMT_SPEC(100, 103, 0xca0, 13),
++ MTK_PIN_IES_SMT_SPEC(104, 104, 0xc80, 13),
++ MTK_PIN_IES_SMT_SPEC(105, 105, 0xc90, 13),
++ MTK_PIN_IES_SMT_SPEC(106, 107, 0x940, 4),
++ MTK_PIN_IES_SMT_SPEC(108, 112, 0x940, 1),
++ MTK_PIN_IES_SMT_SPEC(113, 116, 0x940, 2),
++ MTK_PIN_IES_SMT_SPEC(117, 118, 0x940, 5),
++ MTK_PIN_IES_SMT_SPEC(119, 124, 0x940, 6),
++ MTK_PIN_IES_SMT_SPEC(125, 126, 0x940, 7),
++ MTK_PIN_IES_SMT_SPEC(127, 127, 0x940, 0),
++ MTK_PIN_IES_SMT_SPEC(128, 128, 0x950, 8),
++ MTK_PIN_IES_SMT_SPEC(129, 130, 0x950, 9),
++ MTK_PIN_IES_SMT_SPEC(131, 132, 0x950, 8),
++ MTK_PIN_IES_SMT_SPEC(133, 134, 0x910, 8)
++};
++
++static const struct mtk_pin_ies_smt_set mt7623_ies_set[] = {
++ MTK_PIN_IES_SMT_SPEC(0, 4, 0x900, 1),
++ MTK_PIN_IES_SMT_SPEC(5, 9, 0x900, 2),
++ MTK_PIN_IES_SMT_SPEC(10, 13, 0x900, 10),
++ MTK_PIN_IES_SMT_SPEC(14, 15, 0x910, 10),
++ MTK_PIN_IES_SMT_SPEC(16, 16, 0x900, 0),
++ MTK_PIN_IES_SMT_SPEC(17, 17, 0x920, 2),
++ MTK_PIN_IES_SMT_SPEC(18, 21, 0x910, 3),
++ MTK_PIN_IES_SMT_SPEC(29, 32, 0x900, 3),
++ MTK_PIN_IES_SMT_SPEC(33, 33, 0x900, 4),
++ MTK_PIN_IES_SMT_SPEC(34, 36, 0x900, 5),
++ MTK_PIN_IES_SMT_SPEC(37, 38, 0x900, 6),
++ MTK_PIN_IES_SMT_SPEC(39, 39, 0x900, 7),
++ MTK_PIN_IES_SMT_SPEC(40, 41, 0x900, 9),
++ MTK_PIN_IES_SMT_SPEC(42, 42, 0x910, 0),
++ MTK_PIN_IES_SMT_SPEC(43, 44, 0x900, 11),
++ MTK_PIN_IES_SMT_SPEC(45, 46, 0x900, 12),
++ MTK_PIN_IES_SMT_SPEC(57, 64, 0xc20, 14),
++ MTK_PIN_IES_SMT_SPEC(65, 65, 0xc10, 14),
++ MTK_PIN_IES_SMT_SPEC(66, 66, 0xc00, 14),
++ MTK_PIN_IES_SMT_SPEC(67, 67, 0xd10, 14),
++ MTK_PIN_IES_SMT_SPEC(68, 68, 0xd00, 14),
++ MTK_PIN_IES_SMT_SPEC(69, 72, 0x910, 14),
++ MTK_PIN_IES_SMT_SPEC(73, 76, 0xc60, 14),
++ MTK_PIN_IES_SMT_SPEC(77, 77, 0xc40, 14),
++ MTK_PIN_IES_SMT_SPEC(78, 78, 0xc50, 14),
++ MTK_PIN_IES_SMT_SPEC(79, 82, 0x910, 15),
++ MTK_PIN_IES_SMT_SPEC(83, 83, 0x920, 0),
++ MTK_PIN_IES_SMT_SPEC(84, 85, 0x920, 1),
++ MTK_PIN_IES_SMT_SPEC(86, 91, 0x920, 2),
++ MTK_PIN_IES_SMT_SPEC(92, 92, 0x900, 13),
++ MTK_PIN_IES_SMT_SPEC(93, 95, 0x900, 14),
++ MTK_PIN_IES_SMT_SPEC(96, 99, 0x900, 15),
++ MTK_PIN_IES_SMT_SPEC(100, 103, 0xca0, 14),
++ MTK_PIN_IES_SMT_SPEC(104, 104, 0xc80, 14),
++ MTK_PIN_IES_SMT_SPEC(105, 105, 0xc90, 14),
++ MTK_PIN_IES_SMT_SPEC(106, 107, 0x91, 4),
++ MTK_PIN_IES_SMT_SPEC(108, 112, 0x910, 1),
++ MTK_PIN_IES_SMT_SPEC(113, 116, 0x910, 2),
++ MTK_PIN_IES_SMT_SPEC(117, 118, 0x910, 5),
++ MTK_PIN_IES_SMT_SPEC(119, 124, 0x910, 6),
++ MTK_PIN_IES_SMT_SPEC(125, 126, 0x910, 7),
++ MTK_PIN_IES_SMT_SPEC(127, 127, 0x910, 0),
++ MTK_PIN_IES_SMT_SPEC(128, 128, 0x920, 8),
++ MTK_PIN_IES_SMT_SPEC(129, 130, 0x920, 9),
++ MTK_PIN_IES_SMT_SPEC(131, 132, 0x920, 8),
++ MTK_PIN_IES_SMT_SPEC(133, 134, 0x910, 8)
++};
++
++static int mt7623_ies_smt_set(struct regmap *regmap, unsigned int pin,
++ unsigned char align, int value, enum pin_config_param arg)
++{
++ if (arg == PIN_CONFIG_INPUT_ENABLE)
++ return mtk_pconf_spec_set_ies_smt_range(regmap, mt7623_ies_set,
++ ARRAY_SIZE(mt7623_ies_set), pin, align, value);
++ else if (arg == PIN_CONFIG_INPUT_SCHMITT_ENABLE)
++ return mtk_pconf_spec_set_ies_smt_range(regmap, mt7623_smt_set,
++ ARRAY_SIZE(mt7623_smt_set), pin, align, value);
++ return -EINVAL;
++}
++*/
++static const struct mtk_drv_group_desc mt7623_drv_grp[] = {
++ /* 0E4E8SR 4/8/12/16 */
++ MTK_DRV_GRP(4, 16, 1, 2, 4),
++ /* 0E2E4SR 2/4/6/8 */
++ MTK_DRV_GRP(2, 8, 1, 2, 2),
++ /* E8E4E2 2/4/6/8/10/12/14/16 */
++ MTK_DRV_GRP(2, 16, 0, 2, 2)
++};
++
++/*static const struct mtk_pin_drv_grp mt7623_pin_drv[] = {
++ MTK_PIN_DRV_GRP(0, DRV_BASE+0x20, 12, 0),
++ MTK_PIN_DRV_GRP(1, DRV_BASE+0x20, 12, 0),
++ MTK_PIN_DRV_GRP(2, DRV_BASE+0x20, 12, 0),
++ MTK_PIN_DRV_GRP(3, DRV_BASE+0x20, 12, 0),
++ MTK_PIN_DRV_GRP(4, DRV_BASE+0x20, 12, 0),
++ MTK_PIN_DRV_GRP(5, DRV_BASE+0x30, 0, 0),
++ MTK_PIN_DRV_GRP(6, DRV_BASE+0x30, 0, 0),
++ MTK_PIN_DRV_GRP(7, DRV_BASE+0x30, 0, 0),
++ MTK_PIN_DRV_GRP(8, DRV_BASE+0x30, 0, 0),
++ MTK_PIN_DRV_GRP(9, DRV_BASE+0x30, 0, 0),
++ MTK_PIN_DRV_GRP(10, DRV_BASE+0x30, 4, 1),
++ MTK_PIN_DRV_GRP(11, DRV_BASE+0x30, 4, 1),
++ MTK_PIN_DRV_GRP(12, DRV_BASE+0x30, 4, 1),
++ MTK_PIN_DRV_GRP(13, DRV_BASE+0x30, 4, 1),
++ MTK_PIN_DRV_GRP(14, DRV_BASE+0x40, 8, 1),
++ MTK_PIN_DRV_GRP(15, DRV_BASE+0x40, 8, 1),
++ MTK_PIN_DRV_GRP(16, DRV_BASE, 8, 1),
++ MTK_PIN_DRV_GRP(17, 0xce0, 8, 2),
++ MTK_PIN_DRV_GRP(22, 0xce0, 8, 2),
++ MTK_PIN_DRV_GRP(23, 0xce0, 8, 2),
++ MTK_PIN_DRV_GRP(24, 0xce0, 8, 2),
++ MTK_PIN_DRV_GRP(25, 0xce0, 8, 2),
++ MTK_PIN_DRV_GRP(26, 0xcc0, 8, 2),
++ MTK_PIN_DRV_GRP(27, 0xcd0, 8, 2),
++ MTK_PIN_DRV_GRP(28, 0xd70, 8, 2),
++ MTK_PIN_DRV_GRP(29, DRV_BASE+0x80, 12, 1),
++ MTK_PIN_DRV_GRP(30, DRV_BASE+0x80, 12, 1),
++ MTK_PIN_DRV_GRP(31, DRV_BASE+0x80, 12, 1),
++ MTK_PIN_DRV_GRP(32, DRV_BASE+0x80, 12, 1),
++ MTK_PIN_DRV_GRP(33, DRV_BASE+0x10, 12, 1),
++ MTK_PIN_DRV_GRP(34, DRV_BASE+0x10, 8, 1),
++ MTK_PIN_DRV_GRP(35, DRV_BASE+0x10, 8, 1),
++ MTK_PIN_DRV_GRP(36, DRV_BASE+0x10, 8, 1),
++ MTK_PIN_DRV_GRP(37, DRV_BASE+0x10, 4, 1),
++ MTK_PIN_DRV_GRP(38, DRV_BASE+0x10, 4, 1),
++ MTK_PIN_DRV_GRP(39, DRV_BASE+0x20, 0, 0),
++ MTK_PIN_DRV_GRP(40, DRV_BASE+0x20, 8, 0),
++ MTK_PIN_DRV_GRP(41, DRV_BASE+0x20, 8, 0),
++ MTK_PIN_DRV_GRP(42, DRV_BASE+0x50, 8, 1),
++ MTK_PIN_DRV_GRP(57, 0xc20, 8, 2),
++ MTK_PIN_DRV_GRP(58, 0xc20, 8, 2),
++ MTK_PIN_DRV_GRP(59, 0xc20, 8, 2),
++ MTK_PIN_DRV_GRP(60, 0xc20, 8, 2),
++ MTK_PIN_DRV_GRP(61, 0xc20, 8, 2),
++ MTK_PIN_DRV_GRP(62, 0xc20, 8, 2),
++ MTK_PIN_DRV_GRP(63, 0xc20, 8, 2),
++ MTK_PIN_DRV_GRP(64, 0xc20, 8, 2),
++ MTK_PIN_DRV_GRP(65, 0xc00, 8, 2),
++ MTK_PIN_DRV_GRP(66, 0xc10, 8, 2),
++ MTK_PIN_DRV_GRP(67, 0xd10, 8, 2),
++ MTK_PIN_DRV_GRP(68, 0xd00, 8, 2),
++ MTK_PIN_DRV_GRP(69, DRV_BASE+0x80, 0, 1),
++ MTK_PIN_DRV_GRP(70, DRV_BASE+0x80, 0, 1),
++ MTK_PIN_DRV_GRP(71, DRV_BASE+0x80, 0, 1),
++ MTK_PIN_DRV_GRP(72, DRV_BASE+0x80, 0, 1),
++ MTK_PIN_DRV_GRP(73, 0xc60, 8, 2),
++ MTK_PIN_DRV_GRP(74, 0xc60, 8, 2),
++ MTK_PIN_DRV_GRP(75, 0xc60, 8, 2),
++ MTK_PIN_DRV_GRP(76, 0xc60, 8, 2),
++ MTK_PIN_DRV_GRP(77, 0xc40, 8, 2),
++ MTK_PIN_DRV_GRP(78, 0xc50, 8, 2),
++ MTK_PIN_DRV_GRP(79, DRV_BASE+0x70, 12, 1),
++ MTK_PIN_DRV_GRP(80, DRV_BASE+0x70, 12, 1),
++ MTK_PIN_DRV_GRP(81, DRV_BASE+0x70, 12, 1),
++ MTK_PIN_DRV_GRP(82, DRV_BASE+0x70, 12, 1),
++ MTK_PIN_DRV_GRP(83, DRV_BASE, 4, 1),
++ MTK_PIN_DRV_GRP(84, DRV_BASE, 0, 1),
++ MTK_PIN_DRV_GRP(85, DRV_BASE, 0, 1),
++ MTK_PIN_DRV_GRP(85, DRV_BASE+0x60, 8, 1),
++ MTK_PIN_DRV_GRP(86, DRV_BASE+0x60, 8, 1),
++ MTK_PIN_DRV_GRP(87, DRV_BASE+0x60, 8, 1),
++ MTK_PIN_DRV_GRP(88, DRV_BASE+0x60, 8, 1),
++ MTK_PIN_DRV_GRP(89, DRV_BASE+0x60, 8, 1),
++ MTK_PIN_DRV_GRP(90, DRV_BASE+0x60, 8, 1),
++ MTK_PIN_DRV_GRP(91, DRV_BASE+0x60, 8, 1),
++ MTK_PIN_DRV_GRP(92, DRV_BASE+0x60, 4, 0),
++ MTK_PIN_DRV_GRP(93, DRV_BASE+0x60, 0, 0),
++ MTK_PIN_DRV_GRP(94, DRV_BASE+0x60, 0, 0),
++ MTK_PIN_DRV_GRP(95, DRV_BASE+0x60, 0, 0),
++ MTK_PIN_DRV_GRP(96, DRV_BASE+0x80, 8, 1),
++ MTK_PIN_DRV_GRP(97, DRV_BASE+0x80, 8, 1),
++ MTK_PIN_DRV_GRP(98, DRV_BASE+0x80, 8, 1),
++ MTK_PIN_DRV_GRP(99, DRV_BASE+0x80, 8, 1),
++ MTK_PIN_DRV_GRP(100, 0xca0, 8, 2),
++ MTK_PIN_DRV_GRP(101, 0xca0, 8, 2),
++ MTK_PIN_DRV_GRP(102, 0xca0, 8, 2),
++ MTK_PIN_DRV_GRP(103, 0xca0, 8, 2),
++ MTK_PIN_DRV_GRP(104, 0xc80, 8, 2),
++ MTK_PIN_DRV_GRP(105, 0xc90, 8, 2),
++ MTK_PIN_DRV_GRP(108, DRV_BASE+0x50, 0, 1),
++ MTK_PIN_DRV_GRP(109, DRV_BASE+0x50, 0, 1),
++ MTK_PIN_DRV_GRP(110, DRV_BASE+0x50, 0, 1),
++ MTK_PIN_DRV_GRP(111, DRV_BASE+0x50, 0, 1),
++ MTK_PIN_DRV_GRP(112, DRV_BASE+0x50, 0, 1),
++ MTK_PIN_DRV_GRP(113, DRV_BASE+0x80, 4, 1),
++ MTK_PIN_DRV_GRP(114, DRV_BASE+0x80, 4, 1),
++ MTK_PIN_DRV_GRP(115, DRV_BASE+0x80, 4, 1),
++ MTK_PIN_DRV_GRP(116, DRV_BASE+0x80, 4, 1),
++ MTK_PIN_DRV_GRP(117, DRV_BASE+0x90, 0, 1),
++ MTK_PIN_DRV_GRP(118, DRV_BASE+0x90, 0, 1),
++ MTK_PIN_DRV_GRP(119, DRV_BASE+0x50, 4, 1),
++ MTK_PIN_DRV_GRP(120, DRV_BASE+0x50, 4, 1),
++ MTK_PIN_DRV_GRP(121, DRV_BASE+0x50, 4, 1),
++ MTK_PIN_DRV_GRP(122, DRV_BASE+0x50, 4, 1),
++ MTK_PIN_DRV_GRP(123, DRV_BASE+0x50, 4, 1),
++ MTK_PIN_DRV_GRP(124, DRV_BASE+0x50, 4, 1),
++ MTK_PIN_DRV_GRP(125, DRV_BASE+0x30, 12, 1),
++ MTK_PIN_DRV_GRP(126, DRV_BASE+0x30, 12, 1),
++ MTK_PIN_DRV_GRP(127, DRV_BASE+0x50, 8, 1),
++ MTK_PIN_DRV_GRP(128, DRV_BASE+0x40, 0, 1),
++ MTK_PIN_DRV_GRP(129, DRV_BASE+0x40, 0, 1),
++ MTK_PIN_DRV_GRP(130, DRV_BASE+0x40, 0, 1),
++ MTK_PIN_DRV_GRP(131, DRV_BASE+0x40, 0, 1),
++ MTK_PIN_DRV_GRP(132, DRV_BASE+0x40, 0, 1)
++};
++*/
++static const struct mtk_pinctrl_devdata mt7623_pinctrl_data = {
++ .pins = mtk_pins_mt7623,
++ .npins = ARRAY_SIZE(mtk_pins_mt7623),
++ .grp_desc = mt7623_drv_grp,
++ .n_grp_cls = ARRAY_SIZE(mt7623_drv_grp),
++// .pin_drv_grp = mt7623_pin_drv,
++// .n_pin_drv_grps = ARRAY_SIZE(mt7623_pin_drv),
++ .spec_pull_set = mt7623_spec_pull_set,
++ //.spec_ies_smt_set = mt7623_ies_smt_set,
++ .dir_offset = 0x0000,
++ .pullen_offset = 0x0150,
++ .pullsel_offset = 0x0280,
++ .dout_offset = 0x0550,
++ .din_offset = 0x0630,
++ .pinmux_offset = 0x0760,
++ .port_shf = 4,
++ .port_mask = 0xf,
++ .port_align = 4,
++ .eint_offsets = {
++ .name = "mt7623_eint",
++ .stat = 0x000,
++ .ack = 0x040,
++ .mask = 0x080,
++ .mask_set = 0x0c0,
++ .mask_clr = 0x100,
++ .sens = 0x140,
++ .sens_set = 0x180,
++ .sens_clr = 0x1c0,
++ .soft = 0x200,
++ .soft_set = 0x240,
++ .soft_clr = 0x280,
++ .pol = 0x300,
++ .pol_set = 0x340,
++ .pol_clr = 0x380,
++ .dom_en = 0x400,
++ .dbnc_ctrl = 0x500,
++ .dbnc_set = 0x600,
++ .dbnc_clr = 0x700,
++ .port_mask = 7,
++ .ports = 6,
++ },
++ .ap_num = 224,
++ .db_cnt = 16,
++};
++
++static int mt7623_pinctrl_probe(struct platform_device *pdev)
++{
++ return mtk_pctrl_init(pdev, &mt7623_pinctrl_data, NULL);
++}
++
++static const struct of_device_id mt7623_pctrl_match[] = {
++ {
++ .compatible = "mediatek,mt7623-pinctrl",
++ },
++ { }
++};
++MODULE_DEVICE_TABLE(of, mt7623_pctrl_match);
++
++static struct platform_driver mtk_pinctrl_driver = {
++ .probe = mt7623_pinctrl_probe,
++ .driver = {
++ .name = "mediatek-mt7623-pinctrl",
++ .of_match_table = mt7623_pctrl_match,
++ },
++};
++
++static int __init mtk_pinctrl_init(void)
++{
++ return platform_driver_register(&mtk_pinctrl_driver);
++}
++
++module_init(mtk_pinctrl_init);
++
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("MediaTek Pinctrl Driver");
++MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt7623.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt7623.h
+new file mode 100644
+index 0000000..4b65668
+--- /dev/null
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt7623.h
+@@ -0,0 +1,1926 @@
++#ifndef __PINCTRL_MTK_MT7623_H
++#define __PINCTRL_MTK_MT7623_H
++
++#include <linux/pinctrl/pinctrl.h>
++#include "pinctrl-mtk-common.h"
++
++static const struct mtk_desc_pin mtk_pins_mt7623[] = {
++ MTK_PIN(
++ PINCTRL_PIN(0, "PWRAP_SPI0_MI"),
++ "F11", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO0"),
++ MTK_FUNCTION(1, "PWRAP_SPIDO"),
++ MTK_FUNCTION(2, "PWRAP_SPIDI")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(1, "PWRAP_SPI0_MO"),
++ "D10", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO1"),
++ MTK_FUNCTION(1, "PWRAP_SPIDI"),
++ MTK_FUNCTION(2, "PWRAP_SPIDO")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(2, "PWRAP_INT"),
++ "E11", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO2"),
++ MTK_FUNCTION(1, "PWRAP_INT")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(3, "PWRAP_SPI0_CK"),
++ "H12", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO3"),
++ MTK_FUNCTION(1, "PWRAP_SPICK_I")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(4, "PWRAP_SPI0_CSN"),
++ "E12", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO4"),
++ MTK_FUNCTION(1, "PWRAP_SPICS_B_I")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(5, "PWRAP_SPI0_CK2"),
++ "H11", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO5"),
++ MTK_FUNCTION(1, "PWRAP_SPICK2_I")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(6, "PWRAP_SPI0_CSN2"),
++ "G11", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO6"),
++ MTK_FUNCTION(1, "PWRAP_SPICS2_B_I")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(7, "SPI1_CSN"),
++ "G19", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO7"),
++ MTK_FUNCTION(1, "SPI1_CS")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(8, "SPI1_MI"),
++ "F19", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO8"),
++ MTK_FUNCTION(1, "SPI1_MI"),
++ MTK_FUNCTION(2, "SPI1_MO")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(9, "SPI1_MO"),
++ "G20", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO9"),
++ MTK_FUNCTION(1, "SPI1_MO"),
++ MTK_FUNCTION(2, "SPI1_MI")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(10, "RTC32K_CK"),
++ "A13", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO10"),
++ MTK_FUNCTION(1, "RTC32K_CK")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(11, "WATCHDOG"),
++ "D14", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO11"),
++ MTK_FUNCTION(1, "WATCHDOG")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(12, "SRCLKENA"),
++ "C13", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO12"),
++ MTK_FUNCTION(1, "SRCLKENA")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(13, "SRCLKENAI"),
++ "B13", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO13"),
++ MTK_FUNCTION(1, "SRCLKENAI")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(14, "GPIO14"),
++ "E18", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO14"),
++ MTK_FUNCTION(1, "URXD2"),
++ MTK_FUNCTION(2, "UTXD2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(15, "GPIO15"),
++ "E17", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO15"),
++ MTK_FUNCTION(1, "UTXD2"),
++ MTK_FUNCTION(2, "URXD2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(16, "GPIO16"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO16")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(17, "GPIO17"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO17")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(18, "PCM_CLK"),
++ "C19", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO18"),
++ MTK_FUNCTION(1, "PCM_CLK0"),
++ MTK_FUNCTION(6, "AP_PCM_CLKO")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(19, "PCM_SYNC"),
++ "D19", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO19"),
++ MTK_FUNCTION(1, "PCM_SYNC"),
++ MTK_FUNCTION(6, "AP_PCM_SYNC")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(20, "PCM_RX"),
++ "D18", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO20"),
++ MTK_FUNCTION(1, "PCM_RX"),
++ MTK_FUNCTION(4, "PCM_TX"),
++ MTK_FUNCTION(6, "AP_PCM_RX")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(21, "PCM_TX"),
++ "C18", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO21"),
++ MTK_FUNCTION(1, "PCM_TX"),
++ MTK_FUNCTION(4, "PCM_RX"),
++ MTK_FUNCTION(6, "AP_PCM_TX")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(22, "EINT0"),
++ "H15", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO22"),
++ MTK_FUNCTION(1, "UCTS0"),
++ MTK_FUNCTION(2, "PCIE0_PERST_N")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(23, "EINT1"),
++ "J16", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO23"),
++ MTK_FUNCTION(1, "URTS0"),
++ MTK_FUNCTION(2, "PCIE1_PERST_N")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(24, "EINT2"),
++ "H16", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO24"),
++ MTK_FUNCTION(1, "UCTS1"),
++ MTK_FUNCTION(2, "PCIE2_PERST_N")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(25, "EINT3"),
++ "K15", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO25"),
++ MTK_FUNCTION(1, "URTS1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(26, "EINT4"),
++ "G15", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO26"),
++ MTK_FUNCTION(1, "UCTS3"),
++ MTK_FUNCTION(6, "PCIE2_WAKE_N")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(27, "EINT5"),
++ "F15", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO27"),
++ MTK_FUNCTION(1, "URTS3"),
++ MTK_FUNCTION(6, "PCIE1_WAKE_N")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(28, "EINT6"),
++ "J15", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO28"),
++ MTK_FUNCTION(1, "DRV_VBUS"),
++ MTK_FUNCTION(6, "PCIE0_WAKE_N")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(29, "EINT7"),
++ "E15", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO29"),
++ MTK_FUNCTION(1, "IDDIG"),
++ MTK_FUNCTION(2, "MSDC1_WP"),
++ MTK_FUNCTION(6, "PCIE2_PERST_N")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(30, "GPIO30"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO30")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(31, "GPIO31"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO31")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(32, "GPIO32"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO32")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(33, "I2S1_DATA"),
++ "Y18", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO33"),
++ MTK_FUNCTION(1, "I2S1_DATA"),
++ MTK_FUNCTION(3, "PCM_TX"),
++ MTK_FUNCTION(6, "AP_PCM_TX")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(34, "I2S1_DATA_IN"),
++ "Y17", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO34"),
++ MTK_FUNCTION(1, "I2S1_DATA_IN"),
++ MTK_FUNCTION(3, "PCM_RX"),
++ MTK_FUNCTION(6, "AP_PCM_RX")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(35, "I2S1_BCK"),
++ "V17", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO35"),
++ MTK_FUNCTION(1, "I2S1_BCK"),
++ MTK_FUNCTION(3, "PCM_CLK0"),
++ MTK_FUNCTION(6, "AP_PCM_CLKO")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(36, "I2S1_LRCK"),
++ "W17", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO36"),
++ MTK_FUNCTION(1, "I2S1_LRCK"),
++ MTK_FUNCTION(3, "PCM_SYNC"),
++ MTK_FUNCTION(6, "AP_PCM_SYNC")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(37, "I2S1_MCLK"),
++ "AA18", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO37"),
++ MTK_FUNCTION(1, "I2S1_MCLK")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(38, "GPIO38"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO38")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(39, "JTMS"),
++ "G21", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO39"),
++ MTK_FUNCTION(1, "JTMS")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(40, "JTCK"),
++ "J20", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO40"),
++ MTK_FUNCTION(1, "JTCK")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(41, "JTDI"),
++ "H22", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO41"),
++ MTK_FUNCTION(1, "JTDI")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(42, "JTDO"),
++ "H21", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO42"),
++ MTK_FUNCTION(1, "JTDO")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(43, "NCLE"),
++ "C7", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO43"),
++ MTK_FUNCTION(1, "NCLE"),
++ MTK_FUNCTION(2, "EXT_XCS2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(44, "NCEB1"),
++ "C6", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO44"),
++ MTK_FUNCTION(1, "NCEB1"),
++ MTK_FUNCTION(2, "IDDIG")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(45, "NCEB0"),
++ "D7", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO45"),
++ MTK_FUNCTION(1, "NCEB0"),
++ MTK_FUNCTION(2, "DRV_VBUS")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(46, "IR"),
++ "D15", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO46"),
++ MTK_FUNCTION(1, "IR")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(47, "NREB"),
++ "A6", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO47"),
++ MTK_FUNCTION(1, "NREB")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(48, "NRNB"),
++ "B6", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO48"),
++ MTK_FUNCTION(1, "NRNB")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(49, "I2S0_DATA"),
++ "AB18", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO49"),
++ MTK_FUNCTION(1, "I2S0_DATA"),
++ MTK_FUNCTION(3, "PCM_TX"),
++ MTK_FUNCTION(6, "AP_I2S_DO")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(50, "GPIO50"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO50")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(51, "GPIO51"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO51")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(52, "GPIO52"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO52")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(53, "SPI0_CSN"),
++ "E7", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO53"),
++ MTK_FUNCTION(1, "SPI0_CS"),
++ MTK_FUNCTION(5, "PWM1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(54, "SPI0_CK"),
++ "F7", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO54"),
++ MTK_FUNCTION(1, "SPI0_CK")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(55, "SPI0_MI"),
++ "E6", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO55"),
++ MTK_FUNCTION(1, "SPI0_MI"),
++ MTK_FUNCTION(2, "SPI0_MO"),
++ MTK_FUNCTION(3, "MSDC1_WP"),
++ MTK_FUNCTION(5, "PWM2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(56, "SPI0_MO"),
++ "G7", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO56"),
++ MTK_FUNCTION(1, "SPI0_MO"),
++ MTK_FUNCTION(2, "SPI0_MI")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(57, "GPIO57"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO57")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(58, "GPIO58"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO58")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(59, "GPIO59"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO59")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(60, "WB_RSTB"),
++ "Y21", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO60"),
++ MTK_FUNCTION(1, "WB_RSTB")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(61, "GPIO61"),
++ "AA21", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO61"),
++ MTK_FUNCTION(1, "TEST_FD")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(62, "GPIO62"),
++ "AB22", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO62"),
++ MTK_FUNCTION(1, "TEST_FC")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(63, "WB_SCLK"),
++ "AC23", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO63"),
++ MTK_FUNCTION(1, "WB_SCLK")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(64, "WB_SDATA"),
++ "AB21", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO64"),
++ MTK_FUNCTION(1, "WB_SDATA")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(65, "WB_SEN"),
++ "AB24", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO65"),
++ MTK_FUNCTION(1, "WB_SEN")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(66, "WB_CRTL0"),
++ "AB20", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO66"),
++ MTK_FUNCTION(1, "WB_CRTL0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(67, "WB_CRTL1"),
++ "AC20", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO67"),
++ MTK_FUNCTION(1, "WB_CRTL1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(68, "WB_CRTL2"),
++ "AB19", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO68"),
++ MTK_FUNCTION(1, "WB_CRTL2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(69, "WB_CRTL3"),
++ "AC19", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO69"),
++ MTK_FUNCTION(1, "WB_CRTL3")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(70, "WB_CRTL4"),
++ "AD19", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO70"),
++ MTK_FUNCTION(1, "WB_CRTL4")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(71, "WB_CRTL5"),
++ "AE19", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO71"),
++ MTK_FUNCTION(1, "WB_CRTL5")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(72, "I2S0_DATA_IN"),
++ "AA20", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO72"),
++ MTK_FUNCTION(1, "I2S0_DATA_IN"),
++ MTK_FUNCTION(3, "PCM_RX"),
++ MTK_FUNCTION(4, "PWM0"),
++ MTK_FUNCTION(5, "DISP_PWM"),
++ MTK_FUNCTION(6, "AP_I2S_DI")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(73, "I2S0_LRCK"),
++ "Y20", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO73"),
++ MTK_FUNCTION(1, "I2S0_LRCK"),
++ MTK_FUNCTION(3, "PCM_SYNC"),
++ MTK_FUNCTION(6, "AP_I2S_LRCK")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(74, "I2S0_BCK"),
++ "Y19", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO74"),
++ MTK_FUNCTION(1, "I2S0_BCK"),
++ MTK_FUNCTION(3, "PCM_CLK0"),
++ MTK_FUNCTION(6, "AP_I2S_BCK")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(75, "SDA0"),
++ "K19", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO75"),
++ MTK_FUNCTION(1, "SDA0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(76, "SCL0"),
++ "K20", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO76"),
++ MTK_FUNCTION(1, "SCL0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(77, "GPIO77"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO77")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(78, "GPIO78"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO78")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(79, "GPIO79"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO79")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(80, "GPIO80"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO80")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(81, "GPIO81"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO81")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(82, "GPIO82"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO82")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(83, "LCM_RST"),
++ "V16", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO83"),
++ MTK_FUNCTION(1, "LCM_RST")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(84, "DSI_TE"),
++ "V14", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO84"),
++ MTK_FUNCTION(1, "DSI_TE")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(85, "GPIO85"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO85")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(86, "GPIO86"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO86")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(87, "GPIO87"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO87")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(88, "GPIO88"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO88")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(89, "GPIO89"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO89")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(90, "GPIO90"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO90")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(91, "GPIO91"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO91")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(92, "GPIO92"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO92")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(93, "GPIO93"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO93")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(94, "GPIO94"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO94")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(95, "MIPI_TCN"),
++ "AB14", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO95"),
++ MTK_FUNCTION(1, "TCN")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(96, "MIPI_TCP"),
++ "AC14", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO96"),
++ MTK_FUNCTION(1, "TCP")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(97, "MIPI_TDN1"),
++ "AE15", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO97"),
++ MTK_FUNCTION(1, "TDN1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(98, "MIPI_TDP1"),
++ "AD15", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO98"),
++ MTK_FUNCTION(1, "TDP1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(99, "MIPI_TDN0"),
++ "AB15", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO99"),
++ MTK_FUNCTION(1, "TDN0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(100, "MIPI_TDP0"),
++ "AC15", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO100"),
++ MTK_FUNCTION(1, "TDP0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(101, "GPIO101"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO101")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(102, "GPIO102"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO102")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(103, "GPIO103"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO103")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(104, "GPIO104"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO104")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(105, "MSDC1_CMD"),
++ "AD2", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO105"),
++ MTK_FUNCTION(1, "MSDC1_CMD"),
++ MTK_FUNCTION(3, "SDA1"),
++ MTK_FUNCTION(6, "I2SOUT_BCK")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(106, "MSDC1_CLK"),
++ "AD3", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO106"),
++ MTK_FUNCTION(1, "MSDC1_CLK"),
++ MTK_FUNCTION(3, "SCL1"),
++ MTK_FUNCTION(6, "I2SOUT_LRCK")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(107, "MSDC1_DAT0"),
++ "AE2", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO107"),
++ MTK_FUNCTION(1, "MSDC1_DAT0"),
++ MTK_FUNCTION(5, "UTXD0"),
++ MTK_FUNCTION(6, "I2SOUT_DATA_OUT")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(108, "MSDC1_DAT1"),
++ "AC1", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO108"),
++ MTK_FUNCTION(1, "MSDC1_DAT1"),
++ MTK_FUNCTION(3, "PWM0"),
++ MTK_FUNCTION(5, "URXD0"),
++ MTK_FUNCTION(6, "PWM1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(109, "MSDC1_DAT2"),
++ "AC3", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO109"),
++ MTK_FUNCTION(1, "MSDC1_DAT2"),
++ MTK_FUNCTION(3, "SDA2"),
++ MTK_FUNCTION(5, "UTXD1"),
++ MTK_FUNCTION(6, "PWM2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(110, "MSDC1_DAT3"),
++ "AC4", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO110"),
++ MTK_FUNCTION(1, "MSDC1_DAT3"),
++ MTK_FUNCTION(3, "SCL2"),
++ MTK_FUNCTION(5, "URXD1"),
++ MTK_FUNCTION(6, "PWM3")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(111, "MSDC0_DAT7"),
++ "A2", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO111"),
++ MTK_FUNCTION(1, "MSDC0_DAT7"),
++ MTK_FUNCTION(4, "NLD7")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(112, "MSDC0_DAT6"),
++ "B3", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO112"),
++ MTK_FUNCTION(1, "MSDC0_DAT6"),
++ MTK_FUNCTION(4, "NLD6")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(113, "MSDC0_DAT5"),
++ "C4", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO113"),
++ MTK_FUNCTION(1, "MSDC0_DAT5"),
++ MTK_FUNCTION(4, "NLD5")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(114, "MSDC0_DAT4"),
++ "A4", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO114"),
++ MTK_FUNCTION(1, "MSDC0_DAT4"),
++ MTK_FUNCTION(4, "NLD4")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(115, "MSDC0_RSTB"),
++ "C5", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO115"),
++ MTK_FUNCTION(1, "MSDC0_RSTB"),
++ MTK_FUNCTION(4, "NLD8")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(116, "MSDC0_CMD"),
++ "D5", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO116"),
++ MTK_FUNCTION(1, "MSDC0_CMD"),
++ MTK_FUNCTION(4, "NALE")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(117, "MSDC0_CLK"),
++ "B1", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO117"),
++ MTK_FUNCTION(1, "MSDC0_CLK"),
++ MTK_FUNCTION(4, "NWEB")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(118, "MSDC0_DAT3"),
++ "D6", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO118"),
++ MTK_FUNCTION(1, "MSDC0_DAT3"),
++ MTK_FUNCTION(4, "NLD3")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(119, "MSDC0_DAT2"),
++ "B2", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO119"),
++ MTK_FUNCTION(1, "MSDC0_DAT2"),
++ MTK_FUNCTION(4, "NLD2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(120, "MSDC0_DAT1"),
++ "A3", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO120"),
++ MTK_FUNCTION(1, "MSDC0_DAT1"),
++ MTK_FUNCTION(4, "NLD1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(121, "MSDC0_DAT0"),
++ "B4", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO121"),
++ MTK_FUNCTION(1, "MSDC0_DAT0"),
++ MTK_FUNCTION(4, "NLD0"),
++ MTK_FUNCTION(5, "WATCHDOG")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(122, "GPIO122"),
++ "H17", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO122"),
++ MTK_FUNCTION(1, "TEST"),
++ MTK_FUNCTION(4, "SDA2"),
++ MTK_FUNCTION(5, "URXD0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(123, "GPIO123"),
++ "F17", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO123"),
++ MTK_FUNCTION(1, "TEST"),
++ MTK_FUNCTION(4, "SCL2"),
++ MTK_FUNCTION(5, "UTXD0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(124, "GPIO124"),
++ "H18", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO124"),
++ MTK_FUNCTION(1, "TEST"),
++ MTK_FUNCTION(4, "SDA1"),
++ MTK_FUNCTION(5, "PWM3")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(125, "GPIO125"),
++ "G17", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO125"),
++ MTK_FUNCTION(1, "TEST"),
++ MTK_FUNCTION(4, "SCL1"),
++ MTK_FUNCTION(5, "PWM4")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(126, "I2S0_MCLK"),
++ "AA19", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO126"),
++ MTK_FUNCTION(1, "I2S0_MCLK"),
++ MTK_FUNCTION(6, "AP_I2S_MCLK")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(127, "GPIO127"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO127")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(128, "GPIO128"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO128")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(129, "GPIO129"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO129")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(130, "GPIO130"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO130")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(131, "GPIO131"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO131")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(132, "GPIO132"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO132")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(133, "GPIO133"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO133")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(134, "GPIO134"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO134")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(135, "GPIO135"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO135")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(136, "GPIO136"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO136")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(137, "GPIO137"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO137")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(138, "GPIO138"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO138")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(139, "GPIO139"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO139")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(140, "GPIO140"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO140")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(141, "GPIO141"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO141")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(142, "GPIO142"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO142")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(143, "GPIO143"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO143")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(144, "GPIO144"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO144")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(145, "GPIO145"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO145")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(146, "GPIO146"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO146")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(147, "GPIO147"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO147")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(148, "GPIO148"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO148")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(149, "GPIO149"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO149")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(150, "GPIO150"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO150")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(151, "GPIO151"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO151")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(152, "GPIO152"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO152")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(153, "GPIO153"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO153")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(154, "GPIO154"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO154")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(155, "GPIO155"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO155")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(156, "GPIO156"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO156")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(157, "GPIO157"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO157")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(158, "GPIO158"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO158")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(159, "GPIO159"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO159")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(160, "GPIO160"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO160")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(161, "GPIO161"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO161")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(162, "GPIO162"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO162")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(163, "GPIO163"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO163")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(164, "GPIO164"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO164")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(165, "GPIO165"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO165")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(166, "GPIO166"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO166")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(167, "GPIO167"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO167")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(168, "GPIO168"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO168")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(169, "GPIO169"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO169")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(170, "GPIO170"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO170")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(171, "GPIO171"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO171")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(172, "GPIO172"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO172")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(173, "GPIO173"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO173")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(174, "GPIO174"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO174")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(175, "GPIO175"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO175")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(176, "GPIO176"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO176")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(177, "GPIO177"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO177")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(178, "GPIO178"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO178")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(179, "GPIO179"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO179")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(180, "GPIO180"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO180")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(181, "GPIO181"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO181")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(182, "GPIO182"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO182")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(183, "GPIO183"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO183")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(184, "GPIO184"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO184")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(185, "GPIO185"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO185")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(186, "GPIO186"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO186")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(187, "GPIO187"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO187")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(188, "GPIO188"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO188")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(189, "GPIO189"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO189")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(190, "GPIO190"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO190")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(191, "GPIO191"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO191")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(192, "GPIO192"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO192")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(193, "GPIO193"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO193")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(194, "GPIO194"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO194")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(195, "GPIO195"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO195")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(196, "GPIO196"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO196")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(197, "GPIO197"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO197")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(198, "GPIO198"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO198")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(199, "SPI1_CK"),
++ "E19", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO199"),
++ MTK_FUNCTION(1, "SPI1_CK")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(200, "URXD2"),
++ "K18", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO200"),
++ MTK_FUNCTION(6, "URXD2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(201, "UTXD2"),
++ "L18", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO201"),
++ MTK_FUNCTION(6, "UTXD2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(202, "GPIO202"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO202")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(203, "PWM0"),
++ "AA16", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO203"),
++ MTK_FUNCTION(1, "PWM0"),
++ MTK_FUNCTION(2, "DISP_PWM")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(204, "PWM1"),
++ "Y16", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO204"),
++ MTK_FUNCTION(1, "PWM1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(205, "PWM2"),
++ "AA15", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO205"),
++ MTK_FUNCTION(1, "PWM2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(206, "PWM3"),
++ "AA17", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO206"),
++ MTK_FUNCTION(1, "PWM3")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(207, "PWM4"),
++ "Y15", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO207"),
++ MTK_FUNCTION(1, "PWM4")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(208, "AUD_EXT_CK1"),
++ "W14", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO208"),
++ MTK_FUNCTION(1, "AUD_EXT_CK1"),
++ MTK_FUNCTION(2, "PWM0"),
++ MTK_FUNCTION(3, "PCIE0_PERST_N"),
++ MTK_FUNCTION(5, "DISP_PWM")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(209, "AUD_EXT_CK2"),
++ "V15", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO209"),
++ MTK_FUNCTION(1, "AUD_EXT_CK2"),
++ MTK_FUNCTION(2, "MSDC1_WP"),
++ MTK_FUNCTION(3, "PCIE1_PERST_N"),
++ MTK_FUNCTION(5, "PWM1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(210, "GPIO210"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO210")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(211, "GPIO211"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO211")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(212, "GPIO212"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO212")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(213, "GPIO213"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO213")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(214, "GPIO214"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO214")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(215, "GPIO215"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO215")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(216, "GPIO216"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO216")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(217, "GPIO217"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO217")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(218, "GPIO218"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO218")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(219, "GPIO219"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO219")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(220, "GPIO220"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO220")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(221, "GPIO221"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO221")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(222, "GPIO222"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO222")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(223, "GPIO223"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO223")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(224, "GPIO224"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO224")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(225, "GPIO225"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO225")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(226, "GPIO226"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO226")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(227, "GPIO227"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO227")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(228, "GPIO228"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO228")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(229, "GPIO229"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO229")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(230, "GPIO230"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO230")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(231, "GPIO231"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO231")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(232, "GPIO232"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO232")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(233, "GPIO233"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO233")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(234, "GPIO234"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO234")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(235, "GPIO235"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO235")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(236, "EXT_SDIO3"),
++ "A8", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO236"),
++ MTK_FUNCTION(1, "EXT_SDIO3"),
++ MTK_FUNCTION(2, "IDDIG")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(237, "EXT_SDIO2"),
++ "D8", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO237"),
++ MTK_FUNCTION(1, "EXT_SDIO2"),
++ MTK_FUNCTION(2, "DRV_VBUS")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(238, "EXT_SDIO1"),
++ "D9", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO238"),
++ MTK_FUNCTION(1, "EXT_SDIO1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(239, "EXT_SDIO0"),
++ "B8", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO239"),
++ MTK_FUNCTION(1, "EXT_SDIO0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(240, "EXT_XCS"),
++ "C9", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO240"),
++ MTK_FUNCTION(1, "EXT_XCS")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(241, "EXT_SCK"),
++ "C8", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO241"),
++ MTK_FUNCTION(1, "EXT_SCK")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(242, "URTS2"),
++ "G18", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO242"),
++ MTK_FUNCTION(1, "URTS2"),
++ MTK_FUNCTION(2, "UTXD3"),
++ MTK_FUNCTION(3, "URXD3"),
++ MTK_FUNCTION(4, "SCL1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(243, "UCTS2"),
++ "H19", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO243"),
++ MTK_FUNCTION(1, "UCTS2"),
++ MTK_FUNCTION(2, "URXD3"),
++ MTK_FUNCTION(3, "UTXD3"),
++ MTK_FUNCTION(4, "SDA1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(244, "GPIO244"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO244")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(245, "GPIO245"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO245")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(246, "GPIO246"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO246")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(247, "GPIO247"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO247")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(248, "GPIO248"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO248")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(249, "GPIO249"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO249")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(250, "GPIO250"),
++ "A15", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO250"),
++ MTK_FUNCTION(1, "TEST_MD7"),
++ MTK_FUNCTION(6, "PCIE0_CLKREQ_N")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(251, "GPIO251"),
++ "B15", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO251"),
++ MTK_FUNCTION(1, "TEST_MD6"),
++ MTK_FUNCTION(6, "PCIE0_WAKE_N")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(252, "GPIO252"),
++ "C16", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO252"),
++ MTK_FUNCTION(1, "TEST_MD5"),
++ MTK_FUNCTION(6, "PCIE1_CLKREQ_N")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(253, "GPIO253"),
++ "D17", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO253"),
++ MTK_FUNCTION(1, "TEST_MD4"),
++ MTK_FUNCTION(6, "PCIE1_WAKE_N")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(254, "GPIO254"),
++ "D16", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO254"),
++ MTK_FUNCTION(1, "TEST_MD3"),
++ MTK_FUNCTION(6, "PCIE2_CLKREQ_N")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(255, "GPIO255"),
++ "C17", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO255"),
++ MTK_FUNCTION(1, "TEST_MD2"),
++ MTK_FUNCTION(6, "PCIE2_WAKE_N")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(256, "GPIO256"),
++ "B17", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO256"),
++ MTK_FUNCTION(1, "TEST_MD1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(257, "GPIO257"),
++ "C15", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO257"),
++ MTK_FUNCTION(1, "TEST_MD0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(258, "GPIO258"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO258")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(259, "GPIO259"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO259")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(260, "GPIO260"),
++ "N/C", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), MTK_FUNCTION(0, "GPIO260")
++
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(261, "MSDC1_INS"),
++ "AD1", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO261"),
++ MTK_FUNCTION(1, "MSDC1_INS")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(262, "G2_TXEN"),
++ "A23", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO262"),
++ MTK_FUNCTION(1, "G2_TXEN")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(263, "G2_TXD3"),
++ "N/A", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO263"),
++ MTK_FUNCTION(1, "G2_TXD3")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(264, "G2_TXD2"),
++ "C24", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO264"),
++ MTK_FUNCTION(1, "G2_TXD2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(265, "G2_TXD1"),
++ "B25", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO265"),
++ MTK_FUNCTION(1, "G2_TXD1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(266, "G2_TXD0"),
++ "A24", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO266"),
++ MTK_FUNCTION(1, "G2_TXD0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(267, "G2_TXCLK"),
++ "C23", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO267"),
++ MTK_FUNCTION(1, "G2_TXC")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(268, "G2_RXCLK"),
++ "B23", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO268"),
++ MTK_FUNCTION(1, "G2_RXC")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(269, "G2_RXD0"),
++ "D21", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO269"),
++ MTK_FUNCTION(1, "G2_RXD0")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(270, "G2_RXD1"),
++ "B22", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO270"),
++ MTK_FUNCTION(1, "G2_RXD1")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(271, "G2_RXD2"),
++ "A22", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO271"),
++ MTK_FUNCTION(1, "G2_RXD2")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(272, "G2_RXD3"),
++ "C22", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO272"),
++ MTK_FUNCTION(1, "G2_RXD3")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(273, "D2D_ESW_INT"),
++ "N/A", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO273"),
++ MTK_FUNCTION(1, "ESW_INT")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(274, "G2_RXDV"),
++ "C21", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO274"),
++ MTK_FUNCTION(1, "G2_RXDV")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(275, "G2_MDC"),
++ "N/A", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO275"),
++ MTK_FUNCTION(1, "MDC")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(276, "G2_MDIO"),
++ "N/A", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO276"),
++ MTK_FUNCTION(1, "MDIO")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(277, "D2D_ESW_RSTN"),
++ "N/A", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO277"),
++ MTK_FUNCTION(1, "ESW_RST")
++ ),
++ MTK_PIN(
++ PINCTRL_PIN(278, "JTAG_RESET"),
++ "H20", "mt7623",
++ MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++ MTK_FUNCTION(0, "GPIO278"),
++ MTK_FUNCTION(1, "JTAG_RESET")
++ ),
++};
++
++#endif /* __PINCTRL_MTK_MT7623_H */
+\ No newline at end of file
+diff --git a/include/dt-bindings/pinctrl/mt7623-pinfunc.h b/include/dt-bindings/pinctrl/mt7623-pinfunc.h
+new file mode 100644
+index 0000000..826835c
+--- /dev/null
++++ b/include/dt-bindings/pinctrl/mt7623-pinfunc.h
+@@ -0,0 +1,526 @@
++#ifndef __DTS_MT7623_PINFUNC_H
++#define __DTS_MT7623_PINFUNC_H
++
++#include <dt-bindings/pinctrl/mt65xx.h>
++
++#define MT7623_PIN_0_PWRAP_SPI0_MI_FUNC_GPIO0 (MTK_PIN_NO(0) | 0)
++#define MT7623_PIN_0_PWRAP_SPI0_MI_FUNC_PWRAP_SPIDO (MTK_PIN_NO(0) | 1)
++#define MT7623_PIN_0_PWRAP_SPI0_MI_FUNC_PWRAP_SPIDI (MTK_PIN_NO(0) | 2)
++
++#define MT7623_PIN_1_PWRAP_SPI0_MO_FUNC_GPIO1 (MTK_PIN_NO(1) | 0)
++#define MT7623_PIN_1_PWRAP_SPI0_MO_FUNC_PWRAP_SPIDI (MTK_PIN_NO(1) | 1)
++#define MT7623_PIN_1_PWRAP_SPI0_MO_FUNC_PWRAP_SPIDO (MTK_PIN_NO(1) | 2)
++
++#define MT7623_PIN_2_PWRAP_INT_FUNC_GPIO2 (MTK_PIN_NO(2) | 0)
++#define MT7623_PIN_2_PWRAP_INT_FUNC_PWRAP_INT (MTK_PIN_NO(2) | 1)
++
++#define MT7623_PIN_3_PWRAP_SPI0_CK_FUNC_GPIO3 (MTK_PIN_NO(3) | 0)
++#define MT7623_PIN_3_PWRAP_SPI0_CK_FUNC_PWRAP_SPICK_I (MTK_PIN_NO(3) | 1)
++
++#define MT7623_PIN_4_PWRAP_SPI0_CSN_FUNC_GPIO4 (MTK_PIN_NO(4) | 0)
++#define MT7623_PIN_4_PWRAP_SPI0_CSN_FUNC_PWRAP_SPICS_B_I (MTK_PIN_NO(4) | 1)
++
++#define MT7623_PIN_5_PWRAP_SPI0_CK2_FUNC_GPIO5 (MTK_PIN_NO(5) | 0)
++#define MT7623_PIN_5_PWRAP_SPI0_CK2_FUNC_PWRAP_SPICK2_I (MTK_PIN_NO(5) | 1)
++
++#define MT7623_PIN_6_PWRAP_SPI0_CSN2_FUNC_GPIO6 (MTK_PIN_NO(6) | 0)
++#define MT7623_PIN_6_PWRAP_SPI0_CSN2_FUNC_PWRAP_SPICS2_B_I (MTK_PIN_NO(6) | 1)
++
++#define MT7623_PIN_7_SPI1_CSN_FUNC_GPIO7 (MTK_PIN_NO(7) | 0)
++#define MT7623_PIN_7_SPI1_CSN_FUNC_SPI1_CS (MTK_PIN_NO(7) | 1)
++
++#define MT7623_PIN_8_SPI1_MI_FUNC_GPIO8 (MTK_PIN_NO(8) | 0)
++#define MT7623_PIN_8_SPI1_MI_FUNC_SPI1_MI (MTK_PIN_NO(8) | 1)
++#define MT7623_PIN_8_SPI1_MI_FUNC_SPI1_MO (MTK_PIN_NO(8) | 2)
++
++#define MT7623_PIN_9_SPI1_MO_FUNC_GPIO9 (MTK_PIN_NO(9) | 0)
++#define MT7623_PIN_9_SPI1_MO_FUNC_SPI1_MO (MTK_PIN_NO(9) | 1)
++#define MT7623_PIN_9_SPI1_MO_FUNC_SPI1_MI (MTK_PIN_NO(9) | 2)
++
++#define MT7623_PIN_10_RTC32K_CK_FUNC_GPIO10 (MTK_PIN_NO(10) | 0)
++#define MT7623_PIN_10_RTC32K_CK_FUNC_RTC32K_CK (MTK_PIN_NO(10) | 1)
++
++#define MT7623_PIN_11_WATCHDOG_FUNC_GPIO11 (MTK_PIN_NO(11) | 0)
++#define MT7623_PIN_11_WATCHDOG_FUNC_WATCHDOG (MTK_PIN_NO(11) | 1)
++
++#define MT7623_PIN_12_SRCLKENA_FUNC_GPIO12 (MTK_PIN_NO(12) | 0)
++#define MT7623_PIN_12_SRCLKENA_FUNC_SRCLKENA (MTK_PIN_NO(12) | 1)
++
++#define MT7623_PIN_13_SRCLKENAI_FUNC_GPIO13 (MTK_PIN_NO(13) | 0)
++#define MT7623_PIN_13_SRCLKENAI_FUNC_SRCLKENAI (MTK_PIN_NO(13) | 1)
++
++#define MT7623_PIN_14_GPIO14_FUNC_GPIO14 (MTK_PIN_NO(14) | 0)
++#define MT7623_PIN_14_GPIO14_FUNC_URXD2 (MTK_PIN_NO(14) | 1)
++#define MT7623_PIN_14_GPIO14_FUNC_UTXD2 (MTK_PIN_NO(14) | 2)
++
++#define MT7623_PIN_15_GPIO15_FUNC_GPIO15 (MTK_PIN_NO(15) | 0)
++#define MT7623_PIN_15_GPIO15_FUNC_UTXD2 (MTK_PIN_NO(15) | 1)
++#define MT7623_PIN_15_GPIO15_FUNC_URXD2 (MTK_PIN_NO(15) | 2)
++
++#define MT7623_PIN_18_PCM_CLK_FUNC_GPIO18 (MTK_PIN_NO(18) | 0)
++#define MT7623_PIN_18_PCM_CLK_FUNC_PCM_CLK0 (MTK_PIN_NO(18) | 1)
++#define MT7623_PIN_18_PCM_CLK_FUNC_AP_PCM_CLKO (MTK_PIN_NO(18) | 6)
++
++#define MT7623_PIN_19_PCM_SYNC_FUNC_GPIO19 (MTK_PIN_NO(19) | 0)
++#define MT7623_PIN_19_PCM_SYNC_FUNC_PCM_SYNC (MTK_PIN_NO(19) | 1)
++#define MT7623_PIN_19_PCM_SYNC_FUNC_AP_PCM_SYNC (MTK_PIN_NO(19) | 6)
++
++#define MT7623_PIN_20_PCM_RX_FUNC_GPIO20 (MTK_PIN_NO(20) | 0)
++#define MT7623_PIN_20_PCM_RX_FUNC_PCM_RX (MTK_PIN_NO(20) | 1)
++#define MT7623_PIN_20_PCM_RX_FUNC_PCM_TX (MTK_PIN_NO(20) | 4)
++#define MT7623_PIN_20_PCM_RX_FUNC_AP_PCM_RX (MTK_PIN_NO(20) | 6)
++
++#define MT7623_PIN_21_PCM_TX_FUNC_GPIO21 (MTK_PIN_NO(21) | 0)
++#define MT7623_PIN_21_PCM_TX_FUNC_PCM_TX (MTK_PIN_NO(21) | 1)
++#define MT7623_PIN_21_PCM_TX_FUNC_PCM_RX (MTK_PIN_NO(21) | 4)
++#define MT7623_PIN_21_PCM_TX_FUNC_AP_PCM_TX (MTK_PIN_NO(21) | 6)
++
++#define MT7623_PIN_22_EINT0_FUNC_GPIO22 (MTK_PIN_NO(22) | 0)
++#define MT7623_PIN_22_EINT0_FUNC_UCTS0 (MTK_PIN_NO(22) | 1)
++#define MT7623_PIN_22_EINT0_FUNC_PCIE0_PERST_N (MTK_PIN_NO(22) | 2)
++
++#define MT7623_PIN_23_EINT1_FUNC_GPIO23 (MTK_PIN_NO(23) | 0)
++#define MT7623_PIN_23_EINT1_FUNC_URTS0 (MTK_PIN_NO(23) | 1)
++#define MT7623_PIN_23_EINT1_FUNC_PCIE1_PERST_N (MTK_PIN_NO(23) | 2)
++
++#define MT7623_PIN_24_EINT2_FUNC_GPIO24 (MTK_PIN_NO(24) | 0)
++#define MT7623_PIN_24_EINT2_FUNC_UCTS1 (MTK_PIN_NO(24) | 1)
++#define MT7623_PIN_24_EINT2_FUNC_PCIE2_PERST_N (MTK_PIN_NO(24) | 2)
++
++#define MT7623_PIN_25_EINT3_FUNC_GPIO25 (MTK_PIN_NO(25) | 0)
++#define MT7623_PIN_25_EINT3_FUNC_URTS1 (MTK_PIN_NO(25) | 1)
++
++#define MT7623_PIN_26_EINT4_FUNC_GPIO26 (MTK_PIN_NO(26) | 0)
++#define MT7623_PIN_26_EINT4_FUNC_UCTS3 (MTK_PIN_NO(26) | 1)
++#define MT7623_PIN_26_EINT4_FUNC_PCIE2_WAKE_N (MTK_PIN_NO(26) | 6)
++
++#define MT7623_PIN_27_EINT5_FUNC_GPIO27 (MTK_PIN_NO(27) | 0)
++#define MT7623_PIN_27_EINT5_FUNC_URTS3 (MTK_PIN_NO(27) | 1)
++#define MT7623_PIN_27_EINT5_FUNC_PCIE1_WAKE_N (MTK_PIN_NO(27) | 6)
++
++#define MT7623_PIN_28_EINT6_FUNC_GPIO28 (MTK_PIN_NO(28) | 0)
++#define MT7623_PIN_28_EINT6_FUNC_DRV_VBUS (MTK_PIN_NO(28) | 1)
++#define MT7623_PIN_28_EINT6_FUNC_PCIE0_WAKE_N (MTK_PIN_NO(28) | 6)
++
++#define MT7623_PIN_29_EINT7_FUNC_GPIO29 (MTK_PIN_NO(29) | 0)
++#define MT7623_PIN_29_EINT7_FUNC_IDDIG (MTK_PIN_NO(29) | 1)
++#define MT7623_PIN_29_EINT7_FUNC_MSDC1_WP (MTK_PIN_NO(29) | 2)
++#define MT7623_PIN_29_EINT7_FUNC_PCIE2_PERST_N (MTK_PIN_NO(29) | 6)
++
++#define MT7623_PIN_33_I2S1_DATA_FUNC_GPIO33 (MTK_PIN_NO(33) | 0)
++#define MT7623_PIN_33_I2S1_DATA_FUNC_I2S1_DATA (MTK_PIN_NO(33) | 1)
++#define MT7623_PIN_33_I2S1_DATA_FUNC_PCM_TX (MTK_PIN_NO(33) | 3)
++#define MT7623_PIN_33_I2S1_DATA_FUNC_AP_PCM_TX (MTK_PIN_NO(33) | 6)
++
++#define MT7623_PIN_34_I2S1_DATA_IN_FUNC_GPIO34 (MTK_PIN_NO(34) | 0)
++#define MT7623_PIN_34_I2S1_DATA_IN_FUNC_I2S1_DATA_IN (MTK_PIN_NO(34) | 1)
++#define MT7623_PIN_34_I2S1_DATA_IN_FUNC_PCM_RX (MTK_PIN_NO(34) | 3)
++#define MT7623_PIN_34_I2S1_DATA_IN_FUNC_AP_PCM_RX (MTK_PIN_NO(34) | 6)
++
++#define MT7623_PIN_35_I2S1_BCK_FUNC_GPIO35 (MTK_PIN_NO(35) | 0)
++#define MT7623_PIN_35_I2S1_BCK_FUNC_I2S1_BCK (MTK_PIN_NO(35) | 1)
++#define MT7623_PIN_35_I2S1_BCK_FUNC_PCM_CLK0 (MTK_PIN_NO(35) | 3)
++#define MT7623_PIN_35_I2S1_BCK_FUNC_AP_PCM_CLKO (MTK_PIN_NO(35) | 6)
++
++#define MT7623_PIN_36_I2S1_LRCK_FUNC_GPIO36 (MTK_PIN_NO(36) | 0)
++#define MT7623_PIN_36_I2S1_LRCK_FUNC_I2S1_LRCK (MTK_PIN_NO(36) | 1)
++#define MT7623_PIN_36_I2S1_LRCK_FUNC_PCM_SYNC (MTK_PIN_NO(36) | 3)
++#define MT7623_PIN_36_I2S1_LRCK_FUNC_AP_PCM_SYNC (MTK_PIN_NO(36) | 6)
++
++#define MT7623_PIN_37_I2S1_MCLK_FUNC_GPIO37 (MTK_PIN_NO(37) | 0)
++#define MT7623_PIN_37_I2S1_MCLK_FUNC_I2S1_MCLK (MTK_PIN_NO(37) | 1)
++
++#define MT7623_PIN_39_JTMS_FUNC_GPIO39 (MTK_PIN_NO(39) | 0)
++#define MT7623_PIN_39_JTMS_FUNC_JTMS (MTK_PIN_NO(39) | 1)
++
++#define MT7623_PIN_40_JTCK_FUNC_GPIO40 (MTK_PIN_NO(40) | 0)
++#define MT7623_PIN_40_JTCK_FUNC_JTCK (MTK_PIN_NO(40) | 1)
++
++#define MT7623_PIN_41_JTDI_FUNC_GPIO41 (MTK_PIN_NO(41) | 0)
++#define MT7623_PIN_41_JTDI_FUNC_JTDI (MTK_PIN_NO(41) | 1)
++
++#define MT7623_PIN_42_JTDO_FUNC_GPIO42 (MTK_PIN_NO(42) | 0)
++#define MT7623_PIN_42_JTDO_FUNC_JTDO (MTK_PIN_NO(42) | 1)
++
++#define MT7623_PIN_43_NCLE_FUNC_GPIO43 (MTK_PIN_NO(43) | 0)
++#define MT7623_PIN_43_NCLE_FUNC_NCLE (MTK_PIN_NO(43) | 1)
++#define MT7623_PIN_43_NCLE_FUNC_EXT_XCS2 (MTK_PIN_NO(43) | 2)
++
++#define MT7623_PIN_44_NCEB1_FUNC_GPIO44 (MTK_PIN_NO(44) | 0)
++#define MT7623_PIN_44_NCEB1_FUNC_NCEB1 (MTK_PIN_NO(44) | 1)
++#define MT7623_PIN_44_NCEB1_FUNC_IDDIG (MTK_PIN_NO(44) | 2)
++
++#define MT7623_PIN_45_NCEB0_FUNC_GPIO45 (MTK_PIN_NO(45) | 0)
++#define MT7623_PIN_45_NCEB0_FUNC_NCEB0 (MTK_PIN_NO(45) | 1)
++#define MT7623_PIN_45_NCEB0_FUNC_DRV_VBUS (MTK_PIN_NO(45) | 2)
++
++#define MT7623_PIN_46_IR_FUNC_GPIO46 (MTK_PIN_NO(46) | 0)
++#define MT7623_PIN_46_IR_FUNC_IR (MTK_PIN_NO(46) | 1)
++
++#define MT7623_PIN_47_NREB_FUNC_GPIO47 (MTK_PIN_NO(47) | 0)
++#define MT7623_PIN_47_NREB_FUNC_NREB (MTK_PIN_NO(47) | 1)
++
++#define MT7623_PIN_48_NRNB_FUNC_GPIO48 (MTK_PIN_NO(48) | 0)
++#define MT7623_PIN_48_NRNB_FUNC_NRNB (MTK_PIN_NO(48) | 1)
++
++#define MT7623_PIN_49_I2S0_DATA_FUNC_GPIO49 (MTK_PIN_NO(49) | 0)
++#define MT7623_PIN_49_I2S0_DATA_FUNC_I2S0_DATA (MTK_PIN_NO(49) | 1)
++#define MT7623_PIN_49_I2S0_DATA_FUNC_PCM_TX (MTK_PIN_NO(49) | 3)
++#define MT7623_PIN_49_I2S0_DATA_FUNC_AP_I2S_DO (MTK_PIN_NO(49) | 6)
++
++#define MT7623_PIN_53_SPI0_CSN_FUNC_GPIO53 (MTK_PIN_NO(53) | 0)
++#define MT7623_PIN_53_SPI0_CSN_FUNC_SPI0_CS (MTK_PIN_NO(53) | 1)
++#define MT7623_PIN_53_SPI0_CSN_FUNC_PWM1 (MTK_PIN_NO(53) | 5)
++
++#define MT7623_PIN_54_SPI0_CK_FUNC_GPIO54 (MTK_PIN_NO(54) | 0)
++#define MT7623_PIN_54_SPI0_CK_FUNC_SPI0_CK (MTK_PIN_NO(54) | 1)
++
++#define MT7623_PIN_55_SPI0_MI_FUNC_GPIO55 (MTK_PIN_NO(55) | 0)
++#define MT7623_PIN_55_SPI0_MI_FUNC_SPI0_MI (MTK_PIN_NO(55) | 1)
++#define MT7623_PIN_55_SPI0_MI_FUNC_SPI0_MO (MTK_PIN_NO(55) | 2)
++#define MT7623_PIN_55_SPI0_MI_FUNC_MSDC1_WP (MTK_PIN_NO(55) | 3)
++#define MT7623_PIN_55_SPI0_MI_FUNC_PWM2 (MTK_PIN_NO(55) | 5)
++
++#define MT7623_PIN_56_SPI0_MO_FUNC_GPIO56 (MTK_PIN_NO(56) | 0)
++#define MT7623_PIN_56_SPI0_MO_FUNC_SPI0_MO (MTK_PIN_NO(56) | 1)
++#define MT7623_PIN_56_SPI0_MO_FUNC_SPI0_MI (MTK_PIN_NO(56) | 2)
++
++#define MT7623_PIN_60_WB_RSTB_FUNC_GPIO60 (MTK_PIN_NO(60) | 0)
++#define MT7623_PIN_60_WB_RSTB_FUNC_WB_RSTB (MTK_PIN_NO(60) | 1)
++
++#define MT7623_PIN_61_GPIO61_FUNC_GPIO61 (MTK_PIN_NO(61) | 0)
++#define MT7623_PIN_61_GPIO61_FUNC_TEST_FD (MTK_PIN_NO(61) | 1)
++
++#define MT7623_PIN_62_GPIO62_FUNC_GPIO62 (MTK_PIN_NO(62) | 0)
++#define MT7623_PIN_62_GPIO62_FUNC_TEST_FC (MTK_PIN_NO(62) | 1)
++
++#define MT7623_PIN_63_WB_SCLK_FUNC_GPIO63 (MTK_PIN_NO(63) | 0)
++#define MT7623_PIN_63_WB_SCLK_FUNC_WB_SCLK (MTK_PIN_NO(63) | 1)
++
++#define MT7623_PIN_64_WB_SDATA_FUNC_GPIO64 (MTK_PIN_NO(64) | 0)
++#define MT7623_PIN_64_WB_SDATA_FUNC_WB_SDATA (MTK_PIN_NO(64) | 1)
++
++#define MT7623_PIN_65_WB_SEN_FUNC_GPIO65 (MTK_PIN_NO(65) | 0)
++#define MT7623_PIN_65_WB_SEN_FUNC_WB_SEN (MTK_PIN_NO(65) | 1)
++
++#define MT7623_PIN_66_WB_CRTL0_FUNC_GPIO66 (MTK_PIN_NO(66) | 0)
++#define MT7623_PIN_66_WB_CRTL0_FUNC_WB_CRTL0 (MTK_PIN_NO(66) | 1)
++
++#define MT7623_PIN_67_WB_CRTL1_FUNC_GPIO67 (MTK_PIN_NO(67) | 0)
++#define MT7623_PIN_67_WB_CRTL1_FUNC_WB_CRTL1 (MTK_PIN_NO(67) | 1)
++
++#define MT7623_PIN_68_WB_CRTL2_FUNC_GPIO68 (MTK_PIN_NO(68) | 0)
++#define MT7623_PIN_68_WB_CRTL2_FUNC_WB_CRTL2 (MTK_PIN_NO(68) | 1)
++
++#define MT7623_PIN_69_WB_CRTL3_FUNC_GPIO69 (MTK_PIN_NO(69) | 0)
++#define MT7623_PIN_69_WB_CRTL3_FUNC_WB_CRTL3 (MTK_PIN_NO(69) | 1)
++
++#define MT7623_PIN_70_WB_CRTL4_FUNC_GPIO70 (MTK_PIN_NO(70) | 0)
++#define MT7623_PIN_70_WB_CRTL4_FUNC_WB_CRTL4 (MTK_PIN_NO(70) | 1)
++
++#define MT7623_PIN_71_WB_CRTL5_FUNC_GPIO71 (MTK_PIN_NO(71) | 0)
++#define MT7623_PIN_71_WB_CRTL5_FUNC_WB_CRTL5 (MTK_PIN_NO(71) | 1)
++
++#define MT7623_PIN_72_I2S0_DATA_IN_FUNC_GPIO72 (MTK_PIN_NO(72) | 0)
++#define MT7623_PIN_72_I2S0_DATA_IN_FUNC_I2S0_DATA_IN (MTK_PIN_NO(72) | 1)
++#define MT7623_PIN_72_I2S0_DATA_IN_FUNC_PCM_RX (MTK_PIN_NO(72) | 3)
++#define MT7623_PIN_72_I2S0_DATA_IN_FUNC_PWM0 (MTK_PIN_NO(72) | 4)
++#define MT7623_PIN_72_I2S0_DATA_IN_FUNC_DISP_PWM (MTK_PIN_NO(72) | 5)
++#define MT7623_PIN_72_I2S0_DATA_IN_FUNC_AP_I2S_DI (MTK_PIN_NO(72) | 6)
++
++#define MT7623_PIN_73_I2S0_LRCK_FUNC_GPIO73 (MTK_PIN_NO(73) | 0)
++#define MT7623_PIN_73_I2S0_LRCK_FUNC_I2S0_LRCK (MTK_PIN_NO(73) | 1)
++#define MT7623_PIN_73_I2S0_LRCK_FUNC_PCM_SYNC (MTK_PIN_NO(73) | 3)
++#define MT7623_PIN_73_I2S0_LRCK_FUNC_AP_I2S_LRCK (MTK_PIN_NO(73) | 6)
++
++#define MT7623_PIN_74_I2S0_BCK_FUNC_GPIO74 (MTK_PIN_NO(74) | 0)
++#define MT7623_PIN_74_I2S0_BCK_FUNC_I2S0_BCK (MTK_PIN_NO(74) | 1)
++#define MT7623_PIN_74_I2S0_BCK_FUNC_PCM_CLK0 (MTK_PIN_NO(74) | 3)
++#define MT7623_PIN_74_I2S0_BCK_FUNC_AP_I2S_BCK (MTK_PIN_NO(74) | 6)
++
++#define MT7623_PIN_75_SDA0_FUNC_GPIO75 (MTK_PIN_NO(75) | 0)
++#define MT7623_PIN_75_SDA0_FUNC_SDA0 (MTK_PIN_NO(75) | 1)
++
++#define MT7623_PIN_76_SCL0_FUNC_GPIO76 (MTK_PIN_NO(76) | 0)
++#define MT7623_PIN_76_SCL0_FUNC_SCL0 (MTK_PIN_NO(76) | 1)
++
++#define MT7623_PIN_83_LCM_RST_FUNC_GPIO83 (MTK_PIN_NO(83) | 0)
++#define MT7623_PIN_83_LCM_RST_FUNC_LCM_RST (MTK_PIN_NO(83) | 1)
++
++#define MT7623_PIN_84_DSI_TE_FUNC_GPIO84 (MTK_PIN_NO(84) | 0)
++#define MT7623_PIN_84_DSI_TE_FUNC_DSI_TE (MTK_PIN_NO(84) | 1)
++
++#define MT7623_PIN_95_MIPI_TCN_FUNC_GPIO95 (MTK_PIN_NO(95) | 0)
++#define MT7623_PIN_95_MIPI_TCN_FUNC_TCN (MTK_PIN_NO(95) | 1)
++
++#define MT7623_PIN_96_MIPI_TCP_FUNC_GPIO96 (MTK_PIN_NO(96) | 0)
++#define MT7623_PIN_96_MIPI_TCP_FUNC_TCP (MTK_PIN_NO(96) | 1)
++
++#define MT7623_PIN_97_MIPI_TDN1_FUNC_GPIO97 (MTK_PIN_NO(97) | 0)
++#define MT7623_PIN_97_MIPI_TDN1_FUNC_TDN1 (MTK_PIN_NO(97) | 1)
++
++#define MT7623_PIN_98_MIPI_TDP1_FUNC_GPIO98 (MTK_PIN_NO(98) | 0)
++#define MT7623_PIN_98_MIPI_TDP1_FUNC_TDP1 (MTK_PIN_NO(98) | 1)
++
++#define MT7623_PIN_99_MIPI_TDN0_FUNC_GPIO99 (MTK_PIN_NO(99) | 0)
++#define MT7623_PIN_99_MIPI_TDN0_FUNC_TDN0 (MTK_PIN_NO(99) | 1)
++
++#define MT7623_PIN_100_MIPI_TDP0_FUNC_GPIO100 (MTK_PIN_NO(100) | 0)
++#define MT7623_PIN_100_MIPI_TDP0_FUNC_TDP0 (MTK_PIN_NO(100) | 1)
++
++#define MT7623_PIN_105_MSDC1_CMD_FUNC_GPIO105 (MTK_PIN_NO(105) | 0)
++#define MT7623_PIN_105_MSDC1_CMD_FUNC_MSDC1_CMD (MTK_PIN_NO(105) | 1)
++#define MT7623_PIN_105_MSDC1_CMD_FUNC_SDA1 (MTK_PIN_NO(105) | 3)
++#define MT7623_PIN_105_MSDC1_CMD_FUNC_I2SOUT_BCK (MTK_PIN_NO(105) | 6)
++
++#define MT7623_PIN_106_MSDC1_CLK_FUNC_GPIO106 (MTK_PIN_NO(106) | 0)
++#define MT7623_PIN_106_MSDC1_CLK_FUNC_MSDC1_CLK (MTK_PIN_NO(106) | 1)
++#define MT7623_PIN_106_MSDC1_CLK_FUNC_SCL1 (MTK_PIN_NO(106) | 3)
++#define MT7623_PIN_106_MSDC1_CLK_FUNC_I2SOUT_LRCK (MTK_PIN_NO(106) | 6)
++
++#define MT7623_PIN_107_MSDC1_DAT0_FUNC_GPIO107 (MTK_PIN_NO(107) | 0)
++#define MT7623_PIN_107_MSDC1_DAT0_FUNC_MSDC1_DAT0 (MTK_PIN_NO(107) | 1)
++#define MT7623_PIN_107_MSDC1_DAT0_FUNC_UTXD0 (MTK_PIN_NO(107) | 5)
++#define MT7623_PIN_107_MSDC1_DAT0_FUNC_I2SOUT_DATA_OUT (MTK_PIN_NO(107) | 6)
++
++#define MT7623_PIN_108_MSDC1_DAT1_FUNC_GPIO108 (MTK_PIN_NO(108) | 0)
++#define MT7623_PIN_108_MSDC1_DAT1_FUNC_MSDC1_DAT1 (MTK_PIN_NO(108) | 1)
++#define MT7623_PIN_108_MSDC1_DAT1_FUNC_PWM0 (MTK_PIN_NO(108) | 3)
++#define MT7623_PIN_108_MSDC1_DAT1_FUNC_URXD0 (MTK_PIN_NO(108) | 5)
++#define MT7623_PIN_108_MSDC1_DAT1_FUNC_PWM1 (MTK_PIN_NO(108) | 6)
++
++#define MT7623_PIN_109_MSDC1_DAT2_FUNC_GPIO109 (MTK_PIN_NO(109) | 0)
++#define MT7623_PIN_109_MSDC1_DAT2_FUNC_MSDC1_DAT2 (MTK_PIN_NO(109) | 1)
++#define MT7623_PIN_109_MSDC1_DAT2_FUNC_SDA2 (MTK_PIN_NO(109) | 3)
++#define MT7623_PIN_109_MSDC1_DAT2_FUNC_UTXD1 (MTK_PIN_NO(109) | 5)
++#define MT7623_PIN_109_MSDC1_DAT2_FUNC_PWM2 (MTK_PIN_NO(109) | 6)
++
++#define MT7623_PIN_110_MSDC1_DAT3_FUNC_GPIO110 (MTK_PIN_NO(110) | 0)
++#define MT7623_PIN_110_MSDC1_DAT3_FUNC_MSDC1_DAT3 (MTK_PIN_NO(110) | 1)
++#define MT7623_PIN_110_MSDC1_DAT3_FUNC_SCL2 (MTK_PIN_NO(110) | 3)
++#define MT7623_PIN_110_MSDC1_DAT3_FUNC_URXD1 (MTK_PIN_NO(110) | 5)
++#define MT7623_PIN_110_MSDC1_DAT3_FUNC_PWM3 (MTK_PIN_NO(110) | 6)
++
++#define MT7623_PIN_111_MSDC0_DAT7_FUNC_GPIO111 (MTK_PIN_NO(111) | 0)
++#define MT7623_PIN_111_MSDC0_DAT7_FUNC_MSDC0_DAT7 (MTK_PIN_NO(111) | 1)
++#define MT7623_PIN_111_MSDC0_DAT7_FUNC_NLD7 (MTK_PIN_NO(111) | 4)
++
++#define MT7623_PIN_112_MSDC0_DAT6_FUNC_GPIO112 (MTK_PIN_NO(112) | 0)
++#define MT7623_PIN_112_MSDC0_DAT6_FUNC_MSDC0_DAT6 (MTK_PIN_NO(112) | 1)
++#define MT7623_PIN_112_MSDC0_DAT6_FUNC_NLD6 (MTK_PIN_NO(112) | 4)
++
++#define MT7623_PIN_113_MSDC0_DAT5_FUNC_GPIO113 (MTK_PIN_NO(113) | 0)
++#define MT7623_PIN_113_MSDC0_DAT5_FUNC_MSDC0_DAT5 (MTK_PIN_NO(113) | 1)
++#define MT7623_PIN_113_MSDC0_DAT5_FUNC_NLD5 (MTK_PIN_NO(113) | 4)
++
++#define MT7623_PIN_114_MSDC0_DAT4_FUNC_GPIO114 (MTK_PIN_NO(114) | 0)
++#define MT7623_PIN_114_MSDC0_DAT4_FUNC_MSDC0_DAT4 (MTK_PIN_NO(114) | 1)
++#define MT7623_PIN_114_MSDC0_DAT4_FUNC_NLD4 (MTK_PIN_NO(114) | 4)
++
++#define MT7623_PIN_115_MSDC0_RSTB_FUNC_GPIO115 (MTK_PIN_NO(115) | 0)
++#define MT7623_PIN_115_MSDC0_RSTB_FUNC_MSDC0_RSTB (MTK_PIN_NO(115) | 1)
++#define MT7623_PIN_115_MSDC0_RSTB_FUNC_NLD8 (MTK_PIN_NO(115) | 4)
++
++#define MT7623_PIN_116_MSDC0_CMD_FUNC_GPIO116 (MTK_PIN_NO(116) | 0)
++#define MT7623_PIN_116_MSDC0_CMD_FUNC_MSDC0_CMD (MTK_PIN_NO(116) | 1)
++#define MT7623_PIN_116_MSDC0_CMD_FUNC_NALE (MTK_PIN_NO(116) | 4)
++
++#define MT7623_PIN_117_MSDC0_CLK_FUNC_GPIO117 (MTK_PIN_NO(117) | 0)
++#define MT7623_PIN_117_MSDC0_CLK_FUNC_MSDC0_CLK (MTK_PIN_NO(117) | 1)
++#define MT7623_PIN_117_MSDC0_CLK_FUNC_NWEB (MTK_PIN_NO(117) | 4)
++
++#define MT7623_PIN_118_MSDC0_DAT3_FUNC_GPIO118 (MTK_PIN_NO(118) | 0)
++#define MT7623_PIN_118_MSDC0_DAT3_FUNC_MSDC0_DAT3 (MTK_PIN_NO(118) | 1)
++#define MT7623_PIN_118_MSDC0_DAT3_FUNC_NLD3 (MTK_PIN_NO(118) | 4)
++
++#define MT7623_PIN_119_MSDC0_DAT2_FUNC_GPIO119 (MTK_PIN_NO(119) | 0)
++#define MT7623_PIN_119_MSDC0_DAT2_FUNC_MSDC0_DAT2 (MTK_PIN_NO(119) | 1)
++#define MT7623_PIN_119_MSDC0_DAT2_FUNC_NLD2 (MTK_PIN_NO(119) | 4)
++
++#define MT7623_PIN_120_MSDC0_DAT1_FUNC_GPIO120 (MTK_PIN_NO(120) | 0)
++#define MT7623_PIN_120_MSDC0_DAT1_FUNC_MSDC0_DAT1 (MTK_PIN_NO(120) | 1)
++#define MT7623_PIN_120_MSDC0_DAT1_FUNC_NLD1 (MTK_PIN_NO(120) | 4)
++
++#define MT7623_PIN_121_MSDC0_DAT0_FUNC_GPIO121 (MTK_PIN_NO(121) | 0)
++#define MT7623_PIN_121_MSDC0_DAT0_FUNC_MSDC0_DAT0 (MTK_PIN_NO(121) | 1)
++#define MT7623_PIN_121_MSDC0_DAT0_FUNC_NLD0 (MTK_PIN_NO(121) | 4)
++#define MT7623_PIN_121_MSDC0_DAT0_FUNC_WATCHDOG (MTK_PIN_NO(121) | 5)
++
++#define MT7623_PIN_122_GPIO122_FUNC_GPIO122 (MTK_PIN_NO(122) | 0)
++#define MT7623_PIN_122_GPIO122_FUNC_TEST (MTK_PIN_NO(122) | 1)
++#define MT7623_PIN_122_GPIO122_FUNC_SDA2 (MTK_PIN_NO(122) | 4)
++#define MT7623_PIN_122_GPIO122_FUNC_URXD0 (MTK_PIN_NO(122) | 5)
++
++#define MT7623_PIN_123_GPIO123_FUNC_GPIO123 (MTK_PIN_NO(123) | 0)
++#define MT7623_PIN_123_GPIO123_FUNC_TEST (MTK_PIN_NO(123) | 1)
++#define MT7623_PIN_123_GPIO123_FUNC_SCL2 (MTK_PIN_NO(123) | 4)
++#define MT7623_PIN_123_GPIO123_FUNC_UTXD0 (MTK_PIN_NO(123) | 5)
++
++#define MT7623_PIN_124_GPIO124_FUNC_GPIO124 (MTK_PIN_NO(124) | 0)
++#define MT7623_PIN_124_GPIO124_FUNC_TEST (MTK_PIN_NO(124) | 1)
++#define MT7623_PIN_124_GPIO124_FUNC_SDA1 (MTK_PIN_NO(124) | 4)
++#define MT7623_PIN_124_GPIO124_FUNC_PWM3 (MTK_PIN_NO(124) | 5)
++
++#define MT7623_PIN_125_GPIO125_FUNC_GPIO125 (MTK_PIN_NO(125) | 0)
++#define MT7623_PIN_125_GPIO125_FUNC_TEST (MTK_PIN_NO(125) | 1)
++#define MT7623_PIN_125_GPIO125_FUNC_SCL1 (MTK_PIN_NO(125) | 4)
++#define MT7623_PIN_125_GPIO125_FUNC_PWM4 (MTK_PIN_NO(125) | 5)
++
++#define MT7623_PIN_126_I2S0_MCLK_FUNC_GPIO126 (MTK_PIN_NO(126) | 0)
++#define MT7623_PIN_126_I2S0_MCLK_FUNC_I2S0_MCLK (MTK_PIN_NO(126) | 1)
++#define MT7623_PIN_126_I2S0_MCLK_FUNC_AP_I2S_MCLK (MTK_PIN_NO(126) | 6)
++
++#define MT7623_PIN_199_SPI1_CK_FUNC_GPIO199 (MTK_PIN_NO(199) | 0)
++#define MT7623_PIN_199_SPI1_CK_FUNC_SPI1_CK (MTK_PIN_NO(199) | 1)
++
++#define MT7623_PIN_200_URXD2_FUNC_GPIO200 (MTK_PIN_NO(200) | 0)
++#define MT7623_PIN_200_URXD2_FUNC_URXD2 (MTK_PIN_NO(200) | 6)
++
++#define MT7623_PIN_201_UTXD2_FUNC_GPIO201 (MTK_PIN_NO(201) | 0)
++#define MT7623_PIN_201_UTXD2_FUNC_UTXD2 (MTK_PIN_NO(201) | 6)
++
++#define MT7623_PIN_203_PWM0_FUNC_GPIO203 (MTK_PIN_NO(203) | 0)
++#define MT7623_PIN_203_PWM0_FUNC_PWM0 (MTK_PIN_NO(203) | 1)
++#define MT7623_PIN_203_PWM0_FUNC_DISP_PWM (MTK_PIN_NO(203) | 2)
++
++#define MT7623_PIN_204_PWM1_FUNC_GPIO204 (MTK_PIN_NO(204) | 0)
++#define MT7623_PIN_204_PWM1_FUNC_PWM1 (MTK_PIN_NO(204) | 1)
++
++#define MT7623_PIN_205_PWM2_FUNC_GPIO205 (MTK_PIN_NO(205) | 0)
++#define MT7623_PIN_205_PWM2_FUNC_PWM2 (MTK_PIN_NO(205) | 1)
++
++#define MT7623_PIN_206_PWM3_FUNC_GPIO206 (MTK_PIN_NO(206) | 0)
++#define MT7623_PIN_206_PWM3_FUNC_PWM3 (MTK_PIN_NO(206) | 1)
++
++#define MT7623_PIN_207_PWM4_FUNC_GPIO207 (MTK_PIN_NO(207) | 0)
++#define MT7623_PIN_207_PWM4_FUNC_PWM4 (MTK_PIN_NO(207) | 1)
++
++#define MT7623_PIN_208_AUD_EXT_CK1_FUNC_GPIO208 (MTK_PIN_NO(208) | 0)
++#define MT7623_PIN_208_AUD_EXT_CK1_FUNC_AUD_EXT_CK1 (MTK_PIN_NO(208) | 1)
++#define MT7623_PIN_208_AUD_EXT_CK1_FUNC_PWM0 (MTK_PIN_NO(208) | 2)
++#define MT7623_PIN_208_AUD_EXT_CK1_FUNC_PCIE0_PERST_N (MTK_PIN_NO(208) | 3)
++#define MT7623_PIN_208_AUD_EXT_CK1_FUNC_DISP_PWM (MTK_PIN_NO(208) | 5)
++
++#define MT7623_PIN_209_AUD_EXT_CK2_FUNC_GPIO209 (MTK_PIN_NO(209) | 0)
++#define MT7623_PIN_209_AUD_EXT_CK2_FUNC_AUD_EXT_CK2 (MTK_PIN_NO(209) | 1)
++#define MT7623_PIN_209_AUD_EXT_CK2_FUNC_MSDC1_WP (MTK_PIN_NO(209) | 2)
++#define MT7623_PIN_209_AUD_EXT_CK2_FUNC_PCIE1_PERST_N (MTK_PIN_NO(209) | 3)
++#define MT7623_PIN_209_AUD_EXT_CK2_FUNC_PWM1 (MTK_PIN_NO(209) | 5)
++
++#define MT7623_PIN_236_EXT_SDIO3_FUNC_GPIO236 (MTK_PIN_NO(236) | 0)
++#define MT7623_PIN_236_EXT_SDIO3_FUNC_EXT_SDIO3 (MTK_PIN_NO(236) | 1)
++#define MT7623_PIN_236_EXT_SDIO3_FUNC_IDDIG (MTK_PIN_NO(236) | 2)
++
++#define MT7623_PIN_237_EXT_SDIO2_FUNC_GPIO237 (MTK_PIN_NO(237) | 0)
++#define MT7623_PIN_237_EXT_SDIO2_FUNC_EXT_SDIO2 (MTK_PIN_NO(237) | 1)
++#define MT7623_PIN_237_EXT_SDIO2_FUNC_DRV_VBUS (MTK_PIN_NO(237) | 2)
++
++#define MT7623_PIN_238_EXT_SDIO1_FUNC_GPIO238 (MTK_PIN_NO(238) | 0)
++#define MT7623_PIN_238_EXT_SDIO1_FUNC_EXT_SDIO1 (MTK_PIN_NO(238) | 1)
++
++#define MT7623_PIN_239_EXT_SDIO0_FUNC_GPIO239 (MTK_PIN_NO(239) | 0)
++#define MT7623_PIN_239_EXT_SDIO0_FUNC_EXT_SDIO0 (MTK_PIN_NO(239) | 1)
++
++#define MT7623_PIN_240_EXT_XCS_FUNC_GPIO240 (MTK_PIN_NO(240) | 0)
++#define MT7623_PIN_240_EXT_XCS_FUNC_EXT_XCS (MTK_PIN_NO(240) | 1)
++
++#define MT7623_PIN_241_EXT_SCK_FUNC_GPIO241 (MTK_PIN_NO(241) | 0)
++#define MT7623_PIN_241_EXT_SCK_FUNC_EXT_SCK (MTK_PIN_NO(241) | 1)
++
++#define MT7623_PIN_242_URTS2_FUNC_GPIO242 (MTK_PIN_NO(242) | 0)
++#define MT7623_PIN_242_URTS2_FUNC_URTS2 (MTK_PIN_NO(242) | 1)
++#define MT7623_PIN_242_URTS2_FUNC_UTXD3 (MTK_PIN_NO(242) | 2)
++#define MT7623_PIN_242_URTS2_FUNC_URXD3 (MTK_PIN_NO(242) | 3)
++#define MT7623_PIN_242_URTS2_FUNC_SCL1 (MTK_PIN_NO(242) | 4)
++
++#define MT7623_PIN_243_UCTS2_FUNC_GPIO243 (MTK_PIN_NO(243) | 0)
++#define MT7623_PIN_243_UCTS2_FUNC_UCTS2 (MTK_PIN_NO(243) | 1)
++#define MT7623_PIN_243_UCTS2_FUNC_URXD3 (MTK_PIN_NO(243) | 2)
++#define MT7623_PIN_243_UCTS2_FUNC_UTXD3 (MTK_PIN_NO(243) | 3)
++#define MT7623_PIN_243_UCTS2_FUNC_SDA1 (MTK_PIN_NO(243) | 4)
++
++#define MT7623_PIN_250_GPIO250_FUNC_GPIO250 (MTK_PIN_NO(250) | 0)
++#define MT7623_PIN_250_GPIO250_FUNC_TEST_MD7 (MTK_PIN_NO(250) | 1)
++#define MT7623_PIN_250_GPIO250_FUNC_PCIE0_CLKREQ_N (MTK_PIN_NO(250) | 6)
++
++#define MT7623_PIN_251_GPIO251_FUNC_GPIO251 (MTK_PIN_NO(251) | 0)
++#define MT7623_PIN_251_GPIO251_FUNC_TEST_MD6 (MTK_PIN_NO(251) | 1)
++#define MT7623_PIN_251_GPIO251_FUNC_PCIE0_WAKE_N (MTK_PIN_NO(251) | 6)
++
++#define MT7623_PIN_252_GPIO252_FUNC_GPIO252 (MTK_PIN_NO(252) | 0)
++#define MT7623_PIN_252_GPIO252_FUNC_TEST_MD5 (MTK_PIN_NO(252) | 1)
++#define MT7623_PIN_252_GPIO252_FUNC_PCIE1_CLKREQ_N (MTK_PIN_NO(252) | 6)
++
++#define MT7623_PIN_253_GPIO253_FUNC_GPIO253 (MTK_PIN_NO(253) | 0)
++#define MT7623_PIN_253_GPIO253_FUNC_TEST_MD4 (MTK_PIN_NO(253) | 1)
++#define MT7623_PIN_253_GPIO253_FUNC_PCIE1_WAKE_N (MTK_PIN_NO(253) | 6)
++
++#define MT7623_PIN_254_GPIO254_FUNC_GPIO254 (MTK_PIN_NO(254) | 0)
++#define MT7623_PIN_254_GPIO254_FUNC_TEST_MD3 (MTK_PIN_NO(254) | 1)
++#define MT7623_PIN_254_GPIO254_FUNC_PCIE2_CLKREQ_N (MTK_PIN_NO(254) | 6)
++
++#define MT7623_PIN_255_GPIO255_FUNC_GPIO255 (MTK_PIN_NO(255) | 0)
++#define MT7623_PIN_255_GPIO255_FUNC_TEST_MD2 (MTK_PIN_NO(255) | 1)
++#define MT7623_PIN_255_GPIO255_FUNC_PCIE2_WAKE_N (MTK_PIN_NO(255) | 6)
++
++#define MT7623_PIN_256_GPIO256_FUNC_GPIO256 (MTK_PIN_NO(256) | 0)
++#define MT7623_PIN_256_GPIO256_FUNC_TEST_MD1 (MTK_PIN_NO(256) | 1)
++
++#define MT7623_PIN_257_GPIO257_FUNC_GPIO257 (MTK_PIN_NO(257) | 0)
++#define MT7623_PIN_257_GPIO257_FUNC_TEST_MD0 (MTK_PIN_NO(257) | 1)
++
++#define MT7623_PIN_261_MSDC1_INS_FUNC_GPIO261 (MTK_PIN_NO(261) | 0)
++#define MT7623_PIN_261_MSDC1_INS_FUNC_MSDC1_INS (MTK_PIN_NO(261) | 1)
++
++#define MT7623_PIN_262_G2_TXEN_FUNC_GPIO262 (MTK_PIN_NO(262) | 0)
++#define MT7623_PIN_262_G2_TXEN_FUNC_G2_TXEN (MTK_PIN_NO(262) | 1)
++
++#define MT7623_PIN_263_G2_TXD3_FUNC_GPIO263 (MTK_PIN_NO(263) | 0)
++#define MT7623_PIN_263_G2_TXD3_FUNC_G2_TXD3 (MTK_PIN_NO(263) | 1)
++
++#define MT7623_PIN_264_G2_TXD2_FUNC_GPIO264 (MTK_PIN_NO(264) | 0)
++#define MT7623_PIN_264_G2_TXD2_FUNC_G2_TXD2 (MTK_PIN_NO(264) | 1)
++
++#define MT7623_PIN_265_G2_TXD1_FUNC_GPIO265 (MTK_PIN_NO(265) | 0)
++#define MT7623_PIN_265_G2_TXD1_FUNC_G2_TXD1 (MTK_PIN_NO(265) | 1)
++
++#define MT7623_PIN_266_G2_TXD0_FUNC_GPIO266 (MTK_PIN_NO(266) | 0)
++#define MT7623_PIN_266_G2_TXD0_FUNC_G2_TXD0 (MTK_PIN_NO(266) | 1)
++
++#define MT7623_PIN_267_G2_TXCLK_FUNC_GPIO267 (MTK_PIN_NO(267) | 0)
++#define MT7623_PIN_267_G2_TXCLK_FUNC_G2_TXC (MTK_PIN_NO(267) | 1)
++
++#define MT7623_PIN_268_G2_RXCLK_FUNC_GPIO268 (MTK_PIN_NO(268) | 0)
++#define MT7623_PIN_268_G2_RXCLK_FUNC_G2_RXC (MTK_PIN_NO(268) | 1)
++
++#define MT7623_PIN_269_G2_RXD0_FUNC_GPIO269 (MTK_PIN_NO(269) | 0)
++#define MT7623_PIN_269_G2_RXD0_FUNC_G2_RXD0 (MTK_PIN_NO(269) | 1)
++
++#define MT7623_PIN_270_G2_RXD1_FUNC_GPIO270 (MTK_PIN_NO(270) | 0)
++#define MT7623_PIN_270_G2_RXD1_FUNC_G2_RXD1 (MTK_PIN_NO(270) | 1)
++
++#define MT7623_PIN_271_G2_RXD2_FUNC_GPIO271 (MTK_PIN_NO(271) | 0)
++#define MT7623_PIN_271_G2_RXD2_FUNC_G2_RXD2 (MTK_PIN_NO(271) | 1)
++
++#define MT7623_PIN_272_G2_RXD3_FUNC_GPIO272 (MTK_PIN_NO(272) | 0)
++#define MT7623_PIN_272_G2_RXD3_FUNC_G2_RXD3 (MTK_PIN_NO(272) | 1)
++
++#define MT7623_PIN_273_D2D_ESW_INT_FUNC_GPIO273 (MTK_PIN_NO(273) | 0)
++#define MT7623_PIN_273_D2D_ESW_INT_FUNC_ESW_INT (MTK_PIN_NO(273) | 1)
++
++#define MT7623_PIN_274_G2_RXDV_FUNC_GPIO274 (MTK_PIN_NO(274) | 0)
++#define MT7623_PIN_274_G2_RXDV_FUNC_G2_RXDV (MTK_PIN_NO(274) | 1)
++
++#define MT7623_PIN_275_G2_MDC_FUNC_GPIO275 (MTK_PIN_NO(275) | 0)
++#define MT7623_PIN_275_G2_MDC_FUNC_MDC (MTK_PIN_NO(275) | 1)
++
++#define MT7623_PIN_276_G2_MDIO_FUNC_GPIO276 (MTK_PIN_NO(276) | 0)
++#define MT7623_PIN_276_G2_MDIO_FUNC_MDIO (MTK_PIN_NO(276) | 1)
++
++#define MT7623_PIN_277_D2D_ESW_RSTN_FUNC_GPIO277 (MTK_PIN_NO(277) | 0)
++#define MT7623_PIN_277_D2D_ESW_RSTN_FUNC_ESW_RST (MTK_PIN_NO(277) | 1)
++
++#define MT7623_PIN_278_JTAG_RESET_FUNC_GPIO278 (MTK_PIN_NO(278) | 0)
++#define MT7623_PIN_278_JTAG_RESET_FUNC_JTAG_RESET (MTK_PIN_NO(278) | 1)
++
++#endif /* __DTS_MT7623_PINFUNC_H */
+\ No newline at end of file
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0063-arm-mediatek-add-SDK-ethernet.patch b/target/linux/mediatek/patches/0063-arm-mediatek-add-SDK-ethernet.patch
new file mode 100644
index 0000000000..7263bb2181
--- /dev/null
+++ b/target/linux/mediatek/patches/0063-arm-mediatek-add-SDK-ethernet.patch
@@ -0,0 +1,20654 @@
+From e3aece79d5003b6879298b05551e113117d5cdd8 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 13:13:36 +0200
+Subject: [PATCH 63/76] arm: mediatek: add SDK ethernet
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/net/ethernet/Kconfig | 1 +
+ drivers/net/ethernet/Makefile | 1 +
+ drivers/net/ethernet/raeth/Kconfig | 415 ++
+ drivers/net/ethernet/raeth/Makefile | 67 +
+ drivers/net/ethernet/raeth/Makefile.release | 60 +
+ drivers/net/ethernet/raeth/csr_netlink.h | 27 +
+ drivers/net/ethernet/raeth/dvt/pkt_gen.c | 88 +
+ drivers/net/ethernet/raeth/dvt/pkt_gen_tcp_frag.c | 138 +
+ drivers/net/ethernet/raeth/dvt/pkt_gen_udp_frag.c | 191 +
+ drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.c | 1527 +++++
+ drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.h | 75 +
+ drivers/net/ethernet/raeth/ethtool_readme.txt | 44 +
+ drivers/net/ethernet/raeth/mcast.c | 187 +
+ drivers/net/ethernet/raeth/mii_mgr.c | 603 ++
+ drivers/net/ethernet/raeth/ra2882ethreg.h | 1985 +++++++
+ drivers/net/ethernet/raeth/ra_ethtool.c | 515 ++
+ drivers/net/ethernet/raeth/ra_ethtool.h | 13 +
+ drivers/net/ethernet/raeth/ra_ioctl.h | 102 +
+ drivers/net/ethernet/raeth/ra_mac.c | 2645 +++++++++
+ drivers/net/ethernet/raeth/ra_mac.h | 57 +
+ drivers/net/ethernet/raeth/ra_netlink.c | 142 +
+ drivers/net/ethernet/raeth/ra_netlink.h | 10 +
+ drivers/net/ethernet/raeth/ra_qos.c | 655 +++
+ drivers/net/ethernet/raeth/ra_qos.h | 18 +
+ drivers/net/ethernet/raeth/ra_rfrw.c | 66 +
+ drivers/net/ethernet/raeth/ra_rfrw.h | 6 +
+ drivers/net/ethernet/raeth/raether.c | 6401 +++++++++++++++++++++
+ drivers/net/ethernet/raeth/raether.h | 126 +
+ drivers/net/ethernet/raeth/raether_hwlro.c | 347 ++
+ drivers/net/ethernet/raeth/raether_pdma.c | 1121 ++++
+ drivers/net/ethernet/raeth/raether_qdma.c | 1407 +++++
+ drivers/net/ethernet/raeth/raether_qdma_mt7623.c | 1020 ++++
+ drivers/net/ethernet/raeth/smb_hook.c | 17 +
+ drivers/net/ethernet/raeth/smb_nf.c | 177 +
+ drivers/net/ethernet/raeth/sync_write.h | 103 +
+ 35 files changed, 20357 insertions(+)
+ create mode 100644 drivers/net/ethernet/raeth/Kconfig
+ create mode 100644 drivers/net/ethernet/raeth/Makefile
+ create mode 100644 drivers/net/ethernet/raeth/Makefile.release
+ create mode 100644 drivers/net/ethernet/raeth/csr_netlink.h
+ create mode 100755 drivers/net/ethernet/raeth/dvt/pkt_gen.c
+ create mode 100755 drivers/net/ethernet/raeth/dvt/pkt_gen_tcp_frag.c
+ create mode 100755 drivers/net/ethernet/raeth/dvt/pkt_gen_udp_frag.c
+ create mode 100755 drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.c
+ create mode 100755 drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.h
+ create mode 100644 drivers/net/ethernet/raeth/ethtool_readme.txt
+ create mode 100644 drivers/net/ethernet/raeth/mcast.c
+ create mode 100644 drivers/net/ethernet/raeth/mii_mgr.c
+ create mode 100644 drivers/net/ethernet/raeth/ra2882ethreg.h
+ create mode 100644 drivers/net/ethernet/raeth/ra_ethtool.c
+ create mode 100644 drivers/net/ethernet/raeth/ra_ethtool.h
+ create mode 100644 drivers/net/ethernet/raeth/ra_ioctl.h
+ create mode 100644 drivers/net/ethernet/raeth/ra_mac.c
+ create mode 100644 drivers/net/ethernet/raeth/ra_mac.h
+ create mode 100644 drivers/net/ethernet/raeth/ra_netlink.c
+ create mode 100644 drivers/net/ethernet/raeth/ra_netlink.h
+ create mode 100644 drivers/net/ethernet/raeth/ra_qos.c
+ create mode 100644 drivers/net/ethernet/raeth/ra_qos.h
+ create mode 100644 drivers/net/ethernet/raeth/ra_rfrw.c
+ create mode 100644 drivers/net/ethernet/raeth/ra_rfrw.h
+ create mode 100644 drivers/net/ethernet/raeth/raether.c
+ create mode 100644 drivers/net/ethernet/raeth/raether.h
+ create mode 100755 drivers/net/ethernet/raeth/raether_hwlro.c
+ create mode 100755 drivers/net/ethernet/raeth/raether_pdma.c
+ create mode 100644 drivers/net/ethernet/raeth/raether_qdma.c
+ create mode 100644 drivers/net/ethernet/raeth/raether_qdma_mt7623.c
+ create mode 100644 drivers/net/ethernet/raeth/smb_hook.c
+ create mode 100644 drivers/net/ethernet/raeth/smb_nf.c
+ create mode 100644 drivers/net/ethernet/raeth/sync_write.h
+
+diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
+index eadcb05..627e1d4 100644
+--- a/drivers/net/ethernet/Kconfig
++++ b/drivers/net/ethernet/Kconfig
+@@ -17,6 +17,7 @@ config MDIO
+ config SUNGEM_PHY
+ tristate
+
++source "drivers/net/ethernet/raeth/Kconfig"
+ source "drivers/net/ethernet/3com/Kconfig"
+ source "drivers/net/ethernet/adaptec/Kconfig"
+ source "drivers/net/ethernet/aeroflex/Kconfig"
+diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
+index 1367afc..abdd636 100644
+--- a/drivers/net/ethernet/Makefile
++++ b/drivers/net/ethernet/Makefile
+@@ -84,3 +84,4 @@ obj-$(CONFIG_NET_VENDOR_VIA) += via/
+ obj-$(CONFIG_NET_VENDOR_WIZNET) += wiznet/
+ obj-$(CONFIG_NET_VENDOR_XILINX) += xilinx/
+ obj-$(CONFIG_NET_VENDOR_XIRCOM) += xircom/
++obj-$(CONFIG_RAETH) += raeth/
+diff --git a/drivers/net/ethernet/raeth/Kconfig b/drivers/net/ethernet/raeth/Kconfig
+new file mode 100644
+index 0000000..c252c85
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/Kconfig
+@@ -0,0 +1,415 @@
++config ARCH_MT7623
++ bool
++ default y
++
++config RA_NAT_NONE
++ bool
++ default y
++
++config RAETH
++ tristate "Ralink GMAC"
++ ---help---
++ This driver supports Ralink gigabit ethernet family of
++ adapters.
++
++config PDMA_NEW
++ bool
++ default y if (RALINK_MT7620 || RALINK_MT7621 || ARCH_MT7623)
++ depends on RAETH
++
++config RAETH_SCATTER_GATHER_RX_DMA
++ bool
++ default y if (RALINK_MT7620 || RALINK_MT7621 || ARCH_MT7623)
++ depends on RAETH
++
++
++choice
++ prompt "Network BottomHalves"
++ depends on RAETH
++ default RA_NETWORK_WORKQUEUE_BH
++
++ config RA_NETWORK_TASKLET_BH
++ bool "Tasklet"
++
++ config RA_NETWORK_WORKQUEUE_BH
++ bool "Work Queue"
++
++ config RAETH_NAPI
++ bool "NAPI"
++
++endchoice
++
++#config TASKLET_WORKQUEUE_SW
++# bool "Tasklet and Workqueue switch"
++# depends on RA_NETWORK_TASKLET_BH
++
++config RAETH_SKB_RECYCLE_2K
++ bool "SKB Recycling"
++ depends on RAETH
++
++config RAETH_SPECIAL_TAG
++ bool "Ralink Special Tag (0x810x)"
++ depends on RAETH && RT_3052_ESW
++
++#config RAETH_JUMBOFRAME
++# bool "Jumbo Frame up to 4K bytes"
++# depends on RAETH && !(RALINK_RT3052 || RALINK_RT3352 || RALINK_RT5350 || RALINK_MT7628)
++
++config RAETH_CHECKSUM_OFFLOAD
++ bool "TCP/UDP/IP checksum offload"
++ default y
++ depends on RAETH && !RALINK_RT2880
++
++#config RAETH_SW_FC
++# bool "When TX ring is full, inform kernel stop transmit and stop RX handler"
++# default n
++# depends on RAETH
++
++#config RAETH_8023AZ_EEE
++# bool "Enable Embeded Switch EEE"
++# default n
++# depends on RAETH && (RALINK_MT7620 || RALINK_MT7621 || RALINK_MT7628)
++
++
++
++config 32B_DESC
++ bool "32bytes TX/RX description"
++ default n
++ depends on RAETH && (RALINK_MT7620 || RALINK_MT7621)
++ ---help---
++ At this moment, you cannot enable 32B description with Multiple RX ring at the same time.
++
++config RAETH_LRO
++ bool "LRO (Large Receive Offload )"
++ select INET_LRO
++ depends on RAETH && (RALINK_RT6855A || RALINK_MT7620 || RALINK_MT7621 || ARCH_MT7623)
++
++config RAETH_HW_LRO
++ bool "HW LRO (Large Receive Offload)"
++ default n
++ depends on RAETH
++
++config RAETH_HW_LRO_DBG
++ bool "HW LRO Debug"
++ default n
++ depends on RAETH_HW_LRO
++
++config RAETH_HW_LRO_AUTO_ADJ_DBG
++ bool "HW LRO Auto Adjustment Debug"
++ default y
++ depends on RAETH_HW_LRO
++
++config RAETH_HW_LRO_REASON_DBG
++ bool "HW LRO Flush Reason Debug"
++ default n
++ depends on RAETH_HW_LRO
++
++config RAETH_HW_VLAN_TX
++ bool "Transmit VLAN HW (DoubleVLAN is not supported)"
++ depends on RAETH && !(RALINK_RT5350 || RALINK_MT7628)
++ ---help---
++ Please disable HW_VLAN_TX if you need double vlan
++
++config RAETH_HW_VLAN_RX
++ bool "Receive VLAN HW (DoubleVLAN is not supported)"
++ depends on RAETH && RALINK_MT7621
++ ---help---
++ Please disable HW_VLAN_RX if you need double vlan
++
++config RAETH_TSO
++ bool "TSOV4 (Tcp Segmentaton Offload)"
++ depends on (RAETH_HW_VLAN_TX && (RALINK_RT6855 || RALINK_RT6855A || RALINK_MT7620))||((RALINK_MT7621 || ARCH_MT7623) &&(RAETH_HW_VLAN_TX || RAETH_GMAC2 ))
++
++config RAETH_TSOV6
++ bool "TSOV6 (Tcp Segmentaton Offload)"
++ depends on RAETH_TSO
++
++config RAETH_RW_PDMAPTR_FROM_VAR
++ bool
++ default y if RALINK_RT6855A || RALINK_MT7620
++ depends on RAETH
++
++config MTK_SMB_HOOK
++ bool "Samba Speedup Module"
++ depends on RAETH
++
++config SPLICE_NET_SUPPORT
++ default y if MTK_SMB_HOOK
++ depends on MTK_SMB_HOOK
++ bool
++
++
++config RAETH_DVT
++ bool "RAETH DVT"
++ depends on RAETH && (RALINK_MT7621 || ARCH_MT7623)
++
++config RAETH_PDMA_DVT
++ bool "PDMA DVT"
++ depends on RAETH_DVT
++
++config RAETH_PDMA_LEGACY_MODE
++ bool "PDMA legacy mode"
++ depends on RAETH_PDMA_DVT
++
++#config RAETH_QOS
++# bool "QoS Feature"
++# depends on RAETH && !RALINK_RT2880 && !RALINK_MT7620 && !RALINK_MT7621 && !RAETH_TSO
++
++choice
++ prompt "QoS Type"
++ depends on RAETH_QOS
++ default DSCP_QOS_DSCP
++
++config RAETH_QOS_DSCP_BASED
++ bool "DSCP-based"
++ depends on RAETH_QOS
++
++config RAETH_QOS_VPRI_BASED
++ bool "VPRI-based"
++ depends on RAETH_QOS
++
++endchoice
++
++config RAETH_QDMA
++ bool "Choose QDMA instead PDMA"
++ default n
++ depends on RAETH && (RALINK_MT7621 || ARCH_MT7623)
++
++config RAETH_QDMATX_QDMARX
++ bool "Choose QDMA RX instead PDMA RX"
++ default n
++ depends on RAETH_QDMA && !RALINK_MT7621
++
++
++
++choice
++ prompt "GMAC is connected to"
++ depends on RAETH
++ default GE1_RGMII_FORCE_1000
++
++config GE1_MII_FORCE_100
++ bool "MII_FORCE_100 (10/100M Switch)"
++ depends on (RALINK_RT2880 || RALINK_RT3883 || RALINK_MT7621)
++
++config GE1_MII_AN
++ bool "MII_AN (100Phy)"
++ depends on (RALINK_RT2880 || RALINK_RT3883 || RALINK_MT7621)
++
++config GE1_RVMII_FORCE_100
++ bool "RvMII_FORCE_100 (CPU)"
++ depends on (RALINK_RT2880 || RALINK_RT3883 || RALINK_MT7621)
++
++config GE1_RGMII_FORCE_1000
++ bool "RGMII_FORCE_1000 (GigaSW, CPU)"
++ depends on (RALINK_RT2880 || RALINK_RT3883)
++ select RALINK_SPI
++
++config GE1_RGMII_FORCE_1000
++ bool "RGMII_FORCE_1000 (GigaSW, CPU)"
++ depends on (RALINK_MT7621 || ARCH_MT7623)
++ select RT_3052_ESW
++
++config GE1_TRGMII_FORCE_1200
++ bool "TRGMII_FORCE_1200 (GigaSW, CPU)"
++ depends on (RALINK_MT7621)
++ select RT_3052_ESW
++
++config GE1_TRGMII_FORCE_2000
++ bool "TRGMII_FORCE_2000 (GigaSW, CPU, for MT7623 and MT7683)"
++ depends on (ARCH_MT7623)
++ select RT_3052_ESW
++
++config GE1_TRGMII_FORCE_2600
++ bool "TRGMII_FORCE_2600 (GigaSW, CPU, MT7623 only)"
++ depends on (ARCH_MT7623)
++ select RT_3052_ESW
++
++config GE1_RGMII_AN
++ bool "RGMII_AN (GigaPhy)"
++ depends on (RALINK_RT2880 || RALINK_RT3883 || RALINK_MT7621 || ARCH_MT7623)
++
++config GE1_RGMII_NONE
++ bool "NONE (NO CONNECT)"
++ depends on (RALINK_MT7621 || ARCH_MT7623)
++
++endchoice
++
++config HW_SFQ
++ bool "HW_SFQ"
++ default n
++ depends on RAETH_QDMA && (ARCH_MT7623)
++
++
++config RT_3052_ESW
++ bool "Ralink Embedded Switch"
++ default y
++ depends on RAETH && (RALINK_RT3052 || RALINK_RT3352 || RALINK_RT5350 || RALINK_RT6855 || RALINK_RT6855A || RALINK_MT7620 || RALINK_MT7621 || RALINK_MT7628 || ARCH_MT7623)
++
++config LAN_WAN_SUPPORT
++ bool "LAN/WAN Partition"
++ depends on RAETH && (RAETH_ROUTER || RT_3052_ESW)
++
++config ETH_MEMORY_OPTIMIZATION
++ bool "Ethernet memory optimization"
++ depends on RALINK_MT7628
++
++config ETH_ONE_PORT_ONLY
++ bool "One Port Only"
++ depends on RALINK_MT7628
++
++choice
++ prompt "Switch Board Layout Type"
++ depends on LAN_WAN_SUPPORT || P5_RGMII_TO_MAC_MODE || GE1_RGMII_FORCE_1000 || GE1_TRGMII_FORCE_1200 || GE2_RGMII_FORCE_1000
++ default WAN_AT_P0
++
++ config WAN_AT_P4
++ bool "LLLL/W"
++
++ config WAN_AT_P0
++ bool "W/LLLL"
++endchoice
++
++config RALINK_VISTA_BASIC
++ bool 'Vista Basic Logo for IC+ 175C'
++ depends on LAN_WAN_SUPPORT && (RALINK_RT2880 || RALINK_RT3883)
++
++config ESW_DOUBLE_VLAN_TAG
++ bool
++ default y if RT_3052_ESW
++
++config RAETH_HAS_PORT4
++ bool "Port 4 Support"
++ depends on RAETH && RALINK_MT7620
++choice
++ prompt "Target Mode"
++ depends on RAETH_HAS_PORT4
++ default P4_RGMII_TO_MAC_MODE
++
++ config P4_MAC_TO_PHY_MODE
++ bool "Giga_Phy (RGMII)"
++ config GE_RGMII_MT7530_P0_AN
++ bool "GE_RGMII_MT7530_P0_AN (MT7530 Internal GigaPhy)"
++ config GE_RGMII_MT7530_P4_AN
++ bool "GE_RGMII_MT7530_P4_AN (MT7530 Internal GigaPhy)"
++ config P4_RGMII_TO_MAC_MODE
++ bool "Giga_SW/iNIC (RGMII)"
++ config P4_MII_TO_MAC_MODE
++ bool "External_CPU (MII_RvMII)"
++ config P4_RMII_TO_MAC_MODE
++ bool "External_CPU (RvMII_MII)"
++endchoice
++
++config MAC_TO_GIGAPHY_MODE_ADDR2
++ hex "Port4 Phy Address"
++ default 0x4
++ depends on P4_MAC_TO_PHY_MODE
++
++config RAETH_HAS_PORT5
++ bool "Port 5 Support"
++ depends on RAETH && (RALINK_RT3052 || RALINK_RT3352 || RALINK_RT6855 || RALINK_RT6855A || RALINK_MT7620)
++choice
++ prompt "Target Mode"
++ depends on RAETH_HAS_PORT5
++ default P5_RGMII_TO_MAC_MODE
++
++ config P5_MAC_TO_PHY_MODE
++ bool "Giga_Phy (RGMII)"
++ config P5_RGMII_TO_MAC_MODE
++ bool "Giga_SW/iNIC (RGMII)"
++ config P5_RGMII_TO_MT7530_MODE
++ bool "MT7530 Giga_SW (RGMII)"
++ depends on RALINK_MT7620
++ config P5_MII_TO_MAC_MODE
++ bool "External_CPU (MII_RvMII)"
++ config P5_RMII_TO_MAC_MODE
++ bool "External_CPU (RvMII_MII)"
++endchoice
++
++config MAC_TO_GIGAPHY_MODE_ADDR
++ hex "GE1 Phy Address"
++ default 0x1F
++ depends on GE1_MII_AN || GE1_RGMII_AN
++
++config MAC_TO_GIGAPHY_MODE_ADDR
++ hex "Port5 Phy Address"
++ default 0x5
++ depends on P5_MAC_TO_PHY_MODE
++
++config RAETH_GMAC2
++ bool "GMAC2 Support"
++ depends on RAETH && (RALINK_RT3883 || RALINK_MT7621 || ARCH_MT7623)
++
++choice
++ prompt "GMAC2 is connected to"
++ depends on RAETH_GMAC2
++ default GE2_RGMII_AN
++
++config GE2_MII_FORCE_100
++ bool "MII_FORCE_100 (10/100M Switch)"
++ depends on RAETH_GMAC2
++
++config GE2_MII_AN
++ bool "MII_AN (100Phy)"
++ depends on RAETH_GMAC2
++
++config GE2_RVMII_FORCE_100
++ bool "RvMII_FORCE_100 (CPU)"
++ depends on RAETH_GMAC2
++
++config GE2_RGMII_FORCE_1000
++ bool "RGMII_FORCE_1000 (GigaSW, CPU)"
++ depends on RAETH_GMAC2
++ select RALINK_SPI
++
++config GE2_RGMII_AN
++ bool "RGMII_AN (External GigaPhy)"
++ depends on RAETH_GMAC2
++
++config GE2_INTERNAL_GPHY
++ bool "RGMII_AN (Internal GigaPny)"
++ depends on RAETH_GMAC2
++ select LAN_WAN_SUPPORT
++
++endchoice
++
++config GE_RGMII_INTERNAL_P0_AN
++ bool
++ depends on GE2_INTERNAL_GPHY
++ default y if WAN_AT_P0
++
++config GE_RGMII_INTERNAL_P4_AN
++ bool
++ depends on GE2_INTERNAL_GPHY
++ default y if WAN_AT_P4
++
++config MAC_TO_GIGAPHY_MODE_ADDR2
++ hex
++ default 0 if GE_RGMII_INTERNAL_P0_AN
++ default 4 if GE_RGMII_INTERNAL_P4_AN
++ depends on GE_RGMII_INTERNAL_P0_AN || GE_RGMII_INTERNAL_P4_AN
++
++config MAC_TO_GIGAPHY_MODE_ADDR2
++ hex "GE2 Phy Address"
++ default 0x1E
++ depends on GE2_MII_AN || GE2_RGMII_AN
++
++#force 100M
++config RAETH_ROUTER
++bool
++default y if GE1_MII_FORCE_100 || GE2_MII_FORCE_100 || GE1_RVMII_FORCE_100 || GE2_RVMII_FORCE_100
++
++#force 1000M
++config MAC_TO_MAC_MODE
++bool
++default y if GE1_RGMII_FORCE_1000 || GE2_RGMII_FORCE_1000
++depends on (RALINK_RT2880 || RALINK_RT3883)
++
++#AN
++config GIGAPHY
++bool
++default y if GE1_RGMII_AN || GE2_RGMII_AN
++
++#AN
++config 100PHY
++bool
++default y if GE1_MII_AN || GE2_MII_AN
+diff --git a/drivers/net/ethernet/raeth/Makefile b/drivers/net/ethernet/raeth/Makefile
+new file mode 100644
+index 0000000..563af05
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/Makefile
+@@ -0,0 +1,67 @@
++obj-$(CONFIG_RAETH) += raeth.o
++raeth-objs := ra_mac.o mii_mgr.o ra_rfrw.o
++
++ifeq ($(CONFIG_MTK_SMB_HOOK),y)
++obj-y += smb_hook.o
++obj-m += smb.o
++smb-objs := smb_nf.o
++endif
++
++#EXTRA_CFLAGS += -DCONFIG_RAETH_MULTIPLE_RX_RING
++
++ifeq ($(CONFIG_RAETH_QOS),y)
++raeth-objs += ra_qos.o
++endif
++
++ifeq ($(CONFIG_RAETH_QDMA),y)
++raeth-objs += raether_qdma.o
++endif
++
++ifneq ($(CONFIG_RAETH_QDMA),y)
++raeth-objs += raether_pdma.o
++endif
++
++raeth-objs += raether.o
++
++ifeq ($(CONFIG_ETHTOOL),y)
++raeth-objs += ra_ethtool.o
++endif
++
++ifeq ($(CONFIG_RALINK_RT3052_MP2),y)
++raeth-objs += mcast.o
++endif
++
++ifeq ($(CONFIG_RAETH_NETLINK),y)
++raeth-objs += ra_netlink.o
++endif
++
++ifeq ($(CONFIG_RAETH_PDMA_DVT),y)
++raeth-objs += dvt/raether_pdma_dvt.o
++obj-m += dvt/pkt_gen.o
++obj-m += dvt/pkt_gen_udp_frag.o
++obj-m += dvt/pkt_gen_tcp_frag.o
++endif
++
++ifeq ($(CONFIG_RAETH_HW_LRO),y)
++raeth-objs += raether_hwlro.o
++endif
++
++ifeq ($(CONFIG_RAETH_GMAC2),y)
++EXTRA_CFLAGS += -DCONFIG_PSEUDO_SUPPORT
++endif
++
++ifeq ($(CONFIG_ETH_MEMORY_OPTIMIZATION),y)
++EXTRA_CFLAGS += -DMEMORY_OPTIMIZATION
++endif
++
++ifeq ($(CONFIG_RT2860V2_AP_MEMORY_OPTIMIZATION),y)
++EXTRA_CFLAGS += -DMEMORY_OPTIMIZATION
++endif
++
++ifeq ($(CONFIG_RA_NETWORK_WORKQUEUE_BH),y)
++EXTRA_CFLAGS += -DWORKQUEUE_BH
++endif
++
++ifeq ($(CONFIG_TASKLET_WORKQUEUE_SW),y)
++EXTRA_CFLAGS += -DTASKLET_WORKQUEUE_SW
++endif
+diff --git a/drivers/net/ethernet/raeth/Makefile.release b/drivers/net/ethernet/raeth/Makefile.release
+new file mode 100644
+index 0000000..ecdeeda
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/Makefile.release
+@@ -0,0 +1,60 @@
++obj-$(CONFIG_RAETH) += raeth.o
++raeth-objs := ra_mac.o mii_mgr.o ra_rfrw.o
++
++ifeq ($(CONFIG_MTK_SMB_HOOK),y)
++obj-y += smb_hook.o
++obj-m += smb.o
++smb-objs := smb_nf.o
++endif
++
++#EXTRA_CFLAGS += -DCONFIG_RAETH_MULTIPLE_RX_RING
++
++ifeq ($(CONFIG_RAETH_QOS),y)
++raeth-objs += ra_qos.o
++endif
++
++ifeq ($(CONFIG_RAETH_QDMA),y)
++raeth-objs += raether_qdma.o
++endif
++
++ifneq ($(CONFIG_RAETH_QDMA),y)
++raeth-objs += raether_pdma.o
++endif
++
++raeth-objs += raether.o
++
++ifeq ($(CONFIG_ETHTOOL),y)
++raeth-objs += ra_ethtool.o
++endif
++
++ifeq ($(CONFIG_RALINK_RT3052_MP2),y)
++raeth-objs += mcast.o
++endif
++
++ifeq ($(CONFIG_RAETH_NETLINK),y)
++raeth-objs += ra_netlink.o
++endif
++
++ifeq ($(CONFIG_RAETH_HW_LRO),y)
++raeth-objs += raether_hwlro.o
++endif
++
++ifeq ($(CONFIG_RAETH_GMAC2),y)
++EXTRA_CFLAGS += -DCONFIG_PSEUDO_SUPPORT
++endif
++
++ifeq ($(CONFIG_ETH_MEMORY_OPTIMIZATION),y)
++EXTRA_CFLAGS += -DMEMORY_OPTIMIZATION
++endif
++
++ifeq ($(CONFIG_RT2860V2_AP_MEMORY_OPTIMIZATION),y)
++EXTRA_CFLAGS += -DMEMORY_OPTIMIZATION
++endif
++
++ifeq ($(CONFIG_RA_NETWORK_WORKQUEUE_BH),y)
++EXTRA_CFLAGS += -DWORKQUEUE_BH
++endif
++
++ifeq ($(CONFIG_TASKLET_WORKQUEUE_SW),y)
++EXTRA_CFLAGS += -DTASKLET_WORKQUEUE_SW
++endif
+diff --git a/drivers/net/ethernet/raeth/csr_netlink.h b/drivers/net/ethernet/raeth/csr_netlink.h
+new file mode 100644
+index 0000000..add7745
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/csr_netlink.h
+@@ -0,0 +1,27 @@
++#ifndef CSR_NETLINK_H
++#define CSR_NETLINK_H
++
++#define CSR_NETLINK 30
++#define CSR_READ 0
++#define CSR_WRITE 1
++#define CSR_TEST 2
++
++#define RALINK_CSR_GROUP 2882
++
++typedef struct rt2880_csr_msg {
++ int enable;
++ char reg_name[32];
++ unsigned long address;
++ unsigned long default_value;
++ unsigned long reserved_bits; /* 1 : not reserved, 0 : reserved */
++ unsigned long write_mask;
++ unsigned long write_value;
++ int status;
++} CSR_MSG;
++
++int csr_msg_send(CSR_MSG* msg);
++int csr_msg_recv(void);
++
++// static CSR_MSG input_csr_msg;
++
++#endif
+diff --git a/drivers/net/ethernet/raeth/dvt/pkt_gen.c b/drivers/net/ethernet/raeth/dvt/pkt_gen.c
+new file mode 100755
+index 0000000..b351b21
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/dvt/pkt_gen.c
+@@ -0,0 +1,88 @@
++//#include <linux/config.h>
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/netfilter.h>
++#include <linux/netdevice.h>
++#include <linux/types.h>
++#include <asm/uaccess.h>
++#include <linux/moduleparam.h>
++
++char *ifname="eth3";
++
++static int32_t PktGenInitMod(void)
++{
++
++ struct net_dev *dev;
++ struct sk_buff *skb;
++ int i=0;
++
++ unsigned char pkt[]={
++ //0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // dest bcast mac
++ 0x00, 0x21, 0x86, 0xee, 0xe3, 0x95, // dest macA
++ //0x00, 0x30, 0xdb, 0x02, 0x02, 0x01, // dest macB
++ 0x00, 0x0c, 0x43, 0x28, 0x80, 0x33, // src mac
++ 0x81, 0x00, // vlan tag
++ //0x81, 0x10, // vlan tag
++ //0x87, 0x39, // do not learn
++ //0xc1, 0x03, // vlan tag SA=0, VID=2, LV=1
++ 0x00, 0x03, // pri=0, vlan=3
++ 0x08, 0x00, // eth type=ip
++ 0x45, 0x00, 0x00, 0x30, 0x12, 0x34, 0x40, 0x00, 0xff, 0x06,
++ 0x40, 0x74, 0x0a, 0x0a, 0x1e, 0x0a, 0x0a, 0x0a, 0x1e, 0x0b,
++ 0x00, 0x1e, 0x00, 0x28, 0x00, 0x1c, 0x81, 0x06, 0x00, 0x00,
++ 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
++
++ skb = alloc_skb(256, GFP_ATOMIC);
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ if((dev=dev_get_by_name(&init_net,ifname))){
++#else
++ if((dev=dev_get_by_name(ifname))){
++#endif
++
++
++
++ skb->dev=dev;
++ skb_put(skb,sizeof(pkt));
++ memcpy(skb->data, pkt, sizeof(pkt));
++
++ printk("send pkt(len=%d) to %s\n", skb->len, skb->dev->name);
++
++
++ for(i=0;i<sizeof(pkt);i++){
++ if(i%16==0) {
++ printk("\n");
++ }
++ printk("%02X-",skb->data[i]);
++ }
++
++ dev_queue_xmit(skb);
++ }else{
++ printk("interface %s not found\n",ifname);
++ return 1;
++ }
++
++ return 0;
++}
++
++static void PktGenCleanupMod(void)
++{
++}
++
++module_init(PktGenInitMod);
++module_exit(PktGenCleanupMod);
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12)
++MODULE_PARM (ifname, "s");
++#else
++module_param (ifname, charp, 0);
++#endif
++
++MODULE_DESCRIPTION("Ralink PktGen Module");
++MODULE_AUTHOR("Steven Liu");
++MODULE_LICENSE("Proprietary");
++MODULE_PARM_DESC (ifname, "interface name");
++
+diff --git a/drivers/net/ethernet/raeth/dvt/pkt_gen_tcp_frag.c b/drivers/net/ethernet/raeth/dvt/pkt_gen_tcp_frag.c
+new file mode 100755
+index 0000000..e78c65a
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/dvt/pkt_gen_tcp_frag.c
+@@ -0,0 +1,138 @@
++//#include <linux/config.h>
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/netfilter.h>
++#include <linux/netdevice.h>
++#include <linux/types.h>
++#include <asm/uaccess.h>
++#include <linux/moduleparam.h>
++
++char *ifname="eth3";
++
++
++static int32_t PktGenInitMod(void)
++{
++ unsigned char pkt_1[]={
++ 0x00, 0x21, 0x86, 0xee, 0xe3, 0x90, // dest mac
++ 0x00, 0x0c, 0x43, 0x28, 0x80, 0x33, // src mac
++ 0x08, 0x00, // type: ip
++ 0x45, 0x00, 0x00, 0x34, // ip: ..., total len (0x034 = 52)
++ 0xa1, 0x78, 0x20, 0x00, // ip: id, frag, frag offset
++ 0x80, 0x06, 0x63, 0x07, // ip: ttl, protocol, hdr checksum (0x6307)
++ 0x0a, 0x0a, 0x1e, 0x7b, // src ip (10.10.30.123)
++ 0x0a, 0x0a, 0x1e, 0x05, // dst ip (10.10.30.5)
++ 0x0d, 0xd5, //tcp src port
++ 0x13, 0x89, //tcp dst port
++ 0x40, 0xf5, 0x15, 0x04, //tcp sequence number
++ 0xf6, 0x4f, 0x1e, 0x31, //tcp ack number
++ 0x50, 0x10, 0xfc, 0x00, //tcp flags, win size
++ 0xf1, 0xfe, 0x00, 0x00, //tcp checksum (0xf1fe)
++ 0x01, 0x02, 0x03, 0x04, 0x05, //payload (12 bytes)
++ 0x06, 0x07, 0x08, 0x09, 0x0a,
++ 0x0b, 0x0c
++ };
++
++ unsigned char pkt_2[]={
++ 0x00, 0x21, 0x86, 0xee, 0xe3, 0x90, // dest mac
++ 0x00, 0x0c, 0x43, 0x28, 0x80, 0x33, // src mac
++ 0x08, 0x00, // type: ip
++ 0x45, 0x00, 0x00, 0x20, // ip: ..., total len (0x020 = 32)
++ 0xa1, 0x78, 0x00, 0x04, // ip: id, frag, frag offset (32)
++ 0x40, 0x11, 0x63, 0x07, // ip: ttl, protocol, hdr checksum (0x6307)
++ 0x0a, 0x0a, 0x1e, 0x7b, // src ip (10.10.30.123)
++ 0x0a, 0x0a, 0x1e, 0x05, // dst ip (10.10.30.5)
++ 0x11, 0x12, 0x13, 0x14, 0x15, //payload (12 bytes)
++ 0x16, 0x17, 0x18, 0x19, 0x1a,
++ 0x1b, 0x1c
++ };
++
++ struct net_dev *dev;
++ struct sk_buff *skb_1;
++ struct sk_buff *skb_2;
++ int i=0;
++
++ skb_1 = alloc_skb(256, GFP_ATOMIC);
++ skb_2 = alloc_skb(256, GFP_ATOMIC);
++
++
++#if 1
++/* send packet 1 */
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ if((dev=dev_get_by_name(&init_net,ifname))){
++#else
++ if((dev=dev_get_by_name(ifname))){
++#endif
++
++ skb_1->dev=dev;
++ skb_put(skb_1,sizeof(pkt_1));
++ memcpy(skb_1->data, pkt_1, sizeof(pkt_1));
++
++ printk("send pkt(len=%d) to %s\n", skb_1->len, skb_1->dev->name);
++
++
++ for(i=0;i<sizeof(pkt_1);i++){
++ if(i%16==0) {
++ printk("\n");
++ }
++ printk("%02X-",skb_1->data[i]);
++ }
++
++ dev_queue_xmit(skb_1);
++ }else{
++ printk("interface %s not found\n",ifname);
++ return 1;
++ }
++#endif
++
++#if 1
++/* send packet 2 */
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ if((dev=dev_get_by_name(&init_net,ifname))){
++#else
++ if((dev=dev_get_by_name(ifname))){
++#endif
++
++ skb_2->dev=dev;
++ skb_put(skb_2,sizeof(pkt_2));
++ memcpy(skb_2->data, pkt_2, sizeof(pkt_2));
++
++ printk("send pkt(len=%d) to %s\n", skb_2->len, skb_2->dev->name);
++
++
++ for(i=0;i<sizeof(pkt_2);i++){
++ if(i%16==0) {
++ printk("\n");
++ }
++ printk("%02X-",skb_2->data[i]);
++ }
++
++ dev_queue_xmit(skb_2);
++ }else{
++ printk("interface %s not found\n",ifname);
++ return 1;
++ }
++#endif
++
++ return 0;
++}
++
++static void PktGenCleanupMod(void)
++{
++}
++
++module_init(PktGenInitMod);
++module_exit(PktGenCleanupMod);
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12)
++MODULE_PARM (ifname, "s");
++#else
++module_param (ifname, charp, 0);
++#endif
++
++MODULE_DESCRIPTION("Ralink PktGen Module");
++MODULE_AUTHOR("Steven Liu");
++MODULE_LICENSE("Proprietary");
++MODULE_PARM_DESC (ifname, "interface name");
++
+diff --git a/drivers/net/ethernet/raeth/dvt/pkt_gen_udp_frag.c b/drivers/net/ethernet/raeth/dvt/pkt_gen_udp_frag.c
+new file mode 100755
+index 0000000..917e7ad
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/dvt/pkt_gen_udp_frag.c
+@@ -0,0 +1,191 @@
++//#include <linux/config.h>
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/netfilter.h>
++#include <linux/netdevice.h>
++#include <linux/types.h>
++#include <asm/uaccess.h>
++#include <linux/moduleparam.h>
++
++char *ifname="eth3";
++
++
++static int32_t PktGenInitMod(void)
++{
++#if 0
++ unsigned char pkt_0[]={
++// 0x00, 0x21, 0x86, 0xee, 0xe3, 0x95, // dest mac
++ 0x00, 0x21, 0x86, 0xee, 0xe3, 0x90, // dest mac
++ 0x00, 0x0c, 0x43, 0x28, 0x80, 0x33, // src mac
++ 0x08, 0x00, // type: ip
++ 0x45, 0x00, 0x00, 0x26, // ip: ..., total len (0x026 = 38)
++// 0xa1, 0x78, 0x20, 0x00, // ip: id, frag, frag offset
++ 0xa1, 0x78, 0x40, 0x00, // ip: id, frag, frag offset
++ 0x40, 0x11, 0x63, 0x07, // ip: ttl, protocol, hdr checksum (0x6307)
++ 0x0a, 0x0a, 0x1e, 0x7b, // src ip (10.10.30.123)
++// 0x0a, 0x0a, 0x1e, 0x03, // dst ip (10.10.30.3)
++ 0x0a, 0x0a, 0x1e, 0x05, // dst ip (10.10.30.5)
++ 0xca, 0x7b, //udp src port
++ 0x13, 0x89, //udp dst port
++ 0x00, 0x12, //udp len (0x01c = 18)
++ 0x2f, 0x96, //udp checksum (0x2f96)
++ 0x01, 0x02, 0x03, 0x04, 0x05, //payload (10 bytes)
++ 0x06, 0x07, 0x08, 0x09, 0x0a
++ };
++#endif
++
++ unsigned char pkt_1[]={
++// 0x00, 0x21, 0x86, 0xee, 0xe3, 0x95, // dest mac
++ 0x00, 0x21, 0x86, 0xee, 0xe3, 0x90, // dest mac
++ 0x00, 0x0c, 0x43, 0x28, 0x80, 0x33, // src mac
++ 0x08, 0x00, // type: ip
++ 0x45, 0x00, 0x00, 0x24, // ip: ..., total len (0x024 = 36)
++ 0xa1, 0x78, 0x20, 0x00, // ip: id, frag, frag offset
++// 0xa1, 0x78, 0x40, 0x00, // ip: id, frag, frag offset
++ 0x40, 0x11, 0x63, 0x07, // ip: ttl, protocol, hdr checksum (0x6307)
++ 0x0a, 0x0a, 0x1e, 0x7b, // src ip (10.10.30.123)
++// 0x0a, 0x0a, 0x1e, 0x03, // dst ip (10.10.30.3)
++ 0x0a, 0x0a, 0x1e, 0x05, // dst ip (10.10.30.5)
++ 0xca, 0x7b, //udp src port
++ 0x13, 0x89, //udp dst port
++ 0x00, 0x1a, //udp len (0x01a = 26)
++ 0x2f, 0x96, //udp checksum (0x2f96)
++ 0x01, 0x02, 0x03, 0x04, 0x05, //payload (8 bytes)
++ 0x06, 0x07, 0x08
++ };
++
++ unsigned char pkt_2[]={
++// 0x00, 0x21, 0x86, 0xee, 0xe3, 0x95, // dest mac
++ 0x00, 0x21, 0x86, 0xee, 0xe3, 0x90, // dest mac
++ 0x00, 0x0c, 0x43, 0x28, 0x80, 0x33, // src mac
++ 0x08, 0x00, // type: ip
++ 0x45, 0x00, 0x00, 0x1e, // ip: ..., total len (0x01e = 30)
++ 0xa1, 0x78, 0x00, 0x02, // ip: id, frag, frag offset (16)
++ 0x40, 0x11, 0x63, 0x07, // ip: ttl, protocol, hdr checksum (0x6307)
++ 0x0a, 0x0a, 0x1e, 0x7b, // src ip (10.10.30.123)
++// 0x0a, 0x0a, 0x1e, 0x03, // dst ip (10.10.30.3)
++ 0x0a, 0x0a, 0x1e, 0x05, // dst ip (10.10.30.5)
++ 0x11, 0x12, 0x13, 0x14, 0x15, //payload (10 bytes)
++ 0x16, 0x17, 0x18, 0x19, 0x1a
++ };
++
++ struct net_dev *dev;
++// struct sk_buff *skb_0;
++ struct sk_buff *skb_1;
++ struct sk_buff *skb_2;
++ int i=0;
++
++// skb_0 = alloc_skb(256, GFP_ATOMIC);
++ skb_1 = alloc_skb(256, GFP_ATOMIC);
++ skb_2 = alloc_skb(256, GFP_ATOMIC);
++
++#if 0
++/* send packet 0 */
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ if((dev=dev_get_by_name(&init_net,ifname))){
++#else
++ if((dev=dev_get_by_name(ifname))){
++#endif
++
++ skb_0->dev=dev;
++ skb_put(skb_0,sizeof(pkt_0));
++ memcpy(skb_0->data, pkt_0, sizeof(pkt_0));
++
++ printk("send pkt(len=%d) to %s\n", skb_0->len, skb_0->dev->name);
++
++
++ for(i=0;i<sizeof(pkt_0);i++){
++ if(i%16==0) {
++ printk("\n");
++ }
++ printk("%02X-",skb_0->data[i]);
++ }
++
++ dev_queue_xmit(skb_0);
++ }else{
++ printk("interface %s not found\n",ifname);
++ return 1;
++ }
++#endif
++
++#if 1
++/* send packet 1 */
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ if((dev=dev_get_by_name(&init_net,ifname))){
++#else
++ if((dev=dev_get_by_name(ifname))){
++#endif
++
++ skb_1->dev=dev;
++ skb_put(skb_1,sizeof(pkt_1));
++ memcpy(skb_1->data, pkt_1, sizeof(pkt_1));
++
++ printk("send pkt(len=%d) to %s\n", skb_1->len, skb_1->dev->name);
++
++
++ for(i=0;i<sizeof(pkt_1);i++){
++ if(i%16==0) {
++ printk("\n");
++ }
++ printk("%02X-",skb_1->data[i]);
++ }
++
++ dev_queue_xmit(skb_1);
++ }else{
++ printk("interface %s not found\n",ifname);
++ return 1;
++ }
++#endif
++
++#if 1
++/* send packet 2 */
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ if((dev=dev_get_by_name(&init_net,ifname))){
++#else
++ if((dev=dev_get_by_name(ifname))){
++#endif
++
++ skb_2->dev=dev;
++ skb_put(skb_2,sizeof(pkt_2));
++ memcpy(skb_2->data, pkt_2, sizeof(pkt_2));
++
++ printk("send pkt(len=%d) to %s\n", skb_2->len, skb_2->dev->name);
++
++
++ for(i=0;i<sizeof(pkt_2);i++){
++ if(i%16==0) {
++ printk("\n");
++ }
++ printk("%02X-",skb_2->data[i]);
++ }
++
++ dev_queue_xmit(skb_2);
++ }else{
++ printk("interface %s not found\n",ifname);
++ return 1;
++ }
++#endif
++
++ return 0;
++}
++
++static void PktGenCleanupMod(void)
++{
++}
++
++module_init(PktGenInitMod);
++module_exit(PktGenCleanupMod);
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12)
++MODULE_PARM (ifname, "s");
++#else
++module_param (ifname, charp, 0);
++#endif
++
++MODULE_DESCRIPTION("Ralink PktGen Module");
++MODULE_AUTHOR("Steven Liu");
++MODULE_LICENSE("Proprietary");
++MODULE_PARM_DESC (ifname, "interface name");
++
+diff --git a/drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.c b/drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.c
+new file mode 100755
+index 0000000..971a821
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.c
+@@ -0,0 +1,1527 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <linux/if_vlan.h>
++#include <linux/if_ether.h>
++#include <linux/fs.h>
++#include <asm/uaccess.h>
++#include <asm/rt2880/surfboardint.h>
++#if defined(CONFIG_RAETH_TSO)
++#include <linux/tcp.h>
++#include <net/ipv6.h>
++#include <linux/ip.h>
++#include <net/ip.h>
++#include <net/tcp.h>
++#include <linux/in.h>
++#include <linux/ppp_defs.h>
++#include <linux/if_pppox.h>
++#endif
++#if defined(CONFIG_RAETH_LRO)
++#include <linux/inet_lro.h>
++#endif
++#include <linux/delay.h>
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
++#include <linux/sched.h>
++#endif
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 0)
++#include <asm/rt2880/rt_mmap.h>
++#else
++#include <linux/libata-compat.h>
++#endif
++
++#include "../ra2882ethreg.h"
++#include "../raether.h"
++#include "../ra_mac.h"
++#include "../ra_ioctl.h"
++#include "../ra_rfrw.h"
++#ifdef CONFIG_RAETH_NETLINK
++#include "../ra_netlink.h"
++#endif
++#if defined(CONFIG_RAETH_QOS)
++#include "../ra_qos.h"
++#endif
++#include "raether_pdma_dvt.h"
++
++/* Global variables */
++static unsigned int g_pdma_dvt_show_config;
++static unsigned int g_pdma_dvt_rx_test_config;
++static unsigned int g_pdma_dvt_tx_test_config;
++static unsigned int g_pdma_dvt_debug_test_config;
++static unsigned int g_pdma_dvt_lro_test_config;
++
++unsigned int g_pdma_dev_lanport = 0;
++unsigned int g_pdma_dev_wanport = 0;
++
++void skb_dump(struct sk_buff *sk)
++{
++ unsigned int i;
++
++ printk("skb_dump: from %s with len %d (%d) headroom=%d tailroom=%d\n",
++ sk->dev ? sk->dev->name : "ip stack", sk->len, sk->truesize,
++ skb_headroom(sk), skb_tailroom(sk));
++
++ /* for(i=(unsigned int)sk->head;i<=(unsigned int)sk->tail;i++) { */
++ /* for(i=(unsigned int)sk->head;i<=(unsigned int)sk->data+20;i++) { */
++ for (i = (unsigned int)sk->head; i <= (unsigned int)sk->data + 60; i++) {
++ if ((i % 20) == 0)
++ printk("\n");
++ if (i == (unsigned int)sk->data)
++ printk("{");
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 21)
++ if (i == (unsigned int)sk->transport_header)
++ printk("#");
++ if (i == (unsigned int)sk->network_header)
++ printk("|");
++ if (i == (unsigned int)sk->mac_header)
++ printk("*");
++#else
++ if (i == (unsigned int)sk->h.raw)
++ printk("#");
++ if (i == (unsigned int)sk->nh.raw)
++ printk("|");
++ if (i == (unsigned int)sk->mac.raw)
++ printk("*");
++#endif
++ printk("%02X-", *((unsigned char *)i));
++ if (i == (unsigned int)sk->tail)
++ printk("}");
++ }
++ printk("\n");
++}
++
++#if defined(CONFIG_RAETH_HW_LRO)
++/* PDMA LRO test functions start */
++int pdma_lro_disable_dvt(void)
++{
++ unsigned int regVal = 0;
++
++ printk("pdma_lro_disable_dvt()\n");
++
++ /* 1. Invalid LRO ring1~3 */
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 0);
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 0);
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 0);
++
++ /* 2 Polling relinguish */
++ while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) {;
++ }
++
++ /* 3. Disable LRO */
++ regVal = sysRegRead(ADMA_LRO_CTRL_DW0);
++ regVal &= ~(PDMA_LRO_EN);
++ sysRegWrite(ADMA_LRO_CTRL_DW0, regVal);
++
++#if 0
++ /* 4. Disable non-lro multiple rx */
++ SET_PDMA_NON_LRO_MULTI_EN(0);
++
++ /* 5.1. Set GDM1 to ring0 */
++ SET_GDM_PID1_RXID_SEL(0);
++ /* 5.2. Set GDM2 to ring0 */
++ SET_GDM_PID2_RXID_SEL(0);
++#endif
++
++ return 0;
++}
++
++int pdma_lro_force_aggre_dvt(void)
++{
++ unsigned int regVal = 0;
++ unsigned int ip;
++
++ printk("pdma_lro_force_aggre_dvt()\n");
++
++/* pdma rx ring1 */
++ /* 1. Set RX ring mode to force port */
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_FORCE_PORT);
++
++ /* 2. Configure lro ring */
++ /* 2.1 set src/destination TCP ports */
++ SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING1, 3423);
++ SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING1, 2301);
++ /* 2.2 set src/destination IPs */
++ str_to_ip(&ip, "10.10.10.3");
++ sysRegWrite(LRO_RX_RING1_SIP_DW0, ip);
++ str_to_ip(&ip, "10.10.10.100");
++ sysRegWrite(LRO_RX_RING1_DIP_DW0, ip);
++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING1, 1);
++
++ /* 2.3 Valid LRO ring */
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1);
++
++ /* 2.4 Set AGE timer */
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, 0);
++
++ /* 2.5 Set max AGG timer */
++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING1, 0);
++
++ /* 2.6 Set max LRO agg count */
++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING1, HW_LRO_MAX_AGG_CNT);
++
++ /* 3. IPv4 checksum update enable */
++ SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1);
++
++ /* 4. Polling relinguish */
++ while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) {;
++ }
++
++ /* 5. Enable LRO */
++ regVal = sysRegRead(ADMA_LRO_CTRL_DW0);
++ regVal |= PDMA_LRO_EN;
++ sysRegWrite(ADMA_LRO_CTRL_DW0, regVal);
++
++ return 0;
++}
++
++int pdma_lro_auto_aggre_dvt(void)
++{
++ unsigned int regVal = 0;
++ unsigned int ip;
++
++ printk("pdma_lro_auto_aggre_dvt()\n");
++
++ /* 1.1 Set my IP_1 */
++ str_to_ip(&ip, "10.10.10.254");
++ sysRegWrite(LRO_RX_RING0_DIP_DW0, ip);
++ sysRegWrite(LRO_RX_RING0_DIP_DW1, 0);
++ sysRegWrite(LRO_RX_RING0_DIP_DW2, 0);
++ sysRegWrite(LRO_RX_RING0_DIP_DW3, 0);
++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING0, 1);
++
++ /* 1.2 Set my IP_2 */
++ str_to_ip(&ip, "10.10.20.254");
++ sysRegWrite(LRO_RX_RING1_DIP_DW0, ip);
++ sysRegWrite(LRO_RX_RING1_DIP_DW1, 0);
++ sysRegWrite(LRO_RX_RING1_DIP_DW2, 0);
++ sysRegWrite(LRO_RX_RING1_DIP_DW3, 0);
++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING1, 1);
++
++ /* 1.3 Set my IP_3 */
++ sysRegWrite(LRO_RX_RING2_DIP_DW3, 0x20010238);
++ sysRegWrite(LRO_RX_RING2_DIP_DW2, 0x08000000);
++ sysRegWrite(LRO_RX_RING2_DIP_DW1, 0x00000000);
++ sysRegWrite(LRO_RX_RING2_DIP_DW0, 0x00000254);
++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING2, 1);
++
++ /* 1.4 Set my IP_4 */
++ sysRegWrite(LRO_RX_RING3_DIP_DW3, 0x20010238);
++ sysRegWrite(LRO_RX_RING3_DIP_DW2, 0x08010000);
++ sysRegWrite(LRO_RX_RING3_DIP_DW1, 0x00000000);
++ sysRegWrite(LRO_RX_RING3_DIP_DW0, 0x00000254);
++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING3, 1);
++
++ /* 2.1 Set RX ring1~3 to auto-learn modes */
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_AUTO_LEARN);
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_AUTO_LEARN);
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_AUTO_LEARN);
++
++ /* 2.2 Valid LRO ring */
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING0, 1);
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1);
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 1);
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 1);
++
++ /* 2.3 Set AGE timer */
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, 0);
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, 0);
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, 0);
++
++ /* 2.4 Set max AGG timer */
++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING1, 0);
++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING2, 0);
++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING3, 0);
++
++ /* 2.5 Set max LRO agg count */
++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING1, HW_LRO_MAX_AGG_CNT);
++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING2, HW_LRO_MAX_AGG_CNT);
++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING3, HW_LRO_MAX_AGG_CNT);
++
++ /* 3.0 IPv6 LRO enable */
++ SET_PDMA_LRO_IPV6_EN(1);
++
++ /* 3.1 IPv4 checksum update disable */
++ SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1);
++
++ /* 3.2 switch priority comparision to byte count mode */
++ SET_PDMA_LRO_ALT_SCORE_MODE(PDMA_LRO_ALT_BYTE_CNT_MODE);
++
++ /* 3.3 bandwidth threshold setting */
++ SET_PDMA_LRO_BW_THRESHOLD(0);
++
++ /* 3.4 auto-learn score delta setting */
++ sysRegWrite(LRO_ALT_SCORE_DELTA, 0);
++
++ /* 3.5 Set ALT timer to 20us: (unit: 20us) */
++ SET_PDMA_LRO_ALT_REFRESH_TIMER_UNIT(HW_LRO_TIMER_UNIT);
++ /* 3.6 Set ALT refresh timer to 1 sec. (unit: 20us) */
++ SET_PDMA_LRO_ALT_REFRESH_TIMER(HW_LRO_REFRESH_TIME);
++
++ /* 4. Polling relinguish */
++ while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) {;
++ }
++
++ /* 5. Enable LRO */
++ regVal = sysRegRead(ADMA_LRO_CTRL_DW0);
++ regVal |= PDMA_LRO_EN;
++ sysRegWrite(ADMA_LRO_CTRL_DW0, regVal);
++
++ return 0;
++}
++
++int pdma_lro_auto_ipv6_dvt(void)
++{
++ unsigned int regVal = 0;
++
++ printk("pdma_lro_auto_ipv6_dvt()\n");
++
++ /* 1. Set my IP */
++ sysRegWrite(LRO_RX_RING1_DIP_DW3, 0x20010238);
++ sysRegWrite(LRO_RX_RING1_DIP_DW2, 0x08000000);
++ sysRegWrite(LRO_RX_RING1_DIP_DW1, 0x00000000);
++ sysRegWrite(LRO_RX_RING1_DIP_DW0, 0x00000254);
++
++ /* 2.1 Set RX ring1~3 to auto-learn modes */
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_AUTO_LEARN);
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_AUTO_LEARN);
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_AUTO_LEARN);
++
++ /* 2.2 Valid LRO ring */
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1);
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 1);
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 1);
++
++ /* 2.3 Set AGE timer */
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, HW_LRO_AGE_TIME);
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, HW_LRO_AGE_TIME);
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, HW_LRO_AGE_TIME);
++
++ /* 3.0 IPv6 LRO enable */
++ SET_PDMA_LRO_IPV6_EN(1);
++
++ /* 3.1 IPv4 checksum update disable */
++ SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1);
++
++ /* 3.2 switch priority comparision to byte count mode */
++ SET_PDMA_LRO_ALT_SCORE_MODE(PDMA_LRO_ALT_BYTE_CNT_MODE);
++
++ /* 3.3 bandwidth threshold setting */
++ SET_PDMA_LRO_BW_THRESHOLD(0);
++
++ /* 3.4 auto-learn score delta setting */
++ sysRegWrite(LRO_ALT_SCORE_DELTA, 0);
++
++ /* 3.5 Set ALT timer to 500us: (unit: 20us) */
++ SET_PDMA_LRO_ALT_REFRESH_TIMER_UNIT(25);
++ /* 3.6 Set ALT refresh timer to 1 sec. (unit: 500us) */
++ SET_PDMA_LRO_ALT_REFRESH_TIMER(2000);
++
++ /* 3.7 Set max AGG timer: 10 msec. */
++ SET_PDMA_LRO_MAX_AGG_TIME(HW_LRO_AGG_TIME);
++
++ /* 4. Polling relinguish */
++ while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) {;
++ }
++
++ /* 5. Enable LRO */
++ regVal = sysRegRead(ADMA_LRO_CTRL_DW0);
++ regVal |= PDMA_LRO_EN;
++ sysRegWrite(ADMA_LRO_CTRL_DW0, regVal);
++
++ return 0;
++}
++
++int pdma_lro_auto_myIP_dvt(void)
++{
++ unsigned int regVal = 0;
++ unsigned int ip;
++
++ printk("pdma_lro_auto_myIP_dvt()\n");
++
++ /* 1.1 Set my IP_1 */
++ str_to_ip(&ip, "10.10.10.254");
++ sysRegWrite(LRO_RX_RING0_DIP_DW0, ip);
++ sysRegWrite(LRO_RX_RING0_DIP_DW1, 0);
++ sysRegWrite(LRO_RX_RING0_DIP_DW2, 0);
++ sysRegWrite(LRO_RX_RING0_DIP_DW3, 0);
++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING0, 1);
++ /* 1.2 Set my IP_2 */
++ str_to_ip(&ip, "10.10.20.254");
++ sysRegWrite(LRO_RX_RING1_DIP_DW0, ip);
++ sysRegWrite(LRO_RX_RING1_DIP_DW1, 0);
++ sysRegWrite(LRO_RX_RING1_DIP_DW2, 0);
++ sysRegWrite(LRO_RX_RING1_DIP_DW3, 0);
++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING1, 1);
++ /* 1.3 Set my IP_3 */
++ sysRegWrite(LRO_RX_RING2_DIP_DW3, 0x20010238);
++ sysRegWrite(LRO_RX_RING2_DIP_DW2, 0x08000000);
++ sysRegWrite(LRO_RX_RING2_DIP_DW1, 0x00000000);
++ sysRegWrite(LRO_RX_RING2_DIP_DW0, 0x00000254);
++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING2, 1);
++ /* 1.4 Set my IP_4 */
++ sysRegWrite(LRO_RX_RING3_DIP_DW3, 0x20010238);
++ sysRegWrite(LRO_RX_RING3_DIP_DW2, 0x08010000);
++ sysRegWrite(LRO_RX_RING3_DIP_DW1, 0x00000000);
++ sysRegWrite(LRO_RX_RING3_DIP_DW0, 0x00000254);
++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING3, 1);
++
++ /* 2.1 Set RX ring1~3 to auto-learn modes */
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_AUTO_LEARN);
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_AUTO_LEARN);
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_AUTO_LEARN);
++
++ /* 2.2 Valid LRO ring */
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING0, 1);
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1);
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 1);
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 1);
++
++ /* 2.3 Set AGE timer */
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, HW_LRO_AGE_TIME);
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, HW_LRO_AGE_TIME);
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, HW_LRO_AGE_TIME);
++
++ /* 3.0 IPv6 LRO enable */
++ SET_PDMA_LRO_IPV6_EN(1);
++
++ /* 3.1 IPv4 checksum update disable */
++ SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1);
++
++ /* 3.2 switch priority comparision to byte count mode */
++ SET_PDMA_LRO_ALT_SCORE_MODE(PDMA_LRO_ALT_BYTE_CNT_MODE);
++
++ /* 3.3 bandwidth threshold setting */
++ SET_PDMA_LRO_BW_THRESHOLD(0);
++
++ /* 3.4 auto-learn score delta setting */
++ sysRegWrite(LRO_ALT_SCORE_DELTA, 0);
++
++ /* 3.5 Set ALT timer to 500us: (unit: 20us) */
++ SET_PDMA_LRO_ALT_REFRESH_TIMER_UNIT(25);
++ /* 3.6 Set ALT refresh timer to 1 sec. (unit: 500us) */
++ SET_PDMA_LRO_ALT_REFRESH_TIMER(2000);
++
++ /* 3.7 Set max AGG timer: 10 msec. */
++ SET_PDMA_LRO_MAX_AGG_TIME(HW_LRO_AGG_TIME);
++
++ /* 4. Polling relinguish */
++ while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) {;
++ }
++
++ /* 5. Enable LRO */
++ regVal = sysRegRead(ADMA_LRO_CTRL_DW0);
++ regVal |= PDMA_LRO_EN;
++ sysRegWrite(ADMA_LRO_CTRL_DW0, regVal);
++
++ return 0;
++}
++
++int pdma_lro_dly_int_dvt(int index)
++{
++ unsigned int regVal = 0;
++ unsigned int ip;
++
++ printk("pdma_lro_dly_int_dvt(%d)\n", index);
++
++#if 0
++ /* 1.1 Set my IP_1 */
++ /* str_to_ip( &ip, "10.10.10.254" ); */
++ str_to_ip(&ip, "10.10.10.100");
++ sysRegWrite(LRO_RX_RING0_DIP_DW0, ip);
++ sysRegWrite(LRO_RX_RING0_DIP_DW1, 0);
++ sysRegWrite(LRO_RX_RING0_DIP_DW2, 0);
++ sysRegWrite(LRO_RX_RING0_DIP_DW3, 0);
++#else
++ /* 1.1 set src/destination TCP ports */
++ SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING1, 3423);
++ SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING1, 2301);
++ SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING2, 3423);
++ SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING2, 2301);
++ SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING3, 3423);
++ SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING3, 2301);
++ /* 1.2 set src/destination IPs */
++ str_to_ip(&ip, "10.10.10.3");
++ sysRegWrite(LRO_RX_RING1_SIP_DW0, ip);
++ str_to_ip(&ip, "10.10.10.100");
++ sysRegWrite(LRO_RX_RING1_DIP_DW0, ip);
++ str_to_ip(&ip, "10.10.10.3");
++ sysRegWrite(LRO_RX_RING2_SIP_DW0, ip);
++ str_to_ip(&ip, "10.10.10.100");
++ sysRegWrite(LRO_RX_RING2_DIP_DW0, ip);
++ str_to_ip(&ip, "10.10.10.3");
++ sysRegWrite(LRO_RX_RING3_SIP_DW0, ip);
++ str_to_ip(&ip, "10.10.10.100");
++ sysRegWrite(LRO_RX_RING3_DIP_DW0, ip);
++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING1, 1);
++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING2, 1);
++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING3, 1);
++#endif
++
++ if (index == 0) {
++ /* 1.2 Disable DLY_INT for lro ring */
++ SET_PDMA_LRO_DLY_INT_EN(0);
++ } else {
++ /* 1.2 Enable DLY_INT for lro ring */
++ SET_PDMA_LRO_DLY_INT_EN(1);
++ }
++
++ /* 1.3 LRO ring DLY_INT setting */
++ if (index == 1) {
++ sysRegWrite(LRO_RX1_DLY_INT, DELAY_INT_INIT);
++ } else if (index == 2) {
++ sysRegWrite(LRO_RX2_DLY_INT, DELAY_INT_INIT);
++ } else if (index == 3) {
++ sysRegWrite(LRO_RX3_DLY_INT, DELAY_INT_INIT);
++ }
++#if 0
++ /* 2.1 Set RX rings to auto-learn modes */
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_AUTO_LEARN);
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_AUTO_LEARN);
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_AUTO_LEARN);
++#else
++ /* 2.0 set rx ring mode */
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_FORCE_PORT);
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_FORCE_PORT);
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_FORCE_PORT);
++
++ /* 2.1 IPv4 force port mode */
++ SET_PDMA_RXRING_IPV4_FORCE_MODE(ADMA_RX_RING1, 1);
++ SET_PDMA_RXRING_IPV4_FORCE_MODE(ADMA_RX_RING2, 1);
++ SET_PDMA_RXRING_IPV4_FORCE_MODE(ADMA_RX_RING3, 1);
++#endif
++
++ /* 2.2 Valid LRO ring */
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING0, 1);
++ if ((index == 0) || (index == 1)) {
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1);
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 0);
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 0);
++ } else if (index == 2) {
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 0);
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 1);
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 0);
++ } else {
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 0);
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 0);
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 1);
++ }
++
++ /* 2.3 Set AGE timer */
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, HW_LRO_AGE_TIME);
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, HW_LRO_AGE_TIME);
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, HW_LRO_AGE_TIME);
++
++ /* 3.1 IPv4 checksum update enable */
++ SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1);
++
++ /* 3.2 switch priority comparision to byte count mode */
++ SET_PDMA_LRO_ALT_SCORE_MODE(PDMA_LRO_ALT_BYTE_CNT_MODE);
++
++ /* 3.3 bandwidth threshold setting */
++ SET_PDMA_LRO_BW_THRESHOLD(0);
++
++ /* 3.4 auto-learn score delta setting */
++ sysRegWrite(LRO_ALT_SCORE_DELTA, 0);
++
++ /* 3.5 Set ALT timer to 500us: (unit: 20us) */
++ SET_PDMA_LRO_ALT_REFRESH_TIMER_UNIT(25);
++ /* 3.6 Set ALT refresh timer to 1 sec. (unit: 500us) */
++ SET_PDMA_LRO_ALT_REFRESH_TIMER(2000);
++
++ /* 3.7 Set max AGG timer */
++ SET_PDMA_LRO_MAX_AGG_TIME(HW_LRO_AGG_TIME);
++
++ /* 4. Polling relinguish */
++ while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) {;
++ }
++
++ /* 5. Enable LRO */
++ regVal = sysRegRead(ADMA_LRO_CTRL_DW0);
++ regVal |= PDMA_LRO_EN;
++ sysRegWrite(ADMA_LRO_CTRL_DW0, regVal);
++
++ return 0;
++}
++
++int pdma_lro_dly_int0_dvt(void)
++{
++ return pdma_lro_dly_int_dvt(0);
++}
++
++int pdma_lro_dly_int1_dvt(void)
++{
++ return pdma_lro_dly_int_dvt(1);
++}
++
++int pdma_lro_dly_int2_dvt(void)
++{
++ return pdma_lro_dly_int_dvt(2);
++}
++
++int pdma_lro_dly_int3_dvt(void)
++{
++ return pdma_lro_dly_int_dvt(3);
++}
++
++#endif /* CONFIG_RAETH_HW_LRO */
++
++#if defined(CONFIG_RAETH_MULTIPLE_RX_RING)
++int pdma_gdm_rxid_config(void)
++{
++ unsigned int regVal = 0;
++
++ printk("pdma_gdm_rxid_config()\n");
++
++ /* 1. Set RX ring1~3 to pse modes */
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_PSE_MODE);
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_PSE_MODE);
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_PSE_MODE);
++
++ /* 2. Enable non-lro multiple rx */
++ SET_PDMA_NON_LRO_MULTI_EN(1);
++
++ return 0;
++}
++
++int pdma_non_lro_portid_dvt(void)
++{
++ unsigned int regVal = 0;
++
++ printk("pdma_non_lro_portid_dvt()\n");
++
++ /* 1. Set GDM1 to ring3 */
++ SET_GDM_PID1_RXID_SEL(3);
++#if 0
++ /* 2. Set GDM2 to ring1 */
++ SET_GDM_PID2_RXID_SEL(1);
++#endif
++
++ /* 3. Set priority rule: pid */
++ SET_GDM_RXID_PRI_SEL(GDM_PRI_PID);
++
++ /* PDMA multi-rx enable */
++ pdma_gdm_rxid_config();
++
++ return 0;
++}
++
++int pdma_non_lro_stag_dvt(void)
++{
++ unsigned int regVal = 0;
++
++ printk("pdma_non_lro_stag_dvt()\n");
++
++ /* 1. Set STAG4 to ring0 */
++ GDM_STAG_RXID_SEL(4, 0);
++ /* 2. Set STAG3 to ring1 */
++ GDM_STAG_RXID_SEL(3, 1);
++ /* 3. Set STAG2 to ring2 */
++ GDM_STAG_RXID_SEL(2, 2);
++ /* 4. Set STAG1 to ring3 */
++ GDM_STAG_RXID_SEL(1, 3);
++
++ /* 5. Set priority rule: stag/pid */
++ SET_GDM_RXID_PRI_SEL(GDM_PRI_PID);
++
++ /* PDMA multi-rx enable */
++ pdma_gdm_rxid_config();
++
++ return 0;
++}
++
++int pdma_non_lro_vlan_dvt(void)
++{
++ unsigned int regVal = 0;
++
++ printk("pdma_non_lro_vlan_dvt()\n");
++
++ /* 1. Set vlan priority=3 to ring1 */
++ SET_GDM_VLAN_PRI_RXID_SEL(3, 1);
++ /* 2. Set vlan priority=2 to ring2 */
++ SET_GDM_VLAN_PRI_RXID_SEL(2, 2);
++ /* 3. Set vlan priority=1 to ring3 */
++ SET_GDM_VLAN_PRI_RXID_SEL(1, 3);
++ /* 4. Set vlan priority=0 to ring3 */
++ SET_GDM_VLAN_PRI_RXID_SEL(0, 3);
++
++ /* 1. Set vlan priority=4 to ring1 */
++ SET_GDM_VLAN_PRI_RXID_SEL(4, 1);
++ /* 2. Set vlan priority=5 to ring2 */
++ SET_GDM_VLAN_PRI_RXID_SEL(5, 2);
++ /* 3. Set vlan priority=6 to ring3 */
++ SET_GDM_VLAN_PRI_RXID_SEL(6, 3);
++ /* 4. Set vlan priority=7 to ring3 */
++ SET_GDM_VLAN_PRI_RXID_SEL(7, 3);
++
++ /* 4. Set priority rule: vlan > pid */
++ SET_GDM_RXID_PRI_SEL(GDM_PRI_VLAN_PID);
++
++ /* PDMA multi-rx enable */
++ pdma_gdm_rxid_config();
++
++ return 0;
++}
++
++int pdma_non_lro_tcpack_dvt(void)
++{
++ unsigned int regVal = 0;
++
++ printk("pdma_non_lro_tcpack_dvt()\n");
++
++ /* 1. Enable TCP ACK with zero payload check */
++ SET_GDM_TCP_ACK_WZPC(1);
++ /* 2. Set TCP ACK to ring3 */
++ SET_GDM_TCP_ACK_RXID_SEL(3);
++
++ /* 3. Set priority rule: ack > pid */
++ SET_GDM_RXID_PRI_SEL(GDM_PRI_ACK_PID);
++
++ /* PDMA multi-rx enable */
++ pdma_gdm_rxid_config();
++
++ return 0;
++}
++
++int pdma_non_lro_pri1_dvt(void)
++{
++ unsigned int regVal = 0;
++
++ printk("pdma_non_lro_pri1_dvt()\n");
++
++ /* 1. Set GDM1 to ring0 */
++ SET_GDM_PID1_RXID_SEL(0);
++
++ /* 2.1 Disable TCP ACK with zero payload check */
++ SET_GDM_TCP_ACK_WZPC(0);
++ /* 2.2 Set TCP ACK to ring1 */
++ SET_GDM_TCP_ACK_RXID_SEL(1);
++
++ /* 3. Set vlan priority=1 to ring2 */
++ SET_GDM_VLAN_PRI_RXID_SEL(1, 2);
++
++ /* 4. Set priority rule: vlan > ack > pid */
++ SET_GDM_RXID_PRI_SEL(GDM_PRI_VLAN_ACK_PID);
++
++ /* PDMA multi-rx enable */
++ pdma_gdm_rxid_config();
++
++ return 0;
++}
++
++int pdma_non_lro_pri2_dvt(void)
++{
++ unsigned int regVal = 0;
++
++ printk("pdma_non_lro_pri2_dvt()\n");
++
++ /* 1. Set GDM1 to ring0 */
++ SET_GDM_PID1_RXID_SEL(0);
++
++ /* 2.1 Disable TCP ACK with zero payload check */
++ SET_GDM_TCP_ACK_WZPC(0);
++ /* 2.2 Set TCP ACK to ring1 */
++ SET_GDM_TCP_ACK_RXID_SEL(1);
++
++ /* 3. Set vlan priority=1 to ring2 */
++ SET_GDM_VLAN_PRI_RXID_SEL(1, 2);
++
++ /* 4. Set priority rule: ack > vlan > pid */
++ SET_GDM_RXID_PRI_SEL(GDM_PRI_ACK_VLAN_PID);
++
++ /* PDMA multi-rx enable */
++ pdma_gdm_rxid_config();
++
++ return 0;
++}
++#endif /* CONFIG_RAETH_MULTIPLE_RX_RING */
++const static PDMA_LRO_DVT_FUNC pdma_dvt_lro_func[] = {
++#if defined(CONFIG_RAETH_HW_LRO)
++ [0] = pdma_lro_disable_dvt, /* PDMA_TEST_LRO_DISABLE */
++ [1] = pdma_lro_force_aggre_dvt, /* PDMA_TEST_LRO_FORCE_PORT */
++ [2] = pdma_lro_auto_aggre_dvt, /* PDMA_TEST_LRO_AUTO_LEARN */
++ [3] = pdma_lro_auto_ipv6_dvt, /* PDMA_TEST_LRO_AUTO_IPV6 */
++ [4] = pdma_lro_auto_myIP_dvt, /* PDMA_TEST_LRO_AUTO_MYIP */
++ [5] = pdma_lro_force_aggre_dvt, /* PDMA_TEST_LRO_FORCE_AGGREGATE */
++#endif /* CONFIG_RAETH_HW_LRO */
++#if defined(CONFIG_RAETH_MULTIPLE_RX_RING)
++ [6] = pdma_non_lro_portid_dvt, /* PDMA_TEST_NON_LRO_PORT_ID */
++ [7] = pdma_non_lro_stag_dvt, /* PDMA_TEST_NON_LRO_STAG */
++ [8] = pdma_non_lro_vlan_dvt, /* PDMA_TEST_NON_LRO_VLAN */
++ [9] = pdma_non_lro_tcpack_dvt, /* PDMA_TEST_NON_LRO_TCP_ACK */
++ [10] = pdma_non_lro_pri1_dvt, /* PDMA_TEST_NON_LRO_PRI1 */
++ [11] = pdma_non_lro_pri2_dvt, /* PDMA_TEST_NON_LRO_PRI2 */
++#endif /* CONFIG_RAETH_MULTIPLE_RX_RING */
++#if defined(CONFIG_RAETH_HW_LRO)
++ [12] = pdma_lro_dly_int0_dvt, /* PDMA_TEST_LRO_DLY_INT0 */
++ [13] = pdma_lro_dly_int1_dvt, /* PDMA_TEST_LRO_DLY_INT1 */
++ [14] = pdma_lro_dly_int2_dvt, /* PDMA_TEST_LRO_DLY_INT2 */
++ [15] = pdma_lro_dly_int3_dvt, /* PDMA_TEST_LRO_DLY_INT3 */
++#endif /* CONFIG_RAETH_HW_LRO */
++};
++
++/* PDMA LRO test functions end */
++
++#if defined(CONFIG_RAETH_HW_LRO) || defined(CONFIG_RAETH_MULTIPLE_RX_RING)
++void raeth_pdma_lro_dvt(int rx_ring_no, END_DEVICE *ei_local,
++ int rx_dma_owner_idx0)
++{
++ if (pdma_dvt_get_show_config() & PDMA_SHOW_RX_DESC) {
++ if (rx_ring_no == 1) {
++ printk("------- rt2880_eth_recv (ring1) --------\n");
++ printk("rx_info1=0x%x\n",
++ *(unsigned int *)
++ &ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info1);
++ printk("rx_info2=0x%x\n",
++ *(unsigned int *)
++ &ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info2);
++ printk("rx_info3=0x%x\n",
++ *(unsigned int *)
++ &ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info3);
++ printk("rx_info4=0x%x\n",
++ *(unsigned int *)
++ &ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info4);
++ printk("-------------------------------\n");
++ } else if (rx_ring_no == 2) {
++ printk("------- rt2880_eth_recv (ring2) --------\n");
++ printk("rx_info1=0x%x\n",
++ *(unsigned int *)
++ &ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info1);
++ printk("rx_info2=0x%x\n",
++ *(unsigned int *)
++ &ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info2);
++ printk("rx_info3=0x%x\n",
++ *(unsigned int *)
++ &ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info3);
++ printk("rx_info4=0x%x\n",
++ *(unsigned int *)
++ &ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info4);
++ printk("-------------------------------\n");
++ } else if (rx_ring_no == 3) {
++ printk("------- rt2880_eth_recv (ring3) --------\n");
++ printk("rx_info1=0x%x\n",
++ *(unsigned int *)
++ &ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info1);
++ printk("rx_info2=0x%x\n",
++ *(unsigned int *)
++ &ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info2);
++ printk("rx_info3=0x%x\n",
++ *(unsigned int *)
++ &ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info3);
++ printk("rx_info4=0x%x\n",
++ *(unsigned int *)
++ &ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info4);
++ printk("-------------------------------\n");
++ }
++#if 0
++ else {
++ printk("------- rt2880_eth_recv (ring0) --------\n");
++ printk("rx_info1=0x%x\n",
++ *(unsigned int *)
++ &ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info1);
++ printk("rx_info2=0x%x\n",
++ *(unsigned int *)
++ &ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info2);
++ printk("rx_info3=0x%x\n",
++ *(unsigned int *)
++ &ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info3);
++ printk("rx_info4=0x%x\n",
++ *(unsigned int *)
++ &ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info4);
++ printk("-------------------------------\n");
++ }
++#endif
++ }
++ if ((pdma_dvt_get_show_config() & PDMA_SHOW_DETAIL_RX_DESC) ||
++ (pdma_dvt_get_lro_test_config()==PDMA_TEST_LRO_FORCE_PORT)) {
++ if (rx_ring_no == 1) {
++ printk("------- rt2880_eth_recv (ring1) --------\n");
++ printk("rx_info1.PDP0=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info1.PDP0);
++ printk("rx_info2.DDONE_bit=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info2.DDONE_bit);
++ printk("rx_info2.LS0=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info2.LS0);
++ printk("rx_info2.PLEN0=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info2.PLEN0);
++ printk("rx_info2.TAG=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info2.TAG);
++#if defined(CONFIG_ARCH_MT7623)
++ printk("rx_info2.LRO_AGG_CNT=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info2.LRO_AGG_CNT);
++ printk("rx_info2.REV=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info2.REV);
++#else
++ printk("rx_info2.LS1=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info2.LS1);
++#endif /* CONFIG_RAETH_HW_LRO */
++ printk("rx_info2.PLEN1=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info2.PLEN1);
++ printk("rx_info3.TPID=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info3.TPID);
++ printk("rx_info3.VID=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info3.VID);
++ printk("rx_info4.IP6=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info4.IP6);
++ printk("rx_info4.IP4=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info4.IP4);
++ printk("rx_info4.IP4F=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info4.IP4F);
++ printk("rx_info4.TACK=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info4.TACK);
++ printk("rx_info4.L4VLD=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info4.L4VLD);
++ printk("rx_info4.L4F=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info4.L4F);
++ printk("rx_info4.SPORT=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info4.SP);
++ printk("rx_info4.CRSN=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info4.CRSN);
++ printk("rx_info4.FOE_Entry=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info4.FOE_Entry);
++ printk("-------------------------------\n");
++ } else if (rx_ring_no == 2) {
++ printk("------- rt2880_eth_recv (ring2) --------\n");
++ printk("rx_info1.PDP0=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info1.PDP0);
++ printk("rx_info2.DDONE_bit=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info2.DDONE_bit);
++ printk("rx_info2.LS0=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info2.LS0);
++ printk("rx_info2.PLEN0=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info2.PLEN0);
++ printk("rx_info2.TAG=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info2.TAG);
++#if defined(CONFIG_ARCH_MT7623)
++ printk("rx_info2.LRO_AGG_CNT=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info2.LRO_AGG_CNT);
++ printk("rx_info2.REV=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info2.REV);
++#else
++ printk("rx_info2.LS1=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info2.LS1);
++#endif /* CONFIG_RAETH_HW_LRO */
++ printk("rx_info2.PLEN1=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info2.PLEN1);
++ printk("rx_info3.TPID=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info3.TPID);
++ printk("rx_info3.VID=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info3.VID);
++ printk("rx_info4.IP6=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info4.IP6);
++ printk("rx_info4.IP4=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info4.IP4);
++ printk("rx_info4.IP4F=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info4.IP4F);
++ printk("rx_info4.TACK=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info4.TACK);
++ printk("rx_info4.L4VLD=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info4.L4VLD);
++ printk("rx_info4.L4F=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info4.L4F);
++ printk("rx_info4.SPORT=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info4.SP);
++ printk("rx_info4.CRSN=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info4.CRSN);
++ printk("rx_info4.FOE_Entry=0x%x\n",
++ ei_local->rx_ring2[rx_dma_owner_idx0].
++ rxd_info4.FOE_Entry);
++ printk("-------------------------------\n");
++ } else if (rx_ring_no == 3) {
++ printk("------- rt2880_eth_recv (ring3) --------\n");
++ printk("rx_info1.PDP0=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info1.PDP0);
++ printk("rx_info2.DDONE_bit=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info2.DDONE_bit);
++ printk("rx_info2.LS0=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info2.LS0);
++ printk("rx_info2.PLEN0=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info2.PLEN0);
++ printk("rx_info2.TAG=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info2.TAG);
++#if defined(CONFIG_ARCH_MT7623)
++ printk("rx_info2.LRO_AGG_CNT=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info2.LRO_AGG_CNT);
++ printk("rx_info2.REV=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info2.REV);
++#else
++ printk("rx_info2.LS1=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info2.LS1);
++#endif /* CONFIG_RAETH_HW_LRO */
++ printk("rx_info2.PLEN1=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info2.PLEN1);
++ printk("rx_info3.TPID=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info3.TPID);
++ printk("rx_info3.VID=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info3.VID);
++ printk("rx_info4.IP6=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info4.IP6);
++ printk("rx_info4.IP4=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info4.IP4);
++ printk("rx_info4.IP4F=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info4.IP4F);
++ printk("rx_info4.TACK=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info4.TACK);
++ printk("rx_info4.L4VLD=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info4.L4VLD);
++ printk("rx_info4.L4F=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info4.L4F);
++ printk("rx_info4.SPORT=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info4.SP);
++ printk("rx_info4.CRSN=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info4.CRSN);
++ printk("rx_info4.FOE_Entry=0x%x\n",
++ ei_local->rx_ring3[rx_dma_owner_idx0].
++ rxd_info4.FOE_Entry);
++ printk("-------------------------------\n");
++ }
++#if 0
++ else {
++ printk("------- rt2880_eth_recv (ring0) --------\n");
++ printk("rx_info1.PDP0=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info1.PDP0);
++ printk("rx_info2.DDONE_bit=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info2.DDONE_bit);
++ printk("rx_info2.LS0=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info2.LS0);
++ printk("rx_info2.PLEN0=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info2.PLEN0);
++ printk("rx_info2.TAG=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info2.TAG);
++ printk("rx_info2.LS1=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info2.LS1);
++ printk("rx_info2.PLEN1=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info2.PLEN1);
++ printk("rx_info3.TPID=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info3.TPID);
++ printk("rx_info3.VID=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info3.VID);
++ printk("rx_info4.IP6=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info4.IP6);
++ printk("rx_info4.IP4=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info4.IP4);
++ printk("rx_info4.IP4F=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info4.IP4F);
++ printk("rx_info4.TACK=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info4.TACK);
++ printk("rx_info4.L4VLD=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info4.L4VLD);
++ printk("rx_info4.L4F=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info4.L4F);
++ printk("rx_info4.SPORT=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info4.SP);
++ printk("rx_info4.CRSN=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info4.CRSN);
++ printk("rx_info4.FOE_Entry=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info4.FOE_Entry);
++ printk("-------------------------------\n");
++ }
++#endif
++ }
++ if (pdma_dvt_get_lro_test_config() == PDMA_TEST_LRO_FORCE_AGGREGATE) {
++ if (rx_ring_no == 1) {
++ printk("PASS!!! => RING1: rxd_info1.PDP0=0x%x\n",
++ ei_local->rx_ring1[rx_dma_owner_idx0].
++ rxd_info1.PDP0);
++ skb_dump(ei_local->netrx1_skbuf[rx_dma_owner_idx0]);
++ pdma_dvt_reset_config();
++ }
++ }
++}
++#endif
++
++int pdma_dvt_show_ctrl(int par1, int par2)
++{
++ if (par2 == 0)
++ g_pdma_dvt_show_config = 0;
++ else
++ g_pdma_dvt_show_config |= (1 << par2);
++
++ return 0;
++}
++
++int pdma_dvt_test_rx_ctrl(int par1, int par2)
++{
++ if (par2 == 0)
++ g_pdma_dvt_rx_test_config = 0;
++ else
++ g_pdma_dvt_rx_test_config |= (1 << par2);
++
++ return 0;
++}
++
++int pdma_dvt_test_tx_ctrl(int par1, int par2)
++{
++ if (par2 == 0)
++ g_pdma_dvt_tx_test_config = 0;
++ else
++ g_pdma_dvt_tx_test_config |= (1 << par2);
++
++ return 0;
++}
++
++int pdma_dvt_test_debug_ctrl(int par1, int par2)
++{
++ if (par2 == 0)
++ g_pdma_dvt_debug_test_config = 0;
++ else
++ g_pdma_dvt_debug_test_config |= (1 << par2);
++
++ return 0;
++}
++
++int pdma_dvt_test_lro_ctrl(int par1, int par2)
++{
++ g_pdma_dvt_lro_test_config = par2;
++
++#if defined(CONFIG_RAETH_HW_LRO) || defined(CONFIG_RAETH_MULTIPLE_RX_RING)
++ if (pdma_dvt_lro_func[par2])
++ (*pdma_dvt_lro_func[par2]) ();
++#endif /* #if defined (CONFIG_RAETH_HW_LRO) */
++
++ return 0;
++}
++
++unsigned int pdma_dvt_get_show_config()
++{
++ return g_pdma_dvt_show_config;
++}
++
++unsigned int pdma_dvt_get_rx_test_config()
++{
++ return g_pdma_dvt_rx_test_config;
++}
++
++unsigned int pdma_dvt_get_tx_test_config()
++{
++ return g_pdma_dvt_tx_test_config;
++}
++
++unsigned int pdma_dvt_get_debug_test_config()
++{
++ return g_pdma_dvt_debug_test_config;
++}
++
++unsigned int pdma_dvt_get_lro_test_config()
++{
++ return g_pdma_dvt_lro_test_config;
++}
++
++void pdma_dvt_reset_config()
++{
++ g_pdma_dvt_show_config = 0;
++ g_pdma_dvt_rx_test_config = 0;
++ g_pdma_dvt_tx_test_config = 0;
++ g_pdma_dvt_lro_test_config = 0;
++}
++
++void raeth_pdma_rx_desc_dvt(END_DEVICE *ei_local, int rx_dma_owner_idx0)
++{
++#if 0
++ unsigned int udf = 0;
++#endif
++
++ if (pdma_dvt_get_show_config() & PDMA_SHOW_RX_DESC) {
++ printk("------- rt2880_eth_recv --------\n");
++ printk("rx_info1=0x%x\n",
++ *(unsigned int *)&ei_local->
++ rx_ring0[rx_dma_owner_idx0].rxd_info1);
++ printk("rx_info2=0x%x\n",
++ *(unsigned int *)&ei_local->
++ rx_ring0[rx_dma_owner_idx0].rxd_info2);
++ printk("rx_info3=0x%x\n",
++ *(unsigned int *)&ei_local->
++ rx_ring0[rx_dma_owner_idx0].rxd_info3);
++ printk("rx_info4=0x%x\n",
++ *(unsigned int *)&ei_local->
++ rx_ring0[rx_dma_owner_idx0].rxd_info4);
++ printk("-------------------------------\n");
++ }
++ if ((pdma_dvt_get_show_config() & PDMA_SHOW_DETAIL_RX_DESC) ||
++ pdma_dvt_get_rx_test_config()) {
++#if 0
++ udf = ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP6 << 5 |
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP4 << 4 |
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP4F << 3 |
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.TACK << 2 |
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.L4VLD << 1 |
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.L4F;
++#endif
++ printk("------- rt2880_eth_recv --------\n");
++ printk("rx_info1.PDP0=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info1.PDP0);
++ printk("rx_info2.DDONE_bit=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info2.DDONE_bit);
++ printk("rx_info2.LS0=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.LS0);
++ printk("rx_info2.PLEN0=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.PLEN0);
++ printk("rx_info2.TAG=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.TAG);
++#if defined(CONFIG_ARCH_MT7623)
++ printk("rx_info2.LRO_AGG_CNT=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info2.LRO_AGG_CNT);
++#else
++ printk("rx_info2.LS1=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.LS1);
++#endif /* CONFIG_RAETH_HW_LRO */
++ printk("rx_info2.PLEN1=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.PLEN1);
++ printk("rx_info3.TPID=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info3.TPID);
++ printk("rx_info3.VID=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info3.VID);
++#if 0
++ printk("rx_info4.UDF=0x%x\n", udf);
++#endif
++ printk("rx_info4.IP6=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP6);
++ printk("rx_info4.IP4=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP4);
++ printk("rx_info4.IP4F=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP4F);
++ printk("rx_info4.TACK=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.TACK);
++ printk("rx_info4.L4VLD=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.L4VLD);
++ printk("rx_info4.L4F=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.L4F);
++ printk("rx_info4.SPORT=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.SP);
++ printk("rx_info4.CRSN=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.CRSN);
++ printk("rx_info4.FOE_Entry=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info4.FOE_Entry);
++ printk("-------------------------------\n");
++ }
++ if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_IPV6)) {
++ if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP6) {
++ printk("PASS!!! => rx_info4.IP6=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info4.IP6);
++ pdma_dvt_reset_config();
++ }
++ } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_IPV4)) {
++ if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP4) {
++ printk("PASS!!! => rx_info4.IP4=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info4.IP4);
++ pdma_dvt_reset_config();
++ }
++ } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_IPV4F)) {
++ if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP4F) {
++ printk("PASS!!! => rx_info4.IP4F=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info4.IP4F);
++ pdma_dvt_reset_config();
++ }
++ } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_L4VLD)) {
++ if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.L4VLD) {
++ printk("PASS!!! => rx_info4.L4VLD=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info4.L4VLD);
++ pdma_dvt_reset_config();
++ }
++ } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_L4F)) {
++ if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.L4F) {
++ printk("PASS!!! => rx_info4.L4F=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info4.L4F);
++ pdma_dvt_reset_config();
++ }
++ } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_SPORT)) {
++ if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.SP == 1) {
++ g_pdma_dev_lanport++;
++ } else if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.SP ==
++ 2) {
++ g_pdma_dev_wanport++;
++ }
++ if (g_pdma_dev_lanport && g_pdma_dev_wanport) {
++ printk
++ ("PASS!!! => g_pdma_dev_lanport=0x%x, g_pdma_dev_wanport=0x%x",
++ g_pdma_dev_lanport, g_pdma_dev_wanport);
++
++ g_pdma_dev_lanport = 0;
++ g_pdma_dev_wanport = 0;
++ pdma_dvt_reset_config();
++ }
++ } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_VID_OFF)) {
++ if (!ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info3.VID) {
++ printk("PASS!!! => rxd_info3.VID=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info3.VID);
++ pdma_dvt_reset_config();
++ }
++ } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_VID_ON)) {
++ printk("RX data: (PDP0=%x)\n",
++ (unsigned int)ei_local->
++ netrx0_skbuf[rx_dma_owner_idx0]->data);
++
++ skb_dump(ei_local->netrx0_skbuf[rx_dma_owner_idx0]);
++
++ if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info3.VID &&
++ ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.TAG) {
++ printk("PASS!!! => rxd_info2.TAG=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info2.TAG);
++ printk("PASS!!! => rxd_info3.VID=0x%x\n",
++ ei_local->rx_ring0[rx_dma_owner_idx0].
++ rxd_info3.VID);
++ pdma_dvt_reset_config();
++ }
++ }
++}
++
++void raeth_pdma_tx_vlan_dvt(END_DEVICE *ei_local,
++ unsigned long tx_cpu_owner_idx0)
++{
++ if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_ON)) {
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0x10000 | 0xE007; /* VLAN_TAG = 0x1E007 */
++ } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_ZERO)) {
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0x10000 | 0x0000; /* VLAN_TAG = 0x10000 */
++ } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_MAX)) {
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0x10000 | 0xFFFF; /* VLAN_TAG = 0x1FFFF */
++ }
++}
++
++void raeth_pdma_tx_desc_dvt(END_DEVICE *ei_local,
++ unsigned long tx_cpu_owner_idx0)
++{
++ if (PDMA_TEST_RX_UDF == pdma_dvt_get_rx_test_config()) {
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 4; /* PPE */
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.UDF = 0x2F;
++ }
++ if (pdma_dvt_get_show_config() & PDMA_SHOW_TX_DESC) {
++ printk("------- rt2880_eth_send --------\n");
++ printk("tx_info1=%x\n",
++ *(unsigned int *)&ei_local->
++ tx_ring0[tx_cpu_owner_idx0].txd_info1);
++ printk("tx_info2=%x\n",
++ *(unsigned int *)&ei_local->
++ tx_ring0[tx_cpu_owner_idx0].txd_info2);
++ printk("tx_info3=%x\n",
++ *(unsigned int *)&ei_local->
++ tx_ring0[tx_cpu_owner_idx0].txd_info3);
++ printk("tx_info4=%x\n",
++ *(unsigned int *)&ei_local->
++ tx_ring0[tx_cpu_owner_idx0].txd_info4);
++ printk("--------------------------------\n");
++ }
++ if ((pdma_dvt_get_show_config() & PDMA_SHOW_DETAIL_TX_DESC) ||
++ pdma_dvt_get_tx_test_config()) {
++ printk("------- rt2880_eth_send --------\n");
++ printk("tx_info1.SDP0=%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info1.SDP0);
++ printk("tx_info2.DDONE_bit=%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].
++ txd_info2.DDONE_bit);
++ printk("tx_info2.LS0_bit=%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS0_bit);
++ printk("tx_info2.SDL0=%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.SDL0);
++ printk("tx_info2.BURST_bit=%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].
++ txd_info2.BURST_bit);
++ printk("tx_info2.LS1_bit=%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS1_bit);
++ printk("tx_info2.SDL1=%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.SDL1);
++ printk("tx_info3.SDP1=%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info3.SDP1);
++ printk("tx_info4.TUI_CO=%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TUI_CO);
++ printk("tx_info4.TSO=%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TSO);
++ printk("tx_info4.FPORT=%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT);
++ printk("tx_info4.UDF=%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.UDF);
++ printk("tx_info4.RESV=%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.RESV);
++ printk("tx_info4.VLAN_TAG=%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].
++ txd_info4.VLAN_TAG);
++ printk("--------------------------------\n");
++ }
++ if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_LAN_SPORT)) {
++ if (ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT == 1) {
++ printk("PASS!!! => txd_info4.FPORT=0x%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].
++ txd_info4.FPORT);
++ pdma_dvt_reset_config();
++ }
++ } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_WAN_SPORT)) {
++ if (ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT == 2) {
++ printk("PASS!!! => txd_info4.FPORT=0x%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].
++ txd_info4.FPORT);
++ pdma_dvt_reset_config();
++ }
++ } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_ON)) {
++ if (ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG) {
++ printk("PASS!!! => txd_info4.VLAN_TAG=0x%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].
++ txd_info4.VLAN_TAG);
++ /* pdma_dvt_reset_config(); */
++ }
++ } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_OFF)) {
++ if (!ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG) {
++ printk("PASS!!! => txd_info4.VLAN_TAG=0x%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].
++ txd_info4.VLAN_TAG);
++ pdma_dvt_reset_config();
++ }
++ } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_ZERO)) {
++ if (ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG) {
++ printk("PASS!!! => txd_info4.VLAN_TAG=0x%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].
++ txd_info4.VLAN_TAG);
++ /* pdma_dvt_reset_config(); */
++ }
++ } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_MAX)) {
++ if (ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG) {
++ printk("PASS!!! => txd_info4.VLAN_TAG=0x%x\n",
++ ei_local->tx_ring0[tx_cpu_owner_idx0].
++ txd_info4.VLAN_TAG);
++ /* pdma_dvt_reset_config(); */
++ }
++ }
++}
++
++void raeth_pdma_lro_dly_int_dvt(void)
++{
++ unsigned int reg_int_val;
++
++ reg_int_val = sysRegRead(RAETH_FE_INT_STATUS);
++
++ if (pdma_dvt_get_lro_test_config() == PDMA_TEST_LRO_DLY_INT0) {
++ if ((reg_int_val & RX_DLY_INT)) {
++ printk("PASS!!! => reg_int_val=0x%x\n", reg_int_val);
++ pdma_dvt_reset_config();
++ }
++ } else if (pdma_dvt_get_lro_test_config() == PDMA_TEST_LRO_DLY_INT1) {
++ if ((reg_int_val & RING1_RX_DLY_INT)) {
++ printk("PASS!!! => reg_int_val=0x%x\n", reg_int_val);
++ pdma_dvt_reset_config();
++ }
++ } else if (pdma_dvt_get_lro_test_config() == PDMA_TEST_LRO_DLY_INT2) {
++ if ((reg_int_val & RING2_RX_DLY_INT)) {
++ printk("PASS!!! => reg_int_val=0x%x\n", reg_int_val);
++ pdma_dvt_reset_config();
++ }
++ } else if (pdma_dvt_get_lro_test_config() == PDMA_TEST_LRO_DLY_INT3) {
++ if ((reg_int_val & RING3_RX_DLY_INT)) {
++ printk("PASS!!! => reg_int_val=0x%x\n", reg_int_val);
++ pdma_dvt_reset_config();
++ }
++ }
++}
++
++void pdma_dvt_set_dma_mode(void)
++{
++#if defined(CONFIG_RAETH_PDMA_LEGACY_MODE)
++ unsigned int regVal;
++ regVal = sysRegRead(ADMA_LRO_CTRL_DW3);
++ regVal &= ~(BIT(15));
++ sysRegWrite(ADMA_LRO_CTRL_DW3, regVal);
++#endif /* CONFIG_RAETH_PDMA_DVT */
++}
++
+diff --git a/drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.h b/drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.h
+new file mode 100755
+index 0000000..600aab7
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.h
+@@ -0,0 +1,75 @@
++/* Show controls */
++#define PDMA_SHOW_RX_DESC (1 << 1)
++#define PDMA_SHOW_TX_DESC (1 << 2)
++#define PDMA_SHOW_DETAIL_RX_DESC (1 << 3)
++#define PDMA_SHOW_DETAIL_TX_DESC (1 << 4)
++
++/* Rx test controls */
++#define PDMA_TEST_RX_UDF (1 << 1)
++#define PDMA_TEST_RX_IPV6 (1 << 2)
++#define PDMA_TEST_RX_IPV4 (1 << 3)
++#define PDMA_TEST_RX_IPV4F (1 << 4)
++#define PDMA_TEST_RX_L4VLD (1 << 5)
++#define PDMA_TEST_RX_L4F (1 << 6)
++#define PDMA_TEST_RX_SPORT (1 << 7)
++#define PDMA_TEST_RX_VID_ON (1 << 8)
++#define PDMA_TEST_RX_VID_OFF (1 << 9)
++
++/* Tx test controls */
++#define PDMA_TEST_TX_LAN_SPORT (1 << 1)
++#define PDMA_TEST_TX_WAN_SPORT (1 << 2)
++#define PDMA_TEST_TX_VLAN_ON (1 << 3)
++#define PDMA_TEST_TX_VLAN_OFF (1 << 4)
++#define PDMA_TEST_TX_VLAN_ZERO (1 << 5)
++#define PDMA_TEST_TX_VLAN_MAX (1 << 6)
++#define PDMA_TEST_TX_PDMA_LPK (1 << 31)
++
++/* Debug controls */
++#define PDMA_TEST_TSO_DEBUG (1 << 1)
++
++/* LRO test controls */
++typedef int (*PDMA_LRO_DVT_FUNC) (void);
++
++#define PDMA_TEST_LRO_DISABLE (0)
++#define PDMA_TEST_LRO_FORCE_PORT (1)
++#define PDMA_TEST_LRO_AUTO_LEARN (2)
++#define PDMA_TEST_LRO_AUTO_IPV6 (3)
++#define PDMA_TEST_LRO_AUTO_MYIP (4)
++#define PDMA_TEST_LRO_FORCE_AGGREGATE (5)
++#define PDMA_TEST_NON_LRO_PORT_ID (6)
++#define PDMA_TEST_NON_LRO_STAG (7)
++#define PDMA_TEST_NON_LRO_VLAN (8)
++#define PDMA_TEST_NON_LRO_TCP_ACK (9)
++#define PDMA_TEST_NON_LRO_PRI1 (10)
++#define PDMA_TEST_NON_LRO_PRI2 (11)
++#define PDMA_TEST_LRO_DLY_INT0 (12)
++#define PDMA_TEST_LRO_DLY_INT1 (13)
++#define PDMA_TEST_LRO_DLY_INT2 (14)
++#define PDMA_TEST_LRO_DLY_INT3 (15)
++
++void skb_dump(struct sk_buff *sk);
++
++int pdma_dvt_show_ctrl(int par1, int par2);
++int pdma_dvt_test_rx_ctrl(int par1, int par2);
++int pdma_dvt_test_tx_ctrl(int par1, int par2);
++int pdma_dvt_test_debug_ctrl(int par1, int par2);
++int pdma_dvt_test_lro_ctrl(int par1, int par2);
++
++unsigned int pdma_dvt_get_show_config(void);
++unsigned int pdma_dvt_get_rx_test_config(void);
++unsigned int pdma_dvt_get_tx_test_config(void);
++unsigned int pdma_dvt_get_debug_test_config(void);
++unsigned int pdma_dvt_get_lro_test_config(void);
++void pdma_dvt_reset_config(void);
++
++void raeth_pdma_rx_desc_dvt(END_DEVICE *ei_local, int rx_dma_owner_idx0);
++void raeth_pdma_tx_vlan_dvt(END_DEVICE *ei_local,
++ unsigned long tx_cpu_owner_idx0);
++void raeth_pdma_tx_desc_dvt(END_DEVICE *ei_local,
++ unsigned long tx_cpu_owner_idx0);
++
++void raeth_pdma_lro_dvt(int rx_ring_no, END_DEVICE *ei_local,
++ int rx_dma_owner_idx0);
++void raeth_pdma_lro_dly_int_dvt(void);
++void pdma_dvt_set_dma_mode(void);
++
+diff --git a/drivers/net/ethernet/raeth/ethtool_readme.txt b/drivers/net/ethernet/raeth/ethtool_readme.txt
+new file mode 100644
+index 0000000..10e918b
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ethtool_readme.txt
+@@ -0,0 +1,44 @@
++
++Ethtool readme for selecting different PHY address.
++
++Before doing any ethtool command you should make sure the current PHY
++address is expected. The default PHY address is 1(port 1).
++
++You can change current PHY address to X(0~4) by doing follow command:
++# echo X > /proc/rt2880/gmac
++
++Ethtool command also would show the current PHY address as following.
++
++# ethtool eth2
++Settings for eth2:
++ Supported ports: [ TP MII ]
++ Supported link modes: 10baseT/Half 10baseT/Full
++ 100baseT/Half 100baseT/Full
++ Supports auto-negotiation: Yes
++ Advertised link modes: 10baseT/Half 10baseT/Full
++ 100baseT/Half 100baseT/Full
++ Advertised auto-negotiation: No
++ Speed: 10Mb/s
++ Duplex: Full
++ Port: MII
++ PHYAD: 1
++ Transceiver: internal
++ Auto-negotiation: off
++ Current message level: 0x00000000 (0)
++ Link detected: no
++
++
++The "PHYAD" field shows the current PHY address.
++
++
++
++Usage example
++1) show port1 info
++# echo 1 > /proc/rt2880/gmac # change phy address to 1
++# ethtool eth2
++
++2) show port0 info
++# echo 0 > /proc/rt2880/gmac # change phy address to 0
++# ethtool eth2
++
++
+diff --git a/drivers/net/ethernet/raeth/mcast.c b/drivers/net/ethernet/raeth/mcast.c
+new file mode 100644
+index 0000000..d796b03
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/mcast.c
+@@ -0,0 +1,187 @@
++#include <linux/config.h>
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/netdevice.h>
++#include <linux/if_vlan.h>
++
++
++#define MAX_MCAST_ENTRY 16
++#define AGEING_TIME 5 //Unit: Sec
++#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2], \
++ ((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]
++
++//#define MCAST_DEBUG
++#ifdef MCAST_DEBUG
++#define MCAST_PRINT(fmt, args...) printk(KERN_INFO fmt, ## args)
++#else
++#define MCAST_PRINT(fmt, args...) { }
++#endif
++
++typedef struct {
++ uint8_t src_mac[6];
++ uint8_t dst_mac[6];
++ uint16_t vlan_id;
++ uint32_t valid;
++ uint32_t use_count;
++ unsigned long ageout;
++} mcast_entry;
++
++mcast_entry mcast_tbl[MAX_MCAST_ENTRY];
++atomic_t mcast_entry_num=ATOMIC_INIT(0);
++DECLARE_MUTEX(mtbl_lock);
++
++uint32_t inline is_multicast_pkt(uint8_t *mac)
++{
++ if(mac[0]==0x01 && mac[1]==0x00 && mac[2]==0x5E) {
++ return 1;
++ }else{
++ return 0;
++ }
++}
++
++int32_t inline mcast_entry_get(uint16_t vlan_id, uint8_t *src_mac, uint8_t *dst_mac)
++{
++ int i=0;
++
++ for(i=0;i<MAX_MCAST_ENTRY;i++) {
++ if( (mcast_tbl[i].vlan_id == vlan_id) &&
++ memcmp(mcast_tbl[i].src_mac,src_mac, 6)==0 &&
++ memcmp(mcast_tbl[i].dst_mac, dst_mac, 6)==0 &&
++ mcast_tbl[i].valid == 1) {
++ return i;
++ }
++ }
++ return -1;
++}
++
++int inline __add_mcast_entry(uint16_t vlan_id, uint8_t *src_mac, uint8_t *dst_mac)
++{
++ int i=0;
++
++ // use empty or ageout entry
++ for(i=0;i<MAX_MCAST_ENTRY;i++) {
++ if( mcast_tbl[i].valid==0 ||
++ time_after(jiffies, mcast_tbl[i].ageout)) {
++
++ if(mcast_tbl[i].valid==0) {
++ atomic_inc(&mcast_entry_num);
++ }
++ mcast_tbl[i].vlan_id = vlan_id;
++ memcpy(mcast_tbl[i].src_mac, src_mac, 6);
++ memcpy(mcast_tbl[i].dst_mac, dst_mac, 6);
++ mcast_tbl[i].valid=1;
++ mcast_tbl[i].use_count=1;
++ mcast_tbl[i].ageout=jiffies + AGEING_TIME * HZ;
++
++ return 1;
++ }
++ }
++
++ MCAST_PRINT("RAETH: Multicast Table is FULL!!\n");
++ return 0;
++}
++
++int inline mcast_entry_ins(uint16_t vlan_id, uint8_t *src_mac, uint8_t *dst_mac)
++{
++ int entry_num=0, ret=0;
++
++ down(&mtbl_lock);
++ if((entry_num = mcast_entry_get(vlan_id, src_mac, dst_mac)) >=0) {
++ mcast_tbl[entry_num].use_count++;
++ mcast_tbl[entry_num].ageout=jiffies + AGEING_TIME * HZ;
++ MCAST_PRINT("%s: Update %0X:%0X:%0X:%0X:%0X:%0X's use_count=%d\n" \
++ ,__FUNCTION__, MAC_ARG(dst_mac), mcast_tbl[entry_num].use_count);
++ ret = 1;
++ }else { //if entry not found, create new entry.
++ MCAST_PRINT("%s: Create new entry %0X:%0X:%0X:%0X:%0X:%0X\n", \
++ __FUNCTION__, MAC_ARG(dst_mac));
++ ret = __add_mcast_entry(vlan_id, src_mac,dst_mac);
++ }
++
++ up(&mtbl_lock);
++ return ret;
++
++}
++
++
++/*
++ * Return:
++ * 0: entry found
++ * 1: entry not found
++ */
++int inline mcast_entry_del(uint16_t vlan_id, uint8_t *src_mac, uint8_t *dst_mac)
++{
++ int entry_num;
++
++ down(&mtbl_lock);
++ if((entry_num = mcast_entry_get(vlan_id, src_mac, dst_mac)) >=0) {
++ if((--mcast_tbl[entry_num].use_count)==0) {
++ MCAST_PRINT("%s: %0X:%0X:%0X:%0X:%0X:%0X (entry_num=%d)\n", \
++ __FUNCTION__, MAC_ARG(dst_mac), entry_num);
++ mcast_tbl[entry_num].valid=0;
++ atomic_dec(&mcast_entry_num);
++ }
++ up(&mtbl_lock);
++ return 0;
++ }else {
++ /* this multicast packet was not sent by meself, just ignore it */
++ up(&mtbl_lock);
++ return 1;
++ }
++}
++
++/*
++ * Return
++ * 0: drop packet
++ * 1: continue
++ */
++int32_t mcast_rx(struct sk_buff * skb)
++{
++ struct vlan_ethhdr *eth = (struct vlan_ethhdr *)(skb->data-ETH_HLEN);
++
++ /* if we do not send multicast packet before,
++ * we don't need to check re-inject multicast packet.
++ */
++ if (atomic_read(&mcast_entry_num)==0) {
++ return 1;
++ }
++
++
++ if(is_multicast_pkt(eth->h_dest)) {
++ MCAST_PRINT("%s: %0X:%0X:%0X:%0X:%0X:%0X\n", __FUNCTION__, \
++ MAC_ARG(eth->h_dest));
++
++ if(ntohs(eth->h_vlan_proto)==0x8100) {
++ return mcast_entry_del(eth->h_vlan_TCI, eth->h_source, eth->h_dest);
++ } else {
++ return mcast_entry_del(0, eth->h_source, eth->h_dest);
++ }
++ }
++
++ return 1;
++}
++
++
++int32_t mcast_tx(struct sk_buff *skb)
++{
++ struct vlan_ethhdr *eth = (struct vlan_ethhdr *)(skb->data);
++
++
++ if(is_multicast_pkt(eth->h_dest)) {
++ MCAST_PRINT("%s: %0X:%0X:%0X:%0X:%0X:%0X\n", __FUNCTION__,\
++ MAC_ARG(eth->h_dest));
++
++ if(ntohs(eth->h_vlan_proto)==0x8100) {
++ mcast_entry_ins(eth->h_vlan_TCI, eth->h_source, eth->h_dest);
++ } else {
++ mcast_entry_ins(0, eth->h_source, eth->h_dest);
++ }
++ }
++
++ return 1;
++}
++
+diff --git a/drivers/net/ethernet/raeth/mii_mgr.c b/drivers/net/ethernet/raeth/mii_mgr.c
+new file mode 100644
+index 0000000..77a47f1
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/mii_mgr.c
+@@ -0,0 +1,603 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/netdevice.h>
++
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
++#include <asm/rt2880/rt_mmap.h>
++#endif
++
++#include "ra2882ethreg.h"
++#include "raether.h"
++
++
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++#define PHY_CONTROL_0 0xC0
++#define PHY_CONTROL_1 0xC4
++#define MDIO_PHY_CONTROL_0 (RALINK_ETH_SW_BASE + PHY_CONTROL_0)
++#define MDIO_PHY_CONTROL_1 (RALINK_ETH_SW_BASE + PHY_CONTROL_1)
++
++#define GPIO_MDIO_BIT (1<<7)
++#define GPIO_PURPOSE_SELECT 0x60
++#define GPIO_PRUPOSE (RALINK_SYSCTL_BASE + GPIO_PURPOSE_SELECT)
++
++#elif defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A)
++
++#define PHY_CONTROL_0 0x7004
++#define MDIO_PHY_CONTROL_0 (RALINK_ETH_SW_BASE + PHY_CONTROL_0)
++#define enable_mdio(x)
++
++#elif defined (CONFIG_RALINK_MT7620)
++
++#define PHY_CONTROL_0 0x7004
++#define MDIO_PHY_CONTROL_0 (RALINK_ETH_SW_BASE + PHY_CONTROL_0)
++#define enable_mdio(x)
++
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++
++#define PHY_CONTROL_0 0x0004
++#define MDIO_PHY_CONTROL_0 (RALINK_ETH_SW_BASE + PHY_CONTROL_0)
++#define enable_mdio(x)
++
++#else
++#define PHY_CONTROL_0 0x00
++#define PHY_CONTROL_1 0x04
++#define MDIO_PHY_CONTROL_0 (RALINK_FRAME_ENGINE_BASE + PHY_CONTROL_0)
++#define MDIO_PHY_CONTROL_1 (RALINK_FRAME_ENGINE_BASE + PHY_CONTROL_1)
++#define enable_mdio(x)
++#endif
++
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++void enable_mdio(int enable)
++{
++#if !defined (CONFIG_P5_MAC_TO_PHY_MODE) && !defined(CONFIG_GE1_RGMII_AN) && !defined(CONFIG_GE2_RGMII_AN) && \
++ !defined (CONFIG_GE1_MII_AN) && !defined (CONFIG_GE2_MII_AN) && !defined (CONFIG_RALINK_MT7628)
++ u32 data = sysRegRead(GPIO_PRUPOSE);
++ if (enable)
++ data &= ~GPIO_MDIO_BIT;
++ else
++ data |= GPIO_MDIO_BIT;
++ sysRegWrite(GPIO_PRUPOSE, data);
++#endif
++}
++#endif
++
++#if defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A)
++
++u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data)
++{
++ u32 volatile status = 0;
++ u32 rc = 0;
++ unsigned long volatile t_start = jiffies;
++ u32 volatile data = 0;
++
++ /* We enable mdio gpio purpose register, and disable it when exit. */
++ enable_mdio(1);
++
++ // make sure previous read operation is complete
++ while (1) {
++ // 0 : Read/write operation complete
++ if(!( sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31)))
++ {
++ break;
++ }
++ else if (time_after(jiffies, t_start + 5*HZ)) {
++ enable_mdio(0);
++ printk("\n MDIO Read operation is ongoing !!\n");
++ return rc;
++ }
++ }
++
++ data = (0x01 << 16) | (0x02 << 18) | (phy_addr << 20) | (phy_register << 25);
++ sysRegWrite(MDIO_PHY_CONTROL_0, data);
++ data |= (1<<31);
++ sysRegWrite(MDIO_PHY_CONTROL_0, data);
++ //printk("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0);
++
++
++ // make sure read operation is complete
++ t_start = jiffies;
++ while (1) {
++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) {
++ status = sysRegRead(MDIO_PHY_CONTROL_0);
++ *read_data = (u32)(status & 0x0000FFFF);
++
++ enable_mdio(0);
++ return 1;
++ }
++ else if (time_after(jiffies, t_start+5*HZ)) {
++ enable_mdio(0);
++ printk("\n MDIO Read operation is ongoing and Time Out!!\n");
++ return 0;
++ }
++ }
++}
++
++u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data)
++{
++ unsigned long volatile t_start=jiffies;
++ u32 volatile data;
++
++ enable_mdio(1);
++
++ // make sure previous write operation is complete
++ while(1) {
++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31)))
++ {
++ break;
++ }
++ else if (time_after(jiffies, t_start + 5 * HZ)) {
++ enable_mdio(0);
++ printk("\n MDIO Write operation ongoing\n");
++ return 0;
++ }
++ }
++
++ data = (0x01 << 16)| (1<<18) | (phy_addr << 20) | (phy_register << 25) | write_data;
++ sysRegWrite(MDIO_PHY_CONTROL_0, data);
++ data |= (1<<31);
++ sysRegWrite(MDIO_PHY_CONTROL_0, data); //start operation
++ //printk("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0);
++
++ t_start = jiffies;
++
++ // make sure write operation is complete
++ while (1) {
++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) //0 : Read/write operation complete
++ {
++ enable_mdio(0);
++ return 1;
++ }
++ else if (time_after(jiffies, t_start + 5 * HZ)) {
++ enable_mdio(0);
++ printk("\n MDIO Write operation Time Out\n");
++ return 0;
++ }
++ }
++}
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_ARCH_MT7623)
++
++u32 __mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data)
++{
++ u32 volatile status = 0;
++ u32 rc = 0;
++ unsigned long volatile t_start = jiffies;
++ u32 volatile data = 0;
++
++ /* We enable mdio gpio purpose register, and disable it when exit. */
++ enable_mdio(1);
++
++ // make sure previous read operation is complete
++ while (1) {
++ // 0 : Read/write operation complete
++ if(!( sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31)))
++ {
++ break;
++ }
++ else if (time_after(jiffies, t_start + 5*HZ)) {
++ enable_mdio(0);
++ printk("\n MDIO Read operation is ongoing !!\n");
++ return rc;
++ }
++ }
++
++ data = (0x01 << 16) | (0x02 << 18) | (phy_addr << 20) | (phy_register << 25);
++ sysRegWrite(MDIO_PHY_CONTROL_0, data);
++ data |= (1<<31);
++ sysRegWrite(MDIO_PHY_CONTROL_0, data);
++ //printk("\n Set Command [0x%08X] = [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0, data);
++
++
++ // make sure read operation is complete
++ t_start = jiffies;
++ while (1) {
++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) {
++ status = sysRegRead(MDIO_PHY_CONTROL_0);
++ *read_data = (u32)(status & 0x0000FFFF);
++
++ enable_mdio(0);
++ return 1;
++ }
++ else if (time_after(jiffies, t_start+5*HZ)) {
++ enable_mdio(0);
++ printk("\n MDIO Read operation is ongoing and Time Out!!\n");
++ return 0;
++ }
++ }
++}
++
++u32 __mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data)
++{
++ unsigned long volatile t_start=jiffies;
++ u32 volatile data;
++
++ enable_mdio(1);
++
++ // make sure previous write operation is complete
++ while(1) {
++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31)))
++ {
++ break;
++ }
++ else if (time_after(jiffies, t_start + 5 * HZ)) {
++ enable_mdio(0);
++ printk("\n MDIO Write operation ongoing\n");
++ return 0;
++ }
++ }
++
++ data = (0x01 << 16)| (1<<18) | (phy_addr << 20) | (phy_register << 25) | write_data;
++ sysRegWrite(MDIO_PHY_CONTROL_0, data);
++ data |= (1<<31);
++ sysRegWrite(MDIO_PHY_CONTROL_0, data); //start operation
++ //printk("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0);
++
++ t_start = jiffies;
++
++ // make sure write operation is complete
++ while (1) {
++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) //0 : Read/write operation complete
++ {
++ enable_mdio(0);
++ return 1;
++ }
++ else if (time_after(jiffies, t_start + 5 * HZ)) {
++ enable_mdio(0);
++ printk("\n MDIO Write operation Time Out\n");
++ return 0;
++ }
++ }
++}
++
++u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data)
++{
++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600) || defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
++ u32 low_word;
++ u32 high_word;
++ u32 an_status = 0;
++
++ if(phy_addr==31)
++ {
++ an_status = (*(unsigned long *)(ESW_PHY_POLLING) & (1<<31));
++ if(an_status){
++ *(unsigned long *)(ESW_PHY_POLLING) &= ~(1<<31);//(AN polling off)
++ }
++ //phase1: write page address phase
++ if(__mii_mgr_write(phy_addr, 0x1f, ((phy_register >> 6) & 0x3FF))) {
++ //phase2: write address & read low word phase
++ if(__mii_mgr_read(phy_addr, (phy_register >> 2) & 0xF, &low_word)) {
++ //phase3: write address & read high word phase
++ if(__mii_mgr_read(phy_addr, (0x1 << 4), &high_word)) {
++ *read_data = (high_word << 16) | (low_word & 0xFFFF);
++ if(an_status){
++ *(unsigned long *)(ESW_PHY_POLLING) |= (1<<31);//(AN polling on)
++ }
++ return 1;
++ }
++ }
++ }
++ if(an_status){
++ *(unsigned long *)(ESW_PHY_POLLING) |= (1<<31);//(AN polling on)
++ }
++ } else
++#endif
++ {
++ if(__mii_mgr_read(phy_addr, phy_register, read_data)) {
++ return 1;
++ }
++ }
++
++ return 0;
++}
++
++u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data)
++{
++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600) || defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
++ u32 an_status = 0;
++
++ if(phy_addr == 31)
++ {
++ an_status = (*(unsigned long *)(ESW_PHY_POLLING) & (1<<31));
++ if(an_status){
++ *(unsigned long *)(ESW_PHY_POLLING) &= ~(1<<31);//(AN polling off)
++ }
++ //phase1: write page address phase
++ if(__mii_mgr_write(phy_addr, 0x1f, (phy_register >> 6) & 0x3FF)) {
++ //phase2: write address & read low word phase
++ if(__mii_mgr_write(phy_addr, ((phy_register >> 2) & 0xF), write_data & 0xFFFF)) {
++ //phase3: write address & read high word phase
++ if(__mii_mgr_write(phy_addr, (0x1 << 4), write_data >> 16)) {
++ if(an_status){
++ *(unsigned long *)(ESW_PHY_POLLING) |= (1<<31);//(AN polling on)
++ }
++ return 1;
++ }
++ }
++ }
++ if(an_status){
++ *(unsigned long *)(ESW_PHY_POLLING) |= (1<<31);//(AN polling on)
++ }
++ } else
++#endif
++ {
++ if(__mii_mgr_write(phy_addr, phy_register, write_data)) {
++ return 1;
++ }
++ }
++
++ return 0;
++}
++
++u32 mii_mgr_cl45_set_address(u32 port_num, u32 dev_addr, u32 reg_addr)
++{
++ u32 rc = 0;
++ unsigned long volatile t_start = jiffies;
++ u32 volatile data = 0;
++
++ enable_mdio(1);
++
++ while (1) {
++ if(!( sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31)))
++ {
++ break;
++ }
++ else if (time_after(jiffies, t_start + 5*HZ)) {
++ enable_mdio(0);
++ printk("\n MDIO Read operation is ongoing !!\n");
++ return rc;
++ }
++ }
++ data = (dev_addr << 25) | (port_num << 20) | (0x00 << 18) | (0x00 << 16) | reg_addr;
++ sysRegWrite(MDIO_PHY_CONTROL_0, data);
++ data |= (1<<31);
++ sysRegWrite(MDIO_PHY_CONTROL_0, data);
++
++ t_start = jiffies;
++ while (1) {
++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) //0 : Read/write operation complete
++ {
++ enable_mdio(0);
++ return 1;
++ }
++ else if (time_after(jiffies, t_start + 5 * HZ)) {
++ enable_mdio(0);
++ printk("\n MDIO Write operation Time Out\n");
++ return 0;
++ }
++ }
++
++}
++
++
++u32 mii_mgr_read_cl45(u32 port_num, u32 dev_addr, u32 reg_addr, u32 *read_data)
++{
++ u32 volatile status = 0;
++ u32 rc = 0;
++ unsigned long volatile t_start = jiffies;
++ u32 volatile data = 0;
++
++ // set address first
++ mii_mgr_cl45_set_address(port_num, dev_addr, reg_addr);
++ //udelay(10);
++
++ enable_mdio(1);
++
++ while (1) {
++ if(!( sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31)))
++ {
++ break;
++ }
++ else if (time_after(jiffies, t_start + 5*HZ)) {
++ enable_mdio(0);
++ printk("\n MDIO Read operation is ongoing !!\n");
++ return rc;
++ }
++ }
++ data = (dev_addr << 25) | (port_num << 20) | (0x03 << 18) | (0x00 << 16) | reg_addr;
++ sysRegWrite(MDIO_PHY_CONTROL_0, data);
++ data |= (1<<31);
++ sysRegWrite(MDIO_PHY_CONTROL_0, data);
++ t_start = jiffies;
++ while (1) {
++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) {
++ *read_data = (sysRegRead(MDIO_PHY_CONTROL_0) & 0x0000FFFF);
++ enable_mdio(0);
++ return 1;
++ }
++ else if (time_after(jiffies, t_start+5*HZ)) {
++ enable_mdio(0);
++ printk("\n Set Operation: MDIO Read operation is ongoing and Time Out!!\n");
++ return 0;
++ }
++ status = sysRegRead(MDIO_PHY_CONTROL_0);
++ }
++
++}
++
++u32 mii_mgr_write_cl45 (u32 port_num, u32 dev_addr, u32 reg_addr, u32 write_data)
++{
++ u32 rc = 0;
++ unsigned long volatile t_start = jiffies;
++ u32 volatile data = 0;
++
++ // set address first
++ mii_mgr_cl45_set_address(port_num, dev_addr, reg_addr);
++ //udelay(10);
++
++ enable_mdio(1);
++ while (1) {
++ if(!( sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31)))
++ {
++ break;
++ }
++ else if (time_after(jiffies, t_start + 5*HZ)) {
++ enable_mdio(0);
++ printk("\n MDIO Read operation is ongoing !!\n");
++ return rc;
++ }
++ }
++
++ data = (dev_addr << 25) | (port_num << 20) | (0x01 << 18) | (0x00 << 16) | write_data;
++ sysRegWrite(MDIO_PHY_CONTROL_0, data);
++ data |= (1<<31);
++ sysRegWrite(MDIO_PHY_CONTROL_0, data);
++
++ t_start = jiffies;
++
++ while (1) {
++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31)))
++ {
++ enable_mdio(0);
++ return 1;
++ }
++ else if (time_after(jiffies, t_start + 5 * HZ)) {
++ enable_mdio(0);
++ printk("\n MDIO Write operation Time Out\n");
++ return 0;
++ }
++
++ }
++}
++
++#else // not rt6855
++
++u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data)
++{
++ u32 volatile status = 0;
++ u32 rc = 0;
++ unsigned long volatile t_start = jiffies;
++#if !defined (CONFIG_RALINK_RT3052) && !defined (CONFIG_RALINK_RT3352) && !defined (CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628)
++ u32 volatile data = 0;
++#endif
++
++ /* We enable mdio gpio purpose register, and disable it when exit. */
++ enable_mdio(1);
++
++ // make sure previous read operation is complete
++ while (1) {
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++ // rd_rdy: read operation is complete
++ if(!( sysRegRead(MDIO_PHY_CONTROL_1) & (0x1 << 1)))
++#else
++ // 0 : Read/write operation complet
++ if(!( sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31)))
++#endif
++ {
++ break;
++ }
++ else if (time_after(jiffies, t_start + 5*HZ)) {
++ enable_mdio(0);
++ printk("\n MDIO Read operation is ongoing !!\n");
++ return rc;
++ }
++ }
++
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++ sysRegWrite(MDIO_PHY_CONTROL_0 , (1<<14) | (phy_register << 8) | (phy_addr));
++#else
++ data = (phy_addr << 24) | (phy_register << 16);
++ sysRegWrite(MDIO_PHY_CONTROL_0, data);
++ data |= (1<<31);
++ sysRegWrite(MDIO_PHY_CONTROL_0, data);
++#endif
++ //printk("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0);
++
++
++ // make sure read operation is complete
++ t_start = jiffies;
++ while (1) {
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++ if (sysRegRead(MDIO_PHY_CONTROL_1) & (0x1 << 1)) {
++ status = sysRegRead(MDIO_PHY_CONTROL_1);
++ *read_data = (u32)(status >>16);
++
++ enable_mdio(0);
++ return 1;
++ }
++#else
++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) {
++ status = sysRegRead(MDIO_PHY_CONTROL_0);
++ *read_data = (u32)(status & 0x0000FFFF);
++
++ enable_mdio(0);
++ return 1;
++ }
++#endif
++ else if (time_after(jiffies, t_start+5*HZ)) {
++ enable_mdio(0);
++ printk("\n MDIO Read operation is ongoing and Time Out!!\n");
++ return 0;
++ }
++ }
++}
++
++
++u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data)
++{
++ unsigned long volatile t_start=jiffies;
++ u32 volatile data;
++
++ enable_mdio(1);
++
++ // make sure previous write operation is complete
++ while(1) {
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++ if (!(sysRegRead(MDIO_PHY_CONTROL_1) & (0x1 << 0)))
++#else
++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31)))
++#endif
++ {
++ break;
++ }
++ else if (time_after(jiffies, t_start + 5 * HZ)) {
++ enable_mdio(0);
++ printk("\n MDIO Write operation ongoing\n");
++ return 0;
++ }
++ }
++
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++ data = ((write_data & 0xFFFF) << 16);
++ data |= (phy_register << 8) | (phy_addr);
++ data |= (1<<13);
++ sysRegWrite(MDIO_PHY_CONTROL_0, data);
++#else
++ data = (1<<30) | (phy_addr << 24) | (phy_register << 16) | write_data;
++ sysRegWrite(MDIO_PHY_CONTROL_0, data);
++ data |= (1<<31);
++ sysRegWrite(MDIO_PHY_CONTROL_0, data); //start operation
++#endif
++ //printk("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0);
++
++ t_start = jiffies;
++
++ // make sure write operation is complete
++ while (1) {
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++ if (sysRegRead(MDIO_PHY_CONTROL_1) & (0x1 << 0)) //wt_done ?= 1
++#else
++ if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) //0 : Read/write operation complete
++#endif
++ {
++ enable_mdio(0);
++ return 1;
++ }
++ else if (time_after(jiffies, t_start + 5 * HZ)) {
++ enable_mdio(0);
++ printk("\n MDIO Write operation Time Out\n");
++ return 0;
++ }
++ }
++}
++
++
++
++
++#endif
++
++
++
++
++EXPORT_SYMBOL(mii_mgr_write);
++EXPORT_SYMBOL(mii_mgr_read);
+diff --git a/drivers/net/ethernet/raeth/ra2882ethreg.h b/drivers/net/ethernet/raeth/ra2882ethreg.h
+new file mode 100644
+index 0000000..c67a042
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra2882ethreg.h
+@@ -0,0 +1,1985 @@
++#ifndef RA2882ETHREG_H
++#define RA2882ETHREG_H
++
++#include <linux/mii.h> // for struct mii_if_info in ra2882ethreg.h
++#include <linux/version.h> /* check linux version for 2.4 and 2.6 compatibility */
++#include <linux/interrupt.h> /* for "struct tasklet_struct" in linux-3.10.14 */
++#if defined (CONFIG_HW_SFQ)
++#include <linux/ip.h>
++#include <linux/ipv6.h>
++#endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++#include <asm/rt2880/rt_mmap.h>
++#endif
++#include "raether.h"
++
++#ifdef WORKQUEUE_BH
++#include <linux/workqueue.h>
++#endif // WORKQUEUE_BH //
++#ifdef CONFIG_RAETH_LRO
++#include <linux/inet_lro.h>
++#endif
++
++#define MAX_PACKET_SIZE 1514
++#define MIN_PACKET_SIZE 60
++#define MAX_TXD_LEN 0x3fff
++
++#if defined (CONFIG_ARCH_MT7623)
++#define phys_to_bus(a) (a)
++#else
++#define phys_to_bus(a) (a & 0x1FFFFFFF)
++#endif
++
++
++
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++#define BIT(x) ((1 << x))
++#endif
++/* bits range: for example BITS(16,23) = 0xFF0000
++ * ==> (BIT(m)-1) = 0x0000FFFF ~(BIT(m)-1) => 0xFFFF0000
++ * ==> (BIT(n+1)-1) = 0x00FFFFFF
++ */
++#define BITS(m,n) (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n)))
++
++#define ETHER_ADDR_LEN 6
++
++/* Phy Vender ID list */
++
++#define EV_ICPLUS_PHY_ID0 0x0243
++#define EV_ICPLUS_PHY_ID1 0x0D90
++#define EV_MARVELL_PHY_ID0 0x0141
++#define EV_MARVELL_PHY_ID1 0x0CC2
++#define EV_VTSS_PHY_ID0 0x0007
++#define EV_VTSS_PHY_ID1 0x0421
++
++/*
++ FE_INT_STATUS
++*/
++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || \
++ defined (CONFIG_ARCH_MT7623)
++
++#define RX_COHERENT BIT(31)
++#define RX_DLY_INT BIT(30)
++#define TX_COHERENT BIT(29)
++#define TX_DLY_INT BIT(28)
++#define RING3_RX_DLY_INT BIT(27)
++#define RING2_RX_DLY_INT BIT(26)
++#define RING1_RX_DLY_INT BIT(25)
++
++#define ALT_RPLC_INT3 BIT(23)
++#define ALT_RPLC_INT2 BIT(22)
++#define ALT_RPLC_INT1 BIT(21)
++
++#define RX_DONE_INT3 BIT(19)
++#define RX_DONE_INT2 BIT(18)
++#define RX_DONE_INT1 BIT(17)
++#define RX_DONE_INT0 BIT(16)
++
++#define TX_DONE_INT3 BIT(3)
++#define TX_DONE_INT2 BIT(2)
++#define TX_DONE_INT1 BIT(1)
++#define TX_DONE_INT0 BIT(0)
++
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#define RLS_COHERENT BIT(29)
++#define RLS_DLY_INT BIT(28)
++#define RLS_DONE_INT BIT(0)
++#endif
++
++#else
++//#define CNT_PPE_AF BIT(31)
++//#define CNT_GDM_AF BIT(29)
++#define PSE_P2_FC BIT(26)
++#define GDM_CRC_DROP BIT(25)
++#define PSE_BUF_DROP BIT(24)
++#define GDM_OTHER_DROP BIT(23)
++#define PSE_P1_FC BIT(22)
++#define PSE_P0_FC BIT(21)
++#define PSE_FQ_EMPTY BIT(20)
++#define GE1_STA_CHG BIT(18)
++#define TX_COHERENT BIT(17)
++#define RX_COHERENT BIT(16)
++
++#define TX_DONE_INT3 BIT(11)
++#define TX_DONE_INT2 BIT(10)
++#define TX_DONE_INT1 BIT(9)
++#define TX_DONE_INT0 BIT(8)
++#define RX_DONE_INT1 RX_DONE_INT0
++#define RX_DONE_INT0 BIT(2)
++#define TX_DLY_INT BIT(1)
++#define RX_DLY_INT BIT(0)
++#endif
++
++#define FE_INT_ALL (TX_DONE_INT3 | TX_DONE_INT2 | \
++ TX_DONE_INT1 | TX_DONE_INT0 | \
++ RX_DONE_INT0 | RX_DONE_INT1 | \
++ RX_DONE_INT2 | RX_DONE_INT3)
++
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#define QFE_INT_ALL (RLS_DONE_INT | RX_DONE_INT0 | RX_DONE_INT1)
++#define QFE_INT_DLY_INIT (RLS_DLY_INT | RX_DLY_INT)
++
++#define NUM_QDMA_PAGE 512
++#define QDMA_PAGE_SIZE 2048
++#endif
++/*
++ * SW_INT_STATUS
++ */
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++#define PORT0_QUEUE_FULL BIT(14) //port0 queue full
++#define PORT1_QUEUE_FULL BIT(15) //port1 queue full
++#define PORT2_QUEUE_FULL BIT(16) //port2 queue full
++#define PORT3_QUEUE_FULL BIT(17) //port3 queue full
++#define PORT4_QUEUE_FULL BIT(18) //port4 queue full
++#define PORT5_QUEUE_FULL BIT(19) //port5 queue full
++#define PORT6_QUEUE_FULL BIT(20) //port6 queue full
++#define SHARED_QUEUE_FULL BIT(23) //shared queue full
++#define QUEUE_EXHAUSTED BIT(24) //global queue is used up and all packets are dropped
++#define BC_STROM BIT(25) //the device is undergoing broadcast storm
++#define PORT_ST_CHG BIT(26) //Port status change
++#define UNSECURED_ALERT BIT(27) //Intruder alert
++#define ABNORMAL_ALERT BIT(28) //Abnormal
++
++#define ESW_ISR (RALINK_ETH_SW_BASE + 0x00)
++#define ESW_IMR (RALINK_ETH_SW_BASE + 0x04)
++#define ESW_INT_ALL (PORT_ST_CHG)
++
++#elif defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined (CONFIG_RALINK_MT7620)
++#define MIB_INT BIT(25)
++#define ACL_INT BIT(24)
++#define P5_LINK_CH BIT(5)
++#define P4_LINK_CH BIT(4)
++#define P3_LINK_CH BIT(3)
++#define P2_LINK_CH BIT(2)
++#define P1_LINK_CH BIT(1)
++#define P0_LINK_CH BIT(0)
++
++#define RX_GOCT_CNT BIT(4)
++#define RX_GOOD_CNT BIT(6)
++#define TX_GOCT_CNT BIT(17)
++#define TX_GOOD_CNT BIT(19)
++
++#define MSK_RX_GOCT_CNT BIT(4)
++#define MSK_RX_GOOD_CNT BIT(6)
++#define MSK_TX_GOCT_CNT BIT(17)
++#define MSK_TX_GOOD_CNT BIT(19)
++#define MSK_CNT_INT_ALL (MSK_RX_GOCT_CNT | MSK_RX_GOOD_CNT | MSK_TX_GOCT_CNT | MSK_TX_GOOD_CNT)
++//#define MSK_CNT_INT_ALL (MSK_RX_GOOD_CNT | MSK_TX_GOOD_CNT)
++
++
++#define ESW_IMR (RALINK_ETH_SW_BASE + 0x7000 + 0x8)
++#define ESW_ISR (RALINK_ETH_SW_BASE + 0x7000 + 0xC)
++#define ESW_INT_ALL (P0_LINK_CH | P1_LINK_CH | P2_LINK_CH | P3_LINK_CH | P4_LINK_CH | P5_LINK_CH | ACL_INT | MIB_INT)
++#define ESW_AISR (RALINK_ETH_SW_BASE + 0x8)
++#define ESW_P0_IntSn (RALINK_ETH_SW_BASE + 0x4004)
++#define ESW_P1_IntSn (RALINK_ETH_SW_BASE + 0x4104)
++#define ESW_P2_IntSn (RALINK_ETH_SW_BASE + 0x4204)
++#define ESW_P3_IntSn (RALINK_ETH_SW_BASE + 0x4304)
++#define ESW_P4_IntSn (RALINK_ETH_SW_BASE + 0x4404)
++#define ESW_P5_IntSn (RALINK_ETH_SW_BASE + 0x4504)
++#define ESW_P6_IntSn (RALINK_ETH_SW_BASE + 0x4604)
++#define ESW_P0_IntMn (RALINK_ETH_SW_BASE + 0x4008)
++#define ESW_P1_IntMn (RALINK_ETH_SW_BASE + 0x4108)
++#define ESW_P2_IntMn (RALINK_ETH_SW_BASE + 0x4208)
++#define ESW_P3_IntMn (RALINK_ETH_SW_BASE + 0x4308)
++#define ESW_P4_IntMn (RALINK_ETH_SW_BASE + 0x4408)
++#define ESW_P5_IntMn (RALINK_ETH_SW_BASE + 0x4508)
++#define ESW_P6_IntMn (RALINK_ETH_SW_BASE + 0x4608)
++
++#if defined (CONFIG_RALINK_MT7620)
++#define ESW_P7_IntSn (RALINK_ETH_SW_BASE + 0x4704)
++#define ESW_P7_IntMn (RALINK_ETH_SW_BASE + 0x4708)
++#endif
++
++
++#define ESW_PHY_POLLING (RALINK_ETH_SW_BASE + 0x7000)
++
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++
++#define ESW_PHY_POLLING (RALINK_ETH_SW_BASE + 0x0000)
++
++#define P5_LINK_CH BIT(5)
++#define P4_LINK_CH BIT(4)
++#define P3_LINK_CH BIT(3)
++#define P2_LINK_CH BIT(2)
++#define P1_LINK_CH BIT(1)
++#define P0_LINK_CH BIT(0)
++
++
++#endif // CONFIG_RALINK_RT3052 || CONFIG_RALINK_RT3352 || CONFIG_RALINK_RT5350 || defined (CONFIG_RALINK_MT7628)//
++
++#define RX_BUF_ALLOC_SIZE 2000
++#define FASTPATH_HEADROOM 64
++
++#define ETHER_BUFFER_ALIGN 32 ///// Align on a cache line
++
++#define ETHER_ALIGNED_RX_SKB_ADDR(addr) \
++ ((((unsigned long)(addr) + ETHER_BUFFER_ALIGN - 1) & \
++ ~(ETHER_BUFFER_ALIGN - 1)) - (unsigned long)(addr))
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++typedef struct _PSEUDO_ADAPTER {
++ struct net_device *RaethDev;
++ struct net_device *PseudoDev;
++ struct net_device_stats stat;
++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
++ struct mii_if_info mii_info;
++#endif
++
++} PSEUDO_ADAPTER, PPSEUDO_ADAPTER;
++
++#define MAX_PSEUDO_ENTRY 1
++#endif
++
++
++
++/* Register Categories Definition */
++#define RAFRAMEENGINE_OFFSET 0x0000
++#define RAGDMA_OFFSET 0x0020
++#define RAPSE_OFFSET 0x0040
++#define RAGDMA2_OFFSET 0x0060
++#define RACDMA_OFFSET 0x0080
++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || \
++ defined (CONFIG_ARCH_MT7623)
++
++#define RAPDMA_OFFSET 0x0800
++#define SDM_OFFSET 0x0C00
++#else
++#define RAPDMA_OFFSET 0x0100
++#endif
++#define RAPPE_OFFSET 0x0200
++#define RACMTABLE_OFFSET 0x0400
++#define RAPOLICYTABLE_OFFSET 0x1000
++
++
++/* Register Map Detail */
++/* RT3883 */
++#define SYSCFG1 (RALINK_SYSCTL_BASE + 0x14)
++
++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++
++/* 1. PDMA */
++#define TX_BASE_PTR0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x000)
++#define TX_MAX_CNT0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x004)
++#define TX_CTX_IDX0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x008)
++#define TX_DTX_IDX0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x00C)
++
++#define TX_BASE_PTR1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x010)
++#define TX_MAX_CNT1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x014)
++#define TX_CTX_IDX1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x018)
++#define TX_DTX_IDX1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x01C)
++
++#define TX_BASE_PTR2 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x020)
++#define TX_MAX_CNT2 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x024)
++#define TX_CTX_IDX2 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x028)
++#define TX_DTX_IDX2 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x02C)
++
++#define TX_BASE_PTR3 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x030)
++#define TX_MAX_CNT3 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x034)
++#define TX_CTX_IDX3 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x038)
++#define TX_DTX_IDX3 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x03C)
++
++#define RX_BASE_PTR0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x100)
++#define RX_MAX_CNT0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x104)
++#define RX_CALC_IDX0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x108)
++#define RX_DRX_IDX0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x10C)
++
++#define RX_BASE_PTR1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x110)
++#define RX_MAX_CNT1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x114)
++#define RX_CALC_IDX1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x118)
++#define RX_DRX_IDX1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x11C)
++
++#define PDMA_INFO (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x200)
++#define PDMA_GLO_CFG (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x204)
++#define PDMA_RST_IDX (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x208)
++#define PDMA_RST_CFG (PDMA_RST_IDX)
++#define DLY_INT_CFG (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x20C)
++#define FREEQ_THRES (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x210)
++#define INT_STATUS (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x220)
++#define FE_INT_STATUS (INT_STATUS)
++#define INT_MASK (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x228)
++#define FE_INT_ENABLE (INT_MASK)
++#define PDMA_WRR (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x280)
++#define PDMA_SCH_CFG (PDMA_WRR)
++
++#define SDM_CON (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x00) //Switch DMA configuration
++#define SDM_RRING (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x04) //Switch DMA Rx Ring
++#define SDM_TRING (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x08) //Switch DMA Tx Ring
++#define SDM_MAC_ADRL (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x0C) //Switch MAC address LSB
++#define SDM_MAC_ADRH (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x10) //Switch MAC Address MSB
++#define SDM_TPCNT (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x100) //Switch DMA Tx packet count
++#define SDM_TBCNT (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x104) //Switch DMA Tx byte count
++#define SDM_RPCNT (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x108) //Switch DMA rx packet count
++#define SDM_RBCNT (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x10C) //Switch DMA rx byte count
++#define SDM_CS_ERR (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x110) //Switch DMA rx checksum error count
++
++#elif defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || \
++ defined (CONFIG_ARCH_MT7623)
++
++/* Old FE with New PDMA */
++#define PDMA_RELATED 0x0800
++/* 1. PDMA */
++#define TX_BASE_PTR0 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x000)
++#define TX_MAX_CNT0 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x004)
++#define TX_CTX_IDX0 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x008)
++#define TX_DTX_IDX0 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x00C)
++
++#define TX_BASE_PTR1 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x010)
++#define TX_MAX_CNT1 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x014)
++#define TX_CTX_IDX1 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x018)
++#define TX_DTX_IDX1 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x01C)
++
++#define TX_BASE_PTR2 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x020)
++#define TX_MAX_CNT2 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x024)
++#define TX_CTX_IDX2 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x028)
++#define TX_DTX_IDX2 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x02C)
++
++#define TX_BASE_PTR3 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x030)
++#define TX_MAX_CNT3 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x034)
++#define TX_CTX_IDX3 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x038)
++#define TX_DTX_IDX3 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x03C)
++
++#define RX_BASE_PTR0 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x100)
++#define RX_MAX_CNT0 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x104)
++#define RX_CALC_IDX0 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x108)
++#define RX_DRX_IDX0 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x10C)
++
++#define RX_BASE_PTR1 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x110)
++#define RX_MAX_CNT1 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x114)
++#define RX_CALC_IDX1 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x118)
++#define RX_DRX_IDX1 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x11C)
++
++#define RX_BASE_PTR2 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x120)
++#define RX_MAX_CNT2 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x124)
++#define RX_CALC_IDX2 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x128)
++#define RX_DRX_IDX12 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x12C)
++
++#define RX_BASE_PTR3 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x130)
++#define RX_MAX_CNT3 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x134)
++#define RX_CALC_IDX3 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x138)
++#define RX_DRX_IDX3 (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x13C)
++
++#define PDMA_INFO (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x200)
++#define PDMA_GLO_CFG (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x204)
++#define PDMA_RST_IDX (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x208)
++#define PDMA_RST_CFG (PDMA_RST_IDX)
++#define DLY_INT_CFG (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x20C)
++#define FREEQ_THRES (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x210)
++#define INT_STATUS (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x220)
++#define FE_INT_STATUS (INT_STATUS)
++#define INT_MASK (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x228)
++#define FE_INT_ENABLE (INT_MASK)
++#define SCH_Q01_CFG (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x280)
++#define SCH_Q23_CFG (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x284)
++
++#define FE_GLO_CFG RALINK_FRAME_ENGINE_BASE + 0x00
++#define FE_RST_GL RALINK_FRAME_ENGINE_BASE + 0x04
++#define FE_INT_STATUS2 RALINK_FRAME_ENGINE_BASE + 0x08
++#define FE_INT_ENABLE2 RALINK_FRAME_ENGINE_BASE + 0x0c
++//#define FC_DROP_STA RALINK_FRAME_ENGINE_BASE + 0x18
++#define FOE_TS_T RALINK_FRAME_ENGINE_BASE + 0x10
++
++#if defined (CONFIG_RALINK_MT7620)
++#define GDMA1_RELATED 0x0600
++#define GDMA1_FWD_CFG (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x00)
++#define GDMA1_SHPR_CFG (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x04)
++#define GDMA1_MAC_ADRL (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x08)
++#define GDMA1_MAC_ADRH (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x0C)
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#define GDMA1_RELATED 0x0500
++#define GDMA1_FWD_CFG (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x00)
++#define GDMA1_SHPR_CFG (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x04)
++#define GDMA1_MAC_ADRL (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x08)
++#define GDMA1_MAC_ADRH (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x0C)
++
++#define GDMA2_RELATED 0x1500
++#define GDMA2_FWD_CFG (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x00)
++#define GDMA2_SHPR_CFG (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x04)
++#define GDMA2_MAC_ADRL (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x08)
++#define GDMA2_MAC_ADRH (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x0C)
++#else
++#define GDMA1_RELATED 0x0020
++#define GDMA1_FWD_CFG (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x00)
++#define GDMA1_SCH_CFG (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x04)
++#define GDMA1_SHPR_CFG (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x08)
++#define GDMA1_MAC_ADRL (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x0C)
++#define GDMA1_MAC_ADRH (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x10)
++
++#define GDMA2_RELATED 0x0060
++#define GDMA2_FWD_CFG (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x00)
++#define GDMA2_SCH_CFG (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x04)
++#define GDMA2_SHPR_CFG (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x08)
++#define GDMA2_MAC_ADRL (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x0C)
++#define GDMA2_MAC_ADRH (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x10)
++#endif
++
++#if defined (CONFIG_RALINK_MT7620)
++#define PSE_RELATED 0x0500
++#define PSE_FQFC_CFG (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x00)
++#define PSE_IQ_CFG (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x04)
++#define PSE_QUE_STA (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x08)
++#else
++#define PSE_RELATED 0x0040
++#define PSE_FQ_CFG (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x00)
++#define CDMA_FC_CFG (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x04)
++#define GDMA1_FC_CFG (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x08)
++#define GDMA2_FC_CFG (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x0C)
++#define CDMA_OQ_STA (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x10)
++#define GDMA1_OQ_STA (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x14)
++#define GDMA2_OQ_STA (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x18)
++#define PSE_IQ_STA (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x1C)
++#endif
++
++
++#if defined (CONFIG_RALINK_MT7620)
++#define CDMA_RELATED 0x0400
++#define CDMA_CSG_CFG (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x00)
++#define SMACCR0 (RALINK_ETH_SW_BASE + 0x3FE4)
++#define SMACCR1 (RALINK_ETH_SW_BASE + 0x3FE8)
++#define CKGCR (RALINK_ETH_SW_BASE + 0x3FF0)
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#define CDMA_RELATED 0x0400
++#define CDMA_CSG_CFG (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x00) //fake definition
++#define CDMP_IG_CTRL (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x00)
++#define CDMP_EG_CTRL (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x04)
++#else
++#define CDMA_RELATED 0x0080
++#define CDMA_CSG_CFG (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x00)
++#define CDMA_SCH_CFG (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x04)
++#define SMACCR0 (RALINK_ETH_SW_BASE + 0x30E4)
++#define SMACCR1 (RALINK_ETH_SW_BASE + 0x30E8)
++#define CKGCR (RALINK_ETH_SW_BASE + 0x30F0)
++#endif
++
++#define PDMA_FC_CFG (RALINK_FRAME_ENGINE_BASE+0x100)
++
++
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++/*kurtis: add QDMA define*/
++
++#define CLK_CFG_0 (RALINK_SYSCTL_BASE + 0x2C)
++#define PAD_RGMII2_MDIO_CFG (RALINK_SYSCTL_BASE + 0x58)
++
++#define QDMA_RELATED 0x1800
++#define QTX_CFG_0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x000)
++#define QTX_SCH_0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x004)
++#define QTX_HEAD_0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x008)
++#define QTX_TAIL_0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x00C)
++#define QTX_CFG_1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x010)
++#define QTX_SCH_1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x014)
++#define QTX_HEAD_1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x018)
++#define QTX_TAIL_1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x01C)
++#define QTX_CFG_2 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x020)
++#define QTX_SCH_2 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x024)
++#define QTX_HEAD_2 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x028)
++#define QTX_TAIL_2 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x02C)
++#define QTX_CFG_3 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x030)
++#define QTX_SCH_3 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x034)
++#define QTX_HEAD_3 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x038)
++#define QTX_TAIL_3 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x03C)
++#define QTX_CFG_4 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x040)
++#define QTX_SCH_4 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x044)
++#define QTX_HEAD_4 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x048)
++#define QTX_TAIL_4 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x04C)
++#define QTX_CFG_5 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x050)
++#define QTX_SCH_5 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x054)
++#define QTX_HEAD_5 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x058)
++#define QTX_TAIL_5 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x05C)
++#define QTX_CFG_6 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x060)
++#define QTX_SCH_6 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x064)
++#define QTX_HEAD_6 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x068)
++#define QTX_TAIL_6 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x06C)
++#define QTX_CFG_7 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x070)
++#define QTX_SCH_7 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x074)
++#define QTX_HEAD_7 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x078)
++#define QTX_TAIL_7 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x07C)
++#define QTX_CFG_8 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x080)
++#define QTX_SCH_8 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x084)
++#define QTX_HEAD_8 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x088)
++#define QTX_TAIL_8 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x08C)
++#define QTX_CFG_9 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x090)
++#define QTX_SCH_9 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x094)
++#define QTX_HEAD_9 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x098)
++#define QTX_TAIL_9 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x09C)
++#define QTX_CFG_10 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0A0)
++#define QTX_SCH_10 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0A4)
++#define QTX_HEAD_10 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0A8)
++#define QTX_TAIL_10 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0AC)
++#define QTX_CFG_11 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0B0)
++#define QTX_SCH_11 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0B4)
++#define QTX_HEAD_11 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0B8)
++#define QTX_TAIL_11 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0BC)
++#define QTX_CFG_12 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0C0)
++#define QTX_SCH_12 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0C4)
++#define QTX_HEAD_12 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0C8)
++#define QTX_TAIL_12 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0CC)
++#define QTX_CFG_13 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0D0)
++#define QTX_SCH_13 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0D4)
++#define QTX_HEAD_13 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0D8)
++#define QTX_TAIL_13 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0DC)
++#define QTX_CFG_14 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0E0)
++#define QTX_SCH_14 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0E4)
++#define QTX_HEAD_14 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0E8)
++#define QTX_TAIL_14 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0EC)
++#define QTX_CFG_15 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0F0)
++#define QTX_SCH_15 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0F4)
++#define QTX_HEAD_15 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0F8)
++#define QTX_TAIL_15 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0FC)
++#define QRX_BASE_PTR_0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x100)
++#define QRX_MAX_CNT_0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x104)
++#define QRX_CRX_IDX_0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x108)
++#define QRX_DRX_IDX_0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x10C)
++#define QRX_BASE_PTR_1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x110)
++#define QRX_MAX_CNT_1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x114)
++#define QRX_CRX_IDX_1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x118)
++#define QRX_DRX_IDX_1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x11C)
++#if defined (CONFIG_ARCH_MT7623)
++#define VQTX_TB_BASE_0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x180)
++#define VQTX_TB_BASE_1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x184)
++#define VQTX_TB_BASE_2 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x188)
++#define VQTX_TB_BASE_3 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x18C)
++#endif
++#define QDMA_INFO (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x200)
++#define QDMA_GLO_CFG (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x204)
++#define QDMA_RST_IDX (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x208)
++#define QDMA_RST_CFG (QDMA_RST_IDX)
++#define QDMA_DELAY_INT (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x20C)
++#define QDMA_FC_THRES (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x210)
++#define QDMA_TX_SCH (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x214)
++#define QDMA_INT_STS (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x218)
++#define QFE_INT_STATUS (QDMA_INT_STS)
++#define QDMA_INT_MASK (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x21C)
++#define QFE_INT_ENABLE (QDMA_INT_MASK)
++#define QDMA_TRTCM (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x220)
++#define QDMA_DATA0 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x224)
++#define QDMA_DATA1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x228)
++#define QDMA_RED_THRES (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x22C)
++#define QDMA_TEST (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x230)
++#define QDMA_DMA (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x234)
++#define QDMA_BMU (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x238)
++#define QDMA_HRED1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x240)
++#define QDMA_HRED2 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x244)
++#define QDMA_SRED1 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x248)
++#define QDMA_SRED2 (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x24C)
++#define QTX_CTX_PTR (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x300)
++#define QTX_DTX_PTR (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x304)
++#define QTX_FWD_CNT (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x308)
++#define QTX_CRX_PTR (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x310)
++#define QTX_DRX_PTR (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x314)
++#define QTX_RLS_CNT (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x318)
++#define QDMA_FQ_HEAD (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x320)
++#define QDMA_FQ_TAIL (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x324)
++#define QDMA_FQ_CNT (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x328)
++#define QDMA_FQ_BLEN (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x32C)
++#define QTX_Q0MIN_BK (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x350)
++#define QTX_Q1MIN_BK (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x354)
++#define QTX_Q2MIN_BK (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x358)
++#define QTX_Q3MIN_BK (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x35C)
++#define QTX_Q0MAX_BK (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x360)
++#define QTX_Q1MAX_BK (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x364)
++#define QTX_Q2MAX_BK (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x368)
++#define QTX_Q3MAX_BK (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x36C)
++
++
++#endif/*MT7621 QDMA*/
++
++#else
++
++/* 1. Frame Engine Global Registers */
++#define MDIO_ACCESS (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x00)
++#define MDIO_CFG (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x04)
++#define FE_GLO_CFG (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x08)
++#define FE_RST_GL (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x0C)
++#define FE_INT_STATUS (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x10)
++#define FE_INT_ENABLE (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x14)
++#define MDIO_CFG2 (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x18) //Original:FC_DROP_STA
++#define FOC_TS_T (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x1C)
++
++
++/* 2. GDMA Registers */
++#define GDMA1_FWD_CFG (RALINK_FRAME_ENGINE_BASE+RAGDMA_OFFSET+0x00)
++#define GDMA1_SCH_CFG (RALINK_FRAME_ENGINE_BASE+RAGDMA_OFFSET+0x04)
++#define GDMA1_SHPR_CFG (RALINK_FRAME_ENGINE_BASE+RAGDMA_OFFSET+0x08)
++#define GDMA1_MAC_ADRL (RALINK_FRAME_ENGINE_BASE+RAGDMA_OFFSET+0x0C)
++#define GDMA1_MAC_ADRH (RALINK_FRAME_ENGINE_BASE+RAGDMA_OFFSET+0x10)
++
++#define GDMA2_FWD_CFG (RALINK_FRAME_ENGINE_BASE+RAGDMA2_OFFSET+0x00)
++#define GDMA2_SCH_CFG (RALINK_FRAME_ENGINE_BASE+RAGDMA2_OFFSET+0x04)
++#define GDMA2_SHPR_CFG (RALINK_FRAME_ENGINE_BASE+RAGDMA2_OFFSET+0x08)
++#define GDMA2_MAC_ADRL (RALINK_FRAME_ENGINE_BASE+RAGDMA2_OFFSET+0x0C)
++#define GDMA2_MAC_ADRH (RALINK_FRAME_ENGINE_BASE+RAGDMA2_OFFSET+0x10)
++
++/* 3. PSE */
++#define PSE_FQ_CFG (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x00)
++#define CDMA_FC_CFG (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x04)
++#define GDMA1_FC_CFG (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x08)
++#define GDMA2_FC_CFG (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x0C)
++#define PDMA_FC_CFG (RALINK_FRAME_ENGINE_BASE+0x1f0)
++
++/* 4. CDMA */
++#define CDMA_CSG_CFG (RALINK_FRAME_ENGINE_BASE+RACDMA_OFFSET+0x00)
++#define CDMA_SCH_CFG (RALINK_FRAME_ENGINE_BASE+RACDMA_OFFSET+0x04)
++/* skip ppoe sid and vlan id definition */
++
++
++/* 5. PDMA */
++#define PDMA_GLO_CFG (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x00)
++#define PDMA_RST_CFG (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x04)
++#define PDMA_SCH_CFG (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x08)
++
++#define DLY_INT_CFG (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x0C)
++
++#define TX_BASE_PTR0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x10)
++#define TX_MAX_CNT0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x14)
++#define TX_CTX_IDX0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x18)
++#define TX_DTX_IDX0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x1C)
++
++#define TX_BASE_PTR1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x20)
++#define TX_MAX_CNT1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x24)
++#define TX_CTX_IDX1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x28)
++#define TX_DTX_IDX1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x2C)
++
++#define TX_BASE_PTR2 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x40)
++#define TX_MAX_CNT2 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x44)
++#define TX_CTX_IDX2 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x48)
++#define TX_DTX_IDX2 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x4C)
++
++#define TX_BASE_PTR3 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x50)
++#define TX_MAX_CNT3 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x54)
++#define TX_CTX_IDX3 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x58)
++#define TX_DTX_IDX3 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x5C)
++
++#define RX_BASE_PTR0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x30)
++#define RX_MAX_CNT0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x34)
++#define RX_CALC_IDX0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x38)
++#define RX_DRX_IDX0 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x3C)
++
++#define RX_BASE_PTR1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x40)
++#define RX_MAX_CNT1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x44)
++#define RX_CALC_IDX1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x48)
++#define RX_DRX_IDX1 (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x4C)
++
++#endif
++
++#define DELAY_INT_INIT 0x84048404
++#define FE_INT_DLY_INIT (TX_DLY_INT | RX_DLY_INT)
++
++
++#if !defined (CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628)
++
++/* 6. Counter and Meter Table */
++#define PPE_AC_BCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x000) /* PPE Accounting Group 0 Byte Cnt */
++#define PPE_AC_PCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x004) /* PPE Accounting Group 0 Packet Cnt */
++/* 0 ~ 63 */
++
++#define PPE_MTR_CNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x200) /* 0 ~ 63 */
++/* skip... */
++#define PPE_MTR_CNT63 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x2FC)
++
++#define GDMA_TX_GBCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x300) /* Transmit good byte cnt for GEport */
++#define GDMA_TX_GPCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x304) /* Transmit good pkt cnt for GEport */
++#define GDMA_TX_SKIPCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x308) /* Transmit skip cnt for GEport */
++#define GDMA_TX_COLCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x30C) /* Transmit collision cnt for GEport */
++
++/* update these address mapping to fit data sheet v0.26, by bobtseng, 2007.6.14 */
++#define GDMA_RX_GBCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x320)
++#define GDMA_RX_GPCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x324)
++#define GDMA_RX_OERCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x328)
++#define GDMA_RX_FERCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x32C)
++#define GDMA_RX_SERCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x330)
++#define GDMA_RX_LERCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x334)
++#define GDMA_RX_CERCNT0 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x338)
++#define GDMA_RX_FCCNT1 (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x33C)
++
++#endif
++
++/* LRO global control */
++/* Bits [15:0]:LRO_ALT_RFSH_TIMER, Bits [20:16]:LRO_ALT_TICK_TIMER */
++#define LRO_ALT_REFRESH_TIMER (RALINK_FRAME_ENGINE_BASE+0x001C)
++
++/* LRO auto-learn table info */
++#define PDMA_FE_ALT_CF8 (RALINK_FRAME_ENGINE_BASE+0x0300)
++#define PDMA_FE_ALT_SGL_CFC (RALINK_FRAME_ENGINE_BASE+0x0304)
++#define PDMA_FE_ALT_SEQ_CFC (RALINK_FRAME_ENGINE_BASE+0x0308)
++
++/* LRO controls */
++#define ADMA_LRO_CTRL_OFFSET 0x0980
++/*
++ * Bit [0]:LRO_EN, Bit [1]:LRO_IPv6_EN, Bit [2]:MULTIPLE_NON_LRO_RX_RING_EN, Bit [3]:MULTIPLE_RXD_PREFETCH_EN,
++ * Bit [4]:RXD_PREFETCH_EN, Bit [5]:LRO_DLY_INT_EN, Bit [6]:LRO_CRSN_BNW, Bit [7]:L3_CKS_UPD_EN,
++ * Bit [20]:first_ineligible_pkt_redirect_en, Bit [21]:cr_lro_alt_score_mode, Bit [22]:cr_lro_alt_rplc_mode,
++ * Bit [23]:cr_lro_l4_ctrl_psh_en, Bits [28:26]:LRO_RING_RELINGUISH_REQ, Bits [31:29]:LRO_RING_RELINGUISH_DONE
++ */
++#define ADMA_LRO_CTRL_DW0 (RALINK_FRAME_ENGINE_BASE+ADMA_LRO_CTRL_OFFSET+0x00)
++/* Bits [31:0]:LRO_CPU_REASON */
++#define ADMA_LRO_CTRL_DW1 (RALINK_FRAME_ENGINE_BASE+ADMA_LRO_CTRL_OFFSET+0x04)
++/* Bits [31:0]:AUTO_LEARN_LRO_ELIGIBLE_THRESHOLD */
++#define ADMA_LRO_CTRL_DW2 (RALINK_FRAME_ENGINE_BASE+ADMA_LRO_CTRL_OFFSET+0x08)
++/*
++ * Bits [7:0]:LRO_MAX_AGGREGATED_CNT, Bits [11:8]:LRO_VLAN_EN, Bits [13:12]:LRO_VLAN_VID_CMP_DEPTH,
++ * Bit [14]:ADMA_FW_RSTN_REQ, Bit [15]:ADMA_MODE, Bits [31:16]:LRO_MIN_RXD_SDL0
++ */
++#define ADMA_LRO_CTRL_DW3 (RALINK_FRAME_ENGINE_BASE+ADMA_LRO_CTRL_OFFSET+0x0C)
++
++/* LRO RX delay interrupt configurations */
++#define LRO_RX1_DLY_INT (RALINK_FRAME_ENGINE_BASE+0x0a70)
++#define LRO_RX2_DLY_INT (RALINK_FRAME_ENGINE_BASE+0x0a74)
++#define LRO_RX3_DLY_INT (RALINK_FRAME_ENGINE_BASE+0x0a78)
++
++/* LRO auto-learn configurations */
++#define PDMA_LRO_ATL_OVERFLOW_ADJ_OFFSET 0x0990
++#define PDMA_LRO_ATL_OVERFLOW_ADJ (RALINK_FRAME_ENGINE_BASE+PDMA_LRO_ATL_OVERFLOW_ADJ_OFFSET)
++#define LRO_ALT_SCORE_DELTA (RALINK_FRAME_ENGINE_BASE+0x0a4c)
++
++/* LRO agg timer configurations */
++#define LRO_MAX_AGG_TIME (RALINK_FRAME_ENGINE_BASE+0x0a5c)
++
++/* LRO configurations of RX ring #0 */
++#define LRO_RXRING0_OFFSET 0x0b00
++#define LRO_RX_RING0_DIP_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x04)
++#define LRO_RX_RING0_DIP_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x08)
++#define LRO_RX_RING0_DIP_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x0C)
++#define LRO_RX_RING0_DIP_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x10)
++#define LRO_RX_RING0_CTRL_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x28)
++/* Bit [8]:RING0_VLD, Bit [9]:RING0_MYIP_VLD */
++#define LRO_RX_RING0_CTRL_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x2C)
++#define LRO_RX_RING0_CTRL_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x30)
++/* LRO configurations of RX ring #1 */
++#define LRO_RXRING1_OFFSET 0x0b40
++#define LRO_RX_RING1_STP_DTP_DW (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x00)
++#define LRO_RX_RING1_DIP_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x04)
++#define LRO_RX_RING1_DIP_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x08)
++#define LRO_RX_RING1_DIP_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x0C)
++#define LRO_RX_RING1_DIP_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x10)
++#define LRO_RX_RING1_SIP_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x14)
++#define LRO_RX_RING1_SIP_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x18)
++#define LRO_RX_RING1_SIP_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x1C)
++#define LRO_RX_RING1_SIP_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x20)
++#define LRO_RX_RING1_CTRL_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x24)
++#define LRO_RX_RING1_CTRL_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x28)
++#define LRO_RX_RING1_CTRL_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x2C)
++#define LRO_RX_RING1_CTRL_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x30)
++#define LRO_RXRING2_OFFSET 0x0b80
++#define LRO_RX_RING2_STP_DTP_DW (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x00)
++#define LRO_RX_RING2_DIP_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x04)
++#define LRO_RX_RING2_DIP_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x08)
++#define LRO_RX_RING2_DIP_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x0C)
++#define LRO_RX_RING2_DIP_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x10)
++#define LRO_RX_RING2_SIP_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x14)
++#define LRO_RX_RING2_SIP_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x18)
++#define LRO_RX_RING2_SIP_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x1C)
++#define LRO_RX_RING2_SIP_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x20)
++#define LRO_RX_RING2_CTRL_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x24)
++#define LRO_RX_RING2_CTRL_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x28)
++#define LRO_RX_RING2_CTRL_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x2C)
++#define LRO_RX_RING2_CTRL_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x30)
++#define LRO_RXRING3_OFFSET 0x0bc0
++#define LRO_RX_RING3_STP_DTP_DW (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x00)
++#define LRO_RX_RING3_DIP_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x04)
++#define LRO_RX_RING3_DIP_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x08)
++#define LRO_RX_RING3_DIP_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x0C)
++#define LRO_RX_RING3_DIP_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x10)
++#define LRO_RX_RING3_SIP_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x14)
++#define LRO_RX_RING3_SIP_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x18)
++#define LRO_RX_RING3_SIP_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x1C)
++#define LRO_RX_RING3_SIP_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x20)
++#define LRO_RX_RING3_CTRL_DW0 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x24)
++#define LRO_RX_RING3_CTRL_DW1 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x28)
++#define LRO_RX_RING3_CTRL_DW2 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x2C)
++#define LRO_RX_RING3_CTRL_DW3 (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x30)
++
++/* LRO RX ring mode */
++#define PDMA_RX_NORMAL_MODE (0x0)
++#define PDMA_RX_PSE_MODE (0x1)
++#define PDMA_RX_FORCE_PORT (0x2)
++#define PDMA_RX_AUTO_LEARN (0x3)
++
++#define ADMA_RX_RING0 (0)
++#define ADMA_RX_RING1 (1)
++#define ADMA_RX_RING2 (2)
++#define ADMA_RX_RING3 (3)
++
++#define ADMA_RX_LEN0_MASK (0x3fff)
++#define ADMA_RX_LEN1_MASK (0x3)
++
++#define PDMA_LRO_EN BIT(0)
++#define PDMA_LRO_IPV6_EN BIT(1)
++#define PDMA_LRO_IPV4_CSUM_UPDATE_EN BIT(7)
++#define PDMA_LRO_IPV4_CTRL_PUSH_EN BIT(23)
++#define PDMA_LRO_RXD_PREFETCH_EN BITS(3,4)
++#define PDMA_NON_LRO_MULTI_EN BIT(2)
++#define PDMA_LRO_DLY_INT_EN BIT(5)
++#define PDMA_LRO_FUSH_REQ BITS(26,28)
++#define PDMA_LRO_RELINGUISH BITS(29,31)
++#define PDMA_LRO_FREQ_PRI_ADJ BITS(16,19)
++#define PDMA_LRO_TPUT_PRE_ADJ BITS(8,11)
++#define PDMA_LRO_TPUT_PRI_ADJ BITS(12,15)
++#define PDMA_LRO_ALT_SCORE_MODE BIT(21)
++#define PDMA_LRO_RING_AGE1 BITS(22,31)
++#define PDMA_LRO_RING_AGE2 BITS(0,5)
++#define PDMA_LRO_RING_AGG BITS(10,25)
++#define PDMA_LRO_RING_AGG_CNT1 BITS(26,31)
++#define PDMA_LRO_RING_AGG_CNT2 BITS(0,1)
++#define PDMA_LRO_ALT_TICK_TIMER BITS(16,20)
++#define PDMA_LRO_LRO_MIN_RXD_SDL0 BITS(16,31)
++
++#define PDMA_LRO_DLY_INT_EN_OFFSET (5)
++#define PDMA_LRO_TPUT_PRE_ADJ_OFFSET (8)
++#define PDMA_LRO_FREQ_PRI_ADJ_OFFSET (16)
++#define PDMA_LRO_LRO_MIN_RXD_SDL0_OFFSET (16)
++#define PDMA_LRO_TPUT_PRI_ADJ_OFFSET (12)
++#define PDMA_LRO_ALT_SCORE_MODE_OFFSET (21)
++#define PDMA_LRO_FUSH_REQ_OFFSET (26)
++#define PDMA_NON_LRO_MULTI_EN_OFFSET (2)
++#define PDMA_LRO_IPV6_EN_OFFSET (1)
++#define PDMA_LRO_RXD_PREFETCH_EN_OFFSET (3)
++#define PDMA_LRO_IPV4_CSUM_UPDATE_EN_OFFSET (7)
++#define PDMA_LRO_IPV4_CTRL_PUSH_EN_OFFSET (23)
++#define PDMA_LRO_ALT_TICK_TIMER_OFFSET (16)
++
++#define PDMA_LRO_TPUT_OVERFLOW_ADJ BITS(12,31)
++#define PDMA_LRO_CNT_OVERFLOW_ADJ BITS(0,11)
++
++#define PDMA_LRO_TPUT_OVERFLOW_ADJ_OFFSET (12)
++#define PDMA_LRO_CNT_OVERFLOW_ADJ_OFFSET (0)
++
++#define PDMA_LRO_ALT_BYTE_CNT_MODE (0)
++#define PDMA_LRO_ALT_PKT_CNT_MODE (1)
++
++/* LRO_RX_RING1_CTRL_DW1 offsets */
++#define PDMA_LRO_AGE_H_OFFSET (10)
++#define PDMA_LRO_RING_AGE1_OFFSET (22)
++#define PDMA_LRO_RING_AGG_CNT1_OFFSET (26)
++/* LRO_RX_RING1_CTRL_DW2 offsets */
++#define PDMA_RX_MODE_OFFSET (6)
++#define PDMA_RX_PORT_VALID_OFFSET (8)
++#define PDMA_RX_MYIP_VALID_OFFSET (9)
++#define PDMA_LRO_RING_AGE2_OFFSET (0)
++#define PDMA_LRO_RING_AGG_OFFSET (10)
++#define PDMA_LRO_RING_AGG_CNT2_OFFSET (0)
++/* LRO_RX_RING1_CTRL_DW3 offsets */
++#define PDMA_LRO_AGG_CNT_H_OFFSET (6)
++/* LRO_RX_RING1_STP_DTP_DW offsets */
++#define PDMA_RX_TCP_SRC_PORT_OFFSET (16)
++#define PDMA_RX_TCP_DEST_PORT_OFFSET (0)
++/* LRO_RX_RING1_CTRL_DW0 offsets */
++#define PDMA_RX_IPV4_FORCE_OFFSET (1)
++#define PDMA_RX_IPV6_FORCE_OFFSET (0)
++
++#define SET_ADMA_RX_LEN0(x) ((x)&ADMA_RX_LEN0_MASK)
++#define SET_ADMA_RX_LEN1(x) ((x)&ADMA_RX_LEN1_MASK)
++
++#define SET_PDMA_LRO_MAX_AGG_CNT(x) \
++ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW3; \
++ *addr &= ~0xff; \
++ *addr |= ((x) & 0xff); \
++ }
++#define SET_PDMA_LRO_FLUSH_REQ(x) \
++ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++ *addr &= ~PDMA_LRO_FUSH_REQ; \
++ *addr |= ((x) & 0x7)<<PDMA_LRO_FUSH_REQ_OFFSET; \
++ }
++#define SET_PDMA_LRO_IPV6_EN(x) \
++ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++ *addr &= ~PDMA_LRO_IPV6_EN; \
++ *addr |= ((x) & 0x1)<<PDMA_LRO_IPV6_EN_OFFSET; \
++ }
++#if defined(CONFIG_RAETH_HW_LRO_PREFETCH)
++#define SET_PDMA_LRO_RXD_PREFETCH_EN(x) \
++ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++ *addr &= ~PDMA_LRO_RXD_PREFETCH_EN; \
++ *addr |= ((x) & 0x3)<<PDMA_LRO_RXD_PREFETCH_EN_OFFSET; \
++ }
++#else
++#define SET_PDMA_LRO_RXD_PREFETCH_EN(x)
++#endif
++#define SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(x) \
++ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++ *addr &= ~PDMA_LRO_IPV4_CSUM_UPDATE_EN; \
++ *addr |= ((x) & 0x1)<<PDMA_LRO_IPV4_CSUM_UPDATE_EN_OFFSET; \
++ }
++#define SET_PDMA_LRO_IPV4_CTRL_PUSH_EN(x) \
++ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++ *addr &= ~PDMA_LRO_IPV4_CTRL_PUSH_EN; \
++ *addr |= ((x) & 0x1)<<PDMA_LRO_IPV4_CTRL_PUSH_EN_OFFSET; \
++ }
++#define SET_PDMA_NON_LRO_MULTI_EN(x) \
++ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++ *addr &= ~(PDMA_NON_LRO_MULTI_EN); \
++ *addr |= ((x) & 0x1)<<PDMA_NON_LRO_MULTI_EN_OFFSET; \
++ }
++#define SET_PDMA_LRO_FREQ_PRI_ADJ(x) \
++ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++ *addr &= ~PDMA_LRO_FREQ_PRI_ADJ; \
++ *addr |= ((x) & 0xf)<<PDMA_LRO_FREQ_PRI_ADJ_OFFSET; \
++ }
++#define SET_PDMA_LRO_TPUT_PRE_ADJ(x) \
++ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++ *addr &= ~PDMA_LRO_TPUT_PRE_ADJ; \
++ *addr |= ((x) & 0xf)<<PDMA_LRO_TPUT_PRE_ADJ_OFFSET; \
++ }
++#define SET_PDMA_LRO_TPUT_PRI_ADJ(x) \
++ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++ *addr &= ~PDMA_LRO_TPUT_PRI_ADJ; \
++ *addr |= ((x) & 0xf)<<PDMA_LRO_TPUT_PRI_ADJ_OFFSET; \
++ }
++#define SET_PDMA_LRO_ALT_SCORE_MODE(x) \
++ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++ *addr &= ~PDMA_LRO_ALT_SCORE_MODE; \
++ *addr |= ((x) & 0x1)<<PDMA_LRO_ALT_SCORE_MODE_OFFSET; \
++ }
++#define SET_PDMA_LRO_DLY_INT_EN(x) \
++ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++ *addr &= ~PDMA_LRO_DLY_INT_EN; \
++ *addr |= ((x) & 0x1)<<PDMA_LRO_DLY_INT_EN_OFFSET; \
++ }
++#define SET_PDMA_LRO_BW_THRESHOLD(x) \
++ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW2; \
++ *addr = (x); \
++ }
++#define SET_PDMA_LRO_MIN_RXD_SDL(x) \
++ { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW3; \
++ *addr &= ~PDMA_LRO_LRO_MIN_RXD_SDL0; \
++ *addr |= ((x) & 0xffff)<<PDMA_LRO_LRO_MIN_RXD_SDL0_OFFSET; \
++ }
++#define SET_PDMA_LRO_TPUT_OVERFLOW_ADJ(x) \
++ { volatile unsigned int *addr = (unsigned int*)PDMA_LRO_ATL_OVERFLOW_ADJ; \
++ *addr &= ~PDMA_LRO_TPUT_OVERFLOW_ADJ; \
++ *addr |= ((x) & 0xfffff)<<PDMA_LRO_TPUT_OVERFLOW_ADJ_OFFSET; \
++ }
++#define SET_PDMA_LRO_CNT_OVERFLOW_ADJ(x) \
++ { volatile unsigned int *addr = (unsigned int*)PDMA_LRO_ATL_OVERFLOW_ADJ; \
++ *addr &= ~PDMA_LRO_CNT_OVERFLOW_ADJ; \
++ *addr |= ((x) & 0xfff)<<PDMA_LRO_CNT_OVERFLOW_ADJ_OFFSET; \
++ }
++#define SET_PDMA_LRO_ALT_REFRESH_TIMER_UNIT(x) \
++ { volatile unsigned int *addr = (unsigned int*)LRO_ALT_REFRESH_TIMER; \
++ *addr &= ~PDMA_LRO_ALT_TICK_TIMER; \
++ *addr |= ((x) & 0x1f)<<PDMA_LRO_ALT_TICK_TIMER_OFFSET; \
++ }
++#define SET_PDMA_LRO_ALT_REFRESH_TIMER(x) \
++ { volatile unsigned int *addr = (unsigned int*)LRO_ALT_REFRESH_TIMER; \
++ *addr &= ~0xffff; \
++ *addr |= ((x) & 0xffff); \
++ }
++#define SET_PDMA_LRO_MAX_AGG_TIME(x) \
++ { volatile unsigned int *addr = (unsigned int*)LRO_MAX_AGG_TIME; \
++ *addr &= ~0xffff; \
++ *addr |= ((x) & 0xffff); \
++ }
++#define SET_PDMA_RXRING_MODE(x,y) \
++ { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING0_CTRL_DW2 + ((x) << 6)); \
++ *addr &= ~(0x3<<PDMA_RX_MODE_OFFSET); \
++ *addr |= (y)<<PDMA_RX_MODE_OFFSET; \
++ }
++#define SET_PDMA_RXRING_MYIP_VALID(x,y) \
++ { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING0_CTRL_DW2 + ((x) << 6)); \
++ *addr &= ~(0x1<<PDMA_RX_MYIP_VALID_OFFSET); \
++ *addr |= ((y)&0x1)<<PDMA_RX_MYIP_VALID_OFFSET; \
++ }
++#define SET_PDMA_RXRING_VALID(x,y) \
++ { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING0_CTRL_DW2 + ((x) << 6)); \
++ *addr &= ~(0x1<<PDMA_RX_PORT_VALID_OFFSET); \
++ *addr |= ((y)&0x1)<<PDMA_RX_PORT_VALID_OFFSET; \
++ }
++#define SET_PDMA_RXRING_TCP_SRC_PORT(x,y) \
++ { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING1_STP_DTP_DW + (((x)-1) << 6)); \
++ *addr &= ~(0xffff<<PDMA_RX_TCP_SRC_PORT_OFFSET); \
++ *addr |= (y)<<PDMA_RX_TCP_SRC_PORT_OFFSET; \
++ }
++#define SET_PDMA_RXRING_TCP_DEST_PORT(x,y) \
++ { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING1_STP_DTP_DW + (((x)-1) << 6)); \
++ *addr &= ~(0xffff<<PDMA_RX_TCP_DEST_PORT_OFFSET); \
++ *addr |= (y)<<PDMA_RX_TCP_DEST_PORT_OFFSET; \
++ }
++#define SET_PDMA_RXRING_IPV4_FORCE_MODE(x,y) \
++ { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING1_CTRL_DW0 + (((x)-1) << 6)); \
++ *addr &= ~(0x1<<PDMA_RX_IPV4_FORCE_OFFSET); \
++ *addr |= (y)<<PDMA_RX_IPV4_FORCE_OFFSET; \
++ }
++#define SET_PDMA_RXRING_IPV6_FORCE_MODE(x,y) \
++ { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING1_CTRL_DW0 + (((x)-1) << 6)); \
++ *addr &= ~(0x1<<PDMA_RX_IPV6_FORCE_OFFSET); \
++ *addr |= (y)<<PDMA_RX_IPV6_FORCE_OFFSET; \
++ }
++#define SET_PDMA_RXRING_AGE_TIME(x,y) \
++ { volatile unsigned int *addr1 = (unsigned int*)(LRO_RX_RING0_CTRL_DW1 + ((x) << 6)); \
++ volatile unsigned int *addr2 = (unsigned int*)(LRO_RX_RING0_CTRL_DW2 + ((x) << 6)); \
++ *addr1 &= ~PDMA_LRO_RING_AGE1; \
++ *addr2 &= ~PDMA_LRO_RING_AGE2; \
++ *addr1 |= ((y) & 0x3ff)<<PDMA_LRO_RING_AGE1_OFFSET; \
++ *addr2 |= (((y)>>PDMA_LRO_AGE_H_OFFSET) & 0x03f)<<PDMA_LRO_RING_AGE2_OFFSET; \
++ }
++#define SET_PDMA_RXRING_AGG_TIME(x,y) \
++ { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING0_CTRL_DW2 + ((x) << 6)); \
++ *addr &= ~PDMA_LRO_RING_AGG; \
++ *addr |= ((y) & 0xffff)<<PDMA_LRO_RING_AGG_OFFSET; \
++ }
++#define SET_PDMA_RXRING_MAX_AGG_CNT(x,y) \
++ { volatile unsigned int *addr1 = (unsigned int*)(LRO_RX_RING1_CTRL_DW2 + (((x)-1) << 6)); \
++ volatile unsigned int *addr2 = (unsigned int*)(LRO_RX_RING1_CTRL_DW3 + (((x)-1) << 6)); \
++ *addr1 &= ~PDMA_LRO_RING_AGG_CNT1; \
++ *addr2 &= ~PDMA_LRO_RING_AGG_CNT2; \
++ *addr1 |= ((y) & 0x3f)<<PDMA_LRO_RING_AGG_CNT1_OFFSET; \
++ *addr2 |= (((y)>>PDMA_LRO_AGG_CNT_H_OFFSET) & 0x03)<<PDMA_LRO_RING_AGG_CNT2_OFFSET; \
++ }
++
++typedef struct _PDMA_LRO_AUTO_TLB_INFO0_ PDMA_LRO_AUTO_TLB_INFO0_T;
++typedef struct _PDMA_LRO_AUTO_TLB_INFO1_ PDMA_LRO_AUTO_TLB_INFO1_T;
++typedef struct _PDMA_LRO_AUTO_TLB_INFO2_ PDMA_LRO_AUTO_TLB_INFO2_T;
++typedef struct _PDMA_LRO_AUTO_TLB_INFO3_ PDMA_LRO_AUTO_TLB_INFO3_T;
++typedef struct _PDMA_LRO_AUTO_TLB_INFO4_ PDMA_LRO_AUTO_TLB_INFO4_T;
++typedef struct _PDMA_LRO_AUTO_TLB_INFO5_ PDMA_LRO_AUTO_TLB_INFO5_T;
++typedef struct _PDMA_LRO_AUTO_TLB_INFO6_ PDMA_LRO_AUTO_TLB_INFO6_T;
++typedef struct _PDMA_LRO_AUTO_TLB_INFO7_ PDMA_LRO_AUTO_TLB_INFO7_T;
++typedef struct _PDMA_LRO_AUTO_TLB_INFO8_ PDMA_LRO_AUTO_TLB_INFO8_T;
++
++struct _PDMA_LRO_AUTO_TLB_INFO0_
++{
++ unsigned int DTP : 16;
++ unsigned int STP : 16;
++};
++struct _PDMA_LRO_AUTO_TLB_INFO1_
++{
++ unsigned int SIP0 : 32;
++};
++struct _PDMA_LRO_AUTO_TLB_INFO2_
++{
++ unsigned int SIP1 : 32;
++};
++struct _PDMA_LRO_AUTO_TLB_INFO3_
++{
++ unsigned int SIP2 : 32;
++};
++struct _PDMA_LRO_AUTO_TLB_INFO4_
++{
++ unsigned int SIP3 : 32;
++};
++struct _PDMA_LRO_AUTO_TLB_INFO5_
++{
++ unsigned int VLAN_VID0 : 32;
++};
++struct _PDMA_LRO_AUTO_TLB_INFO6_
++{
++ unsigned int VLAN_VID1 : 16;
++ unsigned int VLAN_VID_VLD : 4;
++ unsigned int CNT : 12;
++};
++struct _PDMA_LRO_AUTO_TLB_INFO7_
++{
++ unsigned int DW_LEN : 32;
++};
++struct _PDMA_LRO_AUTO_TLB_INFO8_
++{
++ unsigned int DIP_ID : 2;
++ unsigned int IPV6 : 1;
++ unsigned int IPV4 : 1;
++ unsigned int RESV : 27;
++ unsigned int VALID : 1;
++};
++struct PDMA_LRO_AUTO_TLB_INFO {
++ PDMA_LRO_AUTO_TLB_INFO0_T auto_tlb_info0;
++ PDMA_LRO_AUTO_TLB_INFO1_T auto_tlb_info1;
++ PDMA_LRO_AUTO_TLB_INFO2_T auto_tlb_info2;
++ PDMA_LRO_AUTO_TLB_INFO3_T auto_tlb_info3;
++ PDMA_LRO_AUTO_TLB_INFO4_T auto_tlb_info4;
++ PDMA_LRO_AUTO_TLB_INFO5_T auto_tlb_info5;
++ PDMA_LRO_AUTO_TLB_INFO6_T auto_tlb_info6;
++ PDMA_LRO_AUTO_TLB_INFO7_T auto_tlb_info7;
++ PDMA_LRO_AUTO_TLB_INFO8_T auto_tlb_info8;
++};
++
++#if defined (CONFIG_HW_SFQ)
++#define VQTX_TB_BASE0 (ETHDMASYS_FRAME_ENGINE_BASE + 0x1980)
++#define VQTX_TB_BASE1 (ETHDMASYS_FRAME_ENGINE_BASE + 0x1984)
++#define VQTX_TB_BASE2 (ETHDMASYS_FRAME_ENGINE_BASE + 0x1988)
++#define VQTX_TB_BASE3 (ETHDMASYS_FRAME_ENGINE_BASE + 0x198C)
++#define SFQ_OFFSET 0x1A80
++#define VQTX_GLO (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET)
++#define VQTX_INVLD_PTR (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x0C)
++#define VQTX_NUM (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x10)
++#define VQTX_SCH (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x18)
++#define VQTX_HASH_CFG (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x20)
++#define VQTX_HASH_SD (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x24)
++#define VQTX_VLD_CFG (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x30)
++#define VQTX_MIB_IF (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x3C)
++#define VQTX_MIB_PCNT (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x40)
++#define VQTX_MIB_BCNT0 (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x44)
++#define VQTX_MIB_BCNT1 (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x48)
++
++#define VQTX_MIB_EN (1<<17)
++#define VQTX_NUM_0 (4<<0)
++#define VQTX_NUM_1 (4<<4)
++#define VQTX_NUM_2 (4<<8)
++#define VQTX_NUM_3 (4<<12)
++
++/*=========================================
++ SFQ Table Format define
++=========================================*/
++typedef struct _SFQ_INFO1_ SFQ_INFO1_T;
++
++struct _SFQ_INFO1_
++{
++ unsigned int VQHPTR;
++};
++//-------------------------------------------------
++typedef struct _SFQ_INFO2_ SFQ_INFO2_T;
++
++struct _SFQ_INFO2_
++{
++ unsigned int VQTPTR;
++};
++//-------------------------------------------------
++typedef struct _SFQ_INFO3_ SFQ_INFO3_T;
++
++struct _SFQ_INFO3_
++{
++ unsigned int QUE_DEPTH:16;
++ unsigned int DEFICIT_CNT:16;
++};
++//-------------------------------------------------
++typedef struct _SFQ_INFO4_ SFQ_INFO4_T;
++
++struct _SFQ_INFO4_
++{
++ unsigned int RESV;
++};
++//-------------------------------------------------
++
++typedef struct _SFQ_INFO5_ SFQ_INFO5_T;
++
++struct _SFQ_INFO5_
++{
++ unsigned int PKT_CNT;
++};
++//-------------------------------------------------
++
++typedef struct _SFQ_INFO6_ SFQ_INFO6_T;
++
++struct _SFQ_INFO6_
++{
++ unsigned int BYTE_CNT;
++};
++//-------------------------------------------------
++
++typedef struct _SFQ_INFO7_ SFQ_INFO7_T;
++
++struct _SFQ_INFO7_
++{
++ unsigned int BYTE_CNT;
++};
++//-------------------------------------------------
++
++typedef struct _SFQ_INFO8_ SFQ_INFO8_T;
++
++struct _SFQ_INFO8_
++{
++ unsigned int RESV;
++};
++
++
++struct SFQ_table {
++ SFQ_INFO1_T sfq_info1;
++ SFQ_INFO2_T sfq_info2;
++ SFQ_INFO3_T sfq_info3;
++ SFQ_INFO4_T sfq_info4;
++ SFQ_INFO5_T sfq_info5;
++ SFQ_INFO6_T sfq_info6;
++ SFQ_INFO7_T sfq_info7;
++ SFQ_INFO8_T sfq_info8;
++
++};
++#endif
++#if defined (CONFIG_RAETH_HW_LRO) || defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++#define FE_GDM_RXID1_OFFSET (0x0130)
++#define FE_GDM_RXID1 (RALINK_FRAME_ENGINE_BASE+FE_GDM_RXID1_OFFSET)
++#define GDM_VLAN_PRI7_RXID_SEL BITS(30,31)
++#define GDM_VLAN_PRI6_RXID_SEL BITS(28,29)
++#define GDM_VLAN_PRI5_RXID_SEL BITS(26,27)
++#define GDM_VLAN_PRI4_RXID_SEL BITS(24,25)
++#define GDM_VLAN_PRI3_RXID_SEL BITS(22,23)
++#define GDM_VLAN_PRI2_RXID_SEL BITS(20,21)
++#define GDM_VLAN_PRI1_RXID_SEL BITS(18,19)
++#define GDM_VLAN_PRI0_RXID_SEL BITS(16,17)
++#define GDM_TCP_ACK_RXID_SEL BITS(4,5)
++#define GDM_TCP_ACK_WZPC BIT(3)
++#define GDM_RXID_PRI_SEL BITS(0,2)
++
++#define FE_GDM_RXID2_OFFSET (0x0134)
++#define FE_GDM_RXID2 (RALINK_FRAME_ENGINE_BASE+FE_GDM_RXID2_OFFSET)
++#define GDM_STAG7_RXID_SEL BITS(30,31)
++#define GDM_STAG6_RXID_SEL BITS(28,29)
++#define GDM_STAG5_RXID_SEL BITS(26,27)
++#define GDM_STAG4_RXID_SEL BITS(24,25)
++#define GDM_STAG3_RXID_SEL BITS(22,23)
++#define GDM_STAG2_RXID_SEL BITS(20,21)
++#define GDM_STAG1_RXID_SEL BITS(18,19)
++#define GDM_STAG0_RXID_SEL BITS(16,17)
++#define GDM_PID2_RXID_SEL BITS(2,3)
++#define GDM_PID1_RXID_SEL BITS(0,1)
++
++#define GDM_PRI_PID (0)
++#define GDM_PRI_VLAN_PID (1)
++#define GDM_PRI_ACK_PID (2)
++#define GDM_PRI_VLAN_ACK_PID (3)
++#define GDM_PRI_ACK_VLAN_PID (4)
++
++#define SET_GDM_VLAN_PRI_RXID_SEL(x,y) \
++ { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID1; \
++ *addr &= ~(0x03 << (((x) << 1)+16)); \
++ *addr |= ((y) & 0x3) << (((x) << 1)+16); \
++ }
++#define SET_GDM_TCP_ACK_RXID_SEL(x) \
++ { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID1; \
++ *addr &= ~(GDM_TCP_ACK_RXID_SEL); \
++ *addr |= ((x) & 0x3) << 4; \
++ }
++#define SET_GDM_TCP_ACK_WZPC(x) \
++ { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID1; \
++ *addr &= ~(GDM_TCP_ACK_WZPC); \
++ *addr |= ((x) & 0x1) << 3; \
++ }
++#define SET_GDM_RXID_PRI_SEL(x) \
++ { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID1; \
++ *addr &= ~(GDM_RXID_PRI_SEL); \
++ *addr |= (x) & 0x7; \
++ }
++#define GDM_STAG_RXID_SEL(x,y) \
++ { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID2; \
++ *addr &= ~(0x03 << (((x) << 1)+16)); \
++ *addr |= ((y) & 0x3) << (((x) << 1)+16); \
++ }
++#define SET_GDM_PID2_RXID_SEL(x) \
++ { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID2; \
++ *addr &= ~(GDM_PID2_RXID_SEL); \
++ *addr |= ((x) & 0x3) << 2; \
++ }
++#define SET_GDM_PID1_RXID_SEL(x) \
++ { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID2; \
++ *addr &= ~(GDM_PID1_RXID_SEL); \
++ *addr |= ((x) & 0x3); \
++ }
++#endif /* CONFIG_RAETH_MULTIPLE_RX_RING */
++/* Per Port Packet Counts in RT3052, added by bobtseng 2009.4.17. */
++#define PORT0_PKCOUNT (0xb01100e8)
++#define PORT1_PKCOUNT (0xb01100ec)
++#define PORT2_PKCOUNT (0xb01100f0)
++#define PORT3_PKCOUNT (0xb01100f4)
++#define PORT4_PKCOUNT (0xb01100f8)
++#define PORT5_PKCOUNT (0xb01100fc)
++
++#if defined (CONFIG_ARCH_MT7623)
++#include "sync_write.h"
++#define sysRegRead(phys) (*(volatile unsigned int *)((phys)))
++#define sysRegWrite(phys, val) mt65xx_reg_sync_writel((val), (phys))
++#else
++#define PHYS_TO_K1(physaddr) KSEG1ADDR(physaddr)
++#define sysRegRead(phys) (*(volatile unsigned int *)PHYS_TO_K1(phys))
++#define sysRegWrite(phys, val) ((*(volatile unsigned int *)PHYS_TO_K1(phys)) = (val))
++#endif
++
++#define u_long unsigned long
++#define u32 unsigned int
++#define u16 unsigned short
++
++
++/* ====================================== */
++#define GDM1_DISPAD BIT(18)
++#define GDM1_DISCRC BIT(17)
++
++//GDMA1 uni-cast frames destination port
++#define GDM1_ICS_EN (0x1 << 22)
++#define GDM1_TCS_EN (0x1 << 21)
++#define GDM1_UCS_EN (0x1 << 20)
++#define GDM1_JMB_EN (0x1 << 19)
++#define GDM1_STRPCRC (0x1 << 16)
++#define GDM1_UFRC_P_CPU (0 << 12)
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#define GDM1_UFRC_P_PPE (4 << 12)
++#else
++#define GDM1_UFRC_P_PPE (6 << 12)
++#endif
++
++//GDMA1 broad-cast MAC address frames
++#define GDM1_BFRC_P_CPU (0 << 8)
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#define GDM1_BFRC_P_PPE (4 << 8)
++#else
++#define GDM1_BFRC_P_PPE (6 << 8)
++#endif
++
++//GDMA1 multi-cast MAC address frames
++#define GDM1_MFRC_P_CPU (0 << 4)
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#define GDM1_MFRC_P_PPE (4 << 4)
++#else
++#define GDM1_MFRC_P_PPE (6 << 4)
++#endif
++
++//GDMA1 other MAC address frames destination port
++#define GDM1_OFRC_P_CPU (0 << 0)
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#define GDM1_OFRC_P_PPE (4 << 0)
++#else
++#define GDM1_OFRC_P_PPE (6 << 0)
++#endif
++
++#if defined (CONFIG_RALINK_RT6856) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++/* checksum generator registers are removed */
++#define ICS_GEN_EN (0 << 2)
++#define UCS_GEN_EN (0 << 1)
++#define TCS_GEN_EN (0 << 0)
++#else
++#define ICS_GEN_EN (1 << 2)
++#define UCS_GEN_EN (1 << 1)
++#define TCS_GEN_EN (1 << 0)
++#endif
++
++// MDIO_CFG bit
++#define MDIO_CFG_GP1_FC_TX (1 << 11)
++#define MDIO_CFG_GP1_FC_RX (1 << 10)
++
++/* ====================================== */
++/* ====================================== */
++#define GP1_LNK_DWN BIT(9)
++#define GP1_AN_FAIL BIT(8)
++/* ====================================== */
++/* ====================================== */
++#define PSE_RESET BIT(0)
++/* ====================================== */
++#define PST_DRX_IDX3 BIT(19)
++#define PST_DRX_IDX2 BIT(18)
++#define PST_DRX_IDX1 BIT(17)
++#define PST_DRX_IDX0 BIT(16)
++#define PST_DTX_IDX3 BIT(3)
++#define PST_DTX_IDX2 BIT(2)
++#define PST_DTX_IDX1 BIT(1)
++#define PST_DTX_IDX0 BIT(0)
++
++#define RX_2B_OFFSET BIT(31)
++#define DESC_32B_EN BIT(8)
++#define TX_WB_DDONE BIT(6)
++#define RX_DMA_BUSY BIT(3)
++#define TX_DMA_BUSY BIT(1)
++#define RX_DMA_EN BIT(2)
++#define TX_DMA_EN BIT(0)
++
++#define PDMA_BT_SIZE_4DWORDS (0<<4)
++#define PDMA_BT_SIZE_8DWORDS (1<<4)
++#define PDMA_BT_SIZE_16DWORDS (2<<4)
++#define PDMA_BT_SIZE_32DWORDS (3<<4)
++
++#define ADMA_RX_BT_SIZE_4DWORDS (0<<11)
++#define ADMA_RX_BT_SIZE_8DWORDS (1<<11)
++#define ADMA_RX_BT_SIZE_16DWORDS (2<<11)
++#define ADMA_RX_BT_SIZE_32DWORDS (3<<11)
++
++/* Register bits.
++ */
++
++#define MACCFG_RXEN (1<<2)
++#define MACCFG_TXEN (1<<3)
++#define MACCFG_PROMISC (1<<18)
++#define MACCFG_RXMCAST (1<<19)
++#define MACCFG_FDUPLEX (1<<20)
++#define MACCFG_PORTSEL (1<<27)
++#define MACCFG_HBEATDIS (1<<28)
++
++
++#define DMACTL_SR (1<<1) /* Start/Stop Receive */
++#define DMACTL_ST (1<<13) /* Start/Stop Transmission Command */
++
++#define DMACFG_SWR (1<<0) /* Software Reset */
++#define DMACFG_BURST32 (32<<8)
++
++#define DMASTAT_TS 0x00700000 /* Transmit Process State */
++#define DMASTAT_RS 0x000e0000 /* Receive Process State */
++
++#define MACCFG_INIT 0 //(MACCFG_FDUPLEX) // | MACCFG_PORTSEL)
++
++
++
++/* Descriptor bits.
++ */
++#define R_OWN 0x80000000 /* Own Bit */
++#define RD_RER 0x02000000 /* Receive End Of Ring */
++#define RD_LS 0x00000100 /* Last Descriptor */
++#define RD_ES 0x00008000 /* Error Summary */
++#define RD_CHAIN 0x01000000 /* Chained */
++
++/* Word 0 */
++#define T_OWN 0x80000000 /* Own Bit */
++#define TD_ES 0x00008000 /* Error Summary */
++
++/* Word 1 */
++#define TD_LS 0x40000000 /* Last Segment */
++#define TD_FS 0x20000000 /* First Segment */
++#define TD_TER 0x08000000 /* Transmit End Of Ring */
++#define TD_CHAIN 0x01000000 /* Chained */
++
++
++#define TD_SET 0x08000000 /* Setup Packet */
++
++
++#define POLL_DEMAND 1
++
++#define RSTCTL (0x34)
++#define RSTCTL_RSTENET1 (1<<19)
++#define RSTCTL_RSTENET2 (1<<20)
++
++#define INIT_VALUE_OF_RT2883_PSE_FQ_CFG 0xff908000
++#define INIT_VALUE_OF_PSE_FQFC_CFG 0x80504000
++#define INIT_VALUE_OF_FORCE_100_FD 0x1001BC01
++#define INIT_VALUE_OF_FORCE_1000_FD 0x1F01DC01
++
++// Define Whole FE Reset Register
++#define RSTCTRL (RALINK_SYSCTL_BASE + 0x34)
++#define RT2880_AGPIOCFG_REG (RALINK_SYSCTL_BASE + 0x3C)
++
++/*=========================================
++ PDMA RX Descriptor Format define
++=========================================*/
++
++//-------------------------------------------------
++typedef struct _PDMA_RXD_INFO1_ PDMA_RXD_INFO1_T;
++
++struct _PDMA_RXD_INFO1_
++{
++ unsigned int PDP0;
++};
++//-------------------------------------------------
++typedef struct _PDMA_RXD_INFO2_ PDMA_RXD_INFO2_T;
++
++struct _PDMA_RXD_INFO2_
++{
++#if defined (CONFIG_ARCH_MT7623)
++ unsigned int PLEN1 : 2;
++ unsigned int LRO_AGG_CNT : 8;
++ unsigned int REV : 5;
++#else
++ unsigned int PLEN1 : 14;
++ unsigned int LS1 : 1;
++#endif /* CONFIG_RAETH_HW_LRO */
++ unsigned int TAG : 1;
++ unsigned int PLEN0 : 14;
++ unsigned int LS0 : 1;
++ unsigned int DDONE_bit : 1;
++};
++//-------------------------------------------------
++typedef struct _PDMA_RXD_INFO3_ PDMA_RXD_INFO3_T;
++
++struct _PDMA_RXD_INFO3_
++{
++ unsigned int VID:16;
++ unsigned int TPID:16;
++};
++//-------------------------------------------------
++typedef struct _PDMA_RXD_INFO4_ PDMA_RXD_INFO4_T;
++
++struct _PDMA_RXD_INFO4_
++{
++#if defined (CONFIG_RALINK_MT7620)
++ unsigned int FOE_Entry : 14;
++ unsigned int CRSN : 5;
++ unsigned int SPORT : 3;
++ unsigned int L4F : 1;
++ unsigned int L4VLD : 1;
++ unsigned int TACK : 1;
++ unsigned int IP4F : 1;
++ unsigned int IP4 : 1;
++ unsigned int IP6 : 1;
++ unsigned int UN_USE1 : 4;
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++ unsigned int FOE_Entry : 14;
++ unsigned int CRSN : 5;
++ unsigned int SP : 4;
++ unsigned int L4F : 1;
++ unsigned int L4VLD : 1;
++ unsigned int TACK : 1;
++ unsigned int IP4F : 1;
++ unsigned int IP4 : 1;
++ unsigned int IP6 : 1;
++ unsigned int UN_USE1 : 3;
++#else
++ unsigned int FOE_Entry : 14;
++ unsigned int FVLD : 1;
++ unsigned int UN_USE1 : 1;
++ unsigned int AI : 8;
++ unsigned int SP : 3;
++ unsigned int AIS : 1;
++ unsigned int L4F : 1;
++ unsigned int IPF : 1;
++ unsigned int L4FVLD_bit : 1;
++ unsigned int IPFVLD_bit : 1;
++#endif
++};
++
++
++struct PDMA_rxdesc {
++ PDMA_RXD_INFO1_T rxd_info1;
++ PDMA_RXD_INFO2_T rxd_info2;
++ PDMA_RXD_INFO3_T rxd_info3;
++ PDMA_RXD_INFO4_T rxd_info4;
++#ifdef CONFIG_32B_DESC
++ unsigned int rxd_info5;
++ unsigned int rxd_info6;
++ unsigned int rxd_info7;
++ unsigned int rxd_info8;
++#endif
++};
++
++/*=========================================
++ PDMA TX Descriptor Format define
++=========================================*/
++//-------------------------------------------------
++typedef struct _PDMA_TXD_INFO1_ PDMA_TXD_INFO1_T;
++
++struct _PDMA_TXD_INFO1_
++{
++ unsigned int SDP0;
++};
++//-------------------------------------------------
++typedef struct _PDMA_TXD_INFO2_ PDMA_TXD_INFO2_T;
++
++struct _PDMA_TXD_INFO2_
++{
++ unsigned int SDL1 : 14;
++ unsigned int LS1_bit : 1;
++ unsigned int BURST_bit : 1;
++ unsigned int SDL0 : 14;
++ unsigned int LS0_bit : 1;
++ unsigned int DDONE_bit : 1;
++};
++//-------------------------------------------------
++typedef struct _PDMA_TXD_INFO3_ PDMA_TXD_INFO3_T;
++
++struct _PDMA_TXD_INFO3_
++{
++ unsigned int SDP1;
++};
++//-------------------------------------------------
++typedef struct _PDMA_TXD_INFO4_ PDMA_TXD_INFO4_T;
++
++struct _PDMA_TXD_INFO4_
++{
++#if defined (CONFIG_RALINK_MT7620)
++ unsigned int VPRI_VIDX : 8;
++ unsigned int SIDX : 4;
++ unsigned int INSP : 1;
++ unsigned int RESV : 2;
++ unsigned int UDF : 5;
++ unsigned int FP_BMAP : 8;
++ unsigned int TSO : 1;
++ unsigned int TUI_CO : 3;
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++ unsigned int VLAN_TAG :17; // INSV(1)+VPRI(3)+CFI(1)+VID(12)
++ unsigned int RESV : 2;
++ unsigned int UDF : 6;
++ unsigned int FPORT : 3;
++ unsigned int TSO : 1;
++ unsigned int TUI_CO : 3;
++#else
++ unsigned int VPRI_VIDX : 8;
++ unsigned int SIDX : 4;
++ unsigned int INSP : 1;
++ unsigned int RESV : 1;
++ unsigned int UN_USE3 : 2;
++ unsigned int QN : 3;
++ unsigned int UN_USE2 : 1;
++ unsigned int UDF : 4;
++ unsigned int PN : 3;
++ unsigned int UN_USE1 : 1;
++ unsigned int TSO : 1;
++ unsigned int TUI_CO : 3;
++#endif
++};
++
++
++struct PDMA_txdesc {
++ PDMA_TXD_INFO1_T txd_info1;
++ PDMA_TXD_INFO2_T txd_info2;
++ PDMA_TXD_INFO3_T txd_info3;
++ PDMA_TXD_INFO4_T txd_info4;
++#ifdef CONFIG_32B_DESC
++ unsigned int txd_info5;
++ unsigned int txd_info6;
++ unsigned int txd_info7;
++ unsigned int txd_info8;
++#endif
++};
++
++
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++/*=========================================
++ QDMA TX Descriptor Format define
++=========================================*/
++//-------------------------------------------------
++typedef struct _QDMA_TXD_INFO1_ QDMA_TXD_INFO1_T;
++
++struct _QDMA_TXD_INFO1_
++{
++ unsigned int SDP;
++};
++//-------------------------------------------------
++typedef struct _QDMA_TXD_INFO2_ QDMA_TXD_INFO2_T;
++
++struct _QDMA_TXD_INFO2_
++{
++ unsigned int NDP;
++};
++//-------------------------------------------------
++typedef struct _QDMA_TXD_INFO3_ QDMA_TXD_INFO3_T;
++
++struct _QDMA_TXD_INFO3_
++{
++ unsigned int QID : 4;
++#if defined (CONFIG_HW_SFQ)
++ //unsigned int VQID : 10;
++ unsigned int PROT : 3;
++ unsigned int IPOFST : 7;
++#else
++ unsigned int RESV : 10;
++#endif
++ unsigned int SWC_bit : 1;
++ unsigned int BURST_bit : 1;
++ unsigned int SDL : 14;
++ unsigned int LS_bit : 1;
++ unsigned int OWN_bit : 1;
++};
++//-------------------------------------------------
++typedef struct _QDMA_TXD_INFO4_ QDMA_TXD_INFO4_T;
++
++struct _QDMA_TXD_INFO4_
++{
++ unsigned int VLAN_TAG :17; // INSV(1)+VPRI(3)+CFI(1)+VID(12)
++#if defined (CONFIG_RALINK_MT7621)
++ unsigned int RESV : 2;
++ unsigned int UDF : 6;
++#elif defined(CONFIG_ARCH_MT7623)
++ unsigned int VQID0 : 1;
++ unsigned int RESV : 7;
++#endif
++ unsigned int FPORT : 3;
++ unsigned int TSO : 1;
++ unsigned int TUI_CO : 3;
++};
++
++
++struct QDMA_txdesc {
++ QDMA_TXD_INFO1_T txd_info1;
++ QDMA_TXD_INFO2_T txd_info2;
++ QDMA_TXD_INFO3_T txd_info3;
++ QDMA_TXD_INFO4_T txd_info4;
++#ifdef CONFIG_32B_DESC
++ unsigned int txd_info5;
++ unsigned int txd_info6;
++ unsigned int txd_info7;
++ unsigned int txd_info8;
++#endif
++};
++#endif
++
++#if defined (CONFIG_ARCH_MT7623)
++#define phys_to_bus(a) (a)
++#else
++#define phys_to_bus(a) (a & 0x1FFFFFFF)
++#endif
++
++#define PHY_Enable_Auto_Nego 0x1000
++#define PHY_Restart_Auto_Nego 0x0200
++
++/* PHY_STAT_REG = 1; */
++#define PHY_Auto_Neco_Comp 0x0020
++#define PHY_Link_Status 0x0004
++
++/* PHY_AUTO_NEGO_REG = 4; */
++#define PHY_Cap_10_Half 0x0020
++#define PHY_Cap_10_Full 0x0040
++#define PHY_Cap_100_Half 0x0080
++#define PHY_Cap_100_Full 0x0100
++
++/* proc definition */
++
++#if !defined (CONFIG_RALINK_RT6855) && !defined(CONFIG_RALINK_RT6855A) && \
++ !defined (CONFIG_RALINK_MT7620) && !defined (CONFIG_RALINK_MT7621) && \
++ !defined (CONFIG_ARCH_MT7623)
++#define CDMA_OQ_STA (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x4c)
++#define GDMA1_OQ_STA (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x50)
++#define PPE_OQ_STA (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x54)
++#define PSE_IQ_STA (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x58)
++#endif
++
++#define PROCREG_CONTROL_FILE "/var/run/procreg_control"
++#if defined (CONFIG_RALINK_RT2880)
++#define PROCREG_DIR "rt2880"
++#elif defined (CONFIG_RALINK_RT3052)
++#define PROCREG_DIR "rt3052"
++#elif defined (CONFIG_RALINK_RT3352)
++#define PROCREG_DIR "rt3352"
++#elif defined (CONFIG_RALINK_RT5350)
++#define PROCREG_DIR "rt5350"
++#elif defined (CONFIG_RALINK_RT2883)
++#define PROCREG_DIR "rt2883"
++#elif defined (CONFIG_RALINK_RT3883)
++#define PROCREG_DIR "rt3883"
++#elif defined (CONFIG_RALINK_RT6855)
++#define PROCREG_DIR "rt6855"
++#elif defined (CONFIG_RALINK_MT7620)
++#define PROCREG_DIR "mt7620"
++#elif defined (CONFIG_RALINK_MT7621)
++#define PROCREG_DIR "mt7621"
++#elif defined (CONFIG_ARCH_MT7623)
++#define PROCREG_DIR "mt7623"
++#elif defined (CONFIG_RALINK_MT7628)
++#define PROCREG_DIR "mt7628"
++#elif defined (CONFIG_RALINK_RT6855A)
++#define PROCREG_DIR "rt6855a"
++#else
++#define PROCREG_DIR "rt2880"
++#endif
++#define PROCREG_SKBFREE "skb_free"
++#define PROCREG_TXRING "tx_ring"
++#define PROCREG_RXRING "rx_ring"
++#define PROCREG_RXRING1 "rx_ring1"
++#define PROCREG_RXRING2 "rx_ring2"
++#define PROCREG_RXRING3 "rx_ring3"
++#define PROCREG_NUM_OF_TXD "num_of_txd"
++#define PROCREG_TSO_LEN "tso_len"
++#define PROCREG_LRO_STATS "lro_stats"
++#define PROCREG_HW_LRO_STATS "hw_lro_stats"
++#define PROCREG_HW_LRO_AUTO_TLB "hw_lro_auto_tlb"
++#define PROCREG_GMAC "gmac"
++#define PROCREG_GMAC2 "gmac2"
++#define PROCREG_CP0 "cp0"
++#define PROCREG_RAQOS "qos"
++#define PROCREG_READ_VAL "regread_value"
++#define PROCREG_WRITE_VAL "regwrite_value"
++#define PROCREG_ADDR "reg_addr"
++#define PROCREG_CTL "procreg_control"
++#define PROCREG_RXDONE_INTR "rxdone_intr_count"
++#define PROCREG_ESW_INTR "esw_intr_count"
++#define PROCREG_ESW_CNT "esw_cnt"
++#define PROCREG_SNMP "snmp"
++#if defined (TASKLET_WORKQUEUE_SW)
++#define PROCREG_SCHE "schedule"
++#endif
++#define PROCREG_QDMA "qdma"
++#if defined(CONFIG_RAETH_PDMA_DVT)
++#define PROCREG_PDMA_DVT "pdma_dvt"
++#endif //#if defined(CONFIG_RAETH_PDMA_DVT)
++struct rt2880_reg_op_data {
++ char name[64];
++ unsigned int reg_addr;
++ unsigned int op;
++ unsigned int reg_value;
++};
++
++#ifdef CONFIG_RAETH_LRO
++struct lro_counters {
++ u32 lro_aggregated;
++ u32 lro_flushed;
++ u32 lro_no_desc;
++};
++
++struct lro_para_struct {
++ unsigned int lan_ip1;
++};
++
++#endif // CONFIG_RAETH_LRO //
++
++
++#if defined (CONFIG_HW_SFQ)
++typedef struct {
++ //layer2 header
++ uint8_t dmac[6];
++ uint8_t smac[6];
++
++ //vlan header
++ uint16_t vlan_tag;
++ uint16_t vlan1_gap;
++ uint16_t vlan1;
++ uint16_t vlan2_gap;
++ uint16_t vlan2;
++ uint16_t vlan_layer;
++
++ //pppoe header
++ uint32_t pppoe_gap;
++ uint16_t ppp_tag;
++ uint16_t pppoe_sid;
++
++ //layer3 header
++ uint16_t eth_type;
++ struct iphdr iph;
++ struct ipv6hdr ip6h;
++
++ //layer4 header
++ struct tcphdr th;
++ struct udphdr uh;
++
++ uint32_t pkt_type;
++ uint8_t is_mcast;
++
++} ParseResult;
++#endif
++typedef struct end_device
++{
++
++ unsigned int tx_cpu_owner_idx0;
++ unsigned int rx_cpu_owner_idx0;
++ unsigned int fe_int_status;
++ unsigned int tx_full;
++
++#if !defined (CONFIG_RAETH_QDMA)
++ unsigned int phy_tx_ring0;
++#else
++ /* QDMA Tx PTR */
++ struct sk_buff *free_skb[NUM_TX_DESC];
++ unsigned int tx_dma_ptr;
++ unsigned int tx_cpu_ptr;
++ unsigned int free_txd_num;
++ unsigned int free_txd_head;
++ unsigned int free_txd_tail;
++ struct QDMA_txdesc *txd_pool;
++ dma_addr_t phy_txd_pool;
++ unsigned int txd_pool_info[NUM_TX_DESC];
++ struct QDMA_txdesc *free_head;
++ unsigned int phy_free_head;
++ unsigned int *free_page_head;
++ unsigned int phy_free_page_head;
++ struct PDMA_rxdesc *qrx_ring;
++ unsigned int phy_qrx_ring;
++#ifdef CONFIG_RAETH_PDMATX_QDMARX /* QDMA RX */
++ unsigned int phy_tx_ring0;
++#endif
++#endif
++
++ unsigned int phy_rx_ring0, phy_rx_ring1, phy_rx_ring2, phy_rx_ring3;
++
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || \
++ defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || \
++ defined(CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || \
++ defined(CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || \
++ defined (CONFIG_ARCH_MT7623)
++ //send signal to user application to notify link status changed
++ struct work_struct kill_sig_wq;
++#endif
++
++ struct work_struct reset_task;
++#ifdef WORKQUEUE_BH
++ struct work_struct rx_wq;
++#else
++#if defined (TASKLET_WORKQUEUE_SW)
++ struct work_struct rx_wq;
++#endif
++ struct tasklet_struct rx_tasklet;
++ struct tasklet_struct tx_tasklet;
++#endif // WORKQUEUE_BH //
++
++#if defined(CONFIG_RAETH_QOS)
++ struct sk_buff * skb_free[NUM_TX_RINGS][NUM_TX_DESC];
++ unsigned int free_idx[NUM_TX_RINGS];
++#else
++ struct sk_buff* skb_free[NUM_TX_DESC];
++ unsigned int free_idx;
++#endif
++
++ struct net_device_stats stat; /* The new statistics table. */
++ spinlock_t page_lock; /* Page register locks */
++ struct PDMA_txdesc *tx_ring0;
++#if defined(CONFIG_RAETH_QOS)
++ struct PDMA_txdesc *tx_ring1;
++ struct PDMA_txdesc *tx_ring2;
++ struct PDMA_txdesc *tx_ring3;
++#endif
++ struct PDMA_rxdesc *rx_ring0;
++ struct sk_buff *netrx0_skbuf[NUM_RX_DESC];
++#if defined (CONFIG_RAETH_HW_LRO)
++ struct PDMA_rxdesc *rx_ring3;
++ struct sk_buff *netrx3_skbuf[NUM_RX_DESC];
++ struct PDMA_rxdesc *rx_ring2;
++ struct sk_buff *netrx2_skbuf[NUM_RX_DESC];
++ struct PDMA_rxdesc *rx_ring1;
++ struct sk_buff *netrx1_skbuf[NUM_RX_DESC];
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++ struct PDMA_rxdesc *rx_ring1;
++ struct sk_buff *netrx1_skbuf[NUM_RX_DESC];
++#if defined(CONFIG_ARCH_MT7623)
++ struct PDMA_rxdesc *rx_ring2;
++ struct sk_buff *netrx2_skbuf[NUM_RX_DESC];
++ struct PDMA_rxdesc *rx_ring3;
++ struct sk_buff *netrx3_skbuf[NUM_RX_DESC];
++#endif /* CONFIG_ARCH_MT7623 */
++#endif
++#ifdef CONFIG_RAETH_NAPI
++ atomic_t irq_sem;
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ struct napi_struct napi;
++#endif
++#endif
++#ifdef CONFIG_PSEUDO_SUPPORT
++ struct net_device *PseudoDev;
++ unsigned int isPseudo;
++#endif
++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
++ struct mii_if_info mii_info;
++#endif
++#ifdef CONFIG_RAETH_LRO
++ struct lro_counters lro_counters;
++ struct net_lro_mgr lro_mgr;
++ struct net_lro_desc lro_arr[8];
++#endif
++#ifdef CONFIG_RAETH_HW_VLAN_RX
++ struct vlan_group *vlgrp;
++#endif
++#if defined (CONFIG_RAETH_HW_LRO)
++ struct work_struct hw_lro_wq;
++ unsigned int hw_lro_pkt_interval[3];
++ unsigned int hw_lro_alpha; /* 0 < packet interval alpha <= 10 */
++ unsigned int hw_lro_fix_setting; /* 0: dynamical AGG/AGE time, 1: fixed AGG/AGE time */
++#endif /* CONFIG_RAETH_HW_LRO */
++} END_DEVICE, *pEND_DEVICE;
++
++
++#define RAETH_VERSION "v3.1"
++
++#endif
++
++#define DMA_GLO_CFG PDMA_GLO_CFG
++
++#if defined(CONFIG_RAETH_QDMATX_QDMARX)
++#define GDMA1_FWD_PORT 0x5555
++#define GDMA2_FWD_PORT 0x5555
++#elif defined(CONFIG_RAETH_PDMATX_QDMARX)
++#define GDMA1_FWD_PORT 0x5555
++#define GDMA2_FWD_PORT 0x5555
++#else
++#define GDMA1_FWD_PORT 0x0000
++#define GDMA2_FWD_PORT 0x0000
++#endif
++
++#if defined(CONFIG_RAETH_QDMATX_QDMARX)
++#define RAETH_RX_CALC_IDX0 QRX_CRX_IDX_0
++#define RAETH_RX_CALC_IDX1 QRX_CRX_IDX_1
++#elif defined(CONFIG_RAETH_PDMATX_QDMARX)
++#define RAETH_RX_CALC_IDX0 QRX_CRX_IDX_0
++#define RAETH_RX_CALC_IDX1 QRX_CRX_IDX_1
++#else
++#define RAETH_RX_CALC_IDX0 RX_CALC_IDX0
++#define RAETH_RX_CALC_IDX1 RX_CALC_IDX1
++#endif
++#define RAETH_RX_CALC_IDX2 RX_CALC_IDX2
++#define RAETH_RX_CALC_IDX3 RX_CALC_IDX3
++#define RAETH_FE_INT_STATUS FE_INT_STATUS
++#define RAETH_FE_INT_ALL FE_INT_ALL
++#define RAETH_FE_INT_ENABLE FE_INT_ENABLE
++#define RAETH_FE_INT_DLY_INIT FE_INT_DLY_INIT
++#define RAETH_FE_INT_SETTING RX_DONE_INT0 | RX_DONE_INT1 | TX_DONE_INT0 | TX_DONE_INT1 | TX_DONE_INT2 | TX_DONE_INT3
++#define QFE_INT_SETTING RX_DONE_INT0 | RX_DONE_INT1 | TX_DONE_INT0 | TX_DONE_INT1 | TX_DONE_INT2 | TX_DONE_INT3
++#define RAETH_TX_DLY_INT TX_DLY_INT
++#define RAETH_TX_DONE_INT0 TX_DONE_INT0
++#define RAETH_DLY_INT_CFG DLY_INT_CFG
+diff --git a/drivers/net/ethernet/raeth/ra_ethtool.c b/drivers/net/ethernet/raeth/ra_ethtool.c
+new file mode 100644
+index 0000000..ff13e59
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_ethtool.c
+@@ -0,0 +1,515 @@
++#include <linux/module.h>
++#include <linux/version.h>
++
++#include <linux/kernel.h>
++#include <linux/sched.h>
++
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++#include <linux/if_ether.h>
++#include <linux/ethtool.h>
++
++#include "ra2882ethreg.h"
++#include "raether.h"
++#include "ra_mac.h"
++#include "ra_ethtool.h"
++
++#define RAETHER_DRIVER_NAME "raether"
++#define RA_NUM_STATS 4
++
++
++static struct {
++ const char str[ETH_GSTRING_LEN];
++} ethtool_stats_keys[] = {
++ { "statistic1" },
++ { "statistic2" },
++ { "statistic3" },
++ { "statistic4" },
++};
++
++unsigned char get_current_phy_address(void)
++{
++ struct net_device *cur_dev_p;
++ END_DEVICE *ei_local;
++#if 0
++ for(cur_dev_p=dev_base; cur_dev_p!=NULL; cur_dev_p=cur_dev_p->next){
++ if (strncmp(cur_dev_p->name, DEV_NAME /* "eth2" usually */, 4) == 0)
++ break;
++ }
++#else
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ cur_dev_p = dev_get_by_name(&init_net, DEV_NAME);
++#else
++ cur_dev_p = dev_get_by_name(DEV_NAME);
++#endif
++#endif
++ if(!cur_dev_p)
++ return 0;
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ ei_local = netdev_priv(cur_dev_p);
++#else
++ ei_local = cur_dev_p->priv;
++#endif
++ return ei_local->mii_info.phy_id;
++}
++#if 0
++static u32 et_get_tx_csum(struct net_device *dev)
++{
++ return (sysRegRead(GDMA1_FWD_CFG) & GDM1_DISCRC) ? 0 : 1; // a pitfall here, "0" means to enable.
++}
++
++static u32 et_get_rx_csum(struct net_device *dev)
++{
++ return (sysRegRead(GDMA1_FWD_CFG) & GDM1_STRPCRC) ? 1 : 0;
++}
++
++static int et_set_tx_csum(struct net_device *dev, u32 data)
++{
++ int value;
++ //printk("et_set_tx_csum(): data = %d\n", data);
++
++ value = sysRegRead(GDMA1_FWD_CFG);
++ if(data)
++ value |= GDM1_DISCRC;
++ else
++ value &= ~GDM1_DISCRC;
++
++ sysRegWrite(GDMA1_FWD_CFG, value);
++ return 0;
++}
++
++static int et_set_rx_csum(struct net_device *dev, u32 data)
++{
++ int value;
++ //printk("et_set_rx_csum(): data = %d\n", data);
++
++ value = sysRegRead(GDMA1_FWD_CFG);
++ if(data)
++ value |= GDM1_STRPCRC;
++ else
++ value &= ~GDM1_STRPCRC;
++
++ sysRegWrite(GDMA1_FWD_CFG, value);
++ return 0;
++}
++#endif
++
++#define MII_CR_ADDR 0x00
++#define MII_CR_MR_AUTONEG_ENABLE (1 << 12)
++#define MII_CR_MR_RESTART_NEGOTIATION (1 << 9)
++
++#define AUTO_NEGOTIATION_ADVERTISEMENT 0x04
++#define AN_PAUSE (1 << 10)
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
++static void et_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
++{
++ int mii_an_reg;
++ int mdio_cfg_reg;
++ END_DEVICE *ei_local = dev->priv;
++
++ // get mii auto-negotiation register
++ mii_mgr_read(ei_local->mii_info.phy_id, AUTO_NEGOTIATION_ADVERTISEMENT, &mii_an_reg);
++ epause->autoneg = (mii_an_reg & AN_PAUSE) ? 1 : 0; //get autonet_enable flag bit
++
++ mdio_cfg_reg = sysRegRead(MDIO_CFG);
++ epause->tx_pause = (mdio_cfg_reg & MDIO_CFG_GP1_FC_TX) ? 1 : 0;
++ epause->rx_pause = (mdio_cfg_reg & MDIO_CFG_GP1_FC_RX) ? 1 : 0;
++
++ //printk("et_get_pauseparam(): autoneg=%d, tx_pause=%d, rx_pause=%d\n", epause->autoneg, epause->tx_pause, epause->rx_pause);
++}
++
++static int et_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
++{
++ int mdio_cfg_reg;
++ int mii_an_reg;
++ END_DEVICE *ei_local = dev->priv;
++
++ //printk("et_set_pauseparam(): autoneg=%d, tx_pause=%d, rx_pause=%d\n", epause->autoneg, epause->tx_pause, epause->rx_pause);
++
++ // auto-neg pause
++ mii_mgr_read(ei_local->mii_info.phy_id, AUTO_NEGOTIATION_ADVERTISEMENT, &mii_an_reg);
++ if(epause->autoneg)
++ mii_an_reg |= AN_PAUSE;
++ else
++ mii_an_reg &= ~AN_PAUSE;
++ mii_mgr_write(ei_local->mii_info.phy_id, AUTO_NEGOTIATION_ADVERTISEMENT, mii_an_reg);
++
++ // tx/rx pause
++ mdio_cfg_reg = sysRegRead(MDIO_CFG);
++ if(epause->tx_pause)
++ mdio_cfg_reg |= MDIO_CFG_GP1_FC_TX;
++ else
++ mdio_cfg_reg &= ~MDIO_CFG_GP1_FC_TX;
++ if(epause->rx_pause)
++ mdio_cfg_reg |= MDIO_CFG_GP1_FC_RX;
++ else
++ mdio_cfg_reg &= ~MDIO_CFG_GP1_FC_RX;
++ sysRegWrite(MDIO_CFG, mdio_cfg_reg);
++
++ return 0;
++}
++
++static int et_nway_reset(struct net_device *dev)
++{
++ END_DEVICE *ei_local = dev->priv;
++ return mii_nway_restart(&ei_local->mii_info);
++}
++#endif
++
++static u32 et_get_link(struct net_device *dev)
++{
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ END_DEVICE *ei_local = netdev_priv(dev);
++#else
++ END_DEVICE *ei_local = dev->priv;
++#endif
++ return mii_link_ok(&ei_local->mii_info);
++}
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
++static int et_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++ END_DEVICE *ei_local = dev->priv;
++ int rc;
++ rc = mii_ethtool_sset(&ei_local->mii_info, cmd);
++ return rc;
++}
++#endif
++
++static int et_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ END_DEVICE *ei_local = netdev_priv(dev);
++#else
++ END_DEVICE *ei_local = dev->priv;
++#endif
++ mii_ethtool_gset(&ei_local->mii_info, cmd);
++ return 0;
++}
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
++static u32 et_get_msglevel(struct net_device *dev)
++{
++ return 0;
++}
++
++static void et_set_msglevel(struct net_device *dev, u32 datum)
++{
++ return;
++}
++
++static void et_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
++{
++ //END_DEVICE *ei_local = dev->priv;
++ strcpy(info->driver, RAETHER_DRIVER_NAME);
++ strcpy(info->version, RAETH_VERSION);
++ strcpy(info->bus_info, "n/a");
++ info->n_stats = RA_NUM_STATS;
++ info->eedump_len = 0;
++ info->regdump_len = 0;
++}
++
++static int et_get_stats_count(struct net_device *dev)
++{
++ return RA_NUM_STATS;
++}
++
++static void et_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data)
++{
++// END_DEVICE *ei_local = dev->priv;
++ data[0] = 0;//np->xstats.early_rx;
++ data[1] = 0;//np->xstats.tx_buf_mapped;
++ data[2] = 0;//np->xstats.tx_timeouts;
++ data[3] = 0;//np->xstats.rx_lost_in_ring;
++}
++
++static void et_get_strings(struct net_device *dev, u32 stringset, u8 *data)
++{
++ memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys));
++}
++#endif
++
++/*
++ * mii_mgr_read wrapper for mii.o ethtool
++ */
++int mdio_read(struct net_device *dev, int phy_id, int location)
++{
++ unsigned int result;
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ END_DEVICE *ei_local = netdev_priv(dev);
++#else
++ END_DEVICE *ei_local = dev->priv;
++#endif
++ mii_mgr_read( (unsigned int) ei_local->mii_info.phy_id, (unsigned int)location, &result);
++ //printk("\n%s mii.o query= phy_id:%d, address:%d retval:%x\n", dev->name, phy_id, location, result);
++ return (int)result;
++}
++
++/*
++ * mii_mgr_write wrapper for mii.o ethtool
++ */
++void mdio_write(struct net_device *dev, int phy_id, int location, int value)
++{
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ END_DEVICE *ei_local = netdev_priv(dev);
++#else
++ END_DEVICE *ei_local = dev->priv;
++#endif
++ //printk("mii.o write= phy_id:%d, address:%d value:%x\n", phy_id, location, value);
++ mii_mgr_write( (unsigned int) ei_local->mii_info.phy_id, (unsigned int)location, (unsigned int)value);
++ return;
++}
++
++struct ethtool_ops ra_ethtool_ops = {
++
++ .get_settings = et_get_settings,
++ .get_link = et_get_link,
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
++ .get_drvinfo = et_get_drvinfo,
++ .set_settings = et_set_settings,
++ .get_pauseparam = et_get_pauseparam,
++ .set_pauseparam = et_set_pauseparam,
++// .get_rx_csum = et_get_rx_csum,
++// .set_rx_csum = et_set_rx_csum,
++// .get_tx_csum = et_get_tx_csum,
++// .set_tx_csum = et_set_tx_csum,
++ .nway_reset = et_nway_reset,
++ .get_msglevel = et_get_msglevel,
++ .set_msglevel = et_set_msglevel,
++ .get_strings = et_get_strings,
++ .get_stats_count = et_get_stats_count,
++ .get_ethtool_stats = et_get_ethtool_stats,
++/* .get_regs_len = et_get_regs_len,
++ .get_regs = et_get_regs,
++*/
++#endif
++};
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++/*
++ * We unable to re-use the Raether functions because it is hard to tell
++ * where the calling from is. From eth2 or eth3?
++ *
++ * These code size is around 950 bytes.
++ */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
++static void et_virt_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
++{
++ // PSEUDO_ADAPTER *pseudo = dev->priv;
++ return et_get_drvinfo(dev, info);
++}
++
++static void et_virt_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
++{
++ int mii_an_reg, mdio_cfg_reg;
++ PSEUDO_ADAPTER *pseudo = dev->priv;
++
++ // get mii auto-negotiation register
++ mii_mgr_read(pseudo->mii_info.phy_id, AUTO_NEGOTIATION_ADVERTISEMENT, &mii_an_reg);
++ epause->autoneg = (mii_an_reg & AN_PAUSE) ? 1 : 0; //get autonet_enable flag bit
++
++ mdio_cfg_reg = sysRegRead(MDIO_CFG);
++ epause->tx_pause = (mdio_cfg_reg & MDIO_CFG_GP1_FC_TX) ? 1 : 0;
++ epause->rx_pause = (mdio_cfg_reg & MDIO_CFG_GP1_FC_RX) ? 1 : 0;
++
++ //printk("et_get_pauseparam(): autoneg=%d, tx_pause=%d, rx_pause=%d\n", epause->autoneg, epause->tx_pause, epause->rx_pause);
++}
++
++static int et_virt_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
++{
++ int mdio_cfg_reg;
++ int mii_an_reg;
++ PSEUDO_ADAPTER *pseudo = dev->priv;
++
++ //printk("et_set_pauseparam(): autoneg=%d, tx_pause=%d, rx_pause=%d\n", epause->autoneg, epause->tx_pause, epause->rx_pause);
++ // auto-neg pause
++ mii_mgr_read(pseudo->mii_info.phy_id, AUTO_NEGOTIATION_ADVERTISEMENT, &mii_an_reg);
++ if(epause->autoneg)
++ mii_an_reg |= AN_PAUSE;
++ else
++ mii_an_reg &= ~AN_PAUSE;
++ mii_mgr_write(pseudo->mii_info.phy_id, AUTO_NEGOTIATION_ADVERTISEMENT, mii_an_reg);
++
++ // tx/rx pause
++ mdio_cfg_reg = sysRegRead(MDIO_CFG);
++ if(epause->tx_pause)
++ mdio_cfg_reg |= MDIO_CFG_GP1_FC_TX;
++ else
++ mdio_cfg_reg &= ~MDIO_CFG_GP1_FC_TX;
++ if(epause->rx_pause)
++ mdio_cfg_reg |= MDIO_CFG_GP1_FC_RX;
++ else
++ mdio_cfg_reg &= ~MDIO_CFG_GP1_FC_RX;
++ sysRegWrite(MDIO_CFG, mdio_cfg_reg);
++
++ return 0;
++}
++
++static u32 et_virt_get_tx_csum(struct net_device *dev)
++{
++ return (sysRegRead(GDMA2_FWD_CFG) & GDM1_DISCRC) ? 0 : 1; // a pitfall here, "0" means to enable.
++}
++
++static u32 et_virt_get_rx_csum(struct net_device *dev)
++{
++ return (sysRegRead(GDMA2_FWD_CFG) & GDM1_STRPCRC) ? 1 : 0;
++}
++
++static int et_virt_set_tx_csum(struct net_device *dev, u32 data)
++{
++ int value;
++ //printk("et_set_tx_csum(): data = %d\n", data);
++ value = sysRegRead(GDMA2_FWD_CFG);
++ if(data)
++ value |= GDM1_DISCRC;
++ else
++ value &= ~GDM1_DISCRC;
++ sysRegWrite(GDMA1_FWD_CFG, value);
++ return 0;
++}
++
++static int et_virt_set_rx_csum(struct net_device *dev, u32 data)
++{
++ int value;
++ //printk("et_set_rx_csum(): data = %d\n", data);
++ value = sysRegRead(GDMA2_FWD_CFG);
++ if(data)
++ value |= GDM1_STRPCRC;
++ else
++ value &= ~GDM1_STRPCRC;
++ sysRegWrite(GDMA1_FWD_CFG, value);
++ return 0;
++}
++
++static int et_virt_nway_reset(struct net_device *dev)
++{
++ PSEUDO_ADAPTER *pseudo = dev->priv;
++ return mii_nway_restart(&pseudo->mii_info);
++}
++#endif
++
++static u32 et_virt_get_link(struct net_device *dev)
++{
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ PSEUDO_ADAPTER *pseudo = netdev_priv(dev);
++#else
++ PSEUDO_ADAPTER *pseudo = dev->priv;
++#endif
++ return mii_link_ok(&pseudo->mii_info);
++}
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
++static int et_virt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++ PSEUDO_ADAPTER *pseudo = dev->priv;
++ int rc = mii_ethtool_sset(&pseudo->mii_info, cmd);
++ return rc;
++}
++#endif
++
++static int et_virt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ PSEUDO_ADAPTER *pseudo = netdev_priv(dev);
++#else
++ PSEUDO_ADAPTER *pseudo = dev->priv;
++#endif
++ mii_ethtool_gset(&pseudo->mii_info, cmd);
++ return 0;
++}
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
++static u32 et_virt_get_msglevel(struct net_device *dev)
++{
++ return 0;
++}
++
++static void et_virt_set_msglevel(struct net_device *dev, u32 datum)
++{
++ return;
++}
++
++static void et_virt_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data)
++{
++// PSEUDO_ADAPTER *pseudo = dev->priv;
++ data[0] = 0;//np->xstats.early_rx;
++ data[1] = 0;//np->xstats.tx_buf_mapped;
++ data[2] = 0;//np->xstats.tx_timeouts;
++ data[3] = 0;//np->xstats.rx_lost_in_ring;
++}
++
++/* for virtual interface dedicated */
++#define RA_VIRT_NUM_STATS 4
++static struct {
++ const char str[ETH_GSTRING_LEN];
++} ethtool_stats_keys_2[] = {
++ { "statistic1" },
++ { "statistic2" },
++ { "statistic3" },
++ { "statistic4" },
++};
++
++static int et_virt_get_stats_count(struct net_device *dev)
++{
++ return RA_VIRT_NUM_STATS;
++}
++
++static void et_virt_get_strings(struct net_device *dev, u32 stringset, u8 *data)
++{
++ memcpy(data, ethtool_stats_keys_2, sizeof(ethtool_stats_keys_2));
++}
++#endif
++
++struct ethtool_ops ra_virt_ethtool_ops = {
++ .get_settings = et_virt_get_settings,
++ .get_link = et_virt_get_link,
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
++ .get_drvinfo = et_virt_get_drvinfo,
++ .set_settings = et_virt_set_settings,
++ .get_pauseparam = et_virt_get_pauseparam,
++ .set_pauseparam = et_virt_set_pauseparam,
++ .get_rx_csum = et_virt_get_rx_csum,
++ .set_rx_csum = et_virt_set_rx_csum,
++ .get_tx_csum = et_virt_get_tx_csum,
++ .set_tx_csum = et_virt_set_tx_csum,
++ .nway_reset = et_virt_nway_reset,
++ .get_msglevel = et_virt_get_msglevel,
++ .set_msglevel = et_virt_set_msglevel,
++ .get_strings = et_virt_get_strings,
++ .get_stats_count = et_virt_get_stats_count,
++ .get_ethtool_stats = et_virt_get_ethtool_stats,
++/* .get_regs_len = et_virt_get_regs_len,
++ .get_regs = et_virt_get_regs,
++*/
++#endif
++};
++
++int mdio_virt_read(struct net_device *dev, int phy_id, int location)
++{
++ unsigned int result;
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ PSEUDO_ADAPTER *pseudo = netdev_priv(dev);
++#else
++ PSEUDO_ADAPTER *pseudo = dev->priv;
++#endif
++ mii_mgr_read( (unsigned int) pseudo->mii_info.phy_id, (unsigned int)location, &result);
++// printk("%s mii.o query= phy_id:%d, address:%d retval:%d\n", dev->name, phy_id, location, result);
++ return (int)result;
++}
++
++void mdio_virt_write(struct net_device *dev, int phy_id, int location, int value)
++{
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ PSEUDO_ADAPTER *pseudo = netdev_priv(dev);
++#else
++ PSEUDO_ADAPTER *pseudo = dev->priv;
++#endif
++// printk("mii.o write= phy_id:%d, address:%d value:%d\n", phy_id, location, value);
++ mii_mgr_write( (unsigned int) pseudo->mii_info.phy_id, (unsigned int)location, (unsigned int)value);
++ return;
++}
++
++#endif /* CONFIG_PSEUDO_SUPPORT */
++
++
+diff --git a/drivers/net/ethernet/raeth/ra_ethtool.h b/drivers/net/ethernet/raeth/ra_ethtool.h
+new file mode 100644
+index 0000000..d64a1ab
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_ethtool.h
+@@ -0,0 +1,13 @@
++#ifndef RA_ETHTOOL_H
++#define RA_ETHTOOL_H
++
++/* ethtool related */
++unsigned char get_current_phy_address(void);
++int mdio_read(struct net_device *dev, int phy_id, int location);
++void mdio_write(struct net_device *dev, int phy_id, int location, int value);
++
++/* for pseudo interface */
++int mdio_virt_read(struct net_device *dev, int phy_id, int location);
++void mdio_virt_write(struct net_device *dev, int phy_id, int location, int value);
++
++#endif
+diff --git a/drivers/net/ethernet/raeth/ra_ioctl.h b/drivers/net/ethernet/raeth/ra_ioctl.h
+new file mode 100644
+index 0000000..83b806a
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_ioctl.h
+@@ -0,0 +1,102 @@
++#ifndef _RAETH_IOCTL_H
++#define _RAETH_IOCTL_H
++
++/* ioctl commands */
++#define RAETH_ESW_REG_READ 0x89F1
++#define RAETH_ESW_REG_WRITE 0x89F2
++#define RAETH_MII_READ 0x89F3
++#define RAETH_MII_WRITE 0x89F4
++#define RAETH_ESW_INGRESS_RATE 0x89F5
++#define RAETH_ESW_EGRESS_RATE 0x89F6
++#define RAETH_ESW_PHY_DUMP 0x89F7
++#define RAETH_QDMA_REG_READ 0x89F8
++#define RAETH_QDMA_REG_WRITE 0x89F9
++#define RAETH_QDMA_QUEUE_MAPPING 0x89FA
++#define RAETH_QDMA_READ_CPU_CLK 0x89FB
++#define RAETH_MII_READ_CL45 0x89FC
++#define RAETH_MII_WRITE_CL45 0x89FD
++#if defined(CONFIG_HW_SFQ)
++#define RAETH_QDMA_SFQ_WEB_ENABLE 0x89FE
++#endif
++
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined (CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || \
++ defined (CONFIG_ARCH_MT7623)
++
++#define REG_ESW_WT_MAC_MFC 0x10
++#define REG_ESW_ISC 0x18
++#define REG_ESW_WT_MAC_ATA1 0x74
++#define REG_ESW_WT_MAC_ATA2 0x78
++#define REG_ESW_WT_MAC_ATWD 0x7C
++#define REG_ESW_WT_MAC_ATC 0x80
++
++#define REG_ESW_TABLE_TSRA1 0x84
++#define REG_ESW_TABLE_TSRA2 0x88
++#define REG_ESW_TABLE_ATRD 0x8C
++
++
++#define REG_ESW_VLAN_VTCR 0x90
++#define REG_ESW_VLAN_VAWD1 0x94
++#define REG_ESW_VLAN_VAWD2 0x98
++
++
++#define REG_ESW_VLAN_ID_BASE 0x100
++
++//#define REG_ESW_VLAN_ID_BASE 0x50
++#define REG_ESW_VLAN_MEMB_BASE 0x70
++#define REG_ESW_TABLE_SEARCH 0x24
++#define REG_ESW_TABLE_STATUS0 0x28
++#define REG_ESW_TABLE_STATUS1 0x2C
++#define REG_ESW_TABLE_STATUS2 0x30
++#define REG_ESW_WT_MAC_AD0 0x34
++#define REG_ESW_WT_MAC_AD1 0x38
++#define REG_ESW_WT_MAC_AD2 0x3C
++
++#else
++/* rt3052 embedded ethernet switch registers */
++#define REG_ESW_VLAN_ID_BASE 0x50
++#define REG_ESW_VLAN_MEMB_BASE 0x70
++#define REG_ESW_TABLE_SEARCH 0x24
++#define REG_ESW_TABLE_STATUS0 0x28
++#define REG_ESW_TABLE_STATUS1 0x2C
++#define REG_ESW_TABLE_STATUS2 0x30
++#define REG_ESW_WT_MAC_AD0 0x34
++#define REG_ESW_WT_MAC_AD1 0x38
++#define REG_ESW_WT_MAC_AD2 0x3C
++#endif
++
++
++#if defined(CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++#define REG_ESW_MAX 0x16C
++#elif defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined (CONFIG_RALINK_MT7620)
++#define REG_ESW_MAX 0x7FFFF
++#else //RT305x, RT3350
++#define REG_ESW_MAX 0xFC
++#endif
++#define REG_HQOS_MAX 0x3FFF
++
++
++typedef struct rt3052_esw_reg {
++ unsigned int off;
++ unsigned int val;
++} esw_reg;
++
++typedef struct ralink_mii_ioctl_data {
++ __u32 phy_id;
++ __u32 reg_num;
++ __u32 val_in;
++ __u32 val_out;
++ __u32 port_num;
++ __u32 dev_addr;
++ __u32 reg_addr;
++} ra_mii_ioctl_data;
++
++typedef struct rt335x_esw_reg {
++ unsigned int on_off;
++ unsigned int port;
++ unsigned int bw;/*Mbps*/
++} esw_rate;
++
++
++#endif
+diff --git a/drivers/net/ethernet/raeth/ra_mac.c b/drivers/net/ethernet/raeth/ra_mac.c
+new file mode 100644
+index 0000000..e8e978d
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_mac.c
+@@ -0,0 +1,2645 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/fcntl.h>
++#include <linux/interrupt.h>
++#include <linux/ptrace.h>
++#include <linux/ioport.h>
++#include <linux/in.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/signal.h>
++#include <linux/irq.h>
++#include <linux/ctype.h>
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,4)
++#include <asm/system.h>
++#include <linux/mca.h>
++#endif
++#include <asm/io.h>
++#include <asm/bitops.h>
++#include <asm/io.h>
++#include <asm/dma.h>
++
++#include <asm/rt2880/surfboardint.h> /* for cp0 reg access, added by bobtseng */
++
++#include <linux/errno.h>
++#include <linux/init.h>
++
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/proc_fs.h>
++#include <asm/uaccess.h>
++
++#include <linux/seq_file.h>
++
++
++#if defined(CONFIG_RAETH_LRO)
++#include <linux/inet_lro.h>
++#endif
++
++#include "ra2882ethreg.h"
++#include "raether.h"
++#include "ra_mac.h"
++#include "ra_ethtool.h"
++#if defined(CONFIG_RAETH_PDMA_DVT)
++#include "dvt/raether_pdma_dvt.h"
++#endif //#if defined(CONFIG_RAETH_PDMA_DVT)
++
++extern struct net_device *dev_raether;
++
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined (CONFIG_RALINK_MT7620)
++extern unsigned short p0_rx_good_cnt;
++extern unsigned short p0_tx_good_cnt;
++extern unsigned short p1_rx_good_cnt;
++extern unsigned short p1_tx_good_cnt;
++extern unsigned short p2_rx_good_cnt;
++extern unsigned short p2_tx_good_cnt;
++extern unsigned short p3_rx_good_cnt;
++extern unsigned short p3_tx_good_cnt;
++extern unsigned short p4_rx_good_cnt;
++extern unsigned short p4_tx_good_cnt;
++extern unsigned short p5_rx_good_cnt;
++extern unsigned short p5_tx_good_cnt;
++extern unsigned short p6_rx_good_cnt;
++extern unsigned short p6_tx_good_cnt;
++
++extern unsigned short p0_rx_byte_cnt;
++extern unsigned short p1_rx_byte_cnt;
++extern unsigned short p2_rx_byte_cnt;
++extern unsigned short p3_rx_byte_cnt;
++extern unsigned short p4_rx_byte_cnt;
++extern unsigned short p5_rx_byte_cnt;
++extern unsigned short p6_rx_byte_cnt;
++extern unsigned short p0_tx_byte_cnt;
++extern unsigned short p1_tx_byte_cnt;
++extern unsigned short p2_tx_byte_cnt;
++extern unsigned short p3_tx_byte_cnt;
++extern unsigned short p4_tx_byte_cnt;
++extern unsigned short p5_tx_byte_cnt;
++extern unsigned short p6_tx_byte_cnt;
++
++#if defined(CONFIG_RALINK_MT7620)
++extern unsigned short p7_rx_good_cnt;
++extern unsigned short p7_tx_good_cnt;
++extern unsigned short p7_rx_byte_cnt;
++extern unsigned short p7_tx_byte_cnt;
++#endif
++#endif
++
++
++
++#if defined(CONFIG_RAETH_TSO)
++int txd_cnt[MAX_SKB_FRAGS/2 + 1];
++int tso_cnt[16];
++#endif
++
++#if defined(CONFIG_RAETH_LRO)
++#define MAX_AGGR 64
++#define MAX_DESC 8
++int lro_stats_cnt[MAX_AGGR + 1];
++int lro_flush_cnt[MAX_AGGR + 1];
++int lro_len_cnt1[16];
++//int lro_len_cnt2[16];
++int aggregated[MAX_DESC];
++int lro_aggregated;
++int lro_flushed;
++int lro_nodesc;
++int force_flush;
++int tot_called1;
++int tot_called2;
++#endif
++
++#if defined(CONFIG_RAETH_HW_LRO)
++#define HW_LRO_RING_NUM 3
++#define MAX_HW_LRO_AGGR 64
++unsigned int hw_lro_agg_num_cnt[HW_LRO_RING_NUM][MAX_HW_LRO_AGGR + 1];
++unsigned int hw_lro_agg_size_cnt[HW_LRO_RING_NUM][16];
++unsigned int hw_lro_tot_agg_cnt[HW_LRO_RING_NUM];
++unsigned int hw_lro_tot_flush_cnt[HW_LRO_RING_NUM];
++#if defined(CONFIG_RAETH_HW_LRO_REASON_DBG)
++unsigned int hw_lro_agg_flush_cnt[HW_LRO_RING_NUM];
++unsigned int hw_lro_age_flush_cnt[HW_LRO_RING_NUM];
++unsigned int hw_lro_seq_flush_cnt[HW_LRO_RING_NUM];
++unsigned int hw_lro_timestamp_flush_cnt[HW_LRO_RING_NUM];
++unsigned int hw_lro_norule_flush_cnt[HW_LRO_RING_NUM];
++#endif /* CONFIG_RAETH_HW_LRO_REASON_DBG */
++#endif /* CONFIG_RAETH_HW_LRO */
++
++#if defined(CONFIG_RAETH_QDMA)
++extern unsigned int M2Q_table[64];
++extern struct QDMA_txdesc *free_head;
++#endif
++#if defined (CONFIG_ARCH_MT7623)
++extern struct SFQ_table *sfq0;
++extern struct SFQ_table *sfq1;
++extern struct SFQ_table *sfq2;
++extern struct SFQ_table *sfq3;
++#endif
++
++#if defined(CONFIG_USER_SNMPD)
++
++static int ra_snmp_seq_show(struct seq_file *seq, void *v)
++{
++#if !defined(CONFIG_RALINK_RT5350) && !defined(CONFIG_RALINK_MT7620) && !defined (CONFIG_RALINK_MT7628)
++
++ seq_printf(seq, "rx counters: %x %x %x %x %x %x %x\n", sysRegRead(GDMA_RX_GBCNT0), sysRegRead(GDMA_RX_GPCNT0),sysRegRead(GDMA_RX_OERCNT0), sysRegRead(GDMA_RX_FERCNT0), sysRegRead(GDMA_RX_SERCNT0), sysRegRead(GDMA_RX_LERCNT0), sysRegRead(GDMA_RX_CERCNT0));
++
++ seq_printf(seq, "fc config: %x %x %x %x\n", sysRegRead(CDMA_FC_CFG), sysRegRead(GDMA1_FC_CFG), PDMA_FC_CFG, sysRegRead(PDMA_FC_CFG));
++
++ seq_printf(seq, "scheduler: %x %x %x\n", sysRegRead(GDMA1_SCH_CFG), sysRegRead(GDMA2_SCH_CFG), sysRegRead(PDMA_SCH_CFG));
++
++#endif
++ seq_printf(seq, "ports: %x %x %x %x %x %x\n", sysRegRead(PORT0_PKCOUNT), sysRegRead(PORT1_PKCOUNT), sysRegRead(PORT2_PKCOUNT), sysRegRead(PORT3_PKCOUNT), sysRegRead(PORT4_PKCOUNT), sysRegRead(PORT5_PKCOUNT));
++
++ return 0;
++}
++
++static int ra_snmp_seq_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, ra_snmp_seq_show, NULL);
++}
++
++static const struct file_operations ra_snmp_seq_fops = {
++ .owner = THIS_MODULE,
++ .open = ra_snmp_seq_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release
++};
++#endif
++
++
++#if defined (CONFIG_GIGAPHY) || defined (CONFIG_100PHY) || \
++ defined (CONFIG_P5_MAC_TO_PHY_MODE) || defined (CONFIG_RAETH_GMAC2)
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined (CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || \
++ defined (CONFIG_ARCH_MT7623)
++void enable_auto_negotiate(int unused)
++{
++ u32 regValue;
++#if !defined (CONFIG_RALINK_MT7621) && !defined (CONFIG_ARCH_MT7623)
++ u32 addr = CONFIG_MAC_TO_GIGAPHY_MODE_ADDR;
++#endif
++
++#if defined (CONFIG_RALINK_MT7621)
++ //enable MDIO mode all the time
++ regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60));
++ regValue &= ~(0x3 << 12);
++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue;
++#endif
++
++ /* FIXME: we don't know how to deal with PHY end addr */
++ regValue = sysRegRead(ESW_PHY_POLLING);
++ regValue |= (1<<31);
++ regValue &= ~(0x1f);
++ regValue &= ~(0x1f<<8);
++#if defined (CONFIG_RALINK_MT7620)
++ regValue |= ((addr-1) << 0);//setup PHY address for auto polling (Start Addr).
++ regValue |= (addr << 8);// setup PHY address for auto polling (End Addr).
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN)|| defined (CONFIG_GE_RGMII_INTERNAL_P4_AN) || defined (CONFIG_GE2_RGMII_AN)
++ regValue |= ((CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2-1)&0x1f << 0);//setup PHY address for auto polling (Start Addr).
++ regValue |= (CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2 << 8);// setup PHY address for auto polling (End Addr).
++#else
++ regValue |= (CONFIG_MAC_TO_GIGAPHY_MODE_ADDR << 0);//setup PHY address for auto polling (Start Addr).
++ regValue |= (CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2 << 8);// setup PHY address for auto polling (End Addr).
++#endif
++#else
++ regValue |= (addr << 0);// setup PHY address for auto polling (start Addr).
++ regValue |= (addr << 8);// setup PHY address for auto polling (End Addr).
++#endif
++
++ /*kurtis: AN is strange*/
++ sysRegWrite(ESW_PHY_POLLING, regValue);
++
++#if defined (CONFIG_P4_MAC_TO_PHY_MODE)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x56330;
++#endif
++#if defined (CONFIG_P5_MAC_TO_PHY_MODE)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x56330;
++#endif
++}
++#elif defined (CONFIG_RALINK_RT2880) || defined(CONFIG_RALINK_RT3883) || \
++ defined (CONFIG_RALINK_RT3052) || defined(CONFIG_RALINK_RT3352)
++
++void enable_auto_negotiate(int ge)
++{
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352)
++ u32 regValue = sysRegRead(0xb01100C8);
++#else
++ u32 regValue;
++ regValue = (ge == 2)? sysRegRead(MDIO_CFG2) : sysRegRead(MDIO_CFG);
++#endif
++
++ regValue &= 0xe0ff7fff; // clear auto polling related field:
++ // (MD_PHY1ADDR & GP1_FRC_EN).
++ regValue |= 0x20000000; // force to enable MDC/MDIO auto polling.
++
++#if defined (CONFIG_GE2_RGMII_AN) || defined (CONFIG_GE2_MII_AN)
++ if(ge==2) {
++ regValue |= (CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2 << 24); // setup PHY address for auto polling.
++ }
++#endif
++#if defined (CONFIG_GE1_RGMII_AN) || defined (CONFIG_GE1_MII_AN) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
++ if(ge==1) {
++ regValue |= (CONFIG_MAC_TO_GIGAPHY_MODE_ADDR << 24); // setup PHY address for auto polling.
++ }
++#endif
++
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352)
++ sysRegWrite(0xb01100C8, regValue);
++#else
++ if (ge == 2)
++ sysRegWrite(MDIO_CFG2, regValue);
++ else
++ sysRegWrite(MDIO_CFG, regValue);
++#endif
++}
++#endif
++#endif
++void ra2880stop(END_DEVICE *ei_local)
++{
++ unsigned int regValue;
++ printk("ra2880stop()...");
++
++ regValue = sysRegRead(DMA_GLO_CFG);
++ regValue &= ~(TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN);
++ sysRegWrite(DMA_GLO_CFG, regValue);
++
++ printk("Done\n");
++ // printk("Done0x%x...\n", readreg(DMA_GLO_CFG));
++}
++
++void ei_irq_clear(void)
++{
++ sysRegWrite(FE_INT_STATUS, 0xFFFFFFFF);
++}
++
++void rt2880_gmac_hard_reset(void)
++{
++#if !defined (CONFIG_RALINK_RT6855A)
++ //FIXME
++ sysRegWrite(RSTCTRL, RALINK_FE_RST);
++ sysRegWrite(RSTCTRL, 0);
++#endif
++}
++
++void ra2880EnableInterrupt()
++{
++ unsigned int regValue = sysRegRead(FE_INT_ENABLE);
++ RAETH_PRINT("FE_INT_ENABLE -- : 0x%08x\n", regValue);
++// regValue |= (RX_DONE_INT0 | TX_DONE_INT0);
++
++ sysRegWrite(FE_INT_ENABLE, regValue);
++}
++
++void ra2880MacAddressSet(unsigned char p[6])
++{
++ unsigned long regValue;
++
++ regValue = (p[0] << 8) | (p[1]);
++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++ sysRegWrite(SDM_MAC_ADRH, regValue);
++ printk("GMAC1_MAC_ADRH -- : 0x%08x\n", sysRegRead(SDM_MAC_ADRH));
++#elif defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A)
++ sysRegWrite(GDMA1_MAC_ADRH, regValue);
++ printk("GMAC1_MAC_ADRH -- : 0x%08x\n", sysRegRead(GDMA1_MAC_ADRH));
++
++ /* To keep the consistence between RT6855 and RT62806, GSW should keep the register. */
++ sysRegWrite(SMACCR1, regValue);
++ printk("SMACCR1 -- : 0x%08x\n", sysRegRead(SMACCR1));
++#elif defined (CONFIG_RALINK_MT7620)
++ sysRegWrite(SMACCR1, regValue);
++ printk("SMACCR1 -- : 0x%08x\n", sysRegRead(SMACCR1));
++#else
++ sysRegWrite(GDMA1_MAC_ADRH, regValue);
++ printk("GMAC1_MAC_ADRH -- : 0x%08x\n", sysRegRead(GDMA1_MAC_ADRH));
++#endif
++
++ regValue = (p[2] << 24) | (p[3] <<16) | (p[4] << 8) | p[5];
++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++ sysRegWrite(SDM_MAC_ADRL, regValue);
++ printk("GMAC1_MAC_ADRL -- : 0x%08x\n", sysRegRead(SDM_MAC_ADRL));
++#elif defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A)
++ sysRegWrite(GDMA1_MAC_ADRL, regValue);
++ printk("GMAC1_MAC_ADRL -- : 0x%08x\n", sysRegRead(GDMA1_MAC_ADRL));
++
++ /* To keep the consistence between RT6855 and RT62806, GSW should keep the register. */
++ sysRegWrite(SMACCR0, regValue);
++ printk("SMACCR0 -- : 0x%08x\n", sysRegRead(SMACCR0));
++#elif defined (CONFIG_RALINK_MT7620)
++ sysRegWrite(SMACCR0, regValue);
++ printk("SMACCR0 -- : 0x%08x\n", sysRegRead(SMACCR0));
++#else
++ sysRegWrite(GDMA1_MAC_ADRL, regValue);
++ printk("GMAC1_MAC_ADRL -- : 0x%08x\n", sysRegRead(GDMA1_MAC_ADRL));
++#endif
++
++ return;
++}
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++void ra2880Mac2AddressSet(unsigned char p[6])
++{
++ unsigned long regValue;
++
++ regValue = (p[0] << 8) | (p[1]);
++ sysRegWrite(GDMA2_MAC_ADRH, regValue);
++
++ regValue = (p[2] << 24) | (p[3] <<16) | (p[4] << 8) | p[5];
++ sysRegWrite(GDMA2_MAC_ADRL, regValue);
++
++ printk("GDMA2_MAC_ADRH -- : 0x%08x\n", sysRegRead(GDMA2_MAC_ADRH));
++ printk("GDMA2_MAC_ADRL -- : 0x%08x\n", sysRegRead(GDMA2_MAC_ADRL));
++ return;
++}
++#endif
++
++/**
++ * hard_init - Called by raeth_probe to inititialize network device
++ * @dev: device pointer
++ *
++ * ethdev_init initilize dev->priv and set to END_DEVICE structure
++ *
++ */
++void ethtool_init(struct net_device *dev)
++{
++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
++ END_DEVICE *ei_local = netdev_priv(dev);
++
++ // init mii structure
++ ei_local->mii_info.dev = dev;
++ ei_local->mii_info.mdio_read = mdio_read;
++ ei_local->mii_info.mdio_write = mdio_write;
++ ei_local->mii_info.phy_id_mask = 0x1f;
++ ei_local->mii_info.reg_num_mask = 0x1f;
++ ei_local->mii_info.supports_gmii = mii_check_gmii_support(&ei_local->mii_info);
++ // TODO: phy_id: 0~4
++ ei_local->mii_info.phy_id = 1;
++#endif
++ return;
++}
++
++/*
++ * Routine Name : get_idx(mode, index)
++ * Description: calculate ring usage for tx/rx rings
++ * Mode 1 : Tx Ring
++ * Mode 2 : Rx Ring
++ */
++int get_ring_usage(int mode, int i)
++{
++ unsigned long tx_ctx_idx, tx_dtx_idx, tx_usage;
++ unsigned long rx_calc_idx, rx_drx_idx, rx_usage;
++
++ struct PDMA_rxdesc* rxring;
++ struct PDMA_txdesc* txring;
++
++ END_DEVICE *ei_local = netdev_priv(dev_raether);
++
++
++ if (mode == 2 ) {
++ /* cpu point to the next descriptor of rx dma ring */
++ rx_calc_idx = *(unsigned long*)RX_CALC_IDX0;
++ rx_drx_idx = *(unsigned long*)RX_DRX_IDX0;
++ rxring = (struct PDMA_rxdesc*)RX_BASE_PTR0;
++
++ rx_usage = (rx_drx_idx - rx_calc_idx -1 + NUM_RX_DESC) % NUM_RX_DESC;
++ if ( rx_calc_idx == rx_drx_idx ) {
++ if ( rxring[rx_drx_idx].rxd_info2.DDONE_bit == 1)
++ tx_usage = NUM_RX_DESC;
++ else
++ tx_usage = 0;
++ }
++ return rx_usage;
++ }
++
++
++ switch (i) {
++ case 0:
++ tx_ctx_idx = *(unsigned long*)TX_CTX_IDX0;
++ tx_dtx_idx = *(unsigned long*)TX_DTX_IDX0;
++ txring = ei_local->tx_ring0;
++ break;
++#if defined(CONFIG_RAETH_QOS)
++ case 1:
++ tx_ctx_idx = *(unsigned long*)TX_CTX_IDX1;
++ tx_dtx_idx = *(unsigned long*)TX_DTX_IDX1;
++ txring = ei_local->tx_ring1;
++ break;
++ case 2:
++ tx_ctx_idx = *(unsigned long*)TX_CTX_IDX2;
++ tx_dtx_idx = *(unsigned long*)TX_DTX_IDX2;
++ txring = ei_local->tx_ring2;
++ break;
++ case 3:
++ tx_ctx_idx = *(unsigned long*)TX_CTX_IDX3;
++ tx_dtx_idx = *(unsigned long*)TX_DTX_IDX3;
++ txring = ei_local->tx_ring3;
++ break;
++#endif
++ default:
++ printk("get_tx_idx failed %d %d\n", mode, i);
++ return 0;
++ };
++
++ tx_usage = (tx_ctx_idx - tx_dtx_idx + NUM_TX_DESC) % NUM_TX_DESC;
++ if ( tx_ctx_idx == tx_dtx_idx ) {
++ if ( txring[tx_ctx_idx].txd_info2.DDONE_bit == 1)
++ tx_usage = 0;
++ else
++ tx_usage = NUM_TX_DESC;
++ }
++ return tx_usage;
++
++}
++
++#if defined(CONFIG_RAETH_QOS)
++void dump_qos(struct seq_file *s)
++{
++ int usage;
++ int i;
++
++ seq_printf(s, "\n-----Raeth QOS -----\n\n");
++
++ for ( i = 0; i < 4; i++) {
++ usage = get_ring_usage(1,i);
++ seq_printf(s, "Tx Ring%d Usage : %d/%d\n", i, usage, NUM_TX_DESC);
++ }
++
++ usage = get_ring_usage(2,0);
++ seq_printf(s, "RX Usage : %d/%d\n\n", usage, NUM_RX_DESC);
++#if defined (CONFIG_RALINK_MT7620)
++ seq_printf(s, "PSE_FQFC_CFG(0x%08x) : 0x%08x\n", PSE_FQFC_CFG, sysRegRead(PSE_FQFC_CFG));
++ seq_printf(s, "PSE_IQ_CFG(0x%08x) : 0x%08x\n", PSE_IQ_CFG, sysRegRead(PSE_IQ_CFG));
++ seq_printf(s, "PSE_QUE_STA(0x%08x) : 0x%08x\n", PSE_QUE_STA, sysRegRead(PSE_QUE_STA));
++#elif defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++
++#else
++ seq_printf(s, "GDMA1_FC_CFG(0x%08x) : 0x%08x\n", GDMA1_FC_CFG, sysRegRead(GDMA1_FC_CFG));
++ seq_printf(s, "GDMA2_FC_CFG(0x%08x) : 0x%08x\n", GDMA2_FC_CFG, sysRegRead(GDMA2_FC_CFG));
++ seq_printf(s, "PDMA_FC_CFG(0x%08x) : 0x%08x\n", PDMA_FC_CFG, sysRegRead(PDMA_FC_CFG));
++ seq_printf(s, "PSE_FQ_CFG(0x%08x) : 0x%08x\n", PSE_FQ_CFG, sysRegRead(PSE_FQ_CFG));
++#endif
++ seq_printf(s, "\n\nTX_CTX_IDX0 : 0x%08x\n", sysRegRead(TX_CTX_IDX0));
++ seq_printf(s, "TX_DTX_IDX0 : 0x%08x\n", sysRegRead(TX_DTX_IDX0));
++ seq_printf(s, "TX_CTX_IDX1 : 0x%08x\n", sysRegRead(TX_CTX_IDX1));
++ seq_printf(s, "TX_DTX_IDX1 : 0x%08x\n", sysRegRead(TX_DTX_IDX1));
++ seq_printf(s, "TX_CTX_IDX2 : 0x%08x\n", sysRegRead(TX_CTX_IDX2));
++ seq_printf(s, "TX_DTX_IDX2 : 0x%08x\n", sysRegRead(TX_DTX_IDX2));
++ seq_printf(s, "TX_CTX_IDX3 : 0x%08x\n", sysRegRead(TX_CTX_IDX3));
++ seq_printf(s, "TX_DTX_IDX3 : 0x%08x\n", sysRegRead(TX_DTX_IDX3));
++ seq_printf(s, "RX_CALC_IDX0 : 0x%08x\n", sysRegRead(RX_CALC_IDX0));
++ seq_printf(s, "RX_DRX_IDX0 : 0x%08x\n", sysRegRead(RX_DRX_IDX0));
++
++ seq_printf(s, "\n------------------------------\n\n");
++}
++#endif
++
++void dump_reg(struct seq_file *s)
++{
++ int fe_int_enable;
++ int rx_usage;
++ int dly_int_cfg;
++ int rx_base_ptr0;
++ int rx_max_cnt0;
++ int rx_calc_idx0;
++ int rx_drx_idx0;
++#if !defined (CONFIG_RAETH_QDMA)
++ int tx_usage;
++ int tx_base_ptr[4];
++ int tx_max_cnt[4];
++ int tx_ctx_idx[4];
++ int tx_dtx_idx[4];
++ int i;
++#endif
++
++ fe_int_enable = sysRegRead(FE_INT_ENABLE);
++ rx_usage = get_ring_usage(2,0);
++
++ dly_int_cfg = sysRegRead(DLY_INT_CFG);
++
++#if !defined (CONFIG_RAETH_QDMA)
++ tx_usage = get_ring_usage(1,0);
++
++ tx_base_ptr[0] = sysRegRead(TX_BASE_PTR0);
++ tx_max_cnt[0] = sysRegRead(TX_MAX_CNT0);
++ tx_ctx_idx[0] = sysRegRead(TX_CTX_IDX0);
++ tx_dtx_idx[0] = sysRegRead(TX_DTX_IDX0);
++
++ tx_base_ptr[1] = sysRegRead(TX_BASE_PTR1);
++ tx_max_cnt[1] = sysRegRead(TX_MAX_CNT1);
++ tx_ctx_idx[1] = sysRegRead(TX_CTX_IDX1);
++ tx_dtx_idx[1] = sysRegRead(TX_DTX_IDX1);
++
++ tx_base_ptr[2] = sysRegRead(TX_BASE_PTR2);
++ tx_max_cnt[2] = sysRegRead(TX_MAX_CNT2);
++ tx_ctx_idx[2] = sysRegRead(TX_CTX_IDX2);
++ tx_dtx_idx[2] = sysRegRead(TX_DTX_IDX2);
++
++ tx_base_ptr[3] = sysRegRead(TX_BASE_PTR3);
++ tx_max_cnt[3] = sysRegRead(TX_MAX_CNT3);
++ tx_ctx_idx[3] = sysRegRead(TX_CTX_IDX3);
++ tx_dtx_idx[3] = sysRegRead(TX_DTX_IDX3);
++#endif
++
++ rx_base_ptr0 = sysRegRead(RX_BASE_PTR0);
++ rx_max_cnt0 = sysRegRead(RX_MAX_CNT0);
++ rx_calc_idx0 = sysRegRead(RX_CALC_IDX0);
++ rx_drx_idx0 = sysRegRead(RX_DRX_IDX0);
++
++ seq_printf(s, "\n\nFE_INT_ENABLE : 0x%08x\n", fe_int_enable);
++#if !defined (CONFIG_RAETH_QDMA)
++ seq_printf(s, "TxRing PktCnt: %d/%d\n", tx_usage, NUM_TX_DESC);
++#endif
++ seq_printf(s, "RxRing PktCnt: %d/%d\n\n", rx_usage, NUM_RX_DESC);
++ seq_printf(s, "DLY_INT_CFG : 0x%08x\n", dly_int_cfg);
++
++#if !defined (CONFIG_RAETH_QDMA)
++ for(i=0;i<4;i++) {
++ seq_printf(s, "TX_BASE_PTR%d : 0x%08x\n", i, tx_base_ptr[i]);
++ seq_printf(s, "TX_MAX_CNT%d : 0x%08x\n", i, tx_max_cnt[i]);
++ seq_printf(s, "TX_CTX_IDX%d : 0x%08x\n", i, tx_ctx_idx[i]);
++ seq_printf(s, "TX_DTX_IDX%d : 0x%08x\n", i, tx_dtx_idx[i]);
++ }
++#endif
++
++ seq_printf(s, "RX_BASE_PTR0 : 0x%08x\n", rx_base_ptr0);
++ seq_printf(s, "RX_MAX_CNT0 : 0x%08x\n", rx_max_cnt0);
++ seq_printf(s, "RX_CALC_IDX0 : 0x%08x\n", rx_calc_idx0);
++ seq_printf(s, "RX_DRX_IDX0 : 0x%08x\n", rx_drx_idx0);
++
++#if defined (CONFIG_ETHTOOL) && defined (CONFIG_RAETH_ROUTER)
++ seq_printf(s, "The current PHY address selected by ethtool is %d\n", get_current_phy_address());
++#endif
++
++#if defined (CONFIG_RALINK_RT2883) || defined(CONFIG_RALINK_RT3883)
++ seq_printf(s, "GDMA_RX_FCCNT1(0x%08x) : 0x%08x\n\n", GDMA_RX_FCCNT1, sysRegRead(GDMA_RX_FCCNT1));
++#endif
++}
++
++#if 0
++void dump_cp0(void)
++{
++ printk("CP0 Register dump --\n");
++ printk("CP0_INDEX\t: 0x%08x\n", read_32bit_cp0_register(CP0_INDEX));
++ printk("CP0_RANDOM\t: 0x%08x\n", read_32bit_cp0_register(CP0_RANDOM));
++ printk("CP0_ENTRYLO0\t: 0x%08x\n", read_32bit_cp0_register(CP0_ENTRYLO0));
++ printk("CP0_ENTRYLO1\t: 0x%08x\n", read_32bit_cp0_register(CP0_ENTRYLO1));
++ printk("CP0_CONF\t: 0x%08x\n", read_32bit_cp0_register(CP0_CONF));
++ printk("CP0_CONTEXT\t: 0x%08x\n", read_32bit_cp0_register(CP0_CONTEXT));
++ printk("CP0_PAGEMASK\t: 0x%08x\n", read_32bit_cp0_register(CP0_PAGEMASK));
++ printk("CP0_WIRED\t: 0x%08x\n", read_32bit_cp0_register(CP0_WIRED));
++ printk("CP0_INFO\t: 0x%08x\n", read_32bit_cp0_register(CP0_INFO));
++ printk("CP0_BADVADDR\t: 0x%08x\n", read_32bit_cp0_register(CP0_BADVADDR));
++ printk("CP0_COUNT\t: 0x%08x\n", read_32bit_cp0_register(CP0_COUNT));
++ printk("CP0_ENTRYHI\t: 0x%08x\n", read_32bit_cp0_register(CP0_ENTRYHI));
++ printk("CP0_COMPARE\t: 0x%08x\n", read_32bit_cp0_register(CP0_COMPARE));
++ printk("CP0_STATUS\t: 0x%08x\n", read_32bit_cp0_register(CP0_STATUS));
++ printk("CP0_CAUSE\t: 0x%08x\n", read_32bit_cp0_register(CP0_CAUSE));
++ printk("CP0_EPC\t: 0x%08x\n", read_32bit_cp0_register(CP0_EPC));
++ printk("CP0_PRID\t: 0x%08x\n", read_32bit_cp0_register(CP0_PRID));
++ printk("CP0_CONFIG\t: 0x%08x\n", read_32bit_cp0_register(CP0_CONFIG));
++ printk("CP0_LLADDR\t: 0x%08x\n", read_32bit_cp0_register(CP0_LLADDR));
++ printk("CP0_WATCHLO\t: 0x%08x\n", read_32bit_cp0_register(CP0_WATCHLO));
++ printk("CP0_WATCHHI\t: 0x%08x\n", read_32bit_cp0_register(CP0_WATCHHI));
++ printk("CP0_XCONTEXT\t: 0x%08x\n", read_32bit_cp0_register(CP0_XCONTEXT));
++ printk("CP0_FRAMEMASK\t: 0x%08x\n", read_32bit_cp0_register(CP0_FRAMEMASK));
++ printk("CP0_DIAGNOSTIC\t: 0x%08x\n", read_32bit_cp0_register(CP0_DIAGNOSTIC));
++ printk("CP0_DEBUG\t: 0x%08x\n", read_32bit_cp0_register(CP0_DEBUG));
++ printk("CP0_DEPC\t: 0x%08x\n", read_32bit_cp0_register(CP0_DEPC));
++ printk("CP0_PERFORMANCE\t: 0x%08x\n", read_32bit_cp0_register(CP0_PERFORMANCE));
++ printk("CP0_ECC\t: 0x%08x\n", read_32bit_cp0_register(CP0_ECC));
++ printk("CP0_CACHEERR\t: 0x%08x\n", read_32bit_cp0_register(CP0_CACHEERR));
++ printk("CP0_TAGLO\t: 0x%08x\n", read_32bit_cp0_register(CP0_TAGLO));
++ printk("CP0_TAGHI\t: 0x%08x\n", read_32bit_cp0_register(CP0_TAGHI));
++ printk("CP0_ERROREPC\t: 0x%08x\n", read_32bit_cp0_register(CP0_ERROREPC));
++ printk("CP0_DESAVE\t: 0x%08x\n\n", read_32bit_cp0_register(CP0_DESAVE));
++}
++#endif
++
++struct proc_dir_entry *procRegDir;
++static struct proc_dir_entry *procGmac, *procSysCP0, *procTxRing, *procRxRing, *procSkbFree;
++#if defined(CONFIG_PSEUDO_SUPPORT) && defined(CONFIG_ETHTOOL)
++static struct proc_dir_entry *procGmac2;
++#endif
++#if defined(CONFIG_USER_SNMPD)
++static struct proc_dir_entry *procRaSnmp;
++#endif
++#if defined(CONFIG_RAETH_TSO)
++static struct proc_dir_entry *procNumOfTxd, *procTsoLen;
++#endif
++
++#if defined(CONFIG_RAETH_LRO)
++static struct proc_dir_entry *procLroStats;
++#endif
++#if defined(CONFIG_RAETH_HW_LRO) || defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++static struct proc_dir_entry *procRxRing1, *procRxRing2, *procRxRing3;
++static struct proc_dir_entry *procHwLroStats, *procHwLroAutoTlb;
++const static HWLRO_DBG_FUNC hw_lro_dbg_func[] =
++{
++ [0] = hwlro_agg_cnt_ctrl,
++ [1] = hwlro_agg_time_ctrl,
++ [2] = hwlro_age_time_ctrl,
++ [3] = hwlro_pkt_int_alpha_ctrl,
++ [4] = hwlro_threshold_ctrl,
++ [5] = hwlro_fix_setting_switch_ctrl,
++};
++#endif /* CONFIG_RAETH_HW_LRO */
++#if defined (TASKLET_WORKQUEUE_SW)
++static struct proc_dir_entry *procSCHE;
++#endif
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++static struct proc_dir_entry *procPdmaDvt;
++
++const static PDMA_DBG_FUNC pdma_dvt_dbg_func[] =
++{
++ [0] = pdma_dvt_show_ctrl,
++ [1] = pdma_dvt_test_rx_ctrl,
++ [2] = pdma_dvt_test_tx_ctrl,
++ [3] = pdma_dvt_test_debug_ctrl,
++ [4] = pdma_dvt_test_lro_ctrl,
++};
++#endif //#if defined(CONFIG_RAETH_PDMA_DVT)
++
++int RegReadMain(struct seq_file *seq, void *v)
++{
++ dump_reg(seq);
++ return 0;
++}
++
++static void *seq_SkbFree_start(struct seq_file *seq, loff_t *pos)
++{
++ if (*pos < NUM_TX_DESC)
++ return pos;
++ return NULL;
++}
++
++static void *seq_SkbFree_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++ (*pos)++;
++ if (*pos >= NUM_TX_DESC)
++ return NULL;
++ return pos;
++}
++
++static void seq_SkbFree_stop(struct seq_file *seq, void *v)
++{
++ /* Nothing to do */
++}
++
++static int seq_SkbFree_show(struct seq_file *seq, void *v)
++{
++ int i = *(loff_t *) v;
++ END_DEVICE *ei_local = netdev_priv(dev_raether);
++
++ seq_printf(seq, "%d: %08x\n",i, *(int *)&ei_local->skb_free[i]);
++
++ return 0;
++}
++
++static const struct seq_operations seq_skb_free_ops = {
++ .start = seq_SkbFree_start,
++ .next = seq_SkbFree_next,
++ .stop = seq_SkbFree_stop,
++ .show = seq_SkbFree_show
++};
++
++static int skb_free_open(struct inode *inode, struct file *file)
++{
++ return seq_open(file, &seq_skb_free_ops);
++}
++
++static const struct file_operations skb_free_fops = {
++ .owner = THIS_MODULE,
++ .open = skb_free_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = seq_release
++};
++
++#if defined (CONFIG_RAETH_QDMA)
++int QDMARead(struct seq_file *seq, void *v)
++{
++ unsigned int temp,i;
++ unsigned int sw_fq, hw_fq;
++ unsigned int min_en, min_rate, max_en, max_rate, sch, weight;
++ unsigned int queue, tx_des_cnt, hw_resv, sw_resv, queue_head, queue_tail;
++ struct net_device *dev = dev_raether;
++ END_DEVICE *ei_local = netdev_priv(dev);
++
++ seq_printf(seq, "==== General Information ====\n");
++ temp = sysRegRead(QDMA_FQ_CNT);
++ sw_fq = (temp&0xFFFF0000)>>16;
++ hw_fq = (temp&0x0000FFFF);
++ seq_printf(seq, "SW TXD: %d/%d; HW TXD: %d/%d\n", sw_fq, NUM_TX_DESC, hw_fq,NUM_QDMA_PAGE);
++ seq_printf(seq, "SW TXD virtual start address: 0x%08x\n", ei_local->txd_pool);
++ seq_printf(seq, "HW TXD virtual start address: 0x%08x\n\n", free_head);
++
++ seq_printf(seq, "==== Scheduler Information ====\n");
++ temp = sysRegRead(QDMA_TX_SCH);
++ max_en = (temp&0x00000800)>>11;
++ max_rate = (temp&0x000007F0)>>4;
++ for(i=0;i<(temp&0x0000000F);i++)
++ max_rate *= 10;
++ seq_printf(seq, "SCH1 rate control:%d. Rate is %dKbps.\n", max_en, max_rate);
++ max_en = (temp&0x08000000)>>27;
++ max_rate = (temp&0x07F00000)>>20;
++ for(i=0;i<(temp&0x000F0000);i++)
++ max_rate *= 10;
++ seq_printf(seq, "SCH2 rate control:%d. Rate is %dKbps.\n\n", max_en, max_rate);
++
++ seq_printf(seq, "==== Physical Queue Information ====\n");
++ for (queue = 0; queue < 16; queue++){
++ temp = sysRegRead(QTX_CFG_0 + 0x10 * queue);
++ tx_des_cnt = (temp & 0xffff0000) >> 16;
++ hw_resv = (temp & 0xff00) >> 8;
++ sw_resv = (temp & 0xff);
++ temp = sysRegRead(QTX_CFG_0 +(0x10 * queue) + 0x4);
++ sch = (temp >> 31) + 1 ;
++ min_en = (temp & 0x8000000) >> 27;
++ min_rate = (temp & 0x7f00000) >> 20;
++ for (i = 0; i< (temp & 0xf0000) >> 16; i++)
++ min_rate *= 10;
++ max_en = (temp & 0x800) >> 11;
++ max_rate = (temp & 0x7f0) >> 4;
++ for (i = 0; i< (temp & 0xf); i++)
++ max_rate *= 10;
++ weight = (temp & 0xf000) >> 12;
++ queue_head = sysRegRead(QTX_HEAD_0 + 0x10 * queue);
++ queue_tail = sysRegRead(QTX_TAIL_0 + 0x10 * queue);
++
++ seq_printf(seq, "Queue#%d Information:\n", queue);
++ seq_printf(seq, "%d packets in the queue; head address is 0x%08x, tail address is 0x%08x.\n", tx_des_cnt, queue_head, queue_tail);
++ seq_printf(seq, "HW_RESV: %d; SW_RESV: %d; SCH: %d; Weighting: %d\n", hw_resv, sw_resv, sch, weight);
++ seq_printf(seq, "Min_Rate_En is %d, Min_Rate is %dKbps; Max_Rate_En is %d, Max_Rate is %dKbps.\n\n", min_en, min_rate, max_en, max_rate);
++ }
++#if defined (CONFIG_ARCH_MT7623) && defined(CONFIG_HW_SFQ)
++ seq_printf(seq, "==== Virtual Queue Information ====\n");
++ seq_printf(seq, "VQTX_TB_BASE_0:0x%08x;VQTX_TB_BASE_1:0x%08x;VQTX_TB_BASE_2:0x%08x;VQTX_TB_BASE_3:0x%08x\n", \
++ sfq0, sfq1, sfq2, sfq3);
++ temp = sysRegRead(VQTX_NUM);
++ seq_printf(seq, "VQTX_NUM_0:0x%01x;VQTX_NUM_1:0x%01x;VQTX_NUM_2:0x%01x;VQTX_NUM_3:0x%01x\n\n", \
++ temp&0xF, (temp&0xF0)>>4, (temp&0xF00)>>8, (temp&0xF000)>>12);
++
++#endif
++
++ seq_printf(seq, "==== Flow Control Information ====\n");
++ temp = sysRegRead(QDMA_FC_THRES);
++ seq_printf(seq, "SW_DROP_EN:%x; SW_DROP_FFA:%d; SW_DROP_MODE:%d\n", \
++ (temp&0x1000000)>>24, (temp&0x200000)>>25, (temp&0x30000000)>>28);
++ seq_printf(seq, "WH_DROP_EN:%x; HW_DROP_FFA:%d; HW_DROP_MODE:%d\n", \
++ (temp&0x10000)>>16, (temp&0x2000)>>17, (temp&0x300000)>>20);
++#if defined (CONFIG_ARCH_MT7623)
++ seq_printf(seq, "SW_DROP_FSTVQ_MODE:%d;SW_DROP_FSTVQ:%d\n", \
++ (temp&0xC0000000)>>30, (temp&0x08000000)>>27);
++ seq_printf(seq, "HW_DROP_FSTVQ_MODE:%d;HW_DROP_FSTVQ:%d\n", \
++ (temp&0xC00000)>>22, (temp&0x080000)>>19);
++#endif
++
++ seq_printf(seq, "\n==== FSM Information\n");
++ temp = sysRegRead(QDMA_DMA);
++#if defined (CONFIG_ARCH_MT7623)
++ seq_printf(seq, "VQTB_FSM:0x%01x\n", (temp&0x0F000000)>>24);
++#endif
++ seq_printf(seq, "FQ_FSM:0x%01x\n", (temp&0x000F0000)>>16);
++ seq_printf(seq, "TX_FSM:0x%01x\n", (temp&0x00000F00)>>12);
++ seq_printf(seq, "RX_FSM:0x%01x\n\n", (temp&0x0000000f));
++
++ seq_printf(seq, "==== M2Q Information ====\n");
++ for (i = 0; i < 64; i+=8){
++ seq_printf(seq, " (%d,%d)(%d,%d)(%d,%d)(%d,%d)(%d,%d)(%d,%d)(%d,%d)(%d,%d)\n",
++ i, M2Q_table[i], i+1, M2Q_table[i+1], i+2, M2Q_table[i+2], i+3, M2Q_table[i+3],
++ i+4, M2Q_table[i+4], i+5, M2Q_table[i+5], i+6, M2Q_table[i+6], i+7, M2Q_table[i+7]);
++ }
++
++ return 0;
++
++}
++
++static int qdma_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, QDMARead, NULL);
++}
++
++static const struct file_operations qdma_fops = {
++ .owner = THIS_MODULE,
++ .open = qdma_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release
++};
++#endif
++
++int TxRingRead(struct seq_file *seq, void *v)
++{
++ END_DEVICE *ei_local = netdev_priv(dev_raether);
++ struct PDMA_txdesc *tx_ring;
++ int i = 0;
++
++ tx_ring = kmalloc(sizeof(struct PDMA_txdesc) * NUM_TX_DESC, GFP_KERNEL);
++ if(tx_ring==NULL){
++ seq_printf(seq, " allocate temp tx_ring fail.\n");
++ return 0;
++ }
++
++ for (i=0; i < NUM_TX_DESC; i++) {
++ tx_ring[i] = ei_local->tx_ring0[i];
++ }
++
++ for (i=0; i < NUM_TX_DESC; i++) {
++#ifdef CONFIG_32B_DESC
++ seq_printf(seq, "%d: %08x %08x %08x %08x %08x %08x %08x %08x\n",i, *(int *)&tx_ring[i].txd_info1,
++ *(int *)&tx_ring[i].txd_info2, *(int *)&tx_ring[i].txd_info3,
++ *(int *)&tx_ring[i].txd_info4, *(int *)&tx_ring[i].txd_info5,
++ *(int *)&tx_ring[i].txd_info6, *(int *)&tx_ring[i].txd_info7,
++ *(int *)&tx_ring[i].txd_info8);
++#else
++ seq_printf(seq, "%d: %08x %08x %08x %08x\n",i, *(int *)&tx_ring[i].txd_info1, *(int *)&tx_ring[i].txd_info2,
++ *(int *)&tx_ring[i].txd_info3, *(int *)&tx_ring[i].txd_info4);
++#endif
++ }
++
++ kfree(tx_ring);
++ return 0;
++}
++
++static int tx_ring_open(struct inode *inode, struct file *file)
++{
++#if !defined (CONFIG_RAETH_QDMA)
++ return single_open(file, TxRingRead, NULL);
++#else
++ return single_open(file, QDMARead, NULL);
++#endif
++}
++
++static const struct file_operations tx_ring_fops = {
++ .owner = THIS_MODULE,
++ .open = tx_ring_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release
++};
++
++int RxRingRead(struct seq_file *seq, void *v)
++{
++ END_DEVICE *ei_local = netdev_priv(dev_raether);
++ struct PDMA_rxdesc *rx_ring;
++ int i = 0;
++
++ rx_ring = kmalloc(sizeof(struct PDMA_rxdesc) * NUM_RX_DESC, GFP_KERNEL);
++ if(rx_ring==NULL){
++ seq_printf(seq, " allocate temp rx_ring fail.\n");
++ return 0;
++ }
++
++ for (i=0; i < NUM_RX_DESC; i++) {
++ memcpy(&rx_ring[i], &ei_local->rx_ring0[i], sizeof(struct PDMA_rxdesc));
++ }
++
++ for (i=0; i < NUM_RX_DESC; i++) {
++#ifdef CONFIG_32B_DESC
++ seq_printf(seq, "%d: %08x %08x %08x %08x %08x %08x %08x %08x\n",i, *(int *)&rx_ring[i].rxd_info1,
++ *(int *)&rx_ring[i].rxd_info2, *(int *)&rx_ring[i].rxd_info3,
++ *(int *)&rx_ring[i].rxd_info4, *(int *)&rx_ring[i].rxd_info5,
++ *(int *)&rx_ring[i].rxd_info6, *(int *)&rx_ring[i].rxd_info7,
++ *(int *)&rx_ring[i].rxd_info8);
++#else
++ seq_printf(seq, "%d: %08x %08x %08x %08x\n",i, *(int *)&rx_ring[i].rxd_info1, *(int *)&rx_ring[i].rxd_info2,
++ *(int *)&rx_ring[i].rxd_info3, *(int *)&rx_ring[i].rxd_info4);
++#endif
++ }
++
++ kfree(rx_ring);
++ return 0;
++}
++
++static int rx_ring_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, RxRingRead, NULL);
++}
++
++static const struct file_operations rx_ring_fops = {
++ .owner = THIS_MODULE,
++ .open = rx_ring_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release
++};
++
++#if defined(CONFIG_RAETH_HW_LRO) || defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++int RxLRORingRead(struct seq_file *seq, void *v, struct PDMA_rxdesc *rx_ring_p)
++{
++ struct PDMA_rxdesc *rx_ring;
++ int i = 0;
++
++ rx_ring = kmalloc(sizeof(struct PDMA_rxdesc) * NUM_LRO_RX_DESC, GFP_KERNEL);
++ if(rx_ring==NULL){
++ seq_printf(seq, " allocate temp rx_ring fail.\n");
++ return 0;
++ }
++
++ for (i=0; i < NUM_LRO_RX_DESC; i++) {
++ memcpy(&rx_ring[i], &rx_ring_p[i], sizeof(struct PDMA_rxdesc));
++ }
++
++ for (i=0; i < NUM_LRO_RX_DESC; i++) {
++#ifdef CONFIG_32B_DESC
++ seq_printf(seq, "%d: %08x %08x %08x %08x %08x %08x %08x %08x\n",i, *(int *)&rx_ring[i].rxd_info1,
++ *(int *)&rx_ring[i].rxd_info2, *(int *)&rx_ring[i].rxd_info3,
++ *(int *)&rx_ring[i].rxd_info4, *(int *)&rx_ring[i].rxd_info5,
++ *(int *)&rx_ring[i].rxd_info6, *(int *)&rx_ring[i].rxd_info7,
++ *(int *)&rx_ring[i].rxd_info8);
++#else
++ seq_printf(seq, "%d: %08x %08x %08x %08x\n",i, *(int *)&rx_ring[i].rxd_info1, *(int *)&rx_ring[i].rxd_info2,
++ *(int *)&rx_ring[i].rxd_info3, *(int *)&rx_ring[i].rxd_info4);
++#endif
++ }
++
++ kfree(rx_ring);
++ return 0;
++}
++
++int RxRing1Read(struct seq_file *seq, void *v)
++{
++ END_DEVICE *ei_local = netdev_priv(dev_raether);
++ RxLRORingRead(seq, v, ei_local->rx_ring1);
++
++ return 0;
++}
++
++int RxRing2Read(struct seq_file *seq, void *v)
++{
++ END_DEVICE *ei_local = netdev_priv(dev_raether);
++ RxLRORingRead(seq, v, ei_local->rx_ring2);
++
++ return 0;
++}
++
++int RxRing3Read(struct seq_file *seq, void *v)
++{
++ END_DEVICE *ei_local = netdev_priv(dev_raether);
++ RxLRORingRead(seq, v, ei_local->rx_ring3);
++
++ return 0;
++}
++
++static int rx_ring1_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, RxRing1Read, NULL);
++}
++
++static int rx_ring2_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, RxRing2Read, NULL);
++}
++
++static int rx_ring3_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, RxRing3Read, NULL);
++}
++
++static const struct file_operations rx_ring1_fops = {
++ .owner = THIS_MODULE,
++ .open = rx_ring1_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release
++};
++
++static const struct file_operations rx_ring2_fops = {
++ .owner = THIS_MODULE,
++ .open = rx_ring2_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release
++};
++
++static const struct file_operations rx_ring3_fops = {
++ .owner = THIS_MODULE,
++ .open = rx_ring3_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release
++};
++#endif /* CONFIG_RAETH_HW_LRO */
++
++#if defined(CONFIG_RAETH_TSO)
++
++int NumOfTxdUpdate(int num_of_txd)
++{
++
++ txd_cnt[num_of_txd]++;
++
++ return 0;
++}
++
++static void *seq_TsoTxdNum_start(struct seq_file *seq, loff_t *pos)
++{
++ seq_printf(seq, "TXD | Count\n");
++ if (*pos < (MAX_SKB_FRAGS/2 + 1))
++ return pos;
++ return NULL;
++}
++
++static void *seq_TsoTxdNum_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++ (*pos)++;
++ if (*pos >= (MAX_SKB_FRAGS/2 + 1))
++ return NULL;
++ return pos;
++}
++
++static void seq_TsoTxdNum_stop(struct seq_file *seq, void *v)
++{
++ /* Nothing to do */
++}
++
++static int seq_TsoTxdNum_show(struct seq_file *seq, void *v)
++{
++ int i = *(loff_t *) v;
++ seq_printf(seq, "%d: %d\n",i , txd_cnt[i]);
++
++ return 0;
++}
++
++ssize_t NumOfTxdWrite(struct file *file, const char __user *buffer,
++ size_t count, loff_t *data)
++{
++ memset(txd_cnt, 0, sizeof(txd_cnt));
++ printk("clear txd cnt table\n");
++
++ return count;
++}
++
++int TsoLenUpdate(int tso_len)
++{
++
++ if(tso_len > 70000) {
++ tso_cnt[14]++;
++ }else if(tso_len > 65000) {
++ tso_cnt[13]++;
++ }else if(tso_len > 60000) {
++ tso_cnt[12]++;
++ }else if(tso_len > 55000) {
++ tso_cnt[11]++;
++ }else if(tso_len > 50000) {
++ tso_cnt[10]++;
++ }else if(tso_len > 45000) {
++ tso_cnt[9]++;
++ }else if(tso_len > 40000) {
++ tso_cnt[8]++;
++ }else if(tso_len > 35000) {
++ tso_cnt[7]++;
++ }else if(tso_len > 30000) {
++ tso_cnt[6]++;
++ }else if(tso_len > 25000) {
++ tso_cnt[5]++;
++ }else if(tso_len > 20000) {
++ tso_cnt[4]++;
++ }else if(tso_len > 15000) {
++ tso_cnt[3]++;
++ }else if(tso_len > 10000) {
++ tso_cnt[2]++;
++ }else if(tso_len > 5000) {
++ tso_cnt[1]++;
++ }else {
++ tso_cnt[0]++;
++ }
++
++ return 0;
++}
++
++ssize_t TsoLenWrite(struct file *file, const char __user *buffer,
++ size_t count, loff_t *data)
++{
++ memset(tso_cnt, 0, sizeof(tso_cnt));
++ printk("clear tso cnt table\n");
++
++ return count;
++}
++
++static void *seq_TsoLen_start(struct seq_file *seq, loff_t *pos)
++{
++ seq_printf(seq, " Length | Count\n");
++ if (*pos < 15)
++ return pos;
++ return NULL;
++}
++
++static void *seq_TsoLen_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++ (*pos)++;
++ if (*pos >= 15)
++ return NULL;
++ return pos;
++}
++
++static void seq_TsoLen_stop(struct seq_file *seq, void *v)
++{
++ /* Nothing to do */
++}
++
++static int seq_TsoLen_show(struct seq_file *seq, void *v)
++{
++ int i = *(loff_t *) v;
++
++ seq_printf(seq, "%d~%d: %d\n", i*5000, (i+1)*5000, tso_cnt[i]);
++
++ return 0;
++}
++
++static const struct seq_operations seq_tso_txd_num_ops = {
++ .start = seq_TsoTxdNum_start,
++ .next = seq_TsoTxdNum_next,
++ .stop = seq_TsoTxdNum_stop,
++ .show = seq_TsoTxdNum_show
++};
++
++static int tso_txd_num_open(struct inode *inode, struct file *file)
++{
++ return seq_open(file, &seq_tso_txd_num_ops);
++}
++
++static struct file_operations tso_txd_num_fops = {
++ .owner = THIS_MODULE,
++ .open = tso_txd_num_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .write = NumOfTxdWrite,
++ .release = seq_release
++};
++
++static const struct seq_operations seq_tso_len_ops = {
++ .start = seq_TsoLen_start,
++ .next = seq_TsoLen_next,
++ .stop = seq_TsoLen_stop,
++ .show = seq_TsoLen_show
++};
++
++static int tso_len_open(struct inode *inode, struct file *file)
++{
++ return seq_open(file, &seq_tso_len_ops);
++}
++
++static struct file_operations tso_len_fops = {
++ .owner = THIS_MODULE,
++ .open = tso_len_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .write = TsoLenWrite,
++ .release = seq_release
++};
++#endif
++
++#if defined(CONFIG_RAETH_LRO)
++static int LroLenUpdate(struct net_lro_desc *lro_desc)
++{
++ int len_idx;
++
++ if(lro_desc->ip_tot_len > 65000) {
++ len_idx = 13;
++ }else if(lro_desc->ip_tot_len > 60000) {
++ len_idx = 12;
++ }else if(lro_desc->ip_tot_len > 55000) {
++ len_idx = 11;
++ }else if(lro_desc->ip_tot_len > 50000) {
++ len_idx = 10;
++ }else if(lro_desc->ip_tot_len > 45000) {
++ len_idx = 9;
++ }else if(lro_desc->ip_tot_len > 40000) {
++ len_idx = 8;
++ }else if(lro_desc->ip_tot_len > 35000) {
++ len_idx = 7;
++ }else if(lro_desc->ip_tot_len > 30000) {
++ len_idx = 6;
++ }else if(lro_desc->ip_tot_len > 25000) {
++ len_idx = 5;
++ }else if(lro_desc->ip_tot_len > 20000) {
++ len_idx = 4;
++ }else if(lro_desc->ip_tot_len > 15000) {
++ len_idx = 3;
++ }else if(lro_desc->ip_tot_len > 10000) {
++ len_idx = 2;
++ }else if(lro_desc->ip_tot_len > 5000) {
++ len_idx = 1;
++ }else {
++ len_idx = 0;
++ }
++
++ return len_idx;
++}
++int LroStatsUpdate(struct net_lro_mgr *lro_mgr, bool all_flushed)
++{
++ struct net_lro_desc *tmp;
++ int len_idx;
++ int i, j;
++
++ if (all_flushed) {
++ for (i=0; i< MAX_DESC; i++) {
++ tmp = & lro_mgr->lro_arr[i];
++ if (tmp->pkt_aggr_cnt !=0) {
++ for(j=0; j<=MAX_AGGR; j++) {
++ if(tmp->pkt_aggr_cnt == j) {
++ lro_flush_cnt[j]++;
++ }
++ }
++ len_idx = LroLenUpdate(tmp);
++ lro_len_cnt1[len_idx]++;
++ tot_called1++;
++ }
++ aggregated[i] = 0;
++ }
++ } else {
++ if (lro_flushed != lro_mgr->stats.flushed) {
++ if (lro_aggregated != lro_mgr->stats.aggregated) {
++ for (i=0; i<MAX_DESC; i++) {
++ tmp = &lro_mgr->lro_arr[i];
++ if ((aggregated[i]!= tmp->pkt_aggr_cnt)
++ && (tmp->pkt_aggr_cnt == 0)) {
++ aggregated[i] ++;
++ for (j=0; j<=MAX_AGGR; j++) {
++ if (aggregated[i] == j) {
++ lro_stats_cnt[j] ++;
++ }
++ }
++ aggregated[i] = 0;
++ //len_idx = LroLenUpdate(tmp);
++ //lro_len_cnt2[len_idx]++;
++ tot_called2++;
++ }
++ }
++ } else {
++ for (i=0; i<MAX_DESC; i++) {
++ tmp = &lro_mgr->lro_arr[i];
++ if ((aggregated[i] != 0) && (tmp->pkt_aggr_cnt==0)) {
++ for (j=0; j<=MAX_AGGR; j++) {
++ if (aggregated[i] == j) {
++ lro_stats_cnt[j] ++;
++ }
++ }
++ aggregated[i] = 0;
++ //len_idx = LroLenUpdate(tmp);
++ //lro_len_cnt2[len_idx]++;
++ force_flush ++;
++ tot_called2++;
++ }
++ }
++ }
++ } else {
++ if (lro_aggregated != lro_mgr->stats.aggregated) {
++ for (i=0; i<MAX_DESC; i++) {
++ tmp = &lro_mgr->lro_arr[i];
++ if (tmp->active) {
++ if (aggregated[i] != tmp->pkt_aggr_cnt)
++ aggregated[i] = tmp->pkt_aggr_cnt;
++ } else
++ aggregated[i] = 0;
++ }
++ }
++ }
++
++ }
++
++ lro_aggregated = lro_mgr->stats.aggregated;
++ lro_flushed = lro_mgr->stats.flushed;
++ lro_nodesc = lro_mgr->stats.no_desc;
++
++ return 0;
++
++}
++
++
++ssize_t LroStatsWrite(struct file *file, const char __user *buffer,
++ size_t count, loff_t *data)
++{
++ memset(lro_stats_cnt, 0, sizeof(lro_stats_cnt));
++ memset(lro_flush_cnt, 0, sizeof(lro_flush_cnt));
++ memset(lro_len_cnt1, 0, sizeof(lro_len_cnt1));
++ //memset(lro_len_cnt2, 0, sizeof(lro_len_cnt2));
++ memset(aggregated, 0, sizeof(aggregated));
++ lro_aggregated = 0;
++ lro_flushed = 0;
++ lro_nodesc = 0;
++ force_flush = 0;
++ tot_called1 = 0;
++ tot_called2 = 0;
++ printk("clear lro cnt table\n");
++
++ return count;
++}
++
++int LroStatsRead(struct seq_file *seq, void *v)
++{
++ int i;
++ int tot_cnt=0;
++ int tot_aggr=0;
++ int ave_aggr=0;
++
++ seq_printf(seq, "LRO statistic dump:\n");
++ seq_printf(seq, "Cnt: Kernel | Driver\n");
++ for(i=0; i<=MAX_AGGR; i++) {
++ tot_cnt = tot_cnt + lro_stats_cnt[i] + lro_flush_cnt[i];
++ seq_printf(seq, " %d : %d %d\n", i, lro_stats_cnt[i], lro_flush_cnt[i]);
++ tot_aggr = tot_aggr + i * (lro_stats_cnt[i] + lro_flush_cnt[i]);
++ }
++ ave_aggr = lro_aggregated/lro_flushed;
++ seq_printf(seq, "Total aggregated pkt: %d\n", lro_aggregated);
++ seq_printf(seq, "Flushed pkt: %d %d\n", lro_flushed, force_flush);
++ seq_printf(seq, "Average flush cnt: %d\n", ave_aggr);
++ seq_printf(seq, "No descriptor pkt: %d\n\n\n", lro_nodesc);
++
++ seq_printf(seq, "Driver flush pkt len:\n");
++ seq_printf(seq, " Length | Count\n");
++ for(i=0; i<15; i++) {
++ seq_printf(seq, "%d~%d: %d\n", i*5000, (i+1)*5000, lro_len_cnt1[i]);
++ }
++ seq_printf(seq, "Kernel flush: %d; Driver flush: %d\n", tot_called2, tot_called1);
++ return 0;
++}
++
++static int lro_stats_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, LroStatsRead, NULL);
++}
++
++static struct file_operations lro_stats_fops = {
++ .owner = THIS_MODULE,
++ .open = lro_stats_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .write = LroStatsWrite,
++ .release = single_release
++};
++#endif
++
++int getnext(const char *src, int separator, char *dest)
++{
++ char *c;
++ int len;
++
++ if ( (src == NULL) || (dest == NULL) ) {
++ return -1;
++ }
++
++ c = strchr(src, separator);
++ if (c == NULL) {
++ strcpy(dest, src);
++ return -1;
++ }
++ len = c - src;
++ strncpy(dest, src, len);
++ dest[len] = '\0';
++ return len + 1;
++}
++
++int str_to_ip(unsigned int *ip, const char *str)
++{
++ int len;
++ const char *ptr = str;
++ char buf[128];
++ unsigned char c[4];
++ int i;
++
++ for (i = 0; i < 3; ++i) {
++ if ((len = getnext(ptr, '.', buf)) == -1) {
++ return 1; /* parse error */
++ }
++ c[i] = simple_strtoul(buf, NULL, 10);
++ ptr += len;
++ }
++ c[3] = simple_strtoul(ptr, NULL, 0);
++ *ip = (c[0]<<24) + (c[1]<<16) + (c[2]<<8) + c[3];
++ return 0;
++}
++
++#if defined(CONFIG_RAETH_HW_LRO)
++static int HwLroLenUpdate(unsigned int agg_size)
++{
++ int len_idx;
++
++ if(agg_size > 65000) {
++ len_idx = 13;
++ }else if(agg_size > 60000) {
++ len_idx = 12;
++ }else if(agg_size > 55000) {
++ len_idx = 11;
++ }else if(agg_size > 50000) {
++ len_idx = 10;
++ }else if(agg_size > 45000) {
++ len_idx = 9;
++ }else if(agg_size > 40000) {
++ len_idx = 8;
++ }else if(agg_size > 35000) {
++ len_idx = 7;
++ }else if(agg_size > 30000) {
++ len_idx = 6;
++ }else if(agg_size > 25000) {
++ len_idx = 5;
++ }else if(agg_size > 20000) {
++ len_idx = 4;
++ }else if(agg_size > 15000) {
++ len_idx = 3;
++ }else if(agg_size > 10000) {
++ len_idx = 2;
++ }else if(agg_size > 5000) {
++ len_idx = 1;
++ }else {
++ len_idx = 0;
++ }
++
++ return len_idx;
++}
++
++int HwLroStatsUpdate(unsigned int ring_num, unsigned int agg_cnt, unsigned int agg_size)
++{
++ if( (ring_num > 0) && (ring_num < 4) )
++ {
++ hw_lro_agg_size_cnt[ring_num-1][HwLroLenUpdate(agg_size)]++;
++ hw_lro_agg_num_cnt[ring_num-1][agg_cnt]++;
++ hw_lro_tot_flush_cnt[ring_num-1]++;
++ hw_lro_tot_agg_cnt[ring_num-1] += agg_cnt;
++ }
++
++ return 0;
++}
++
++#if defined(CONFIG_RAETH_HW_LRO_REASON_DBG)
++int HwLroFlushStatsUpdate(unsigned int ring_num, unsigned int flush_reason)
++{
++ if( (ring_num > 0) && (ring_num < 4) )
++ {
++#if 1
++ if ( (flush_reason & 0x7) == HW_LRO_AGG_FLUSH )
++ hw_lro_agg_flush_cnt[ring_num-1]++;
++ else if ( (flush_reason & 0x7) == HW_LRO_AGE_FLUSH )
++ hw_lro_age_flush_cnt[ring_num-1]++;
++ else if ( (flush_reason & 0x7) == HW_LRO_NOT_IN_SEQ_FLUSH )
++ hw_lro_seq_flush_cnt[ring_num-1]++;
++ else if ( (flush_reason & 0x7) == HW_LRO_TIMESTAMP_FLUSH )
++ hw_lro_timestamp_flush_cnt[ring_num-1]++;
++ else if ( (flush_reason & 0x7) == HW_LRO_NON_RULE_FLUSH )
++ hw_lro_norule_flush_cnt[ring_num-1]++;
++#else
++ if ( flush_reason & BIT(4) )
++ hw_lro_agg_flush_cnt[ring_num-1]++;
++ else if ( flush_reason & BIT(3) )
++ hw_lro_age_flush_cnt[ring_num-1]++;
++ else if ( flush_reason & BIT(2) )
++ hw_lro_seq_flush_cnt[ring_num-1]++;
++ else if ( flush_reason & BIT(1) )
++ hw_lro_timestamp_flush_cnt[ring_num-1]++;
++ else if ( flush_reason & BIT(0) )
++ hw_lro_norule_flush_cnt[ring_num-1]++;
++#endif
++ }
++
++ return 0;
++}
++#endif /* CONFIG_RAETH_HW_LRO_REASON_DBG */
++
++ssize_t HwLroStatsWrite(struct file *file, const char __user *buffer,
++ size_t count, loff_t *data)
++{
++ memset(hw_lro_agg_num_cnt, 0, sizeof(hw_lro_agg_num_cnt));
++ memset(hw_lro_agg_size_cnt, 0, sizeof(hw_lro_agg_size_cnt));
++ memset(hw_lro_tot_agg_cnt, 0, sizeof(hw_lro_tot_agg_cnt));
++ memset(hw_lro_tot_flush_cnt, 0, sizeof(hw_lro_tot_flush_cnt));
++#if defined(CONFIG_RAETH_HW_LRO_REASON_DBG)
++ memset(hw_lro_agg_flush_cnt, 0, sizeof(hw_lro_agg_flush_cnt));
++ memset(hw_lro_age_flush_cnt, 0, sizeof(hw_lro_age_flush_cnt));
++ memset(hw_lro_seq_flush_cnt, 0, sizeof(hw_lro_seq_flush_cnt));
++ memset(hw_lro_timestamp_flush_cnt, 0, sizeof(hw_lro_timestamp_flush_cnt));
++ memset(hw_lro_norule_flush_cnt, 0, sizeof(hw_lro_norule_flush_cnt));
++#endif /* CONFIG_RAETH_HW_LRO_REASON_DBG */
++
++ printk("clear hw lro cnt table\n");
++
++ return count;
++}
++
++int HwLroStatsRead(struct seq_file *seq, void *v)
++{
++ int i;
++
++ seq_printf(seq, "HW LRO statistic dump:\n");
++
++ /* Agg number count */
++ seq_printf(seq, "Cnt: RING1 | RING2 | RING3 | Total\n");
++ for(i=0; i<=MAX_HW_LRO_AGGR; i++) {
++ seq_printf(seq, " %d : %d %d %d %d\n",
++ i, hw_lro_agg_num_cnt[0][i], hw_lro_agg_num_cnt[1][i], hw_lro_agg_num_cnt[2][i],
++ hw_lro_agg_num_cnt[0][i]+hw_lro_agg_num_cnt[1][i]+hw_lro_agg_num_cnt[2][i]);
++ }
++
++ /* Total agg count */
++ seq_printf(seq, "Total agg: RING1 | RING2 | RING3 | Total\n");
++ seq_printf(seq, " %d %d %d %d\n",
++ hw_lro_tot_agg_cnt[0], hw_lro_tot_agg_cnt[1], hw_lro_tot_agg_cnt[2],
++ hw_lro_tot_agg_cnt[0]+hw_lro_tot_agg_cnt[1]+hw_lro_tot_agg_cnt[2]);
++
++ /* Total flush count */
++ seq_printf(seq, "Total flush: RING1 | RING2 | RING3 | Total\n");
++ seq_printf(seq, " %d %d %d %d\n",
++ hw_lro_tot_flush_cnt[0], hw_lro_tot_flush_cnt[1], hw_lro_tot_flush_cnt[2],
++ hw_lro_tot_flush_cnt[0]+hw_lro_tot_flush_cnt[1]+hw_lro_tot_flush_cnt[2]);
++
++ /* Avg agg count */
++ seq_printf(seq, "Avg agg: RING1 | RING2 | RING3 | Total\n");
++ seq_printf(seq, " %d %d %d %d\n",
++ (hw_lro_tot_flush_cnt[0]) ? hw_lro_tot_agg_cnt[0]/hw_lro_tot_flush_cnt[0] : 0,
++ (hw_lro_tot_flush_cnt[1]) ? hw_lro_tot_agg_cnt[1]/hw_lro_tot_flush_cnt[1] : 0,
++ (hw_lro_tot_flush_cnt[2]) ? hw_lro_tot_agg_cnt[2]/hw_lro_tot_flush_cnt[2] : 0,
++ (hw_lro_tot_flush_cnt[0]+hw_lro_tot_flush_cnt[1]+hw_lro_tot_flush_cnt[2]) ? \
++ ((hw_lro_tot_agg_cnt[0]+hw_lro_tot_agg_cnt[1]+hw_lro_tot_agg_cnt[2])/(hw_lro_tot_flush_cnt[0]+hw_lro_tot_flush_cnt[1]+hw_lro_tot_flush_cnt[2])) : 0
++ );
++
++ /* Statistics of aggregation size counts */
++ seq_printf(seq, "HW LRO flush pkt len:\n");
++ seq_printf(seq, " Length | RING1 | RING2 | RING3 | Total\n");
++ for(i=0; i<15; i++) {
++ seq_printf(seq, "%d~%d: %d %d %d %d\n", i*5000, (i+1)*5000,
++ hw_lro_agg_size_cnt[0][i], hw_lro_agg_size_cnt[1][i], hw_lro_agg_size_cnt[2][i],
++ hw_lro_agg_size_cnt[0][i]+hw_lro_agg_size_cnt[1][i]+hw_lro_agg_size_cnt[2][i]);
++ }
++#if defined(CONFIG_RAETH_HW_LRO_REASON_DBG)
++ seq_printf(seq, "Flush reason: RING1 | RING2 | RING3 | Total\n");
++ seq_printf(seq, "AGG timeout: %d %d %d %d\n",
++ hw_lro_agg_flush_cnt[0], hw_lro_agg_flush_cnt[1], hw_lro_agg_flush_cnt[2],
++ (hw_lro_agg_flush_cnt[0]+hw_lro_agg_flush_cnt[1]+hw_lro_agg_flush_cnt[2])
++ );
++ seq_printf(seq, "AGE timeout: %d %d %d %d\n",
++ hw_lro_age_flush_cnt[0], hw_lro_age_flush_cnt[1], hw_lro_age_flush_cnt[2],
++ (hw_lro_age_flush_cnt[0]+hw_lro_age_flush_cnt[1]+hw_lro_age_flush_cnt[2])
++ );
++ seq_printf(seq, "Not in-sequence: %d %d %d %d\n",
++ hw_lro_seq_flush_cnt[0], hw_lro_seq_flush_cnt[1], hw_lro_seq_flush_cnt[2],
++ (hw_lro_seq_flush_cnt[0]+hw_lro_seq_flush_cnt[1]+hw_lro_seq_flush_cnt[2])
++ );
++ seq_printf(seq, "Timestamp: %d %d %d %d\n",
++ hw_lro_timestamp_flush_cnt[0], hw_lro_timestamp_flush_cnt[1], hw_lro_timestamp_flush_cnt[2],
++ (hw_lro_timestamp_flush_cnt[0]+hw_lro_timestamp_flush_cnt[1]+hw_lro_timestamp_flush_cnt[2])
++ );
++ seq_printf(seq, "No LRO rule: %d %d %d %d\n",
++ hw_lro_norule_flush_cnt[0], hw_lro_norule_flush_cnt[1], hw_lro_norule_flush_cnt[2],
++ (hw_lro_norule_flush_cnt[0]+hw_lro_norule_flush_cnt[1]+hw_lro_norule_flush_cnt[2])
++ );
++#endif /* CONFIG_RAETH_HW_LRO_REASON_DBG */
++
++ return 0;
++}
++
++static int hw_lro_stats_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, HwLroStatsRead, NULL);
++}
++
++static struct file_operations hw_lro_stats_fops = {
++ .owner = THIS_MODULE,
++ .open = hw_lro_stats_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .write = HwLroStatsWrite,
++ .release = single_release
++};
++
++int hwlro_agg_cnt_ctrl(int par1, int par2)
++{
++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING1, par2);
++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING2, par2);
++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING3, par2);
++ return 0;
++}
++
++int hwlro_agg_time_ctrl(int par1, int par2)
++{
++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING1, par2);
++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING2, par2);
++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING3, par2);
++ return 0;
++}
++
++int hwlro_age_time_ctrl(int par1, int par2)
++{
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, par2);
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, par2);
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, par2);
++ return 0;
++}
++
++int hwlro_pkt_int_alpha_ctrl(int par1, int par2)
++{
++ END_DEVICE *ei_local = netdev_priv(dev_raether);
++
++ ei_local->hw_lro_alpha = par2;
++ printk("[hwlro_pkt_int_alpha_ctrl]ei_local->hw_lro_alpha = %d\n", ei_local->hw_lro_alpha);
++
++ return 0;
++}
++
++int hwlro_threshold_ctrl(int par1, int par2)
++{
++ /* bandwidth threshold setting */
++ SET_PDMA_LRO_BW_THRESHOLD(par2);
++ return 0;
++}
++
++int hwlro_fix_setting_switch_ctrl(int par1, int par2)
++{
++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG)
++ END_DEVICE *ei_local = netdev_priv(dev_raether);
++
++ ei_local->hw_lro_fix_setting = par2;
++ printk("[hwlro_pkt_int_alpha_ctrl]ei_local->hw_lro_fix_setting = %d\n", ei_local->hw_lro_fix_setting);
++#endif /* CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG */
++
++ return 0;
++}
++
++ssize_t HwLroAutoTlbWrite(struct file *file, const char __user *buffer,
++ size_t count, loff_t *data)
++{
++ char buf[32];
++ char *pBuf;
++ int len = count;
++ int x = 0,y = 0;
++ char *pToken = NULL;
++ char *pDelimiter = " \t";
++
++ printk("[HwLroAutoTlbWrite]write parameter len = %d\n\r", (int)len);
++ if(len >= sizeof(buf)){
++ printk("input handling fail!\n");
++ len = sizeof(buf) - 1;
++ return -1;
++ }
++
++ if(copy_from_user(buf, buffer, len)){
++ return -EFAULT;
++ }
++ buf[len] = '\0';
++ printk("[HwLroAutoTlbWrite]write parameter data = %s\n\r", buf);
++
++ pBuf = buf;
++ pToken = strsep(&pBuf, pDelimiter);
++ x = NULL != pToken ? simple_strtol(pToken, NULL, 16) : 0;
++
++ pToken = strsep(&pBuf, "\t\n ");
++ if(pToken != NULL){
++ y = NULL != pToken ? simple_strtol(pToken, NULL, 16) : 0;
++ printk("y = 0x%08x \n\r", y);
++ }
++
++ if ( (sizeof(hw_lro_dbg_func)/sizeof(hw_lro_dbg_func[0]) > x) && NULL != hw_lro_dbg_func[x])
++ {
++ (*hw_lro_dbg_func[x])(x, y);
++ }
++
++ return count;
++}
++
++void HwLroAutoTlbDump(struct seq_file *seq, unsigned int index)
++{
++ int i;
++ struct PDMA_LRO_AUTO_TLB_INFO pdma_lro_auto_tlb;
++ unsigned int tlb_info[9];
++ unsigned int dw_len, cnt, priority;
++ unsigned int entry;
++
++ if( index > 4 )
++ index = index - 1;
++ entry = (index * 9) + 1;
++
++ /* read valid entries of the auto-learn table */
++ sysRegWrite( PDMA_FE_ALT_CF8, entry );
++
++ //seq_printf(seq, "\nEntry = %d\n", entry);
++ for(i=0; i<9; i++){
++ tlb_info[i] = sysRegRead(PDMA_FE_ALT_SEQ_CFC);
++ //seq_printf(seq, "tlb_info[%d] = 0x%x\n", i, tlb_info[i]);
++ }
++ memcpy(&pdma_lro_auto_tlb, tlb_info, sizeof(struct PDMA_LRO_AUTO_TLB_INFO));
++
++ dw_len = pdma_lro_auto_tlb.auto_tlb_info7.DW_LEN;
++ cnt = pdma_lro_auto_tlb.auto_tlb_info6.CNT;
++
++ if ( sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_ALT_SCORE_MODE ) /* packet count */
++ priority = cnt;
++ else /* byte count */
++ priority = dw_len;
++
++ /* dump valid entries of the auto-learn table */
++ if( index >= 4 )
++ seq_printf(seq, "\n===== TABLE Entry: %d (Act) =====\n", index);
++ else
++ seq_printf(seq, "\n===== TABLE Entry: %d (LRU) =====\n", index);
++ if( pdma_lro_auto_tlb.auto_tlb_info8.IPV4 ){
++ seq_printf(seq, "SIP = 0x%x:0x%x:0x%x:0x%x (IPv4)\n",
++ pdma_lro_auto_tlb.auto_tlb_info4.SIP3,
++ pdma_lro_auto_tlb.auto_tlb_info3.SIP2,
++ pdma_lro_auto_tlb.auto_tlb_info2.SIP1,
++ pdma_lro_auto_tlb.auto_tlb_info1.SIP0);
++ }
++ else{
++ seq_printf(seq, "SIP = 0x%x:0x%x:0x%x:0x%x (IPv6)\n",
++ pdma_lro_auto_tlb.auto_tlb_info4.SIP3,
++ pdma_lro_auto_tlb.auto_tlb_info3.SIP2,
++ pdma_lro_auto_tlb.auto_tlb_info2.SIP1,
++ pdma_lro_auto_tlb.auto_tlb_info1.SIP0);
++ }
++ seq_printf(seq, "DIP_ID = %d\n", pdma_lro_auto_tlb.auto_tlb_info8.DIP_ID);
++ seq_printf(seq, "TCP SPORT = %d | TCP DPORT = %d\n",
++ pdma_lro_auto_tlb.auto_tlb_info0.STP,
++ pdma_lro_auto_tlb.auto_tlb_info0.DTP);
++ seq_printf(seq, "VLAN1 = %d | VLAN2 = %d | VLAN3 = %d | VLAN4 =%d \n",
++ pdma_lro_auto_tlb.auto_tlb_info5.VLAN_VID0,
++ (pdma_lro_auto_tlb.auto_tlb_info5.VLAN_VID0 << 12),
++ (pdma_lro_auto_tlb.auto_tlb_info5.VLAN_VID0 << 24),
++ pdma_lro_auto_tlb.auto_tlb_info6.VLAN_VID1);
++ seq_printf(seq, "TPUT = %d | FREQ = %d\n", dw_len, cnt);
++ seq_printf(seq, "PRIORITY = %d\n", priority);
++}
++
++int HwLroAutoTlbRead(struct seq_file *seq, void *v)
++{
++ int i;
++ unsigned int regVal;
++ unsigned int regOp1, regOp2, regOp3, regOp4;
++ unsigned int agg_cnt, agg_time, age_time;
++
++ /* Read valid entries of the auto-learn table */
++ sysRegWrite(PDMA_FE_ALT_CF8, 0);
++ regVal = sysRegRead(PDMA_FE_ALT_SEQ_CFC);
++
++ seq_printf(seq, "HW LRO Auto-learn Table: (PDMA_LRO_ALT_CFC_RSEQ_DBG=0x%x)\n", regVal);
++
++ for(i = 7; i >= 0; i--)
++ {
++ if( regVal & (1 << i) )
++ HwLroAutoTlbDump(seq, i);
++ }
++
++ /* Read the agg_time/age_time/agg_cnt of LRO rings */
++ seq_printf(seq, "\nHW LRO Ring Settings\n");
++ for(i = 1; i <= 3; i++)
++ {
++ regOp1 = sysRegRead( LRO_RX_RING0_CTRL_DW1 + (i * 0x40) );
++ regOp2 = sysRegRead( LRO_RX_RING0_CTRL_DW2 + (i * 0x40) );
++ regOp3 = sysRegRead( LRO_RX_RING0_CTRL_DW3 + (i * 0x40) );
++ regOp4 = sysRegRead( ADMA_LRO_CTRL_DW2 );
++ agg_cnt = ((regOp3 & 0x03) << PDMA_LRO_AGG_CNT_H_OFFSET) | ((regOp2 >> PDMA_LRO_RING_AGG_CNT1_OFFSET) & 0x3f);
++ agg_time = (regOp2 >> PDMA_LRO_RING_AGG_OFFSET) & 0xffff;
++ age_time = ((regOp2 & 0x03f) << PDMA_LRO_AGE_H_OFFSET) | ((regOp1 >> PDMA_LRO_RING_AGE1_OFFSET) & 0x3ff);
++ seq_printf(seq, "Ring[%d]: MAX_AGG_CNT=%d, AGG_TIME=%d, AGE_TIME=%d, Threshold=%d\n",
++ i, agg_cnt, agg_time, age_time, regOp4);
++ }
++
++ return 0;
++}
++
++static int hw_lro_auto_tlb_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, HwLroAutoTlbRead, NULL);
++}
++
++static struct file_operations hw_lro_auto_tlb_fops = {
++ .owner = THIS_MODULE,
++ .open = hw_lro_auto_tlb_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .write = HwLroAutoTlbWrite,
++ .release = single_release
++};
++#endif /* CONFIG_RAETH_HW_LRO */
++
++#if defined (CONFIG_MIPS)
++int CP0RegRead(struct seq_file *seq, void *v)
++{
++ seq_printf(seq, "CP0 Register dump --\n");
++ seq_printf(seq, "CP0_INDEX\t: 0x%08x\n", read_32bit_cp0_register(CP0_INDEX));
++ seq_printf(seq, "CP0_RANDOM\t: 0x%08x\n", read_32bit_cp0_register(CP0_RANDOM));
++ seq_printf(seq, "CP0_ENTRYLO0\t: 0x%08x\n", read_32bit_cp0_register(CP0_ENTRYLO0));
++ seq_printf(seq, "CP0_ENTRYLO1\t: 0x%08x\n", read_32bit_cp0_register(CP0_ENTRYLO1));
++ seq_printf(seq, "CP0_CONF\t: 0x%08x\n", read_32bit_cp0_register(CP0_CONF));
++ seq_printf(seq, "CP0_CONTEXT\t: 0x%08x\n", read_32bit_cp0_register(CP0_CONTEXT));
++ seq_printf(seq, "CP0_PAGEMASK\t: 0x%08x\n", read_32bit_cp0_register(CP0_PAGEMASK));
++ seq_printf(seq, "CP0_WIRED\t: 0x%08x\n", read_32bit_cp0_register(CP0_WIRED));
++ seq_printf(seq, "CP0_INFO\t: 0x%08x\n", read_32bit_cp0_register(CP0_INFO));
++ seq_printf(seq, "CP0_BADVADDR\t: 0x%08x\n", read_32bit_cp0_register(CP0_BADVADDR));
++ seq_printf(seq, "CP0_COUNT\t: 0x%08x\n", read_32bit_cp0_register(CP0_COUNT));
++ seq_printf(seq, "CP0_ENTRYHI\t: 0x%08x\n", read_32bit_cp0_register(CP0_ENTRYHI));
++ seq_printf(seq, "CP0_COMPARE\t: 0x%08x\n", read_32bit_cp0_register(CP0_COMPARE));
++ seq_printf(seq, "CP0_STATUS\t: 0x%08x\n", read_32bit_cp0_register(CP0_STATUS));
++ seq_printf(seq, "CP0_CAUSE\t: 0x%08x\n", read_32bit_cp0_register(CP0_CAUSE));
++ seq_printf(seq, "CP0_EPC\t: 0x%08x\n", read_32bit_cp0_register(CP0_EPC));
++ seq_printf(seq, "CP0_PRID\t: 0x%08x\n", read_32bit_cp0_register(CP0_PRID));
++ seq_printf(seq, "CP0_CONFIG\t: 0x%08x\n", read_32bit_cp0_register(CP0_CONFIG));
++ seq_printf(seq, "CP0_LLADDR\t: 0x%08x\n", read_32bit_cp0_register(CP0_LLADDR));
++ seq_printf(seq, "CP0_WATCHLO\t: 0x%08x\n", read_32bit_cp0_register(CP0_WATCHLO));
++ seq_printf(seq, "CP0_WATCHHI\t: 0x%08x\n", read_32bit_cp0_register(CP0_WATCHHI));
++ seq_printf(seq, "CP0_XCONTEXT\t: 0x%08x\n", read_32bit_cp0_register(CP0_XCONTEXT));
++ seq_printf(seq, "CP0_FRAMEMASK\t: 0x%08x\n", read_32bit_cp0_register(CP0_FRAMEMASK));
++ seq_printf(seq, "CP0_DIAGNOSTIC\t: 0x%08x\n", read_32bit_cp0_register(CP0_DIAGNOSTIC));
++ seq_printf(seq, "CP0_DEBUG\t: 0x%08x\n", read_32bit_cp0_register(CP0_DEBUG));
++ seq_printf(seq, "CP0_DEPC\t: 0x%08x\n", read_32bit_cp0_register(CP0_DEPC));
++ seq_printf(seq, "CP0_PERFORMANCE\t: 0x%08x\n", read_32bit_cp0_register(CP0_PERFORMANCE));
++ seq_printf(seq, "CP0_ECC\t: 0x%08x\n", read_32bit_cp0_register(CP0_ECC));
++ seq_printf(seq, "CP0_CACHEERR\t: 0x%08x\n", read_32bit_cp0_register(CP0_CACHEERR));
++ seq_printf(seq, "CP0_TAGLO\t: 0x%08x\n", read_32bit_cp0_register(CP0_TAGLO));
++ seq_printf(seq, "CP0_TAGHI\t: 0x%08x\n", read_32bit_cp0_register(CP0_TAGHI));
++ seq_printf(seq, "CP0_ERROREPC\t: 0x%08x\n", read_32bit_cp0_register(CP0_ERROREPC));
++ seq_printf(seq, "CP0_DESAVE\t: 0x%08x\n\n", read_32bit_cp0_register(CP0_DESAVE));
++
++ return 0;
++}
++
++static int cp0_reg_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, CP0RegRead, NULL);
++}
++
++static const struct file_operations cp0_reg_fops = {
++ .owner = THIS_MODULE,
++ .open = cp0_reg_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release
++};
++#endif
++
++#if defined(CONFIG_RAETH_QOS)
++static struct proc_dir_entry *procRaQOS, *procRaFeIntr, *procRaEswIntr;
++extern uint32_t num_of_rxdone_intr;
++extern uint32_t num_of_esw_intr;
++
++int RaQOSRegRead(struct seq_file *seq, void *v)
++{
++ dump_qos(seq);
++ return 0;
++}
++
++static int raeth_qos_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, RaQOSRegRead, NULL);
++}
++
++static const struct file_operations raeth_qos_fops = {
++ .owner = THIS_MODULE,
++ .open = raeth_qos_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release
++};
++#endif
++
++static struct proc_dir_entry *procEswCnt;
++
++int EswCntRead(struct seq_file *seq, void *v)
++{
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_P5_RGMII_TO_MT7530_MODE) || defined (CONFIG_ARCH_MT7623)
++ unsigned int pkt_cnt = 0;
++ int i = 0;
++#endif
++ seq_printf(seq, "\n <<CPU>> \n");
++ seq_printf(seq, " | \n");
++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++ seq_printf(seq, "+-----------------------------------------------+\n");
++ seq_printf(seq, "| <<PDMA>> |\n");
++ seq_printf(seq, "+-----------------------------------------------+\n");
++#else
++ seq_printf(seq, "+-----------------------------------------------+\n");
++ seq_printf(seq, "| <<PSE>> |\n");
++ seq_printf(seq, "+-----------------------------------------------+\n");
++ seq_printf(seq, " | \n");
++ seq_printf(seq, "+-----------------------------------------------+\n");
++ seq_printf(seq, "| <<GDMA>> |\n");
++#if defined (CONFIG_RALINK_MT7620)
++ seq_printf(seq, "| GDMA1_TX_GPCNT : %010u (Tx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1304));
++ seq_printf(seq, "| GDMA1_RX_GPCNT : %010u (Rx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1324));
++ seq_printf(seq, "| |\n");
++ seq_printf(seq, "| GDMA1_TX_SKIPCNT: %010u (skip) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1308));
++ seq_printf(seq, "| GDMA1_TX_COLCNT : %010u (collision) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x130c));
++ seq_printf(seq, "| GDMA1_RX_OERCNT : %010u (overflow) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1328));
++ seq_printf(seq, "| GDMA1_RX_FERCNT : %010u (FCS error) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x132c));
++ seq_printf(seq, "| GDMA1_RX_SERCNT : %010u (too short) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1330));
++ seq_printf(seq, "| GDMA1_RX_LERCNT : %010u (too long) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1334));
++ seq_printf(seq, "| GDMA1_RX_CERCNT : %010u (l3/l4 checksum) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1338));
++ seq_printf(seq, "| GDMA1_RX_FCCNT : %010u (flow control) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x133c));
++
++ seq_printf(seq, "| |\n");
++ seq_printf(seq, "| GDMA2_TX_GPCNT : %010u (Tx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1344));
++ seq_printf(seq, "| GDMA2_RX_GPCNT : %010u (Rx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1364));
++ seq_printf(seq, "| |\n");
++ seq_printf(seq, "| GDMA2_TX_SKIPCNT: %010u (skip) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1348));
++ seq_printf(seq, "| GDMA2_TX_COLCNT : %010u (collision) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x134c));
++ seq_printf(seq, "| GDMA2_RX_OERCNT : %010u (overflow) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1368));
++ seq_printf(seq, "| GDMA2_RX_FERCNT : %010u (FCS error) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x136c));
++ seq_printf(seq, "| GDMA2_RX_SERCNT : %010u (too short) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1370));
++ seq_printf(seq, "| GDMA2_RX_LERCNT : %010u (too long) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1374));
++ seq_printf(seq, "| GDMA2_RX_CERCNT : %010u (l3/l4 checksum) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1378));
++ seq_printf(seq, "| GDMA2_RX_FCCNT : %010u (flow control) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x137c));
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++ seq_printf(seq, "| GDMA1_RX_GBCNT : %010u (Rx Good Bytes) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2400));
++ seq_printf(seq, "| GDMA1_RX_GPCNT : %010u (Rx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2408));
++ seq_printf(seq, "| GDMA1_RX_OERCNT : %010u (overflow error) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2410));
++ seq_printf(seq, "| GDMA1_RX_FERCNT : %010u (FCS error) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2414));
++ seq_printf(seq, "| GDMA1_RX_SERCNT : %010u (too short) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2418));
++ seq_printf(seq, "| GDMA1_RX_LERCNT : %010u (too long) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x241C));
++ seq_printf(seq, "| GDMA1_RX_CERCNT : %010u (checksum error) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2420));
++ seq_printf(seq, "| GDMA1_RX_FCCNT : %010u (flow control) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2424));
++ seq_printf(seq, "| GDMA1_TX_SKIPCNT: %010u (about count) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2428));
++ seq_printf(seq, "| GDMA1_TX_COLCNT : %010u (collision count) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x242C));
++ seq_printf(seq, "| GDMA1_TX_GBCNT : %010u (Tx Good Bytes) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2430));
++ seq_printf(seq, "| GDMA1_TX_GPCNT : %010u (Tx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2438));
++ seq_printf(seq, "| |\n");
++ seq_printf(seq, "| GDMA2_RX_GBCNT : %010u (Rx Good Bytes) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2440));
++ seq_printf(seq, "| GDMA2_RX_GPCNT : %010u (Rx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2448));
++ seq_printf(seq, "| GDMA2_RX_OERCNT : %010u (overflow error) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2450));
++ seq_printf(seq, "| GDMA2_RX_FERCNT : %010u (FCS error) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2454));
++ seq_printf(seq, "| GDMA2_RX_SERCNT : %010u (too short) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2458));
++ seq_printf(seq, "| GDMA2_RX_LERCNT : %010u (too long) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x245C));
++ seq_printf(seq, "| GDMA2_RX_CERCNT : %010u (checksum error) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2460));
++ seq_printf(seq, "| GDMA2_RX_FCCNT : %010u (flow control) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2464));
++ seq_printf(seq, "| GDMA2_TX_SKIPCNT: %010u (skip) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2468));
++ seq_printf(seq, "| GDMA2_TX_COLCNT : %010u (collision) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x246C));
++ seq_printf(seq, "| GDMA2_TX_GBCNT : %010u (Tx Good Bytes) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2470));
++ seq_printf(seq, "| GDMA2_TX_GPCNT : %010u (Tx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2478));
++#else
++ seq_printf(seq, "| GDMA_TX_GPCNT1 : %010u (Tx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x704));
++ seq_printf(seq, "| GDMA_RX_GPCNT1 : %010u (Rx Good Pkts) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x724));
++ seq_printf(seq, "| |\n");
++ seq_printf(seq, "| GDMA_TX_SKIPCNT1: %010u (skip) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x708));
++ seq_printf(seq, "| GDMA_TX_COLCNT1 : %010u (collision) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x70c));
++ seq_printf(seq, "| GDMA_RX_OERCNT1 : %010u (overflow) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x728));
++ seq_printf(seq, "| GDMA_RX_FERCNT1 : %010u (FCS error) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x72c));
++ seq_printf(seq, "| GDMA_RX_SERCNT1 : %010u (too short) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x730));
++ seq_printf(seq, "| GDMA_RX_LERCNT1 : %010u (too long) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x734));
++ seq_printf(seq, "| GDMA_RX_CERCNT1 : %010u (l3/l4 checksum) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x738));
++ seq_printf(seq, "| GDMA_RX_FCCNT1 : %010u (flow control) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x73c));
++
++#endif
++ seq_printf(seq, "+-----------------------------------------------+\n");
++#endif
++
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined (CONFIG_RALINK_MT7620)
++
++ seq_printf(seq, " ^ \n");
++ seq_printf(seq, " | Port6 Rx:%010u Good Pkt \n", ((p6_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4620)&0xFFFF)));
++ seq_printf(seq, " | Port6 Rx:%010u Bad Pkt \n", sysRegRead(RALINK_ETH_SW_BASE+0x4620)>>16);
++ seq_printf(seq, " | Port6 Tx:%010u Good Pkt \n", ((p6_tx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4610)&0xFFFF)));
++ seq_printf(seq, " | Port6 Tx:%010u Bad Pkt \n", sysRegRead(RALINK_ETH_SW_BASE+0x4610)>>16);
++#if defined (CONFIG_RALINK_MT7620)
++
++ seq_printf(seq, " | Port7 Rx:%010u Good Pkt \n", ((p7_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4720)&0xFFFF)));
++ seq_printf(seq, " | Port7 Rx:%010u Bad Pkt \n", sysRegRead(RALINK_ETH_SW_BASE+0x4720)>>16);
++ seq_printf(seq, " | Port7 Tx:%010u Good Pkt \n", ((p7_tx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4710)&0xFFFF)));
++ seq_printf(seq, " | Port7 Tx:%010u Bad Pkt \n", sysRegRead(RALINK_ETH_SW_BASE+0x4710)>>16);
++#endif
++ seq_printf(seq, "+---------------------v-------------------------+\n");
++ seq_printf(seq, "| P6 |\n");
++ seq_printf(seq, "| <<10/100/1000 Embedded Switch>> |\n");
++ seq_printf(seq, "| P0 P1 P2 P3 P4 P5 |\n");
++ seq_printf(seq, "+-----------------------------------------------+\n");
++ seq_printf(seq, " | | | | | | \n");
++#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++ /* no built-in switch */
++#else
++ seq_printf(seq, " ^ \n");
++ seq_printf(seq, " | Port6 Rx:%08u Good Pkt \n", sysRegRead(RALINK_ETH_SW_BASE+0xE0)&0xFFFF);
++ seq_printf(seq, " | Port6 Tx:%08u Good Pkt \n", sysRegRead(RALINK_ETH_SW_BASE+0xE0)>>16);
++ seq_printf(seq, "+---------------------v-------------------------+\n");
++ seq_printf(seq, "| P6 |\n");
++ seq_printf(seq, "| <<10/100 Embedded Switch>> |\n");
++ seq_printf(seq, "| P0 P1 P2 P3 P4 P5 |\n");
++ seq_printf(seq, "+-----------------------------------------------+\n");
++ seq_printf(seq, " | | | | | | \n");
++#endif
++
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined (CONFIG_RALINK_MT7620)
++
++ seq_printf(seq, "Port0 Good RX=%010u Tx=%010u (Bad Rx=%010u Tx=%010u)\n", ((p0_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4020)&0xFFFF)), ((p0_tx_good_cnt << 16)| (sysRegRead(RALINK_ETH_SW_BASE+0x4010)&0xFFFF)), sysRegRead(RALINK_ETH_SW_BASE+0x4020)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x4010)>>16);
++
++ seq_printf(seq, "Port1 Good RX=%010u Tx=%010u (Bad Rx=%010u Tx=%010u)\n", ((p1_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4120)&0xFFFF)), ((p1_tx_good_cnt << 16)| (sysRegRead(RALINK_ETH_SW_BASE+0x4110)&0xFFFF)), sysRegRead(RALINK_ETH_SW_BASE+0x4120)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x4110)>>16);
++
++ seq_printf(seq, "Port2 Good RX=%010u Tx=%010u (Bad Rx=%010u Tx=%010u)\n", ((p2_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4220)&0xFFFF)), ((p2_tx_good_cnt << 16)| (sysRegRead(RALINK_ETH_SW_BASE+0x4210)&0xFFFF)), sysRegRead(RALINK_ETH_SW_BASE+0x4220)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x4210)>>16);
++
++ seq_printf(seq, "Port3 Good RX=%010u Tx=%010u (Bad Rx=%010u Tx=%010u)\n", ((p3_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4320)&0xFFFF)), ((p3_tx_good_cnt << 16)| (sysRegRead(RALINK_ETH_SW_BASE+0x4310)&0xFFFF)), sysRegRead(RALINK_ETH_SW_BASE+0x4320)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x4310)>>16);
++
++ seq_printf(seq, "Port4 Good RX=%010u Tx=%010u (Bad Rx=%010u Tx=%010u)\n", ((p4_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4420)&0xFFFF)), ((p4_tx_good_cnt << 16)| (sysRegRead(RALINK_ETH_SW_BASE+0x4410)&0xFFFF)), sysRegRead(RALINK_ETH_SW_BASE+0x4420)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x4410)>>16);
++
++ seq_printf(seq, "Port5 Good RX=%010u Tx=%010u (Bad Rx=%010u Tx=%010u)\n", ((p5_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4520)&0xFFFF)), ((p5_tx_good_cnt << 16)| (sysRegRead(RALINK_ETH_SW_BASE+0x4510)&0xFFFF)), sysRegRead(RALINK_ETH_SW_BASE+0x4520)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x4510)>>16);
++
++ seq_printf(seq, "Port0 KBytes RX=%010u Tx=%010u \n", ((p0_rx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4028) >> 10)), ((p0_tx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4018) >> 10)));
++
++ seq_printf(seq, "Port1 KBytes RX=%010u Tx=%010u \n", ((p1_rx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4128) >> 10)), ((p1_tx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4118) >> 10)));
++
++ seq_printf(seq, "Port2 KBytes RX=%010u Tx=%010u \n", ((p2_rx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4228) >> 10)), ((p2_tx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4218) >> 10)));
++
++ seq_printf(seq, "Port3 KBytes RX=%010u Tx=%010u \n", ((p3_rx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4328) >> 10)), ((p3_tx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4318) >> 10)));
++
++ seq_printf(seq, "Port4 KBytes RX=%010u Tx=%010u \n", ((p4_rx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4428) >> 10)), ((p4_tx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4418) >> 10)));
++
++ seq_printf(seq, "Port5 KBytes RX=%010u Tx=%010u \n", ((p5_rx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4528) >> 10)), ((p5_tx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4518) >> 10)));
++
++#if defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
++#define DUMP_EACH_PORT(base) \
++ for(i=0; i < 7;i++) { \
++ mii_mgr_read(31, (base) + (i*0x100), &pkt_cnt); \
++ seq_printf(seq, "%8u ", pkt_cnt); \
++ } \
++ seq_printf(seq, "\n");
++ seq_printf(seq, "========================================[MT7530] READ CLEAR========================\n");
++
++ seq_printf(seq, "===================== %8s %8s %8s %8s %8s %8s %8s\n","Port0", "Port1", "Port2", "Port3", "Port4", "Port5", "Port6");
++ seq_printf(seq, "Tx Drop Packet :"); DUMP_EACH_PORT(0x4000);
++ //seq_printf(seq, "Tx CRC Error :"); DUMP_EACH_PORT(0x4004);
++ seq_printf(seq, "Tx Unicast Packet :"); DUMP_EACH_PORT(0x4008);
++ seq_printf(seq, "Tx Multicast Packet :"); DUMP_EACH_PORT(0x400C);
++ seq_printf(seq, "Tx Broadcast Packet :"); DUMP_EACH_PORT(0x4010);
++ //seq_printf(seq, "Tx Collision Event :"); DUMP_EACH_PORT(0x4014);
++ seq_printf(seq, "Tx Pause Packet :"); DUMP_EACH_PORT(0x402C);
++ seq_printf(seq, "Rx Drop Packet :"); DUMP_EACH_PORT(0x4060);
++ seq_printf(seq, "Rx Filtering Packet :"); DUMP_EACH_PORT(0x4064);
++ seq_printf(seq, "Rx Unicast Packet :"); DUMP_EACH_PORT(0x4068);
++ seq_printf(seq, "Rx Multicast Packet :"); DUMP_EACH_PORT(0x406C);
++ seq_printf(seq, "Rx Broadcast Packet :"); DUMP_EACH_PORT(0x4070);
++ seq_printf(seq, "Rx Alignment Error :"); DUMP_EACH_PORT(0x4074);
++ seq_printf(seq, "Rx CRC Error :"); DUMP_EACH_PORT(0x4078);
++ seq_printf(seq, "Rx Undersize Error :"); DUMP_EACH_PORT(0x407C);
++ //seq_printf(seq, "Rx Fragment Error :"); DUMP_EACH_PORT(0x4080);
++ //seq_printf(seq, "Rx Oversize Error :"); DUMP_EACH_PORT(0x4084);
++ //seq_printf(seq, "Rx Jabber Error :"); DUMP_EACH_PORT(0x4088);
++ seq_printf(seq, "Rx Pause Packet :"); DUMP_EACH_PORT(0x408C);
++ mii_mgr_write(31, 0x4fe0, 0xf0);
++ mii_mgr_write(31, 0x4fe0, 0x800000f0);
++#endif
++
++
++#elif defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++ seq_printf(seq, "Port0 Good Pkt Cnt: RX=%08u Tx=%08u (Bad Pkt Cnt: Rx=%08u Tx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xE8)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0x150)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xE8)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x150)>>16);
++
++ seq_printf(seq, "Port1 Good Pkt Cnt: RX=%08u Tx=%08u (Bad Pkt Cnt: Rx=%08u Tx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xEC)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0x154)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xEC)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x154)>>16);
++
++ seq_printf(seq, "Port2 Good Pkt Cnt: RX=%08u Tx=%08u (Bad Pkt Cnt: Rx=%08u Tx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xF0)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0x158)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xF0)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x158)>>16);
++
++ seq_printf(seq, "Port3 Good Pkt Cnt: RX=%08u Tx=%08u (Bad Pkt Cnt: Rx=%08u Tx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xF4)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0x15C)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xF4)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x15c)>>16);
++
++ seq_printf(seq, "Port4 Good Pkt Cnt: RX=%08u Tx=%08u (Bad Pkt Cnt: Rx=%08u Tx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xF8)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0x160)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xF8)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x160)>>16);
++
++ seq_printf(seq, "Port5 Good Pkt Cnt: RX=%08u Tx=%08u (Bad Pkt Cnt: Rx=%08u Tx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xFC)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0x164)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xFC)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x164)>>16);
++#elif defined (CONFIG_RALINK_RT3883)
++ /* no built-in switch */
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++
++#define DUMP_EACH_PORT(base) \
++ for(i=0; i < 7;i++) { \
++ mii_mgr_read(31, (base) + (i*0x100), &pkt_cnt); \
++ seq_printf(seq, "%8u ", pkt_cnt); \
++ } \
++ seq_printf(seq, "\n");
++
++#if defined (CONFIG_RALINK_MT7621) /* TODO: need to update to use MT7530 compiler flag */
++ if(sysRegRead(0xbe00000c & (1<<16)))//MCM
++#endif
++ {
++ seq_printf(seq, "===================== %8s %8s %8s %8s %8s %8s %8s\n","Port0", "Port1", "Port2", "Port3", "Port4", "Port5", "Port6");
++ seq_printf(seq, "Tx Drop Packet :"); DUMP_EACH_PORT(0x4000);
++ seq_printf(seq, "Tx CRC Error :"); DUMP_EACH_PORT(0x4004);
++ seq_printf(seq, "Tx Unicast Packet :"); DUMP_EACH_PORT(0x4008);
++ seq_printf(seq, "Tx Multicast Packet :"); DUMP_EACH_PORT(0x400C);
++ seq_printf(seq, "Tx Broadcast Packet :"); DUMP_EACH_PORT(0x4010);
++ seq_printf(seq, "Tx Collision Event :"); DUMP_EACH_PORT(0x4014);
++ seq_printf(seq, "Tx Pause Packet :"); DUMP_EACH_PORT(0x402C);
++ seq_printf(seq, "Rx Drop Packet :"); DUMP_EACH_PORT(0x4060);
++ seq_printf(seq, "Rx Filtering Packet :"); DUMP_EACH_PORT(0x4064);
++ seq_printf(seq, "Rx Unicast Packet :"); DUMP_EACH_PORT(0x4068);
++ seq_printf(seq, "Rx Multicast Packet :"); DUMP_EACH_PORT(0x406C);
++ seq_printf(seq, "Rx Broadcast Packet :"); DUMP_EACH_PORT(0x4070);
++ seq_printf(seq, "Rx Alignment Error :"); DUMP_EACH_PORT(0x4074);
++ seq_printf(seq, "Rx CRC Error :"); DUMP_EACH_PORT(0x4078);
++ seq_printf(seq, "Rx Undersize Error :"); DUMP_EACH_PORT(0x407C);
++ seq_printf(seq, "Rx Fragment Error :"); DUMP_EACH_PORT(0x4080);
++ seq_printf(seq, "Rx Oversize Error :"); DUMP_EACH_PORT(0x4084);
++ seq_printf(seq, "Rx Jabber Error :"); DUMP_EACH_PORT(0x4088);
++ seq_printf(seq, "Rx Pause Packet :"); DUMP_EACH_PORT(0x408C);
++ mii_mgr_write(31, 0x4fe0, 0xf0);
++ mii_mgr_write(31, 0x4fe0, 0x800000f0);
++ }
++#if defined (CONFIG_RALINK_MT7621) /* TODO: need to update to use MT7530 compiler flag */
++ else {
++ seq_printf(seq, "no built-in switch\n");
++ }
++#endif
++
++#else /* RT305x, RT3352 */
++ seq_printf(seq, "Port0: Good Pkt Cnt: RX=%08u (Bad Pkt Cnt: Rx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xE8)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xE8)>>16);
++ seq_printf(seq, "Port1: Good Pkt Cnt: RX=%08u (Bad Pkt Cnt: Rx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xEC)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xEC)>>16);
++ seq_printf(seq, "Port2: Good Pkt Cnt: RX=%08u (Bad Pkt Cnt: Rx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xF0)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xF0)>>16);
++ seq_printf(seq, "Port3: Good Pkt Cnt: RX=%08u (Bad Pkt Cnt: Rx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xF4)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xF4)>>16);
++ seq_printf(seq, "Port4: Good Pkt Cnt: RX=%08u (Bad Pkt Cnt: Rx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xF8)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xF8)>>16);
++ seq_printf(seq, "Port5: Good Pkt Cnt: RX=%08u (Bad Pkt Cnt: Rx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xFC)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xFC)>>16);
++#endif
++ seq_printf(seq, "\n");
++
++ return 0;
++}
++
++static int switch_count_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, EswCntRead, NULL);
++}
++
++static const struct file_operations switch_count_fops = {
++ .owner = THIS_MODULE,
++ .open = switch_count_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release
++};
++
++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
++/*
++ * proc write procedure
++ */
++static ssize_t change_phyid(struct file *file, const char __user *buffer,
++ size_t count, loff_t *data)
++{
++ char buf[32];
++ struct net_device *cur_dev_p;
++ END_DEVICE *ei_local;
++ char if_name[64];
++ unsigned int phy_id;
++
++ if (count > 32)
++ count = 32;
++ memset(buf, 0, 32);
++ if (copy_from_user(buf, buffer, count))
++ return -EFAULT;
++
++ /* determine interface name */
++ strcpy(if_name, DEV_NAME); /* "eth2" by default */
++ if(isalpha(buf[0]))
++ sscanf(buf, "%s %d", if_name, &phy_id);
++ else
++ phy_id = simple_strtol(buf, 0, 10);
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ cur_dev_p = dev_get_by_name(&init_net, DEV_NAME);
++#else
++ cur_dev_p = dev_get_by_name(DEV_NAME);
++#endif
++ if (cur_dev_p == NULL)
++ return -EFAULT;
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ ei_local = netdev_priv(cur_dev_p);
++#else
++ ei_local = cur_dev_p->priv;
++#endif
++ ei_local->mii_info.phy_id = (unsigned char)phy_id;
++ return count;
++}
++
++#if defined(CONFIG_PSEUDO_SUPPORT)
++static ssize_t change_gmac2_phyid(struct file *file, const char __user *buffer,
++ size_t count, loff_t *data)
++{
++ char buf[32];
++ struct net_device *cur_dev_p;
++ PSEUDO_ADAPTER *pPseudoAd;
++ char if_name[64];
++ unsigned int phy_id;
++
++ if (count > 32)
++ count = 32;
++ memset(buf, 0, 32);
++ if (copy_from_user(buf, buffer, count))
++ return -EFAULT;
++ /* determine interface name */
++ strcpy(if_name, DEV2_NAME); /* "eth3" by default */
++ if(isalpha(buf[0]))
++ sscanf(buf, "%s %d", if_name, &phy_id);
++ else
++ phy_id = simple_strtol(buf, 0, 10);
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ cur_dev_p = dev_get_by_name(&init_net, DEV2_NAME);
++#else
++ cur_dev_p = dev_get_by_name(DEV2_NAMEj);
++#endif
++ if (cur_dev_p == NULL)
++ return -EFAULT;
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ pPseudoAd = netdev_priv(cur_dev_p);
++#else
++ pPseudoAd = cur_dev_p->priv;
++#endif
++ pPseudoAd->mii_info.phy_id = (unsigned char)phy_id;
++ return count;
++}
++
++static struct file_operations gmac2_fops = {
++ .owner = THIS_MODULE,
++ .write = change_gmac2_phyid
++};
++#endif
++#endif
++
++static int gmac_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, RegReadMain, NULL);
++}
++
++static struct file_operations gmac_fops = {
++ .owner = THIS_MODULE,
++ .open = gmac_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++#if defined (CONFIG_ETHTOOL)
++ .write = change_phyid,
++#endif
++ .release = single_release
++};
++
++#if defined (TASKLET_WORKQUEUE_SW)
++extern int init_schedule;
++extern int working_schedule;
++static int ScheduleRead(struct seq_file *seq, void *v)
++{
++ if (init_schedule == 1)
++ seq_printf(seq, "Initialize Raeth with workqueque<%d>\n", init_schedule);
++ else
++ seq_printf(seq, "Initialize Raeth with tasklet<%d>\n", init_schedule);
++ if (working_schedule == 1)
++ seq_printf(seq, "Raeth is running at workqueque<%d>\n", working_schedule);
++ else
++ seq_printf(seq, "Raeth is running at tasklet<%d>\n", working_schedule);
++
++ return 0;
++}
++
++static ssize_t ScheduleWrite(struct file *file, const char __user *buffer,
++ size_t count, loff_t *data)
++{
++ char buf[2];
++ int old;
++
++ if (copy_from_user(buf, buffer, count))
++ return -EFAULT;
++ old = init_schedule;
++ init_schedule = simple_strtol(buf, 0, 10);
++ printk("Change Raeth initial schedule from <%d> to <%d>\n! Not running schedule at present !\n",
++ old, init_schedule);
++
++ return count;
++}
++
++static int schedule_switch_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, ScheduleRead, NULL);
++}
++
++static const struct file_operations schedule_sw_fops = {
++ .owner = THIS_MODULE,
++ .open = schedule_switch_open,
++ .read = seq_read,
++ .write = ScheduleWrite,
++ .llseek = seq_lseek,
++ .release = single_release
++};
++#endif
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++static int PdmaDvtRead(struct seq_file *seq, void *v)
++{
++ seq_printf(seq, "g_pdma_dvt_show_config = 0x%x\n", pdma_dvt_get_show_config());
++ seq_printf(seq, "g_pdma_dvt_rx_test_config = 0x%x\n", pdma_dvt_get_rx_test_config());
++ seq_printf(seq, "g_pdma_dvt_tx_test_config = 0x%x\n", pdma_dvt_get_tx_test_config());
++
++ return 0;
++}
++
++static int PdmaDvtOpen(struct inode *inode, struct file *file)
++{
++ return single_open(file, PdmaDvtRead, NULL);
++}
++
++static ssize_t PdmaDvtWrite(struct file *file, const char __user *buffer,
++ size_t count, loff_t *data)
++{
++ char buf[32];
++ char *pBuf;
++ int len = count;
++ int x = 0,y = 0;
++ char *pToken = NULL;
++ char *pDelimiter = " \t";
++
++ printk("write parameter len = %d\n\r", (int)len);
++ if(len >= sizeof(buf)){
++ printk("input handling fail!\n");
++ len = sizeof(buf) - 1;
++ return -1;
++ }
++
++ if(copy_from_user(buf, buffer, len)){
++ return -EFAULT;
++ }
++ buf[len] = '\0';
++ printk("write parameter data = %s\n\r", buf);
++
++ pBuf = buf;
++ pToken = strsep(&pBuf, pDelimiter);
++ x = NULL != pToken ? simple_strtol(pToken, NULL, 16) : 0;
++
++ pToken = strsep(&pBuf, "\t\n ");
++ if(pToken != NULL){
++ y = NULL != pToken ? simple_strtol(pToken, NULL, 16) : 0;
++ printk("y = 0x%08x \n\r", y);
++ }
++
++ if ( (sizeof(pdma_dvt_dbg_func)/sizeof(pdma_dvt_dbg_func[0]) > x) && NULL != pdma_dvt_dbg_func[x])
++ {
++ (*pdma_dvt_dbg_func[x])(x, y);
++ }
++ else
++ {
++ printk("no handler defined for command id(0x%08x)\n\r", x);
++ }
++
++ printk("x(0x%08x), y(0x%08x)\n", x, y);
++
++ return len;
++}
++
++static const struct file_operations pdma_dev_sw_fops = {
++ .owner = THIS_MODULE,
++ .open = PdmaDvtOpen,
++ .read = seq_read,
++ .write = PdmaDvtWrite
++};
++#endif //#if defined(CONFIG_RAETH_PDMA_DVT)
++
++int debug_proc_init(void)
++{
++ if (procRegDir == NULL)
++ procRegDir = proc_mkdir(PROCREG_DIR, NULL);
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++ if ((procGmac = create_proc_entry(PROCREG_GMAC, 0, procRegDir)))
++ procGmac->proc_fops = &gmac_fops;
++ else
++#else
++ if (!(procGmac = proc_create(PROCREG_GMAC, 0, procRegDir, &gmac_fops)))
++#endif
++ printk("!! FAIL to create %s PROC !!\n", PROCREG_GMAC);
++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
++#if defined(CONFIG_PSEUDO_SUPPORT)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++ if ((procGmac2 = create_proc_entry(PROCREG_GMAC2, 0, procRegDir)))
++ procGmac2->proc_fops = &gmac2_fops;
++ else
++#else
++ if (!(procGmac2 = proc_create(PROCREG_GMAC2, 0, procRegDir, &gmac2_fops)))
++#endif
++ printk("!! FAIL to create %s PROC !!\n", PROCREG_GMAC2);
++#endif
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++ if ((procSkbFree = create_proc_entry(PROCREG_SKBFREE, 0, procRegDir)))
++ procSkbFree->proc_fops = &skb_free_fops;
++ else
++#else
++ if (!(procSkbFree = proc_create(PROCREG_SKBFREE, 0, procRegDir, &skb_free_fops)))
++#endif
++ printk("!! FAIL to create %s PROC !!\n", PROCREG_SKBFREE);
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++ if ((procTxRing = create_proc_entry(PROCREG_TXRING, 0, procRegDir)))
++ procTxRing->proc_fops = &tx_ring_fops;
++ else
++#else
++ if (!(procTxRing = proc_create(PROCREG_TXRING, 0, procRegDir, &tx_ring_fops)))
++#endif
++ printk("!! FAIL to create %s PROC !!\n", PROCREG_TXRING);
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++ if ((procRxRing = create_proc_entry(PROCREG_RXRING, 0, procRegDir)))
++ procRxRing->proc_fops = &rx_ring_fops;
++ else
++#else
++ if (!(procRxRing = proc_create(PROCREG_RXRING, 0, procRegDir, &rx_ring_fops)))
++#endif
++ printk("!! FAIL to create %s PROC !!\n", PROCREG_RXRING);
++
++#if defined (CONFIG_RAETH_HW_LRO) || defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++ if ((procRxRing1 = create_proc_entry(PROCREG_RXRING1, 0, procRegDir)))
++ procRxRing1->proc_fops = &rx_ring1_fops;
++ else
++#else
++ if (!(procRxRing1 = proc_create(PROCREG_RXRING1, 0, procRegDir, &rx_ring1_fops)))
++#endif
++ printk("!! FAIL to create %s PROC !!\n", PROCREG_RXRING1);
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++ if ((procRxRing2 = create_proc_entry(PROCREG_RXRING2, 0, procRegDir)))
++ procRxRing2->proc_fops = &rx_ring2_fops;
++ else
++#else
++ if (!(procRxRing2 = proc_create(PROCREG_RXRING2, 0, procRegDir, &rx_ring2_fops)))
++#endif
++ printk("!! FAIL to create %s PROC !!\n", PROCREG_RXRING2);
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++ if ((procRxRing3 = create_proc_entry(PROCREG_RXRING3, 0, procRegDir)))
++ procRxRing3->proc_fops = &rx_ring3_fops;
++ else
++#else
++ if (!(procRxRing3 = proc_create(PROCREG_RXRING3, 0, procRegDir, &rx_ring3_fops)))
++#endif
++ printk("!! FAIL to create %s PROC !!\n", PROCREG_RXRING3);
++#endif /* CONFIG_RAETH_HW_LRO */
++
++#if defined (CONFIG_MIPS)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++ if ((procSysCP0 = create_proc_entry(PROCREG_CP0, 0, procRegDir)))
++ procSysCP0->proc_fops = &cp0_reg_fops;
++ else
++#else
++ if (!(procSysCP0 = proc_create(PROCREG_CP0, 0, procRegDir, &cp0_reg_fops)))
++#endif
++ printk("!! FAIL to create %s PROC !!\n", PROCREG_CP0);
++#endif
++
++#if defined(CONFIG_RAETH_TSO)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++ if ((procNumOfTxd = create_proc_entry(PROCREG_NUM_OF_TXD, 0, procRegDir)))
++ procNumOfTxd->proc_fops = &tso_txd_num_fops;
++ else
++#else
++ if (!(procNumOfTxd = proc_create(PROCREG_NUM_OF_TXD, 0, procRegDir, &tso_txd_num_fops)))
++#endif
++ printk("!! FAIL to create %s PROC !!\n", PROCREG_NUM_OF_TXD);
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++ if ((procTsoLen = create_proc_entry(PROCREG_TSO_LEN, 0, procRegDir)))
++ procTsoLen->proc_fops = &tso_len_fops;
++ else
++#else
++ if (!(procTsoLen = proc_create(PROCREG_TSO_LEN, 0, procRegDir, &tso_len_fops)))
++#endif
++ printk("!! FAIL to create %s PROC !!\n", PROCREG_TSO_LEN);
++#endif
++
++#if defined(CONFIG_RAETH_LRO)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++ if ((procLroStats = create_proc_entry(PROCREG_LRO_STATS, 0, procRegDir)))
++ procLroStats->proc_fops = &lro_stats_fops;
++ else
++#else
++ if (!(procLroStats = proc_create(PROCREG_LRO_STATS, 0, procRegDir, &lro_stats_fops)))
++#endif
++ printk("!! FAIL to create %s PROC !!\n", PROCREG_LRO_STATS);
++#endif
++
++#if defined(CONFIG_RAETH_HW_LRO)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++ if ((procHwLroStats = create_proc_entry(PROCREG_HW_LRO_STATS, 0, procRegDir)))
++ procHwLroStats->proc_fops = &hw_lro_stats_fops;
++ else
++#else
++ if (!(procHwLroStats = proc_create(PROCREG_HW_LRO_STATS, 0, procRegDir, &hw_lro_stats_fops)))
++#endif
++ printk("!! FAIL to create %s PROC !!\n", PROCREG_HW_LRO_STATS);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++ if ((procHwLroAutoTlb = create_proc_entry(PROCREG_HW_LRO_AUTO_TLB, 0, procRegDir)))
++ procHwLroAutoTlb->proc_fops = &hw_lro_auto_tlb_fops;
++ else
++#else
++ if (!(procHwLroAutoTlb = proc_create(PROCREG_HW_LRO_AUTO_TLB, 0, procRegDir, &hw_lro_auto_tlb_fops)))
++#endif
++ printk("!! FAIL to create %s PROC !!\n", PROCREG_HW_LRO_AUTO_TLB);
++#endif /* CONFIG_RAETH_HW_LRO */
++
++#if defined(CONFIG_RAETH_QOS)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++ if ((procRaQOS = create_proc_entry(PROCREG_RAQOS, 0, procRegDir)))
++ procRaQOS->proc_fops = &raeth_qos_fops;
++ else
++#else
++ if (!(procRaQOS = proc_create(PROCREG_RAQOS, 0, procRegDir, &raeth_qos_fops)))
++#endif
++ printk("!! FAIL to create %s PROC !!\n", PROCREG_RAQOS);
++#endif
++
++#if defined(CONFIG_USER_SNMPD)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++ if ((procRaSnmp = create_proc_entry(PROCREG_SNMP, S_IRUGO, procRegDir)))
++ procRaSnmp->proc_fops = &ra_snmp_seq_fops;
++ else
++#else
++ if (!(procRaSnmp = proc_create(PROCREG_SNMP, S_IRUGO, procRegDir, &ra_snmp_seq_fops)))
++#endif
++ printk("!! FAIL to create %s PROC !!\n", PROCREG_SNMP);
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++ if ((procEswCnt = create_proc_entry(PROCREG_ESW_CNT, 0, procRegDir)))
++ procEswCnt->proc_fops = &switch_count_fops;
++ else
++#else
++ if (!(procEswCnt = proc_create(PROCREG_ESW_CNT, 0, procRegDir, &switch_count_fops)))
++#endif
++ printk("!! FAIL to create %s PROC !!\n", PROCREG_ESW_CNT);
++
++#if defined (TASKLET_WORKQUEUE_SW)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++ if ((procSCHE = create_proc_entry(PROCREG_SCHE, 0, procRegDir)))
++ procSCHE->proc_fops = &schedule_sw_fops;
++ else
++#else
++ if (!(procSCHE = proc_create(PROCREG_SCHE, 0, procRegDir, &schedule_sw_fops)))
++#endif
++ printk("!! FAIL to create %s PROC !!\n", PROCREG_SCHE);
++#endif
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++ if ((procPdmaDvt = create_proc_entry(PROCREG_PDMA_DVT, 0, procRegDir)))
++ procPdmaDvt->proc_fops = &pdma_dev_sw_fops;
++ else
++#else
++ if (!(procPdmaDvt = proc_create(PROCREG_PDMA_DVT, 0, procRegDir, &pdma_dev_sw_fops )))
++#endif
++ printk("!! FAIL to create %s PROC !!\n", PROCREG_PDMA_DVT);
++#endif //#if defined(CONFIG_RAETH_PDMA_DVT)
++
++ printk(KERN_ALERT "PROC INIT OK!\n");
++ return 0;
++}
++
++void debug_proc_exit(void)
++{
++
++ if (procSysCP0)
++ remove_proc_entry(PROCREG_CP0, procRegDir);
++
++ if (procGmac)
++ remove_proc_entry(PROCREG_GMAC, procRegDir);
++#if defined(CONFIG_PSEUDO_SUPPORT) && defined(CONFIG_ETHTOOL)
++ if (procGmac)
++ remove_proc_entry(PROCREG_GMAC, procRegDir);
++#endif
++ if (procSkbFree)
++ remove_proc_entry(PROCREG_SKBFREE, procRegDir);
++
++ if (procTxRing)
++ remove_proc_entry(PROCREG_TXRING, procRegDir);
++
++ if (procRxRing)
++ remove_proc_entry(PROCREG_RXRING, procRegDir);
++
++#if defined(CONFIG_RAETH_TSO)
++ if (procNumOfTxd)
++ remove_proc_entry(PROCREG_NUM_OF_TXD, procRegDir);
++
++ if (procTsoLen)
++ remove_proc_entry(PROCREG_TSO_LEN, procRegDir);
++#endif
++
++#if defined(CONFIG_RAETH_LRO)
++ if (procLroStats)
++ remove_proc_entry(PROCREG_LRO_STATS, procRegDir);
++#endif
++
++#if defined(CONFIG_RAETH_QOS)
++ if (procRaQOS)
++ remove_proc_entry(PROCREG_RAQOS, procRegDir);
++ if (procRaFeIntr)
++ remove_proc_entry(PROCREG_RXDONE_INTR, procRegDir);
++ if (procRaEswIntr)
++ remove_proc_entry(PROCREG_ESW_INTR, procRegDir);
++#endif
++
++#if defined(CONFIG_USER_SNMPD)
++ if (procRaSnmp)
++ remove_proc_entry(PROCREG_SNMP, procRegDir);
++#endif
++
++ if (procEswCnt)
++ remove_proc_entry(PROCREG_ESW_CNT, procRegDir);
++
++ //if (procRegDir)
++ //remove_proc_entry(PROCREG_DIR, 0);
++
++ printk(KERN_ALERT "proc exit\n");
++}
++EXPORT_SYMBOL(procRegDir);
+diff --git a/drivers/net/ethernet/raeth/ra_mac.h b/drivers/net/ethernet/raeth/ra_mac.h
+new file mode 100644
+index 0000000..66b32d3
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_mac.h
+@@ -0,0 +1,57 @@
++#ifndef RA_MAC_H
++#define RA_MAC_H
++
++void ra2880stop(END_DEVICE *ei_local);
++void ra2880MacAddressSet(unsigned char p[6]);
++void ra2880Mac2AddressSet(unsigned char p[6]);
++void ethtool_init(struct net_device *dev);
++
++void ra2880EnableInterrupt(void);
++
++void dump_qos(void);
++void dump_reg(struct seq_file *s);
++void dump_cp0(void);
++
++int debug_proc_init(void);
++void debug_proc_exit(void);
++
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined (CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621)
++void enable_auto_negotiate(int unused);
++#else
++void enable_auto_negotiate(int ge);
++#endif
++
++void rt2880_gmac_hard_reset(void);
++
++int TsoLenUpdate(int tso_len);
++int NumOfTxdUpdate(int num_of_txd);
++
++#ifdef CONFIG_RAETH_LRO
++int LroStatsUpdate(struct net_lro_mgr *lro_mgr, bool all_flushed);
++#endif
++#ifdef CONFIG_RAETH_HW_LRO
++int HwLroStatsUpdate(unsigned int ring_num, unsigned int agg_cnt, unsigned int agg_size);
++#if defined(CONFIG_RAETH_HW_LRO_REASON_DBG)
++#define HW_LRO_AGG_FLUSH (1)
++#define HW_LRO_AGE_FLUSH (2)
++#define HW_LRO_NOT_IN_SEQ_FLUSH (3)
++#define HW_LRO_TIMESTAMP_FLUSH (4)
++#define HW_LRO_NON_RULE_FLUSH (5)
++int HwLroFlushStatsUpdate(unsigned int ring_num, unsigned int flush_reason);
++#endif /* CONFIG_RAETH_HW_LRO_REASON_DBG */
++typedef int (*HWLRO_DBG_FUNC)(int par1, int par2);
++int hwlro_agg_cnt_ctrl(int par1, int par2);
++int hwlro_agg_time_ctrl(int par1, int par2);
++int hwlro_age_time_ctrl(int par1, int par2);
++int hwlro_pkt_int_alpha_ctrl(int par1, int par2);
++int hwlro_threshold_ctrl(int par1, int par2);
++int hwlro_fix_setting_switch_ctrl(int par1, int par2);
++#endif /* CONFIG_RAETH_HW_LRO */
++int getnext(const char *src, int separator, char *dest);
++int str_to_ip(unsigned int *ip, const char *str);
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++typedef int (*PDMA_DBG_FUNC)(int par1, int par2);
++#endif //#if defined(CONFIG_RAETH_PDMA_DVT)
++#endif
+diff --git a/drivers/net/ethernet/raeth/ra_netlink.c b/drivers/net/ethernet/raeth/ra_netlink.c
+new file mode 100644
+index 0000000..f7c3650
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_netlink.c
+@@ -0,0 +1,142 @@
++// for netlink header
++#include <asm/types.h>
++#include <net/sock.h>
++#include <linux/socket.h>
++#include <linux/netlink.h>
++#include <linux/skbuff.h>
++#include <linux/net.h>
++#include <linux/version.h>
++
++#include "csr_netlink.h"
++#include "ra2882ethreg.h"
++#include "ra_netlink.h"
++
++static struct sock *csr_msg_socket = NULL; // synchronize socket for netlink use
++unsigned int flags;
++
++void rt2880_csr_receiver(struct sock *sk, int len)
++{
++ struct sk_buff *skb;
++ int err;
++ struct nlmsghdr *nlh;
++ unsigned int reg_value = 0;
++ CSR_MSG *csrmsg;
++ RAETH_PRINT("csr netlink receiver!\n");
++ skb = skb_recv_datagram(sk, 0, 1, &err);
++
++ RAETH_PRINT("error no : %d\n", err);
++
++ if (skb == NULL) {
++ printk("rt2880_csr_receiver(): No data received, error!\n");
++ return;
++ }
++
++ nlh = (struct nlmsghdr*)skb->data;
++
++ csrmsg = NLMSG_DATA(nlh);
++
++ if (csrmsg->enable == CSR_READ ) {
++ reg_value = sysRegRead(csrmsg->address);
++#if 0
++ printk("raeth -- 0x%08x: 0x%08x\n", csrmsg->address, reg_value);
++#endif
++ } else if ( csrmsg->enable == CSR_WRITE ) {
++ sysRegWrite(csrmsg->address, csrmsg->default_value);
++ reg_value = sysRegRead(csrmsg->address);
++ } else if ( csrmsg->enable == CSR_TEST ) {
++ reg_value = sysRegRead(csrmsg->address);
++ printk("0x%08x: 0x%08x\n", (unsigned int)csrmsg->address, reg_value);
++ }
++ else
++ printk("drv: Command format error!\n");
++
++ csrmsg->default_value = reg_value;
++
++ RAETH_PRINT("drv: rt2880_csr_msgsend() - msg to send!\n");
++
++ err = rt2880_csr_msgsend(csrmsg);
++
++ if ( err == -2 )
++ printk("drv: msg send error!\n");
++
++ skb_free_datagram(sk, skb);
++}
++
++int rt2880_csr_msgsend(CSR_MSG* csrmsg)
++{
++ struct sk_buff *skb;
++ struct nlmsghdr *nlh = NULL;
++ size_t size = 0;
++ struct sock *send_syncnl = csr_msg_socket;
++
++ CSR_MSG* csr_reg;
++ if (send_syncnl == NULL) {
++ printk("drv: netlink_kernel_create() failed!\n");
++ return -1;
++ }
++
++ size = NLMSG_SPACE(sizeof(CSR_MSG));
++ skb = alloc_skb(size, GFP_ATOMIC);
++
++ if(!skb)
++ {
++ printk("rt2880_csr_msgsend() : error! msg structure not available\n");
++ return -1;
++ }
++
++ nlh = NLMSG_PUT(skb, 0, 0, RALINK_CSR_GROUP, size - sizeof(struct nlmsghdr));
++
++ if (!nlh)
++ {
++ printk("rt2880_csr_msgsend() : error! nlh structure not available\n");
++ return -1;
++ }
++
++ csr_reg = NLMSG_DATA(nlh);
++ if (!csr_reg)
++ {
++ printk("rt2880_csr_msgsend() : error! nlh structure not available\n");
++ return -1;
++ }
++
++ csr_reg->address = csrmsg->address;
++ csr_reg->default_value = csrmsg->default_value;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
++ NETLINK_CB(skb).dst_group = RALINK_CSR_GROUP;
++#else
++ NETLINK_CB(skb).dst_groups = RALINK_CSR_GROUP;
++#endif
++ netlink_broadcast(send_syncnl, skb, 0, RALINK_CSR_GROUP, GFP_ATOMIC);
++ return 0;
++
++nlmsg_failure:
++ return -2;
++}
++
++int csr_netlink_init()
++{
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
++ csr_msg_socket = netlink_kernel_create(NETLINK_CSR, RALINK_CSR_GROUP, rt2880_csr_receiver, THIS_MODULE);
++#else
++ csr_msg_socket = netlink_kernel_create(NETLINK_CSR, rt2880_csr_receiver);
++#endif
++
++ if ( csr_msg_socket == NULL )
++ printk("unable to create netlink socket!\n");
++ else
++ printk("Netlink init ok!\n");
++ return 0;
++}
++
++void csr_netlink_end()
++{
++ if (csr_msg_socket != NULL){
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
++ sock_release(csr_msg_socket->sk_socket);
++#else
++ sock_release(csr_msg_socket->socket);
++#endif
++ printk("Netlink end...\n");
++ }
++}
+diff --git a/drivers/net/ethernet/raeth/ra_netlink.h b/drivers/net/ethernet/raeth/ra_netlink.h
+new file mode 100644
+index 0000000..19ca71f
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_netlink.h
+@@ -0,0 +1,10 @@
++#ifndef RA_NETLINK
++#define RA_NETLINK
++
++#include "csr_netlink.h"
++int rt2880_csr_msgsend(CSR_MSG* csrmsg);
++void rt2880_csr_receiver(struct sock *sk, int len);
++int csr_netlink_init(void);
++void csr_netlink_end(void);
++
++#endif
+diff --git a/drivers/net/ethernet/raeth/ra_qos.c b/drivers/net/ethernet/raeth/ra_qos.c
+new file mode 100644
+index 0000000..0a7d9c5
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_qos.c
+@@ -0,0 +1,655 @@
++#include <asm/io.h>
++#include <linux/pci.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/net.h>
++#include <linux/in.h>
++#include "ra_qos.h"
++#include "raether.h"
++#include "ra2882ethreg.h"
++
++#include <asm/types.h>
++#include <net/sock.h>
++#include <linux/socket.h>
++#include <linux/skbuff.h>
++#include <linux/net.h>
++#include <linux/if_vlan.h>
++#include <linux/ip.h>
++
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++#include "../../../net/nat/hw_nat/ra_nat.h"
++#endif
++
++#define CONTI_TX_SEND_MAX_SIZE 1440
++
++/*
++ * set tx queue # to descriptor
++ */
++void rt3052_tx_queue_init(unsigned long data)
++{
++ /* define qos p */
++
++}
++
++void rt3052_pse_port0_fc_clear(unsigned long data)
++{
++ /* clear FE_INT_STATUS.PSE_P0_FC */
++
++}
++
++inline int get_tx_ctx_idx(unsigned int ring_no, unsigned long *idx)
++{
++ switch (ring_no) {
++ case RING0:
++ *idx = *(unsigned long*)TX_CTX_IDX0;
++ break;
++ case RING1:
++ *idx = *(unsigned long*)TX_CTX_IDX1;
++ break;
++ case RING2:
++ *idx = *(unsigned long*)TX_CTX_IDX2;
++ break;
++ case RING3:
++ *idx = *(unsigned long*)TX_CTX_IDX3;
++ break;
++ default:
++ printk("set_tx_ctx_idex error\n");
++ return -1;
++ };
++ return 0;
++}
++
++inline int set_tx_ctx_idx(unsigned int ring_no, unsigned int idx)
++{
++ switch (ring_no ) {
++ case RING0:
++ *(unsigned long*)TX_CTX_IDX0 = cpu_to_le32((u32)idx);
++ break;
++ case RING1:
++ *(unsigned long*)TX_CTX_IDX1 = cpu_to_le32((u32)idx);
++ break;
++ case RING2:
++ *(unsigned long*)TX_CTX_IDX2 = cpu_to_le32((u32)idx);
++ break;
++ case RING3:
++ *(unsigned long*)TX_CTX_IDX3 = cpu_to_le32((u32)idx);
++ break;
++ default:
++ printk("set_tx_ctx_idex error\n");
++ return -1;
++ };
++
++ return 1;
++}
++
++void get_tx_desc_and_dtx_idx(END_DEVICE* ei_local, int ring_no, unsigned long *tx_dtx_idx, struct PDMA_txdesc **tx_desc)
++{
++ switch (ring_no) {
++ case RING0:
++ *tx_desc = ei_local->tx_ring0;
++ *tx_dtx_idx = *(unsigned long*)TX_DTX_IDX0;
++ break;
++ case RING1:
++ *tx_desc = ei_local->tx_ring1;
++ *tx_dtx_idx = *(unsigned long*)TX_DTX_IDX1;
++ break;
++ case RING2:
++ *tx_desc = ei_local->tx_ring2;
++ *tx_dtx_idx = *(unsigned long*)TX_DTX_IDX2;
++ break;
++ case RING3:
++ *tx_desc = ei_local->tx_ring3;
++ *tx_dtx_idx = *(unsigned long*)TX_DTX_IDX3;
++ break;
++ default:
++ printk("ring_no input error... %d\n", ring_no);
++ };
++}
++
++int fe_qos_packet_send(struct net_device *dev, struct sk_buff* skb, unsigned int ring_no, unsigned int qn, unsigned pn)
++{
++ END_DEVICE* ei_local = netdev_priv(dev);
++ struct PDMA_txdesc* tx_desc;
++ unsigned int tx_cpu_owner_idx, tx_dtx_idx;
++
++ unsigned int length=skb->len;
++ int ret;
++ unsigned long flags;
++
++ //printk("fe_qos_packet_send: ring_no=%d qn=%d pn=%d\n", ring_no, qn, pn);
++
++ switch ( ring_no ) {
++ case 0:
++ tx_desc = ei_local->tx_ring0;
++ tx_cpu_owner_idx = *(unsigned long*)TX_CTX_IDX0;
++ tx_dtx_idx = *(unsigned long*)TX_DTX_IDX0;
++ break;
++ case 1:
++ tx_desc = ei_local->tx_ring1;
++ tx_cpu_owner_idx = *(unsigned long*)TX_CTX_IDX1;
++ tx_dtx_idx = *(unsigned long*)TX_DTX_IDX1;
++ break;
++ case 2:
++ tx_desc = ei_local->tx_ring2;
++ tx_cpu_owner_idx = *(unsigned long*)TX_CTX_IDX2;
++ tx_dtx_idx = *(unsigned long*)TX_DTX_IDX2;
++ break;
++ case 3:
++ tx_desc = ei_local->tx_ring3;
++ tx_cpu_owner_idx = *(unsigned long*)TX_CTX_IDX3;
++ tx_dtx_idx = *(unsigned long*)TX_DTX_IDX3;
++ break;
++ default:
++ printk("ring_no input error... %d\n", ring_no);
++ return -1;
++ };
++
++ //printk("tx_cpu_owner_idx=%d tx_dtx_idx=%d\n", tx_cpu_owner_idx, tx_dtx_idx);
++
++ if(tx_desc == NULL) {
++ printk("%s : txdesc is NULL\n", dev->name);
++ return -1;
++ }
++
++ tx_desc[tx_cpu_owner_idx].txd_info1.SDP0 = virt_to_phys(skb->data);
++ tx_desc[tx_cpu_owner_idx].txd_info2.SDL0 = length;
++ tx_desc[tx_cpu_owner_idx].txd_info2.DDONE_bit = 0;
++ tx_desc[tx_cpu_owner_idx].txd_info4.PN = pn;
++ tx_desc[tx_cpu_owner_idx].txd_info4.QN = qn;
++
++#ifdef CONFIG_RAETH_CHECKSUM_OFFLOAD
++ ei_local->tx_ring0[tx_cpu_owner_idx].txd_info4.TCO = 1;
++ ei_local->tx_ring0[tx_cpu_owner_idx].txd_info4.UCO = 1;
++ ei_local->tx_ring0[tx_cpu_owner_idx].txd_info4.ICO = 1;
++#endif
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++ if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) {
++ tx_desc[tx_cpu_owner_idx].txd_info4.PN = 6; /* PPE */
++ } else {
++ tx_desc[tx_cpu_owner_idx].txd_info4.PN = pn;
++ }
++
++#endif
++
++ spin_lock_irqsave(&ei_local->page_lock, flags);
++ ei_local->skb_free[ring_no][tx_cpu_owner_idx] = skb;
++ tx_cpu_owner_idx = (tx_cpu_owner_idx +1) % NUM_TX_DESC;
++ ret = set_tx_ctx_idx(ring_no, tx_cpu_owner_idx);
++ spin_unlock_irqrestore(&ei_local->page_lock, flags);
++
++ ei_local->stat.tx_packets++;
++ ei_local->stat.tx_bytes += length;
++
++#ifdef CONFIG_RAETH_NAPI
++ switch ( ring_no ) {
++ case 0:
++ if ( ei_local->tx0_full == 1) {
++ ei_local->tx0_full = 0;
++ netif_wake_queue(dev);
++ }
++ break;
++ case 1:
++ if ( ei_local->tx1_full == 1) {
++ ei_local->tx1_full = 0;
++ netif_wake_queue(dev);
++ }
++ break;
++ case 2:
++ if ( ei_local->tx2_full == 1) {
++ ei_local->tx2_full = 0;
++ netif_wake_queue(dev);
++ }
++ break;
++ case 3:
++ if ( ei_local->tx3_full == 1) {
++ ei_local->tx3_full = 0;
++ netif_wake_queue(dev);
++ }
++ break;
++ default :
++ printk("ring_no input error %d\n", ring_no);
++ };
++#endif
++ return length;
++}
++
++int fe_tx_desc_init(struct net_device *dev, unsigned int ring_no, unsigned int qn, unsigned int pn)
++{
++ END_DEVICE* ei_local = netdev_priv(dev);
++ struct PDMA_txdesc *tx_desc;
++ unsigned int tx_cpu_owner_idx = 0;
++ int i;
++ unsigned int phy_tx_ring;
++
++ // sanity check
++ if ( ring_no > 3 ){
++ printk("%s : ring_no - %d, please under 4...\n", dev->name, ring_no);
++ return 0;
++ }
++
++ if ( pn > 2 ){
++ printk("%s : pn - %d, please under 2...\n", dev->name, pn);
++ return 0;
++ }
++
++ tx_desc = pci_alloc_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), &phy_tx_ring);
++ ei_local->tx_cpu_owner_idx0 = tx_cpu_owner_idx;
++
++ switch (ring_no) {
++ case 0:
++ ei_local->tx_ring0 = tx_desc;
++ ei_local->phy_tx_ring0 = phy_tx_ring;
++ break;
++ case 1:
++ ei_local->phy_tx_ring1 = phy_tx_ring;
++ ei_local->tx_ring1 = tx_desc;
++ break;
++ case 2:
++ ei_local->phy_tx_ring2 = phy_tx_ring;
++ ei_local->tx_ring2 = tx_desc;
++ break;
++ case 3:
++ ei_local->phy_tx_ring3 = phy_tx_ring;
++ ei_local->tx_ring3 = tx_desc;
++ break;
++ default:
++ printk("ring_no input error! %d\n", ring_no);
++ pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), tx_desc, phy_tx_ring);
++ return 0;
++ };
++
++ if ( tx_desc == NULL)
++ {
++ printk("tx desc allocation failed!\n");
++ return 0;
++ }
++
++ for( i = 0; i < NUM_TX_DESC; i++) {
++ memset( &tx_desc[i], 0, sizeof(struct PDMA_txdesc));
++ tx_desc[i].txd_info2.LS0_bit = 1;
++ tx_desc[i].txd_info2.DDONE_bit = 1;
++ tx_desc[i].txd_info4.PN = pn;
++ tx_desc[i].txd_info4.QN = qn;
++ }
++
++ switch ( ring_no ) {
++ case 0 :
++ *(unsigned long*)TX_BASE_PTR0 = phys_to_bus((u32) phy_tx_ring);
++ *(unsigned long*)TX_MAX_CNT0 = cpu_to_le32((u32)NUM_TX_DESC);
++ *(unsigned long*)TX_CTX_IDX0 = cpu_to_le32((u32) tx_cpu_owner_idx);
++ sysRegWrite(PDMA_RST_CFG, PST_DTX_IDX0);
++ break;
++ case 1 :
++ *(unsigned long*)TX_BASE_PTR1 = phys_to_bus((u32) phy_tx_ring);
++ *(unsigned long*)TX_MAX_CNT1 = cpu_to_le32((u32)NUM_TX_DESC);
++ *(unsigned long*)TX_CTX_IDX1 = cpu_to_le32((u32) tx_cpu_owner_idx);
++ sysRegWrite(PDMA_RST_CFG, PST_DTX_IDX1);
++ break;
++ case 2 :
++ *(unsigned long*)TX_BASE_PTR2 = phys_to_bus((u32) phy_tx_ring);
++ *(unsigned long*)TX_MAX_CNT2 = cpu_to_le32((u32)NUM_TX_DESC);
++ *(unsigned long*)TX_CTX_IDX2 = cpu_to_le32((u32) tx_cpu_owner_idx);
++ sysRegWrite(PDMA_RST_CFG, PST_DTX_IDX2);
++ break;
++ case 3 :
++ *(unsigned long*)TX_BASE_PTR3 = phys_to_bus((u32) phy_tx_ring);
++ *(unsigned long*)TX_MAX_CNT3 = cpu_to_le32((u32)NUM_TX_DESC);
++ *(unsigned long*)TX_CTX_IDX3 = cpu_to_le32((u32) tx_cpu_owner_idx);
++ sysRegWrite(PDMA_RST_CFG, PST_DTX_IDX3);
++ break;
++ default :
++ printk("tx descriptor init failed %d\n", ring_no);
++ return 0;
++ };
++ return 1;
++}
++
++/*
++ DSCP | AC | WMM_AC (Access Category)
++ ------+----+--------
++ 00-07| 1 | BE
++ 24-31| 1 | BE
++ 08-15| 0 | BG
++ 16-23| 0 | BG
++ 32-39| 2 | VI
++ 40-47| 2 | VI
++ 48-55| 3 | VO
++ 56-63| 3 | VO
++
++ | TOS |
++ DSCP |(bit5~bit7)| WMM
++ -------+-----------+-------
++ 0x00 | 000 | BE
++ 0x18 | 011 | BE
++ 0x08 | 001 | BG
++ 0x10 | 010 | BG
++ 0x20 | 100 | VI
++ 0x28 | 101 | VI
++ 0x30 | 110 | VO
++ 0x38 | 111 | VO
++
++ Notes: BE should be mapped to AC1, but mapped to AC0 in linux kernel.
++
++ */
++
++int pkt_classifier(struct sk_buff *skb,int gmac_no, int *ring_no, int *queue_no, int *port_no)
++{
++#if defined(CONFIG_RALINK_RT2880)
++ /* RT2880 -- Assume using 1 Ring (Ring0), Queue 0, and Port 0 */
++ *port_no = 0;
++ *ring_no = 0;
++ *queue_no = 0;
++#else
++ unsigned int ac=0;
++ unsigned int bridge_traffic=0, lan_traffic=0;
++ struct iphdr *iph=NULL;
++ struct vlan_ethhdr *veth=NULL;
++ unsigned int vlan_id=0;
++#if defined (CONFIG_RAETH_QOS_DSCP_BASED)
++ static char DscpToAcMap[8]={1,0,0,1,2,2,3,3};
++#elif defined (CONFIG_RAETH_QOS_VPRI_BASED)
++ static char VlanPriToAcMap[8]={1,0,0,1,2,2,3,3};
++#endif
++
++ /* Bridge:: {BG,BE,VI,VO} */
++ /* GateWay:: WAN: {BG,BE,VI,VO}, LAN: {BG,BE,VI,VO} */
++#if defined (CONFIG_RALINK_RT3883) && defined (CONFIG_RAETH_GMAC2)
++ /*
++ * 1) Bridge:
++ * 1.1) GMAC1 ONLY:
++ * VO/VI->Ring3, BG/BE->Ring2
++ * 1.2) GMAC1+GMAC2:
++ * GMAC1:: VO/VI->Ring3, BG/BE->Ring2
++ * GMAC2:: VO/VI->Ring1, BG/BE->Ring0
++ * 2) GateWay:
++ * 2.1) GMAC1 ONLY:
++ * GMAC1:: LAN:VI/VO->Ring2, BE/BK->Ring2
++ * WAN:VI/VO->Ring3, BE/BK->Ring3
++ * 2.2)GMAC1+GMAC2:
++ * GMAC1:: LAN:VI/VO/BE/BK->Ring2, WAN:VI/VO/BE/BK->Ring3
++ * GMAC2:: VI/VO->Ring1, BE/BK->Ring0
++ */
++ static unsigned char AcToRing_BridgeMap[4] = {2, 2, 3, 3};
++ static unsigned char AcToRing_GE1Map[2][4] = {{3, 3, 3, 3},{2, 2, 2, 2}};
++ static unsigned char AcToRing_GE2Map[4] = {0, 0, 1, 1};
++#elif defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT2883) || \
++ defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || \
++ defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined (CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || \
++ defined (CONFIG_RALINK_MT7628) || \
++ (defined (CONFIG_RALINK_RT3883) && !defined(CONFIG_RAETH_GMAC2))
++ /*
++ * 1) Bridge: VO->Ring3, VI->Ring2, BG->Ring1, BE->Ring0
++ * 2) GateWay:
++ * 2.1) GMAC1:: LAN:VI/VO->Ring1, BE/BK->Ring0
++ * WAN:VI/VO->Ring3, BE/BK->Ring2
++ */
++ static unsigned char AcToRing_BridgeMap[4] = {0, 1, 2, 3};
++ static unsigned char AcToRing_GE1Map[2][4] = {{2, 2, 3, 3},{0, 0, 1, 1}};
++#endif // CONFIG_RALINK_RT2883
++
++ /*
++ * Set queue no - QN field in TX Descriptor
++ * always use queue 3 for the packet from CPU to GMAC
++ */
++ *queue_no = 3;
++
++ /* Get access category */
++ veth = (struct vlan_ethhdr *)(skb->data);
++ if(veth->h_vlan_proto == htons(ETH_P_8021Q)) { // VLAN traffic
++ iph= (struct iphdr *)(skb->data + VLAN_ETH_HLEN);
++
++ vlan_id = ntohs(veth->h_vlan_TCI & VLAN_VID_MASK);
++ if(vlan_id==1) { //LAN
++ lan_traffic = 1;
++ } else { //WAN
++ lan_traffic = 0;
++ }
++
++ if (veth->h_vlan_encapsulated_proto == htons(ETH_P_IP)) { //IPv4
++#if defined (CONFIG_RAETH_QOS_DSCP_BASED)
++ ac = DscpToAcMap[(iph->tos & 0xe0) >> 5];
++#elif defined (CONFIG_RAETH_QOS_VPRI_BASED)
++ ac = VlanPriToAcMap[skb->priority];
++#endif
++ }else { //Ipv6, ARP ...etc
++ ac = 0;
++ }
++ }else { // non-VLAN traffic
++ if (veth->h_vlan_proto == htons(ETH_P_IP)) { //IPv4
++#if defined (CONFIG_RAETH_QOS_DSCP_BASED)
++ iph= (struct iphdr *)(skb->data + ETH_HLEN);
++ ac = DscpToAcMap[(iph->tos & 0xe0) >> 5];
++#elif defined (CONFIG_RAETH_QOS_VPRI_BASED)
++ ac= VlanPriToAcMap[skb->priority];
++#endif
++ }else { // IPv6, ARP ...etc
++ ac = 0;
++ }
++
++ bridge_traffic=1;
++ }
++
++
++ /* Set Tx Ring no */
++ if(gmac_no==1) { //GMAC1
++ if(bridge_traffic) { //Bridge Mode
++ *ring_no = AcToRing_BridgeMap[ac];
++ }else { //GateWay Mode
++ *ring_no = AcToRing_GE1Map[lan_traffic][ac];
++ }
++ }else { //GMAC2
++#if defined (CONFIG_RALINK_RT3883) && defined (CONFIG_RAETH_GMAC2)
++ *ring_no = AcToRing_GE2Map[ac];
++#endif
++ }
++
++
++ /* Set Port No - PN field in Tx Descriptor*/
++#if defined(CONFIG_RAETH_GMAC2)
++ *port_no = gmac_no;
++#else
++ if(bridge_traffic) {
++ *port_no = 1;
++ }else {
++ if(lan_traffic==1) { //LAN use VP1
++ *port_no = 1;
++ }else { //WAN use VP2
++ *port_no = 2;
++ }
++ }
++#endif // CONFIG_RAETH_GMAC2 //
++
++#endif
++
++ return 1;
++
++}
++
++
++/*
++ * Routine Description :
++ * Hi/Li Rings and Queues definition for QoS Purpose
++ *
++ * Related registers: (Detail information refer to pp106 of RT3052_DS_20080226.doc)
++ * Priority High/Low Definition - PDMA_FC_CFG, GDMA1_FC_CFG, GDMA2_FC_CFG
++ * Bit 28 - Allows high priority Q to share low priority Q's reserved pages
++ * Bit 27:24 - Px high priority definition bitmap
++ * Weight Configuration - GDMA1_SCH_CFG, GDMA2_SCH_CFG, PDMA_SCH_CFG -> default 3210
++ *
++ * Parameter:
++ * NONE
++ *
++*/
++#define PSE_P1_LQ_FULL (1<<2)
++#define PSE_P1_HQ_FULL (1<<3)
++#define PSE_P2_LQ_FULL (1<<4)
++#define PSE_P2_HQ_FULL (1<<5)
++
++#define HIGH_QUEUE(queue) (1<<(queue))
++#define LOW_QUEUE(queue) (0<<(queue))
++#define PAGES_SHARING (1<<28)
++#define RSEV_PAGE_COUNT_HQ 0x10 /* Reserved page count for high priority Q */
++#define RSEV_PAGE_COUNT_LQ 0x10 /* Reserved page count for low priority Q */
++#define VIQ_FC_ASRT 0x10 /* Virtual input Q FC assertion threshold */
++
++#define QUEUE_WEIGHT_1 0
++#define QUEUE_WEIGHT_2 1
++#define QUEUE_WEIGHT_4 2
++#define QUEUE_WEIGHT_8 3
++#define QUEUE_WEIGHT_16 4
++
++#define WRR_SCH 0 /*WRR */
++#define STRICT_PRI_SCH 1 /* Strict Priority */
++#define MIX_SCH 2 /* Mixed : Q3>WRR(Q2,Q1,Q0) */
++
++/*
++ * Ring3 Ring2 Ring1 Ring0
++ * | | | | | | | |
++ * | | | | | | | |
++ * --------------------------------
++ * | WRR Scheduler |
++ * --------------------------------
++ * |
++ * ---------------------------------------
++ * | PDMA |
++ * ---------------------------------------
++ * |Q3||Q2||Q1||Q0| |Q3||Q2||Q1||Q0|
++ * | || || || | | || || || |
++ * ------------------- -------------------
++ * | GDMA2 | | GDMA1 |
++ * ------------------- -------------------
++ * | |
++ * ------------------------------------
++ * | GMAC |
++ * ------------------------------------
++ * |
++ *
++ */
++void set_scheduler_weight(void)
++{
++#if !defined (CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628)
++ /*
++ * STEP1: Queue scheduling configuration
++ */
++ *(unsigned long *)GDMA1_SCH_CFG = (WRR_SCH << 24) |
++ (QUEUE_WEIGHT_16 << 12) | /* queue 3 weight */
++ (QUEUE_WEIGHT_8 << 8) | /* queue 2 weight */
++ (QUEUE_WEIGHT_4 << 4) | /* queue 1 weight */
++ (QUEUE_WEIGHT_2 << 0); /* queue 0 weight */
++
++ *(unsigned long *)GDMA2_SCH_CFG = (WRR_SCH << 24) |
++ (QUEUE_WEIGHT_16 << 12) | /* queue 3 weight */
++ (QUEUE_WEIGHT_8 << 8) | /* queue 2 weight */
++ (QUEUE_WEIGHT_4 << 4) | /* queue 1 weight */
++ (QUEUE_WEIGHT_2 << 0); /* queue 0 weight */
++
++#endif
++ /*
++ * STEP2: Ring scheduling configuration
++ */
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined (CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621)
++ /* MIN_RATE_RATIO0=0, MAX_RATE_ULMT0=1, Weight0=1 */
++ *(unsigned long *)SCH_Q01_CFG = (0 << 10) | (1<<14) | (0 << 12);
++ /* MIN_RATE_RATIO1=0, MAX_RATE_ULMT1=1, Weight1=4 */
++ *(unsigned long *)SCH_Q01_CFG |= (0 << 26) | (1<<30) | (2 << 28);
++
++ /* MIN_RATE_RATIO2=0, MAX_RATE_ULMT2=1, Weight0=1 */
++ *(unsigned long *)SCH_Q23_CFG = (0 << 10) | (1<<14) | (0 << 12);
++ /* MIN_RATE_RATIO3=0, MAX_RATE_ULMT3=1, Weight1=4 */
++ *(unsigned long *)SCH_Q23_CFG |= (0 << 26) | (1<<30) | (2 << 28);
++#else
++ *(unsigned long *)PDMA_SCH_CFG = (WRR_SCH << 24) |
++ (QUEUE_WEIGHT_16 << 12) | /* ring 3 weight */
++ (QUEUE_WEIGHT_4 << 8) | /* ring 2 weight */
++ (QUEUE_WEIGHT_16 << 4) | /* ring 1 weight */
++ (QUEUE_WEIGHT_4 << 0); /* ring 0 weight */
++#endif
++}
++
++/*
++ * Routine Description :
++ * Bucket size and related information from ASIC Designer,
++ * please check Max Lee to update these values
++ *
++ * Related Registers
++ * FE_GLO_CFG - initialize clock rate for rate limiting
++ * PDMA_FC_CFG - Pause mechanism for Rings (Ref to pp116 in datasheet)
++ * :
++ * Parameter:
++ * NONE
++ */
++/*
++ * Bit 29:24 - Q3 flow control pause condition
++ * Bit 21:16 - Q2 flow control pause condition
++ * Bit 13:8 - Q1 flow control pause condition
++ * Bit 5:0 - Q0 flow control pause condition
++ *
++ * detail bitmap -
++ * Bit[5] - Pause Qx when PSE p2 HQ full
++ * Bit[4] - Pause Qx when PSE p2 LQ full
++ * Bit[3] - Pause Qx when PSE p1 HQ full
++ * Bit[2] - Pause Qx when PSE p1 LQ full
++ * Bit[1] - Pause Qx when PSE p0 HQ full
++ * Bit[0] - Pause Qx when PSE p0 LQ full
++ */
++void set_schedule_pause_condition(void)
++{
++#if defined (CONFIG_RALINK_MT7620)
++
++#elif defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++ *(unsigned long *)SDM_TRING = (0xC << 28) | (0x3 << 24) | (0xC << 4) | 0x3;
++#else
++ /*
++ * STEP1: Set queue priority is high or low
++ *
++ * Set queue 3 as high queue in GMAC1/GMAC2
++ */
++ *(unsigned long *)GDMA1_FC_CFG = ((HIGH_QUEUE(3)|LOW_QUEUE(2) |
++ LOW_QUEUE(1)|LOW_QUEUE(0))<<24) |
++ (RSEV_PAGE_COUNT_HQ << 16) |
++ (RSEV_PAGE_COUNT_LQ <<8) |
++ VIQ_FC_ASRT | PAGES_SHARING;
++
++ *(unsigned long *)GDMA2_FC_CFG = ((HIGH_QUEUE(3)|LOW_QUEUE(2) |
++ LOW_QUEUE(1)|LOW_QUEUE(0))<<24) |
++ (RSEV_PAGE_COUNT_HQ << 16) |
++ (RSEV_PAGE_COUNT_LQ <<8) |
++ VIQ_FC_ASRT | PAGES_SHARING;
++
++ /*
++ * STEP2: Set flow control pause condition
++ *
++ * CPU always use queue 3, and queue3 is high queue.
++ * If P2(GMAC2) high queue is full, pause ring3/ring2
++ * If P1(GMAC1) high queue is full, pause ring1/ring0
++ */
++ *(unsigned long *)PDMA_FC_CFG = ( PSE_P2_HQ_FULL << 24 ) | /* queue 3 */
++ ( PSE_P2_HQ_FULL << 16 ) | /* queue 2 */
++ ( PSE_P1_HQ_FULL << 8 ) | /* queue 1 */
++ ( PSE_P1_HQ_FULL << 0 ); /* queue 0 */
++#endif
++
++}
++
++
++void set_output_shaper(void)
++{
++#define GDMA1_TOKEN_RATE 16 /* unit=64bits/ms */
++#define GDMA2_TOKEN_RATE 16 /* unit=64bits/ms */
++
++#if 0
++ *(unsigned long *)GDMA1_SHPR_CFG = (1 << 24) | /* output shaper enable */
++ (128 << 16) | /* bucket size (unit=1KB) */
++ (GDMA1_TOKEN_RATE << 0); /* token rate (unit=8B/ms) */
++#endif
++
++#if 0
++ *(unsigned long *)GDMA2_SHPR_CFG = (1 << 24) | /* output shaper enable */
++ (128 << 16) | /* bucket size (unit=1KB) */
++ (GDMA2_TOKEN_RATE << 0); /* token rate (unit=8B/ms) */
++#endif
++}
+diff --git a/drivers/net/ethernet/raeth/ra_qos.h b/drivers/net/ethernet/raeth/ra_qos.h
+new file mode 100644
+index 0000000..7f2a8a1
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_qos.h
+@@ -0,0 +1,18 @@
++#ifndef RA_QOS_H
++#define RA_QOS_H
++
++#include "ra2882ethreg.h"
++#define RING0 0
++#define RING1 1
++#define RING2 2
++#define RING3 3
++void get_tx_desc_and_dtx_idx(END_DEVICE* ei_local, int ring_no, unsigned long *tx_dtx_idx, struct PDMA_txdesc **tx_desc);
++int get_tx_ctx_idx(unsigned int ring_no, unsigned long *idx);
++int fe_tx_desc_init(struct net_device *dev, unsigned int ring_no, unsigned int qn, unsigned int pn);
++int fe_qos_packet_send(struct net_device *dev, struct sk_buff* skb, unsigned int ring_no, unsigned int qn, unsigned int pn);
++
++int pkt_classifier(struct sk_buff *skb,int gmac_no, int *ring_no, int *queue_no, int *port_no);
++void set_schedule_pause_condition(void);
++void set_scheduler_weight(void);
++void set_output_shaper(void);
++#endif
+diff --git a/drivers/net/ethernet/raeth/ra_rfrw.c b/drivers/net/ethernet/raeth/ra_rfrw.c
+new file mode 100644
+index 0000000..d73db01
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_rfrw.c
+@@ -0,0 +1,66 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/fcntl.h>
++#include <linux/interrupt.h>
++#include <linux/ptrace.h>
++#include <linux/ioport.h>
++#include <linux/in.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/signal.h>
++#include <linux/irq.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++
++#include "ra2882ethreg.h"
++#include "raether.h"
++#include "ra_mac.h"
++
++#define RF_CSR_CFG 0xb0180500
++#define RF_CSR_KICK (1<<17)
++int rw_rf_reg(int write, int reg, int *data)
++{
++ unsigned long rfcsr, i = 0;
++
++ while (1) {
++ rfcsr = sysRegRead(RF_CSR_CFG);
++ if (! (rfcsr & (u32)RF_CSR_KICK) )
++ break;
++ if (++i > 10000) {
++ printk("Warning: Abort rw rf register: too busy\n");
++ return -1;
++ }
++ }
++
++ rfcsr = (u32)(RF_CSR_KICK | ((reg&0x3f) << 8) | (*data & 0xff));
++ if (write)
++ rfcsr |= 0x10000;
++
++ sysRegRead(RF_CSR_CFG) = cpu_to_le32(rfcsr);
++
++ i = 0;
++ while (1) {
++ rfcsr = sysRegRead(RF_CSR_CFG);
++ if (! (rfcsr & (u32)RF_CSR_KICK) )
++ break;
++ if (++i > 10000) {
++ printk("Warning: still busy\n");
++ return -1;
++ }
++ }
++
++ rfcsr = sysRegRead(RF_CSR_CFG);
++
++ if (((rfcsr&0x1f00) >> 8) != (reg & 0x1f)) {
++ printk("Error: rw register failed\n");
++ return -1;
++ }
++ *data = (int)(rfcsr & 0xff);
++
++ return 0;
++}
++
+diff --git a/drivers/net/ethernet/raeth/ra_rfrw.h b/drivers/net/ethernet/raeth/ra_rfrw.h
+new file mode 100644
+index 0000000..da5a371
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_rfrw.h
+@@ -0,0 +1,6 @@
++#ifndef RA_RFRW_H
++#define RA_RFRW_H
++
++int rw_rf_reg(int write, int reg, int *data);
++
++#endif
+diff --git a/drivers/net/ethernet/raeth/raether.c b/drivers/net/ethernet/raeth/raether.c
+new file mode 100644
+index 0000000..328285a
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/raether.c
+@@ -0,0 +1,6401 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <linux/if_vlan.h>
++#include <linux/if_ether.h>
++#include <linux/fs.h>
++#include <asm/uaccess.h>
++#include <asm/rt2880/surfboardint.h>
++#include <linux/platform_device.h>
++#if defined (CONFIG_RAETH_TSO)
++#include <linux/tcp.h>
++#include <net/ipv6.h>
++#include <linux/ip.h>
++#include <net/ip.h>
++#include <net/tcp.h>
++#include <linux/in.h>
++#include <linux/ppp_defs.h>
++#include <linux/if_pppox.h>
++#endif
++#if defined (CONFIG_RAETH_LRO)
++#include <linux/inet_lro.h>
++#endif
++#include <linux/delay.h>
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++#include <linux/sched.h>
++#endif
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
++#include <asm/rt2880/rt_mmap.h>
++#else
++#include <linux/libata-compat.h>
++#endif
++
++#include "ra2882ethreg.h"
++#include "raether.h"
++#include "ra_mac.h"
++#include "ra_ioctl.h"
++#include "ra_rfrw.h"
++#ifdef CONFIG_RAETH_NETLINK
++#include "ra_netlink.h"
++#endif
++#if defined (CONFIG_RAETH_QOS)
++#include "ra_qos.h"
++#endif
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++#include "../../../net/nat/hw_nat/ra_nat.h"
++#endif
++#if defined(CONFIG_RAETH_PDMA_DVT)
++#include "dvt/raether_pdma_dvt.h"
++#endif /* CONFIG_RAETH_PDMA_DVT */
++
++static int fe_irq = 0;
++
++#if defined (TASKLET_WORKQUEUE_SW)
++int init_schedule;
++int working_schedule;
++#endif
++
++#ifdef CONFIG_RAETH_NAPI
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++static int raeth_clean(struct napi_struct *napi, int budget);
++#else
++static int raeth_clean(struct net_device *dev, int *budget);
++#endif
++
++static int rt2880_eth_recv(struct net_device* dev, int *work_done, int work_to_do);
++#else
++static int rt2880_eth_recv(struct net_device* dev);
++#endif
++
++#if !defined(CONFIG_RA_NAT_NONE)
++/* bruce+
++ */
++extern int (*ra_sw_nat_hook_rx)(struct sk_buff *skb);
++extern int (*ra_sw_nat_hook_tx)(struct sk_buff *skb, int gmac_no);
++#endif
++
++#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE)
++/* Qwert+
++ */
++#include <asm/mipsregs.h>
++extern int (*ra_classifier_hook_tx)(struct sk_buff *skb, unsigned long cur_cycle);
++extern int (*ra_classifier_hook_rx)(struct sk_buff *skb, unsigned long cur_cycle);
++#endif /* CONFIG_RA_CLASSIFIER */
++
++#if defined (CONFIG_RALINK_RT3052_MP2)
++int32_t mcast_rx(struct sk_buff * skb);
++int32_t mcast_tx(struct sk_buff * skb);
++#endif
++
++int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf)
++{
++ /* TODO */
++ return 0;
++}
++
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_P5_RGMII_TO_MT7530_MODE) || defined (CONFIG_ARCH_MT7623)
++void setup_internal_gsw(void);
++#if defined (CONFIG_GE1_TRGMII_FORCE_1200)
++void apll_xtal_enable(void);
++#define REGBIT(x, n) (x << n)
++#endif
++#endif
++
++#if defined (CONFIG_MT7623_FPGA)
++void setup_fpga_gsw(void);
++#endif
++
++/* gmac driver feature set config */
++#if defined (CONFIG_RAETH_NAPI) || defined (CONFIG_RAETH_QOS)
++#undef DELAY_INT
++#else
++#if defined (CONFIG_ARCH_MT7623)
++#undef DELAY_INT
++#else
++#define DELAY_INT 1
++#endif
++#endif
++
++//#define CONFIG_UNH_TEST
++/* end of config */
++
++#if defined (CONFIG_RAETH_JUMBOFRAME)
++#define MAX_RX_LENGTH 4096
++#else
++#define MAX_RX_LENGTH 1536
++#endif
++
++struct net_device *dev_raether;
++
++static int rx_dma_owner_idx;
++static int rx_dma_owner_idx0;
++#if defined (CONFIG_RAETH_HW_LRO)
++static int rx_dma_owner_lro1;
++static int rx_dma_owner_lro2;
++static int rx_dma_owner_lro3;
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++static int rx_dma_owner_idx1;
++#if defined(CONFIG_ARCH_MT7623)
++static int rx_dma_owner_idx2;
++static int rx_dma_owner_idx3;
++#endif /* CONFIG_ARCH_MT7623 */
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++int rx_calc_idx1;
++#endif
++#endif
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++int rx_calc_idx0;
++#endif
++static int pending_recv;
++static struct PDMA_rxdesc *rx_ring;
++unsigned long tx_ring_full=0;
++
++#if defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined(CONFIG_RALINK_MT7620)
++unsigned short p0_rx_good_cnt = 0;
++unsigned short p1_rx_good_cnt = 0;
++unsigned short p2_rx_good_cnt = 0;
++unsigned short p3_rx_good_cnt = 0;
++unsigned short p4_rx_good_cnt = 0;
++unsigned short p5_rx_good_cnt = 0;
++unsigned short p6_rx_good_cnt = 0;
++unsigned short p0_tx_good_cnt = 0;
++unsigned short p1_tx_good_cnt = 0;
++unsigned short p2_tx_good_cnt = 0;
++unsigned short p3_tx_good_cnt = 0;
++unsigned short p4_tx_good_cnt = 0;
++unsigned short p5_tx_good_cnt = 0;
++unsigned short p6_tx_good_cnt = 0;
++
++unsigned short p0_rx_byte_cnt = 0;
++unsigned short p1_rx_byte_cnt = 0;
++unsigned short p2_rx_byte_cnt = 0;
++unsigned short p3_rx_byte_cnt = 0;
++unsigned short p4_rx_byte_cnt = 0;
++unsigned short p5_rx_byte_cnt = 0;
++unsigned short p6_rx_byte_cnt = 0;
++unsigned short p0_tx_byte_cnt = 0;
++unsigned short p1_tx_byte_cnt = 0;
++unsigned short p2_tx_byte_cnt = 0;
++unsigned short p3_tx_byte_cnt = 0;
++unsigned short p4_tx_byte_cnt = 0;
++unsigned short p5_tx_byte_cnt = 0;
++unsigned short p6_tx_byte_cnt = 0;
++
++#if defined(CONFIG_RALINK_MT7620)
++unsigned short p7_rx_good_cnt = 0;
++unsigned short p7_tx_good_cnt = 0;
++
++unsigned short p7_rx_byte_cnt = 0;
++unsigned short p7_tx_byte_cnt = 0;
++#endif
++#endif
++
++
++
++
++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
++#include "ra_ethtool.h"
++extern struct ethtool_ops ra_ethtool_ops;
++#ifdef CONFIG_PSEUDO_SUPPORT
++extern struct ethtool_ops ra_virt_ethtool_ops;
++#endif // CONFIG_PSEUDO_SUPPORT //
++#endif // (CONFIG_ETHTOOL //
++
++#ifdef CONFIG_RALINK_VISTA_BASIC
++int is_switch_175c = 1;
++#endif
++
++unsigned int M2Q_table[64] = {0};
++unsigned int lan_wan_separate = 0;
++
++#if defined(CONFIG_HW_SFQ)
++unsigned int web_sfq_enable = 0;
++EXPORT_SYMBOL(web_sfq_enable);
++#endif
++
++EXPORT_SYMBOL(M2Q_table);
++EXPORT_SYMBOL(lan_wan_separate);
++#if defined (CONFIG_RAETH_LRO)
++unsigned int lan_ip;
++struct lro_para_struct lro_para;
++int lro_flush_needed;
++extern char const *nvram_get(int index, char *name);
++#endif
++
++#define KSEG1 0xa0000000
++#if defined (CONFIG_MIPS)
++#define PHYS_TO_VIRT(x) ((void *)((x) | KSEG1))
++#define VIRT_TO_PHYS(x) ((unsigned long)(x) & ~KSEG1)
++#else
++#define PHYS_TO_VIRT(x) phys_to_virt(x)
++#define VIRT_TO_PHYS(x) virt_to_phys(x)
++#endif
++
++extern int fe_dma_init(struct net_device *dev);
++extern int ei_start_xmit(struct sk_buff* skb, struct net_device *dev, int gmac_no);
++extern void ei_xmit_housekeeping(unsigned long unused);
++extern inline int rt2880_eth_send(struct net_device* dev, struct sk_buff *skb, int gmac_no);
++#if defined (CONFIG_RAETH_HW_LRO)
++extern int fe_hw_lro_init(struct net_device *dev);
++#endif /* CONFIG_RAETH_HW_LRO */
++
++#if 0
++void skb_dump(struct sk_buff* sk) {
++ unsigned int i;
++
++ printk("skb_dump: from %s with len %d (%d) headroom=%d tailroom=%d\n",
++ sk->dev?sk->dev->name:"ip stack",sk->len,sk->truesize,
++ skb_headroom(sk),skb_tailroom(sk));
++
++ //for(i=(unsigned int)sk->head;i<=(unsigned int)sk->tail;i++) {
++ for(i=(unsigned int)sk->head;i<=(unsigned int)sk->data+20;i++) {
++ if((i % 20) == 0)
++ printk("\n");
++ if(i==(unsigned int)sk->data) printk("{");
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)
++ if(i==(unsigned int)sk->transport_header) printk("#");
++ if(i==(unsigned int)sk->network_header) printk("|");
++ if(i==(unsigned int)sk->mac_header) printk("*");
++#else
++ if(i==(unsigned int)sk->h.raw) printk("#");
++ if(i==(unsigned int)sk->nh.raw) printk("|");
++ if(i==(unsigned int)sk->mac.raw) printk("*");
++#endif
++ printk("%02X-",*((unsigned char*)i));
++ if(i==(unsigned int)sk->tail) printk("}");
++ }
++ printk("\n");
++}
++#endif
++
++
++
++#if defined (CONFIG_GIGAPHY) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
++int isICPlusGigaPHY(int ge)
++{
++ u32 phy_id0 = 0, phy_id1 = 0;
++
++#ifdef CONFIG_GE2_RGMII_AN
++ if (ge == 2) {
++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 2, &phy_id0)) {
++ printk("\n Read PhyID 1 is Fail!!\n");
++ phy_id0 =0;
++ }
++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 3, &phy_id1)) {
++ printk("\n Read PhyID 1 is Fail!!\n");
++ phy_id1 = 0;
++ }
++ }
++ else
++#endif
++#if defined (CONFIG_GE1_RGMII_AN) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
++ {
++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 2, &phy_id0)) {
++ printk("\n Read PhyID 0 is Fail!!\n");
++ phy_id0 =0;
++ }
++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 3, &phy_id1)) {
++ printk("\n Read PhyID 0 is Fail!!\n");
++ phy_id1 = 0;
++ }
++ }
++#endif
++
++ if ((phy_id0 == EV_ICPLUS_PHY_ID0) && ((phy_id1 & 0xfff0) == EV_ICPLUS_PHY_ID1))
++ return 1;
++ return 0;
++}
++
++
++int isMarvellGigaPHY(int ge)
++{
++ u32 phy_id0 = 0, phy_id1 = 0;
++
++#if defined (CONFIG_GE2_RGMII_AN) || defined (CONFIG_P4_MAC_TO_PHY_MODE)
++ if (ge == 2) {
++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 2, &phy_id0)) {
++ printk("\n Read PhyID 1 is Fail!!\n");
++ phy_id0 =0;
++ }
++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 3, &phy_id1)) {
++ printk("\n Read PhyID 1 is Fail!!\n");
++ phy_id1 = 0;
++ }
++ }
++ else
++#endif
++#if defined (CONFIG_GE1_RGMII_AN) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
++ {
++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 2, &phy_id0)) {
++ printk("\n Read PhyID 0 is Fail!!\n");
++ phy_id0 =0;
++ }
++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 3, &phy_id1)) {
++ printk("\n Read PhyID 0 is Fail!!\n");
++ phy_id1 = 0;
++ }
++ }
++#endif
++ ;
++ if ((phy_id0 == EV_MARVELL_PHY_ID0) && (phy_id1 == EV_MARVELL_PHY_ID1))
++ return 1;
++ return 0;
++}
++
++int isVtssGigaPHY(int ge)
++{
++ u32 phy_id0 = 0, phy_id1 = 0;
++
++#if defined (CONFIG_GE2_RGMII_AN) || defined (CONFIG_P4_MAC_TO_PHY_MODE)
++ if (ge == 2) {
++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 2, &phy_id0)) {
++ printk("\n Read PhyID 1 is Fail!!\n");
++ phy_id0 =0;
++ }
++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 3, &phy_id1)) {
++ printk("\n Read PhyID 1 is Fail!!\n");
++ phy_id1 = 0;
++ }
++ }
++ else
++#endif
++#if defined (CONFIG_GE1_RGMII_AN) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
++ {
++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 2, &phy_id0)) {
++ printk("\n Read PhyID 0 is Fail!!\n");
++ phy_id0 =0;
++ }
++ if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 3, &phy_id1)) {
++ printk("\n Read PhyID 0 is Fail!!\n");
++ phy_id1 = 0;
++ }
++ }
++#endif
++ ;
++ if ((phy_id0 == EV_VTSS_PHY_ID0) && (phy_id1 == EV_VTSS_PHY_ID1))
++ return 1;
++ return 0;
++}
++#endif
++
++/*
++ * Set the hardware MAC address.
++ */
++static int ei_set_mac_addr(struct net_device *dev, void *p)
++{
++ struct sockaddr *addr = p;
++
++ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
++
++ if(netif_running(dev))
++ return -EBUSY;
++
++ ra2880MacAddressSet(addr->sa_data);
++ return 0;
++}
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++static int ei_set_mac2_addr(struct net_device *dev, void *p)
++{
++ struct sockaddr *addr = p;
++
++ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
++
++ if(netif_running(dev))
++ return -EBUSY;
++
++ ra2880Mac2AddressSet(addr->sa_data);
++ return 0;
++}
++#endif
++
++void set_fe_dma_glo_cfg(void)
++{
++ int dma_glo_cfg=0;
++#if defined (CONFIG_RALINK_RT2880) || defined(CONFIG_RALINK_RT2883) || \
++ defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3883)
++ int fe_glo_cfg=0;
++#endif
++
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A)
++ dma_glo_cfg = (TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN | PDMA_BT_SIZE_32DWORDS);
++#elif defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621)
++ dma_glo_cfg = (TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN | PDMA_BT_SIZE_16DWORDS);
++#elif defined (CONFIG_ARCH_MT7623)
++ dma_glo_cfg = (TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN | PDMA_BT_SIZE_16DWORDS | ADMA_RX_BT_SIZE_32DWORDS);
++#else
++ dma_glo_cfg = (TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN | PDMA_BT_SIZE_4DWORDS);
++#endif
++
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++ dma_glo_cfg |= (RX_2B_OFFSET);
++#endif
++
++#if defined (CONFIG_32B_DESC)
++ dma_glo_cfg |= (DESC_32B_EN);
++#endif
++ sysRegWrite(DMA_GLO_CFG, dma_glo_cfg);
++#ifdef CONFIG_RAETH_QDMA
++ sysRegWrite(QDMA_GLO_CFG, dma_glo_cfg);
++#endif
++
++ /* only the following chipset need to set it */
++#if defined (CONFIG_RALINK_RT2880) || defined(CONFIG_RALINK_RT2883) || \
++ defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3883)
++ //set 1us timer count in unit of clock cycle
++ fe_glo_cfg = sysRegRead(FE_GLO_CFG);
++ fe_glo_cfg &= ~(0xff << 8); //clear bit8-bit15
++ fe_glo_cfg |= (((get_surfboard_sysclk()/1000000)) << 8);
++ sysRegWrite(FE_GLO_CFG, fe_glo_cfg);
++#endif
++}
++
++int forward_config(struct net_device *dev)
++{
++
++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++
++ /* RT5350: No GDMA, PSE, CDMA, PPE */
++ unsigned int sdmVal;
++ sdmVal = sysRegRead(SDM_CON);
++
++#ifdef CONFIG_RAETH_CHECKSUM_OFFLOAD
++ sdmVal |= 0x7<<16; // UDPCS, TCPCS, IPCS=1
++#endif // CONFIG_RAETH_CHECKSUM_OFFLOAD //
++
++#if defined (CONFIG_RAETH_SPECIAL_TAG)
++ sdmVal |= 0x1<<20; // TCI_81XX
++#endif // CONFIG_RAETH_SPECIAL_TAG //
++
++ sysRegWrite(SDM_CON, sdmVal);
++
++#else //Non RT5350 chipset
++
++ unsigned int regVal, regCsg;
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++ unsigned int regVal2;
++#endif
++
++#ifdef CONFIG_RAETH_HW_VLAN_TX
++#if defined(CONFIG_RALINK_MT7620)
++ /* frame engine will push VLAN tag regarding to VIDX feild in Tx desc. */
++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x430) = 0x00010000;
++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x434) = 0x00030002;
++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x438) = 0x00050004;
++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x43C) = 0x00070006;
++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x440) = 0x00090008;
++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x444) = 0x000b000a;
++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x448) = 0x000d000c;
++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x44C) = 0x000f000e;
++#else
++ /*
++ * VLAN_IDX 0 = VLAN_ID 0
++ * .........
++ * VLAN_IDX 15 = VLAN ID 15
++ *
++ */
++ /* frame engine will push VLAN tag regarding to VIDX feild in Tx desc. */
++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xa8) = 0x00010000;
++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xac) = 0x00030002;
++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xb0) = 0x00050004;
++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xb4) = 0x00070006;
++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xb8) = 0x00090008;
++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xbc) = 0x000b000a;
++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xc0) = 0x000d000c;
++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xc4) = 0x000f000e;
++#endif
++#endif
++
++ regVal = sysRegRead(GDMA1_FWD_CFG);
++ regCsg = sysRegRead(CDMA_CSG_CFG);
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++ regVal2 = sysRegRead(GDMA2_FWD_CFG);
++#endif
++
++ //set unicast/multicast/broadcast frame to cpu
++#if defined (CONFIG_RALINK_MT7620)
++ /* GDMA1 frames destination port is port0 CPU*/
++ regVal &= ~0x7;
++#else
++ regVal &= ~0xFFFF;
++ regVal |= GDMA1_FWD_PORT;
++#endif
++ regCsg &= ~0x7;
++
++#if defined (CONFIG_RAETH_SPECIAL_TAG)
++ regVal |= (1 << 24); //GDM1_TCI_81xx
++#endif
++
++
++#ifdef CONFIG_RAETH_HW_VLAN_TX
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
++ dev->features |= NETIF_F_HW_VLAN_TX;
++#else
++ dev->features |= NETIF_F_HW_VLAN_CTAG_TX;
++#endif
++#endif
++#ifdef CONFIG_RAETH_HW_VLAN_RX
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
++ dev->features |= NETIF_F_HW_VLAN_RX;
++#else
++ dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
++#endif
++#endif
++
++#ifdef CONFIG_RAETH_CHECKSUM_OFFLOAD
++ //enable ipv4 header checksum check
++ regVal |= GDM1_ICS_EN;
++ regCsg |= ICS_GEN_EN;
++
++ //enable tcp checksum check
++ regVal |= GDM1_TCS_EN;
++ regCsg |= TCS_GEN_EN;
++
++ //enable udp checksum check
++ regVal |= GDM1_UCS_EN;
++ regCsg |= UCS_GEN_EN;
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++ regVal2 &= ~0xFFFF;
++ regVal2 |= GDMA2_FWD_PORT;
++
++ regVal2 |= GDM1_ICS_EN;
++ regVal2 |= GDM1_TCS_EN;
++ regVal2 |= GDM1_UCS_EN;
++#endif
++
++#if defined (CONFIG_RAETH_HW_LRO)
++ dev->features |= NETIF_F_HW_CSUM;
++#else
++ dev->features |= NETIF_F_IP_CSUM; /* Can checksum TCP/UDP over IPv4 */
++#endif /* CONFIG_RAETH_HW_LRO */
++//#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
++// dev->vlan_features |= NETIF_F_IP_CSUM;
++//#endif
++
++#if defined(CONFIG_RALINK_MT7620)
++#if defined (CONFIG_RAETH_TSO)
++ if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
++ dev->features |= NETIF_F_SG;
++ dev->features |= NETIF_F_TSO;
++ }
++#endif // CONFIG_RAETH_TSO //
++
++#if defined (CONFIG_RAETH_TSOV6)
++ if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
++ dev->features |= NETIF_F_TSO6;
++ dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */
++ }
++#endif // CONFIG_RAETH_TSOV6 //
++#else
++#if defined (CONFIG_RAETH_TSO)
++ dev->features |= NETIF_F_SG;
++ dev->features |= NETIF_F_TSO;
++#endif // CONFIG_RAETH_TSO //
++
++#if defined (CONFIG_RAETH_TSOV6)
++ dev->features |= NETIF_F_TSO6;
++ dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */
++#endif // CONFIG_RAETH_TSOV6 //
++#endif // CONFIG_RALINK_MT7620 //
++#else // Checksum offload disabled
++
++ //disable ipv4 header checksum check
++ regVal &= ~GDM1_ICS_EN;
++ regCsg &= ~ICS_GEN_EN;
++
++ //disable tcp checksum check
++ regVal &= ~GDM1_TCS_EN;
++ regCsg &= ~TCS_GEN_EN;
++
++ //disable udp checksum check
++ regVal &= ~GDM1_UCS_EN;
++ regCsg &= ~UCS_GEN_EN;
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++ regVal2 &= ~GDM1_ICS_EN;
++ regVal2 &= ~GDM1_TCS_EN;
++ regVal2 &= ~GDM1_UCS_EN;
++#endif
++
++ dev->features &= ~NETIF_F_IP_CSUM; /* disable checksum TCP/UDP over IPv4 */
++#endif // CONFIG_RAETH_CHECKSUM_OFFLOAD //
++
++#ifdef CONFIG_RAETH_JUMBOFRAME
++ regVal |= GDM1_JMB_EN;
++#ifdef CONFIG_PSEUDO_SUPPORT
++ regVal2 |= GDM1_JMB_EN;
++#endif
++#endif
++
++ sysRegWrite(GDMA1_FWD_CFG, regVal);
++ sysRegWrite(CDMA_CSG_CFG, regCsg);
++#ifdef CONFIG_PSEUDO_SUPPORT
++ sysRegWrite(GDMA2_FWD_CFG, regVal2);
++#endif
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
++ dev->vlan_features = dev->features;
++#endif
++
++/*
++ * PSE_FQ_CFG register definition -
++ *
++ * Define max free queue page count in PSE. (31:24)
++ * RT2883/RT3883 - 0xff908000 (255 pages)
++ * RT3052 - 0x80504000 (128 pages)
++ * RT2880 - 0x80504000 (128 pages)
++ *
++ * In each page, there are 128 bytes in each page.
++ *
++ * 23:16 - free queue flow control release threshold
++ * 15:8 - free queue flow control assertion threshold
++ * 7:0 - free queue empty threshold
++ *
++ * The register affects QOS correctness in frame engine!
++ */
++
++#if defined(CONFIG_RALINK_RT2883) || defined(CONFIG_RALINK_RT3883)
++ sysRegWrite(PSE_FQ_CFG, cpu_to_le32(INIT_VALUE_OF_RT2883_PSE_FQ_CFG));
++#elif defined(CONFIG_RALINK_RT3352) || defined(CONFIG_RALINK_RT5350) || \
++ defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined(CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || \
++ defined (CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
++ /*use default value*/
++#else
++ sysRegWrite(PSE_FQ_CFG, cpu_to_le32(INIT_VALUE_OF_PSE_FQFC_CFG));
++#endif
++
++ /*
++ *FE_RST_GLO register definition -
++ *Bit 0: PSE Rest
++ *Reset PSE after re-programming PSE_FQ_CFG.
++ */
++ regVal = 0x1;
++ sysRegWrite(FE_RST_GL, regVal);
++ sysRegWrite(FE_RST_GL, 0); // update for RSTCTL issue
++
++ regCsg = sysRegRead(CDMA_CSG_CFG);
++ printk("CDMA_CSG_CFG = %0X\n",regCsg);
++ regVal = sysRegRead(GDMA1_FWD_CFG);
++ printk("GDMA1_FWD_CFG = %0X\n",regVal);
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++ regVal = sysRegRead(GDMA2_FWD_CFG);
++ printk("GDMA2_FWD_CFG = %0X\n",regVal);
++#endif
++#endif
++ return 1;
++}
++
++#ifdef CONFIG_RAETH_LRO
++static int
++rt_get_skb_header(struct sk_buff *skb, void **iphdr, void **tcph,
++ u64 *hdr_flags, void *priv)
++{
++ struct iphdr *iph = NULL;
++ int vhdr_len = 0;
++
++ /*
++ * Make sure that this packet is Ethernet II, is not VLAN
++ * tagged, is IPv4, has a valid IP header, and is TCP.
++ */
++ if (skb->protocol == 0x0081) {
++ vhdr_len = VLAN_HLEN;
++ }
++
++ iph = (struct iphdr *)(skb->data + vhdr_len);
++ if (iph->daddr != lro_para.lan_ip1) {
++ return -1;
++ }
++
++ if(iph->protocol != IPPROTO_TCP) {
++ return -1;
++ } else {
++ *iphdr = iph;
++ *tcph = skb->data + (iph->ihl << 2) + vhdr_len;
++ *hdr_flags = LRO_IPV4 | LRO_TCP;
++
++ lro_flush_needed = 1;
++ return 0;
++ }
++}
++#endif // CONFIG_RAETH_LRO //
++
++#ifdef CONFIG_RAETH_NAPI
++static int rt2880_eth_recv(struct net_device* dev, int *work_done, int work_to_do)
++#else
++static int rt2880_eth_recv(struct net_device* dev)
++#endif
++{
++ struct sk_buff *skb, *rx_skb;
++ unsigned int length = 0;
++ unsigned long RxProcessed;
++
++ int bReschedule = 0;
++ END_DEVICE* ei_local = netdev_priv(dev);
++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING) || defined (CONFIG_RAETH_HW_LRO)
++ int rx_ring_no=0;
++#endif
++
++#if defined (CONFIG_RAETH_SPECIAL_TAG)
++ struct vlan_ethhdr *veth=NULL;
++#endif
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++ PSEUDO_ADAPTER *pAd;
++#endif
++
++ RxProcessed = 0;
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ rx_dma_owner_idx0 = (rx_calc_idx0 + 1) % NUM_RX_DESC;
++#else
++ rx_dma_owner_idx0 = (sysRegRead(RAETH_RX_CALC_IDX0) + 1) % NUM_RX_DESC;
++#endif
++
++#if defined (CONFIG_32B_DESC)
++ dma_cache_sync(NULL, &ei_local->rx_ring0[rx_dma_owner_idx0], sizeof(struct PDMA_rxdesc), DMA_FROM_DEVICE);
++#endif
++#if defined (CONFIG_RAETH_HW_LRO)
++ rx_dma_owner_lro1 = (sysRegRead(RX_CALC_IDX1) + 1) % NUM_LRO_RX_DESC;
++ rx_dma_owner_lro2 = (sysRegRead(RX_CALC_IDX2) + 1) % NUM_LRO_RX_DESC;
++ rx_dma_owner_lro3 = (sysRegRead(RX_CALC_IDX3) + 1) % NUM_LRO_RX_DESC;
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ rx_dma_owner_idx1 = (rx_calc_idx1 + 1) % NUM_RX_DESC;
++#else
++ rx_dma_owner_idx1 = (sysRegRead(RX_CALC_IDX1) + 1) % NUM_RX_DESC;
++#endif /* CONFIG_RAETH_RW_PDMAPTR_FROM_VAR */
++#if defined(CONFIG_ARCH_MT7623)
++ rx_dma_owner_idx2 = (sysRegRead(RX_CALC_IDX2) + 1) % NUM_RX_DESC;
++ rx_dma_owner_idx3 = (sysRegRead(RX_CALC_IDX3) + 1) % NUM_RX_DESC;
++#endif
++#if defined (CONFIG_32B_DESC)
++ dma_cache_sync(NULL, &ei_local->rx_ring1[rx_dma_owner_idx1], sizeof(struct PDMA_rxdesc), DMA_FROM_DEVICE);
++#endif
++#endif
++ for ( ; ; ) {
++
++
++#ifdef CONFIG_RAETH_NAPI
++ if(*work_done >= work_to_do)
++ break;
++ (*work_done)++;
++#else
++ if (RxProcessed++ > NUM_RX_MAX_PROCESS)
++ {
++ // need to reschedule rx handle
++ bReschedule = 1;
++ break;
++ }
++#endif
++
++
++#if defined (CONFIG_RAETH_HW_LRO)
++ if (ei_local->rx_ring3[rx_dma_owner_lro3].rxd_info2.DDONE_bit == 1) {
++ rx_ring = ei_local->rx_ring3;
++ rx_dma_owner_idx = rx_dma_owner_lro3;
++ // printk("rx_dma_owner_lro3=%x\n",rx_dma_owner_lro3);
++ rx_ring_no=3;
++ }
++ else if (ei_local->rx_ring2[rx_dma_owner_lro2].rxd_info2.DDONE_bit == 1) {
++ rx_ring = ei_local->rx_ring2;
++ rx_dma_owner_idx = rx_dma_owner_lro2;
++ // printk("rx_dma_owner_lro2=%x\n",rx_dma_owner_lro2);
++ rx_ring_no=2;
++ }
++ else if (ei_local->rx_ring1[rx_dma_owner_lro1].rxd_info2.DDONE_bit == 1) {
++ rx_ring = ei_local->rx_ring1;
++ rx_dma_owner_idx = rx_dma_owner_lro1;
++ // printk("rx_dma_owner_lro1=%x\n",rx_dma_owner_lro1);
++ rx_ring_no=1;
++ }
++ else if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.DDONE_bit == 1) {
++ rx_ring = ei_local->rx_ring0;
++ rx_dma_owner_idx = rx_dma_owner_idx0;
++ // printk("rx_dma_owner_idx0=%x\n",rx_dma_owner_idx0);
++ rx_ring_no=0;
++ } else {
++ break;
++ }
++ #if defined (CONFIG_RAETH_HW_LRO_DBG)
++ HwLroStatsUpdate(rx_ring_no, rx_ring[rx_dma_owner_idx].rxd_info2.LRO_AGG_CNT, \
++ (rx_ring[rx_dma_owner_idx].rxd_info2.PLEN1 << 14) | rx_ring[rx_dma_owner_idx].rxd_info2.PLEN0);
++ #endif
++ #if defined(CONFIG_RAETH_HW_LRO_REASON_DBG)
++ HwLroFlushStatsUpdate(rx_ring_no, rx_ring[rx_dma_owner_idx].rxd_info2.REV);
++ #endif
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++ if (ei_local->rx_ring1[rx_dma_owner_idx1].rxd_info2.DDONE_bit == 1) {
++ rx_ring = ei_local->rx_ring1;
++ rx_dma_owner_idx = rx_dma_owner_idx1;
++ // printk("rx_dma_owner_idx1=%x\n",rx_dma_owner_idx1);
++ rx_ring_no=1;
++ }
++#if defined(CONFIG_ARCH_MT7623)
++ else if (ei_local->rx_ring2[rx_dma_owner_idx2].rxd_info2.DDONE_bit == 1) {
++ rx_ring = ei_local->rx_ring2;
++ rx_dma_owner_idx = rx_dma_owner_idx2;
++ // printk("rx_dma_owner_idx2=%x\n",rx_dma_owner_idx2);
++ rx_ring_no=2;
++ }
++ else if (ei_local->rx_ring3[rx_dma_owner_idx3].rxd_info2.DDONE_bit == 1) {
++ rx_ring = ei_local->rx_ring3;
++ rx_dma_owner_idx = rx_dma_owner_idx3;
++ // printk("rx_dma_owner_idx3=%x\n",rx_dma_owner_idx3);
++ rx_ring_no=3;
++ }
++#endif /* CONFIG_ARCH_MT7623 */
++ else if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.DDONE_bit == 1) {
++ rx_ring = ei_local->rx_ring0;
++ rx_dma_owner_idx = rx_dma_owner_idx0;
++ // printk("rx_dma_owner_idx0=%x\n",rx_dma_owner_idx0);
++ rx_ring_no=0;
++ } else {
++ break;
++ }
++#else
++
++ if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.DDONE_bit == 1) {
++ rx_ring = ei_local->rx_ring0;
++ rx_dma_owner_idx = rx_dma_owner_idx0;
++ } else {
++ break;
++ }
++#endif
++
++#if defined (CONFIG_32B_DESC)
++ prefetch(&rx_ring[(rx_dma_owner_idx + 1) % NUM_RX_DESC]);
++#endif
++ /* skb processing */
++#if defined (CONFIG_RAETH_HW_LRO)
++ length = (rx_ring[rx_dma_owner_idx].rxd_info2.PLEN1 << 14) | rx_ring[rx_dma_owner_idx].rxd_info2.PLEN0;
++#else
++ length = rx_ring[rx_dma_owner_idx].rxd_info2.PLEN0;
++#endif /* CONFIG_RAETH_HW_LRO */
++
++#if defined (CONFIG_ARCH_MT7623)
++ dma_unmap_single(NULL, rx_ring[rx_dma_owner_idx].rxd_info1.PDP0, length, DMA_FROM_DEVICE);
++#endif
++
++#if defined (CONFIG_RAETH_HW_LRO)
++ if(rx_ring_no==3) {
++ rx_skb = ei_local->netrx3_skbuf[rx_dma_owner_idx];
++ rx_skb->data = ei_local->netrx3_skbuf[rx_dma_owner_idx]->data;
++ }
++ else if(rx_ring_no==2) {
++ rx_skb = ei_local->netrx2_skbuf[rx_dma_owner_idx];
++ rx_skb->data = ei_local->netrx2_skbuf[rx_dma_owner_idx]->data;
++ }
++ else if(rx_ring_no==1) {
++ rx_skb = ei_local->netrx1_skbuf[rx_dma_owner_idx];
++ rx_skb->data = ei_local->netrx1_skbuf[rx_dma_owner_idx]->data;
++ }
++ else {
++ rx_skb = ei_local->netrx0_skbuf[rx_dma_owner_idx];
++ rx_skb->data = ei_local->netrx0_skbuf[rx_dma_owner_idx]->data;
++ }
++ #if defined(CONFIG_RAETH_PDMA_DVT)
++ raeth_pdma_lro_dvt( rx_ring_no, ei_local, rx_dma_owner_idx );
++ #endif /* CONFIG_RAETH_PDMA_DVT */
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++ if(rx_ring_no==1) {
++ rx_skb = ei_local->netrx1_skbuf[rx_dma_owner_idx];
++ rx_skb->data = ei_local->netrx1_skbuf[rx_dma_owner_idx]->data;
++ }
++#if defined(CONFIG_ARCH_MT7623)
++ else if(rx_ring_no==2) {
++ rx_skb = ei_local->netrx2_skbuf[rx_dma_owner_idx];
++ rx_skb->data = ei_local->netrx2_skbuf[rx_dma_owner_idx]->data;
++ }
++ else if(rx_ring_no==3) {
++ rx_skb = ei_local->netrx3_skbuf[rx_dma_owner_idx];
++ rx_skb->data = ei_local->netrx3_skbuf[rx_dma_owner_idx]->data;
++ }
++#endif /* CONFIG_ARCH_MT7623 */
++ else {
++ rx_skb = ei_local->netrx0_skbuf[rx_dma_owner_idx];
++ rx_skb->data = ei_local->netrx0_skbuf[rx_dma_owner_idx]->data;
++ }
++ #if defined(CONFIG_RAETH_PDMA_DVT)
++ raeth_pdma_lro_dvt( rx_ring_no, ei_local, rx_dma_owner_idx );
++ #endif /* CONFIG_RAETH_PDMA_DVT */
++#else
++ rx_skb = ei_local->netrx0_skbuf[rx_dma_owner_idx];
++ rx_skb->data = ei_local->netrx0_skbuf[rx_dma_owner_idx]->data;
++ #if defined(CONFIG_RAETH_PDMA_DVT)
++ raeth_pdma_rx_desc_dvt( ei_local, rx_dma_owner_idx0 );
++ #endif /* CONFIG_RAETH_PDMA_DVT */
++#endif
++ rx_skb->len = length;
++/*TODO*/
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++ rx_skb->data += NET_IP_ALIGN;
++#endif
++ rx_skb->tail = rx_skb->data + length;
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++ if(rx_ring[rx_dma_owner_idx].rxd_info4.SP == 2) {
++ if(ei_local->PseudoDev!=NULL) {
++ rx_skb->dev = ei_local->PseudoDev;
++ rx_skb->protocol = eth_type_trans(rx_skb,ei_local->PseudoDev);
++ }else {
++ printk("ERROR: PseudoDev is still not initialize but receive packet from GMAC2\n");
++ }
++ }else{
++ rx_skb->dev = dev;
++ rx_skb->protocol = eth_type_trans(rx_skb,dev);
++ }
++#else
++ rx_skb->dev = dev;
++ rx_skb->protocol = eth_type_trans(rx_skb,dev);
++#endif
++
++#ifdef CONFIG_RAETH_CHECKSUM_OFFLOAD
++#if defined (CONFIG_PDMA_NEW)
++ if(rx_ring[rx_dma_owner_idx].rxd_info4.L4VLD) {
++ rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
++ }else {
++ rx_skb->ip_summed = CHECKSUM_NONE;
++ }
++#else
++ if(rx_ring[rx_dma_owner_idx].rxd_info4.IPFVLD_bit) {
++ rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
++ }else {
++ rx_skb->ip_summed = CHECKSUM_NONE;
++ }
++#endif
++#else
++ rx_skb->ip_summed = CHECKSUM_NONE;
++#endif
++
++#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE)
++ /* Qwert+
++ */
++ if(ra_classifier_hook_rx!= NULL)
++ {
++#if defined(CONFIG_RALINK_EXTERNAL_TIMER)
++ ra_classifier_hook_rx(rx_skb, (*((volatile u32 *)(0xB0000D08))&0x0FFFF));
++#else
++ ra_classifier_hook_rx(rx_skb, read_c0_count());
++#endif
++ }
++#endif /* CONFIG_RA_CLASSIFIER */
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++ if(ra_sw_nat_hook_rx != NULL) {
++ FOE_MAGIC_TAG(rx_skb)= FOE_MAGIC_GE;
++ *(uint32_t *)(FOE_INFO_START_ADDR(rx_skb)+2) = *(uint32_t *)&rx_ring[rx_dma_owner_idx].rxd_info4;
++ FOE_ALG(rx_skb) = 0;
++ }
++#endif
++
++ /* We have to check the free memory size is big enough
++ * before pass the packet to cpu*/
++#if defined (CONFIG_RAETH_SKB_RECYCLE_2K)
++#if defined (CONFIG_RAETH_HW_LRO)
++ if( rx_ring != ei_local->rx_ring0 )
++ skb = __dev_alloc_skb(MAX_LRO_RX_LENGTH + NET_IP_ALIGN, GFP_ATOMIC);
++ else
++#endif /* CONFIG_RAETH_HW_LRO */
++ skb = skbmgr_dev_alloc_skb2k();
++#else
++#if defined (CONFIG_RAETH_HW_LRO)
++ if( rx_ring != ei_local->rx_ring0 )
++ skb = __dev_alloc_skb(MAX_LRO_RX_LENGTH + NET_IP_ALIGN, GFP_ATOMIC);
++ else
++#endif /* CONFIG_RAETH_HW_LRO */
++ skb = __dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN, GFP_ATOMIC);
++#endif
++
++ if (unlikely(skb == NULL))
++ {
++ printk(KERN_ERR "skb not available...\n");
++#ifdef CONFIG_PSEUDO_SUPPORT
++ if (rx_ring[rx_dma_owner_idx].rxd_info4.SP == 2) {
++ if (ei_local->PseudoDev != NULL) {
++ pAd = netdev_priv(ei_local->PseudoDev);
++ pAd->stat.rx_dropped++;
++ }
++ } else
++#endif
++ ei_local->stat.rx_dropped++;
++ bReschedule = 1;
++ break;
++ }
++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++ skb_reserve(skb, NET_IP_ALIGN);
++#endif
++
++#if defined (CONFIG_RAETH_SPECIAL_TAG)
++ // port0: 0x8100 => 0x8100 0001
++ // port1: 0x8101 => 0x8100 0002
++ // port2: 0x8102 => 0x8100 0003
++ // port3: 0x8103 => 0x8100 0004
++ // port4: 0x8104 => 0x8100 0005
++ // port5: 0x8105 => 0x8100 0006
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)
++ veth = (struct vlan_ethhdr *)(rx_skb->mac_header);
++#else
++ veth = (struct vlan_ethhdr *)(rx_skb->mac.raw);
++#endif
++ /*donot check 0x81 due to MT7530 SPEC*/
++ //if((veth->h_vlan_proto & 0xFF) == 0x81)
++ {
++ veth->h_vlan_TCI = htons( (((veth->h_vlan_proto >> 8) & 0xF) + 1) );
++ rx_skb->protocol = veth->h_vlan_proto = htons(ETH_P_8021Q);
++ }
++#endif
++
++/* ra_sw_nat_hook_rx return 1 --> continue
++ * ra_sw_nat_hook_rx return 0 --> FWD & without netif_rx
++ */
++#if !defined(CONFIG_RA_NAT_NONE)
++ if((ra_sw_nat_hook_rx == NULL) ||
++ (ra_sw_nat_hook_rx!= NULL && ra_sw_nat_hook_rx(rx_skb)))
++#endif
++ {
++#if defined (CONFIG_RALINK_RT3052_MP2)
++ if(mcast_rx(rx_skb)==0) {
++ kfree_skb(rx_skb);
++ }else
++#endif
++#if defined (CONFIG_RAETH_LRO)
++ if (rx_skb->ip_summed == CHECKSUM_UNNECESSARY) {
++ lro_receive_skb(&ei_local->lro_mgr, rx_skb, NULL);
++ //LroStatsUpdate(&ei_local->lro_mgr,0);
++ } else
++#endif
++#ifdef CONFIG_RAETH_NAPI
++ netif_receive_skb(rx_skb);
++#else
++#ifdef CONFIG_RAETH_HW_VLAN_RX
++ if(ei_local->vlgrp && rx_ring[rx_dma_owner_idx].rxd_info2.TAG) {
++ vlan_hwaccel_rx(rx_skb, ei_local->vlgrp, rx_ring[rx_dma_owner_idx].rxd_info3.VID);
++ } else {
++ netif_rx(rx_skb);
++ }
++#else
++#ifdef CONFIG_RAETH_CPU_LOOPBACK
++ skb_push(rx_skb,ETH_HLEN);
++ ei_start_xmit(rx_skb, dev, 1);
++#else
++ netif_rx(rx_skb);
++#endif
++#endif
++#endif
++ }
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++ if (rx_ring[rx_dma_owner_idx].rxd_info4.SP == 2) {
++ if (ei_local->PseudoDev != NULL) {
++ pAd = netdev_priv(ei_local->PseudoDev);
++ pAd->stat.rx_packets++;
++ pAd->stat.rx_bytes += length;
++ }
++ } else
++#endif
++ {
++ ei_local->stat.rx_packets++;
++ ei_local->stat.rx_bytes += length;
++ }
++
++
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++#if defined (CONFIG_RAETH_HW_LRO)
++ if( rx_ring != ei_local->rx_ring0 ){
++ rx_ring[rx_dma_owner_idx].rxd_info2.PLEN0 = SET_ADMA_RX_LEN0(MAX_LRO_RX_LENGTH);
++ rx_ring[rx_dma_owner_idx].rxd_info2.PLEN1 = SET_ADMA_RX_LEN1(MAX_LRO_RX_LENGTH >> 14);
++ }
++ else
++#endif /* CONFIG_RAETH_HW_LRO */
++ rx_ring[rx_dma_owner_idx].rxd_info2.PLEN0 = MAX_RX_LENGTH;
++ rx_ring[rx_dma_owner_idx].rxd_info2.LS0 = 0;
++#endif
++ rx_ring[rx_dma_owner_idx].rxd_info2.DDONE_bit = 0;
++#if defined (CONFIG_RAETH_HW_LRO)
++ if( rx_ring != ei_local->rx_ring0 )
++ rx_ring[rx_dma_owner_idx].rxd_info1.PDP0 = dma_map_single(NULL, skb->data, MAX_LRO_RX_LENGTH, PCI_DMA_FROMDEVICE);
++ else
++#endif /* CONFIG_RAETH_HW_LRO */
++ rx_ring[rx_dma_owner_idx].rxd_info1.PDP0 = dma_map_single(NULL, skb->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++#ifdef CONFIG_32B_DESC
++ dma_cache_sync(NULL, &rx_ring[rx_dma_owner_idx], sizeof(struct PDMA_rxdesc), DMA_TO_DEVICE);
++#endif
++ /* Move point to next RXD which wants to alloc*/
++#if defined (CONFIG_RAETH_HW_LRO)
++ if(rx_ring_no==3) {
++ sysRegWrite(RAETH_RX_CALC_IDX3, rx_dma_owner_idx);
++ ei_local->netrx3_skbuf[rx_dma_owner_idx] = skb;
++ }
++ else if(rx_ring_no==2) {
++ sysRegWrite(RAETH_RX_CALC_IDX2, rx_dma_owner_idx);
++ ei_local->netrx2_skbuf[rx_dma_owner_idx] = skb;
++ }
++ else if(rx_ring_no==1) {
++ sysRegWrite(RAETH_RX_CALC_IDX1, rx_dma_owner_idx);
++ ei_local->netrx1_skbuf[rx_dma_owner_idx] = skb;
++ }
++ else if(rx_ring_no==0) {
++ sysRegWrite(RAETH_RX_CALC_IDX0, rx_dma_owner_idx);
++ ei_local->netrx0_skbuf[rx_dma_owner_idx] = skb;
++ }
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++ if(rx_ring_no==0) {
++ sysRegWrite(RAETH_RX_CALC_IDX0, rx_dma_owner_idx);
++ ei_local->netrx0_skbuf[rx_dma_owner_idx] = skb;
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ rx_calc_idx0 = rx_dma_owner_idx;
++#endif
++ }
++#if defined(CONFIG_ARCH_MT7623)
++ else if(rx_ring_no==3) {
++ sysRegWrite(RAETH_RX_CALC_IDX3, rx_dma_owner_idx);
++ ei_local->netrx3_skbuf[rx_dma_owner_idx] = skb;
++ }
++ else if(rx_ring_no==2) {
++ sysRegWrite(RAETH_RX_CALC_IDX2, rx_dma_owner_idx);
++ ei_local->netrx2_skbuf[rx_dma_owner_idx] = skb;
++ }
++#endif /* CONFIG_ARCH_MT7623 */
++ else {
++ sysRegWrite(RAETH_RX_CALC_IDX1, rx_dma_owner_idx);
++ ei_local->netrx1_skbuf[rx_dma_owner_idx] = skb;
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ rx_calc_idx1 = rx_dma_owner_idx;
++#endif
++ }
++#else
++ sysRegWrite(RAETH_RX_CALC_IDX0, rx_dma_owner_idx);
++ ei_local->netrx0_skbuf[rx_dma_owner_idx] = skb;
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ rx_calc_idx0 = rx_dma_owner_idx;
++#endif
++#endif
++
++
++ /* Update to Next packet point that was received.
++ */
++#if defined (CONFIG_RAETH_HW_LRO)
++ if(rx_ring_no==3)
++ rx_dma_owner_lro3 = (sysRegRead(RAETH_RX_CALC_IDX3) + 1) % NUM_LRO_RX_DESC;
++ else if(rx_ring_no==2)
++ rx_dma_owner_lro2 = (sysRegRead(RAETH_RX_CALC_IDX2) + 1) % NUM_LRO_RX_DESC;
++ else if(rx_ring_no==1)
++ rx_dma_owner_lro1 = (sysRegRead(RAETH_RX_CALC_IDX1) + 1) % NUM_LRO_RX_DESC;
++ else if(rx_ring_no==0)
++ rx_dma_owner_idx0 = (sysRegRead(RAETH_RX_CALC_IDX0) + 1) % NUM_RX_DESC;
++ else {
++ }
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++ if(rx_ring_no==0) {
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ rx_dma_owner_idx0 = (rx_dma_owner_idx + 1) % NUM_RX_DESC;
++#else
++ rx_dma_owner_idx0 = (sysRegRead(RAETH_RX_CALC_IDX0) + 1) % NUM_RX_DESC;
++#endif
++#if defined(CONFIG_ARCH_MT7623)
++ }else if(rx_ring_no==3) {
++ rx_dma_owner_idx3 = (sysRegRead(RAETH_RX_CALC_IDX3) + 1) % NUM_RX_DESC;
++ }else if(rx_ring_no==2) {
++ rx_dma_owner_idx2 = (sysRegRead(RAETH_RX_CALC_IDX2) + 1) % NUM_RX_DESC;
++#endif /* CONFIG_ARCH_MT7623 */
++ }else {
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ rx_dma_owner_idx1 = (rx_dma_owner_idx + 1) % NUM_RX_DESC;
++#else
++ rx_dma_owner_idx1 = (sysRegRead(RAETH_RX_CALC_IDX1) + 1) % NUM_RX_DESC;
++#endif
++ }
++#else
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ rx_dma_owner_idx0 = (rx_dma_owner_idx + 1) % NUM_RX_DESC;
++#else
++ rx_dma_owner_idx0 = (sysRegRead(RAETH_RX_CALC_IDX0) + 1) % NUM_RX_DESC;
++#endif
++#endif
++ } /* for */
++
++#if defined (CONFIG_RAETH_LRO)
++ if (lro_flush_needed) {
++ //LroStatsUpdate(&ei_local->lro_mgr,1);
++ lro_flush_all(&ei_local->lro_mgr);
++ lro_flush_needed = 0;
++ }
++#endif
++ return bReschedule;
++}
++
++
++///////////////////////////////////////////////////////////////////
++/////
++///// ra_get_stats - gather packet information for management plane
++/////
++///// Pass net_device_stats to the upper layer.
++/////
++/////
++///// RETURNS: pointer to net_device_stats
++///////////////////////////////////////////////////////////////////
++
++struct net_device_stats *ra_get_stats(struct net_device *dev)
++{
++ END_DEVICE *ei_local = netdev_priv(dev);
++ return &ei_local->stat;
++}
++
++#if defined (CONFIG_RT_3052_ESW)
++void kill_sig_workq(struct work_struct *work)
++{
++ struct file *fp;
++ char pid[8];
++ struct task_struct *p = NULL;
++
++ //read udhcpc pid from file, and send signal USR2,USR1 to get a new IP
++ fp = filp_open("/var/run/udhcpc.pid", O_RDONLY, 0);
++ if (IS_ERR(fp))
++ return;
++
++ if (fp->f_op && fp->f_op->read) {
++ if (fp->f_op->read(fp, pid, 8, &fp->f_pos) > 0) {
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ p = pid_task(find_get_pid(simple_strtoul(pid, NULL, 10)), PIDTYPE_PID);
++#else
++ p = find_task_by_pid(simple_strtoul(pid, NULL, 10));
++#endif
++
++ if (NULL != p) {
++ send_sig(SIGUSR2, p, 0);
++ send_sig(SIGUSR1, p, 0);
++ }
++ }
++ }
++ filp_close(fp, NULL);
++
++}
++#endif
++
++
++///////////////////////////////////////////////////////////////////
++/////
++///// ra2880Recv - process the next incoming packet
++/////
++///// Handle one incoming packet. The packet is checked for errors and sent
++///// to the upper layer.
++/////
++///// RETURNS: OK on success or ERROR.
++///////////////////////////////////////////////////////////////////
++
++#ifndef CONFIG_RAETH_NAPI
++#if defined WORKQUEUE_BH || defined (TASKLET_WORKQUEUE_SW)
++void ei_receive_workq(struct work_struct *work)
++#else
++void ei_receive(unsigned long unused) // device structure
++#endif // WORKQUEUE_BH //
++{
++ struct net_device *dev = dev_raether;
++ END_DEVICE *ei_local = netdev_priv(dev);
++ unsigned long reg_int_mask=0;
++ int bReschedule=0;
++
++
++ if(tx_ring_full==0){
++ bReschedule = rt2880_eth_recv(dev);
++ if(bReschedule)
++ {
++#ifdef WORKQUEUE_BH
++ schedule_work(&ei_local->rx_wq);
++#else
++#if defined (TASKLET_WORKQUEUE_SW)
++ if (working_schedule == 1)
++ schedule_work(&ei_local->rx_wq);
++ else
++#endif
++ tasklet_hi_schedule(&ei_local->rx_tasklet);
++#endif // WORKQUEUE_BH //
++ }else{
++ reg_int_mask=sysRegRead(RAETH_FE_INT_ENABLE);
++#if defined(DELAY_INT)
++ sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask| RX_DLY_INT);
++#else
++ sysRegWrite(RAETH_FE_INT_ENABLE, (reg_int_mask | RX_DONE_INT0 | RX_DONE_INT1 | RX_DONE_INT2 | RX_DONE_INT3));
++#endif
++#ifdef CONFIG_RAETH_QDMA
++ reg_int_mask=sysRegRead(QFE_INT_ENABLE);
++#if defined(DELAY_INT)
++ sysRegWrite(QFE_INT_ENABLE, reg_int_mask| RX_DLY_INT);
++#else
++ sysRegWrite(QFE_INT_ENABLE, (reg_int_mask | RX_DONE_INT0 | RX_DONE_INT1));
++#endif
++
++#endif
++
++ }
++ }else{
++#ifdef WORKQUEUE_BH
++ schedule_work(&ei_local->rx_wq);
++#else
++#if defined (TASKLET_WORKQUEUE_SW)
++ if (working_schedule == 1)
++ schedule_work(&ei_local->rx_wq);
++ else
++#endif
++ tasklet_schedule(&ei_local->rx_tasklet);
++#endif // WORKQUEUE_BH //
++ }
++}
++#endif
++
++#if defined (CONFIG_RAETH_HW_LRO)
++void ei_hw_lro_auto_adj(unsigned int index, END_DEVICE* ei_local)
++{
++ unsigned int entry;
++ unsigned int pkt_cnt;
++ unsigned int tick_cnt;
++ unsigned int duration_us;
++ unsigned int byte_cnt;
++
++ /* read packet count statitics of the auto-learn table */
++ entry = index + 68;
++ sysRegWrite( PDMA_FE_ALT_CF8, entry );
++ pkt_cnt = sysRegRead(PDMA_FE_ALT_SGL_CFC) & 0xfff;
++ tick_cnt = (sysRegRead(PDMA_FE_ALT_SGL_CFC) >> 16) & 0xffff;
++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG)
++ printk("[HW LRO] ei_hw_lro_auto_adj(): pkt_cnt[%d]=%d, tick_cnt[%d]=%d\n", index, pkt_cnt, index, tick_cnt);
++ printk("[HW LRO] ei_hw_lro_auto_adj(): packet_interval[%d]=%d (ticks/pkt)\n", index, tick_cnt/pkt_cnt);
++#endif
++
++ /* read byte count statitics of the auto-learn table */
++ entry = index + 64;
++ sysRegWrite( PDMA_FE_ALT_CF8, entry );
++ byte_cnt = sysRegRead(PDMA_FE_ALT_SGL_CFC);
++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG)
++ printk("[HW LRO] ei_hw_lro_auto_adj(): byte_cnt[%d]=%d\n", index, byte_cnt);
++#endif
++
++ /* calculate the packet interval of the rx flow */
++ duration_us = tick_cnt * HW_LRO_TIMER_UNIT;
++ ei_local->hw_lro_pkt_interval[index - 1] = (duration_us/pkt_cnt) * ei_local->hw_lro_alpha / 100;
++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG)
++ printk("[HW LRO] ei_hw_lro_auto_adj(): packet_interval[%d]=%d (20us)\n", index, duration_us/pkt_cnt);
++#endif
++
++ if ( !ei_local->hw_lro_fix_setting ){
++ /* adjust age_time, agg_time for the lro ring */
++ if(ei_local->hw_lro_pkt_interval[index - 1] > 0){
++ SET_PDMA_RXRING_AGE_TIME(index, (ei_local->hw_lro_pkt_interval[index - 1] * HW_LRO_MAX_AGG_CNT));
++ SET_PDMA_RXRING_AGG_TIME(index, (ei_local->hw_lro_pkt_interval[index - 1] * HW_LRO_AGG_DELTA));
++ }
++ else{
++ SET_PDMA_RXRING_AGE_TIME(index, HW_LRO_MAX_AGG_CNT);
++ SET_PDMA_RXRING_AGG_TIME(index, HW_LRO_AGG_DELTA);
++ }
++ }
++}
++
++void ei_hw_lro_workq(struct work_struct *work)
++{
++ END_DEVICE *ei_local;
++ unsigned int reg_int_val;
++ unsigned int reg_int_mask;
++
++ ei_local = container_of(work, struct end_device, hw_lro_wq);
++
++ reg_int_val = sysRegRead(RAETH_FE_INT_STATUS);
++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG)
++ printk("[HW LRO] ei_hw_lro_workq(): RAETH_FE_INT_STATUS=0x%x\n", reg_int_val);
++#endif
++ if((reg_int_val & ALT_RPLC_INT3)){
++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG)
++ printk("[HW LRO] ALT_RPLC_INT3 occurred!\n");
++#endif
++ sysRegWrite(RAETH_FE_INT_STATUS, ALT_RPLC_INT3);
++ ei_hw_lro_auto_adj(3, ei_local);
++ }
++ if((reg_int_val & ALT_RPLC_INT2)){
++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG)
++ printk("[HW LRO] ALT_RPLC_INT2 occurred!\n");
++#endif
++ sysRegWrite(RAETH_FE_INT_STATUS, ALT_RPLC_INT2);
++ ei_hw_lro_auto_adj(2, ei_local);
++ }
++ if((reg_int_val & ALT_RPLC_INT1)){
++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG)
++ printk("[HW LRO] ALT_RPLC_INT1 occurred!\n");
++#endif
++ sysRegWrite(RAETH_FE_INT_STATUS, ALT_RPLC_INT1);
++ ei_hw_lro_auto_adj(1, ei_local);
++ }
++
++ /* unmask interrupts of rx flow to hw lor rings */
++ reg_int_mask = sysRegRead(RAETH_FE_INT_ENABLE);
++ sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask | ALT_RPLC_INT3 | ALT_RPLC_INT2 | ALT_RPLC_INT1);
++}
++#endif /* CONFIG_RAETH_HW_LRO */
++
++#ifdef CONFIG_RAETH_NAPI
++static int
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++raeth_clean(struct napi_struct *napi, int budget)
++#else
++raeth_clean(struct net_device *netdev, int *budget)
++#endif
++{
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ struct net_device *netdev=dev_raether;
++ int work_to_do = budget;
++#else
++ int work_to_do = min(*budget, netdev->quota);
++#endif
++ END_DEVICE *ei_local =netdev_priv(netdev);
++ int work_done = 0;
++ unsigned long reg_int_mask=0;
++
++ ei_xmit_housekeeping(0);
++
++ rt2880_eth_recv(netdev, &work_done, work_to_do);
++
++ /* this could control when to re-enable interrupt, 0-> mean never enable interrupt*/
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
++ *budget -= work_done;
++ netdev->quota -= work_done;
++#endif
++ /* if no Tx and not enough Rx work done, exit the polling mode */
++ if(( (work_done < work_to_do)) || !netif_running(netdev)) {
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ napi_complete(&ei_local->napi);
++#else
++ netif_rx_complete(netdev);
++#endif
++ atomic_dec_and_test(&ei_local->irq_sem);
++
++ sysRegWrite(RAETH_FE_INT_STATUS, RAETH_FE_INT_ALL); // ack all fe interrupts
++ reg_int_mask=sysRegRead(RAETH_FE_INT_ENABLE);
++
++#ifdef DELAY_INT
++ sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask |RAETH_FE_INT_DLY_INIT); // init delay interrupt only
++#else
++ sysRegWrite(RAETH_FE_INT_ENABLE,reg_int_mask | RAETH_FE_INT_SETTING);
++#endif
++
++#ifdef CONFIG_RAETH_QDMA
++ sysRegWrite(QFE_INT_STATUS, QFE_INT_ALL);
++ reg_int_mask=sysRegRead(QFE_INT_ENABLE);
++#ifdef DELAY_INT
++ sysRegWrite(QFE_INT_ENABLE, reg_int_mask |QFE_INT_DLY_INIT); // init delay interrupt only
++#else
++ sysRegWrite(QFE_INT_ENABLE,reg_int_mask | (RX_DONE_INT0 | RX_DONE_INT1 | RLS_DONE_INT));
++#endif
++#endif // CONFIG_RAETH_QDMA //
++
++ return 0;
++ }
++
++ return 1;
++}
++
++#endif
++
++
++void gsw_delay_setting(void)
++{
++#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN) || defined (CONFIG_GE_RGMII_INTERNAL_P4_AN)
++ END_DEVICE *ei_local = netdev_priv(dev_raether);
++ int reg_int_val = 0;
++ int link_speed = 0;
++
++ reg_int_val = sysRegRead(FE_INT_STATUS2);
++#if defined (CONFIG_RALINK_MT7621)
++ if( reg_int_val & BIT(25))
++ {
++ if(sysRegRead(RALINK_ETH_SW_BASE+0x0208) & 0x1) // link up
++ {
++ link_speed = (sysRegRead(RALINK_ETH_SW_BASE+0x0208)>>2 & 0x3);
++ if(link_speed == 1)
++ {
++ // delay setting for 100M
++ if((sysRegRead(0xbe00000c)&0xFFFF)==0x0101)
++ mii_mgr_write(31, 0x7b00, 8);
++ printk("MT7621 GE2 link rate to 100M\n");
++ } else
++ {
++ //delay setting for 10/1000M
++ if((sysRegRead(0xbe00000c)&0xFFFF)==0x0101)
++ mii_mgr_write(31, 0x7b00, 0x102);
++ printk("MT7621 GE2 link rate to 10M/1G\n");
++ }
++ schedule_work(&ei_local->kill_sig_wq);
++ }
++ }
++#endif
++ sysRegWrite(FE_INT_STATUS2, reg_int_val);
++#endif
++}
++
++/**
++ * ei_interrupt - handle controler interrupt
++ *
++ * This routine is called at interrupt level in response to an interrupt from
++ * the controller.
++ *
++ * RETURNS: N/A.
++ */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
++static irqreturn_t ei_interrupt(int irq, void *dev_id)
++#else
++static irqreturn_t ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
++#endif
++{
++#if !defined(CONFIG_RAETH_NAPI)
++ unsigned long reg_int_val;
++ unsigned long reg_int_mask=0;
++ unsigned int recv = 0;
++ unsigned int transmit __maybe_unused = 0;
++ unsigned long flags;
++#endif
++
++ struct net_device *dev = (struct net_device *) dev_id;
++ END_DEVICE *ei_local = netdev_priv(dev);
++
++ //Qwert
++ /*
++ unsigned long old,cur,dcycle;
++ static int cnt = 0;
++ static unsigned long max_dcycle = 0,tcycle = 0;
++ old = read_c0_count();
++ */
++ if (dev == NULL)
++ {
++ printk (KERN_ERR "net_interrupt(): irq %x for unknown device.\n", IRQ_ENET0);
++ return IRQ_NONE;
++ }
++
++#ifdef CONFIG_RAETH_NAPI
++ gsw_delay_setting();
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ if(napi_schedule_prep(&ei_local->napi)) {
++#else
++ if(netif_rx_schedule_prep(dev)) {
++#endif
++ atomic_inc(&ei_local->irq_sem);
++ sysRegWrite(RAETH_FE_INT_ENABLE, 0);
++#ifdef CONFIG_RAETH_QDMA
++ sysRegWrite(QFE_INT_ENABLE, 0);
++#endif
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ __napi_schedule(&ei_local->napi);
++#else
++ __netif_rx_schedule(dev);
++#endif
++ }
++#else
++
++ spin_lock_irqsave(&(ei_local->page_lock), flags);
++ reg_int_val = sysRegRead(RAETH_FE_INT_STATUS);
++#ifdef CONFIG_RAETH_QDMA
++ reg_int_val |= sysRegRead(QFE_INT_STATUS);
++#endif
++#if defined (DELAY_INT)
++ if((reg_int_val & RX_DLY_INT))
++ recv = 1;
++
++ if (reg_int_val & RAETH_TX_DLY_INT)
++ transmit = 1;
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++ raeth_pdma_lro_dly_int_dvt();
++#endif /* CONFIG_RAETH_PDMA_DVT */
++
++#else
++ if((reg_int_val & (RX_DONE_INT0 | RX_DONE_INT3 | RX_DONE_INT2 | RX_DONE_INT1)))
++ recv = 1;
++
++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++#if defined(CONFIG_ARCH_MT7623)
++ if((reg_int_val & RX_DONE_INT3))
++ recv = 3;
++ if((reg_int_val & RX_DONE_INT2))
++ recv = 2;
++#endif /* CONFIG_ARCH_MT7623 */
++ if((reg_int_val & RX_DONE_INT1))
++ recv = 1;
++#endif
++
++ if (reg_int_val & RAETH_TX_DONE_INT0)
++ transmit |= RAETH_TX_DONE_INT0;
++#if defined (CONFIG_RAETH_QOS)
++ if (reg_int_val & TX_DONE_INT1)
++ transmit |= TX_DONE_INT1;
++ if (reg_int_val & TX_DONE_INT2)
++ transmit |= TX_DONE_INT2;
++ if (reg_int_val & TX_DONE_INT3)
++ transmit |= TX_DONE_INT3;
++#endif //CONFIG_RAETH_QOS
++
++#endif //DELAY_INT
++
++#if defined (DELAY_INT)
++ sysRegWrite(RAETH_FE_INT_STATUS, RAETH_FE_INT_DLY_INIT);
++#else
++ sysRegWrite(RAETH_FE_INT_STATUS, RAETH_FE_INT_ALL);
++#endif
++#ifdef CONFIG_RAETH_QDMA
++#if defined (DELAY_INT)
++ sysRegWrite(QFE_INT_STATUS, QFE_INT_DLY_INIT);
++#else
++ sysRegWrite(QFE_INT_STATUS, QFE_INT_ALL);
++#endif
++#endif
++
++#if defined (CONFIG_RAETH_HW_LRO)
++ if( reg_int_val & (ALT_RPLC_INT3 | ALT_RPLC_INT2 | ALT_RPLC_INT1) ){
++ /* mask interrupts of rx flow to hw lor rings */
++ reg_int_mask = sysRegRead(RAETH_FE_INT_ENABLE);
++ sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask & ~(ALT_RPLC_INT3 | ALT_RPLC_INT2 | ALT_RPLC_INT1));
++ schedule_work(&ei_local->hw_lro_wq);
++ }
++#endif /* CONFIG_RAETH_HW_LRO */
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
++ if(transmit)
++ ei_xmit_housekeeping(0);
++#else
++ ei_xmit_housekeeping(0);
++#endif
++
++ if (((recv == 1) || (pending_recv ==1)) && (tx_ring_full==0))
++ {
++ reg_int_mask = sysRegRead(RAETH_FE_INT_ENABLE);
++#if defined (DELAY_INT)
++ sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask & ~(RX_DLY_INT));
++#else
++ sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask & ~(RX_DONE_INT0 | RX_DONE_INT1 | RX_DONE_INT2 | RX_DONE_INT3));
++#endif //DELAY_INT
++#ifdef CONFIG_RAETH_QDMA
++ reg_int_mask = sysRegRead(QFE_INT_ENABLE);
++#if defined (DELAY_INT)
++ sysRegWrite(QFE_INT_ENABLE, reg_int_mask & ~(RX_DLY_INT));
++#else
++ sysRegWrite(QFE_INT_ENABLE, reg_int_mask & ~(RX_DONE_INT0 | RX_DONE_INT1 | RX_DONE_INT2 | RX_DONE_INT3));
++#endif //DELAY_INT
++#endif
++
++ pending_recv=0;
++#ifdef WORKQUEUE_BH
++ schedule_work(&ei_local->rx_wq);
++#else
++#if defined (TASKLET_WORKQUEUE_SW)
++ if (working_schedule == 1)
++ schedule_work(&ei_local->rx_wq);
++ else
++#endif
++ tasklet_hi_schedule(&ei_local->rx_tasklet);
++#endif // WORKQUEUE_BH //
++ }
++ else if (recv == 1 && tx_ring_full==1)
++ {
++ pending_recv=1;
++ }
++ else if((recv == 0) && (transmit == 0))
++ {
++ gsw_delay_setting();
++ }
++ spin_unlock_irqrestore(&(ei_local->page_lock), flags);
++#endif
++
++ return IRQ_HANDLED;
++}
++
++#if defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || \
++ defined (CONFIG_RALINK_MT7620)|| defined (CONFIG_RALINK_MT7621)
++static void esw_link_status_changed(int port_no, void *dev_id)
++{
++ unsigned int reg_val;
++ struct net_device *dev = (struct net_device *) dev_id;
++ END_DEVICE *ei_local = netdev_priv(dev);
++
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined (CONFIG_RALINK_MT7620)
++ reg_val = *((volatile u32 *)(RALINK_ETH_SW_BASE+ 0x3008 + (port_no*0x100)));
++#elif defined (CONFIG_RALINK_MT7621)
++ mii_mgr_read(31, (0x3008 + (port_no*0x100)), &reg_val);
++#endif
++ if(reg_val & 0x1) {
++ printk("ESW: Link Status Changed - Port%d Link UP\n", port_no);
++#if defined (CONFIG_RALINK_MT7621) && defined (CONFIG_RAETH_8023AZ_EEE)
++ mii_mgr_write(port_no, 31, 0x52b5);
++ mii_mgr_write(port_no, 16, 0xb780);
++ mii_mgr_write(port_no, 17, 0x00e0);
++ mii_mgr_write(port_no, 16, 0x9780);
++#endif
++
++#if defined (CONFIG_WAN_AT_P0)
++ if(port_no==0) {
++ schedule_work(&ei_local->kill_sig_wq);
++ }
++#elif defined (CONFIG_WAN_AT_P4)
++ if(port_no==4) {
++ schedule_work(&ei_local->kill_sig_wq);
++ }
++#endif
++ } else {
++ printk("ESW: Link Status Changed - Port%d Link Down\n", port_no);
++#if defined (CONFIG_RALINK_MT7621) && defined (CONFIG_RAETH_8023AZ_EEE)
++ mii_mgr_write(port_no, 31, 0x52b5);
++ mii_mgr_write(port_no, 16, 0xb780);
++ mii_mgr_write(port_no, 17, 0x0000);
++ mii_mgr_write(port_no, 16, 0x9780);
++#endif
++
++ }
++}
++#endif
++
++#if defined (CONFIG_RT_3052_ESW) && ! defined(CONFIG_RALINK_MT7621) && ! defined(CONFIG_ARCH_MT7623)
++static irqreturn_t esw_interrupt(int irq, void *dev_id)
++{
++ unsigned long flags;
++ unsigned long reg_int_val;
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined(CONFIG_RALINK_MT7620)
++ unsigned long acl_int_val;
++ unsigned long mib_int_val;
++#else
++ static unsigned long stat;
++ unsigned long stat_curr;
++#endif
++
++ struct net_device *dev = (struct net_device *) dev_id;
++ END_DEVICE *ei_local = netdev_priv(dev);
++
++
++ spin_lock_irqsave(&(ei_local->page_lock), flags);
++ reg_int_val = (*((volatile u32 *)(ESW_ISR))); //Interrupt Status Register
++
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined(CONFIG_RALINK_MT7620)
++ if (reg_int_val & P5_LINK_CH) {
++ esw_link_status_changed(5, dev_id);
++ }
++ if (reg_int_val & P4_LINK_CH) {
++ esw_link_status_changed(4, dev_id);
++ }
++ if (reg_int_val & P3_LINK_CH) {
++ esw_link_status_changed(3, dev_id);
++ }
++ if (reg_int_val & P2_LINK_CH) {
++ esw_link_status_changed(2, dev_id);
++ }
++ if (reg_int_val & P1_LINK_CH) {
++ esw_link_status_changed(1, dev_id);
++ }
++ if (reg_int_val & P0_LINK_CH) {
++ esw_link_status_changed(0, dev_id);
++ }
++ if (reg_int_val & ACL_INT) {
++ acl_int_val = sysRegRead(ESW_AISR);
++ sysRegWrite(ESW_AISR, acl_int_val);
++ }
++ if (reg_int_val & MIB_INT) {
++
++ mib_int_val = sysRegRead(ESW_P0_IntSn);
++ if(mib_int_val){
++ sysRegWrite(ESW_P0_IntSn, mib_int_val);
++ if(mib_int_val & RX_GOOD_CNT)
++ p0_rx_good_cnt ++;
++ if(mib_int_val & TX_GOOD_CNT)
++ p0_tx_good_cnt ++;
++ if(mib_int_val & RX_GOCT_CNT)
++ p0_rx_byte_cnt ++;
++ if(mib_int_val & TX_GOCT_CNT)
++ p0_tx_byte_cnt ++;
++ }
++
++ mib_int_val = sysRegRead(ESW_P1_IntSn);
++ if(mib_int_val){
++ sysRegWrite(ESW_P1_IntSn, mib_int_val);
++ if(mib_int_val & RX_GOOD_CNT)
++ p1_rx_good_cnt ++;
++ if(mib_int_val & TX_GOOD_CNT)
++ p1_tx_good_cnt ++;
++ if(mib_int_val & RX_GOCT_CNT)
++ p1_rx_byte_cnt ++;
++ if(mib_int_val & TX_GOCT_CNT)
++ p1_tx_byte_cnt ++;
++ }
++
++ mib_int_val = sysRegRead(ESW_P2_IntSn);
++ if(mib_int_val){
++ sysRegWrite(ESW_P2_IntSn, mib_int_val);
++ if(mib_int_val & RX_GOOD_CNT)
++ p2_rx_good_cnt ++;
++ if(mib_int_val & TX_GOOD_CNT)
++ p2_tx_good_cnt ++;
++ if(mib_int_val & RX_GOCT_CNT)
++ p2_rx_byte_cnt ++;
++ if(mib_int_val & TX_GOCT_CNT)
++ p2_tx_byte_cnt ++;
++ }
++
++
++ mib_int_val = sysRegRead(ESW_P3_IntSn);
++ if(mib_int_val){
++ sysRegWrite(ESW_P3_IntSn, mib_int_val);
++ if(mib_int_val & RX_GOOD_CNT)
++ p3_rx_good_cnt ++;
++ if(mib_int_val & TX_GOOD_CNT)
++ p3_tx_good_cnt ++;
++ if(mib_int_val & RX_GOCT_CNT)
++ p3_rx_byte_cnt ++;
++ if(mib_int_val & TX_GOCT_CNT)
++ p3_tx_byte_cnt ++;
++ }
++
++ mib_int_val = sysRegRead(ESW_P4_IntSn);
++ if(mib_int_val){
++ sysRegWrite(ESW_P4_IntSn, mib_int_val);
++ if(mib_int_val & RX_GOOD_CNT)
++ p4_rx_good_cnt ++;
++ if(mib_int_val & TX_GOOD_CNT)
++ p4_tx_good_cnt ++;
++ if(mib_int_val & RX_GOCT_CNT)
++ p4_rx_byte_cnt ++;
++ if(mib_int_val & TX_GOCT_CNT)
++ p4_tx_byte_cnt ++;
++ }
++
++ mib_int_val = sysRegRead(ESW_P5_IntSn);
++ if(mib_int_val){
++ sysRegWrite(ESW_P5_IntSn, mib_int_val);
++ if(mib_int_val & RX_GOOD_CNT)
++ p5_rx_good_cnt ++;
++ if(mib_int_val & TX_GOOD_CNT)
++ p5_tx_good_cnt ++;
++ if(mib_int_val & RX_GOCT_CNT)
++ p5_rx_byte_cnt ++;
++ if(mib_int_val & TX_GOCT_CNT)
++ p5_tx_byte_cnt ++;
++ }
++
++ mib_int_val = sysRegRead(ESW_P6_IntSn);
++ if(mib_int_val){
++ sysRegWrite(ESW_P6_IntSn, mib_int_val);
++ if(mib_int_val & RX_GOOD_CNT)
++ p6_rx_good_cnt ++;
++ if(mib_int_val & TX_GOOD_CNT)
++ p6_tx_good_cnt ++;
++ if(mib_int_val & RX_GOCT_CNT)
++ p6_rx_byte_cnt ++;
++ if(mib_int_val & TX_GOCT_CNT)
++ p6_tx_byte_cnt ++;
++ }
++#if defined (CONFIG_RALINK_MT7620)
++ mib_int_val = sysRegRead(ESW_P7_IntSn);
++ if(mib_int_val){
++ sysRegWrite(ESW_P7_IntSn, mib_int_val);
++ if(mib_int_val & RX_GOOD_CNT)
++ p7_rx_good_cnt ++;
++ if(mib_int_val & TX_GOOD_CNT)
++ p7_tx_good_cnt ++;
++ if(mib_int_val & RX_GOCT_CNT)
++ p7_rx_byte_cnt ++;
++ if(mib_int_val & TX_GOCT_CNT)
++ p7_tx_byte_cnt ++;
++
++ }
++#endif
++ }
++
++#else // not RT6855
++ if (reg_int_val & PORT_ST_CHG) {
++ printk("RT305x_ESW: Link Status Changed\n");
++
++ stat_curr = *((volatile u32 *)(RALINK_ETH_SW_BASE+0x80));
++#ifdef CONFIG_WAN_AT_P0
++ //link down --> link up : send signal to user application
++ //link up --> link down : ignore
++ if ((stat & (1<<25)) || !(stat_curr & (1<<25)))
++#else
++ if ((stat & (1<<29)) || !(stat_curr & (1<<29)))
++#endif
++ goto out;
++
++ schedule_work(&ei_local->kill_sig_wq);
++out:
++ stat = stat_curr;
++ }
++
++#endif // defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A)//
++
++ sysRegWrite(ESW_ISR, reg_int_val);
++
++ spin_unlock_irqrestore(&(ei_local->page_lock), flags);
++ return IRQ_HANDLED;
++}
++
++
++
++#elif defined (CONFIG_RT_3052_ESW) && defined(CONFIG_RALINK_MT7621)
++
++static irqreturn_t esw_interrupt(int irq, void *dev_id)
++{
++ unsigned long flags;
++ unsigned int reg_int_val;
++ struct net_device *dev = (struct net_device *) dev_id;
++ END_DEVICE *ei_local = netdev_priv(dev);
++
++ spin_lock_irqsave(&(ei_local->page_lock), flags);
++ mii_mgr_read(31, 0x700c, &reg_int_val);
++
++ if (reg_int_val & P4_LINK_CH) {
++ esw_link_status_changed(4, dev_id);
++ }
++
++ if (reg_int_val & P3_LINK_CH) {
++ esw_link_status_changed(3, dev_id);
++ }
++ if (reg_int_val & P2_LINK_CH) {
++ esw_link_status_changed(2, dev_id);
++ }
++ if (reg_int_val & P1_LINK_CH) {
++ esw_link_status_changed(1, dev_id);
++ }
++ if (reg_int_val & P0_LINK_CH) {
++ esw_link_status_changed(0, dev_id);
++ }
++
++ mii_mgr_write(31, 0x700c, 0x1f); //ack switch link change
++
++ spin_unlock_irqrestore(&(ei_local->page_lock), flags);
++ return IRQ_HANDLED;
++}
++
++#endif
++
++
++static int ei_start_xmit_fake(struct sk_buff* skb, struct net_device *dev)
++{
++ return ei_start_xmit(skb, dev, 1);
++}
++
++
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350)
++void dump_phy_reg(int port_no, int from, int to, int is_local)
++{
++ u32 i=0;
++ u32 temp=0;
++
++ if(is_local==0) {
++ printk("Global Register\n");
++ printk("===============");
++ mii_mgr_write(0, 31, 0); //select global register
++ for(i=from;i<=to;i++) {
++ if(i%8==0) {
++ printk("\n");
++ }
++ mii_mgr_read(port_no,i, &temp);
++ printk("%02d: %04X ",i, temp);
++ }
++ } else {
++ mii_mgr_write(0, 31, 0x8000); //select local register
++ printk("\n\nLocal Register Port %d\n",port_no);
++ printk("===============");
++ for(i=from;i<=to;i++) {
++ if(i%8==0) {
++ printk("\n");
++ }
++ mii_mgr_read(port_no,i, &temp);
++ printk("%02d: %04X ",i, temp);
++ }
++ }
++ printk("\n");
++}
++#else
++void dump_phy_reg(int port_no, int from, int to, int is_local, int page_no)
++{
++
++ u32 i=0;
++ u32 temp=0;
++ u32 r31=0;
++
++
++ if(is_local==0) {
++
++ printk("\n\nGlobal Register Page %d\n",page_no);
++ printk("===============");
++ r31 |= 0 << 15; //global
++ r31 |= ((page_no&0x7) << 12); //page no
++ mii_mgr_write(port_no, 31, r31); //select global page x
++ for(i=16;i<32;i++) {
++ if(i%8==0) {
++ printk("\n");
++ }
++ mii_mgr_read(port_no,i, &temp);
++ printk("%02d: %04X ",i, temp);
++ }
++ }else {
++ printk("\n\nLocal Register Port %d Page %d\n",port_no, page_no);
++ printk("===============");
++ r31 |= 1 << 15; //local
++ r31 |= ((page_no&0x7) << 12); //page no
++ mii_mgr_write(port_no, 31, r31); //select local page x
++ for(i=16;i<32;i++) {
++ if(i%8==0) {
++ printk("\n");
++ }
++ mii_mgr_read(port_no,i, &temp);
++ printk("%02d: %04X ",i, temp);
++ }
++ }
++ printk("\n");
++}
++
++#endif
++
++int ei_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
++{
++#if defined(CONFIG_RT_3052_ESW) || defined(CONFIG_RAETH_QDMA)
++ esw_reg reg;
++#endif
++#if defined(CONFIG_RALINK_RT3352) || defined(CONFIG_RALINK_RT5350) || \
++ defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined(CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || \
++ defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
++ esw_rate ratelimit;
++#endif
++#if defined(CONFIG_RT_3052_ESW)
++ unsigned int offset = 0;
++ unsigned int value = 0;
++#endif
++
++ int ret = 0;
++ END_DEVICE *ei_local = netdev_priv(dev);
++ ra_mii_ioctl_data mii;
++ spin_lock_irq(&ei_local->page_lock);
++
++ switch (cmd) {
++#if defined(CONFIG_RAETH_QDMA)
++#define _HQOS_REG(x) (*((volatile u32 *)(RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + x)))
++ case RAETH_QDMA_REG_READ:
++ copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
++ if (reg.off > REG_HQOS_MAX) {
++ ret = -EINVAL;
++ break;
++ }
++ reg.val = _HQOS_REG(reg.off);
++ //printk("read reg off:%x val:%x\n", reg.off, reg.val);
++ copy_to_user(ifr->ifr_data, &reg, sizeof(reg));
++ break;
++ case RAETH_QDMA_REG_WRITE:
++ copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
++ if (reg.off > REG_HQOS_MAX) {
++ ret = -EINVAL;
++ break;
++ }
++ _HQOS_REG(reg.off) = reg.val;
++ //printk("write reg off:%x val:%x\n", reg.off, reg.val);
++ break;
++#if 0
++ case RAETH_QDMA_READ_CPU_CLK:
++ copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
++ reg.val = get_surfboard_sysclk();
++ //printk("read reg off:%x val:%x\n", reg.off, reg.val);
++ copy_to_user(ifr->ifr_data, &reg, sizeof(reg));
++ break;
++#endif
++ case RAETH_QDMA_QUEUE_MAPPING:
++ copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
++ if((reg.off&0x100) == 0x100){
++ lan_wan_separate = 1;
++ reg.off &= 0xff;
++ }else{
++ lan_wan_separate = 0;
++ }
++ M2Q_table[reg.off] = reg.val;
++ break;
++#if defined(CONFIG_HW_SFQ)
++ case RAETH_QDMA_SFQ_WEB_ENABLE:
++ copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
++ if((reg.val) == 0x1){
++ web_sfq_enable = 1;
++
++ }else{
++ web_sfq_enable = 0;
++ }
++ break;
++#endif
++
++
++#endif
++ case RAETH_MII_READ:
++ copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
++ mii_mgr_read(mii.phy_id, mii.reg_num, &mii.val_out);
++ //printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_out);
++ copy_to_user(ifr->ifr_data, &mii, sizeof(mii));
++ break;
++
++ case RAETH_MII_WRITE:
++ copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
++ //printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_in);
++ mii_mgr_write(mii.phy_id, mii.reg_num, mii.val_in);
++ break;
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_ARCH_MT7623)
++ case RAETH_MII_READ_CL45:
++ copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
++ //mii_mgr_cl45_set_address(mii.port_num, mii.dev_addr, mii.reg_addr);
++ mii_mgr_read_cl45(mii.port_num, mii.dev_addr, mii.reg_addr, &mii.val_out);
++ copy_to_user(ifr->ifr_data, &mii, sizeof(mii));
++ break;
++ case RAETH_MII_WRITE_CL45:
++ copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
++ //mii_mgr_cl45_set_address(mii.port_num, mii.dev_addr, mii.reg_addr);
++ mii_mgr_write_cl45(mii.port_num, mii.dev_addr, mii.reg_addr, mii.val_in);
++ break;
++#endif
++
++#if defined(CONFIG_RT_3052_ESW)
++#define _ESW_REG(x) (*((volatile u32 *)(RALINK_ETH_SW_BASE + x)))
++ case RAETH_ESW_REG_READ:
++ copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
++ if (reg.off > REG_ESW_MAX) {
++ ret = -EINVAL;
++ break;
++ }
++ reg.val = _ESW_REG(reg.off);
++ //printk("read reg off:%x val:%x\n", reg.off, reg.val);
++ copy_to_user(ifr->ifr_data, &reg, sizeof(reg));
++ break;
++ case RAETH_ESW_REG_WRITE:
++ copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
++ if (reg.off > REG_ESW_MAX) {
++ ret = -EINVAL;
++ break;
++ }
++ _ESW_REG(reg.off) = reg.val;
++ //printk("write reg off:%x val:%x\n", reg.off, reg.val);
++ break;
++ case RAETH_ESW_PHY_DUMP:
++ copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350)
++ if (reg.val ==32 ) {//dump all phy register
++ /* Global Register 0~31
++ * Local Register 0~31
++ */
++ dump_phy_reg(0, 0, 31, 0); //dump global register
++ for(offset=0;offset<5;offset++) {
++ dump_phy_reg(offset, 0, 31, 1); //dump local register
++ }
++ } else {
++ dump_phy_reg(reg.val, 0, 31, 0); //dump global register
++ dump_phy_reg(reg.val, 0, 31, 1); //dump local register
++ }
++#else
++ /* SPEC defined Register 0~15
++ * Global Register 16~31 for each page
++ * Local Register 16~31 for each page
++ */
++ printk("SPEC defined Register");
++ if (reg.val ==32 ) {//dump all phy register
++ int i = 0;
++ for(i=0; i<5; i++){
++ printk("\n[Port %d]===============",i);
++ for(offset=0;offset<16;offset++) {
++ if(offset%8==0) {
++ printk("\n");
++ }
++ mii_mgr_read(i,offset, &value);
++ printk("%02d: %04X ",offset, value);
++ }
++ }
++ }
++ else{
++ printk("\n[Port %d]===============",reg.val);
++ for(offset=0;offset<16;offset++) {
++ if(offset%8==0) {
++ printk("\n");
++ }
++ mii_mgr_read(reg.val,offset, &value);
++ printk("%02d: %04X ",offset, value);
++ }
++ }
++
++#if defined (CONFIG_RALINK_MT7628)
++ for(offset=0;offset<7;offset++) { //global register page 0~6
++#else
++ for(offset=0;offset<5;offset++) { //global register page 0~4
++#endif
++ if(reg.val == 32) //dump all phy register
++ dump_phy_reg(0, 16, 31, 0, offset);
++ else
++ dump_phy_reg(reg.val, 16, 31, 0, offset);
++ }
++
++ if (reg.val == 32) {//dump all phy register
++#if !defined (CONFIG_RAETH_HAS_PORT4)
++ for(offset=0;offset<5;offset++) { //local register port 0-port4
++#else
++ for(offset=0;offset<4;offset++) { //local register port 0-port3
++#endif
++ dump_phy_reg(offset, 16, 31, 1, 0); //dump local page 0
++ dump_phy_reg(offset, 16, 31, 1, 1); //dump local page 1
++ dump_phy_reg(offset, 16, 31, 1, 2); //dump local page 2
++ dump_phy_reg(offset, 16, 31, 1, 3); //dump local page 3
++ }
++ }else {
++ dump_phy_reg(reg.val, 16, 31, 1, 0); //dump local page 0
++ dump_phy_reg(reg.val, 16, 31, 1, 1); //dump local page 1
++ dump_phy_reg(reg.val, 16, 31, 1, 2); //dump local page 2
++ dump_phy_reg(reg.val, 16, 31, 1, 3); //dump local page 3
++ }
++#endif
++ break;
++
++#if defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++#define _ESW_REG(x) (*((volatile u32 *)(RALINK_ETH_SW_BASE + x)))
++ case RAETH_ESW_INGRESS_RATE:
++ copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit));
++ offset = 0x11c + (4 * (ratelimit.port / 2));
++ value = _ESW_REG(offset);
++
++ if((ratelimit.port % 2) == 0)
++ {
++ value &= 0xffff0000;
++ if(ratelimit.on_off == 1)
++ {
++ value |= (ratelimit.on_off << 14);
++ value |= (0x07 << 10);
++ value |= ratelimit.bw;
++ }
++ }
++ else if((ratelimit.port % 2) == 1)
++ {
++ value &= 0x0000ffff;
++ if(ratelimit.on_off == 1)
++ {
++ value |= (ratelimit.on_off << 30);
++ value |= (0x07 << 26);
++ value |= (ratelimit.bw << 16);
++ }
++ }
++ printk("offset = 0x%4x value=0x%x\n\r", offset, value);
++
++ _ESW_REG(offset) = value;
++ break;
++
++ case RAETH_ESW_EGRESS_RATE:
++ copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit));
++ offset = 0x140 + (4 * (ratelimit.port / 2));
++ value = _ESW_REG(offset);
++
++ if((ratelimit.port % 2) == 0)
++ {
++ value &= 0xffff0000;
++ if(ratelimit.on_off == 1)
++ {
++ value |= (ratelimit.on_off << 12);
++ value |= (0x03 << 10);
++ value |= ratelimit.bw;
++ }
++ }
++ else if((ratelimit.port % 2) == 1)
++ {
++ value &= 0x0000ffff;
++ if(ratelimit.on_off == 1)
++ {
++ value |= (ratelimit.on_off << 28);
++ value |= (0x03 << 26);
++ value |= (ratelimit.bw << 16);
++ }
++ }
++ printk("offset = 0x%4x value=0x%x\n\r", offset, value);
++ _ESW_REG(offset) = value;
++ break;
++#elif defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++ defined(CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#define _ESW_REG(x) (*((volatile u32 *)(RALINK_ETH_SW_BASE + x)))
++ case RAETH_ESW_INGRESS_RATE:
++ copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit));
++#if defined(CONFIG_RALINK_RT6855A) || defined(CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++ offset = 0x1800 + (0x100 * ratelimit.port);
++#else
++ offset = 0x1080 + (0x100 * ratelimit.port);
++#endif
++ value = _ESW_REG(offset);
++
++ value &= 0xffff0000;
++ if(ratelimit.on_off == 1)
++ {
++ value |= (ratelimit.on_off << 15);
++ if (ratelimit.bw < 100)
++ {
++ value |= (0x0 << 8);
++ value |= ratelimit.bw;
++ }else if(ratelimit.bw < 1000)
++ {
++ value |= (0x1 << 8);
++ value |= ratelimit.bw/10;
++ }else if(ratelimit.bw < 10000)
++ {
++ value |= (0x2 << 8);
++ value |= ratelimit.bw/100;
++ }else if(ratelimit.bw < 100000)
++ {
++ value |= (0x3 << 8);
++ value |= ratelimit.bw/1000;
++ }else
++ {
++ value |= (0x4 << 8);
++ value |= ratelimit.bw/10000;
++ }
++ }
++ printk("offset = 0x%4x value=0x%x\n\r", offset, value);
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++ mii_mgr_write(0x1f, offset, value);
++#else
++ _ESW_REG(offset) = value;
++#endif
++ break;
++
++ case RAETH_ESW_EGRESS_RATE:
++ copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit));
++ offset = 0x1040 + (0x100 * ratelimit.port);
++ value = _ESW_REG(offset);
++
++ value &= 0xffff0000;
++ if(ratelimit.on_off == 1)
++ {
++ value |= (ratelimit.on_off << 15);
++ if (ratelimit.bw < 100)
++ {
++ value |= (0x0 << 8);
++ value |= ratelimit.bw;
++ }else if(ratelimit.bw < 1000)
++ {
++ value |= (0x1 << 8);
++ value |= ratelimit.bw/10;
++ }else if(ratelimit.bw < 10000)
++ {
++ value |= (0x2 << 8);
++ value |= ratelimit.bw/100;
++ }else if(ratelimit.bw < 100000)
++ {
++ value |= (0x3 << 8);
++ value |= ratelimit.bw/1000;
++ }else
++ {
++ value |= (0x4 << 8);
++ value |= ratelimit.bw/10000;
++ }
++ }
++ printk("offset = 0x%4x value=0x%x\n\r", offset, value);
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++ mii_mgr_write(0x1f, offset, value);
++#else
++ _ESW_REG(offset) = value;
++#endif
++ break;
++#endif
++#endif // CONFIG_RT_3052_ESW
++ default:
++ ret = -EOPNOTSUPP;
++ break;
++
++ }
++
++ spin_unlock_irq(&ei_local->page_lock);
++ return ret;
++}
++
++/*
++ * Set new MTU size
++ * Change the mtu of Raeth Ethernet Device
++ */
++static int ei_change_mtu(struct net_device *dev, int new_mtu)
++{
++ END_DEVICE *ei_local = netdev_priv(dev); // get priv ei_local pointer from net_dev structure
++
++ if ( ei_local == NULL ) {
++ printk(KERN_EMERG "%s: ei_change_mtu passed a non-existent private pointer from net_dev!\n", dev->name);
++ return -ENXIO;
++ }
++
++
++ if ( (new_mtu > 4096) || (new_mtu < 64)) {
++ return -EINVAL;
++ }
++
++#ifndef CONFIG_RAETH_JUMBOFRAME
++ if ( new_mtu > 1500 ) {
++ return -EINVAL;
++ }
++#endif
++
++ dev->mtu = new_mtu;
++
++ return 0;
++}
++
++#ifdef CONFIG_RAETH_HW_VLAN_RX
++static void ei_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
++{
++ END_DEVICE *ei_local = netdev_priv(dev);
++
++ ei_local->vlgrp = grp;
++
++ /* enable HW VLAN RX */
++ sysRegWrite(CDMP_EG_CTRL, 1);
++
++}
++#endif
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++static const struct net_device_ops ei_netdev_ops = {
++ .ndo_init = rather_probe,
++ .ndo_open = ei_open,
++ .ndo_stop = ei_close,
++ .ndo_start_xmit = ei_start_xmit_fake,
++ .ndo_get_stats = ra_get_stats,
++ .ndo_set_mac_address = eth_mac_addr,
++ .ndo_change_mtu = ei_change_mtu,
++ .ndo_do_ioctl = ei_ioctl,
++ .ndo_validate_addr = eth_validate_addr,
++#ifdef CONFIG_RAETH_HW_VLAN_RX
++ .ndo_vlan_rx_register = ei_vlan_rx_register,
++#endif
++#ifdef CONFIG_NET_POLL_CONTROLLER
++ .ndo_poll_controller = raeth_clean,
++#endif
++// .ndo_tx_timeout = ei_tx_timeout,
++};
++#endif
++
++void ra2880_setup_dev_fptable(struct net_device *dev)
++{
++ RAETH_PRINT(__FUNCTION__ "is called!\n");
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ dev->netdev_ops = &ei_netdev_ops;
++#else
++ dev->open = ei_open;
++ dev->stop = ei_close;
++ dev->hard_start_xmit = ei_start_xmit_fake;
++ dev->get_stats = ra_get_stats;
++ dev->set_mac_address = ei_set_mac_addr;
++ dev->change_mtu = ei_change_mtu;
++ dev->mtu = 1500;
++ dev->do_ioctl = ei_ioctl;
++// dev->tx_timeout = ei_tx_timeout;
++
++#ifdef CONFIG_RAETH_NAPI
++ dev->poll = &raeth_clean;
++#if defined (CONFIG_RAETH_ROUTER)
++ dev->weight = 32;
++#elif defined (CONFIG_RT_3052_ESW)
++ dev->weight = 32;
++#else
++ dev->weight = 128;
++#endif
++#endif
++#endif
++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
++ dev->ethtool_ops = &ra_ethtool_ops;
++#endif
++#define TX_TIMEOUT (5*HZ)
++ dev->watchdog_timeo = TX_TIMEOUT;
++
++}
++
++/* reset frame engine */
++void fe_reset(void)
++{
++#if defined (CONFIG_RALINK_RT6855A)
++ /* FIXME */
++#else
++ u32 val;
++
++ //val = *(volatile u32 *)(0x1b000000);
++ //printk("0x1b000000 is 0x%x\n", val);
++ //val = sysRegRead(0xFB110100);
++ //val = 0x8000;
++ //sysRegWrite(0xFB110100, val);
++
++
++
++ val = sysRegRead(RSTCTRL);
++
++// RT5350 need to reset ESW and FE at the same to avoid PDMA panic //
++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++ val = val | RALINK_FE_RST | RALINK_ESW_RST ;
++#else
++ val = val | RALINK_FE_RST;
++#endif
++ sysRegWrite(RSTCTRL, val);
++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7628)
++ val = val & ~(RALINK_FE_RST | RALINK_ESW_RST);
++#else
++ val = val & ~(RALINK_FE_RST);
++#endif
++
++ sysRegWrite(RSTCTRL, val);
++#endif
++}
++
++/* set TRGMII */
++#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC)
++void trgmii_set_7621(void)
++{
++ u32 val = 0;
++ u32 val_0 = 0;
++
++ val = sysRegRead(RSTCTRL);
++// MT7621 need to reset GMAC and FE first //
++ val = val | RALINK_FE_RST | RALINK_ETH_RST ;
++ sysRegWrite(RSTCTRL, val);
++
++//set TRGMII clock//
++ val_0 = sysRegRead(CLK_CFG_0);
++ val_0 &= 0xffffff9f;
++ val_0 |= (0x1 << 5);
++ sysRegWrite(CLK_CFG_0, val_0);
++ mdelay(1);
++ val_0 = sysRegRead(CLK_CFG_0);
++ printk("set CLK_CFG_0 = 0x%x!!!!!!!!!!!!!!!!!!1\n",val_0);
++ val = val & ~(RALINK_FE_RST | RALINK_ETH_RST);
++ sysRegWrite(RSTCTRL, val);
++}
++
++void trgmii_set_7530(void)
++{
++// set MT7530 //
++#if 0
++
++ mii_mgr_write(31, 103, 0x0020);
++
++
++ //disable EEE
++ mii_mgr_write(0, 0x16, 0);
++ mii_mgr_write(1, 0x16, 0);
++ mii_mgr_write(2, 0x16, 0);
++ mii_mgr_write(3, 0x16, 0);
++ mii_mgr_write(4, 0x16, 0);
++
++
++ //PLL reset for E2
++ mii_mgr_write(31, 104, 0x0608);
++ mii_mgr_write(31, 104, 0x2608);
++
++ mii_mgr_write(31, 0x7808, 0x0);
++ mdelay(1);
++ mii_mgr_write(31, 0x7804, 0x01017e8f);
++ mdelay(1);
++ mii_mgr_write(31, 0x7808, 0x1);
++ mdelay(1);
++
++#endif
++#if 1
++ //CL45 command
++ //PLL to 150Mhz
++ mii_mgr_write(0, 13, 0x1f);
++ mii_mgr_write(0, 14, 0x404);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_read(31, 0x7800, &regValue);
++ regValue = (regValue >> 9) & 0x3;
++ if(regValue == 0x3) { //25Mhz Xtal
++ mii_mgr_write(0, 14, 0x0A00);//25Mhz XTAL for 150Mhz CLK
++ } else if(regValue == 0x2) { //40Mhz
++ mii_mgr_write(0, 14, 0x0780);//40Mhz XTAL for 150Mhz CLK
++ }
++ //mii_mgr_write(0, 14, 0x0C00);//ori
++ mdelay(1);
++
++ mii_mgr_write(0, 13, 0x1f);
++ mii_mgr_write(0, 14, 0x409);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0x57);
++ mdelay(1);
++
++ mii_mgr_write(0, 13, 0x1f);
++ mii_mgr_write(0, 14, 0x40a);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0x57);
++
++//PLL BIAS en
++ mii_mgr_write(0, 13, 0x1f);
++ mii_mgr_write(0, 14, 0x403);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0x1800);
++ mdelay(1);
++
++//BIAS LPF en
++ mii_mgr_write(0, 13, 0x1f);
++ mii_mgr_write(0, 14, 0x403);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0x1c00);
++
++//sys PLL en
++ mii_mgr_write(0, 13, 0x1f);
++ mii_mgr_write(0, 14, 0x401);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0xc020);
++
++//LCDDDS PWDS
++ mii_mgr_write(0, 13, 0x1f);
++ mii_mgr_write(0, 14, 0x406);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0xa030);
++ mdelay(1);
++
++//GSW_2X_CLK
++ mii_mgr_write(0, 13, 0x1f);
++ mii_mgr_write(0, 14, 0x410);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0x0003);
++
++//enable P6
++ mii_mgr_write(31, 0x3600, 0x5e33b);
++
++//enable TRGMII
++ mii_mgr_write(31, 0x7830, 0x1);
++#endif
++
++}
++#endif
++
++void ei_reset_task(struct work_struct *work)
++{
++ struct net_device *dev = dev_raether;
++
++ ei_close(dev);
++ ei_open(dev);
++
++ return;
++}
++
++void ei_tx_timeout(struct net_device *dev)
++{
++ END_DEVICE *ei_local = netdev_priv(dev);
++
++ schedule_work(&ei_local->reset_task);
++}
++
++void setup_statistics(END_DEVICE* ei_local)
++{
++ ei_local->stat.tx_packets = 0;
++ ei_local->stat.tx_bytes = 0;
++ ei_local->stat.tx_dropped = 0;
++ ei_local->stat.tx_errors = 0;
++ ei_local->stat.tx_aborted_errors= 0;
++ ei_local->stat.tx_carrier_errors= 0;
++ ei_local->stat.tx_fifo_errors = 0;
++ ei_local->stat.tx_heartbeat_errors = 0;
++ ei_local->stat.tx_window_errors = 0;
++
++ ei_local->stat.rx_packets = 0;
++ ei_local->stat.rx_bytes = 0;
++ ei_local->stat.rx_dropped = 0;
++ ei_local->stat.rx_errors = 0;
++ ei_local->stat.rx_length_errors = 0;
++ ei_local->stat.rx_over_errors = 0;
++ ei_local->stat.rx_crc_errors = 0;
++ ei_local->stat.rx_frame_errors = 0;
++ ei_local->stat.rx_fifo_errors = 0;
++ ei_local->stat.rx_missed_errors = 0;
++
++ ei_local->stat.collisions = 0;
++#if defined (CONFIG_RAETH_QOS)
++ ei_local->tx3_full = 0;
++ ei_local->tx2_full = 0;
++ ei_local->tx1_full = 0;
++ ei_local->tx0_full = 0;
++#else
++ ei_local->tx_full = 0;
++#endif
++#ifdef CONFIG_RAETH_NAPI
++ atomic_set(&ei_local->irq_sem, 1);
++#endif
++
++}
++
++/**
++ * rather_probe - pick up ethernet port at boot time
++ * @dev: network device to probe
++ *
++ * This routine probe the ethernet port at boot time.
++ *
++ *
++ */
++
++int __init rather_probe(struct net_device *dev)
++{
++ int i;
++ END_DEVICE *ei_local = netdev_priv(dev);
++ struct sockaddr addr;
++ unsigned char zero1[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
++ unsigned char zero2[6]={0x00,0x00,0x00,0x00,0x00,0x00};
++
++ fe_reset();
++
++ //Get mac0 address from flash
++#ifdef RA_MTD_RW_BY_NUM
++ i = ra_mtd_read(2, GMAC0_OFFSET, 6, addr.sa_data);
++#else
++ i = ra_mtd_read_nm("Factory", GMAC0_OFFSET, 6, addr.sa_data);
++#endif
++ //If reading mtd failed or mac0 is empty, generate a mac address
++ if (i < 0 || ((memcmp(addr.sa_data, zero1, 6) == 0) || (addr.sa_data[0] & 0x1)) ||
++ (memcmp(addr.sa_data, zero2, 6) == 0)) {
++ unsigned char mac_addr01234[5] = {0x00, 0x0C, 0x43, 0x28, 0x80};
++ // net_srandom(jiffies);
++ memcpy(addr.sa_data, mac_addr01234, 5);
++ // addr.sa_data[5] = net_random()&0xFF;
++ }
++
++#ifdef CONFIG_RAETH_NAPI
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ netif_napi_add(dev, &ei_local->napi, raeth_clean, 128);
++#endif
++#endif
++ ei_set_mac_addr(dev, &addr);
++ spin_lock_init(&ei_local->page_lock);
++ ether_setup(dev);
++
++#ifdef CONFIG_RAETH_LRO
++ ei_local->lro_mgr.dev = dev;
++ memset(&ei_local->lro_mgr.stats, 0, sizeof(ei_local->lro_mgr.stats));
++ ei_local->lro_mgr.features = LRO_F_NAPI;
++ ei_local->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
++ ei_local->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
++ ei_local->lro_mgr.max_desc = ARRAY_SIZE(ei_local->lro_arr);
++ ei_local->lro_mgr.max_aggr = 64;
++ ei_local->lro_mgr.frag_align_pad = 0;
++ ei_local->lro_mgr.lro_arr = ei_local->lro_arr;
++ ei_local->lro_mgr.get_skb_header = rt_get_skb_header;
++#endif
++
++ setup_statistics(ei_local);
++
++ return 0;
++}
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++int VirtualIF_ioctl(struct net_device * net_dev,
++ struct ifreq * ifr, int cmd)
++{
++ ra_mii_ioctl_data mii;
++
++ switch (cmd) {
++ case RAETH_MII_READ:
++ copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
++ mii_mgr_read(mii.phy_id, mii.reg_num, &mii.val_out);
++ //printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_out);
++ copy_to_user(ifr->ifr_data, &mii, sizeof(mii));
++ break;
++
++ case RAETH_MII_WRITE:
++ copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
++ //printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_in);
++ mii_mgr_write(mii.phy_id, mii.reg_num, mii.val_in);
++ break;
++ default:
++ return -EOPNOTSUPP;
++ }
++
++ return 0;
++}
++
++struct net_device_stats *VirtualIF_get_stats(struct net_device *dev)
++{
++ PSEUDO_ADAPTER *pAd = netdev_priv(dev);
++ return &pAd->stat;
++}
++
++int VirtualIF_open(struct net_device * dev)
++{
++ PSEUDO_ADAPTER *pPesueoAd = netdev_priv(dev);
++
++ printk("%s: ===> VirtualIF_open\n", dev->name);
++
++#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN) || defined (CONFIG_GE_RGMII_INTERNAL_P4_AN)
++ *((volatile u32 *)(FE_INT_ENABLE2)) |= (1<<25); //enable GE2 link change intr for MT7530 delay setting
++#endif
++
++ netif_start_queue(pPesueoAd->PseudoDev);
++
++ return 0;
++}
++
++int VirtualIF_close(struct net_device * dev)
++{
++ PSEUDO_ADAPTER *pPesueoAd = netdev_priv(dev);
++
++ printk("%s: ===> VirtualIF_close\n", dev->name);
++
++ netif_stop_queue(pPesueoAd->PseudoDev);
++
++ return 0;
++}
++
++int VirtualIFSendPackets(struct sk_buff * pSkb,
++ struct net_device * dev)
++{
++ PSEUDO_ADAPTER *pPesueoAd = netdev_priv(dev);
++ END_DEVICE *ei_local __maybe_unused;
++
++
++ //printk("VirtualIFSendPackets --->\n");
++
++ ei_local = netdev_priv(dev);
++ if (!(pPesueoAd->RaethDev->flags & IFF_UP)) {
++ dev_kfree_skb_any(pSkb);
++ return 0;
++ }
++ //pSkb->cb[40]=0x5a;
++ pSkb->dev = pPesueoAd->RaethDev;
++ ei_start_xmit(pSkb, pPesueoAd->RaethDev, 2);
++ return 0;
++}
++
++void virtif_setup_statistics(PSEUDO_ADAPTER* pAd)
++{
++ pAd->stat.tx_packets = 0;
++ pAd->stat.tx_bytes = 0;
++ pAd->stat.tx_dropped = 0;
++ pAd->stat.tx_errors = 0;
++ pAd->stat.tx_aborted_errors= 0;
++ pAd->stat.tx_carrier_errors= 0;
++ pAd->stat.tx_fifo_errors = 0;
++ pAd->stat.tx_heartbeat_errors = 0;
++ pAd->stat.tx_window_errors = 0;
++
++ pAd->stat.rx_packets = 0;
++ pAd->stat.rx_bytes = 0;
++ pAd->stat.rx_dropped = 0;
++ pAd->stat.rx_errors = 0;
++ pAd->stat.rx_length_errors = 0;
++ pAd->stat.rx_over_errors = 0;
++ pAd->stat.rx_crc_errors = 0;
++ pAd->stat.rx_frame_errors = 0;
++ pAd->stat.rx_fifo_errors = 0;
++ pAd->stat.rx_missed_errors = 0;
++
++ pAd->stat.collisions = 0;
++}
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++static const struct net_device_ops VirtualIF_netdev_ops = {
++ .ndo_open = VirtualIF_open,
++ .ndo_stop = VirtualIF_close,
++ .ndo_start_xmit = VirtualIFSendPackets,
++ .ndo_get_stats = VirtualIF_get_stats,
++ .ndo_set_mac_address = ei_set_mac2_addr,
++ .ndo_change_mtu = ei_change_mtu,
++ .ndo_do_ioctl = VirtualIF_ioctl,
++ .ndo_validate_addr = eth_validate_addr,
++};
++#endif
++// Register pseudo interface
++void RAETH_Init_PSEUDO(pEND_DEVICE pAd, struct net_device *net_dev)
++{
++ int index;
++ struct net_device *dev;
++ PSEUDO_ADAPTER *pPseudoAd;
++ int i = 0;
++ struct sockaddr addr;
++ unsigned char zero1[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
++ unsigned char zero2[6]={0x00,0x00,0x00,0x00,0x00,0x00};
++
++ for (index = 0; index < MAX_PSEUDO_ENTRY; index++) {
++
++ dev = alloc_etherdev(sizeof(PSEUDO_ADAPTER));
++ if (NULL == dev)
++ {
++ printk(" alloc_etherdev for PSEUDO_ADAPTER failed.\n");
++ return;
++ }
++ strcpy(dev->name, DEV2_NAME);
++
++ //Get mac2 address from flash
++#ifdef RA_MTD_RW_BY_NUM
++ i = ra_mtd_read(2, GMAC2_OFFSET, 6, addr.sa_data);
++#else
++ i = ra_mtd_read_nm("Factory", GMAC2_OFFSET, 6, addr.sa_data);
++#endif
++
++ //If reading mtd failed or mac0 is empty, generate a mac address
++ if (i < 0 || ((memcmp(addr.sa_data, zero1, 6) == 0) || (addr.sa_data[0] & 0x1)) ||
++ (memcmp(addr.sa_data, zero2, 6) == 0)) {
++ unsigned char mac_addr01234[5] = {0x00, 0x0C, 0x43, 0x28, 0x80};
++ // net_srandom(jiffies);
++ memcpy(addr.sa_data, mac_addr01234, 5);
++ // addr.sa_data[5] = net_random()&0xFF;
++ }
++
++ ei_set_mac2_addr(dev, &addr);
++ ether_setup(dev);
++ pPseudoAd = netdev_priv(dev);
++
++ pPseudoAd->PseudoDev = dev;
++ pPseudoAd->RaethDev = net_dev;
++ virtif_setup_statistics(pPseudoAd);
++ pAd->PseudoDev = dev;
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ dev->netdev_ops = &VirtualIF_netdev_ops;
++#else
++ dev->hard_start_xmit = VirtualIFSendPackets;
++ dev->stop = VirtualIF_close;
++ dev->open = VirtualIF_open;
++ dev->do_ioctl = VirtualIF_ioctl;
++ dev->set_mac_address = ei_set_mac2_addr;
++ dev->get_stats = VirtualIF_get_stats;
++ dev->change_mtu = ei_change_mtu;
++ dev->mtu = 1500;
++#endif
++
++#if defined (CONFIG_RAETH_HW_LRO)
++ dev->features |= NETIF_F_HW_CSUM;
++#else
++ dev->features |= NETIF_F_IP_CSUM; /* Can checksum TCP/UDP over IPv4 */
++#endif /* CONFIG_RAETH_HW_LRO */
++
++#if defined(CONFIG_RALINK_MT7620)
++#if defined (CONFIG_RAETH_TSO)
++ if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
++ dev->features |= NETIF_F_SG;
++ dev->features |= NETIF_F_TSO;
++ }
++#endif // CONFIG_RAETH_TSO //
++
++#if defined (CONFIG_RAETH_TSOV6)
++ if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
++ dev->features |= NETIF_F_TSO6;
++ dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */
++ }
++#endif
++#else
++#if defined (CONFIG_RAETH_TSO)
++ dev->features |= NETIF_F_SG;
++ dev->features |= NETIF_F_TSO;
++#endif // CONFIG_RAETH_TSO //
++
++#if defined (CONFIG_RAETH_TSOV6)
++ dev->features |= NETIF_F_TSO6;
++ dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */
++#endif
++#endif // CONFIG_RALINK_MT7620 //
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
++ dev->vlan_features = dev->features;
++#endif
++
++
++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
++ dev->ethtool_ops = &ra_virt_ethtool_ops;
++ // init mii structure
++ pPseudoAd->mii_info.dev = dev;
++ pPseudoAd->mii_info.mdio_read = mdio_virt_read;
++ pPseudoAd->mii_info.mdio_write = mdio_virt_write;
++ pPseudoAd->mii_info.phy_id_mask = 0x1f;
++ pPseudoAd->mii_info.reg_num_mask = 0x1f;
++ pPseudoAd->mii_info.phy_id = 0x1e;
++ pPseudoAd->mii_info.supports_gmii = mii_check_gmii_support(&pPseudoAd->mii_info);
++#endif
++
++ // Register this device
++ register_netdevice(dev);
++ }
++}
++#endif
++
++/**
++ * ei_open - Open/Initialize the ethernet port.
++ * @dev: network device to initialize
++ *
++ * This routine goes all-out, setting everything
++ * up a new at each open, even though many of these registers should only need to be set once at boot.
++ */
++int ei_open(struct net_device *dev)
++{
++ int i, err;
++#if !defined (CONFIG_MT7623_FPGA)
++ unsigned long flags;
++#endif
++ END_DEVICE *ei_local;
++
++#ifdef CONFIG_RAETH_LRO
++ const char *lan_ip_tmp;
++#ifdef CONFIG_DUAL_IMAGE
++#define RT2860_NVRAM 1
++#else
++#define RT2860_NVRAM 0
++#endif
++#endif // CONFIG_RAETH_LRO //
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
++ if (!try_module_get(THIS_MODULE))
++ {
++ printk("%s: Cannot reserve module\n", __FUNCTION__);
++ return -1;
++ }
++#else
++ MOD_INC_USE_COUNT;
++#endif
++
++ printk("Raeth %s (",RAETH_VERSION);
++#if defined (CONFIG_RAETH_NAPI)
++ printk("NAPI\n");
++#elif defined (CONFIG_RA_NETWORK_TASKLET_BH)
++ printk("Tasklet");
++#elif defined (CONFIG_RA_NETWORK_WORKQUEUE_BH)
++ printk("Workqueue");
++#endif
++
++#if defined (CONFIG_RAETH_SKB_RECYCLE_2K)
++ printk(",SkbRecycle");
++#endif
++ printk(")\n");
++
++
++ ei_local = netdev_priv(dev); // get device pointer from System
++ // unsigned int flags;
++
++ if (ei_local == NULL)
++ {
++ printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name);
++ return -ENXIO;
++ }
++
++ /* receiving packet buffer allocation - NUM_RX_DESC x MAX_RX_LENGTH */
++ for ( i = 0; i < NUM_RX_DESC; i++)
++ {
++#if defined (CONFIG_RAETH_SKB_RECYCLE_2K)
++ ei_local->netrx0_skbuf[i] = skbmgr_dev_alloc_skb2k();
++#else
++ ei_local->netrx0_skbuf[i] = dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN);
++#endif
++ if (ei_local->netrx0_skbuf[i] == NULL ) {
++ printk("rx skbuff buffer allocation failed!");
++ } else {
++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++ skb_reserve(ei_local->netrx0_skbuf[i], NET_IP_ALIGN);
++#endif
++ }
++
++
++#if defined (CONFIG_RAETH_HW_LRO)
++ ei_local->netrx3_skbuf[i] = dev_alloc_skb(MAX_LRO_RX_LENGTH + NET_IP_ALIGN);
++ if (ei_local->netrx3_skbuf[i] == NULL ) {
++ printk("rx3 skbuff buffer allocation failed!");
++ } else {
++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++ skb_reserve(ei_local->netrx3_skbuf[i], NET_IP_ALIGN);
++#endif
++ }
++ ei_local->netrx2_skbuf[i] = dev_alloc_skb(MAX_LRO_RX_LENGTH + NET_IP_ALIGN);
++ if (ei_local->netrx2_skbuf[i] == NULL ) {
++ printk("rx2 skbuff buffer allocation failed!");
++ } else {
++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++ skb_reserve(ei_local->netrx2_skbuf[i], NET_IP_ALIGN);
++#endif
++ }
++ ei_local->netrx1_skbuf[i] = dev_alloc_skb(MAX_LRO_RX_LENGTH + NET_IP_ALIGN);
++ if (ei_local->netrx1_skbuf[i] == NULL ) {
++ printk("rx1 skbuff buffer allocation failed!");
++ } else {
++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++ skb_reserve(ei_local->netrx1_skbuf[i], NET_IP_ALIGN);
++#endif
++ }
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++#if defined(CONFIG_ARCH_MT7623)
++ ei_local->netrx3_skbuf[i] = dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN);
++ if (ei_local->netrx3_skbuf[i] == NULL ) {
++ printk("rx3 skbuff buffer allocation failed!");
++ } else {
++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++ skb_reserve(ei_local->netrx3_skbuf[i], NET_IP_ALIGN);
++#endif
++ }
++ ei_local->netrx2_skbuf[i] = dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN);
++ if (ei_local->netrx2_skbuf[i] == NULL ) {
++ printk("rx2 skbuff buffer allocation failed!");
++ } else {
++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++ skb_reserve(ei_local->netrx2_skbuf[i], NET_IP_ALIGN);
++#endif
++ }
++#endif /* CONFIG_ARCH_MT7623 */
++ ei_local->netrx1_skbuf[i] = dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN);
++ if (ei_local->netrx1_skbuf[i] == NULL ) {
++ printk("rx1 skbuff buffer allocation failed!");
++ } else {
++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++ skb_reserve(ei_local->netrx1_skbuf[i], NET_IP_ALIGN);
++#endif
++ }
++#endif
++ }
++#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC)
++ trgmii_set_7621(); //reset FE/GMAC in this function
++#endif
++
++ fe_dma_init(dev);
++
++#if defined (CONFIG_RAETH_HW_LRO)
++ fe_hw_lro_init(dev);
++#endif /* CONFIG_RAETH_HW_LRO */
++
++ fe_sw_init(); //initialize fe and switch register
++#if defined (CONFIG_MIPS)
++ err = request_irq( dev->irq, ei_interrupt, IRQF_DISABLED, dev->name, dev); // try to fix irq in open
++#else
++ err = request_irq(dev->irq, ei_interrupt, /*IRQF_TRIGGER_LOW*/ 0, dev->name, dev); // try to fix irq in open
++#endif
++ if (err)
++ return err;
++
++ if ( dev->dev_addr != NULL) {
++ ra2880MacAddressSet((void *)(dev->dev_addr));
++ } else {
++ printk("dev->dev_addr is empty !\n");
++ }
++/*TODO: MT7623 MCM INT */
++#if defined (CONFIG_RT_3052_ESW) && !defined(CONFIG_ARCH_MT7623)
++ err = request_irq(SURFBOARDINT_ESW, esw_interrupt, IRQF_DISABLED, "Ralink_ESW", dev);
++ if (err)
++ return err;
++ INIT_WORK(&ei_local->kill_sig_wq, kill_sig_workq);
++#if defined (CONFIG_RALINK_MT7621)
++ mii_mgr_write(31, 0x7008, 0x1f); //enable switch link change intr
++
++#else
++ *((volatile u32 *)(RALINK_INTCL_BASE + 0x34)) = (1<<17);
++ *((volatile u32 *)(ESW_IMR)) &= ~(ESW_INT_ALL);
++
++#if defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || \
++ defined (CONFIG_RALINK_MT7620)
++ *((volatile u32 *)(ESW_P0_IntMn)) &= ~(MSK_CNT_INT_ALL);
++ *((volatile u32 *)(ESW_P1_IntMn)) &= ~(MSK_CNT_INT_ALL);
++ *((volatile u32 *)(ESW_P2_IntMn)) &= ~(MSK_CNT_INT_ALL);
++ *((volatile u32 *)(ESW_P3_IntMn)) &= ~(MSK_CNT_INT_ALL);
++ *((volatile u32 *)(ESW_P4_IntMn)) &= ~(MSK_CNT_INT_ALL);
++ *((volatile u32 *)(ESW_P5_IntMn)) &= ~(MSK_CNT_INT_ALL);
++ *((volatile u32 *)(ESW_P6_IntMn)) &= ~(MSK_CNT_INT_ALL);
++#endif
++#if defined(CONFIG_RALINK_MT7620)
++ *((volatile u32 *)(ESW_P7_IntMn)) &= ~(MSK_CNT_INT_ALL);
++#endif
++
++#endif
++#endif // CONFIG_RT_3052_ESW //
++
++/*TODO*/
++#if !defined (CONFIG_MT7623_FPGA)
++ spin_lock_irqsave(&(ei_local->page_lock), flags);
++#endif
++
++
++#ifdef DELAY_INT
++ sysRegWrite(RAETH_DLY_INT_CFG, DELAY_INT_INIT);
++ sysRegWrite(RAETH_FE_INT_ENABLE, RAETH_FE_INT_DLY_INIT);
++ #if defined (CONFIG_RAETH_HW_LRO)
++ sysRegWrite(RAETH_FE_INT_ENABLE, RAETH_FE_INT_DLY_INIT | ALT_RPLC_INT3 | ALT_RPLC_INT2 | ALT_RPLC_INT1);
++ #endif /* CONFIG_RAETH_HW_LRO */
++#else
++ sysRegWrite(RAETH_FE_INT_ENABLE, RAETH_FE_INT_ALL);
++ #if defined (CONFIG_RAETH_HW_LRO)
++ sysRegWrite(RAETH_FE_INT_ENABLE, RAETH_FE_INT_ALL | ALT_RPLC_INT3 | ALT_RPLC_INT2 | ALT_RPLC_INT1);
++ #endif /* CONFIG_RAETH_HW_LRO */
++#endif
++
++#ifdef CONFIG_RAETH_QDMA
++#ifdef DELAY_INT
++ sysRegWrite(QDMA_DELAY_INT, DELAY_INT_INIT);
++ sysRegWrite(QFE_INT_ENABLE, QFE_INT_DLY_INIT);
++#else
++ sysRegWrite(QFE_INT_ENABLE, QFE_INT_ALL);
++
++#endif
++#endif
++
++ INIT_WORK(&ei_local->reset_task, ei_reset_task);
++
++#ifdef WORKQUEUE_BH
++#ifndef CONFIG_RAETH_NAPI
++ INIT_WORK(&ei_local->rx_wq, ei_receive_workq);
++#endif // CONFIG_RAETH_NAPI //
++#else
++#ifndef CONFIG_RAETH_NAPI
++#if defined (TASKLET_WORKQUEUE_SW)
++ working_schedule = init_schedule;
++ INIT_WORK(&ei_local->rx_wq, ei_receive_workq);
++ tasklet_init(&ei_local->rx_tasklet, ei_receive_workq, 0);
++#else
++ tasklet_init(&ei_local->rx_tasklet, ei_receive, 0);
++#endif
++#endif // CONFIG_RAETH_NAPI //
++#endif // WORKQUEUE_BH //
++
++ netif_start_queue(dev);
++
++#ifdef CONFIG_RAETH_NAPI
++ atomic_dec(&ei_local->irq_sem);
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ napi_enable(&ei_local->napi);
++#else
++ netif_poll_enable(dev);
++#endif
++#endif
++//*TODO*/
++#if !defined (CONFIG_MT7623_FPGA)
++ spin_unlock_irqrestore(&(ei_local->page_lock), flags);
++#endif
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++ if(ei_local->PseudoDev == NULL) {
++ RAETH_Init_PSEUDO(ei_local, dev);
++ }
++
++ if(ei_local->PseudoDev == NULL)
++ printk("Open PseudoDev failed.\n");
++ else
++ VirtualIF_open(ei_local->PseudoDev);
++
++#endif
++
++#ifdef CONFIG_RAETH_LRO
++ lan_ip_tmp = nvram_get(RT2860_NVRAM, "lan_ipaddr");
++ str_to_ip(&lan_ip, lan_ip_tmp);
++ lro_para.lan_ip1 = lan_ip = htonl(lan_ip);
++#endif // CONFIG_RAETH_LRO //
++
++#if defined (CONFIG_RAETH_HW_LRO)
++ INIT_WORK(&ei_local->hw_lro_wq, ei_hw_lro_workq);
++#endif /* CONFIG_RAETH_HW_LRO */
++
++ forward_config(dev);
++ return 0;
++}
++
++/**
++ * ei_close - shut down network device
++ * @dev: network device to clear
++ *
++ * This routine shut down network device.
++ *
++ *
++ */
++int ei_close(struct net_device *dev)
++{
++ int i;
++ END_DEVICE *ei_local = netdev_priv(dev); // device pointer
++
++ netif_stop_queue(dev);
++ ra2880stop(ei_local);
++
++ free_irq(dev->irq, dev);
++
++/*TODO: MT7623 MCM INT */
++#if defined (CONFIG_RT_3052_ESW) && !defined(CONFIG_ARCH_MT7623)
++ free_irq(SURFBOARDINT_ESW, dev);
++#endif
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ cancel_work_sync(&ei_local->reset_task);
++#endif
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++ VirtualIF_close(ei_local->PseudoDev);
++#endif
++
++
++#ifdef WORKQUEUE_BH
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ cancel_work_sync(&ei_local->rx_wq);
++#endif
++#else
++#if defined (TASKLET_WORKQUEUE_SW)
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ cancel_work_sync(&ei_local->rx_wq);
++#endif
++#endif
++ tasklet_kill(&ei_local->tx_tasklet);
++ tasklet_kill(&ei_local->rx_tasklet);
++#endif // WORKQUEUE_BH //
++
++#ifdef CONFIG_RAETH_NAPI
++ atomic_inc(&ei_local->irq_sem);
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ napi_disable(&ei_local->napi);
++#else
++ netif_poll_disable(dev);
++#endif
++#endif
++
++
++#if defined (CONFIG_RAETH_HW_LRO)
++ cancel_work_sync(&ei_local->hw_lro_wq);
++#endif /* CONFIG_RAETH_HW_LRO */
++
++ for ( i = 0; i < NUM_RX_DESC; i++)
++ {
++ if (ei_local->netrx0_skbuf[i] != NULL) {
++ dev_kfree_skb(ei_local->netrx0_skbuf[i]);
++ ei_local->netrx0_skbuf[i] = NULL;
++ }
++#if defined (CONFIG_RAETH_HW_LRO)
++ if (ei_local->netrx3_skbuf[i] != NULL) {
++ dev_kfree_skb(ei_local->netrx3_skbuf[i]);
++ ei_local->netrx3_skbuf[i] = NULL;
++ }
++ if (ei_local->netrx2_skbuf[i] != NULL) {
++ dev_kfree_skb(ei_local->netrx2_skbuf[i]);
++ ei_local->netrx2_skbuf[i] = NULL;
++ }
++ if (ei_local->netrx1_skbuf[i] != NULL) {
++ dev_kfree_skb(ei_local->netrx1_skbuf[i]);
++ ei_local->netrx1_skbuf[i] = NULL;
++ }
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++#if defined(CONFIG_ARCH_MT7623)
++ if (ei_local->netrx3_skbuf[i] != NULL) {
++ dev_kfree_skb(ei_local->netrx3_skbuf[i]);
++ ei_local->netrx3_skbuf[i] = NULL;
++ }
++ if (ei_local->netrx2_skbuf[i] != NULL) {
++ dev_kfree_skb(ei_local->netrx2_skbuf[i]);
++ ei_local->netrx2_skbuf[i] = NULL;
++ }
++#endif /* CONFIG_ARCH_MT7623 */
++ if (ei_local->netrx1_skbuf[i] != NULL) {
++ dev_kfree_skb(ei_local->netrx1_skbuf[i]);
++ ei_local->netrx1_skbuf[i] = NULL;
++ }
++#endif
++ }
++
++ for ( i = 0; i < NUM_TX_DESC; i++)
++ {
++ if((ei_local->skb_free[i]!=(struct sk_buff *)0xFFFFFFFF) && (ei_local->skb_free[i]!= 0))
++ {
++ dev_kfree_skb_any(ei_local->skb_free[i]);
++ }
++ }
++
++ /* TX Ring */
++#ifdef CONFIG_RAETH_QDMA
++ if (ei_local->txd_pool != NULL) {
++ pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct QDMA_txdesc), ei_local->txd_pool, ei_local->phy_txd_pool);
++ }
++ if (ei_local->free_head != NULL){
++ pci_free_consistent(NULL, NUM_QDMA_PAGE * sizeof(struct QDMA_txdesc), ei_local->free_head, ei_local->phy_free_head);
++ }
++ if (ei_local->free_page_head != NULL){
++ pci_free_consistent(NULL, NUM_QDMA_PAGE * QDMA_PAGE_SIZE, ei_local->free_page_head, ei_local->phy_free_page_head);
++ }
++#else
++ if (ei_local->tx_ring0 != NULL) {
++ pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring0, ei_local->phy_tx_ring0);
++ }
++#endif
++
++#if defined (CONFIG_RAETH_QOS)
++ if (ei_local->tx_ring1 != NULL) {
++ pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring1, ei_local->phy_tx_ring1);
++ }
++
++#if !defined (CONFIG_RALINK_RT2880)
++ if (ei_local->tx_ring2 != NULL) {
++ pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring2, ei_local->phy_tx_ring2);
++ }
++
++ if (ei_local->tx_ring3 != NULL) {
++ pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring3, ei_local->phy_tx_ring3);
++ }
++#endif
++#endif
++ /* RX Ring */
++#ifdef CONFIG_32B_DESC
++ kfree(ei_local->rx_ring0);
++#else
++ pci_free_consistent(NULL, NUM_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring0, ei_local->phy_rx_ring0);
++#endif
++#if defined CONFIG_RAETH_QDMA && !defined(CONFIG_RAETH_QDMATX_QDMARX)
++#ifdef CONFIG_32B_DESC
++ kfree(ei_local->qrx_ring);
++#else
++ pci_free_consistent(NULL, NUM_QRX_DESC*sizeof(struct PDMA_rxdesc), ei_local->qrx_ring, ei_local->phy_qrx_ring);
++#endif
++#endif
++#if defined (CONFIG_RAETH_HW_LRO)
++ pci_free_consistent(NULL, NUM_LRO_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring3, ei_local->phy_rx_ring3);
++ pci_free_consistent(NULL, NUM_LRO_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring2, ei_local->phy_rx_ring2);
++ pci_free_consistent(NULL, NUM_LRO_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring1, ei_local->phy_rx_ring1);
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++#ifdef CONFIG_32B_DESC
++ kfree(ei_local->rx_ring1);
++#else
++#if defined(CONFIG_ARCH_MT7623)
++ pci_free_consistent(NULL, NUM_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring3, ei_local->phy_rx_ring3);
++ pci_free_consistent(NULL, NUM_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring2, ei_local->phy_rx_ring2);
++#endif /* CONFIG_ARCH_MT7623 */
++ pci_free_consistent(NULL, NUM_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring1, ei_local->phy_rx_ring1);
++#endif
++#endif
++
++ printk("Free TX/RX Ring Memory!\n");
++
++ fe_reset();
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
++ module_put(THIS_MODULE);
++#else
++ MOD_DEC_USE_COUNT;
++#endif
++ return 0;
++}
++
++#if defined (CONFIG_RT6855A_FPGA)
++void rt6855A_eth_gpio_reset(void)
++{
++ u8 ether_gpio = 12;
++
++ /* Load the ethernet gpio value to reset Ethernet PHY */
++ *(unsigned long *)(RALINK_PIO_BASE + 0x00) |= 1<<(ether_gpio<<1);
++ *(unsigned long *)(RALINK_PIO_BASE + 0x14) |= 1<<(ether_gpio);
++ *(unsigned long *)(RALINK_PIO_BASE + 0x04) &= ~(1<<ether_gpio);
++
++ udelay(100000);
++
++ *(unsigned long *)(RALINK_PIO_BASE + 0x04) |= (1<<ether_gpio);
++
++ /* must wait for 0.6 seconds after reset*/
++ udelay(600000);
++}
++#endif
++
++#if defined(CONFIG_RALINK_RT6855A)
++void rt6855A_gsw_init(void)
++{
++ u32 phy_val=0;
++ u32 rev=0;
++
++#if defined (CONFIG_RT6855A_FPGA)
++ /*keep dump switch mode */
++ rt6855A_eth_gpio_reset();
++
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3000) = 0x5e353;//(P0,Force mode,Link Up,100Mbps,Full-Duplex,FC ON)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3100) = 0x5e353;//(P1,Force mode,Link Up,100Mbps,Full-Duplex,FC ON)
++ //*(unsigned long *)(RALINK_ETH_SW_BASE+0x3000) = 0x5e333;//(P0,Force mode,Link Up,10Mbps,Full-Duplex,FC ON)
++ //*(unsigned long *)(RALINK_ETH_SW_BASE+0x3100) = 0x5e333;//(P1,Force mode,Link Up,10Mbps,Full-Duplex,FC ON)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3200) = 0x8000;//link down
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3300) = 0x8000;//link down
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x8000;//link down
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x8000;//link down
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3600) = 0x5e33b;//CPU Port6 Force Link 1G, FC ON
++
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0010) = 0xffffffe0;//Set Port6 CPU Port
++
++ /* In order to use 10M/Full on FPGA board. We configure phy capable to
++ * 10M Full/Half duplex, so we can use auto-negotiation on PC side */
++ for(i=6;i<8;i++){
++ mii_mgr_write(i, 4, 0x07e1); //Capable of 10M&100M Full/Half Duplex, flow control on/off
++ //mii_mgr_write(i, 4, 0x0461); //Capable of 10M Full/Half Duplex, flow control on/off
++ mii_mgr_write(i, 0, 0xB100); //reset all digital logic, except phy_reg
++ mii_mgr_read(i, 9, &phy_val);
++ phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
++ mii_mgr_write(i, 9, phy_val);
++ }
++#elif defined (CONFIG_RT6855A_ASIC)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3600) = 0x5e33b;//CPU Port6 Force Link 1G, FC ON
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0010) = 0xffffffe0;//Set Port6 CPU Port
++
++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE+0x1ec) = 0x0fffffff;//Set PSE should pause 4 tx ring as default
++ *(unsigned long *)(RALINK_FRAME_ENGINE_BASE+0x1f0) = 0x0fffffff;//switch IOT more stable
++
++ *(unsigned long *)(CKGCR) &= ~(0x3 << 4); //keep rx/tx port clock ticking, disable internal clock-gating to avoid switch stuck
++
++ /*
++ *Reg 31: Page Control
++ * Bit 15 => PortPageSel, 1=local, 0=global
++ * Bit 14:12 => PageSel, local:0~3, global:0~4
++ *
++ *Reg16~30:Local/Global registers
++ *
++ */
++ /*correct PHY setting J8.0*/
++ mii_mgr_read(0, 31, &rev);
++ rev &= (0x0f);
++
++ mii_mgr_write(1, 31, 0x4000); //global, page 4
++
++ mii_mgr_write(1, 16, 0xd4cc);
++ mii_mgr_write(1, 17, 0x7444);
++ mii_mgr_write(1, 19, 0x0112);
++ mii_mgr_write(1, 21, 0x7160);
++ mii_mgr_write(1, 22, 0x10cf);
++ mii_mgr_write(1, 26, 0x0777);
++
++ if(rev == 0){
++ mii_mgr_write(1, 25, 0x0102);
++ mii_mgr_write(1, 29, 0x8641);
++ }
++ else{
++ mii_mgr_write(1, 25, 0x0212);
++ mii_mgr_write(1, 29, 0x4640);
++ }
++
++ mii_mgr_write(1, 31, 0x2000); //global, page 2
++ mii_mgr_write(1, 21, 0x0655);
++ mii_mgr_write(1, 22, 0x0fd3);
++ mii_mgr_write(1, 23, 0x003d);
++ mii_mgr_write(1, 24, 0x096e);
++ mii_mgr_write(1, 25, 0x0fed);
++ mii_mgr_write(1, 26, 0x0fc4);
++
++ mii_mgr_write(1, 31, 0x1000); //global, page 1
++ mii_mgr_write(1, 17, 0xe7f8);
++
++
++ mii_mgr_write(1, 31, 0xa000); //local, page 2
++
++ mii_mgr_write(0, 16, 0x0e0e);
++ mii_mgr_write(1, 16, 0x0c0c);
++ mii_mgr_write(2, 16, 0x0f0f);
++ mii_mgr_write(3, 16, 0x1010);
++ mii_mgr_write(4, 16, 0x0909);
++
++ mii_mgr_write(0, 17, 0x0000);
++ mii_mgr_write(1, 17, 0x0000);
++ mii_mgr_write(2, 17, 0x0000);
++ mii_mgr_write(3, 17, 0x0000);
++ mii_mgr_write(4, 17, 0x0000);
++#endif
++
++#if defined (CONFIG_RT6855A_ASIC)
++
++#if defined (CONFIG_P5_RGMII_TO_MAC_MODE)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e33b;//(P5, Force mode, Link Up, 1000Mbps, Full-Duplex, FC ON)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x7014) = 0x1f0c000c;//disable port0-port4 internal phy, set phy base address to 12
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x250c) = 0x000fff10;//disable port5 mac learning
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x260c) = 0x000fff10;//disable port6 mac learning
++
++#elif defined (CONFIG_P5_MII_TO_MAC_MODE)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
++#elif defined (CONFIG_P5_MAC_TO_PHY_MODE)
++ //rt6855/6 need to modify TX/RX phase
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x7014) = 0xc;//TX/RX CLOCK Phase select
++
++ enable_auto_negotiate(1);
++
++ if (isICPlusGigaPHY(1)) {
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, &phy_val);
++ phy_val |= 1<<10; //enable pause ability
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, phy_val);
++
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
++ phy_val |= 1<<9; //restart AN
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
++ }
++
++ if (isMarvellGigaPHY(1)) {
++ printk("Reset MARVELL phy1\n");
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, &phy_val);
++ phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, phy_val);
++
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
++ phy_val |= 1<<15; //PHY Software Reset
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
++ }
++ if (isVtssGigaPHY(1)) {
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0001); //extended page
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, &phy_val);
++ printk("Vitesse phy skew: %x --> ", phy_val);
++ phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
++ phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns
++ printk("%x\n", phy_val);
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, phy_val);
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0000); //main registers
++ }
++#elif defined (CONFIG_P5_RMII_TO_MAC_MODE)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
++#else // Port 5 Disabled //
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x8000;//link down
++#endif
++#endif
++}
++#endif
++
++
++
++
++#if defined (CONFIG_MT7623_FPGA)
++void setup_fpga_gsw(void)
++{
++ u32 i;
++ u32 regValue;
++
++ /* reduce RGMII2 PAD driving strength */
++ *(volatile u_long *)(PAD_RGMII2_MDIO_CFG) &= ~(0x3 << 4);
++
++ //RGMII1=Normal mode
++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 14);
++
++ //GMAC1= RGMII mode
++ *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 12);
++
++ //enable MDIO to control MT7530
++ regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60));
++ regValue &= ~(0x3 << 12);
++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue;
++
++ for(i=0;i<=4;i++)
++ {
++ //turn off PHY
++ mii_mgr_read(i, 0x0 ,&regValue);
++ regValue |= (0x1<<11);
++ mii_mgr_write(i, 0x0, regValue);
++ }
++ mii_mgr_write(31, 0x7000, 0x3); //reset switch
++ udelay(10);
++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2105e337);//(GE1, Force 100M/FD, FC ON)
++ mii_mgr_write(31, 0x3600, 0x5e337);
++
++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x00008000);//(GE2, Link down)
++ mii_mgr_write(31, 0x3500, 0x8000);
++
++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600)
++ //regValue = 0x117ccf; //Enable Port 6, P5 as GMAC5, P5 disable*/
++ mii_mgr_read(31, 0x7804 ,&regValue);
++ regValue &= ~(1<<8); //Enable Port 6
++ regValue |= (1<<6); //Disable Port 5
++ regValue |= (1<<13); //Port 5 as GMAC, no Internal PHY
++
++#if defined (CONFIG_RAETH_GMAC2)
++ //RGMII2=Normal mode
++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15);
++
++ //GMAC2= RGMII mode
++ *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14);
++
++ mii_mgr_write(31, 0x3500, 0x56300); //MT7530 P5 AN, we can ignore this setting??????
++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x21056300);//(GE2, auto-polling)
++
++ enable_auto_negotiate(0);//set polling address
++ /* set MT7530 Port 5 to PHY 0/4 mode */
++#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN)
++ regValue &= ~((1<<13)|(1<<6));
++ regValue |= ((1<<7)|(1<<16)|(1<<20));
++#elif defined (CONFIG_GE_RGMII_INTERNAL_P4_AN)
++ regValue &= ~((1<<13)|(1<<6)|((1<<20)));
++ regValue |= ((1<<7)|(1<<16));
++#endif
++
++ //sysRegWrite(GDMA2_FWD_CFG, 0x20710000);
++#endif
++ regValue |= (1<<16);//change HW-TRAP
++ printk("change HW-TRAP to 0x%x\n",regValue);
++ mii_mgr_write(31, 0x7804 ,regValue);
++#endif
++ mii_mgr_write(0, 14, 0x1); /*RGMII*/
++/* set MT7530 central align */
++ mii_mgr_read(31, 0x7830, &regValue);
++ regValue &= ~1;
++ regValue |= 1<<1;
++ mii_mgr_write(31, 0x7830, regValue);
++
++ mii_mgr_read(31, 0x7a40, &regValue);
++ regValue &= ~(1<<30);
++ mii_mgr_write(31, 0x7a40, regValue);
++
++ regValue = 0x855;
++ mii_mgr_write(31, 0x7a78, regValue);
++
++/*to check!!*/
++ mii_mgr_write(31, 0x7b00, 0x102); //delay setting for 10/1000M
++ mii_mgr_write(31, 0x7b04, 0x14); //delay setting for 10/1000M
++
++ for(i=0;i<=4;i++) {
++ mii_mgr_read(i, 4, &regValue);
++ regValue |= (3<<7); //turn on 100Base-T Advertisement
++ //regValue &= ~(3<<7); //turn off 100Base-T Advertisement
++ mii_mgr_write(i, 4, regValue);
++
++ mii_mgr_read(i, 9, &regValue);
++ //regValue |= (3<<8); //turn on 1000Base-T Advertisement
++ regValue &= ~(3<<8); //turn off 1000Base-T Advertisement
++ mii_mgr_write(i, 9, regValue);
++
++ //restart AN
++ mii_mgr_read(i, 0, &regValue);
++ regValue |= (1 << 9);
++ mii_mgr_write(i, 0, regValue);
++ }
++
++ /*Tx Driving*/
++ mii_mgr_write(31, 0x7a54, 0x44); //lower driving
++ mii_mgr_write(31, 0x7a5c, 0x44); //lower driving
++ mii_mgr_write(31, 0x7a64, 0x44); //lower driving
++ mii_mgr_write(31, 0x7a6c, 0x44); //lower driving
++ mii_mgr_write(31, 0x7a74, 0x44); //lower driving
++ mii_mgr_write(31, 0x7a7c, 0x44); //lower driving
++
++ for(i=0;i<=4;i++)
++ {
++ //turn on PHY
++ mii_mgr_read(i, 0x0 ,&regValue);
++ regValue &= ~(0x1<<11);
++ mii_mgr_write(i, 0x0, regValue);
++ }
++}
++#endif
++
++
++#if defined (CONFIG_RALINK_MT7621)
++
++
++void setup_external_gsw(void)
++{
++ u32 regValue;
++
++ /* reduce RGMII2 PAD driving strength */
++ *(volatile u_long *)(PAD_RGMII2_MDIO_CFG) &= ~(0x3 << 4);
++ //enable MDIO
++ regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60));
++ regValue &= ~(0x3 << 12);
++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue;
++
++ //RGMII1=Normal mode
++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 14);
++ //GMAC1= RGMII mode
++ *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 12);
++
++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x00008000);//(GE1, Link down)
++
++ //RGMII2=Normal mode
++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15);
++ //GMAC2= RGMII mode
++ *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14);
++
++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x2105e33b);//(GE2, Force 1000M/FD, FC ON)
++
++}
++
++
++
++
++
++
++
++
++
++
++void IsSwitchVlanTableBusy(void)
++{
++ int j = 0;
++ unsigned int value = 0;
++
++ for (j = 0; j < 20; j++) {
++ mii_mgr_read(31, 0x90, &value);
++ if ((value & 0x80000000) == 0 ){ //table busy
++ break;
++ }
++ udelay(70000);
++ }
++ if (j == 20)
++ printk("set vlan timeout value=0x%x.\n", value);
++}
++
++void LANWANPartition(void)
++{
++/*Set MT7530 */
++#ifdef CONFIG_WAN_AT_P0
++ printk("set LAN/WAN WLLLL\n");
++ //WLLLL, wan at P0
++ //LAN/WAN ports as security mode
++ mii_mgr_write(31, 0x2004, 0xff0003);//port0
++ mii_mgr_write(31, 0x2104, 0xff0003);//port1
++ mii_mgr_write(31, 0x2204, 0xff0003);//port2
++ mii_mgr_write(31, 0x2304, 0xff0003);//port3
++ mii_mgr_write(31, 0x2404, 0xff0003);//port4
++
++ //set PVID
++ mii_mgr_write(31, 0x2014, 0x10002);//port0
++ mii_mgr_write(31, 0x2114, 0x10001);//port1
++ mii_mgr_write(31, 0x2214, 0x10001);//port2
++ mii_mgr_write(31, 0x2314, 0x10001);//port3
++ mii_mgr_write(31, 0x2414, 0x10001);//port4
++ /*port6 */
++ //VLAN member
++ IsSwitchVlanTableBusy();
++ mii_mgr_write(31, 0x94, 0x407e0001);//VAWD1
++ mii_mgr_write(31, 0x90, 0x80001001);//VTCR, VID=1
++ IsSwitchVlanTableBusy();
++
++ mii_mgr_write(31, 0x94, 0x40610001);//VAWD1
++ mii_mgr_write(31, 0x90, 0x80001002);//VTCR, VID=2
++ IsSwitchVlanTableBusy();
++#endif
++#ifdef CONFIG_WAN_AT_P4
++ printk("set LAN/WAN LLLLW\n");
++ //LLLLW, wan at P4
++ //LAN/WAN ports as security mode
++ mii_mgr_write(31, 0x2004, 0xff0003);//port0
++ mii_mgr_write(31, 0x2104, 0xff0003);//port1
++ mii_mgr_write(31, 0x2204, 0xff0003);//port2
++ mii_mgr_write(31, 0x2304, 0xff0003);//port3
++ mii_mgr_write(31, 0x2404, 0xff0003);//port4
++
++ //set PVID
++ mii_mgr_write(31, 0x2014, 0x10001);//port0
++ mii_mgr_write(31, 0x2114, 0x10001);//port1
++ mii_mgr_write(31, 0x2214, 0x10001);//port2
++ mii_mgr_write(31, 0x2314, 0x10001);//port3
++ mii_mgr_write(31, 0x2414, 0x10002);//port4
++
++ //VLAN member
++ IsSwitchVlanTableBusy();
++ mii_mgr_write(31, 0x94, 0x404f0001);//VAWD1
++ mii_mgr_write(31, 0x90, 0x80001001);//VTCR, VID=1
++ IsSwitchVlanTableBusy();
++ mii_mgr_write(31, 0x94, 0x40500001);//VAWD1
++ mii_mgr_write(31, 0x90, 0x80001002);//VTCR, VID=2
++ IsSwitchVlanTableBusy();
++#endif
++}
++
++#if defined (CONFIG_RAETH_8023AZ_EEE) && defined (CONFIG_RALINK_MT7621)
++void mt7621_eee_patch(void)
++{
++ u32 i;
++
++ for(i=0;i<5;i++)
++ {
++ /* Enable EEE */
++ mii_mgr_write(i, 13, 0x07);
++ mii_mgr_write(i, 14, 0x3c);
++ mii_mgr_write(i, 13, 0x4007);
++ mii_mgr_write(i, 14, 0x6);
++
++ /* Forced Slave mode */
++ mii_mgr_write(i, 31, 0x0);
++ mii_mgr_write(i, 9, 0x1600);
++ /* Increase SlvDPSready time */
++ mii_mgr_write(i, 31, 0x52b5);
++ mii_mgr_write(i, 16, 0xafae);
++ mii_mgr_write(i, 18, 0x2f);
++ mii_mgr_write(i, 16, 0x8fae);
++ /* Incease post_update_timer */
++ mii_mgr_write(i, 31, 0x3);
++ mii_mgr_write(i, 17, 0x4b);
++ /* Adjust 100_mse_threshold */
++ mii_mgr_write(i, 13, 0x1e);
++ mii_mgr_write(i, 14, 0x123);
++ mii_mgr_write(i, 13, 0x401e);
++ mii_mgr_write(i, 14, 0xffff);
++ /* Disable mcc
++ mii_mgr_write(i, 13, 0x1e);
++ mii_mgr_write(i, 14, 0xa6);
++ mii_mgr_write(i, 13, 0x401e);
++ mii_mgr_write(i, 14, 0x300);
++ */
++ }
++
++}
++#endif
++
++
++#if defined (CONFIG_RALINK_MT7621)
++void setup_internal_gsw(void)
++{
++ u32 i;
++ u32 regValue;
++
++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600)
++ /*Hardware reset Switch*/
++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x34) |= (0x1 << 2);
++ udelay(1000);
++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x34) &= ~(0x1 << 2);
++ udelay(10000);
++
++ /* reduce RGMII2 PAD driving strength */
++ *(volatile u_long *)(PAD_RGMII2_MDIO_CFG) &= ~(0x3 << 4);
++
++ //RGMII1=Normal mode
++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 14);
++
++ //GMAC1= RGMII mode
++ *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 12);
++
++ //enable MDIO to control MT7530
++ regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60));
++ regValue &= ~(0x3 << 12);
++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue;
++
++ for(i=0;i<=4;i++)
++ {
++ //turn off PHY
++ mii_mgr_read(i, 0x0 ,&regValue);
++ regValue |= (0x1<<11);
++ mii_mgr_write(i, 0x0, regValue);
++ }
++ mii_mgr_write(31, 0x7000, 0x3); //reset switch
++ udelay(100);
++
++
++#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC)
++ trgmii_set_7530(); //reset FE, config MDIO again
++
++ //enable MDIO to control MT7530
++ regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60));
++ regValue &= ~(0x3 << 12);
++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue;
++
++ // switch to APLL if TRGMII and DDR2
++ if ((sysRegRead(0xBE000010)>>4)&0x1)
++ {
++ apll_xtal_enable();
++ }
++#endif
++
++#if defined (CONFIG_MT7621_ASIC)
++ if((sysRegRead(0xbe00000c)&0xFFFF)==0x0101) {
++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2105e30b);//(GE1, Force 1000M/FD, FC ON)
++ mii_mgr_write(31, 0x3600, 0x5e30b);
++ } else {
++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2105e33b);//(GE1, Force 1000M/FD, FC ON)
++ mii_mgr_write(31, 0x3600, 0x5e33b);
++ }
++#elif defined (CONFIG_MT7621_FPGA)
++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2105e337);//(GE1, Force 100M/FD, FC ON)
++ mii_mgr_write(31, 0x3600, 0x5e337);
++#endif
++
++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x00008000);//(GE2, Link down)
++#endif
++
++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600)
++ //regValue = 0x117ccf; //Enable Port 6, P5 as GMAC5, P5 disable*/
++ mii_mgr_read(31, 0x7804 ,&regValue);
++ regValue &= ~(1<<8); //Enable Port 6
++ regValue |= (1<<6); //Disable Port 5
++ regValue |= (1<<13); //Port 5 as GMAC, no Internal PHY
++
++#if defined (CONFIG_RAETH_GMAC2)
++ //RGMII2=Normal mode
++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15);
++
++ //GMAC2= RGMII mode
++ *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14);
++#if !defined (CONFIG_RAETH_8023AZ_EEE)
++ mii_mgr_write(31, 0x3500, 0x56300); //MT7530 P5 AN, we can ignore this setting??????
++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x21056300);//(GE2, auto-polling)
++
++ enable_auto_negotiate(0);//set polling address
++#endif
++#if defined (CONFIG_RAETH_8023AZ_EEE)
++ mii_mgr_write(31, 0x3500, 0x5e33b); //MT7530 P5 Force 1000, we can ignore this setting??????
++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x2105e33b);//(GE2, Force 1000)
++#endif
++
++
++
++ /* set MT7530 Port 5 to PHY 0/4 mode */
++#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN)
++ regValue &= ~((1<<13)|(1<<6));
++ regValue |= ((1<<7)|(1<<16)|(1<<20));
++#elif defined (CONFIG_GE_RGMII_INTERNAL_P4_AN)
++ regValue &= ~((1<<13)|(1<<6)|(1<<20));
++ regValue |= ((1<<7)|(1<<16));
++#endif
++
++#if defined (CONFIG_RAETH_8023AZ_EEE)
++ regValue |= (1<<13); //Port 5 as GMAC, no Internal PHY
++#endif
++ //sysRegWrite(GDMA2_FWD_CFG, 0x20710000);
++#endif
++ regValue |= (1<<16);//change HW-TRAP
++ //printk("change HW-TRAP to 0x%x\n",regValue);
++ mii_mgr_write(31, 0x7804 ,regValue);
++#endif
++ mii_mgr_read(31, 0x7800, &regValue);
++ regValue = (regValue >> 9) & 0x3;
++ if(regValue == 0x3) { //25Mhz Xtal
++ /* do nothing */
++ } else if(regValue == 0x2) { //40Mhz
++
++ mii_mgr_write(0, 13, 0x1f); // disable MT7530 core clock
++ mii_mgr_write(0, 14, 0x410);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0x0);
++
++ mii_mgr_write(0, 13, 0x1f); // disable MT7530 PLL
++ mii_mgr_write(0, 14, 0x40d);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0x2020);
++
++ mii_mgr_write(0, 13, 0x1f); // for MT7530 core clock = 500Mhz
++ mii_mgr_write(0, 14, 0x40e);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0x119);
++
++ mii_mgr_write(0, 13, 0x1f); // enable MT7530 PLL
++ mii_mgr_write(0, 14, 0x40d);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0x2820);
++
++ udelay(20); //suggest by CD
++
++ mii_mgr_write(0, 13, 0x1f); // enable MT7530 core clock
++ mii_mgr_write(0, 14, 0x410);
++ mii_mgr_write(0, 13, 0x401f);
++ }else { //20Mhz Xtal
++
++ /* TODO */
++
++ }
++#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC)
++ mii_mgr_write(0, 14, 0x3); /*TRGMII*/
++#else
++ mii_mgr_write(0, 14, 0x1); /*RGMII*/
++/* set MT7530 central align */
++ mii_mgr_read(31, 0x7830, &regValue);
++ regValue &= ~1;
++ regValue |= 1<<1;
++ mii_mgr_write(31, 0x7830, regValue);
++
++ mii_mgr_read(31, 0x7a40, &regValue);
++ regValue &= ~(1<<30);
++ mii_mgr_write(31, 0x7a40, regValue);
++
++ regValue = 0x855;
++ mii_mgr_write(31, 0x7a78, regValue);
++
++#endif
++#if !defined (CONFIG_RAETH_8023AZ_EEE)
++ mii_mgr_write(31, 0x7b00, 0x102); //delay setting for 10/1000M
++ mii_mgr_write(31, 0x7b04, 0x14); //delay setting for 10/1000M
++#endif
++#if 0
++ for(i=0;i<=4;i++) {
++ mii_mgr_read(i, 4, &regValue);
++ regValue |= (3<<7); //turn on 100Base-T Advertisement
++ //regValue &= ~(3<<7); //turn off 100Base-T Advertisement
++ mii_mgr_write(i, 4, regValue);
++
++ mii_mgr_read(i, 9, &regValue);
++ regValue |= (3<<8); //turn on 1000Base-T Advertisement
++ //regValue &= ~(3<<8); //turn off 1000Base-T Advertisement
++ mii_mgr_write(i, 9, regValue);
++
++ //restart AN
++ mii_mgr_read(i, 0, &regValue);
++ regValue |= (1 << 9);
++ mii_mgr_write(i, 0, regValue);
++ }
++#endif
++
++ /*Tx Driving*/
++ mii_mgr_write(31, 0x7a54, 0x44); //lower driving
++ mii_mgr_write(31, 0x7a5c, 0x44); //lower driving
++ mii_mgr_write(31, 0x7a64, 0x44); //lower driving
++ mii_mgr_write(31, 0x7a6c, 0x44); //lower driving
++ mii_mgr_write(31, 0x7a74, 0x44); //lower driving
++ mii_mgr_write(31, 0x7a7c, 0x44); //lower driving
++
++
++ LANWANPartition();
++
++#if !defined (CONFIG_RAETH_8023AZ_EEE)
++ //disable EEE
++ for(i=0;i<=4;i++)
++ {
++ mii_mgr_write(i, 13, 0x7);
++ mii_mgr_write(i, 14, 0x3C);
++ mii_mgr_write(i, 13, 0x4007);
++ mii_mgr_write(i, 14, 0x0);
++ }
++
++ //Disable EEE 10Base-Te:
++ for(i=0;i<=4;i++)
++ {
++ mii_mgr_write(i, 13, 0x1f);
++ mii_mgr_write(i, 14, 0x027b);
++ mii_mgr_write(i, 13, 0x401f);
++ mii_mgr_write(i, 14, 0x1177);
++ }
++#endif
++
++ for(i=0;i<=4;i++)
++ {
++ //turn on PHY
++ mii_mgr_read(i, 0x0 ,&regValue);
++ regValue &= ~(0x1<<11);
++ mii_mgr_write(i, 0x0, regValue);
++ }
++
++ mii_mgr_read(31, 0x7808 ,&regValue);
++ regValue |= (3<<16); //Enable INTR
++ mii_mgr_write(31, 0x7808 ,regValue);
++#if defined (CONFIG_RAETH_8023AZ_EEE) && defined (CONFIG_RALINK_MT7621)
++ mt7621_eee_patch();
++#endif
++}
++#endif
++
++#if defined (CONFIG_GE1_TRGMII_FORCE_1200)
++void apll_xtal_enable(void)
++{
++ unsigned long data = 0;
++ unsigned long regValue = 0;
++
++ /* Firstly, reset all required register to default value */
++ sysRegWrite(RALINK_ANA_CTRL_BASE, 0x00008000);
++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x0014, 0x01401d61);
++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x0018, 0x38233d0e);
++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, 0x80120004);
++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x0020, 0x1c7dbf48);
++
++ /* toggle RG_XPTL_CHG */
++ sysRegWrite(RALINK_ANA_CTRL_BASE, 0x00008800);
++ sysRegWrite(RALINK_ANA_CTRL_BASE, 0x00008c00);
++
++ data = sysRegRead(RALINK_ANA_CTRL_BASE+0x0014);
++ data &= ~(0x0000ffc0);
++
++ regValue = *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x10);
++ regValue = (regValue >> 6) & 0x7;
++ if(regValue < 6) { //20/40Mhz Xtal
++ data |= REGBIT(0x1d, 8);
++ }else {
++ data |= REGBIT(0x17, 8);
++ }
++
++ if(regValue < 6) { //20/40Mhz Xtal
++ data |= REGBIT(0x1, 6);
++ }
++
++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x0014, data);
++
++ data = sysRegRead(RALINK_ANA_CTRL_BASE+0x0018);
++ data &= ~(0xf0773f00);
++ data |= REGBIT(0x3, 28);
++ data |= REGBIT(0x2, 20);
++ if(regValue < 6) { //20/40Mhz Xtal
++ data |= REGBIT(0x3, 16);
++ }else {
++ data |= REGBIT(0x2, 16);
++ }
++ data |= REGBIT(0x3, 12);
++
++ if(regValue < 6) { //20/40Mhz Xtal
++ data |= REGBIT(0xd, 8);
++ }else {
++ data |= REGBIT(0x7, 8);
++ }
++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x0018, data);
++
++ if(regValue < 6) { //20/40Mhz Xtal
++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x0020, 0x1c7dbf48);
++ }else {
++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x0020, 0x1697cc39);
++ }
++ //*Common setting - Set PLLGP_CTRL_4 *//
++ ///* 1. Bit 31 */
++ data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
++ data &= ~(REGBIT(0x1, 31));
++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
++
++ /* 2. Bit 0 */
++ data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
++ data |= REGBIT(0x1, 0);
++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
++
++ /* 3. Bit 3 */
++ data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
++ data |= REGBIT(0x1, 3);
++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
++
++ /* 4. Bit 8 */
++ data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
++ data |= REGBIT(0x1, 8);
++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
++
++ /* 5. Bit 6 */
++ data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
++ data |= REGBIT(0x1, 6);
++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
++
++ /* 6. Bit 7 */
++ data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
++ data |= REGBIT(0x1, 5);
++ data |= REGBIT(0x1, 7);
++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
++
++ /* 7. Bit 17 */
++ data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
++ data &= ~REGBIT(0x1, 17);
++ sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
++
++ /* 8. TRGMII TX CLK SEL APLL */
++ data = sysRegRead(0xbe00002c);
++ data &= 0xffffff9f;
++ data |= 0x40;
++ sysRegWrite(0xbe00002c, data);
++
++}
++#endif
++
++#endif
++#if defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_MT7620)
++void rt_gsw_init(void)
++{
++#if defined (CONFIG_P4_MAC_TO_PHY_MODE) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
++ u32 phy_val=0;
++#endif
++#if defined (CONFIG_RT6855_FPGA) || defined (CONFIG_MT7620_FPGA)
++ u32 i=0;
++#elif defined (CONFIG_MT7620_ASIC)
++ u32 is_BGA=0;
++#endif
++#if defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
++ unsigned int regValue = 0;
++#endif
++#if defined (CONFIG_RT6855_FPGA) || defined (CONFIG_MT7620_FPGA)
++ /*keep dump switch mode */
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3000) = 0x5e333;//(P0, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3100) = 0x5e333;//(P1, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3200) = 0x5e333;//(P2, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3300) = 0x5e333;//(P3, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
++#if defined (CONFIG_RAETH_HAS_PORT4)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e337;//(P4, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
++#else
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e333;//(P4, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
++#endif
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
++
++ /* In order to use 10M/Full on FPGA board. We configure phy capable to
++ * 10M Full/Half duplex, so we can use auto-negotiation on PC side */
++#if defined (CONFIG_RAETH_HAS_PORT4)
++ for(i=0;i<4;i++){
++#else
++ for(i=0;i<5;i++){
++#endif
++ mii_mgr_write(i, 4, 0x0461); //Capable of 10M Full/Half Duplex, flow control on/off
++ mii_mgr_write(i, 0, 0xB100); //reset all digital logic, except phy_reg
++ }
++
++#endif
++
++#if defined (CONFIG_PDMA_NEW)
++ *(unsigned long *)(SYSCFG1) |= (0x1 << 8); //PCIE_RC_MODE=1
++#endif
++
++
++#if defined (CONFIG_MT7620_ASIC) && !defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
++ is_BGA = (sysRegRead(RALINK_SYSCTL_BASE + 0xc) >> 16) & 0x1;
++ /*
++ * Reg 31: Page Control
++ * Bit 15 => PortPageSel, 1=local, 0=global
++ * Bit 14:12 => PageSel, local:0~3, global:0~4
++ *
++ * Reg16~30:Local/Global registers
++ *
++ */
++ /*correct PHY setting L3.0 BGA*/
++ mii_mgr_write(1, 31, 0x4000); //global, page 4
++
++ mii_mgr_write(1, 17, 0x7444);
++ if(is_BGA){
++ mii_mgr_write(1, 19, 0x0114);
++ }else{
++ mii_mgr_write(1, 19, 0x0117);
++ }
++
++ mii_mgr_write(1, 22, 0x10cf);
++ mii_mgr_write(1, 25, 0x6212);
++ mii_mgr_write(1, 26, 0x0777);
++ mii_mgr_write(1, 29, 0x4000);
++ mii_mgr_write(1, 28, 0xc077);
++ mii_mgr_write(1, 24, 0x0000);
++
++ mii_mgr_write(1, 31, 0x3000); //global, page 3
++ mii_mgr_write(1, 17, 0x4838);
++
++ mii_mgr_write(1, 31, 0x2000); //global, page 2
++ if(is_BGA){
++ mii_mgr_write(1, 21, 0x0515);
++ mii_mgr_write(1, 22, 0x0053);
++ mii_mgr_write(1, 23, 0x00bf);
++ mii_mgr_write(1, 24, 0x0aaf);
++ mii_mgr_write(1, 25, 0x0fad);
++ mii_mgr_write(1, 26, 0x0fc1);
++ }else{
++ mii_mgr_write(1, 21, 0x0517);
++ mii_mgr_write(1, 22, 0x0fd2);
++ mii_mgr_write(1, 23, 0x00bf);
++ mii_mgr_write(1, 24, 0x0aab);
++ mii_mgr_write(1, 25, 0x00ae);
++ mii_mgr_write(1, 26, 0x0fff);
++ }
++ mii_mgr_write(1, 31, 0x1000); //global, page 1
++ mii_mgr_write(1, 17, 0xe7f8);
++
++ mii_mgr_write(1, 31, 0x8000); //local, page 0
++ mii_mgr_write(0, 30, 0xa000);
++ mii_mgr_write(1, 30, 0xa000);
++ mii_mgr_write(2, 30, 0xa000);
++ mii_mgr_write(3, 30, 0xa000);
++#if !defined (CONFIG_RAETH_HAS_PORT4)
++ mii_mgr_write(4, 30, 0xa000);
++#endif
++
++ mii_mgr_write(0, 4, 0x05e1);
++ mii_mgr_write(1, 4, 0x05e1);
++ mii_mgr_write(2, 4, 0x05e1);
++ mii_mgr_write(3, 4, 0x05e1);
++#if !defined (CONFIG_RAETH_HAS_PORT4)
++ mii_mgr_write(4, 4, 0x05e1);
++#endif
++
++ mii_mgr_write(1, 31, 0xa000); //local, page 2
++ mii_mgr_write(0, 16, 0x1111);
++ mii_mgr_write(1, 16, 0x1010);
++ mii_mgr_write(2, 16, 0x1515);
++ mii_mgr_write(3, 16, 0x0f0f);
++#if !defined (CONFIG_RAETH_HAS_PORT4)
++ mii_mgr_write(4, 16, 0x1313);
++#endif
++
++#if !defined (CONFIG_RAETH_8023AZ_EEE)
++ mii_mgr_write(1, 31, 0xb000); //local, page 3
++ mii_mgr_write(0, 17, 0x0);
++ mii_mgr_write(1, 17, 0x0);
++ mii_mgr_write(2, 17, 0x0);
++ mii_mgr_write(3, 17, 0x0);
++#if !defined (CONFIG_RAETH_HAS_PORT4)
++ mii_mgr_write(4, 17, 0x0);
++#endif
++#endif
++
++
++
++#if 0
++ // for ethernet extended mode
++ mii_mgr_write(1, 31, 0x3000);
++ mii_mgr_write(1, 19, 0x122);
++ mii_mgr_write(1, 20, 0x0044);
++ mii_mgr_write(1, 23, 0xa80c);
++ mii_mgr_write(1, 24, 0x129d);
++ mii_mgr_write(1, 31, 9000);
++ mii_mgr_write(0, 18, 0x140c);
++ mii_mgr_write(1, 18, 0x140c);
++ mii_mgr_write(2, 18, 0x140c);
++ mii_mgr_write(3, 18, 0x140c);
++ mii_mgr_write(0, 0, 0x3300);
++ mii_mgr_write(1, 0, 0x3300);
++ mii_mgr_write(2, 0, 0x3300);
++ mii_mgr_write(3, 0, 0x3300);
++#if !defined (CONFIG_RAETH_HAS_PORT4)
++ mii_mgr_write(4, 18, 0x140c);
++ mii_mgr_write(4, 0, 0x3300);
++#endif
++#endif
++
++#endif
++
++#if defined(CONFIG_RALINK_MT7620)
++ if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x701c) = 0x800000c; //enlarge FE2SW_IPG
++ }
++#endif // CONFIG_RAETH_7620 //
++
++
++
++#if defined (CONFIG_MT7620_FPGA)|| defined (CONFIG_MT7620_ASIC)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3600) = 0x5e33b;//CPU Port6 Force Link 1G, FC ON
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0010) = 0x7f7f7fe0;//Set Port6 CPU Port
++
++#if defined (CONFIG_P5_RGMII_TO_MAC_MODE) || defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e33b;//(P5, Force mode, Link Up, 1000Mbps, Full-Duplex, FC ON)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x7014) = 0x1f0c000c; //disable port 0 ~ 4 internal phy, set phy base address to 12
++ /*MT7620 need mac learning for PPE*/
++ //*(unsigned long *)(RALINK_ETH_SW_BASE+0x250c) = 0x000fff10;//disable port5 mac learning
++ //*(unsigned long *)(RALINK_ETH_SW_BASE+0x260c) = 0x000fff10;//disable port6 mac learning
++ *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
++ //rxclk_skew, txclk_skew = 0
++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RGMii Mode
++#if defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
++
++ *(unsigned long *)(0xb0000060) &= ~(3 << 7); //set MDIO to Normal mode
++
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x56330;//(P4, AN)
++ *(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
++ //rxclk_skew, txclk_skew = 0
++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=RGMii Mode
++
++
++ /* set MT7530 Port 0 to PHY mode */
++ mii_mgr_read(31, 0x7804 ,&regValue);
++#if defined (CONFIG_GE_RGMII_MT7530_P0_AN)
++ regValue &= ~((1<<13)|(1<<6)|(1<<5)|(1<<15));
++ regValue |= ((1<<7)|(1<<16)|(1<<20)|(1<<24));
++ //mii_mgr_write(31, 0x7804 ,0x115c8f);
++#elif defined (CONFIG_GE_RGMII_MT7530_P4_AN)
++ regValue &= ~((1<<13)|(1<<6)|(1<<20)|(1<<5)|(1<<15));
++ regValue |= ((1<<7)|(1<<16)|(1<<24));
++#endif
++ regValue &= ~(1<<8); //Enable Port 6
++ mii_mgr_write(31, 0x7804 ,regValue); //bit 24 standalone switch
++
++/* set MT7530 central align */
++ mii_mgr_read(31, 0x7830, &regValue);
++ regValue &= ~1;
++ regValue |= 1<<1;
++ mii_mgr_write(31, 0x7830, regValue);
++
++ mii_mgr_read(31, 0x7a40, &regValue);
++ regValue &= ~(1<<30);
++ mii_mgr_write(31, 0x7a40, regValue);
++
++ regValue = 0x855;
++ mii_mgr_write(31, 0x7a78, regValue);
++
++ /*AN should be set after MT7530 HWSTRAP*/
++#if defined (CONFIG_GE_RGMII_MT7530_P0_AN)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x7000) = 0xc5000100;//(P0, AN polling)
++#elif defined (CONFIG_GE_RGMII_MT7530_P4_AN)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x7000) = 0xc5000504;//(P4, AN polling)
++#endif
++#endif
++
++#elif defined (CONFIG_P5_MII_TO_MAC_MODE)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
++ *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=Mii Mode
++ *(unsigned long *)(SYSCFG1) |= (0x1 << 12);
++
++#elif defined (CONFIG_P5_MAC_TO_PHY_MODE)
++ *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
++ *(unsigned long *)(0xb0000060) &= ~(3 << 7); //set MDIO to Normal mode
++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RGMii Mode
++
++ enable_auto_negotiate(1);
++
++ if (isICPlusGigaPHY(1)) {
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, &phy_val);
++ phy_val |= 1<<10; //enable pause ability
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, phy_val);
++
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
++ phy_val |= 1<<9; //restart AN
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
++ }else if (isMarvellGigaPHY(1)) {
++#if defined (CONFIG_MT7620_FPGA)
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, &phy_val);
++ phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, phy_val);
++#endif
++ printk("Reset MARVELL phy1\n");
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, &phy_val);
++ phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, phy_val);
++
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
++ phy_val |= 1<<15; //PHY Software Reset
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
++ }else if (isVtssGigaPHY(1)) {
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0001); //extended page
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, &phy_val);
++ printk("Vitesse phy skew: %x --> ", phy_val);
++ phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
++ phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns
++ printk("%x\n", phy_val);
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, phy_val);
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0000); //main registers
++ }
++
++
++#elif defined (CONFIG_P5_RMII_TO_MAC_MODE)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
++ *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RvMii Mode
++ *(unsigned long *)(SYSCFG1) |= (0x2 << 12);
++
++#else // Port 5 Disabled //
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x8000;//link down
++ *(unsigned long *)(0xb0000060) |= (1 << 9); //set RGMII to GPIO mode
++#endif
++#endif
++
++#if defined (CONFIG_P4_RGMII_TO_MAC_MODE)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e33b;//(P4, Force mode, Link Up, 1000Mbps, Full-Duplex, FC ON)
++ *(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
++ //rxclk_skew, txclk_skew = 0
++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=RGMii Mode
++
++#elif defined (CONFIG_P4_MII_TO_MAC_MODE)
++ *(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=Mii Mode
++ *(unsigned long *)(SYSCFG1) |= (0x1 << 14);
++
++#elif defined (CONFIG_P4_MAC_TO_PHY_MODE)
++ *(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
++ *(unsigned long *)(0xb0000060) &= ~(3 << 7); //set MDIO to Normal mode
++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=RGMii Mode
++
++ enable_auto_negotiate(1);
++
++ if (isICPlusGigaPHY(2)) {
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 4, &phy_val);
++ phy_val |= 1<<10; //enable pause ability
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 4, phy_val);
++
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, &phy_val);
++ phy_val |= 1<<9; //restart AN
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, phy_val);
++ }else if (isMarvellGigaPHY(2)) {
++#if defined (CONFIG_MT7620_FPGA)
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, &phy_val);
++ phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, phy_val);
++#endif
++ printk("Reset MARVELL phy2\n");
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, &phy_val);
++ phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, phy_val);
++
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, &phy_val);
++ phy_val |= 1<<15; //PHY Software Reset
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, phy_val);
++ }else if (isVtssGigaPHY(2)) {
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 0x0001); //extended page
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, &phy_val);
++ printk("Vitesse phy skew: %x --> ", phy_val);
++ phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
++ phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns
++ printk("%x\n", phy_val);
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, phy_val);
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 0x0000); //main registers
++ }
++
++#elif defined (CONFIG_P4_RMII_TO_MAC_MODE)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
++ *(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE1_MODE=RvMii Mode
++ *(unsigned long *)(SYSCFG1) |= (0x2 << 14);
++#elif defined (CONFIG_GE_RGMII_MT7530_P0_AN) || defined (CONFIG_GE_RGMII_MT7530_P4_AN)
++#else // Port 4 Disabled //
++ *(unsigned long *)(SYSCFG1) |= (0x3 << 14); //GE2_MODE=RJ45 Mode
++ *(unsigned long *)(0xb0000060) |= (1 << 10); //set RGMII2 to GPIO mode
++#endif
++
++}
++#endif
++
++#if defined (CONFIG_RALINK_MT7628)
++
++void mt7628_ephy_init(void)
++{
++ int i;
++ u32 phy_val;
++ mii_mgr_write(0, 31, 0x2000); //change G2 page
++ mii_mgr_write(0, 26, 0x0000);
++
++ for(i=0; i<5; i++){
++ mii_mgr_write(i, 31, 0x8000); //change L0 page
++ mii_mgr_write(i, 0, 0x3100);
++
++#if defined (CONFIG_RAETH_8023AZ_EEE)
++ mii_mgr_read(i, 26, &phy_val);// EEE setting
++ phy_val |= (1 << 5);
++ mii_mgr_write(i, 26, phy_val);
++#else
++ //disable EEE
++ mii_mgr_write(i, 13, 0x7);
++ mii_mgr_write(i, 14, 0x3C);
++ mii_mgr_write(i, 13, 0x4007);
++ mii_mgr_write(i, 14, 0x0);
++#endif
++ mii_mgr_write(i, 30, 0xa000);
++ mii_mgr_write(i, 31, 0xa000); // change L2 page
++ mii_mgr_write(i, 16, 0x0606);
++ mii_mgr_write(i, 23, 0x0f0e);
++ mii_mgr_write(i, 24, 0x1610);
++ mii_mgr_write(i, 30, 0x1f15);
++ mii_mgr_write(i, 28, 0x6111);
++
++ mii_mgr_read(i, 4, &phy_val);
++ phy_val |= (1 << 10);
++ mii_mgr_write(i, 4, phy_val);
++ }
++
++ //100Base AOI setting
++ mii_mgr_write(0, 31, 0x5000); //change G5 page
++ mii_mgr_write(0, 19, 0x004a);
++ mii_mgr_write(0, 20, 0x015a);
++ mii_mgr_write(0, 21, 0x00ee);
++ mii_mgr_write(0, 22, 0x0033);
++ mii_mgr_write(0, 23, 0x020a);
++ mii_mgr_write(0, 24, 0x0000);
++ mii_mgr_write(0, 25, 0x024a);
++ mii_mgr_write(0, 26, 0x035a);
++ mii_mgr_write(0, 27, 0x02ee);
++ mii_mgr_write(0, 28, 0x0233);
++ mii_mgr_write(0, 29, 0x000a);
++ mii_mgr_write(0, 30, 0x0000);
++ /* Fix EPHY idle state abnormal behavior */
++ mii_mgr_write(0, 31, 0x4000); //change G4 page
++ mii_mgr_write(0, 29, 0x000d);
++ mii_mgr_write(0, 30, 0x0500);
++
++}
++
++#endif
++
++
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++void rt305x_esw_init(void)
++{
++ int i=0;
++ u32 phy_val=0, val=0;
++#if defined (CONFIG_RT3052_ASIC)
++ u32 phy_val2;
++#endif
++
++#if defined (CONFIG_RT5350_ASIC)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0168) = 0x17;
++#endif
++
++ /*
++ * FC_RLS_TH=200, FC_SET_TH=160
++ * DROP_RLS=120, DROP_SET_TH=80
++ */
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0008) = 0xC8A07850;
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00E4) = 0x00000000;
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0014) = 0x00405555;
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0050) = 0x00002001;
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0090) = 0x00007f7f;
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0098) = 0x00007f3f; //disable VLAN
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00CC) = 0x0002500c;
++#ifndef CONFIG_UNH_TEST
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x009C) = 0x0008a301; //hashing algorithm=XOR48, aging interval=300sec
++#else
++ /*
++ * bit[30]:1 Backoff Algorithm Option: The latest one to pass UNH test
++ * bit[29]:1 Length of Received Frame Check Enable
++ * bit[8]:0 Enable collision 16 packet abort and late collision abort
++ * bit[7:6]:01 Maximum Packet Length: 1518
++ */
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x009C) = 0x6008a241;
++#endif
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x008C) = 0x02404040;
++#if defined (CONFIG_RT3052_ASIC) || defined (CONFIG_RT3352_ASIC) || defined (CONFIG_RT5350_ASIC) || defined (CONFIG_MT7628_ASIC)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) = 0x3f502b28; //Change polling Ext PHY Addr=0x1F
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0084) = 0x00000000;
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0110) = 0x7d000000; //1us cycle number=125 (FE's clock=125Mhz)
++#elif defined (CONFIG_RT3052_FPGA) || defined (CONFIG_RT3352_FPGA) || defined (CONFIG_RT5350_FPGA) || defined (CONFIG_MT7628_FPGA)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) = 0x00f03ff9; //polling Ext PHY Addr=0x0, force port5 as 100F/D (disable auto-polling)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0084) = 0xffdf1f00;
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x0110) = 0x0d000000; //1us cycle number=13 (FE's clock=12.5Mhz)
++
++ /* In order to use 10M/Full on FPGA board. We configure phy capable to
++ * 10M Full/Half duplex, so we can use auto-negotiation on PC side */
++ for(i=0;i<5;i++){
++ mii_mgr_write(i, 4, 0x0461); //Capable of 10M Full/Half Duplex, flow control on/off
++ mii_mgr_write(i, 0, 0xB100); //reset all digital logic, except phy_reg
++ }
++#endif
++
++ /*
++ * set port 5 force to 1000M/Full when connecting to switch or iNIC
++ */
++#if defined (CONFIG_P5_RGMII_TO_MAC_MODE)
++ *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1<<29); //disable port 5 auto-polling
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) |= 0x3fff; //force 1000M full duplex
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(0xf<<20); //rxclk_skew, txclk_skew = 0
++#elif defined (CONFIG_P5_MII_TO_MAC_MODE)
++ *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1<<29); //disable port 5 auto-polling
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(0x3fff);
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) |= 0x3ffd; //force 100M full duplex
++
++#if defined (CONFIG_RALINK_RT3352)
++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=Mii Mode
++ *(unsigned long *)(SYSCFG1) |= (0x1 << 12);
++#endif
++
++#elif defined (CONFIG_P5_MAC_TO_PHY_MODE)
++ *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
++ *(unsigned long *)(0xb0000060) &= ~(1 << 7); //set MDIO to Normal mode
++#if defined (CONFIG_RT3052_ASIC) || defined (CONFIG_RT3352_ASIC)
++ enable_auto_negotiate(1);
++#endif
++ if (isMarvellGigaPHY(1)) {
++#if defined (CONFIG_RT3052_FPGA) || defined (CONFIG_RT3352_FPGA)
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, &phy_val);
++ phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, phy_val);
++#endif
++ printk("\n Reset MARVELL phy\n");
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, &phy_val);
++ phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, phy_val);
++
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
++ phy_val |= 1<<15; //PHY Software Reset
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
++ }
++ if (isVtssGigaPHY(1)) {
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0001); //extended page
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, &phy_val);
++ printk("Vitesse phy skew: %x --> ", phy_val);
++ phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
++ phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns
++ printk("%x\n", phy_val);
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, phy_val);
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0000); //main registers
++ }
++
++#elif defined (CONFIG_P5_RMII_TO_MAC_MODE)
++ *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1<<29); //disable port 5 auto-polling
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(0x3fff);
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) |= 0x3ffd; //force 100M full duplex
++
++#if defined (CONFIG_RALINK_RT3352)
++ *(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RvMii Mode
++ *(unsigned long *)(SYSCFG1) |= (0x2 << 12);
++#endif
++#else // Port 5 Disabled //
++
++#if defined (CONFIG_RALINK_RT3052)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1 << 29); //port5 auto polling disable
++ *(unsigned long *)(0xb0000060) |= (1 << 7); //set MDIO to GPIO mode (GPIO22-GPIO23)
++ *(unsigned long *)(0xb0000060) |= (1 << 9); //set RGMII to GPIO mode (GPIO41-GPIO50)
++ *(unsigned long *)(0xb0000674) = 0xFFF; //GPIO41-GPIO50 output mode
++ *(unsigned long *)(0xb000067C) = 0x0; //GPIO41-GPIO50 output low
++#elif defined (CONFIG_RALINK_RT3352)
++ *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1 << 29); //port5 auto polling disable
++ *(unsigned long *)(0xb0000060) |= (1 << 7); //set MDIO to GPIO mode (GPIO22-GPIO23)
++ *(unsigned long *)(0xb0000624) = 0xC0000000; //GPIO22-GPIO23 output mode
++ *(unsigned long *)(0xb000062C) = 0xC0000000; //GPIO22-GPIO23 output high
++
++ *(unsigned long *)(0xb0000060) |= (1 << 9); //set RGMII to GPIO mode (GPIO24-GPIO35)
++ *(unsigned long *)(0xb000064C) = 0xFFF; //GPIO24-GPIO35 output mode
++ *(unsigned long *)(0xb0000654) = 0xFFF; //GPIO24-GPIO35 output high
++#elif defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++ /* do nothing */
++#endif
++#endif // CONFIG_P5_RGMII_TO_MAC_MODE //
++
++
++#if defined (CONFIG_RT3052_ASIC)
++ rw_rf_reg(0, 0, &phy_val);
++ phy_val = phy_val >> 4;
++
++ if(phy_val > 0x5) {
++
++ rw_rf_reg(0, 26, &phy_val);
++ phy_val2 = (phy_val | (0x3 << 5));
++ rw_rf_reg(1, 26, &phy_val2);
++
++ // reset EPHY
++ val = sysRegRead(RSTCTRL);
++ val = val | RALINK_EPHY_RST;
++ sysRegWrite(RSTCTRL, val);
++ val = val & ~(RALINK_EPHY_RST);
++ sysRegWrite(RSTCTRL, val);
++
++ rw_rf_reg(1, 26, &phy_val);
++
++ //select local register
++ mii_mgr_write(0, 31, 0x8000);
++ for(i=0;i<5;i++){
++ mii_mgr_write(i, 26, 0x1600); //TX10 waveform coefficient //LSB=0 disable PHY
++ mii_mgr_write(i, 29, 0x7058); //TX100/TX10 AD/DA current bias
++ mii_mgr_write(i, 30, 0x0018); //TX100 slew rate control
++ }
++
++ //select global register
++ mii_mgr_write(0, 31, 0x0);
++ mii_mgr_write(0, 1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
++ mii_mgr_write(0, 2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
++ mii_mgr_write(0, 3, 0xa17f); //enlarge agcsel threshold 6
++//#define ENABLE_LDPS
++#if defined (ENABLE_LDPS)
++ mii_mgr_write(0, 12, 0x7eaa);
++ mii_mgr_write(0, 22, 0x252f); //tune TP_IDL tail and head waveform, enable power down slew rate control
++#else
++ mii_mgr_write(0, 12, 0x0);
++ mii_mgr_write(0, 22, 0x052f);
++#endif
++ mii_mgr_write(0, 14, 0x65); //longer TP_IDL tail length
++ mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
++ mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
++ mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
++ mii_mgr_write(0, 27, 0x2fce); //set PLL/Receive bias current are calibrated
++ mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
++ mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
++ mii_mgr_write(0, 31, 0x8000); //select local register
++
++ for(i=0;i<5;i++){
++ //LSB=1 enable PHY
++ mii_mgr_read(i, 26, &phy_val);
++ phy_val |= 0x0001;
++ mii_mgr_write(i, 26, phy_val);
++ }
++ } else {
++ //select local register
++ mii_mgr_write(0, 31, 0x8000);
++ for(i=0;i<5;i++){
++ mii_mgr_write(i, 26, 0x1600); //TX10 waveform coefficient //LSB=0 disable PHY
++ mii_mgr_write(i, 29, 0x7058); //TX100/TX10 AD/DA current bias
++ mii_mgr_write(i, 30, 0x0018); //TX100 slew rate control
++ }
++
++ //select global register
++ mii_mgr_write(0, 31, 0x0);
++ mii_mgr_write(0, 1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
++ mii_mgr_write(0, 2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
++ mii_mgr_write(0, 3, 0xa17f); //enlarge agcsel threshold 6
++ mii_mgr_write(0, 14, 0x65); //longer TP_IDL tail length
++ mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
++ mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
++ mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
++ mii_mgr_write(0, 22, 0x052f); //tune TP_IDL tail and head waveform
++ mii_mgr_write(0, 27, 0x2fce); //set PLL/Receive bias current are calibrated
++ mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
++ mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
++ mii_mgr_write(0, 31, 0x8000); //select local register
++
++ for(i=0;i<5;i++){
++ //LSB=1 enable PHY
++ mii_mgr_read(i, 26, &phy_val);
++ phy_val |= 0x0001;
++ mii_mgr_write(i, 26, phy_val);
++ }
++ }
++#elif defined (CONFIG_RT3352_ASIC)
++ //PHY IOT
++ // reset EPHY
++ val = sysRegRead(RSTCTRL);
++ val = val | RALINK_EPHY_RST;
++ sysRegWrite(RSTCTRL, val);
++ val = val & ~(RALINK_EPHY_RST);
++ sysRegWrite(RSTCTRL, val);
++
++ //select local register
++ mii_mgr_write(0, 31, 0x8000);
++ for(i=0;i<5;i++){
++ mii_mgr_write(i, 26, 0x1600); //TX10 waveform coefficient //LSB=0 disable PHY
++ mii_mgr_write(i, 29, 0x7016); //TX100/TX10 AD/DA current bias
++ mii_mgr_write(i, 30, 0x0038); //TX100 slew rate control
++ }
++
++ //select global register
++ mii_mgr_write(0, 31, 0x0);
++ mii_mgr_write(0, 1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
++ mii_mgr_write(0, 2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
++ mii_mgr_write(0, 3, 0xa17f); //enlarge agcsel threshold 6
++ mii_mgr_write(0, 12, 0x7eaa);
++ mii_mgr_write(0, 14, 0x65); //longer TP_IDL tail length
++ mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
++ mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
++ mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
++ mii_mgr_write(0, 22, 0x253f); //tune TP_IDL tail and head waveform, enable power down slew rate control
++ mii_mgr_write(0, 27, 0x2fda); //set PLL/Receive bias current are calibrated
++ mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
++ mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
++ mii_mgr_write(0, 31, 0x8000); //select local register
++
++ for(i=0;i<5;i++){
++ //LSB=1 enable PHY
++ mii_mgr_read(i, 26, &phy_val);
++ phy_val |= 0x0001;
++ mii_mgr_write(i, 26, phy_val);
++ }
++
++#elif defined (CONFIG_RT5350_ASIC)
++ //PHY IOT
++ // reset EPHY
++ val = sysRegRead(RSTCTRL);
++ val = val | RALINK_EPHY_RST;
++ sysRegWrite(RSTCTRL, val);
++ val = val & ~(RALINK_EPHY_RST);
++ sysRegWrite(RSTCTRL, val);
++
++ //select local register
++ mii_mgr_write(0, 31, 0x8000);
++ for(i=0;i<5;i++){
++ mii_mgr_write(i, 26, 0x1600); //TX10 waveform coefficient //LSB=0 disable PHY
++ mii_mgr_write(i, 29, 0x7015); //TX100/TX10 AD/DA current bias
++ mii_mgr_write(i, 30, 0x0038); //TX100 slew rate control
++ }
++
++ //select global register
++ mii_mgr_write(0, 31, 0x0);
++ mii_mgr_write(0, 1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
++ mii_mgr_write(0, 2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
++ mii_mgr_write(0, 3, 0xa17f); //enlarge agcsel threshold 6
++ mii_mgr_write(0, 12, 0x7eaa);
++ mii_mgr_write(0, 14, 0x65); //longer TP_IDL tail length
++ mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
++ mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
++ mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
++ mii_mgr_write(0, 22, 0x253f); //tune TP_IDL tail and head waveform, enable power down slew rate control
++ mii_mgr_write(0, 27, 0x2fda); //set PLL/Receive bias current are calibrated
++ mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
++ mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
++ mii_mgr_write(0, 31, 0x8000); //select local register
++
++ for(i=0;i<5;i++){
++ //LSB=1 enable PHY
++ mii_mgr_read(i, 26, &phy_val);
++ phy_val |= 0x0001;
++ mii_mgr_write(i, 26, phy_val);
++ }
++#elif defined (CONFIG_MT7628_ASIC)
++/*INIT MT7628 PHY HERE*/
++ val = sysRegRead(RT2880_AGPIOCFG_REG);
++#if defined (CONFIG_ETH_ONE_PORT_ONLY)
++ val |= (MT7628_P0_EPHY_AIO_EN | MT7628_P1_EPHY_AIO_EN | MT7628_P2_EPHY_AIO_EN | MT7628_P3_EPHY_AIO_EN | MT7628_P4_EPHY_AIO_EN);
++ val = val & ~(MT7628_P0_EPHY_AIO_EN);
++#else
++ val = val & ~(MT7628_P0_EPHY_AIO_EN | MT7628_P1_EPHY_AIO_EN | MT7628_P2_EPHY_AIO_EN | MT7628_P3_EPHY_AIO_EN | MT7628_P4_EPHY_AIO_EN);
++#endif
++ if ((*((volatile u32 *)(RALINK_SYSCTL_BASE + 0x8))) & 0x10000)
++ val &= ~0x1f0000;
++ sysRegWrite(RT2880_AGPIOCFG_REG, val);
++
++ val = sysRegRead(RSTCTRL);
++ val = val | RALINK_EPHY_RST;
++ sysRegWrite(RSTCTRL, val);
++ val = val & ~(RALINK_EPHY_RST);
++ sysRegWrite(RSTCTRL, val);
++
++
++ val = sysRegRead(RALINK_SYSCTL_BASE + 0x64);
++#if defined (CONFIG_ETH_ONE_PORT_ONLY)
++ val &= 0xf003f003;
++ val |= 0x05540554;
++ sysRegWrite(RALINK_SYSCTL_BASE + 0x64, val); // set P0 EPHY LED mode
++#else
++ val &= 0xf003f003;
++ sysRegWrite(RALINK_SYSCTL_BASE + 0x64, val); // set P0~P4 EPHY LED mode
++#endif
++
++ udelay(5000);
++ mt7628_ephy_init();
++
++#endif
++}
++#endif
++
++#if defined (CONFIG_ARCH_MT7623) /* TODO: just for bring up, should be removed!!! */
++void mt7623_pinmux_set(void)
++{
++ unsigned long regValue;
++
++ //printk("[mt7623_pinmux_set]start\n");
++ /* Pin277: ESW_RST (1) */
++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ad0));
++ regValue &= ~(BITS(6,8));
++ regValue |= BIT(6);
++ *(volatile u_long *)(0xf0005ad0) = regValue;
++
++ /* Pin262: G2_TXEN (1) */
++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005aa0));
++ regValue &= ~(BITS(6,8));
++ regValue |= BIT(6);
++ *(volatile u_long *)(0xf0005aa0) = regValue;
++ /* Pin263: G2_TXD3 (1) */
++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005aa0));
++ regValue &= ~(BITS(9,11));
++ regValue |= BIT(9);
++ *(volatile u_long *)(0xf0005aa0) = regValue;
++ /* Pin264: G2_TXD2 (1) */
++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005aa0));
++ regValue &= ~(BITS(12,14));
++ regValue |= BIT(12);
++ *(volatile u_long *)(0xf0005aa0) = regValue;
++ /* Pin265: G2_TXD1 (1) */
++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ab0));
++ regValue &= ~(BITS(0,2));
++ regValue |= BIT(0);
++ *(volatile u_long *)(0xf0005ab0) = regValue;
++ /* Pin266: G2_TXD0 (1) */
++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ab0));
++ regValue &= ~(BITS(3,5));
++ regValue |= BIT(3);
++ *(volatile u_long *)(0xf0005ab0) = regValue;
++ /* Pin267: G2_TXC (1) */
++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ab0));
++ regValue &= ~(BITS(6,8));
++ regValue |= BIT(6);
++ *(volatile u_long *)(0xf0005ab0) = regValue;
++ /* Pin268: G2_RXC (1) */
++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ab0));
++ regValue &= ~(BITS(9,11));
++ regValue |= BIT(9);
++ *(volatile u_long *)(0xf0005ab0) = regValue;
++ /* Pin269: G2_RXD0 (1) */
++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ab0));
++ regValue &= ~(BITS(12,14));
++ regValue |= BIT(12);
++ *(volatile u_long *)(0xf0005ab0) = regValue;
++ /* Pin270: G2_RXD1 (1) */
++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ac0));
++ regValue &= ~(BITS(0,2));
++ regValue |= BIT(0);
++ *(volatile u_long *)(0xf0005ac0) = regValue;
++ /* Pin271: G2_RXD2 (1) */
++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ac0));
++ regValue &= ~(BITS(3,5));
++ regValue |= BIT(3);
++ *(volatile u_long *)(0xf0005ac0) = regValue;
++ /* Pin272: G2_RXD3 (1) */
++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ac0));
++ regValue &= ~(BITS(6,8));
++ regValue |= BIT(6);
++ *(volatile u_long *)(0xf0005ac0) = regValue;
++ /* Pin274: G2_RXDV (1) */
++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ac0));
++ regValue &= ~(BITS(12,14));
++ regValue |= BIT(12);
++ *(volatile u_long *)(0xf0005ac0) = regValue;
++
++ /* Pin275: MDC (1) */
++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ad0));
++ regValue &= ~(BITS(0,2));
++ regValue |= BIT(0);
++ *(volatile u_long *)(0xf0005ad0) = regValue;
++ /* Pin276: MDIO (1) */
++ regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ad0));
++ regValue &= ~(BITS(3,5));
++ regValue |= BIT(3);
++ *(volatile u_long *)(0xf0005ad0) = regValue;
++ //printk("[mt7623_pinmux_set]end\n");
++}
++
++void wait_loop(void) {
++ int i,j;
++ int read_data;
++ j =0;
++ while (j< 10) {
++ for(i = 0; i<32; i = i+1){
++ read_data = *(volatile u_long *)(0xFB110610);
++ }
++ j++;
++ }
++}
++
++void trgmii_calibration_7623(void) {
++
++ unsigned int tap_a[5]; // minumum delay for all correct
++ unsigned int tap_b[5]; // maximum delay for all correct
++ unsigned int final_tap[5];
++ unsigned int bslip_en;
++ unsigned int rxc_step_size;
++ unsigned int rxd_step_size;
++ unsigned int read_data;
++ unsigned int tmp;
++ unsigned int rd_wd;
++ int i;
++ unsigned int err_cnt[5];
++ unsigned int init_toggle_data;
++ unsigned int err_flag[5];
++ unsigned int err_total_flag;
++ unsigned int training_word;
++ unsigned int rd_tap;
++
++ u32 TRGMII_7623_base;
++ u32 TRGMII_7623_RD_0;
++ u32 TRGMII_RD_1;
++ u32 TRGMII_RD_2;
++ u32 TRGMII_RD_3;
++ u32 TRGMII_RXCTL;
++ u32 TRGMII_RCK_CTRL;
++ u32 TRGMII_7530_base;
++ TRGMII_7623_base = 0xFB110300;
++ TRGMII_7623_RD_0 = TRGMII_7623_base + 0x10;
++ TRGMII_RCK_CTRL = TRGMII_7623_base;
++ rxd_step_size =0x1;
++ rxc_step_size =0x4;
++ init_toggle_data = 0x00000055;
++ training_word = 0x000000AC;
++
++ //printk("Calibration begin ........");
++ *(volatile u_long *)(TRGMII_7623_base +0x04) &= 0x3fffffff; // RX clock gating in MT7623
++ *(volatile u_long *)(TRGMII_7623_base +0x00) |= 0x80000000; // Assert RX reset in MT7623
++ *(volatile u_long *)(TRGMII_7623_base +0x78) |= 0x00002000; // Set TX OE edge in MT7623
++ *(volatile u_long *)(TRGMII_7623_base +0x04) |= 0xC0000000; // Disable RX clock gating in MT7623
++ *(volatile u_long *)(TRGMII_7623_base ) &= 0x7fffffff; // Release RX reset in MT7623
++ //printk("Check Point 1 .....\n");
++ for (i = 0 ; i<5 ; i++) {
++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) |= 0x80000000; // Set bslip_en = 1
++ }
++
++ //printk("Enable Training Mode in MT7530\n");
++ mii_mgr_read(0x1F,0x7A40,&read_data);
++ read_data |= 0xc0000000;
++ mii_mgr_write(0x1F,0x7A40,read_data); //Enable Training Mode in MT7530
++ err_total_flag = 0;
++ //printk("Adjust RXC delay in MT7623\n");
++ read_data =0x0;
++ while (err_total_flag == 0 && read_data != 0x68) {
++ //printk("2nd Enable EDGE CHK in MT7623\n");
++ /* Enable EDGE CHK in MT7623*/
++ for (i = 0 ; i<5 ; i++) {
++ tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8);
++ tmp |= 0x40000000;
++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff;
++ }
++ wait_loop();
++ err_total_flag = 1;
++ for (i = 0 ; i<5 ; i++) {
++ err_cnt[i] = ((*(volatile u_long *)(TRGMII_7623_RD_0 + i*8)) >> 8) & 0x0000000f;
++ rd_wd = ((*(volatile u_long *)(TRGMII_7623_RD_0 + i*8)) >> 16) & 0x000000ff;
++ //printk("ERR_CNT = %d, RD_WD =%x\n",err_cnt[i],rd_wd);
++ if ( err_cnt[i] !=0 ) {
++ err_flag[i] = 1;
++ }
++ else if (rd_wd != 0x55) {
++ err_flag[i] = 1;
++ }
++ else {
++ err_flag[i] = 0;
++ }
++ err_total_flag = err_flag[i] & err_total_flag;
++ }
++
++ //printk("2nd Disable EDGE CHK in MT7623\n");
++ /* Disable EDGE CHK in MT7623*/
++ for (i = 0 ; i<5 ; i++) {
++ tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8);
++ tmp |= 0x40000000;
++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff;
++ }
++ wait_loop();
++ //printk("2nd Disable EDGE CHK in MT7623\n");
++ /* Adjust RXC delay */
++ *(volatile u_long *)(TRGMII_7623_base +0x00) |= 0x80000000; // Assert RX reset in MT7623
++ *(volatile u_long *)(TRGMII_7623_base +0x04) &= 0x3fffffff; // RX clock gating in MT7623
++ read_data = *(volatile u_long *)(TRGMII_7623_base);
++ if (err_total_flag == 0) {
++ tmp = (read_data & 0x0000007f) + rxc_step_size;
++ //printk(" RXC delay = %d\n", tmp);
++ read_data >>= 8;
++ read_data &= 0xffffff80;
++ read_data |= tmp;
++ read_data <<=8;
++ read_data &= 0xffffff80;
++ read_data |=tmp;
++ *(volatile u_long *)(TRGMII_7623_base) = read_data;
++ }
++ read_data &=0x000000ff;
++ *(volatile u_long *)(TRGMII_7623_base ) &= 0x7fffffff; // Release RX reset in MT7623
++ *(volatile u_long *)(TRGMII_7623_base +0x04) |= 0xC0000000; // Disable RX clock gating in MT7623
++ for (i = 0 ; i<5 ; i++) {
++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = (*(volatile u_long *)(TRGMII_7623_RD_0 + i*8)) | 0x80000000; // Set bslip_en = ~bit_slip_en
++ }
++ }
++ //printk("Finish RXC Adjustment while loop\n");
++ //printk("Read RD_WD MT7623\n");
++ /* Read RD_WD MT7623*/
++ for (i = 0 ; i<5 ; i++) {
++ rd_tap=0;
++ while (err_flag[i] != 0) {
++ /* Enable EDGE CHK in MT7623*/
++ tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8);
++ tmp |= 0x40000000;
++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff;
++ wait_loop();
++ read_data = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8);
++ err_cnt[i] = (read_data >> 8) & 0x0000000f; // Read MT7623 Errcnt
++ rd_wd = (read_data >> 16) & 0x000000ff;
++ if (err_cnt[i] != 0 || rd_wd !=0x55){
++ err_flag [i] = 1;
++ }
++ else {
++ err_flag[i] =0;
++ }
++ /* Disable EDGE CHK in MT7623*/
++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) &= 0x4fffffff;
++ tmp |= 0x40000000;
++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff;
++ wait_loop();
++ //err_cnt[i] = ((read_data) >> 8) & 0x0000000f; // Read MT7623 Errcnt
++ if (err_flag[i] !=0) {
++ rd_tap = (read_data & 0x0000007f) + rxd_step_size; // Add RXD delay in MT7623
++ read_data = (read_data & 0xffffff80) | rd_tap;
++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = read_data;
++ tap_a[i] = rd_tap;
++ } else {
++ rd_tap = (read_data & 0x0000007f) + 4;
++ read_data = (read_data & 0xffffff80) | rd_tap;
++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = read_data;
++ }
++ //err_cnt[i] = (*(volatile u_long *)(TRGMII_7623_RD_0 + i*8) >> 8) & 0x0000000f; // Read MT7623 Errcnt
++
++ }
++ //printk("%dth bit Tap_a = %d\n", i, tap_a[i]);
++ }
++ //printk("Last While Loop\n");
++ for (i = 0 ; i<5 ; i++) {
++ //printk(" Bit%d\n", i);
++ rd_tap =0;
++ while ((err_cnt[i] == 0) && (rd_tap !=128)) {
++ read_data = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8);
++ rd_tap = (read_data & 0x0000007f) + rxd_step_size; // Add RXD delay in MT7623
++ read_data = (read_data & 0xffffff80) | rd_tap;
++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = read_data;
++ /* Enable EDGE CHK in MT7623*/
++ tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8);
++ tmp |= 0x40000000;
++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff;
++ wait_loop();
++ err_cnt[i] = ((*(volatile u_long *)(TRGMII_7623_RD_0 + i*8)) >> 8) & 0x0000000f; // Read MT7623 Errcnt
++ /* Disable EDGE CHK in MT7623*/
++ tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8);
++ tmp |= 0x40000000;
++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff;
++ wait_loop();
++ //err_cnt[i] = ((*(volatile u_long *)(TRGMII_7623_RD_0 + i*8)) >> 8) & 0x0000000f; // Read MT7623 Errcnt
++
++ }
++ tap_b[i] = rd_tap;// -rxd_step_size; // Record the max delay TAP_B
++ //printk("tap_b[%d] is %d \n", i,tap_b[i]);
++ final_tap[i] = (tap_a[i]+tap_b[i])/2; // Calculate RXD delay = (TAP_A + TAP_B)/2
++ //printk("%dth bit Final Tap = %d\n", i, final_tap[i]);
++ read_data = (read_data & 0xffffff80) | final_tap[i];
++ *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = read_data;
++ }
++// /*word alignment*/
++// mii_mgr_read(0x1F,0x7A50,&read_data);
++// read_data &= ~(0xff);
++// read_data |= 0xac;
++// mii_mgr_write(0x1F,0x7A50,read_data);
++// while (i <10) {
++// i++;
++// wait_loop();
++// }
++// /* Enable EDGE CHK in MT7623*/
++// for (i=0; i<5; i++) {
++// tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8);
++// tmp |= 0x40000000;
++// *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff;
++// wait_loop();
++// /* Disable EDGE CHK in MT7623*/
++// tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8);
++// tmp |= 0x40000000;
++// *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff;
++// wait_loop();
++// read_data = *(volatile u_long *)(TRGMII_7623_RD_0+i*8);
++// printk(" MT7623 training word = %x\n", read_data);
++// }
++
++
++ mii_mgr_read(0x1F,0x7A40,&read_data);
++ //printk(" MT7530 0x7A40 = %x\n", read_data);
++ read_data &=0x3fffffff;
++ mii_mgr_write(0x1F,0x7A40,read_data);
++}
++
++
++void trgmii_calibration_7530(void){
++
++ unsigned int tap_a[5];
++ unsigned int tap_b[5];
++ unsigned int final_tap[5];
++ unsigned int bslip_en;
++ unsigned int rxc_step_size;
++ unsigned int rxd_step_size;
++ unsigned int read_data;
++ unsigned int tmp;
++ int i,j;
++ unsigned int err_cnt[5];
++ unsigned int rd_wd;
++ unsigned int init_toggle_data;
++ unsigned int err_flag[5];
++ unsigned int err_total_flag;
++ unsigned int training_word;
++ unsigned int rd_tap;
++
++ u32 TRGMII_7623_base;
++ u32 TRGMII_7530_RD_0;
++ u32 TRGMII_RD_1;
++ u32 TRGMII_RD_2;
++ u32 TRGMII_RD_3;
++ u32 TRGMII_RXCTL;
++ u32 TRGMII_RCK_CTRL;
++ u32 TRGMII_7530_base;
++ u32 TRGMII_7530_TX_base;
++ TRGMII_7623_base = 0xFB110300;
++ TRGMII_7530_base = 0x7A00;
++ TRGMII_7530_RD_0 = TRGMII_7530_base + 0x10;
++ TRGMII_RCK_CTRL = TRGMII_7623_base;
++ rxd_step_size = 0x1;
++ rxc_step_size = 0x8;
++ init_toggle_data = 0x00000055;
++ training_word = 0x000000AC;
++
++ TRGMII_7530_TX_base = TRGMII_7530_base + 0x50;
++
++ //printk("Calibration begin ........\n");
++ *(volatile u_long *)(TRGMII_7623_base + 0x40) |= 0x80000000;
++ mii_mgr_read(0x1F, 0x7a10, &read_data);
++ //printk("TRGMII_7530_RD_0 is %x\n", read_data);
++
++ mii_mgr_read(0x1F,TRGMII_7530_base+0x04,&read_data);
++ read_data &= 0x3fffffff;
++ mii_mgr_write(0x1F,TRGMII_7530_base+0x04,read_data); // RX clock gating in MT7530
++
++ mii_mgr_read(0x1F,TRGMII_7530_base+0x78,&read_data);
++ read_data |= 0x00002000;
++ mii_mgr_write(0x1F,TRGMII_7530_base+0x78,read_data); // Set TX OE edge in MT7530
++
++ mii_mgr_read(0x1F,TRGMII_7530_base,&read_data);
++ read_data |= 0x80000000;
++ mii_mgr_write(0x1F,TRGMII_7530_base,read_data); // Assert RX reset in MT7530
++
++
++ mii_mgr_read(0x1F,TRGMII_7530_base,&read_data);
++ read_data &= 0x7fffffff;
++ mii_mgr_write(0x1F,TRGMII_7530_base,read_data); // Release RX reset in MT7530
++
++ mii_mgr_read(0x1F,TRGMII_7530_base+0x04,&read_data);
++ read_data |= 0xC0000000;
++ mii_mgr_write(0x1F,TRGMII_7530_base+0x04,read_data); // Disable RX clock gating in MT7530
++
++ //printk("Enable Training Mode in MT7623\n");
++ /*Enable Training Mode in MT7623*/
++ *(volatile u_long *)(TRGMII_7623_base + 0x40) &= 0xbfffffff;
++ *(volatile u_long *)(TRGMII_7623_base + 0x40) |= 0x80000000;
++ *(volatile u_long *)(TRGMII_7623_base + 0x78) &= 0xfffff0ff;
++ *(volatile u_long *)(TRGMII_7623_base + 0x78) |= 0x00000400;
++
++ err_total_flag =0;
++ //printk("Adjust RXC delay in MT7530\n");
++ read_data =0x0;
++ while (err_total_flag == 0 && (read_data != 0x68)) {
++ //printk("2nd Enable EDGE CHK in MT7530\n");
++ /* Enable EDGE CHK in MT7530*/
++ for (i = 0 ; i<5 ; i++) {
++ mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&read_data);
++ read_data |= 0x40000000;
++ read_data &= 0x4fffffff;
++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++ wait_loop();
++ //printk("2nd Disable EDGE CHK in MT7530\n");
++ mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&err_cnt[i]);
++ //printk("***** MT7530 %dth bit ERR_CNT =%x\n",i, err_cnt[i]);
++ //printk("MT7530 %dth bit ERR_CNT =%x\n",i, err_cnt[i]);
++ err_cnt[i] >>= 8;
++ err_cnt[i] &= 0x0000ff0f;
++ rd_wd = err_cnt[i] >> 8;
++ rd_wd &= 0x000000ff;
++ err_cnt[i] &= 0x0000000f;
++ //mii_mgr_read(0x1F,0x7a10,&read_data);
++ if ( err_cnt[i] !=0 ) {
++ err_flag[i] = 1;
++ }
++ else if (rd_wd != 0x55) {
++ err_flag[i] = 1;
++ } else {
++ err_flag[i] = 0;
++ }
++ if (i==0) {
++ err_total_flag = err_flag[i];
++ } else {
++ err_total_flag = err_flag[i] & err_total_flag;
++ }
++ /* Disable EDGE CHK in MT7530*/
++ mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&read_data);
++ read_data |= 0x40000000;
++ read_data &= 0x4fffffff;
++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++ wait_loop();
++ }
++ /*Adjust RXC delay*/
++ if (err_total_flag ==0) {
++ mii_mgr_read(0x1F,TRGMII_7530_base,&read_data);
++ read_data |= 0x80000000;
++ mii_mgr_write(0x1F,TRGMII_7530_base,read_data); // Assert RX reset in MT7530
++
++ mii_mgr_read(0x1F,TRGMII_7530_base+0x04,&read_data);
++ read_data &= 0x3fffffff;
++ mii_mgr_write(0x1F,TRGMII_7530_base+0x04,read_data); // RX clock gating in MT7530
++
++ mii_mgr_read(0x1F,TRGMII_7530_base,&read_data);
++ tmp = read_data;
++ tmp &= 0x0000007f;
++ tmp += rxc_step_size;
++ //printk("Current rxc delay = %d\n", tmp);
++ read_data &= 0xffffff80;
++ read_data |= tmp;
++ mii_mgr_write (0x1F,TRGMII_7530_base,read_data);
++ mii_mgr_read(0x1F,TRGMII_7530_base,&read_data);
++ //printk("Current RXC delay = %x\n", read_data);
++
++ mii_mgr_read(0x1F,TRGMII_7530_base,&read_data);
++ read_data &= 0x7fffffff;
++ mii_mgr_write(0x1F,TRGMII_7530_base,read_data); // Release RX reset in MT7530
++
++ mii_mgr_read(0x1F,TRGMII_7530_base+0x04,&read_data);
++ read_data |= 0xc0000000;
++ mii_mgr_write(0x1F,TRGMII_7530_base+0x04,read_data); // Disable RX clock gating in MT7530
++ }
++ read_data = tmp;
++ }
++ //printk("RXC delay is %d\n", tmp);
++ //printk("Finish RXC Adjustment while loop\n");
++
++ //printk("Read RD_WD MT7530\n");
++ /* Read RD_WD MT7530*/
++ for (i = 0 ; i<5 ; i++) {
++ rd_tap = 0;
++ while (err_flag[i] != 0) {
++ /* Enable EDGE CHK in MT7530*/
++ mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&read_data);
++ read_data |= 0x40000000;
++ read_data &= 0x4fffffff;
++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++ wait_loop();
++ err_cnt[i] = (read_data >> 8) & 0x0000000f;
++ rd_wd = (read_data >> 16) & 0x000000ff;
++ //printk("##### %dth bit ERR_CNT = %x RD_WD =%x ######\n", i, err_cnt[i],rd_wd);
++ if (err_cnt[i] != 0 || rd_wd !=0x55){
++ err_flag [i] = 1;
++ }
++ else {
++ err_flag[i] =0;
++ }
++ if (err_flag[i] !=0 ) {
++ rd_tap = (read_data & 0x0000007f) + rxd_step_size; // Add RXD delay in MT7530
++ read_data = (read_data & 0xffffff80) | rd_tap;
++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++ tap_a[i] = rd_tap;
++ } else {
++ tap_a[i] = (read_data & 0x0000007f); // Record the min delay TAP_A
++ rd_tap = tap_a[i] + 0x4;
++ read_data = (read_data & 0xffffff80) | rd_tap ;
++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++ }
++
++ /* Disable EDGE CHK in MT7530*/
++ mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&read_data);
++ read_data |= 0x40000000;
++ read_data &= 0x4fffffff;
++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++ wait_loop();
++
++ }
++ //printk("%dth bit Tap_a = %d\n", i, tap_a[i]);
++ }
++ //printk("Last While Loop\n");
++ for (i = 0 ; i<5 ; i++) {
++ rd_tap =0;
++ while (err_cnt[i] == 0 && (rd_tap!=128)) {
++ /* Enable EDGE CHK in MT7530*/
++ mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&read_data);
++ read_data |= 0x40000000;
++ read_data &= 0x4fffffff;
++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++ wait_loop();
++ err_cnt[i] = (read_data >> 8) & 0x0000000f;
++ //rd_tap = (read_data & 0x0000007f) + 0x4; // Add RXD delay in MT7530
++ if (err_cnt[i] == 0 && (rd_tap!=128)) {
++ rd_tap = (read_data & 0x0000007f) + rxd_step_size; // Add RXD delay in MT7530
++ read_data = (read_data & 0xffffff80) | rd_tap;
++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++ }
++ /* Disable EDGE CHK in MT7530*/
++ mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&read_data);
++ read_data |= 0x40000000;
++ read_data &= 0x4fffffff;
++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++ wait_loop();
++ }
++ tap_b[i] = rd_tap;// - rxd_step_size; // Record the max delay TAP_B
++ //printk("%dth bit Tap_b = %d, ERR_CNT=%d\n", i, tap_b[i],err_cnt[i]);
++ final_tap[i] = (tap_a[i]+tap_b[i])/2; // Calculate RXD delay = (TAP_A + TAP_B)/2
++ //printk("%dth bit Final Tap = %d\n", i, final_tap[i]);
++
++ read_data = ( read_data & 0xffffff80) | final_tap[i];
++ mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++ }
++ *(volatile u_long *)(TRGMII_7623_base + 0x40) &=0x3fffffff;
++
++}
++
++void set_trgmii_325_delay_setting(void)
++{
++ /*mt7530 side*/
++ *(volatile u_long *)(0xfb110300) = 0x80020050;
++ *(volatile u_long *)(0xfb110304) = 0x00980000;
++ *(volatile u_long *)(0xfb110300) = 0x40020050;
++ *(volatile u_long *)(0xfb110304) = 0xc0980000;
++ *(volatile u_long *)(0xfb110310) = 0x00000028;
++ *(volatile u_long *)(0xfb110318) = 0x0000002e;
++ *(volatile u_long *)(0xfb110320) = 0x0000002d;
++ *(volatile u_long *)(0xfb110328) = 0x0000002b;
++ *(volatile u_long *)(0xfb110330) = 0x0000002a;
++ *(volatile u_long *)(0xfb110340) = 0x00020000;
++ /*mt7530 side*/
++ mii_mgr_write(31, 0x7a00, 0x10);
++ mii_mgr_write(31, 0x7a10, 0x23);
++ mii_mgr_write(31, 0x7a18, 0x27);
++ mii_mgr_write(31, 0x7a20, 0x24);
++ mii_mgr_write(31, 0x7a28, 0x29);
++ mii_mgr_write(31, 0x7a30, 0x24);
++
++}
++
++
++void setup_internal_gsw(void)
++{
++ u32 i;
++ u32 regValue;
++ u32 xtal_mode;
++
++ mt7623_pinmux_set(); /* TODO: just for bring up, should be removed!!! */
++
++#if 0
++ /* GE1: RGMII mode setting */
++ *(volatile u_long *)(0xfb110300) = 0x80020000;
++ *(volatile u_long *)(0xfb110304) = 0x00980000;
++ *(volatile u_long *)(0xfb110300) = 0x40020000;
++ *(volatile u_long *)(0xfb110304) = 0xc0980000;
++ *(volatile u_long *)(0xfb110310) = 0x00000041;
++ *(volatile u_long *)(0xfb110318) = 0x00000044;
++ *(volatile u_long *)(0xfb110320) = 0x00000043;
++ *(volatile u_long *)(0xfb110328) = 0x00000042;
++ *(volatile u_long *)(0xfb110330) = 0x00000042;
++ *(volatile u_long *)(0xfb110340) = 0x00020000;
++ *(volatile u_long *)(0xfb110390) &= 0xfffffff8; //RGMII mode
++#else
++ /* GE1: TRGMII mode setting */
++ *(volatile u_long *)(0xfb110390) |= 0x00000002; //TRGMII mode
++#endif
++
++ /*Todo: Hardware reset Switch*/
++ /*Hardware reset Switch*/
++#if defined(CONFIG_ARCH_MT7623)
++ regValue = *(volatile u_long *)(0xfb00000c);
++ /*MT7530 Reset. Flows for MT7623 and MT7683 are both excuted.*/
++ /* Should Modify this section if EFUSE is ready*/
++ /*For MT7683 reset MT7530*/
++ if(!(regValue & (1<<16)))
++ {
++ *(volatile u_long *)(0xf0005520) &= ~(1<<1);
++ udelay(1000);
++ *(volatile u_long *)(0xf0005520) |= (1<<1);
++ mdelay(100);
++ }
++ //printk("Assert MT7623 RXC reset\n");
++ *(volatile u_long *)(0xfb110300) |= 0x80000000; // Assert MT7623 RXC reset
++ /*For MT7623 reset MT7530*/
++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x34) |= (0x1 << 2);
++ udelay(1000);
++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x34) &= ~(0x1 << 2);
++ mdelay(100);
++#endif
++
++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600)
++ for(i=0;i<=4;i++)
++ {
++ //turn off PHY
++ mii_mgr_read(i, 0x0 ,&regValue);
++ regValue |= (0x1<<11);
++ mii_mgr_write(i, 0x0, regValue);
++ }
++ mii_mgr_write(31, 0x7000, 0x3); //reset switch
++ udelay(100);
++
++#if defined (CONFIG_MT7621_ASIC) || defined (CONFIG_ARCH_MT7623)
++#if 0
++ if((sysRegRead(0xbe00000c)&0xFFFF)==0x0101) {
++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2105e30b);//(GE1, Force 1000M/FD, FC ON)
++ mii_mgr_write(31, 0x3600, 0x5e30b);
++ } else
++#endif
++ {
++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2105e33b);//(GE1, Force 1000M/FD, FC ON)
++ mii_mgr_write(31, 0x3600, 0x5e33b);
++ mii_mgr_read(31, 0x3600 ,&regValue);
++ }
++#endif
++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x00008000);//(GE2, Link down)
++#endif
++
++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600)
++ //regValue = 0x117ccf; //Enable Port 6, P5 as GMAC5, P5 disable*/
++ mii_mgr_read(31, 0x7804 ,&regValue);
++ regValue &= ~(1<<8); //Enable Port 6
++ regValue |= (1<<6); //Disable Port 5
++ regValue |= (1<<13); //Port 5 as GMAC, no Internal PHY
++
++#if defined (CONFIG_RAETH_GMAC2)
++ //RGMII2=Normal mode
++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15);
++
++ //GMAC2= RGMII mode
++ *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14);
++ mii_mgr_write(31, 0x3500, 0x56300); //MT7530 P5 AN, we can ignore this setting??????
++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x21056300);//(GE2, auto-polling)
++ enable_auto_negotiate(0);//set polling address
++
++ /* set MT7530 Port 5 to PHY 0/4 mode */
++#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN)
++ regValue &= ~((1<<13)|(1<<6));
++ regValue |= ((1<<7)|(1<<16)|(1<<20));
++#elif defined (CONFIG_GE_RGMII_INTERNAL_P4_AN)
++ regValue &= ~((1<<13)|(1<<6)|(1<<20));
++ regValue |= ((1<<7)|(1<<16));
++#endif
++ /*Set MT7530 phy direct access mode**/
++ regValue &= ~(1<<5);
++
++ //sysRegWrite(GDMA2_FWD_CFG, 0x20710000);
++#endif
++ regValue |= (1<<16);//change HW-TRAP
++ printk("change HW-TRAP to 0x%x\n",regValue);
++ mii_mgr_write(31, 0x7804 ,regValue);
++#endif
++ mii_mgr_read(31, 0x7800, &regValue);
++ regValue = (regValue >> 9) & 0x3;
++ if(regValue == 0x3)//25Mhz Xtal
++ xtal_mode = 1;
++ else if(regValue == 0x2) //40Mhz
++ xtal_mode = 2;
++ else
++ xtal_mode = 3;
++
++ if(xtal_mode == 1) { //25Mhz Xtal
++ /* do nothing */
++ } else if(xtal_mode = 2) { //40Mhz
++ mii_mgr_write(0, 13, 0x1f); // disable MT7530 core clock
++ mii_mgr_write(0, 14, 0x410);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0x0);
++
++ mii_mgr_write(0, 13, 0x1f); // disable MT7530 PLL
++ mii_mgr_write(0, 14, 0x40d);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0x2020);
++
++ mii_mgr_write(0, 13, 0x1f); // for MT7530 core clock = 500Mhz
++ mii_mgr_write(0, 14, 0x40e);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0x119);
++
++ mii_mgr_write(0, 13, 0x1f); // enable MT7530 PLL
++ mii_mgr_write(0, 14, 0x40d);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0x2820);
++
++ udelay(20); //suggest by CD
++
++ mii_mgr_write(0, 13, 0x1f); // enable MT7530 core clock
++ mii_mgr_write(0, 14, 0x410);
++ mii_mgr_write(0, 13, 0x401f);
++ }else {//20MHz
++ /*TODO*/
++ }
++
++#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC)
++ mii_mgr_write(0, 14, 0x3); /*TRGMII*/
++#else
++ mii_mgr_write(0, 14, 0x1); /*RGMII*/
++/* set MT7530 central align */
++ mii_mgr_read(31, 0x7830, &regValue);
++ regValue &= ~1;
++ regValue |= 1<<1;
++ mii_mgr_write(31, 0x7830, regValue);
++
++ mii_mgr_read(31, 0x7a40, &regValue);
++ regValue &= ~(1<<30);
++ mii_mgr_write(31, 0x7a40, regValue);
++
++ regValue = 0x855;
++ mii_mgr_write(31, 0x7a78, regValue);
++
++#endif
++ mii_mgr_write(31, 0x7b00, 0x104); //delay setting for 10/1000M
++ mii_mgr_write(31, 0x7b04, 0x10); //delay setting for 10/1000M
++
++ /*Tx Driving*/
++ mii_mgr_write(31, 0x7a54, 0x88); //lower GE1 driving
++ mii_mgr_write(31, 0x7a5c, 0x88); //lower GE1 driving
++ mii_mgr_write(31, 0x7a64, 0x88); //lower GE1 driving
++ mii_mgr_write(31, 0x7a6c, 0x88); //lower GE1 driving
++ mii_mgr_write(31, 0x7a74, 0x88); //lower GE1 driving
++ mii_mgr_write(31, 0x7a7c, 0x88); //lower GE1 driving
++ mii_mgr_write(31, 0x7810, 0x11); //lower GE2 driving
++ /*Set MT7623/MT7683 TX Driving*/
++ *(volatile u_long *)(0xfb110354) = 0x88;
++ *(volatile u_long *)(0xfb11035c) = 0x88;
++ *(volatile u_long *)(0xfb110364) = 0x88;
++ *(volatile u_long *)(0xfb11036c) = 0x88;
++ *(volatile u_long *)(0xfb110374) = 0x88;
++ *(volatile u_long *)(0xfb11037c) = 0x88;
++#if defined (CONFIG_GE2_RGMII_AN)
++ *(volatile u_long *)(0xf0005f00) = 0xe00; //Set GE2 driving and slew rate
++#else
++ *(volatile u_long *)(0xf0005f00) = 0xa00; //Set GE2 driving and slew rate
++#endif
++ *(volatile u_long *)(0xf00054c0) = 0x5; //set GE2 TDSEL
++ *(volatile u_long *)(0xf0005ed0) = 0; //set GE2 TUNE
++
++ /* TRGMII Clock */
++// printk("Set TRGMII mode clock stage 1\n");
++ mii_mgr_write(0, 13, 0x1f);
++ mii_mgr_write(0, 14, 0x404);
++ mii_mgr_write(0, 13, 0x401f);
++ if (xtal_mode == 1){ //25MHz
++#if defined (CONFIG_GE1_TRGMII_FORCE_2900)
++ mii_mgr_write(0, 14, 0x1d00); // 362.5MHz
++#elif defined (CONFIG_GE1_TRGMII_FORCE_2600)
++ mii_mgr_write(0, 14, 0x1a00); // 325MHz
++#elif defined (CONFIG_GE1_TRGMII_FORCE_2000)
++ mii_mgr_write(0, 14, 0x1400); //250MHz
++#elif defined (CONFIG_GE1_RGMII_FORCE_1000)
++ mii_mgr_write(0, 14, 0x00a0); //125MHz
++#endif
++ }else if(xtal_mode == 2){//40MHz
++#if defined (CONFIG_GE1_TRGMII_FORCE_2900)
++ mii_mgr_write(0, 14, 0x1220); // 362.5MHz
++#elif defined (CONFIG_GE1_TRGMII_FORCE_2600)
++ mii_mgr_write(0, 14, 0x1040); // 325MHz
++#elif defined (CONFIG_GE1_TRGMII_FORCE_2000)
++ mii_mgr_write(0, 14, 0x0c80); //250MHz
++#elif defined (CONFIG_GE1_RGMII_FORCE_1000)
++ mii_mgr_write(0, 14, 0x0640); //125MHz
++#endif
++ }
++// printk("Set TRGMII mode clock stage 2\n");
++ mii_mgr_write(0, 13, 0x1f);
++ mii_mgr_write(0, 14, 0x405);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0x0);
++
++// printk("Set TRGMII mode clock stage 3\n");
++ mii_mgr_write(0, 13, 0x1f);
++ mii_mgr_write(0, 14, 0x409);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0x0087);
++
++// printk("Set TRGMII mode clock stage 4\n");
++ mii_mgr_write(0, 13, 0x1f);
++ mii_mgr_write(0, 14, 0x40a);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0x0087);
++
++// printk("Set TRGMII mode clock stage 5\n");
++ mii_mgr_write(0, 13, 0x1f);
++ mii_mgr_write(0, 14, 0x403);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0x1800);
++
++// printk("Set TRGMII mode clock stage 6\n");
++ mii_mgr_write(0, 13, 0x1f);
++ mii_mgr_write(0, 14, 0x403);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0x1c00);
++
++// printk("Set TRGMII mode clock stage 7\n");
++ mii_mgr_write(0, 13, 0x1f);
++ mii_mgr_write(0, 14, 0x401);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0xc020);
++
++// printk("Set TRGMII mode clock stage 8\n");
++ mii_mgr_write(0, 13, 0x1f);
++ mii_mgr_write(0, 14, 0x406);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0xa030);
++
++// printk("Set TRGMII mode clock stage 9\n");
++ mii_mgr_write(0, 13, 0x1f);
++ mii_mgr_write(0, 14, 0x406);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0xa038);
++
++ udelay(120); // for MT7623 bring up test
++
++// printk("Set TRGMII mode clock stage 10\n");
++ mii_mgr_write(0, 13, 0x1f);
++ mii_mgr_write(0, 14, 0x410);
++ mii_mgr_write(0, 13, 0x401f);
++ mii_mgr_write(0, 14, 0x3);
++
++// printk("Set TRGMII mode clock stage 11\n");
++
++ mii_mgr_read(31, 0x7830 ,&regValue);
++ regValue &=0xFFFFFFFC;
++ regValue |=0x00000001;
++ mii_mgr_write(31, 0x7830, regValue);
++
++// printk("Set TRGMII mode clock stage 12\n");
++ mii_mgr_read(31, 0x7a40 ,&regValue);
++ regValue &= ~(0x1<<30);
++ regValue &= ~(0x1<<28);
++ mii_mgr_write(31, 0x7a40, regValue);
++
++ //mii_mgr_write(31, 0x7a78, 0x855);
++ mii_mgr_write(31, 0x7a78, 0x55);
++// printk(" Adjust MT7530 TXC delay\n");
++ udelay(100); // for mt7623 bring up test
++
++// printk(" Release MT7623 RXC Reset\n");
++ *(volatile u_long *)(0xfb110300) &= 0x7fffffff; // Release MT7623 RXC reset
++ //disable EEE
++ for(i=0;i<=4;i++)
++ {
++ mii_mgr_write(i, 13, 0x7);
++ mii_mgr_write(i, 14, 0x3C);
++ mii_mgr_write(i, 13, 0x4007);
++ mii_mgr_write(i, 14, 0x0);
++ }
++
++ //Disable EEE 10Base-Te:
++ for(i=0;i<=4;i++)
++ {
++ mii_mgr_write(i, 13, 0x1f);
++ mii_mgr_write(i, 14, 0x027b);
++ mii_mgr_write(i, 13, 0x401f);
++ mii_mgr_write(i, 14, 0x1177);
++ }
++
++ for(i=0;i<=4;i++)
++ {
++ //turn on PHY
++ mii_mgr_read(i, 0x0 ,&regValue);
++ regValue &= ~(0x1<<11);
++ mii_mgr_write(i, 0x0, regValue);
++ }
++
++ for(i=0;i<=4;i++) {
++ mii_mgr_read(i, 4, &regValue);
++ regValue |= (3<<7); //turn on 100Base-T Advertisement
++ mii_mgr_write(i, 4, regValue);
++
++ mii_mgr_read(i, 9, &regValue);
++ regValue |= (3<<8); //turn on 1000Base-T Advertisement
++ mii_mgr_write(i, 9, regValue);
++
++ //restart AN
++ mii_mgr_read(i, 0, &regValue);
++ regValue |= (1 << 9);
++ mii_mgr_write(i, 0, regValue);
++ }
++
++ mii_mgr_read(31, 0x7808 ,&regValue);
++ regValue |= (3<<16); //Enable INTR
++ mii_mgr_write(31, 0x7808 ,regValue);
++}
++
++void mt7623_ethifsys_init(void)
++{
++#define TRGPLL_CON0 (0xF0209280)
++#define TRGPLL_CON1 (0xF0209284)
++#define TRGPLL_CON2 (0xF0209288)
++#define TRGPLL_PWR_CON0 (0xF020928C)
++#define ETHPLL_CON0 (0xF0209290)
++#define ETHPLL_CON1 (0xF0209294)
++#define ETHPLL_CON2 (0xF0209298)
++#define ETHPLL_PWR_CON0 (0xF020929C)
++#define ETH_PWR_CON (0xF00062A0)
++#define HIF_PWR_CON (0xF00062A4)
++
++ u32 temp, pwr_ack_status;
++ /*=========================================================================*/
++ /* Enable ETHPLL & TRGPLL*/
++ /*=========================================================================*/
++ /* xPLL PWR ON*/
++ temp = sysRegRead(ETHPLL_PWR_CON0);
++ sysRegWrite(ETHPLL_PWR_CON0, temp | 0x1);
++
++ temp = sysRegRead(TRGPLL_PWR_CON0);
++ sysRegWrite(TRGPLL_PWR_CON0, temp | 0x1);
++
++ udelay(5); /* wait for xPLL_PWR_ON ready (min delay is 1us)*/
++
++ /* xPLL ISO Disable*/
++ temp = sysRegRead(ETHPLL_PWR_CON0);
++ sysRegWrite(ETHPLL_PWR_CON0, temp & ~0x2);
++
++ temp = sysRegRead(TRGPLL_PWR_CON0);
++ sysRegWrite(TRGPLL_PWR_CON0, temp & ~0x2);
++
++ /* xPLL Frequency Set*/
++ temp = sysRegRead(ETHPLL_CON0);
++ sysRegWrite(ETHPLL_CON0, temp | 0x1);
++#if defined (CONFIG_GE1_TRGMII_FORCE_2900)
++ temp = sysRegRead(TRGPLL_CON0);
++ sysRegWrite(TRGPLL_CON0, temp | 0x1);
++#elif defined (CONFIG_GE1_TRGMII_FORCE_2600)
++ sysRegWrite(TRGPLL_CON1, 0xB2000000);
++ temp = sysRegRead(TRGPLL_CON0);
++ sysRegWrite(TRGPLL_CON0, temp | 0x1);
++#elif defined (CONFIG_GE1_TRGMII_FORCE_2000)
++ sysRegWrite(TRGPLL_CON1, 0xCCEC4EC5);
++ sysRegWrite(TRGPLL_CON0, 0x121);
++#endif
++ udelay(40); /* wait for PLL stable (min delay is 20us)*/
++
++
++ /*=========================================================================*/
++ /* Power on ETHDMASYS and HIFSYS*/
++ /*=========================================================================*/
++ /* Power on ETHDMASYS*/
++ sysRegWrite(0xF0006000, 0x0b160001);
++ pwr_ack_status = (sysRegRead(ETH_PWR_CON) & 0x0000f000) >> 12;
++
++ if(pwr_ack_status == 0x0) {
++ printk("ETH already turn on and power on flow will be skipped...\n");
++ }else {
++ temp = sysRegRead(ETH_PWR_CON) ;
++ sysRegWrite(ETH_PWR_CON, temp | 0x4); /* PWR_ON*/
++ temp = sysRegRead(ETH_PWR_CON) ;
++ sysRegWrite(ETH_PWR_CON, temp | 0x8); /* PWR_ON_S*/
++
++ udelay(5); /* wait power settle time (min delay is 1us)*/
++
++ temp = sysRegRead(ETH_PWR_CON) ;
++ sysRegWrite(ETH_PWR_CON, temp & ~0x10); /* PWR_CLK_DIS*/
++ temp = sysRegRead(ETH_PWR_CON) ;
++ sysRegWrite(ETH_PWR_CON, temp & ~0x2); /* PWR_ISO*/
++ temp = sysRegRead(ETH_PWR_CON) ;
++ sysRegWrite(ETH_PWR_CON, temp & ~0x100); /* SRAM_PDN 0*/
++ temp = sysRegRead(ETH_PWR_CON) ;
++ sysRegWrite(ETH_PWR_CON, temp & ~0x200); /* SRAM_PDN 1*/
++ temp = sysRegRead(ETH_PWR_CON) ;
++ sysRegWrite(ETH_PWR_CON, temp & ~0x400); /* SRAM_PDN 2*/
++ temp = sysRegRead(ETH_PWR_CON) ;
++ sysRegWrite(ETH_PWR_CON, temp & ~0x800); /* SRAM_PDN 3*/
++
++ udelay(5); /* wait SRAM settle time (min delay is 1Us)*/
++
++ temp = sysRegRead(ETH_PWR_CON) ;
++ sysRegWrite(ETH_PWR_CON, temp | 0x1); /* PWR_RST_B*/
++ }
++
++ /* Power on HIFSYS*/
++ pwr_ack_status = (sysRegRead(HIF_PWR_CON) & 0x0000f000) >> 12;
++ if(pwr_ack_status == 0x0) {
++ printk("HIF already turn on and power on flow will be skipped...\n");
++ }
++ else {
++ temp = sysRegRead(HIF_PWR_CON) ;
++ sysRegWrite(HIF_PWR_CON, temp | 0x4); /* PWR_ON*/
++ temp = sysRegRead(HIF_PWR_CON) ;
++ sysRegWrite(HIF_PWR_CON, temp | 0x8); /* PWR_ON_S*/
++
++ udelay(5); /* wait power settle time (min delay is 1us)*/
++
++ temp = sysRegRead(HIF_PWR_CON) ;
++ sysRegWrite(HIF_PWR_CON, temp & ~0x10); /* PWR_CLK_DIS*/
++ temp = sysRegRead(HIF_PWR_CON) ;
++ sysRegWrite(HIF_PWR_CON, temp & ~0x2); /* PWR_ISO*/
++ temp = sysRegRead(HIF_PWR_CON) ;
++ sysRegWrite(HIF_PWR_CON, temp & ~0x100); /* SRAM_PDN 0*/
++ temp = sysRegRead(HIF_PWR_CON) ;
++ sysRegWrite(HIF_PWR_CON, temp & ~0x200); /* SRAM_PDN 1*/
++ temp = sysRegRead(HIF_PWR_CON) ;
++ sysRegWrite(HIF_PWR_CON, temp & ~0x400); /* SRAM_PDN 2*/
++ temp = sysRegRead(HIF_PWR_CON) ;
++ sysRegWrite(HIF_PWR_CON, temp & ~0x800); /* SRAM_PDN 3*/
++
++ udelay(5); /* wait SRAM settle time (min delay is 1Us)*/
++
++ temp = sysRegRead(HIF_PWR_CON) ;
++ sysRegWrite(HIF_PWR_CON, temp | 0x1); /* PWR_RST_B*/
++ }
++
++ /* Release mt7530 reset */
++ temp = le32_to_cpu(*(volatile u_long *)(0xfb000034));
++ temp &= ~(BIT(2));
++ *(volatile u_long *)(0xfb000034) = temp;
++}
++#endif
++
++/**
++ * ra2882eth_init - Module Init code
++ *
++ * Called by kernel to register net_device
++ *
++ */
++
++static int fe_probe(struct platform_device *pdev)
++{
++ int ret;
++ struct net_device *dev = alloc_etherdev(sizeof(END_DEVICE));
++
++ fe_irq = platform_get_irq(pdev, 0);
++
++#ifdef CONFIG_RALINK_VISTA_BASIC
++ int sw_id=0;
++ mii_mgr_read(29, 31, &sw_id);
++ is_switch_175c = (sw_id == 0x175c) ? 1:0;
++#endif
++
++ if (!dev)
++ return -ENOMEM;
++
++ strcpy(dev->name, DEV_NAME);
++ printk("%s:%s[%d]%d\n", __FILE__, __func__, __LINE__, fe_irq);
++ dev->irq = fe_irq;
++ dev->addr_len = 6;
++ dev->base_addr = RALINK_FRAME_ENGINE_BASE;
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ rather_probe(dev);
++#else
++ dev->init = rather_probe;
++#endif
++ ra2880_setup_dev_fptable(dev);
++
++ /* net_device structure Init */
++ ethtool_init(dev);
++ printk("Ralink APSoC Ethernet Driver Initilization. %s %d rx/tx descriptors allocated, mtu = %d!\n", RAETH_VERSION, NUM_RX_DESC, dev->mtu);
++#ifdef CONFIG_RAETH_NAPI
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ printk("NAPI enable, Tx Ring = %d, Rx Ring = %d\n", NUM_TX_DESC, NUM_RX_DESC);
++#else
++ printk("NAPI enable, weight = %d, Tx Ring = %d, Rx Ring = %d\n", dev->weight, NUM_TX_DESC, NUM_RX_DESC);
++#endif
++#endif
++
++ /* Register net device for the driver */
++ if ( register_netdev(dev) != 0) {
++ printk(KERN_WARNING " " __FILE__ ": No ethernet port found.\n");
++ return -ENXIO;
++ }
++
++
++#ifdef CONFIG_RAETH_NETLINK
++ csr_netlink_init();
++#endif
++ ret = debug_proc_init();
++
++ dev_raether = dev;
++#ifdef CONFIG_ARCH_MT7623
++ mt7623_ethifsys_init();
++#endif
++ return ret;
++}
++
++
++
++
++
++
++
++void fe_sw_init(void)
++{
++#if defined (CONFIG_GIGAPHY) || defined (CONFIG_RAETH_ROUTER) || defined (CONFIG_100PHY)
++ unsigned int regValue = 0;
++#endif
++
++ // Case1: RT288x/RT3883/MT7621 GE1 + GigaPhy
++#if defined (CONFIG_GE1_RGMII_AN)
++ enable_auto_negotiate(1);
++ if (isMarvellGigaPHY(1)) {
++#if defined (CONFIG_RT3883_FPGA)
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, &regValue);
++ regValue &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, regValue);
++
++ printk("\n Reset MARVELL phy\n");
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, &regValue);
++ regValue |= 1<<7; //Add delay to RX_CLK for RXD Outputs
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, regValue);
++
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &regValue);
++ regValue |= 1<<15; //PHY Software Reset
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, regValue);
++#elif defined (CONFIG_MT7621_FPGA) || defined (CONFIG_MT7623_FPGA)
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, &regValue);
++ regValue &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, regValue);
++
++ /*10Mbps, debug*/
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, 0x461);
++
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &regValue);
++ regValue |= 1<<9; //restart AN
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, regValue);
++#endif
++
++ }
++ if (isVtssGigaPHY(1)) {
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 1);
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, &regValue);
++ printk("Vitesse phy skew: %x --> ", regValue);
++ regValue |= (0x3<<12);
++ regValue &= ~(0x3<<14);
++ printk("%x\n", regValue);
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, regValue);
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0);
++ }
++#if defined (CONFIG_RALINK_MT7621)
++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x21056300);//(P0, Auto mode)
++#endif
++#endif // CONFIG_GE1_RGMII_AN //
++
++ // Case2: RT3883/MT7621 GE2 + GigaPhy
++#if defined (CONFIG_GE2_RGMII_AN)
++ enable_auto_negotiate(2);
++ if (isMarvellGigaPHY(2)) {
++#if defined (CONFIG_RT3883_FPGA)
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, &regValue);
++ regValue &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, regValue);
++
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, &regValue);
++ regValue |= 1<<7; //Add delay to RX_CLK for RXD Outputs
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, regValue);
++
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, &regValue);
++ regValue |= 1<<15; //PHY Software Reset
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, regValue);
++#elif defined (CONFIG_MT7621_FPGA) || defined (CONFIG_MT7623_FPGA)
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, &regValue);
++ regValue &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, regValue);
++
++ /*10Mbps, debug*/
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 4, 0x461);
++
++
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, &regValue);
++ regValue |= 1<<9; //restart AN
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, regValue);
++#endif
++
++ }
++ if (isVtssGigaPHY(2)) {
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 1);
++ mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, &regValue);
++ printk("Vitesse phy skew: %x --> ", regValue);
++ regValue |= (0x3<<12);
++ regValue &= ~(0x3<<14);
++ printk("%x\n", regValue);
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, regValue);
++ mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 0);
++ }
++#if defined (CONFIG_RALINK_MT7621)
++ //RGMII2=Normal mode
++ *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15);
++ //GMAC2= RGMII mode
++ *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14);
++
++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x21056300);//(P1, Auto mode)
++#endif
++#endif // CONFIG_GE2_RGMII_AN //
++
++ // Case3: RT305x/RT335x/RT6855/RT6855A/MT7620 + EmbeddedSW
++#if defined (CONFIG_RT_3052_ESW) && !defined(CONFIG_RALINK_MT7621) && !defined(CONFIG_ARCH_MT7623)
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_MT7620)
++ rt_gsw_init();
++#elif defined(CONFIG_RALINK_RT6855A)
++ rt6855A_gsw_init();
++#else
++ rt305x_esw_init();
++#endif
++#endif
++ // Case4: RT288x/RT388x/MT7621 GE1 + Internal GigaSW
++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600)
++#if defined (CONFIG_RALINK_MT7621)
++ setup_internal_gsw();
++ /*MT7530 Init*/
++#elif defined (CONFIG_ARCH_MT7623)
++#if defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600)
++ *(volatile u_long *)(0xfb00002c) |= (1<<11);
++#else
++ *(volatile u_long *)(0xfb00002c) &= ~(1<<11);
++#endif
++ setup_internal_gsw();
++ trgmii_calibration_7623();
++ trgmii_calibration_7530();
++ //*(volatile u_long *)(0xfb110300) |= (0x1f << 24); //Just only for 312.5/325MHz
++ *(volatile u_long *)(0xfb110340) = 0x00020000;
++ *(volatile u_long *)(0xfb110304) &= 0x3fffffff; // RX clock gating in MT7623
++ *(volatile u_long *)(0xfb110300) |= 0x80000000; // Assert RX reset in MT7623
++ *(volatile u_long *)(0xfb110300 ) &= 0x7fffffff; // Release RX reset in MT7623
++ *(volatile u_long *)(0xfb110300 +0x04) |= 0xC0000000; // Disable RX clock gating in MT7623
++/*GE1@125MHz(RGMII mode) TX delay adjustment*/
++#if defined (CONFIG_GE1_RGMII_FORCE_1000)
++ *(volatile u_long *)(0xfb110350) = 0x55;
++ *(volatile u_long *)(0xfb110358) = 0x55;
++ *(volatile u_long *)(0xfb110360) = 0x55;
++ *(volatile u_long *)(0xfb110368) = 0x55;
++ *(volatile u_long *)(0xfb110370) = 0x55;
++ *(volatile u_long *)(0xfb110378) = 0x855;
++#endif
++
++
++#elif defined (CONFIG_MT7623_FPGA) /* Nelson: remove for bring up, should be added!!! */
++ setup_fpga_gsw();
++#else
++ sysRegWrite(MDIO_CFG, INIT_VALUE_OF_FORCE_1000_FD);
++#endif
++#endif
++
++ // Case5: RT388x/MT7621 GE2 + GigaSW
++#if defined (CONFIG_GE2_RGMII_FORCE_1000)
++#if defined (CONFIG_RALINK_MT7621)
++ setup_external_gsw();
++#else
++ sysRegWrite(MDIO_CFG2, INIT_VALUE_OF_FORCE_1000_FD);
++#endif
++#endif
++
++ // Case6: RT288x GE1 /RT388x,MT7621 GE1/GE2 + (10/100 Switch or 100PHY)
++#if defined (CONFIG_RAETH_ROUTER) || defined (CONFIG_100PHY)
++
++ //set GMAC to MII or RvMII mode
++#if defined (CONFIG_RALINK_RT3883)
++ regValue = sysRegRead(SYSCFG1);
++#if defined (CONFIG_GE1_MII_FORCE_100) || defined (CONFIG_GE1_MII_AN)
++ regValue &= ~(0x3 << 12);
++ regValue |= 0x1 << 12; // GE1 MII Mode
++#elif defined (CONFIG_GE1_RVMII_FORCE_100)
++ regValue &= ~(0x3 << 12);
++ regValue |= 0x2 << 12; // GE1 RvMII Mode
++#endif
++
++#if defined (CONFIG_GE2_MII_FORCE_100) || defined (CONFIG_GE2_MII_AN)
++ regValue &= ~(0x3 << 14);
++ regValue |= 0x1 << 14; // GE2 MII Mode
++#elif defined (CONFIG_GE2_RVMII_FORCE_100)
++ regValue &= ~(0x3 << 14);
++ regValue |= 0x2 << 14; // GE2 RvMII Mode
++#endif
++ sysRegWrite(SYSCFG1, regValue);
++#endif // CONFIG_RALINK_RT3883 //
++
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++
++#if defined (CONFIG_GE1_MII_FORCE_100)
++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x5e337);//(P0, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
++#endif
++#if defined (CONFIG_GE2_MII_FORCE_100)
++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x5e337);//(P1, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
++#endif
++#if defined (CONFIG_GE1_MII_AN) || defined (CONFIG_GE1_RGMII_AN)
++ enable_auto_negotiate(1);
++#if defined (CONFIG_RALINK_MT7621)
++ sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x21056300);//(P0, Auto mode)
++#endif
++#endif
++#if defined (CONFIG_GE2_MII_AN) || defined (CONFIG_GE1_RGMII_AN)
++ enable_auto_negotiate(2);
++#if defined (CONFIG_RALINK_MT7621)
++ sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x21056300);//(P1, Auto mode)
++#endif
++#endif
++
++#else
++#if defined (CONFIG_GE1_MII_FORCE_100)
++#if defined (CONFIG_RALINK_MT7621)
++#else
++ sysRegWrite(MDIO_CFG, INIT_VALUE_OF_FORCE_100_FD);
++#endif
++#endif
++#if defined (CONFIG_GE2_MII_FORCE_100)
++#if defined (CONFIG_RALINK_MT7621)
++#else
++ sysRegWrite(MDIO_CFG2, INIT_VALUE_OF_FORCE_100_FD);
++#endif
++#endif
++ //add switch configuration here for other switch chips.
++#if defined (CONFIG_GE1_MII_FORCE_100) || defined (CONFIG_GE2_MII_FORCE_100)
++ // IC+ 175x: force IC+ switch cpu port is 100/FD
++ mii_mgr_write(29, 22, 0x8420);
++#endif
++
++
++#endif // defined (CONFIG_RAETH_ROUTER) || defined (CONFIG_100PHY) //
++
++}
++
++
++/**
++ * ra2882eth_cleanup_module - Module Exit code
++ *
++ * Cmd 'rmmod' will invode the routine to exit the module
++ *
++ */
++#if 0
++ void ra2882eth_cleanup_module(void)
++{
++ struct net_device *dev = dev_raether;
++ END_DEVICE *ei_local;
++
++ ei_local = netdev_priv(dev);
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++ unregister_netdev(ei_local->PseudoDev);
++ free_netdev(ei_local->PseudoDev);
++#endif
++ unregister_netdev(dev);
++ RAETH_PRINT("Free ei_local and unregister netdev...\n");
++
++ free_netdev(dev);
++ debug_proc_exit();
++#ifdef CONFIG_RAETH_NETLINK
++ csr_netlink_end();
++#endif
++}
++#endif
++EXPORT_SYMBOL(set_fe_dma_glo_cfg);
++//module_init(ra2882eth_init);
++//module_exit(ra2882eth_cleanup_module);
++
++const struct of_device_id of_fe_match[] = {
++ { .compatible = "mediatek,mt7623-net", },
++ {},
++};
++
++MODULE_DEVICE_TABLE(of, of_fe_match);
++
++static struct platform_driver fe_driver = {
++ .probe = fe_probe,
++// .remove = ra2882eth_cleanup_module,
++ .driver = {
++ .name = "ralink_soc_eth",
++ .owner = THIS_MODULE,
++ .of_match_table = of_fe_match,
++ },
++};
++
++static int __init init_rtfe(void)
++{
++ int ret;
++ ret = platform_driver_register(&fe_driver);
++ return ret;
++}
++
++static void __exit exit_rtfe(void)
++{
++ platform_driver_unregister(&fe_driver);
++}
++
++module_init(init_rtfe);
++module_exit(exit_rtfe);
++
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/net/ethernet/raeth/raether.h b/drivers/net/ethernet/raeth/raether.h
+new file mode 100644
+index 0000000..7a97109
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/raether.h
+@@ -0,0 +1,126 @@
++#ifndef RA2882ETHEND_H
++#define RA2882ETHEND_H
++
++#ifdef DSP_VIA_NONCACHEABLE
++#define ESRAM_BASE 0xa0800000 /* 0x0080-0000 ~ 0x00807FFF */
++#else
++#define ESRAM_BASE 0x80800000 /* 0x0080-0000 ~ 0x00807FFF */
++#endif
++
++#define RX_RING_BASE ((int)(ESRAM_BASE + 0x7000))
++#define TX_RING_BASE ((int)(ESRAM_BASE + 0x7800))
++
++#if defined(CONFIG_RALINK_RT2880)
++#define NUM_TX_RINGS 1
++#else
++#define NUM_TX_RINGS 4
++#endif
++#ifdef MEMORY_OPTIMIZATION
++#ifdef CONFIG_RAETH_ROUTER
++#define NUM_RX_DESC 32 //128
++#define NUM_TX_DESC 32 //128
++#elif CONFIG_RT_3052_ESW
++#define NUM_RX_DESC 16 //64
++#define NUM_TX_DESC 16 //64
++#else
++#define NUM_RX_DESC 32 //128
++#define NUM_TX_DESC 32 //128
++#endif
++//#define NUM_RX_MAX_PROCESS 32
++#define NUM_RX_MAX_PROCESS 32
++#else
++#if defined (CONFIG_RAETH_ROUTER)
++#define NUM_RX_DESC 256
++#define NUM_TX_DESC 256
++#elif defined (CONFIG_RT_3052_ESW)
++#if defined (CONFIG_RALINK_MT7621)
++#define NUM_RX_DESC 512
++#define NUM_QRX_DESC 16
++#define NUM_TX_DESC 512
++#else
++#define NUM_RX_DESC 256
++#define NUM_QRX_DESC NUM_RX_DESC
++#define NUM_TX_DESC 256
++#endif
++#else
++#define NUM_RX_DESC 256
++#define NUM_QRX_DESC NUM_RX_DESC
++#define NUM_TX_DESC 256
++#endif
++#if defined(CONFIG_RALINK_RT3883) || defined(CONFIG_RALINK_MT7620)
++#define NUM_RX_MAX_PROCESS 2
++#else
++#define NUM_RX_MAX_PROCESS 16
++#endif
++#endif
++#define NUM_LRO_RX_DESC 16
++
++#if defined (CONFIG_SUPPORT_OPENWRT)
++#define DEV_NAME "eth0"
++#define DEV2_NAME "eth1"
++#else
++#define DEV_NAME "eth2"
++#define DEV2_NAME "eth3"
++#endif
++
++#if defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7621)
++#define GMAC0_OFFSET 0xE000
++#define GMAC2_OFFSET 0xE006
++#else
++#define GMAC0_OFFSET 0x28
++#define GMAC2_OFFSET 0x22
++#endif
++
++#if defined(CONFIG_RALINK_RT6855A)
++#define IRQ_ENET0 22
++#elif defined(CONFIG_ARCH_MT7623)
++#define IRQ_ENET0 232
++#else
++#define IRQ_ENET0 3 /* hardware interrupt #3, defined in RT2880 Soc Design Spec Rev 0.03, pp43 */
++#endif
++
++#if defined (CONFIG_RAETH_HW_LRO)
++#define HW_LRO_TIMER_UNIT 1
++#define HW_LRO_REFRESH_TIME 50000
++#define HW_LRO_MAX_AGG_CNT 64
++#define HW_LRO_AGG_DELTA 1
++#if defined(CONFIG_RAETH_PDMA_DVT)
++#define MAX_LRO_RX_LENGTH 10240
++#else
++#define MAX_LRO_RX_LENGTH (PAGE_SIZE - SKB_DATA_ALIGN(NET_SKB_PAD + sizeof(struct skb_shared_info)))
++#endif
++#define HW_LRO_AGG_TIME 10 /* 200us */
++#define HW_LRO_AGE_TIME 50
++#define HW_LRO_BW_THRE 3000
++#define HW_LRO_PKT_INT_ALPHA 100
++#endif /* CONFIG_RAETH_HW_LRO */
++#define FE_INT_STATUS_REG (*(volatile unsigned long *)(FE_INT_STATUS))
++#define FE_INT_STATUS_CLEAN(reg) (*(volatile unsigned long *)(FE_INT_STATUS)) = reg
++
++//#define RAETH_DEBUG
++#ifdef RAETH_DEBUG
++#define RAETH_PRINT(fmt, args...) printk(KERN_INFO fmt, ## args)
++#else
++#define RAETH_PRINT(fmt, args...) { }
++#endif
++
++struct net_device_stats *ra_get_stats(struct net_device *dev);
++
++void ei_tx_timeout(struct net_device *dev);
++int rather_probe(struct net_device *dev);
++int ei_open(struct net_device *dev);
++int ei_close(struct net_device *dev);
++
++int ra2882eth_init(void);
++void ra2882eth_cleanup_module(void);
++
++void ei_xmit_housekeeping(unsigned long data);
++
++u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data);
++u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data);
++u32 mii_mgr_cl45_set_address(u32 port_num, u32 dev_addr, u32 reg_addr);
++u32 mii_mgr_read_cl45(u32 port_num, u32 dev_addr, u32 reg_addr, u32 *read_data);
++u32 mii_mgr_write_cl45(u32 port_num, u32 dev_addr, u32 reg_addr, u32 write_data);
++void fe_sw_init(void);
++
++#endif
+diff --git a/drivers/net/ethernet/raeth/raether_hwlro.c b/drivers/net/ethernet/raeth/raether_hwlro.c
+new file mode 100755
+index 0000000..5fc4f36
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/raether_hwlro.c
+@@ -0,0 +1,347 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <linux/if_vlan.h>
++#include <linux/if_ether.h>
++#include <linux/fs.h>
++#include <asm/uaccess.h>
++#include <asm/rt2880/surfboardint.h>
++#include <linux/delay.h>
++#include <linux/sched.h>
++#include <asm/rt2880/rt_mmap.h>
++#include "ra2882ethreg.h"
++#include "raether.h"
++#include "ra_mac.h"
++#include "ra_ioctl.h"
++#include "ra_rfrw.h"
++
++#if defined(CONFIG_RAETH_HW_LRO_FORCE)
++int set_fe_lro_ring1_cfg(struct net_device *dev)
++{
++ unsigned int ip;
++
++ netdev_printk(KERN_CRIT, dev, "set_fe_lro_ring1_cfg()\n");
++
++ /* 1. Set RX ring mode to force port */
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_FORCE_PORT);
++
++ /* 2. Configure lro ring */
++ /* 2.1 set src/destination TCP ports */
++ SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING1, 1122);
++ SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING1, 3344);
++ /* 2.2 set src/destination IPs */
++ str_to_ip(&ip, "10.10.10.3");
++ sysRegWrite(LRO_RX_RING1_SIP_DW0, ip);
++ str_to_ip(&ip, "10.10.10.254");
++ sysRegWrite(LRO_RX_RING1_DIP_DW0, ip);
++ /* 2.3 IPv4 force port mode */
++ SET_PDMA_RXRING_IPV4_FORCE_MODE(ADMA_RX_RING1, 1);
++ /* 2.4 IPv6 force port mode */
++ SET_PDMA_RXRING_IPV6_FORCE_MODE(ADMA_RX_RING1, 1);
++
++ /* 3. Set Age timer: 10 msec. */
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, HW_LRO_AGE_TIME);
++
++ /* 4. Valid LRO ring */
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1);
++
++ return 0;
++}
++
++int set_fe_lro_ring2_cfg(struct net_device *dev)
++{
++ unsigned int ip;
++
++ netdev_printk(KERN_CRIT, dev, "set_fe_lro_ring2_cfg()\n");
++
++ /* 1. Set RX ring mode to force port */
++ SET_PDMA_RXRING2_MODE(PDMA_RX_FORCE_PORT);
++
++ /* 2. Configure lro ring */
++ /* 2.1 set src/destination TCP ports */
++ SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING2, 5566);
++ SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING2, 7788);
++ /* 2.2 set src/destination IPs */
++ str_to_ip(&ip, "10.10.10.3");
++ sysRegWrite(LRO_RX_RING2_SIP_DW0, ip);
++ str_to_ip(&ip, "10.10.10.254");
++ sysRegWrite(LRO_RX_RING2_DIP_DW0, ip);
++ /* 2.3 IPv4 force port mode */
++ SET_PDMA_RXRING_IPV4_FORCE_MODE(ADMA_RX_RING2, 1);
++ /* 2.4 IPv6 force port mode */
++ SET_PDMA_RXRING_IPV6_FORCE_MODE(ADMA_RX_RING2, 1);
++
++ /* 3. Set Age timer: 10 msec. */
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, HW_LRO_AGE_TIME);
++
++ /* 4. Valid LRO ring */
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 1);
++
++ return 0;
++}
++
++int set_fe_lro_ring3_cfg(struct net_device *dev)
++{
++ unsigned int ip;
++
++ netdev_printk(KERN_CRIT, dev, "set_fe_lro_ring3_cfg()\n");
++
++ /* 1. Set RX ring mode to force port */
++ SET_PDMA_RXRING3_MODE(PDMA_RX_FORCE_PORT);
++
++ /* 2. Configure lro ring */
++ /* 2.1 set src/destination TCP ports */
++ SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING3, 9900);
++ SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING3, 99);
++ /* 2.2 set src/destination IPs */
++ str_to_ip(&ip, "10.10.10.3");
++ sysRegWrite(LRO_RX_RING3_SIP_DW0, ip);
++ str_to_ip(&ip, "10.10.10.254");
++ sysRegWrite(LRO_RX_RING3_DIP_DW0, ip);
++ /* 2.3 IPv4 force port mode */
++ SET_PDMA_RXRING_IPV4_FORCE_MODE(ADMA_RX_RING3, 1);
++ /* 2.4 IPv6 force port mode */
++ SET_PDMA_RXRING_IPV6_FORCE_MODE(ADMA_RX_RING3, 1);
++
++ /* 3. Set Age timer: 10 msec. */
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, HW_LRO_AGE_TIME);
++
++ /* 4. Valid LRO ring */
++ SET_PDMA_RXRING3_VALID(1);
++
++ return 0;
++}
++
++int set_fe_lro_glo_cfg(struct net_device *dev)
++{
++ unsigned int regVal = 0;
++
++ netdev_printk(KERN_CRIT, dev, "set_fe_lro_glo_cfg()\n");
++
++ /* 1 Set max AGG timer: 10 msec. */
++ SET_PDMA_LRO_MAX_AGG_TIME(HW_LRO_AGG_TIME);
++
++ /* 2. Set max LRO agg count */
++ SET_PDMA_LRO_MAX_AGG_CNT(HW_LRO_MAX_AGG_CNT);
++
++ /* PDMA prefetch enable setting */
++ SET_PDMA_LRO_RXD_PREFETCH_EN(0x3);
++
++ /* 2.1 IPv4 checksum update enable */
++ SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1);
++
++ /* 3. Polling relinguish */
++ while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH)
++ ;
++
++ /* 4. Enable LRO */
++ regVal = sysRegRead(ADMA_LRO_CTRL_DW0);
++ regVal |= PDMA_LRO_EN;
++ sysRegWrite(ADMA_LRO_CTRL_DW0, regVal);
++
++ return 0;
++}
++#else
++int set_fe_lro_auto_cfg(struct net_device *dev)
++{
++ unsigned int regVal = 0;
++ unsigned int ip;
++
++ netdev_printk(KERN_CRIT, dev, "set_fe_lro_auto_cfg()\n");
++
++ /* 1.1 Set my IP_1 */
++ str_to_ip(&ip, "10.10.10.254");
++ sysRegWrite(LRO_RX_RING0_DIP_DW0, ip);
++ sysRegWrite(LRO_RX_RING0_DIP_DW1, 0);
++ sysRegWrite(LRO_RX_RING0_DIP_DW2, 0);
++ sysRegWrite(LRO_RX_RING0_DIP_DW3, 0);
++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING0, 1);
++
++ /* 1.2 Set my IP_2 */
++ str_to_ip(&ip, "10.10.20.254");
++ sysRegWrite(LRO_RX_RING1_DIP_DW0, ip);
++ sysRegWrite(LRO_RX_RING1_DIP_DW1, 0);
++ sysRegWrite(LRO_RX_RING1_DIP_DW2, 0);
++ sysRegWrite(LRO_RX_RING1_DIP_DW3, 0);
++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING1, 1);
++
++ /* 1.3 Set my IP_3 */
++ sysRegWrite(LRO_RX_RING2_DIP_DW3, 0x20010238);
++ sysRegWrite(LRO_RX_RING2_DIP_DW2, 0x08000000);
++ sysRegWrite(LRO_RX_RING2_DIP_DW1, 0x00000000);
++ sysRegWrite(LRO_RX_RING2_DIP_DW0, 0x00000254);
++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING2, 1);
++
++ /* 1.4 Set my IP_4 */
++ sysRegWrite(LRO_RX_RING3_DIP_DW3, 0x20010238);
++ sysRegWrite(LRO_RX_RING3_DIP_DW2, 0x08010000);
++ sysRegWrite(LRO_RX_RING3_DIP_DW1, 0x00000000);
++ sysRegWrite(LRO_RX_RING3_DIP_DW0, 0x00000254);
++ SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING3, 1);
++
++ /* 2.1 Set RX ring1~3 to auto-learn modes */
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_AUTO_LEARN);
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_AUTO_LEARN);
++ SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_AUTO_LEARN);
++
++ /* 2.2 Valid LRO ring */
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING0, 1);
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1);
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 1);
++ SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 1);
++
++ /* 2.3 Set AGE timer */
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, HW_LRO_AGE_TIME);
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, HW_LRO_AGE_TIME);
++ SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, HW_LRO_AGE_TIME);
++
++ /* 2.4 Set max AGG timer */
++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING1, HW_LRO_AGG_TIME);
++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING2, HW_LRO_AGG_TIME);
++ SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING3, HW_LRO_AGG_TIME);
++
++ /* 2.5 Set max LRO agg count */
++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING1, HW_LRO_MAX_AGG_CNT);
++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING2, HW_LRO_MAX_AGG_CNT);
++ SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING3, HW_LRO_MAX_AGG_CNT);
++
++ /* 3.0 IPv6 LRO enable */
++ SET_PDMA_LRO_IPV6_EN(1);
++
++ /* 3.1 IPv4 checksum update enable */
++ SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1);
++
++ /* 3.2 TCP push option check disable */
++ //SET_PDMA_LRO_IPV4_CTRL_PUSH_EN(0);
++
++ /* PDMA prefetch enable setting */
++ SET_PDMA_LRO_RXD_PREFETCH_EN(0x3);
++
++ /* 3.2 switch priority comparison to byte count mode */
++/* SET_PDMA_LRO_ALT_SCORE_MODE(PDMA_LRO_ALT_BYTE_CNT_MODE); */
++ SET_PDMA_LRO_ALT_SCORE_MODE(PDMA_LRO_ALT_PKT_CNT_MODE);
++
++ /* 3.3 bandwidth threshold setting */
++ SET_PDMA_LRO_BW_THRESHOLD(HW_LRO_BW_THRE);
++
++ /* 3.4 auto-learn score delta setting */
++ sysRegWrite(LRO_ALT_SCORE_DELTA, 0);
++
++ /* 3.5 Set ALT timer to 20us: (unit: 20us) */
++ SET_PDMA_LRO_ALT_REFRESH_TIMER_UNIT(HW_LRO_TIMER_UNIT);
++ /* 3.6 Set ALT refresh timer to 1 sec. (unit: 20us) */
++ SET_PDMA_LRO_ALT_REFRESH_TIMER(HW_LRO_REFRESH_TIME);
++
++ /* 3.7 the least remaining room of SDL0 in RXD for lro aggregation */
++ SET_PDMA_LRO_MIN_RXD_SDL(1522);
++
++ /* 4. Polling relinguish */
++ while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH)
++ ;
++
++ /* 5. Enable LRO */
++ regVal = sysRegRead(ADMA_LRO_CTRL_DW0);
++ regVal |= PDMA_LRO_EN;
++ sysRegWrite(ADMA_LRO_CTRL_DW0, regVal);
++
++ return 0;
++}
++#endif /* CONFIG_RAETH_HW_LRO_FORCE */
++
++int fe_hw_lro_init(struct net_device *dev)
++{
++ int i;
++ END_DEVICE *ei_local = netdev_priv(dev);
++
++ /* Initial RX Ring 3 */
++ ei_local->rx_ring3 =
++ pci_alloc_consistent(NULL, NUM_LRO_RX_DESC * sizeof(struct PDMA_rxdesc),
++ &ei_local->phy_rx_ring3);
++ for (i = 0; i < NUM_LRO_RX_DESC; i++) {
++ memset(&ei_local->rx_ring3[i], 0, sizeof(struct PDMA_rxdesc));
++ ei_local->rx_ring3[i].rxd_info2.DDONE_bit = 0;
++ ei_local->rx_ring3[i].rxd_info2.LS0 = 0;
++ ei_local->rx_ring3[i].rxd_info2.PLEN0 =
++ SET_ADMA_RX_LEN0(MAX_LRO_RX_LENGTH);
++ ei_local->rx_ring3[i].rxd_info2.PLEN1 =
++ SET_ADMA_RX_LEN1(MAX_LRO_RX_LENGTH >> 14);
++ ei_local->rx_ring3[i].rxd_info1.PDP0 =
++ dma_map_single(NULL, ei_local->netrx3_skbuf[i]->data,
++ MAX_LRO_RX_LENGTH, PCI_DMA_FROMDEVICE);
++ }
++ netdev_printk(KERN_CRIT, dev,
++ "\nphy_rx_ring3 = 0x%08x, rx_ring3 = 0x%p\n",
++ ei_local->phy_rx_ring3, ei_local->rx_ring3);
++ /* Initial RX Ring 2 */
++ ei_local->rx_ring2 =
++ pci_alloc_consistent(NULL, NUM_LRO_RX_DESC * sizeof(struct PDMA_rxdesc),
++ &ei_local->phy_rx_ring2);
++ for (i = 0; i < NUM_LRO_RX_DESC; i++) {
++ memset(&ei_local->rx_ring2[i], 0, sizeof(struct PDMA_rxdesc));
++ ei_local->rx_ring2[i].rxd_info2.DDONE_bit = 0;
++ ei_local->rx_ring2[i].rxd_info2.LS0 = 0;
++ ei_local->rx_ring2[i].rxd_info2.PLEN0 =
++ SET_ADMA_RX_LEN0(MAX_LRO_RX_LENGTH);
++ ei_local->rx_ring2[i].rxd_info2.PLEN1 =
++ SET_ADMA_RX_LEN1(MAX_LRO_RX_LENGTH >> 14);
++ ei_local->rx_ring2[i].rxd_info1.PDP0 =
++ dma_map_single(NULL, ei_local->netrx2_skbuf[i]->data,
++ MAX_LRO_RX_LENGTH, PCI_DMA_FROMDEVICE);
++ }
++ netdev_printk(KERN_CRIT, dev,
++ "\nphy_rx_ring2 = 0x%08x, rx_ring2 = 0x%p\n",
++ ei_local->phy_rx_ring2, ei_local->rx_ring2);
++ /* Initial RX Ring 1 */
++ ei_local->rx_ring1 =
++ pci_alloc_consistent(NULL, NUM_LRO_RX_DESC * sizeof(struct PDMA_rxdesc),
++ &ei_local->phy_rx_ring1);
++ for (i = 0; i < NUM_LRO_RX_DESC; i++) {
++ memset(&ei_local->rx_ring1[i], 0, sizeof(struct PDMA_rxdesc));
++ ei_local->rx_ring1[i].rxd_info2.DDONE_bit = 0;
++ ei_local->rx_ring1[i].rxd_info2.LS0 = 0;
++ ei_local->rx_ring1[i].rxd_info2.PLEN0 =
++ SET_ADMA_RX_LEN0(MAX_LRO_RX_LENGTH);
++ ei_local->rx_ring1[i].rxd_info2.PLEN1 =
++ SET_ADMA_RX_LEN1(MAX_LRO_RX_LENGTH >> 14);
++ ei_local->rx_ring1[i].rxd_info1.PDP0 =
++ dma_map_single(NULL, ei_local->netrx1_skbuf[i]->data,
++ MAX_LRO_RX_LENGTH, PCI_DMA_FROMDEVICE);
++ }
++ netdev_printk(KERN_CRIT, dev,
++ "\nphy_rx_ring1 = 0x%08x, rx_ring1 = 0x%p\n",
++ ei_local->phy_rx_ring1, ei_local->rx_ring1);
++
++ sysRegWrite(RX_BASE_PTR3, phys_to_bus((u32) ei_local->phy_rx_ring3));
++ sysRegWrite(RX_MAX_CNT3, cpu_to_le32((u32) NUM_LRO_RX_DESC));
++ sysRegWrite(RX_CALC_IDX3, cpu_to_le32((u32) (NUM_LRO_RX_DESC - 1)));
++ sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX3);
++ sysRegWrite(RX_BASE_PTR2, phys_to_bus((u32) ei_local->phy_rx_ring2));
++ sysRegWrite(RX_MAX_CNT2, cpu_to_le32((u32) NUM_LRO_RX_DESC));
++ sysRegWrite(RX_CALC_IDX2, cpu_to_le32((u32) (NUM_LRO_RX_DESC - 1)));
++ sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX2);
++ sysRegWrite(RX_BASE_PTR1, phys_to_bus((u32) ei_local->phy_rx_ring1));
++ sysRegWrite(RX_MAX_CNT1, cpu_to_le32((u32) NUM_LRO_RX_DESC));
++ sysRegWrite(RX_CALC_IDX1, cpu_to_le32((u32) (NUM_LRO_RX_DESC - 1)));
++ sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX1);
++
++#if defined(CONFIG_RAETH_HW_LRO_FORCE)
++ set_fe_lro_ring1_cfg(dev);
++ set_fe_lro_ring2_cfg(dev);
++ set_fe_lro_ring3_cfg(dev);
++ set_fe_lro_glo_cfg(dev);
++#else
++ set_fe_lro_auto_cfg(dev);
++#endif /* CONFIG_RAETH_HW_LRO_FORCE */
++
++ /* HW LRO parameter settings */
++ ei_local->hw_lro_alpha = HW_LRO_PKT_INT_ALPHA;
++ ei_local->hw_lro_fix_setting = 1;
++
++ return 1;
++}
++EXPORT_SYMBOL(fe_hw_lro_init);
++
+diff --git a/drivers/net/ethernet/raeth/raether_pdma.c b/drivers/net/ethernet/raeth/raether_pdma.c
+new file mode 100755
+index 0000000..4d47ee2
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/raether_pdma.c
+@@ -0,0 +1,1121 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <linux/if_vlan.h>
++#include <linux/if_ether.h>
++#include <linux/fs.h>
++#include <asm/uaccess.h>
++#include <asm/rt2880/surfboardint.h>
++#if defined (CONFIG_RAETH_TSO)
++#include <linux/tcp.h>
++#include <net/ipv6.h>
++#include <linux/ip.h>
++#include <net/ip.h>
++#include <net/tcp.h>
++#include <linux/in.h>
++#include <linux/ppp_defs.h>
++#include <linux/if_pppox.h>
++#endif
++#if defined (CONFIG_RAETH_LRO)
++#include <linux/inet_lro.h>
++#endif
++#include <linux/delay.h>
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++#include <linux/sched.h>
++#endif
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
++#include <asm/rt2880/rt_mmap.h>
++#else
++#include <linux/libata-compat.h>
++#endif
++
++#include "ra2882ethreg.h"
++#include "raether.h"
++#include "ra_mac.h"
++#include "ra_ioctl.h"
++#include "ra_rfrw.h"
++#ifdef CONFIG_RAETH_NETLINK
++#include "ra_netlink.h"
++#endif
++#if defined (CONFIG_RAETH_QOS)
++#include "ra_qos.h"
++#endif
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++#include "../../../net/nat/hw_nat/ra_nat.h"
++#endif
++#if defined(CONFIG_RAETH_PDMA_DVT)
++#include "dvt/raether_pdma_dvt.h"
++#endif /* CONFIG_RAETH_PDMA_DVT */
++
++#if !defined(CONFIG_RA_NAT_NONE)
++/* bruce+
++ */
++extern int (*ra_sw_nat_hook_rx)(struct sk_buff *skb);
++extern int (*ra_sw_nat_hook_tx)(struct sk_buff *skb, int gmac_no);
++#endif
++
++#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE)
++/* Qwert+
++ */
++#include <asm/mipsregs.h>
++extern int (*ra_classifier_hook_tx)(struct sk_buff *skb, unsigned long cur_cycle);
++extern int (*ra_classifier_hook_rx)(struct sk_buff *skb, unsigned long cur_cycle);
++#endif /* CONFIG_RA_CLASSIFIER */
++
++#if defined (CONFIG_RALINK_RT3052_MP2)
++int32_t mcast_rx(struct sk_buff * skb);
++int32_t mcast_tx(struct sk_buff * skb);
++#endif
++
++#if 0
++#ifdef RA_MTD_RW_BY_NUM
++int ra_mtd_read(int num, loff_t from, size_t len, u_char *buf);
++#else
++int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf);
++#endif
++#endif
++/* gmac driver feature set config */
++#if defined (CONFIG_RAETH_NAPI) || defined (CONFIG_RAETH_QOS)
++#undef DELAY_INT
++#else
++#if defined (CONFIG_ARCH_MT7623)
++#undef DELAY_INT
++#else
++#define DELAY_INT 1
++#endif
++#endif
++
++//#define CONFIG_UNH_TEST
++/* end of config */
++
++#if defined (CONFIG_RAETH_JUMBOFRAME)
++#define MAX_RX_LENGTH 4096
++#else
++#define MAX_RX_LENGTH 1536
++#endif
++
++extern struct net_device *dev_raether;
++
++
++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++extern int rx_calc_idx1;
++#endif
++#endif
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++extern int rx_calc_idx0;
++static unsigned long tx_cpu_owner_idx0=0;
++#endif
++extern unsigned long tx_ring_full;
++
++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
++#include "ra_ethtool.h"
++extern struct ethtool_ops ra_ethtool_ops;
++#ifdef CONFIG_PSEUDO_SUPPORT
++extern struct ethtool_ops ra_virt_ethtool_ops;
++#endif // CONFIG_PSEUDO_SUPPORT //
++#endif // (CONFIG_ETHTOOL //
++
++#ifdef CONFIG_RALINK_VISTA_BASIC
++int is_switch_175c = 1;
++#endif
++
++#ifdef CONFIG_RAETH_PDMATX_QDMARX /* QDMA RX */
++struct QDMA_txdesc *free_head = NULL;
++#endif
++
++//#if defined (CONFIG_RAETH_LRO)
++#if 0
++unsigned int lan_ip;
++struct lro_para_struct lro_para;
++int lro_flush_needed;
++extern char const *nvram_get(int index, char *name);
++#endif
++
++#define KSEG1 0xa0000000
++#define PHYS_TO_VIRT(x) ((void *)((x) | KSEG1))
++#define VIRT_TO_PHYS(x) ((unsigned long)(x) & ~KSEG1)
++
++extern void set_fe_dma_glo_cfg(void);
++
++/*
++ * @brief cal txd number for a page
++ *
++ * @parm size
++ *
++ * @return frag_txd_num
++ */
++
++unsigned int cal_frag_txd_num(unsigned int size)
++{
++ unsigned int frag_txd_num = 0;
++ if(size == 0)
++ return 0;
++ while(size > 0){
++ if(size > MAX_TXD_LEN){
++ frag_txd_num++;
++ size -= MAX_TXD_LEN;
++ }else{
++ frag_txd_num++;
++ size = 0;
++ }
++ }
++ return frag_txd_num;
++
++}
++
++#ifdef CONFIG_RAETH_PDMATX_QDMARX /* QDMA RX */
++bool fq_qdma_init(struct net_device *dev)
++{
++ END_DEVICE* ei_local = netdev_priv(dev);
++ unsigned int phy_free_head;
++ unsigned int phy_free_tail;
++ unsigned int *free_page_head = NULL;
++ unsigned int phy_free_page_head;
++ int i;
++
++ free_head = pci_alloc_consistent(NULL, NUM_QDMA_PAGE * sizeof(struct QDMA_txdesc), &phy_free_head);
++ if (unlikely(free_head == NULL)){
++ printk(KERN_ERR "QDMA FQ decriptor not available...\n");
++ return 0;
++ }
++ memset(free_head, 0x0, sizeof(struct QDMA_txdesc) * NUM_QDMA_PAGE);
++
++ free_page_head = pci_alloc_consistent(NULL, NUM_QDMA_PAGE * QDMA_PAGE_SIZE, &phy_free_page_head);
++ if (unlikely(free_page_head == NULL)){
++ printk(KERN_ERR "QDMA FQ page not available...\n");
++ return 0;
++ }
++ for (i=0; i < NUM_QDMA_PAGE; i++) {
++ free_head[i].txd_info1.SDP = (phy_free_page_head + (i * QDMA_PAGE_SIZE));
++ if(i < (NUM_QDMA_PAGE-1)){
++ free_head[i].txd_info2.NDP = (phy_free_head + ((i+1) * sizeof(struct QDMA_txdesc)));
++
++
++#if 0
++ printk("free_head_phy[%d] is 0x%x!!!\n",i, VIRT_TO_PHYS(&free_head[i]) );
++ printk("free_head[%d] is 0x%x!!!\n",i, &free_head[i] );
++ printk("free_head[%d].txd_info1.SDP is 0x%x!!!\n",i, free_head[i].txd_info1.SDP );
++ printk("free_head[%d].txd_info2.NDP is 0x%x!!!\n",i, free_head[i].txd_info2.NDP );
++#endif
++ }
++ free_head[i].txd_info3.SDL = QDMA_PAGE_SIZE;
++
++ }
++ phy_free_tail = (phy_free_head + (u32)((NUM_QDMA_PAGE-1) * sizeof(struct QDMA_txdesc)));
++
++ printk("phy_free_head is 0x%x!!!\n", phy_free_head);
++ printk("phy_free_tail_phy is 0x%x!!!\n", phy_free_tail);
++ sysRegWrite(QDMA_FQ_HEAD, (u32)phy_free_head);
++ sysRegWrite(QDMA_FQ_TAIL, (u32)phy_free_tail);
++ sysRegWrite(QDMA_FQ_CNT, ((NUM_TX_DESC << 16) | NUM_QDMA_PAGE));
++ sysRegWrite(QDMA_FQ_BLEN, QDMA_PAGE_SIZE << 16);
++
++ ei_local->free_head = free_head;
++ ei_local->phy_free_head = phy_free_head;
++ ei_local->free_page_head = free_page_head;
++ ei_local->phy_free_page_head = phy_free_page_head;
++ return 1;
++}
++#endif
++
++int fe_dma_init(struct net_device *dev)
++{
++
++ int i;
++ unsigned int regVal;
++ END_DEVICE* ei_local = netdev_priv(dev);
++#if defined (CONFIG_RAETH_QOS)
++ int j;
++#endif
++
++ while(1)
++ {
++ regVal = sysRegRead(PDMA_GLO_CFG);
++ if((regVal & RX_DMA_BUSY))
++ {
++ printk("\n RX_DMA_BUSY !!! ");
++ continue;
++ }
++ if((regVal & TX_DMA_BUSY))
++ {
++ printk("\n TX_DMA_BUSY !!! ");
++ continue;
++ }
++ break;
++ }
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++ pdma_dvt_set_dma_mode();
++#endif /* CONFIG_RAETH_PDMA_DVT */
++
++#if defined (CONFIG_RAETH_QOS)
++ for (i=0;i<NUM_TX_RINGS;i++){
++ for (j=0;j<NUM_TX_DESC;j++){
++ ei_local->skb_free[i][j]=0;
++ }
++ ei_local->free_idx[i]=0;
++ }
++ /*
++ * RT2880: 2 x TX_Ring, 1 x Rx_Ring
++ * RT2883: 4 x TX_Ring, 1 x Rx_Ring
++ * RT3883: 4 x TX_Ring, 1 x Rx_Ring
++ * RT3052: 4 x TX_Ring, 1 x Rx_Ring
++ */
++ fe_tx_desc_init(dev, 0, 3, 1);
++ if (ei_local->tx_ring0 == NULL) {
++ printk("RAETH: tx ring0 allocation failed\n");
++ return 0;
++ }
++
++ fe_tx_desc_init(dev, 1, 3, 1);
++ if (ei_local->tx_ring1 == NULL) {
++ printk("RAETH: tx ring1 allocation failed\n");
++ return 0;
++ }
++
++ printk("\nphy_tx_ring0 = %08x, tx_ring0 = %p, size: %d bytes\n", ei_local->phy_tx_ring0, ei_local->tx_ring0, sizeof(struct PDMA_txdesc));
++
++ printk("\nphy_tx_ring1 = %08x, tx_ring1 = %p, size: %d bytes\n", ei_local->phy_tx_ring1, ei_local->tx_ring1, sizeof(struct PDMA_txdesc));
++
++#if ! defined (CONFIG_RALINK_RT2880)
++ fe_tx_desc_init(dev, 2, 3, 1);
++ if (ei_local->tx_ring2 == NULL) {
++ printk("RAETH: tx ring2 allocation failed\n");
++ return 0;
++ }
++
++ fe_tx_desc_init(dev, 3, 3, 1);
++ if (ei_local->tx_ring3 == NULL) {
++ printk("RAETH: tx ring3 allocation failed\n");
++ return 0;
++ }
++
++ printk("\nphy_tx_ring2 = %08x, tx_ring2 = %p, size: %d bytes\n", ei_local->phy_tx_ring2, ei_local->tx_ring2, sizeof(struct PDMA_txdesc));
++
++ printk("\nphy_tx_ring3 = %08x, tx_ring3 = %p, size: %d bytes\n", ei_local->phy_tx_ring3, ei_local->tx_ring3, sizeof(struct PDMA_txdesc));
++
++#endif // CONFIG_RALINK_RT2880 //
++#else
++ for (i=0;i<NUM_TX_DESC;i++){
++ ei_local->skb_free[i]=0;
++ }
++ ei_local->free_idx =0;
++#if defined (CONFIG_MIPS)
++ ei_local->tx_ring0 = pci_alloc_consistent(NULL, NUM_TX_DESC * sizeof(struct PDMA_txdesc), &ei_local->phy_tx_ring0);
++#else
++ ei_local->tx_ring0 = dma_alloc_coherent(NULL, NUM_TX_DESC * sizeof(struct PDMA_txdesc), &ei_local->phy_tx_ring0, GFP_KERNEL);
++#endif
++ printk("\nphy_tx_ring = 0x%08x, tx_ring = 0x%p\n", ei_local->phy_tx_ring0, ei_local->tx_ring0);
++
++ for (i=0; i < NUM_TX_DESC; i++) {
++ memset(&ei_local->tx_ring0[i],0,sizeof(struct PDMA_txdesc));
++ ei_local->tx_ring0[i].txd_info2.LS0_bit = 1;
++ ei_local->tx_ring0[i].txd_info2.DDONE_bit = 1;
++
++ }
++#endif // CONFIG_RAETH_QOS
++
++#ifdef CONFIG_RAETH_PDMATX_QDMARX /* QDMA RX */
++
++ fq_qdma_init(dev);
++
++ while(1)
++ {
++ regVal = sysRegRead(QDMA_GLO_CFG);
++ if((regVal & RX_DMA_BUSY))
++ {
++ printk("\n RX_DMA_BUSY !!! ");
++ continue;
++ }
++ if((regVal & TX_DMA_BUSY))
++ {
++ printk("\n TX_DMA_BUSY !!! ");
++ continue;
++ }
++ break;
++ }
++
++ /* Initial RX Ring 0*/
++
++#ifdef CONFIG_32B_DESC
++ ei_local->qrx_ring = kmalloc(NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL);
++ ei_local->phy_qrx_ring = virt_to_phys(ei_local->qrx_ring);
++#else
++ ei_local->qrx_ring = pci_alloc_consistent(NULL, NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_qrx_ring);
++#endif
++ for (i = 0; i < NUM_QRX_DESC; i++) {
++ memset(&ei_local->qrx_ring[i],0,sizeof(struct PDMA_rxdesc));
++ ei_local->qrx_ring[i].rxd_info2.DDONE_bit = 0;
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++ ei_local->qrx_ring[i].rxd_info2.LS0 = 0;
++ ei_local->qrx_ring[i].rxd_info2.PLEN0 = MAX_RX_LENGTH;
++#else
++ ei_local->qrx_ring[i].rxd_info2.LS0 = 1;
++#endif
++ ei_local->qrx_ring[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx0_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++ }
++ printk("\nphy_qrx_ring = 0x%08x, qrx_ring = 0x%p\n",ei_local->phy_qrx_ring,ei_local->qrx_ring);
++
++ regVal = sysRegRead(QDMA_GLO_CFG);
++ regVal &= 0x000000FF;
++
++ sysRegWrite(QDMA_GLO_CFG, regVal);
++ regVal=sysRegRead(QDMA_GLO_CFG);
++
++ /* Tell the adapter where the TX/RX rings are located. */
++
++ sysRegWrite(QRX_BASE_PTR_0, phys_to_bus((u32) ei_local->phy_qrx_ring));
++ sysRegWrite(QRX_MAX_CNT_0, cpu_to_le32((u32) NUM_QRX_DESC));
++ sysRegWrite(QRX_CRX_IDX_0, cpu_to_le32((u32) (NUM_QRX_DESC - 1)));
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ rx_calc_idx0 = rx_dma_owner_idx0 = sysRegRead(QRX_CRX_IDX_0);
++#endif
++ sysRegWrite(QDMA_RST_CFG, PST_DRX_IDX0);
++
++ ei_local->rx_ring0 = ei_local->qrx_ring;
++
++#else /* PDMA RX */
++
++ /* Initial RX Ring 0*/
++#ifdef CONFIG_32B_DESC
++ ei_local->rx_ring0 = kmalloc(NUM_RX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL);
++ ei_local->phy_rx_ring0 = virt_to_phys(ei_local->rx_ring0);
++#else
++#if defined (CONFIG_MIPS)
++ ei_local->rx_ring0 = pci_alloc_consistent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring0);
++#else
++ ei_local->rx_ring0 = dma_alloc_coherent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring0, GFP_KERNEL);
++#endif
++#endif
++ for (i = 0; i < NUM_RX_DESC; i++) {
++ memset(&ei_local->rx_ring0[i],0,sizeof(struct PDMA_rxdesc));
++ ei_local->rx_ring0[i].rxd_info2.DDONE_bit = 0;
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++ ei_local->rx_ring0[i].rxd_info2.LS0 = 0;
++ ei_local->rx_ring0[i].rxd_info2.PLEN0 = MAX_RX_LENGTH;
++#else
++ ei_local->rx_ring0[i].rxd_info2.LS0 = 1;
++#endif
++ ei_local->rx_ring0[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx0_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++ }
++ printk("\nphy_rx_ring0 = 0x%08x, rx_ring0 = 0x%p\n",ei_local->phy_rx_ring0,ei_local->rx_ring0);
++
++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++ /* Initial RX Ring 1*/
++#ifdef CONFIG_32B_DESC
++ ei_local->rx_ring1 = kmalloc(NUM_RX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL);
++ ei_local->phy_rx_ring1 = virt_to_phys(ei_local->rx_ring1);
++#else
++#if defined (CONFIG_MIPS)
++ ei_local->rx_ring1 = pci_alloc_consistent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring1);
++#else
++ ei_local->rx_ring1 = dma_alloc_coherent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring1, GFP_KERNEL);
++
++#endif
++#endif
++ for (i = 0; i < NUM_RX_DESC; i++) {
++ memset(&ei_local->rx_ring1[i],0,sizeof(struct PDMA_rxdesc));
++ ei_local->rx_ring1[i].rxd_info2.DDONE_bit = 0;
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++ ei_local->rx_ring1[i].rxd_info2.LS0 = 0;
++ ei_local->rx_ring1[i].rxd_info2.PLEN0 = MAX_RX_LENGTH;
++#else
++ ei_local->rx_ring1[i].rxd_info2.LS0 = 1;
++#endif
++ ei_local->rx_ring1[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx1_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++ }
++ printk("\nphy_rx_ring1 = 0x%08x, rx_ring1 = 0x%p\n",ei_local->phy_rx_ring1,ei_local->rx_ring1);
++#if defined(CONFIG_ARCH_MT7623)
++ /* Initial RX Ring 2*/
++ ei_local->rx_ring2 = pci_alloc_consistent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring2);
++ for (i = 0; i < NUM_RX_DESC; i++) {
++ memset(&ei_local->rx_ring2[i],0,sizeof(struct PDMA_rxdesc));
++ ei_local->rx_ring2[i].rxd_info2.DDONE_bit = 0;
++ ei_local->rx_ring2[i].rxd_info2.LS0 = 0;
++ ei_local->rx_ring2[i].rxd_info2.PLEN0 = SET_ADMA_RX_LEN0(MAX_RX_LENGTH);
++ ei_local->rx_ring2[i].rxd_info2.PLEN1 = SET_ADMA_RX_LEN1(MAX_RX_LENGTH >> 14);
++ ei_local->rx_ring2[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx2_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++ }
++ printk("\nphy_rx_ring2 = 0x%08x, rx_ring2 = 0x%p\n",ei_local->phy_rx_ring2,ei_local->rx_ring2);
++ /* Initial RX Ring 3*/
++ ei_local->rx_ring3 = pci_alloc_consistent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring3);
++ for (i = 0; i < NUM_RX_DESC; i++) {
++ memset(&ei_local->rx_ring3[i],0,sizeof(struct PDMA_rxdesc));
++ ei_local->rx_ring3[i].rxd_info2.DDONE_bit = 0;
++ ei_local->rx_ring3[i].rxd_info2.LS0 = 0;
++ ei_local->rx_ring3[i].rxd_info2.PLEN0 = SET_ADMA_RX_LEN0(MAX_RX_LENGTH);
++ ei_local->rx_ring3[i].rxd_info2.PLEN1 = SET_ADMA_RX_LEN1(MAX_RX_LENGTH >> 14);
++ ei_local->rx_ring3[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx3_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++ }
++ printk("\nphy_rx_ring3 = 0x%08x, rx_ring3 = 0x%p\n",ei_local->phy_rx_ring3,ei_local->rx_ring3);
++#endif /* CONFIG_ARCH_MT7623 */
++#endif
++
++#endif
++
++ regVal = sysRegRead(PDMA_GLO_CFG);
++ regVal &= 0x000000FF;
++ sysRegWrite(PDMA_GLO_CFG, regVal);
++ regVal=sysRegRead(PDMA_GLO_CFG);
++
++ /* Tell the adapter where the TX/RX rings are located. */
++#if !defined (CONFIG_RAETH_QOS)
++ sysRegWrite(TX_BASE_PTR0, phys_to_bus((u32) ei_local->phy_tx_ring0));
++ sysRegWrite(TX_MAX_CNT0, cpu_to_le32((u32) NUM_TX_DESC));
++ sysRegWrite(TX_CTX_IDX0, 0);
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ tx_cpu_owner_idx0 = 0;
++#endif
++ sysRegWrite(PDMA_RST_CFG, PST_DTX_IDX0);
++#endif
++
++#ifdef CONFIG_RAETH_PDMATX_QDMARX /* QDMA RX */
++ sysRegWrite(QRX_BASE_PTR_0, phys_to_bus((u32) ei_local->phy_qrx_ring));
++ sysRegWrite(QRX_MAX_CNT_0, cpu_to_le32((u32) NUM_QRX_DESC));
++ sysRegWrite(QRX_CRX_IDX_0, cpu_to_le32((u32) (NUM_QRX_DESC - 1)));
++#else /* PDMA RX */
++ sysRegWrite(RX_BASE_PTR0, phys_to_bus((u32) ei_local->phy_rx_ring0));
++ sysRegWrite(RX_MAX_CNT0, cpu_to_le32((u32) NUM_RX_DESC));
++ sysRegWrite(RX_CALC_IDX0, cpu_to_le32((u32) (NUM_RX_DESC - 1)));
++#endif
++
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ rx_calc_idx0 = sysRegRead(RX_CALC_IDX0);
++#endif
++ sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX0);
++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++ sysRegWrite(RX_BASE_PTR1, phys_to_bus((u32) ei_local->phy_rx_ring1));
++ sysRegWrite(RX_MAX_CNT1, cpu_to_le32((u32) NUM_RX_DESC));
++ sysRegWrite(RX_CALC_IDX1, cpu_to_le32((u32) (NUM_RX_DESC - 1)));
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ rx_calc_idx1 = sysRegRead(RX_CALC_IDX1);
++#endif
++ sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX1);
++#if defined(CONFIG_ARCH_MT7623)
++ sysRegWrite(RX_BASE_PTR2, phys_to_bus((u32) ei_local->phy_rx_ring2));
++ sysRegWrite(RX_MAX_CNT2, cpu_to_le32((u32) NUM_RX_DESC));
++ sysRegWrite(RX_CALC_IDX2, cpu_to_le32((u32) (NUM_RX_DESC - 1)));
++ sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX2);
++ sysRegWrite(RX_BASE_PTR3, phys_to_bus((u32) ei_local->phy_rx_ring3));
++ sysRegWrite(RX_MAX_CNT3, cpu_to_le32((u32) NUM_RX_DESC));
++ sysRegWrite(RX_CALC_IDX3, cpu_to_le32((u32) (NUM_RX_DESC - 1)));
++ sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX3);
++#endif /* CONFIG_ARCH_MT7623 */
++#endif
++#if defined (CONFIG_RALINK_RT6855A)
++ regVal = sysRegRead(RX_DRX_IDX0);
++ regVal = (regVal == 0)? (NUM_RX_DESC - 1) : (regVal - 1);
++ sysRegWrite(RX_CALC_IDX0, cpu_to_le32(regVal));
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ rx_calc_idx0 = sysRegRead(RX_CALC_IDX0);
++#endif
++ regVal = sysRegRead(TX_DTX_IDX0);
++ sysRegWrite(TX_CTX_IDX0, cpu_to_le32(regVal));
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ tx_cpu_owner_idx0 = regVal;
++#endif
++ ei_local->free_idx = regVal;
++#endif
++
++#if defined (CONFIG_RAETH_QOS)
++ set_scheduler_weight();
++ set_schedule_pause_condition();
++ set_output_shaper();
++#endif
++
++ set_fe_dma_glo_cfg();
++
++ return 1;
++}
++
++inline int rt2880_eth_send(struct net_device* dev, struct sk_buff *skb, int gmac_no)
++{
++ unsigned int length=skb->len;
++ END_DEVICE* ei_local = netdev_priv(dev);
++#ifndef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ unsigned long tx_cpu_owner_idx0 = sysRegRead(TX_CTX_IDX0);
++#endif
++#if defined (CONFIG_RAETH_TSO)
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ unsigned long ctx_idx_start_addr = tx_cpu_owner_idx0;
++#endif
++ struct iphdr *iph = NULL;
++ struct tcphdr *th = NULL;
++ struct skb_frag_struct *frag;
++ unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
++ int i=0;
++ unsigned int len, size, offset, frag_txd_num, skb_txd_num ;
++#endif // CONFIG_RAETH_TSO //
++
++#if defined (CONFIG_RAETH_TSOV6)
++ struct ipv6hdr *ip6h = NULL;
++#endif
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++ PSEUDO_ADAPTER *pAd;
++#endif
++
++ while(ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.DDONE_bit == 0)
++ {
++#ifdef CONFIG_PSEUDO_SUPPORT
++ if (gmac_no == 2) {
++ if (ei_local->PseudoDev != NULL) {
++ pAd = netdev_priv(ei_local->PseudoDev);
++ pAd->stat.tx_errors++;
++ }
++ } else
++#endif
++ ei_local->stat.tx_errors++;
++ }
++
++#if !defined (CONFIG_RAETH_TSO)
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info1.SDP0 = virt_to_phys(skb->data);
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.SDL0 = length;
++#if defined (CONFIG_RALINK_MT7620)
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FP_BMAP = 0;
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++ if (gmac_no == 1) {
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 1;
++ }else {
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 2;
++ }
++#else
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.PN = gmac_no;
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.QN = 3;
++#endif
++
++#if defined (CONFIG_RAETH_CHECKSUM_OFFLOAD) && ! defined(CONFIG_RALINK_RT5350) && !defined(CONFIG_RALINK_MT7628)
++ if (skb->ip_summed == CHECKSUM_PARTIAL){
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TUI_CO = 7;
++ }else {
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TUI_CO = 0;
++ }
++#endif
++
++#ifdef CONFIG_RAETH_HW_VLAN_TX
++ if(vlan_tx_tag_present(skb)) {
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0x10000 | vlan_tx_tag_get(skb);
++#else
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VPRI_VIDX = 0x80 | (vlan_tx_tag_get(skb) >> 13) << 4 | (vlan_tx_tag_get(skb) & 0xF);
++#endif
++ }else {
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0;
++#else
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VPRI_VIDX = 0;
++#endif
++ }
++#endif
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++ raeth_pdma_tx_vlan_dvt( ei_local, tx_cpu_owner_idx0 );
++#endif /* CONFIG_RAETH_PDMA_DVT */
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++ if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) {
++ if(ra_sw_nat_hook_rx!= NULL){
++#if defined (CONFIG_RALINK_MT7620)
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FP_BMAP = (1 << 7); /* PPE */
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 4; /* PPE */
++#else
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.PN = 6; /* PPE */
++#endif
++ FOE_MAGIC_TAG(skb) = 0;
++ }
++ }
++#endif
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++ raeth_pdma_tx_desc_dvt( ei_local, tx_cpu_owner_idx0 );
++#endif /* CONFIG_RAETH_PDMA_DVT */
++
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.DDONE_bit = 0;
++
++#if 0
++ printk("---------------\n");
++ printk("tx_info1=%x\n",ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info1);
++ printk("tx_info2=%x\n",ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2);
++ printk("tx_info3=%x\n",ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info3);
++ printk("tx_info4=%x\n",ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4);
++#endif
++
++#else
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info1.SDP0 = virt_to_phys(skb->data);
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.SDL0 = (length - skb->data_len);
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS0_bit = nr_frags ? 0:1;
++#if defined (CONFIG_RALINK_MT7620)
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FP_BMAP = 0;
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++ if (gmac_no == 1) {
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 1;
++ }else {
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 2;
++ }
++#else
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.PN = gmac_no;
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.QN = 3;
++#endif
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TSO = 0;
++
++#if defined (CONFIG_RAETH_CHECKSUM_OFFLOAD) && ! defined(CONFIG_RALINK_RT5350) && !defined(CONFIG_RALINK_MT7628)
++ if (skb->ip_summed == CHECKSUM_PARTIAL){
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TUI_CO = 7;
++ }else {
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TUI_CO = 0;
++ }
++#endif
++
++#ifdef CONFIG_RAETH_HW_VLAN_TX
++ if(vlan_tx_tag_present(skb)) {
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0x10000 | vlan_tx_tag_get(skb);
++#else
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VPRI_VIDX = 0x80 | (vlan_tx_tag_get(skb) >> 13) << 4 | (vlan_tx_tag_get(skb) & 0xF);
++#endif
++ }else {
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0;
++#else
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VPRI_VIDX = 0;
++#endif
++ }
++#endif
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++ raeth_pdma_tx_vlan_dvt( ei_local, tx_cpu_owner_idx0 );
++#endif /* CONFIG_RAETH_PDMA_DVT */
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++ if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) {
++ if(ra_sw_nat_hook_rx!= NULL){
++#if defined (CONFIG_RALINK_MT7620)
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FP_BMAP = (1 << 7); /* PPE */
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 4; /* PPE */
++#else
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.PN = 6; /* PPE */
++#endif
++ FOE_MAGIC_TAG(skb) = 0;
++ }
++ }
++#endif
++
++ skb_txd_num = 1;
++
++ if(nr_frags > 0) {
++
++ for(i=0;i<nr_frags;i++) {
++ frag = &skb_shinfo(skb)->frags[i];
++ offset = frag->page_offset;
++ len = frag->size;
++ frag_txd_num = cal_frag_txd_num(len);
++
++ while(frag_txd_num > 0){
++ if(len < MAX_TXD_LEN)
++ size = len;
++ else
++ size = MAX_TXD_LEN;
++ if(skb_txd_num%2 == 0) {
++ tx_cpu_owner_idx0 = (tx_cpu_owner_idx0+1) % NUM_TX_DESC;
++
++ while(ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.DDONE_bit == 0)
++ {
++#ifdef config_pseudo_support
++ if (gmac_no == 2) {
++ if (ei_local->pseudodev != null) {
++ pad = netdev_priv(ei_local->pseudodev);
++ pad->stat.tx_errors++;
++ }
++ } else
++#endif
++ ei_local->stat.tx_errors++;
++ }
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info1.SDP0 = pci_map_page(NULL, frag->page, offset, size, PCI_DMA_TODEVICE);
++#else
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info1.SDP0 = pci_map_page(NULL, frag->page.p, offset, size, PCI_DMA_TODEVICE);
++#endif
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.SDL0 = size;
++
++ if( (i==(nr_frags-1)) && (frag_txd_num == 1))
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS0_bit = 1;
++ else
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS0_bit = 0;
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.DDONE_bit = 0;
++ }else {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info3.SDP1 = pci_map_page(NULL, frag->page, offset, size, PCI_DMA_TODEVICE);
++#else
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info3.SDP1 = pci_map_page(NULL, frag->page.p, offset, size, PCI_DMA_TODEVICE);
++
++#endif
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.SDL1 = size;
++ if( (i==(nr_frags-1)) && (frag_txd_num == 1))
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS1_bit = 1;
++ else
++ ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS1_bit = 0;
++ }
++ offset += size;
++ len -= size;
++ frag_txd_num--;
++ skb_txd_num++;
++ }
++ }
++ }
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++ if( (pdma_dvt_get_debug_test_config() & PDMA_TEST_TSO_DEBUG) ){
++ printk("skb_shinfo(skb)->gso_segs = %d\n", skb_shinfo(skb)->gso_segs);
++ }
++#endif /* CONFIG_RAETH_PDMA_DVT */
++ /* fill in MSS info in tcp checksum field */
++ if(skb_shinfo(skb)->gso_segs > 1) {
++
++// TsoLenUpdate(skb->len);
++
++ /* TCP over IPv4 */
++ iph = (struct iphdr *)skb_network_header(skb);
++#if defined (CONFIG_RAETH_TSOV6)
++ /* TCP over IPv6 */
++ ip6h = (struct ipv6hdr *)skb_network_header(skb);
++#endif
++ if((iph->version == 4) && (iph->protocol == IPPROTO_TCP)) {
++ th = (struct tcphdr *)skb_transport_header(skb);
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ ei_local->tx_ring0[ctx_idx_start_addr].txd_info4.TSO = 1;
++#else
++ ei_local->tx_ring0[sysRegRead(TX_CTX_IDX0)].txd_info4.TSO = 1;
++#endif
++ th->check = htons(skb_shinfo(skb)->gso_size);
++#if defined (CONFIG_MIPS)
++ dma_cache_sync(NULL, th, sizeof(struct tcphdr), DMA_TO_DEVICE);
++#else
++ dma_sync_single_for_device(NULL, virt_to_phys(th), sizeof(struct tcphdr), DMA_TO_DEVICE);
++#endif
++ }
++
++#if defined (CONFIG_RAETH_TSOV6)
++ /* TCP over IPv6 */
++ else if ((ip6h->version == 6) && (ip6h->nexthdr == NEXTHDR_TCP)) {
++ th = (struct tcphdr *)skb_transport_header(skb);
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ ei_local->tx_ring0[ctx_idx_start_addr].txd_info4.TSO = 1;
++#else
++ ei_local->tx_ring0[sysRegRead(TX_CTX_IDX0)].txd_info4.TSO = 1;
++#endif
++ th->check = htons(skb_shinfo(skb)->gso_size);
++#if defined (CONFIG_MIPS)
++ dma_cache_sync(NULL, th, sizeof(struct tcphdr), DMA_TO_DEVICE);
++#else
++ dma_sync_single_for_device(NULL, virt_to_phys(th), sizeof(struct tcphdr), DMA_TO_DEVICE);
++#endif
++ }
++#endif // CONFIG_RAETH_TSOV6 //
++ }
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++ raeth_pdma_tx_desc_dvt( ei_local, tx_cpu_owner_idx0 );
++#endif /* CONFIG_RAETH_PDMA_DVT */
++
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ ei_local->tx_ring0[ctx_idx_start_addr].txd_info2.DDONE_bit = 0;
++#else
++ ei_local->tx_ring0[sysRegRead(TX_CTX_IDX0)].txd_info2.DDONE_bit = 0;
++#endif
++#endif // CONFIG_RAETH_TSO //
++
++ tx_cpu_owner_idx0 = (tx_cpu_owner_idx0+1) % NUM_TX_DESC;
++ while(ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.DDONE_bit == 0)
++ {
++// printk(KERN_ERR "%s: TXD=%lu TX DMA is Busy !!\n", dev->name, tx_cpu_owner_idx0);
++#ifdef CONFIG_PSEUDO_SUPPORT
++ if (gmac_no == 2) {
++ if (ei_local->PseudoDev != NULL) {
++ pAd = netdev_priv(ei_local->PseudoDev);
++ pAd->stat.tx_errors++;
++ }
++ } else
++#endif
++ ei_local->stat.tx_errors++;
++ }
++ sysRegWrite(TX_CTX_IDX0, cpu_to_le32((u32)tx_cpu_owner_idx0));
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++ if (gmac_no == 2) {
++ if (ei_local->PseudoDev != NULL) {
++ pAd = netdev_priv(ei_local->PseudoDev);
++ pAd->stat.tx_packets++;
++ pAd->stat.tx_bytes += length;
++ }
++ } else
++#endif
++ {
++ ei_local->stat.tx_packets++;
++ ei_local->stat.tx_bytes += length;
++ }
++#ifdef CONFIG_RAETH_NAPI
++ if ( ei_local->tx_full == 1) {
++ ei_local->tx_full = 0;
++ netif_wake_queue(dev);
++ }
++#endif
++
++ return length;
++}
++
++int ei_start_xmit(struct sk_buff* skb, struct net_device *dev, int gmac_no)
++{
++ END_DEVICE *ei_local = netdev_priv(dev);
++ unsigned long flags;
++ unsigned long tx_cpu_owner_idx;
++ unsigned int tx_cpu_owner_idx_next;
++ unsigned int num_of_txd = 0;
++#if defined (CONFIG_RAETH_TSO)
++ unsigned int nr_frags = skb_shinfo(skb)->nr_frags, i;
++ struct skb_frag_struct *frag;
++#endif
++#if !defined(CONFIG_RAETH_QOS)
++ unsigned int tx_cpu_owner_idx_next2;
++#else
++ int ring_no, queue_no, port_no;
++#endif
++#ifdef CONFIG_RALINK_VISTA_BASIC
++ struct vlan_ethhdr *veth;
++#endif
++#ifdef CONFIG_PSEUDO_SUPPORT
++ PSEUDO_ADAPTER *pAd;
++#endif
++
++#if !defined(CONFIG_RA_NAT_NONE)
++ if(ra_sw_nat_hook_tx!= NULL)
++ {
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++ if(FOE_MAGIC_TAG(skb) != FOE_MAGIC_PPE)
++#endif
++ {
++ //spin_lock_irqsave(&ei_local->page_lock, flags);
++ if(ra_sw_nat_hook_tx(skb, gmac_no)==1){
++ //spin_unlock_irqrestore(&ei_local->page_lock, flags);
++ }else{
++ kfree_skb(skb);
++ //spin_unlock_irqrestore(&ei_local->page_lock, flags);
++ return 0;
++ }
++ }
++ }
++#endif
++#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE)
++ /* Qwert+
++ */
++ if(ra_classifier_hook_tx!= NULL)
++ {
++#if defined(CONFIG_RALINK_EXTERNAL_TIMER)
++ ra_classifier_hook_tx(skb, (*((volatile u32 *)(0xB0000D08))&0x0FFFF));
++#else
++ ra_classifier_hook_tx(skb, read_c0_count());
++#endif
++ }
++#endif /* CONFIG_RA_CLASSIFIER */
++
++#if defined (CONFIG_RALINK_RT3052_MP2)
++ mcast_tx(skb);
++#endif
++
++#if !defined (CONFIG_RALINK_RT6855) && !defined (CONFIG_RALINK_RT6855A) && \
++ !defined(CONFIG_RALINK_MT7621) && !defined (CONFIG_ARCH_MT7623)
++
++#define MIN_PKT_LEN 60
++ if (skb->len < MIN_PKT_LEN) {
++ if (skb_padto(skb, MIN_PKT_LEN)) {
++ printk("raeth: skb_padto failed\n");
++ return 0;
++ }
++ skb_put(skb, MIN_PKT_LEN - skb->len);
++ }
++#endif
++
++ dev->trans_start = jiffies; /* save the timestamp */
++ spin_lock_irqsave(&ei_local->page_lock, flags);
++#if defined (CONFIG_MIPS)
++ dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE);
++#else
++ dma_sync_single_for_device(NULL, virt_to_phys(skb->data), skb->len, DMA_TO_DEVICE);
++
++#endif
++
++#ifdef CONFIG_RALINK_VISTA_BASIC
++ veth = (struct vlan_ethhdr *)(skb->data);
++ if (is_switch_175c && veth->h_vlan_proto == __constant_htons(ETH_P_8021Q)) {
++ if ((veth->h_vlan_TCI & __constant_htons(VLAN_VID_MASK)) == 0) {
++ veth->h_vlan_TCI |= htons(VLAN_DEV_INFO(dev)->vlan_id);
++ }
++ }
++#endif
++
++#if defined (CONFIG_RAETH_QOS)
++ if(pkt_classifier(skb, gmac_no, &ring_no, &queue_no, &port_no)) {
++ get_tx_ctx_idx(ring_no, &tx_cpu_owner_idx);
++ tx_cpu_owner_idx_next = (tx_cpu_owner_idx + 1) % NUM_TX_DESC;
++ if(((ei_local->skb_free[ring_no][tx_cpu_owner_idx]) ==0) && (ei_local->skb_free[ring_no][tx_cpu_owner_idx_next]==0)){
++ fe_qos_packet_send(dev, skb, ring_no, queue_no, port_no);
++ }else{
++ ei_local->stat.tx_dropped++;
++ kfree_skb(skb);
++ spin_unlock_irqrestore(&ei_local->page_lock, flags);
++ return 0;
++ }
++ }
++#else
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ tx_cpu_owner_idx = tx_cpu_owner_idx0;
++#else
++ tx_cpu_owner_idx = sysRegRead(TX_CTX_IDX0);
++#endif
++#if defined (CONFIG_RAETH_TSO)
++// num_of_txd = (nr_frags==0) ? 1 : ((nr_frags>>1) + 1);
++// NumOfTxdUpdate(num_of_txd);
++ if(nr_frags != 0){
++ for(i=0;i<nr_frags;i++) {
++ frag = &skb_shinfo(skb)->frags[i];
++ num_of_txd += cal_frag_txd_num(frag->size);
++ }
++ num_of_txd = (num_of_txd >> 1) + 1;
++ }else
++ num_of_txd = 1;
++
++#else
++ num_of_txd = 1;
++#endif
++ tx_cpu_owner_idx_next = (tx_cpu_owner_idx + num_of_txd) % NUM_TX_DESC;
++
++ if(((ei_local->skb_free[tx_cpu_owner_idx]) ==0) && (ei_local->skb_free[tx_cpu_owner_idx_next]==0)){
++ rt2880_eth_send(dev, skb, gmac_no);
++
++ tx_cpu_owner_idx_next2 = (tx_cpu_owner_idx_next + 1) % NUM_TX_DESC;
++
++ if(ei_local->skb_free[tx_cpu_owner_idx_next2]!=0){
++#if defined (CONFIG_RAETH_SW_FC)
++ netif_stop_queue(dev);
++#ifdef CONFIG_PSEUDO_SUPPORT
++ netif_stop_queue(ei_local->PseudoDev);
++#endif
++ tx_ring_full=1;
++#endif
++ }
++ }else {
++#ifdef CONFIG_PSEUDO_SUPPORT
++ if (gmac_no == 2) {
++ if (ei_local->PseudoDev != NULL) {
++ pAd = netdev_priv(ei_local->PseudoDev);
++ pAd->stat.tx_dropped++;
++ }
++ } else
++#endif
++ ei_local->stat.tx_dropped++;
++#if defined (CONFIG_RAETH_SW_FC)
++ printk("tx_ring_full, drop packet\n");
++#endif
++ kfree_skb(skb);
++ spin_unlock_irqrestore(&ei_local->page_lock, flags);
++ return 0;
++ }
++
++#if defined (CONFIG_RAETH_TSO)
++ /* SG: use multiple TXD to send the packet (only have one skb) */
++ ei_local->skb_free[(tx_cpu_owner_idx + num_of_txd - 1) % NUM_TX_DESC] = skb;
++ while(--num_of_txd) {
++ ei_local->skb_free[(tx_cpu_owner_idx + num_of_txd -1) % NUM_TX_DESC] = (struct sk_buff *)0xFFFFFFFF; //MAGIC ID
++ }
++#else
++ ei_local->skb_free[tx_cpu_owner_idx] = skb;
++#endif
++#endif
++ spin_unlock_irqrestore(&ei_local->page_lock, flags);
++ return 0;
++}
++
++void ei_xmit_housekeeping(unsigned long unused)
++{
++ struct net_device *dev = dev_raether;
++ END_DEVICE *ei_local = netdev_priv(dev);
++ struct PDMA_txdesc *tx_desc;
++ unsigned long skb_free_idx;
++ unsigned long tx_dtx_idx __maybe_unused;
++#ifndef CONFIG_RAETH_NAPI
++ unsigned long reg_int_mask=0;
++#endif
++
++#ifdef CONFIG_RAETH_QOS
++ int i;
++ for (i=0;i<NUM_TX_RINGS;i++){
++ skb_free_idx = ei_local->free_idx[i];
++ if((ei_local->skb_free[i][skb_free_idx])==0){
++ continue;
++ }
++
++ get_tx_desc_and_dtx_idx(ei_local, i, &tx_dtx_idx, &tx_desc);
++
++ while(tx_desc[skb_free_idx].txd_info2.DDONE_bit==1 && (ei_local->skb_free[i][skb_free_idx])!=0 ){
++ dev_kfree_skb_any((ei_local->skb_free[i][skb_free_idx]));
++
++ ei_local->skb_free[i][skb_free_idx]=0;
++ skb_free_idx = (skb_free_idx +1) % NUM_TX_DESC;
++ }
++ ei_local->free_idx[i] = skb_free_idx;
++ }
++#else
++ tx_dtx_idx = sysRegRead(TX_DTX_IDX0);
++ tx_desc = ei_local->tx_ring0;
++ skb_free_idx = ei_local->free_idx;
++ if ((ei_local->skb_free[skb_free_idx]) != 0 && tx_desc[skb_free_idx].txd_info2.DDONE_bit==1) {
++ while(tx_desc[skb_free_idx].txd_info2.DDONE_bit==1 && (ei_local->skb_free[skb_free_idx])!=0 ){
++#if defined (CONFIG_RAETH_TSO)
++ if(ei_local->skb_free[skb_free_idx]!=(struct sk_buff *)0xFFFFFFFF) {
++ dev_kfree_skb_any(ei_local->skb_free[skb_free_idx]);
++ }
++#else
++ dev_kfree_skb_any(ei_local->skb_free[skb_free_idx]);
++#endif
++ ei_local->skb_free[skb_free_idx]=0;
++ skb_free_idx = (skb_free_idx +1) % NUM_TX_DESC;
++ }
++
++ netif_wake_queue(dev);
++#ifdef CONFIG_PSEUDO_SUPPORT
++ netif_wake_queue(ei_local->PseudoDev);
++#endif
++ tx_ring_full=0;
++ ei_local->free_idx = skb_free_idx;
++ } /* if skb_free != 0 */
++#endif
++
++#ifndef CONFIG_RAETH_NAPI
++ reg_int_mask=sysRegRead(FE_INT_ENABLE);
++#if defined (DELAY_INT)
++ sysRegWrite(FE_INT_ENABLE, reg_int_mask| TX_DLY_INT);
++#else
++
++ sysRegWrite(FE_INT_ENABLE, reg_int_mask | TX_DONE_INT0 \
++ | TX_DONE_INT1 \
++ | TX_DONE_INT2 \
++ | TX_DONE_INT3);
++#endif
++#endif //CONFIG_RAETH_NAPI//
++}
++
++
++
++EXPORT_SYMBOL(ei_start_xmit);
++EXPORT_SYMBOL(ei_xmit_housekeeping);
++EXPORT_SYMBOL(fe_dma_init);
++EXPORT_SYMBOL(rt2880_eth_send);
+diff --git a/drivers/net/ethernet/raeth/raether_qdma.c b/drivers/net/ethernet/raeth/raether_qdma.c
+new file mode 100644
+index 0000000..acf8bfe
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/raether_qdma.c
+@@ -0,0 +1,1407 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <linux/if_vlan.h>
++#include <linux/if_ether.h>
++#include <linux/fs.h>
++#include <asm/uaccess.h>
++#include <asm/rt2880/surfboardint.h>
++#if defined (CONFIG_RAETH_TSO)
++#include <linux/tcp.h>
++#include <net/ipv6.h>
++#include <linux/ip.h>
++#include <net/ip.h>
++#include <net/tcp.h>
++#include <linux/in.h>
++#include <linux/ppp_defs.h>
++#include <linux/if_pppox.h>
++#endif
++#include <linux/delay.h>
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++#include <linux/sched.h>
++#endif
++#if defined (CONFIG_HW_SFQ)
++#include <linux/if_vlan.h>
++#include <net/ipv6.h>
++#include <net/ip.h>
++#include <linux/if_pppox.h>
++#include <linux/ppp_defs.h>
++#endif
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
++#include <asm/rt2880/rt_mmap.h>
++#else
++#include <linux/libata-compat.h>
++#endif
++
++#include "ra2882ethreg.h"
++#include "raether.h"
++#include "ra_mac.h"
++#include "ra_ioctl.h"
++#include "ra_rfrw.h"
++#ifdef CONFIG_RAETH_NETLINK
++#include "ra_netlink.h"
++#endif
++#if defined (CONFIG_RAETH_QOS)
++#include "ra_qos.h"
++#endif
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++#include "../../../net/nat/hw_nat/ra_nat.h"
++#endif
++
++
++#if !defined(CONFIG_RA_NAT_NONE)
++/* bruce+
++ */
++extern int (*ra_sw_nat_hook_rx)(struct sk_buff *skb);
++extern int (*ra_sw_nat_hook_tx)(struct sk_buff *skb, int gmac_no);
++#endif
++
++#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE)
++/* Qwert+
++ */
++#include <asm/mipsregs.h>
++extern int (*ra_classifier_hook_tx)(struct sk_buff *skb, unsigned long cur_cycle);
++extern int (*ra_classifier_hook_rx)(struct sk_buff *skb, unsigned long cur_cycle);
++#endif /* CONFIG_RA_CLASSIFIER */
++
++#if defined (CONFIG_RALINK_RT3052_MP2)
++int32_t mcast_rx(struct sk_buff * skb);
++int32_t mcast_tx(struct sk_buff * skb);
++#endif
++
++#ifdef RA_MTD_RW_BY_NUM
++int ra_mtd_read(int num, loff_t from, size_t len, u_char *buf);
++#else
++int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf);
++#endif
++
++/* gmac driver feature set config */
++#if defined (CONFIG_RAETH_NAPI) || defined (CONFIG_RAETH_QOS)
++#undef DELAY_INT
++#else
++#if defined (CONFIG_ARCH_MT7623)
++#undef DELAY_INT
++#else
++#define DELAY_INT 1
++#endif
++#endif
++
++//#define CONFIG_UNH_TEST
++/* end of config */
++
++#if defined (CONFIG_RAETH_JUMBOFRAME)
++#define MAX_RX_LENGTH 4096
++#else
++#define MAX_RX_LENGTH 1536
++#endif
++
++extern struct net_device *dev_raether;
++
++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++static int rx_dma_owner_idx1;
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++static int rx_calc_idx1;
++#endif
++#endif
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++static int rx_calc_idx0;
++static unsigned long tx_cpu_owner_idx0=0;
++#endif
++extern unsigned long tx_ring_full;
++
++#if defined (CONFIG_ETHTOOL) && defined (CONFIG_RAETH_ROUTER)
++#include "ra_ethtool.h"
++extern struct ethtool_ops ra_ethtool_ops;
++#ifdef CONFIG_PSEUDO_SUPPORT
++extern struct ethtool_ops ra_virt_ethtool_ops;
++#endif // CONFIG_PSEUDO_SUPPORT //
++#endif // (CONFIG_ETHTOOL //
++
++#ifdef CONFIG_RALINK_VISTA_BASIC
++int is_switch_175c = 1;
++#endif
++
++//skb->mark to queue mapping table
++extern unsigned int M2Q_table[64];
++struct QDMA_txdesc *free_head = NULL;
++extern unsigned int lan_wan_separate;
++#if defined (CONFIG_HW_SFQ)
++extern unsigned int web_sfq_enable;
++#define HwSfqQUp 3
++#define HwSfqQDl 1
++#endif
++int dbg =0;//debug used
++#if defined (CONFIG_HW_SFQ)
++struct SFQ_table *sfq0;
++struct SFQ_table *sfq1;
++struct SFQ_table *sfq2;
++struct SFQ_table *sfq3;
++#endif
++
++#define KSEG1 0xa0000000
++#if defined (CONFIG_MIPS)
++#define PHYS_TO_VIRT(x) ((void *)((x) | KSEG1))
++#define VIRT_TO_PHYS(x) ((unsigned long)(x) & ~KSEG1)
++#else
++#define PHYS_TO_VIRT(x) phys_to_virt(x)
++#define VIRT_TO_PHYS(x) virt_to_phys(x)
++#endif
++
++extern void set_fe_dma_glo_cfg(void);
++
++#if defined (CONFIG_HW_SFQ)
++ParseResult SfqParseResult;
++#endif
++
++/**
++ *
++ * @brief: get the TXD index from its address
++ *
++ * @param: cpu_ptr
++ *
++ * @return: TXD index
++*/
++
++static unsigned int GET_TXD_OFFSET(struct QDMA_txdesc **cpu_ptr)
++{
++ struct net_device *dev = dev_raether;
++ END_DEVICE *ei_local = netdev_priv(dev);
++ int ctx_offset;
++ //ctx_offset = (((((u32)*cpu_ptr) <<8)>>8) - ((((u32)ei_local->txd_pool)<<8)>>8))/ sizeof(struct QDMA_txdesc);
++ //ctx_offset = (*cpu_ptr - ei_local->txd_pool);
++ ctx_offset = (((((u32)*cpu_ptr) <<8)>>8) - ((((u32)ei_local->phy_txd_pool)<<8)>>8))/ sizeof(struct QDMA_txdesc);
++
++ return ctx_offset;
++}
++
++
++
++
++/**
++ * @brief cal txd number for a page
++ *
++ * @parm size
++ *
++ * @return frag_txd_num
++ */
++
++unsigned int cal_frag_txd_num(unsigned int size)
++{
++ unsigned int frag_txd_num = 0;
++ if(size == 0)
++ return 0;
++ while(size > 0){
++ if(size > MAX_TXD_LEN){
++ frag_txd_num++;
++ size -= MAX_TXD_LEN;
++ }else{
++ frag_txd_num++;
++ size = 0;
++ }
++ }
++ return frag_txd_num;
++
++}
++
++/**
++ * @brief get free TXD from TXD queue
++ *
++ * @param free_txd
++ *
++ * @return
++ */
++static int get_free_txd(struct QDMA_txdesc **free_txd)
++{
++ struct net_device *dev = dev_raether;
++ END_DEVICE *ei_local = netdev_priv(dev);
++ unsigned int tmp_idx;
++
++ if(ei_local->free_txd_num > 0){
++ tmp_idx = ei_local->free_txd_head;
++ ei_local->free_txd_head = ei_local->txd_pool_info[tmp_idx];
++ ei_local->free_txd_num -= 1;
++ //*free_txd = &ei_local->txd_pool[tmp_idx];
++ *free_txd = ei_local->phy_txd_pool + (sizeof(struct QDMA_txdesc) * tmp_idx);
++ return tmp_idx;
++ }else
++ return NUM_TX_DESC;
++}
++
++
++/**
++ * @brief add free TXD into TXD queue
++ *
++ * @param free_txd
++ *
++ * @return
++ */
++int put_free_txd(int free_txd_idx)
++{
++ struct net_device *dev = dev_raether;
++ END_DEVICE *ei_local = netdev_priv(dev);
++ ei_local->txd_pool_info[ei_local->free_txd_tail] = free_txd_idx;
++ ei_local->free_txd_tail = free_txd_idx;
++ ei_local->txd_pool_info[free_txd_idx] = NUM_TX_DESC;
++ ei_local->free_txd_num += 1;
++ return 1;
++}
++
++/*define qdma initial alloc*/
++/**
++ * @brief
++ *
++ * @param net_dev
++ *
++ * @return 0: fail
++ * 1: success
++ */
++bool qdma_tx_desc_alloc(void)
++{
++ struct net_device *dev = dev_raether;
++ END_DEVICE *ei_local = netdev_priv(dev);
++ struct QDMA_txdesc *free_txd = NULL;
++ unsigned int txd_idx;
++ int i = 0;
++
++
++ ei_local->txd_pool = pci_alloc_consistent(NULL, sizeof(struct QDMA_txdesc) * NUM_TX_DESC, &ei_local->phy_txd_pool);
++ printk("txd_pool=%p phy_txd_pool=%08X\n", ei_local->txd_pool , ei_local->phy_txd_pool);
++
++ if (ei_local->txd_pool == NULL) {
++ printk("adapter->txd_pool allocation failed!\n");
++ return 0;
++ }
++ printk("ei_local->skb_free start address is 0x%p.\n", ei_local->skb_free);
++ //set all txd_pool_info to 0.
++ for ( i = 0; i < NUM_TX_DESC; i++)
++ {
++ ei_local->skb_free[i]= 0;
++ ei_local->txd_pool_info[i] = i + 1;
++ ei_local->txd_pool[i].txd_info3.LS_bit = 1;
++ ei_local->txd_pool[i].txd_info3.OWN_bit = 1;
++ }
++
++ ei_local->free_txd_head = 0;
++ ei_local->free_txd_tail = NUM_TX_DESC - 1;
++ ei_local->free_txd_num = NUM_TX_DESC;
++
++
++ //get free txd from txd pool
++ txd_idx = get_free_txd(&free_txd);
++ if( txd_idx == NUM_TX_DESC) {
++ printk("get_free_txd fail\n");
++ return 0;
++ }
++
++ //add null TXD for transmit
++ //ei_local->tx_dma_ptr = VIRT_TO_PHYS(free_txd);
++ //ei_local->tx_cpu_ptr = VIRT_TO_PHYS(free_txd);
++ ei_local->tx_dma_ptr = free_txd;
++ ei_local->tx_cpu_ptr = free_txd;
++ sysRegWrite(QTX_CTX_PTR, ei_local->tx_cpu_ptr);
++ sysRegWrite(QTX_DTX_PTR, ei_local->tx_dma_ptr);
++
++ //get free txd from txd pool
++
++ txd_idx = get_free_txd(&free_txd);
++ if( txd_idx == NUM_TX_DESC) {
++ printk("get_free_txd fail\n");
++ return 0;
++ }
++ // add null TXD for release
++ //sysRegWrite(QTX_CRX_PTR, VIRT_TO_PHYS(free_txd));
++ //sysRegWrite(QTX_DRX_PTR, VIRT_TO_PHYS(free_txd));
++ sysRegWrite(QTX_CRX_PTR, free_txd);
++ sysRegWrite(QTX_DRX_PTR, free_txd);
++ printk("free_txd: %p, ei_local->cpu_ptr: %08X\n", free_txd, ei_local->tx_cpu_ptr);
++
++ printk(" POOL HEAD_PTR | DMA_PTR | CPU_PTR \n");
++ printk("----------------+---------+--------\n");
++ printk(" 0x%p 0x%08X 0x%08X\n",ei_local->txd_pool, ei_local->tx_dma_ptr, ei_local->tx_cpu_ptr);
++ return 1;
++}
++#if defined (CONFIG_HW_SFQ)
++bool sfq_init(void)
++{
++ unsigned int regVal;
++
++ unsigned int sfq_phy0;
++ unsigned int sfq_phy1;
++ unsigned int sfq_phy2;
++ unsigned int sfq_phy3;
++ struct SFQ_table *sfq0;
++ struct SFQ_table *sfq1;
++ struct SFQ_table *sfq2;
++ struct SFQ_table *sfq3;
++ int i = 0;
++ regVal = sysRegRead(VQTX_GLO);
++ regVal = regVal | VQTX_MIB_EN |(1<<16) ;
++ sysRegWrite(VQTX_GLO, regVal);// Virtual table extends to 32bytes
++ regVal = sysRegRead(VQTX_GLO);
++ sysRegWrite(VQTX_NUM, (VQTX_NUM_0) | (VQTX_NUM_1) | (VQTX_NUM_2) | (VQTX_NUM_3));
++ sysRegWrite(VQTX_HASH_CFG, 0xF002710); //10 s change hash algorithm
++ sysRegWrite(VQTX_VLD_CFG, 0x00);
++ sysRegWrite(VQTX_HASH_SD, 0x0D);
++ sysRegWrite(QDMA_FC_THRES, 0x9b9b4444);
++ sysRegWrite(QDMA_HRED1, 0);
++ sysRegWrite(QDMA_HRED2, 0);
++ sysRegWrite(QDMA_SRED1, 0);
++ sysRegWrite(QDMA_SRED2, 0);
++ sfq0 = pci_alloc_consistent(NULL, 256*sizeof(struct SFQ_table), &sfq_phy0);
++ memset(sfq0, 0x0, 256*sizeof(struct SFQ_table) );
++ for (i=0; i < 256; i++) {
++ sfq0[i].sfq_info1.VQHPTR = 0xdeadbeef;
++ sfq0[i].sfq_info2.VQTPTR = 0xdeadbeef;
++ }
++#if(1)
++ sfq1 = pci_alloc_consistent(NULL, 256*sizeof(struct SFQ_table), &sfq_phy1);
++
++ memset(sfq1, 0x0, 256*sizeof(struct SFQ_table) );
++ for (i=0; i < 256; i++) {
++ sfq1[i].sfq_info1.VQHPTR = 0xdeadbeef;
++ sfq1[i].sfq_info2.VQTPTR = 0xdeadbeef;
++ }
++
++ sfq2 = pci_alloc_consistent(NULL, 256*sizeof(struct SFQ_table), &sfq_phy2);
++ memset(sfq2, 0x0, 256*sizeof(struct SFQ_table) );
++ for (i=0; i < 256; i++) {
++ sfq2[i].sfq_info1.VQHPTR = 0xdeadbeef;
++ sfq2[i].sfq_info2.VQTPTR = 0xdeadbeef;
++ }
++
++ sfq3 = pci_alloc_consistent(NULL, 256*sizeof(struct SFQ_table), &sfq_phy3);
++ memset(sfq3, 0x0, 256*sizeof(struct SFQ_table) );
++ for (i=0; i < 256; i++) {
++ sfq3[i].sfq_info1.VQHPTR = 0xdeadbeef;
++ sfq3[i].sfq_info2.VQTPTR = 0xdeadbeef;
++ }
++
++#endif
++ printk("*****sfq_phy0 is 0x%x!!!*******\n", sfq_phy0);
++ printk("*****sfq_phy1 is 0x%x!!!*******\n", sfq_phy1);
++ printk("*****sfq_phy2 is 0x%x!!!*******\n", sfq_phy2);
++ printk("*****sfq_phy3 is 0x%x!!!*******\n", sfq_phy3);
++ printk("*****sfq_virt0 is 0x%x!!!*******\n", sfq0);
++ printk("*****sfq_virt1 is 0x%x!!!*******\n", sfq1);
++ printk("*****sfq_virt2 is 0x%x!!!*******\n", sfq2);
++ printk("*****sfq_virt3 is 0x%x!!!*******\n", sfq3);
++ printk("*****sfq_virt0 is 0x%x!!!*******\n", sfq0);
++ sysRegWrite(VQTX_TB_BASE0, (u32)sfq_phy0);
++ sysRegWrite(VQTX_TB_BASE1, (u32)sfq_phy1);
++ sysRegWrite(VQTX_TB_BASE2, (u32)sfq_phy2);
++ sysRegWrite(VQTX_TB_BASE3, (u32)sfq_phy3);
++
++ return 1;
++}
++#endif
++bool fq_qdma_init(struct net_device *dev)
++{
++ END_DEVICE* ei_local = netdev_priv(dev);
++ //struct QDMA_txdesc *free_head = NULL;
++ unsigned int phy_free_head;
++ unsigned int phy_free_tail;
++ unsigned int *free_page_head = NULL;
++ unsigned int phy_free_page_head;
++ int i;
++
++ free_head = pci_alloc_consistent(NULL, NUM_QDMA_PAGE * sizeof(struct QDMA_txdesc), &phy_free_head);
++ if (unlikely(free_head == NULL)){
++ printk(KERN_ERR "QDMA FQ decriptor not available...\n");
++ return 0;
++ }
++ memset(free_head, 0x0, sizeof(struct QDMA_txdesc) * NUM_QDMA_PAGE);
++
++ free_page_head = pci_alloc_consistent(NULL, NUM_QDMA_PAGE * QDMA_PAGE_SIZE, &phy_free_page_head);
++ if (unlikely(free_page_head == NULL)){
++ printk(KERN_ERR "QDMA FQ page not available...\n");
++ return 0;
++ }
++ for (i=0; i < NUM_QDMA_PAGE; i++) {
++ free_head[i].txd_info1.SDP = (phy_free_page_head + (i * QDMA_PAGE_SIZE));
++ if(i < (NUM_QDMA_PAGE-1)){
++ free_head[i].txd_info2.NDP = (phy_free_head + ((i+1) * sizeof(struct QDMA_txdesc)));
++
++
++#if 0
++ printk("free_head_phy[%d] is 0x%x!!!\n",i, VIRT_TO_PHYS(&free_head[i]) );
++ printk("free_head[%d] is 0x%x!!!\n",i, &free_head[i] );
++ printk("free_head[%d].txd_info1.SDP is 0x%x!!!\n",i, free_head[i].txd_info1.SDP );
++ printk("free_head[%d].txd_info2.NDP is 0x%x!!!\n",i, free_head[i].txd_info2.NDP );
++#endif
++ }
++ free_head[i].txd_info3.SDL = QDMA_PAGE_SIZE;
++
++ }
++ phy_free_tail = (phy_free_head + (u32)((NUM_QDMA_PAGE-1) * sizeof(struct QDMA_txdesc)));
++
++ printk("phy_free_head is 0x%x!!!\n", phy_free_head);
++ printk("phy_free_tail_phy is 0x%x!!!\n", phy_free_tail);
++ sysRegWrite(QDMA_FQ_HEAD, (u32)phy_free_head);
++ sysRegWrite(QDMA_FQ_TAIL, (u32)phy_free_tail);
++ sysRegWrite(QDMA_FQ_CNT, ((NUM_TX_DESC << 16) | NUM_QDMA_PAGE));
++ sysRegWrite(QDMA_FQ_BLEN, QDMA_PAGE_SIZE << 16);
++
++ ei_local->free_head = free_head;
++ ei_local->phy_free_head = phy_free_head;
++ ei_local->free_page_head = free_page_head;
++ ei_local->phy_free_page_head = phy_free_page_head;
++ return 1;
++}
++
++int fe_dma_init(struct net_device *dev)
++{
++
++ int i;
++ unsigned int regVal;
++ END_DEVICE* ei_local = netdev_priv(dev);
++
++
++ #if defined (CONFIG_HW_SFQ)
++ sfq_init();
++ #endif
++ fq_qdma_init(dev);
++
++ while(1)
++ {
++ regVal = sysRegRead(QDMA_GLO_CFG);
++ if((regVal & RX_DMA_BUSY))
++ {
++ printk("\n RX_DMA_BUSY !!! ");
++ continue;
++ }
++ if((regVal & TX_DMA_BUSY))
++ {
++ printk("\n TX_DMA_BUSY !!! ");
++ continue;
++ }
++ break;
++ }
++ /*tx desc alloc, add a NULL TXD to HW*/
++
++ qdma_tx_desc_alloc();
++
++ /* Initial RX Ring 0*/
++
++#ifdef CONFIG_32B_DESC
++ ei_local->qrx_ring = kmalloc(NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL);
++ ei_local->phy_qrx_ring = virt_to_phys(ei_local->qrx_ring);
++#else
++ ei_local->qrx_ring = pci_alloc_consistent(NULL, NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_qrx_ring);
++#endif
++ for (i = 0; i < NUM_QRX_DESC; i++) {
++ memset(&ei_local->qrx_ring[i],0,sizeof(struct PDMA_rxdesc));
++ ei_local->qrx_ring[i].rxd_info2.DDONE_bit = 0;
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++ ei_local->qrx_ring[i].rxd_info2.LS0 = 0;
++ ei_local->qrx_ring[i].rxd_info2.PLEN0 = MAX_RX_LENGTH;
++#else
++ ei_local->qrx_ring[i].rxd_info2.LS0 = 1;
++#endif
++ ei_local->qrx_ring[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx0_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++ }
++ printk("\nphy_qrx_ring = 0x%08x, qrx_ring = 0x%p\n",ei_local->phy_qrx_ring,ei_local->qrx_ring);
++
++ regVal = sysRegRead(QDMA_GLO_CFG);
++ regVal &= 0x000000FF;
++
++ sysRegWrite(QDMA_GLO_CFG, regVal);
++ regVal=sysRegRead(QDMA_GLO_CFG);
++
++ /* Tell the adapter where the TX/RX rings are located. */
++
++ sysRegWrite(QRX_BASE_PTR_0, phys_to_bus((u32) ei_local->phy_qrx_ring));
++ sysRegWrite(QRX_MAX_CNT_0, cpu_to_le32((u32) NUM_QRX_DESC));
++ sysRegWrite(QRX_CRX_IDX_0, cpu_to_le32((u32) (NUM_QRX_DESC - 1)));
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ rx_calc_idx0 = rx_dma_owner_idx0 = sysRegRead(QRX_CRX_IDX_0);
++#endif
++ sysRegWrite(QDMA_RST_CFG, PST_DRX_IDX0);
++
++ ei_local->rx_ring0 = ei_local->qrx_ring;
++#if !defined (CONFIG_RAETH_QDMATX_QDMARX)
++ /* Initial PDMA RX Ring 0*/
++#ifdef CONFIG_32B_DESC
++ ei_local->rx_ring0 = kmalloc(NUM_RX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL);
++ ei_local->phy_rx_ring0 = virt_to_phys(ei_local->rx_ring0);
++#else
++ ei_local->rx_ring0 = pci_alloc_consistent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring0);
++#endif
++ for (i = 0; i < NUM_RX_DESC; i++) {
++ memset(&ei_local->rx_ring0[i],0,sizeof(struct PDMA_rxdesc));
++ ei_local->rx_ring0[i].rxd_info2.DDONE_bit = 0;
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++ ei_local->rx_ring0[i].rxd_info2.LS0 = 0;
++ ei_local->rx_ring0[i].rxd_info2.PLEN0 = MAX_RX_LENGTH;
++#else
++ ei_local->rx_ring0[i].rxd_info2.LS0 = 1;
++#endif
++ ei_local->rx_ring0[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx0_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++ }
++ printk("\nphy_rx_ring0 = 0x%08x, rx_ring0 = 0x%p\n",ei_local->phy_rx_ring0,ei_local->rx_ring0);
++
++ regVal = sysRegRead(PDMA_GLO_CFG);
++ regVal &= 0x000000FF;
++ sysRegWrite(PDMA_GLO_CFG, regVal);
++ regVal=sysRegRead(PDMA_GLO_CFG);
++
++ sysRegWrite(RX_BASE_PTR0, phys_to_bus((u32) ei_local->phy_rx_ring0));
++ sysRegWrite(RX_MAX_CNT0, cpu_to_le32((u32) NUM_RX_DESC));
++ sysRegWrite(RX_CALC_IDX0, cpu_to_le32((u32) (NUM_RX_DESC - 1)));
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ rx_calc_idx0 = sysRegRead(RX_CALC_IDX0);
++#endif
++ sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX0);
++#endif
++#if !defined (CONFIG_HW_SFQ)
++ /* Enable randon early drop and set drop threshold automatically */
++ sysRegWrite(QDMA_FC_THRES, 0x174444);
++#endif
++ sysRegWrite(QDMA_HRED2, 0x0);
++ set_fe_dma_glo_cfg();
++#if defined (CONFIG_ARCH_MT7623)
++ printk("Enable QDMA TX NDP coherence check and re-read mechanism\n");
++ regVal=sysRegRead(QDMA_GLO_CFG);
++ regVal = regVal | 0x400;
++ sysRegWrite(QDMA_GLO_CFG, regVal);
++ printk("***********QDMA_GLO_CFG=%x\n", sysRegRead(QDMA_GLO_CFG));
++#endif
++
++ return 1;
++}
++
++#if defined (CONFIG_HW_SFQ)
++
++int sfq_prot = 0;
++int proto_id=0;
++int udp_source_port=0;
++int tcp_source_port=0;
++int ack_packt =0;
++int SfqParseLayerInfo(struct sk_buff * skb)
++{
++
++ struct vlan_hdr *vh_sfq = NULL;
++ struct ethhdr *eth_sfq = NULL;
++ struct iphdr *iph_sfq = NULL;
++ struct ipv6hdr *ip6h_sfq = NULL;
++ struct tcphdr *th_sfq = NULL;
++ struct udphdr *uh_sfq = NULL;
++#ifdef CONFIG_RAETH_HW_VLAN_TX
++ struct vlan_hdr pseudo_vhdr_sfq;
++#endif
++
++ memset(&SfqParseResult, 0, sizeof(SfqParseResult));
++
++ eth_sfq = (struct ethhdr *)skb->data;
++ memcpy(SfqParseResult.dmac, eth_sfq->h_dest, ETH_ALEN);
++ memcpy(SfqParseResult.smac, eth_sfq->h_source, ETH_ALEN);
++ SfqParseResult.eth_type = eth_sfq->h_proto;
++
++
++ if (SfqParseResult.eth_type == htons(ETH_P_8021Q)){
++ SfqParseResult.vlan1_gap = VLAN_HLEN;
++ vh_sfq = (struct vlan_hdr *)(skb->data + ETH_HLEN);
++ SfqParseResult.eth_type = vh_sfq->h_vlan_encapsulated_proto;
++ }else{
++ SfqParseResult.vlan1_gap = 0;
++ }
++
++
++
++ LAYER2_HEADER(skb) = skb->data;
++ LAYER3_HEADER(skb) = (skb->data + ETH_HLEN + (SfqParseResult.vlan1_gap));
++
++
++
++ /* set layer4 start addr */
++ if ((SfqParseResult.eth_type == htons(ETH_P_IP)) || (SfqParseResult.eth_type == htons(ETH_P_PPP_SES)
++ && SfqParseResult.ppp_tag == htons(PPP_IP))) {
++ iph_sfq = (struct iphdr *)LAYER3_HEADER(skb);
++
++ //prepare layer3/layer4 info
++ memcpy(&SfqParseResult.iph, iph_sfq, sizeof(struct iphdr));
++ if (iph_sfq->protocol == IPPROTO_TCP) {
++
++ LAYER4_HEADER(skb) = ((uint8_t *) iph_sfq + (iph_sfq->ihl * 4));
++ th_sfq = (struct tcphdr *)LAYER4_HEADER(skb);
++ memcpy(&SfqParseResult.th, th_sfq, sizeof(struct tcphdr));
++ SfqParseResult.pkt_type = IPV4_HNAPT;
++ //printk("tcp parsing\n");
++ tcp_source_port = ntohs(SfqParseResult.th.source);
++ udp_source_port = 0;
++ #if(0) //for TCP ack, test use
++ if(ntohl(SfqParseResult.iph.saddr) == 0xa0a0a04){ // tcp ack packet
++ ack_packt = 1;
++ }else {
++ ack_packt = 0;
++ }
++ #endif
++ sfq_prot = 2;//IPV4_HNAPT
++ proto_id = 1;//TCP
++ if(iph_sfq->frag_off & htons(IP_MF|IP_OFFSET)) {
++ //return 1;
++ }
++ } else if (iph_sfq->protocol == IPPROTO_UDP) {
++ LAYER4_HEADER(skb) = ((uint8_t *) iph_sfq + iph_sfq->ihl * 4);
++ uh_sfq = (struct udphdr *)LAYER4_HEADER(skb);
++ memcpy(&SfqParseResult.uh, uh_sfq, sizeof(struct udphdr));
++ SfqParseResult.pkt_type = IPV4_HNAPT;
++ udp_source_port = ntohs(SfqParseResult.uh.source);
++ tcp_source_port = 0;
++ ack_packt = 0;
++ sfq_prot = 2;//IPV4_HNAPT
++ proto_id =2;//UDP
++ if(iph_sfq->frag_off & htons(IP_MF|IP_OFFSET)) {
++ return 1;
++ }
++ }else{
++ sfq_prot = 1;
++ }
++ }else if (SfqParseResult.eth_type == htons(ETH_P_IPV6) ||
++ (SfqParseResult.eth_type == htons(ETH_P_PPP_SES) &&
++ SfqParseResult.ppp_tag == htons(PPP_IPV6))) {
++ ip6h_sfq = (struct ipv6hdr *)LAYER3_HEADER(skb);
++ memcpy(&SfqParseResult.ip6h, ip6h_sfq, sizeof(struct ipv6hdr));
++
++ if (ip6h_sfq->nexthdr == NEXTHDR_TCP) {
++ LAYER4_HEADER(skb) = ((uint8_t *) ip6h_sfq + sizeof(struct ipv6hdr));
++ th_sfq = (struct tcphdr *)LAYER4_HEADER(skb);
++ memcpy(&SfqParseResult.th, th_sfq, sizeof(struct tcphdr));
++ SfqParseResult.pkt_type = IPV6_5T_ROUTE;
++ sfq_prot = 4;//IPV6_5T
++ #if(0) //for TCP ack, test use
++ if(ntohl(SfqParseResult.ip6h.saddr.s6_addr32[3]) == 8){
++ ack_packt = 1;
++ }else {
++ ack_packt = 0;
++ }
++ #endif
++ } else if (ip6h_sfq->nexthdr == NEXTHDR_UDP) {
++ LAYER4_HEADER(skb) = ((uint8_t *) ip6h_sfq + sizeof(struct ipv6hdr));
++ uh_sfq = (struct udphdr *)LAYER4_HEADER(skb);
++ memcpy(&SfqParseResult.uh, uh_sfq, sizeof(struct udphdr));
++ SfqParseResult.pkt_type = IPV6_5T_ROUTE;
++ ack_packt = 0;
++ sfq_prot = 4;//IPV6_5T
++
++ }else{
++ sfq_prot = 3;//IPV6_3T
++ }
++ }
++
++ return 0;
++}
++#endif
++
++inline int rt2880_eth_send(struct net_device* dev, struct sk_buff *skb, int gmac_no)
++{
++ unsigned int length=skb->len;
++ END_DEVICE* ei_local = netdev_priv(dev);
++
++ struct QDMA_txdesc *cpu_ptr;
++
++ struct QDMA_txdesc *dma_ptr __maybe_unused;
++ struct QDMA_txdesc *free_txd;
++ int ctx_offset;
++#if defined (CONFIG_RAETH_TSO)
++ struct iphdr *iph = NULL;
++ struct QDMA_txdesc *init_cpu_ptr;
++ struct tcphdr *th = NULL;
++ struct skb_frag_struct *frag;
++ unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
++ unsigned int len, size, offset, frag_txd_num;
++ int init_txd_idx, i;
++#endif // CONFIG_RAETH_TSO //
++
++#if defined (CONFIG_RAETH_TSOV6)
++ struct ipv6hdr *ip6h = NULL;
++#endif
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++ PSEUDO_ADAPTER *pAd;
++#endif
++ //cpu_ptr = PHYS_TO_VIRT(ei_local->tx_cpu_ptr);
++ //dma_ptr = PHYS_TO_VIRT(ei_local->tx_dma_ptr);
++ //ctx_offset = GET_TXD_OFFSET(&cpu_ptr);
++ cpu_ptr = (ei_local->tx_cpu_ptr);
++ ctx_offset = GET_TXD_OFFSET(&cpu_ptr);
++ cpu_ptr = phys_to_virt(ei_local->tx_cpu_ptr);
++ dma_ptr = phys_to_virt(ei_local->tx_dma_ptr);
++ cpu_ptr = (ei_local->txd_pool + (ctx_offset));
++ ei_local->skb_free[ctx_offset] = skb;
++#if defined (CONFIG_RAETH_TSO)
++ init_cpu_ptr = cpu_ptr;
++ init_txd_idx = ctx_offset;
++#endif
++
++#if !defined (CONFIG_RAETH_TSO)
++
++ //2. prepare data
++ //cpu_ptr->txd_info1.SDP = VIRT_TO_PHYS(skb->data);
++ cpu_ptr->txd_info1.SDP = virt_to_phys(skb->data);
++ cpu_ptr->txd_info3.SDL = skb->len;
++#if defined (CONFIG_HW_SFQ)
++ SfqParseLayerInfo(skb);
++ cpu_ptr->txd_info4.VQID0 = 1;//1:HW hash 0:CPU
++
++
++#if(0)// for tcp ack use, test use
++ if (ack_packt==1){
++ cpu_ptr->txd_info3.QID = 0x0a;
++ //cpu_ptr->txd_info3.VQID = 0;
++ }else{
++ cpu_ptr->txd_info3.QID = 0;
++ }
++#endif
++ cpu_ptr->txd_info3.PROT = sfq_prot;
++ cpu_ptr->txd_info3.IPOFST = 14 + (SfqParseResult.vlan1_gap); //no vlan
++
++#endif
++ if (gmac_no == 1) {
++ cpu_ptr->txd_info4.FPORT = 1;
++ }else {
++ cpu_ptr->txd_info4.FPORT = 2;
++ }
++
++ cpu_ptr->txd_info3.QID = M2Q_table[skb->mark];
++#ifdef CONFIG_PSEUDO_SUPPORT
++ if((lan_wan_separate==1) && (gmac_no==2)){
++ cpu_ptr->txd_info3.QID += 8;
++#if defined (CONFIG_HW_SFQ)
++ if(web_sfq_enable==1 &&(skb->mark == 2)){
++ cpu_ptr->txd_info3.QID = HwSfqQUp;
++ }
++#endif
++ }
++#if defined (CONFIG_HW_SFQ)
++ if((lan_wan_separate==1) && (gmac_no==1)){
++ if(web_sfq_enable==1 &&(skb->mark == 2)){
++ cpu_ptr->txd_info3.QID = HwSfqQDl;
++ }
++ }
++#endif
++#endif //end CONFIG_PSEUDO_SUPPORT
++
++ if(dbg==1){
++ printk("M2Q_table[%d]=%d\n", skb->mark, M2Q_table[skb->mark]);
++ printk("cpu_ptr->txd_info3.QID = %d\n", cpu_ptr->txd_info3.QID);
++ }
++#if 0
++ iph = (struct iphdr *)skb_network_header(skb);
++ if (iph->tos == 0xe0)
++ cpu_ptr->txd_info3.QID = 3;
++ else if (iph->tos == 0xa0)
++ cpu_ptr->txd_info3.QID = 2;
++ else if (iph->tos == 0x20)
++ cpu_ptr->txd_info3.QID = 1;
++ else
++ cpu_ptr->txd_info3.QID = 0;
++#endif
++
++#if defined (CONFIG_RAETH_CHECKSUM_OFFLOAD) && ! defined(CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628)
++ if (skb->ip_summed == CHECKSUM_PARTIAL){
++ cpu_ptr->txd_info4.TUI_CO = 7;
++ }else {
++ cpu_ptr->txd_info4.TUI_CO = 0;
++ }
++#endif
++
++#ifdef CONFIG_RAETH_HW_VLAN_TX
++ if(vlan_tx_tag_present(skb)) {
++ cpu_ptr->txd_info4.VLAN_TAG = 0x10000 | vlan_tx_tag_get(skb);
++ }else {
++ cpu_ptr->txd_info4.VLAN_TAG = 0;
++ }
++#endif
++
++#ifdef CONFIG_RAETH_HW_VLAN_TX // QoS Web UI used
++
++ if((lan_wan_separate==1) && (vlan_tx_tag_get(skb)==2)){
++ cpu_ptr->txd_info3.QID += 8;
++#if defined (CONFIG_HW_SFQ)
++ if(web_sfq_enable==1 &&(skb->mark == 2)){
++ cpu_ptr->txd_info3.QID = HwSfqQUp;
++ }
++#endif
++ }
++#if defined (CONFIG_HW_SFQ)
++ if((lan_wan_separate==1) && (vlan_tx_tag_get(skb)==1)){
++ if(web_sfq_enable==1 &&(skb->mark == 2)){
++ cpu_ptr->txd_info3.QID = HwSfqQDl;
++ }
++ }
++#endif
++#endif // CONFIG_RAETH_HW_VLAN_TX
++
++
++//no hw van, no GE2, web UI used
++#ifndef CONFIG_PSEUDO_SUPPORT
++#ifndef CONFIG_RAETH_HW_VLAN_TX
++ if(lan_wan_separate==1){
++ struct vlan_hdr *vh = NULL;
++ unsigned short vlanid = 0;
++ unsigned short vlan_TCI;
++ vh = (struct vlan_hdr *)(skb->data + ETH_HLEN);
++ vlan_TCI = vh->h_vlan_TCI;
++ vlanid = (vlan_TCI & VLAN_VID_MASK)>>8;
++ if(vlanid == 2)//to wan
++ {
++ cpu_ptr->txd_info3.QID += 8;
++#if defined (CONFIG_HW_SFQ)
++ if(web_sfq_enable==1 &&(skb->mark == 2)){
++ cpu_ptr->txd_info3.QID = HwSfqQUp;
++ }
++#endif
++ }else if(vlanid == 1){ //to lan
++#if defined (CONFIG_HW_SFQ)
++ if(web_sfq_enable==1 &&(skb->mark == 2)){
++ cpu_ptr->txd_info3.QID = HwSfqQDl;
++ }
++#endif
++ }
++ }
++#endif
++#endif
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++ if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) {
++ if(ra_sw_nat_hook_rx!= NULL){
++ cpu_ptr->txd_info4.FPORT = 4; /* PPE */
++ FOE_MAGIC_TAG(skb) = 0;
++ }
++ }
++#endif
++#if 0
++ cpu_ptr->txd_info4.FPORT = 4; /* PPE */
++ cpu_ptr->txd_info4.UDF = 0x2F;
++#endif
++
++#if defined (CONFIG_MIPS)
++ dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE);
++#else
++ dma_sync_single_for_device(NULL, virt_to_phys(skb->data), skb->len, DMA_TO_DEVICE);
++#endif
++ cpu_ptr->txd_info3.SWC_bit = 1;
++
++ //3. get NULL TXD and decrease free_tx_num by 1.
++ ctx_offset = get_free_txd(&free_txd);
++ if(ctx_offset == NUM_TX_DESC) {
++ printk("get_free_txd fail\n"); // this should not happen. free_txd_num is 2 at least.
++ return 0;
++ }
++
++ //4. hook new TXD in the end of queue
++ //cpu_ptr->txd_info2.NDP = VIRT_TO_PHYS(free_txd);
++ cpu_ptr->txd_info2.NDP = (free_txd);
++
++
++ //5. move CPU_PTR to new TXD
++ //ei_local->tx_cpu_ptr = VIRT_TO_PHYS(free_txd);
++ ei_local->tx_cpu_ptr = (free_txd);
++ cpu_ptr->txd_info3.OWN_bit = 0;
++ sysRegWrite(QTX_CTX_PTR, ei_local->tx_cpu_ptr);
++
++#if 0
++ printk("----------------------------------------------\n");
++ printk("txd_info1:%08X \n",*(int *)&cpu_ptr->txd_info1);
++ printk("txd_info2:%08X \n",*(int *)&cpu_ptr->txd_info2);
++ printk("txd_info3:%08X \n",*(int *)&cpu_ptr->txd_info3);
++ printk("txd_info4:%08X \n",*(int *)&cpu_ptr->txd_info4);
++#endif
++
++#else //#if !defined (CONFIG_RAETH_TSO)
++ cpu_ptr->txd_info1.SDP = virt_to_phys(skb->data);
++ cpu_ptr->txd_info3.SDL = (length - skb->data_len);
++ cpu_ptr->txd_info3.LS_bit = nr_frags ? 0:1;
++#if defined (CONFIG_HW_SFQ)
++ SfqParseLayerInfo(skb);
++ // printk("tcp_source_port=%d\n", tcp_source_port);
++#if(0)
++ cpu_ptr->txd_info4.VQID0 = 0;//1:HW hash 0:CPU
++ if (tcp_source_port==1000) cpu_ptr->txd_info3.VQID = 0;
++ else if (tcp_source_port==1100) cpu_ptr->txd_info3.VQID = 1;
++ else if (tcp_source_port==1200) cpu_ptr->txd_info3.VQID = 2;
++ else cpu_ptr->txd_info3.VQID = 0;
++ #else
++ cpu_ptr->txd_info4.VQID0 = 1;
++ cpu_ptr->txd_info3.PROT = sfq_prot;
++ cpu_ptr->txd_info3.IPOFST = 14 + (SfqParseResult.vlan1_gap); //no vlan
++#endif
++#endif
++ if (gmac_no == 1) {
++ cpu_ptr->txd_info4.FPORT = 1;
++ }else {
++ cpu_ptr->txd_info4.FPORT = 2;
++ }
++
++ cpu_ptr->txd_info4.TSO = 0;
++ cpu_ptr->txd_info3.QID = M2Q_table[skb->mark];
++#ifdef CONFIG_PSEUDO_SUPPORT //web UI used tso
++ if((lan_wan_separate==1) && (gmac_no==2)){
++ cpu_ptr->txd_info3.QID += 8;
++#if defined (CONFIG_HW_SFQ)
++ if(web_sfq_enable == 1 &&(skb->mark == 2)){
++ cpu_ptr->txd_info3.QID = HwSfqQUp;
++ }
++#endif
++ }
++#if defined (CONFIG_HW_SFQ)
++ if((lan_wan_separate==1) && (gmac_no==1)){
++ if(web_sfq_enable==1 &&(skb->mark == 2)){
++ cpu_ptr->txd_info3.QID = HwSfqQDl;
++ }
++ }
++#endif
++#endif //CONFIG_PSEUDO_SUPPORT
++ if(dbg==1){
++ printk("M2Q_table[%d]=%d\n", skb->mark, M2Q_table[skb->mark]);
++ printk("cpu_ptr->txd_info3.QID = %d\n", cpu_ptr->txd_info3.QID);
++ }
++#if defined (CONFIG_RAETH_CHECKSUM_OFFLOAD) && ! defined(CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628)
++ if (skb->ip_summed == CHECKSUM_PARTIAL){
++ cpu_ptr->txd_info4.TUI_CO = 7;
++ }else {
++ cpu_ptr->txd_info4.TUI_CO = 0;
++ }
++#endif
++
++#ifdef CONFIG_RAETH_HW_VLAN_TX
++ if(vlan_tx_tag_present(skb)) {
++ cpu_ptr->txd_info4.VLAN_TAG = 0x10000 | vlan_tx_tag_get(skb);
++ }else {
++ cpu_ptr->txd_info4.VLAN_TAG = 0;
++ }
++#endif
++#ifdef CONFIG_RAETH_HW_VLAN_TX // QoS Web UI used tso
++
++ if((lan_wan_separate==1) && (vlan_tx_tag_get(skb)==2)){
++ //cpu_ptr->txd_info3.QID += 8;
++ cpu_ptr->txd_info3.QID += 8;
++#if defined (CONFIG_HW_SFQ)
++ if(web_sfq_enable==1 &&(skb->mark == 2)){
++ cpu_ptr->txd_info3.QID = HwSfqQUp;
++ }
++#endif
++ }
++#if defined (CONFIG_HW_SFQ)
++ if((lan_wan_separate==1) && (vlan_tx_tag_get(skb)==1)){
++ if(web_sfq_enable==1 &&(skb->mark == 2)){
++ cpu_ptr->txd_info3.QID = HwSfqQDl;
++ }
++ }
++#endif
++#endif // CONFIG_RAETH_HW_VLAN_TX
++
++
++//no hw van, no GE2, web UI used
++#ifndef CONFIG_PSEUDO_SUPPORT
++#ifndef CONFIG_RAETH_HW_VLAN_TX
++ if(lan_wan_separate==1){
++ struct vlan_hdr *vh = NULL;
++ unsigned short vlanid = 0;
++ unsigned short vlan_TCI;
++ vh = (struct vlan_hdr *)(skb->data + ETH_HLEN);
++ vlan_TCI = vh->h_vlan_TCI;
++ vlanid = (vlan_TCI & VLAN_VID_MASK)>>8;
++ if(vlanid == 2)//eth2.2 to wan
++ {
++ cpu_ptr->txd_info3.QID += 8;
++#if defined (CONFIG_HW_SFQ)
++ if(web_sfq_enable==1 &&(skb->mark == 2)){
++ cpu_ptr->txd_info3.QID = HwSfqQUp;
++ }
++#endif
++ }else if(!strcmp(netdev, "eth2.1")){ // eth2.1 to lan
++#if defined (CONFIG_HW_SFQ)
++ if(web_sfq_enable==1 &&(skb->mark == 2)){
++ cpu_ptr->txd_info3.QID = HwSfqQDl;
++ }
++#endif
++ }
++}
++#endif
++#endif
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++ if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) {
++ if(ra_sw_nat_hook_rx!= NULL){
++ cpu_ptr->txd_info4.FPORT = 4; /* PPE */
++ FOE_MAGIC_TAG(skb) = 0;
++ }
++ }
++#endif
++
++ cpu_ptr->txd_info3.SWC_bit = 1;
++
++ ctx_offset = get_free_txd(&free_txd);
++ if(ctx_offset == NUM_TX_DESC) {
++ printk("get_free_txd fail\n");
++ return 0;
++ }
++ //cpu_ptr->txd_info2.NDP = VIRT_TO_PHYS(free_txd);
++ //ei_local->tx_cpu_ptr = VIRT_TO_PHYS(free_txd);
++ cpu_ptr->txd_info2.NDP = free_txd;
++ ei_local->tx_cpu_ptr = free_txd;
++
++
++ if(nr_frags > 0) {
++ for(i=0;i<nr_frags;i++) {
++ // 1. set or get init value for current fragment
++ offset = 0;
++ frag = &skb_shinfo(skb)->frags[i];
++ len = frag->size;
++ frag_txd_num = cal_frag_txd_num(len); // calculate the needed TXD numbers for this fragment
++ for(frag_txd_num = frag_txd_num;frag_txd_num > 0; frag_txd_num --){
++ // 2. size will be assigned to SDL and can't be larger than MAX_TXD_LEN
++ if(len < MAX_TXD_LEN)
++ size = len;
++ else
++ size = MAX_TXD_LEN;
++
++ //3. Update TXD info
++ cpu_ptr = (ei_local->txd_pool + (ctx_offset));
++ cpu_ptr->txd_info3.QID = M2Q_table[skb->mark];
++#ifdef CONFIG_PSEUDO_SUPPORT //QoS Web UI used , nr_frags
++ if((lan_wan_separate==1) && (gmac_no==2)){
++ //cpu_ptr->txd_info3.QID += 8;
++ cpu_ptr->txd_info3.QID += 8;
++#if defined (CONFIG_HW_SFQ)
++ if(web_sfq_enable==1 &&(skb->mark == 2)){
++ cpu_ptr->txd_info3.QID = HwSfqQUp;
++ }
++#endif
++ }
++#if defined (CONFIG_HW_SFQ)
++ if((lan_wan_separate==1) && (gmac_no==1)){
++ if(web_sfq_enable==1 &&(skb->mark == 2)){
++ cpu_ptr->txd_info3.QID = HwSfqQDl;
++ }
++ }
++#endif
++#endif //CONFIG_PSEUDO_SUPPORT
++
++//QoS web used, nr_frags
++#ifdef CONFIG_RAETH_HW_VLAN_TX
++ if((lan_wan_separate==1) && (vlan_tx_tag_get(skb)==2)){
++ cpu_ptr->txd_info3.QID += 8;
++#if defined (CONFIG_HW_SFQ)
++ if(web_sfq_enable==1 &&(skb->mark == 2)){
++ cpu_ptr->txd_info3.QID = HwSfqQUp;
++ }
++#endif
++ }
++#if defined (CONFIG_HW_SFQ)
++ if((lan_wan_separate==1) && (vlan_tx_tag_get(skb)==1)){
++ if(web_sfq_enable==1 &&(skb->mark == 2)){
++ cpu_ptr->txd_info3.QID = HwSfqQDl;
++ }
++ }
++#endif
++#endif // CONFIG_RAETH_HW_VLAN_TX
++//no hw van, no GE2, web UI used
++#ifndef CONFIG_PSEUDO_SUPPORT
++#ifndef CONFIG_RAETH_HW_VLAN_TX
++ if(lan_wan_separate==1){
++ struct vlan_hdr *vh = NULL;
++ unsigned short vlanid = 0;
++ unsigned short vlan_TCI;
++ vh = (struct vlan_hdr *)(skb->data + ETH_HLEN);
++ vlan_TCI = vh->h_vlan_TCI;
++ vlanid = (vlan_TCI & VLAN_VID_MASK)>>8;
++ if(vlanid == 2))//eth2.2 to wan
++ {
++ cpu_ptr->txd_info3.QID += 8;
++#if defined (CONFIG_HW_SFQ)
++ if(web_sfq_enable==1 &&(skb->mark == 2)){
++ cpu_ptr->txd_info3.QID = HwSfqQUp;
++ }
++#endif
++ }
++ }else if(vlanid == 1){ // eth2.1 to lan
++#if defined (CONFIG_HW_SFQ)
++ if(web_sfq_enable==1 &&(skb->mark == 2)){
++ cpu_ptr->txd_info3.QID = HwSfqQDl;
++ }
++#endif
++ }
++ }
++#endif
++#endif
++ if(dbg==1){
++ printk("M2Q_table[%d]=%d\n", skb->mark, M2Q_table[skb->mark]);
++ printk("cpu_ptr->txd_info3.QID = %d\n", cpu_ptr->txd_info3.QID);
++ }
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)
++ cpu_ptr->txd_info1.SDP = pci_map_page(NULL, frag->page, frag->page_offset, frag->size, PCI_DMA_TODEVICE);
++#else
++ cpu_ptr->txd_info1.SDP = pci_map_page(NULL, frag->page.p, frag->page_offset + offset, size, PCI_DMA_TODEVICE);
++// printk(" frag->page = %08x. frag->page_offset = %08x. frag->size = % 08x.\n", frag->page, (frag->page_offset+offset), size);
++#endif
++ cpu_ptr->txd_info3.SDL = size;
++ if( (i==(nr_frags-1)) && (frag_txd_num == 1))
++ cpu_ptr->txd_info3.LS_bit = 1;
++ else
++ cpu_ptr->txd_info3.LS_bit = 0;
++ cpu_ptr->txd_info3.OWN_bit = 0;
++ cpu_ptr->txd_info3.SWC_bit = 1;
++ //4. Update skb_free for housekeeping
++ ei_local->skb_free[ctx_offset] = (cpu_ptr->txd_info3.LS_bit == 1)?skb:(struct sk_buff *)0xFFFFFFFF; //MAGIC ID
++
++ //5. Get next TXD
++ ctx_offset = get_free_txd(&free_txd);
++ //cpu_ptr->txd_info2.NDP = VIRT_TO_PHYS(free_txd);
++ //ei_local->tx_cpu_ptr = VIRT_TO_PHYS(free_txd);
++ cpu_ptr->txd_info2.NDP = free_txd;
++ ei_local->tx_cpu_ptr = free_txd;
++ //6. Update offset and len.
++ offset += size;
++ len -= size;
++ }
++ }
++ ei_local->skb_free[init_txd_idx]= (struct sk_buff *)0xFFFFFFFF; //MAGIC ID
++ }
++
++ if(skb_shinfo(skb)->gso_segs > 1) {
++
++// TsoLenUpdate(skb->len);
++
++ /* TCP over IPv4 */
++ iph = (struct iphdr *)skb_network_header(skb);
++#if defined (CONFIG_RAETH_TSOV6)
++ /* TCP over IPv6 */
++ ip6h = (struct ipv6hdr *)skb_network_header(skb);
++#endif
++ if((iph->version == 4) && (iph->protocol == IPPROTO_TCP)) {
++ th = (struct tcphdr *)skb_transport_header(skb);
++#if defined (CONFIG_HW_SFQ)
++#if(0)
++ init_cpu_ptr->txd_info4.VQID0 = 0;//1:HW hash 0:CPU
++ if (tcp_source_port==1000) init_cpu_ptr->txd_info3.VQID = 0;
++ else if (tcp_source_port==1100) init_cpu_ptr->txd_info3.VQID = 1;
++ else if (tcp_source_port==1200) init_cpu_ptr->txd_info3.VQID = 2;
++ else cpu_ptr->txd_info3.VQID = 0;
++ #else
++ init_cpu_ptr->txd_info4.VQID0 = 1;
++ init_cpu_ptr->txd_info3.PROT = sfq_prot;
++ init_cpu_ptr->txd_info3.IPOFST = 14 + (SfqParseResult.vlan1_gap); //no vlan
++#endif
++#endif
++ init_cpu_ptr->txd_info4.TSO = 1;
++
++ th->check = htons(skb_shinfo(skb)->gso_size);
++#if defined (CONFIG_MIPS)
++ dma_cache_sync(NULL, th, sizeof(struct tcphdr), DMA_TO_DEVICE);
++#else
++ dma_sync_single_for_device(NULL, virt_to_phys(th), sizeof(struct tcphdr), DMA_TO_DEVICE);
++#endif
++ }
++
++#if defined (CONFIG_RAETH_TSOV6)
++ /* TCP over IPv6 */
++ //ip6h = (struct ipv6hdr *)skb_network_header(skb);
++ else if ((ip6h->version == 6) && (ip6h->nexthdr == NEXTHDR_TCP)) {
++ th = (struct tcphdr *)skb_transport_header(skb);
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ init_cpu_ptr->txd_info4.TSO = 1;
++#else
++ init_cpu_ptr->txd_info4.TSO = 1;
++#endif
++ th->check = htons(skb_shinfo(skb)->gso_size);
++#if defined (CONFIG_MIPS)
++ dma_cache_sync(NULL, th, sizeof(struct tcphdr), DMA_TO_DEVICE);
++#else
++ dma_sync_single_for_device(NULL, virt_to_phys(th), sizeof(struct tcphdr), DMA_TO_DEVICE);
++#endif
++ }
++#endif
++ }
++
++
++// dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE);
++
++ init_cpu_ptr->txd_info3.OWN_bit = 0;
++#endif // CONFIG_RAETH_TSO //
++
++ sysRegWrite(QTX_CTX_PTR, ei_local->tx_cpu_ptr);
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++ if (gmac_no == 2) {
++ if (ei_local->PseudoDev != NULL) {
++ pAd = netdev_priv(ei_local->PseudoDev);
++ pAd->stat.tx_packets++;
++ pAd->stat.tx_bytes += length;
++ }
++ } else
++
++#endif
++ {
++ ei_local->stat.tx_packets++;
++ ei_local->stat.tx_bytes += skb->len;
++ }
++#ifdef CONFIG_RAETH_NAPI
++ if ( ei_local->tx_full == 1) {
++ ei_local->tx_full = 0;
++ netif_wake_queue(dev);
++ }
++#endif
++
++ return length;
++}
++
++int ei_start_xmit(struct sk_buff* skb, struct net_device *dev, int gmac_no)
++{
++ END_DEVICE *ei_local = netdev_priv(dev);
++ unsigned long flags;
++ unsigned int num_of_txd = 0;
++#if defined (CONFIG_RAETH_TSO)
++ unsigned int nr_frags = skb_shinfo(skb)->nr_frags, i;
++ struct skb_frag_struct *frag;
++#endif
++#ifdef CONFIG_PSEUDO_SUPPORT
++ PSEUDO_ADAPTER *pAd;
++#endif
++
++#if !defined(CONFIG_RA_NAT_NONE)
++ if(ra_sw_nat_hook_tx!= NULL)
++ {
++// spin_lock_irqsave(&ei_local->page_lock, flags);
++ if(ra_sw_nat_hook_tx(skb, gmac_no)==1){
++// spin_unlock_irqrestore(&ei_local->page_lock, flags);
++ }else{
++ kfree_skb(skb);
++// spin_unlock_irqrestore(&ei_local->page_lock, flags);
++ return 0;
++ }
++ }
++#endif
++
++
++
++ dev->trans_start = jiffies; /* save the timestamp */
++ spin_lock_irqsave(&ei_local->page_lock, flags);
++#if defined (CONFIG_MIPS)
++ dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE);
++#else
++ dma_sync_single_for_device(NULL, virt_to_phys(skb->data), skb->len, DMA_TO_DEVICE);
++#endif
++
++
++//check free_txd_num before calling rt288_eth_send()
++
++#if defined (CONFIG_RAETH_TSO)
++ // num_of_txd = (nr_frags==0) ? 1 : (nr_frags + 1);
++ if(nr_frags != 0){
++ for(i=0;i<nr_frags;i++) {
++ frag = &skb_shinfo(skb)->frags[i];
++ num_of_txd += cal_frag_txd_num(frag->size);
++ }
++ }else
++ num_of_txd = 1;
++#else
++ num_of_txd = 1;
++#endif
++
++#if defined(CONFIG_RALINK_MT7621)
++ if((sysRegRead(0xbe00000c)&0xFFFF) == 0x0101) {
++ ei_xmit_housekeeping(0);
++ }
++#endif
++
++
++ if ((ei_local->free_txd_num > num_of_txd + 1) && (ei_local->free_txd_num != NUM_TX_DESC))
++ {
++ rt2880_eth_send(dev, skb, gmac_no); // need to modify rt2880_eth_send() for QDMA
++ if (ei_local->free_txd_num < 3)
++ {
++#if defined (CONFIG_RAETH_STOP_RX_WHEN_TX_FULL)
++ netif_stop_queue(dev);
++#ifdef CONFIG_PSEUDO_SUPPORT
++ netif_stop_queue(ei_local->PseudoDev);
++#endif
++ tx_ring_full = 1;
++#endif
++ }
++ } else {
++#ifdef CONFIG_PSEUDO_SUPPORT
++ if (gmac_no == 2)
++ {
++ if (ei_local->PseudoDev != NULL)
++ {
++ pAd = netdev_priv(ei_local->PseudoDev);
++ pAd->stat.tx_dropped++;
++ }
++ } else
++#endif
++ ei_local->stat.tx_dropped++;
++ kfree_skb(skb);
++ spin_unlock_irqrestore(&ei_local->page_lock, flags);
++ return 0;
++ }
++ spin_unlock_irqrestore(&ei_local->page_lock, flags);
++ return 0;
++}
++
++void ei_xmit_housekeeping(unsigned long unused)
++{
++ struct net_device *dev = dev_raether;
++ END_DEVICE *ei_local = netdev_priv(dev);
++#ifndef CONFIG_RAETH_NAPI
++ unsigned long reg_int_mask=0;
++#endif
++ struct QDMA_txdesc *dma_ptr = NULL;
++ struct QDMA_txdesc *cpu_ptr = NULL;
++ struct QDMA_txdesc *tmp_ptr = NULL;
++ unsigned int ctx_offset = 0;
++ unsigned int dtx_offset = 0;
++
++ cpu_ptr = sysRegRead(QTX_CRX_PTR);
++ dma_ptr = sysRegRead(QTX_DRX_PTR);
++ ctx_offset = GET_TXD_OFFSET(&cpu_ptr);
++ dtx_offset = GET_TXD_OFFSET(&dma_ptr);
++ cpu_ptr = (ei_local->txd_pool + (ctx_offset));
++ dma_ptr = (ei_local->txd_pool + (dtx_offset));
++
++ while(cpu_ptr != dma_ptr && (cpu_ptr->txd_info3.OWN_bit == 1)) {
++ //1. keep cpu next TXD
++ tmp_ptr = cpu_ptr->txd_info2.NDP;
++ //2. release TXD
++ put_free_txd(ctx_offset);
++ //3. update ctx_offset and free skb memory
++ ctx_offset = GET_TXD_OFFSET(&tmp_ptr);
++#if defined (CONFIG_RAETH_TSO)
++ if(ei_local->skb_free[ctx_offset]!=(struct sk_buff *)0xFFFFFFFF) {
++ dev_kfree_skb_any(ei_local->skb_free[ctx_offset]);
++ }
++#else
++ dev_kfree_skb_any(ei_local->skb_free[ctx_offset]);
++#endif
++ ei_local->skb_free[ctx_offset] = 0;
++
++ netif_wake_queue(dev);
++#ifdef CONFIG_PSEUDO_SUPPORT
++ netif_wake_queue(ei_local->PseudoDev);
++#endif
++ tx_ring_full=0;
++ //4. update cpu_ptr
++ cpu_ptr = (ei_local->txd_pool + ctx_offset);
++ }
++ sysRegWrite(QTX_CRX_PTR, (ei_local->phy_txd_pool + (ctx_offset << 4)));
++#ifndef CONFIG_RAETH_NAPI
++ reg_int_mask=sysRegRead(QFE_INT_ENABLE);
++#if defined (DELAY_INT)
++ sysRegWrite(QFE_INT_ENABLE, reg_int_mask| RLS_DLY_INT);
++#else
++
++ sysRegWrite(QFE_INT_ENABLE, reg_int_mask | RLS_DONE_INT);
++#endif
++#endif //CONFIG_RAETH_NAPI//
++}
++
++EXPORT_SYMBOL(ei_start_xmit);
++EXPORT_SYMBOL(ei_xmit_housekeeping);
++EXPORT_SYMBOL(fe_dma_init);
++EXPORT_SYMBOL(rt2880_eth_send);
+diff --git a/drivers/net/ethernet/raeth/raether_qdma_mt7623.c b/drivers/net/ethernet/raeth/raether_qdma_mt7623.c
+new file mode 100644
+index 0000000..b465b75
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/raether_qdma_mt7623.c
+@@ -0,0 +1,1020 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <linux/if_vlan.h>
++#include <linux/if_ether.h>
++#include <linux/fs.h>
++#include <asm/uaccess.h>
++#include <asm/rt2880/surfboardint.h>
++#if defined (CONFIG_RAETH_TSO)
++#include <linux/tcp.h>
++#include <net/ipv6.h>
++#include <linux/ip.h>
++#include <net/ip.h>
++#include <net/tcp.h>
++#include <linux/in.h>
++#include <linux/ppp_defs.h>
++#include <linux/if_pppox.h>
++#endif
++#include <linux/delay.h>
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++#include <linux/sched.h>
++#endif
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
++#include <asm/rt2880/rt_mmap.h>
++#else
++#include <linux/libata-compat.h>
++#endif
++
++#include "ra2882ethreg.h"
++#include "raether.h"
++#include "ra_mac.h"
++#include "ra_ioctl.h"
++#include "ra_rfrw.h"
++#ifdef CONFIG_RAETH_NETLINK
++#include "ra_netlink.h"
++#endif
++#if defined (CONFIG_RAETH_QOS)
++#include "ra_qos.h"
++#endif
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++#include "../../../net/nat/hw_nat/ra_nat.h"
++#endif
++
++
++#if !defined(CONFIG_RA_NAT_NONE)
++/* bruce+
++ */
++extern int (*ra_sw_nat_hook_rx)(struct sk_buff *skb);
++extern int (*ra_sw_nat_hook_tx)(struct sk_buff *skb, int gmac_no);
++#endif
++
++#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE)
++/* Qwert+
++ */
++#include <asm/mipsregs.h>
++extern int (*ra_classifier_hook_tx)(struct sk_buff *skb, unsigned long cur_cycle);
++extern int (*ra_classifier_hook_rx)(struct sk_buff *skb, unsigned long cur_cycle);
++#endif /* CONFIG_RA_CLASSIFIER */
++
++#if defined (CONFIG_RALINK_RT3052_MP2)
++int32_t mcast_rx(struct sk_buff * skb);
++int32_t mcast_tx(struct sk_buff * skb);
++#endif
++
++#ifdef RA_MTD_RW_BY_NUM
++int ra_mtd_read(int num, loff_t from, size_t len, u_char *buf);
++#else
++int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf);
++#endif
++
++/* gmac driver feature set config */
++#if defined (CONFIG_RAETH_NAPI) || defined (CONFIG_RAETH_QOS)
++#undef DELAY_INT
++#else
++#define DELAY_INT 1
++#endif
++
++//#define CONFIG_UNH_TEST
++/* end of config */
++
++#if defined (CONFIG_RAETH_JUMBOFRAME)
++#define MAX_RX_LENGTH 4096
++#else
++#define MAX_RX_LENGTH 1536
++#endif
++
++extern struct net_device *dev_raether;
++
++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++static int rx_dma_owner_idx1;
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++static int rx_calc_idx1;
++#endif
++#endif
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++static int rx_calc_idx0;
++static unsigned long tx_cpu_owner_idx0=0;
++#endif
++static unsigned long tx_ring_full=0;
++
++#if defined (CONFIG_ETHTOOL) && defined (CONFIG_RAETH_ROUTER)
++#include "ra_ethtool.h"
++extern struct ethtool_ops ra_ethtool_ops;
++#ifdef CONFIG_PSEUDO_SUPPORT
++extern struct ethtool_ops ra_virt_ethtool_ops;
++#endif // CONFIG_PSEUDO_SUPPORT //
++#endif // (CONFIG_ETHTOOL //
++
++#ifdef CONFIG_RALINK_VISTA_BASIC
++int is_switch_175c = 1;
++#endif
++
++//skb->mark to queue mapping table
++extern unsigned int M2Q_table[64];
++
++
++#define KSEG1 0xa0000000
++#if defined (CONFIG_MIPS)
++#define PHYS_TO_VIRT(x) ((void *)((x) | KSEG1))
++#define VIRT_TO_PHYS(x) ((unsigned long)(x) & ~KSEG1)
++#else
++#define PHYS_TO_VIRT(x) phys_to_virt(x)
++#define VIRT_TO_PHYS(x) virt_to_phys(x)
++#endif
++
++
++extern void set_fe_dma_glo_cfg(void);
++
++
++/**
++ *
++ * @brief: get the TXD index from its address
++ *
++ * @param: cpu_ptr
++ *
++ * @return: TXD index
++*/
++
++static unsigned int GET_TXD_OFFSET(struct QDMA_txdesc **cpu_ptr)
++{
++ struct net_device *dev = dev_raether;
++ END_DEVICE *ei_local = netdev_priv(dev);
++ int ctx_offset;
++ //ctx_offset = (((((u32)*cpu_ptr) <<8)>>8) - ((((u32)ei_local->txd_pool)<<8)>>8))/ sizeof(struct QDMA_txdesc);
++ //ctx_offset = (*cpu_ptr - ei_local->txd_pool);
++ /*kurtis*/
++ ctx_offset = (((((u32)*cpu_ptr) <<8)>>8) - ((((u32)ei_local->phy_txd_pool)<<8)>>8))/ sizeof(struct QDMA_txdesc);
++ return ctx_offset;
++}
++
++
++
++
++/**
++ * @brief cal txd number for a page
++ *
++ * @parm size
++ *
++ * @return frag_txd_num
++ */
++
++unsigned int cal_frag_txd_num(unsigned int size)
++{
++ unsigned int frag_txd_num = 0;
++ if(size == 0)
++ return 0;
++ while(size > 0){
++ if(size > MAX_TXD_LEN){
++ frag_txd_num++;
++ size -= MAX_TXD_LEN;
++ }else{
++ frag_txd_num++;
++ size = 0;
++ }
++ }
++ return frag_txd_num;
++
++}
++
++/**
++ * @brief get free TXD from TXD queue
++ *
++ * @param free_txd
++ *
++ * @return
++ */
++static int get_free_txd(struct QDMA_txdesc **free_txd)
++{
++ struct net_device *dev = dev_raether;
++ END_DEVICE *ei_local = netdev_priv(dev);
++ unsigned int tmp_idx;
++
++ if(ei_local->free_txd_num > 0){
++ tmp_idx = ei_local->free_txd_head;
++ ei_local->free_txd_head = ei_local->txd_pool_info[tmp_idx];
++ ei_local->free_txd_num -= 1;
++ //*free_txd = &ei_local->txd_pool[tmp_idx];
++ *free_txd = ei_local->phy_txd_pool + (sizeof(struct QDMA_txdesc) * tmp_idx);
++ return tmp_idx;
++ }else
++ return NUM_TX_DESC;
++}
++
++
++/**
++ * @brief add free TXD into TXD queue
++ *
++ * @param free_txd
++ *
++ * @return
++ */
++int put_free_txd(int free_txd_idx)
++{
++ struct net_device *dev = dev_raether;
++ END_DEVICE *ei_local = netdev_priv(dev);
++ ei_local->txd_pool_info[ei_local->free_txd_tail] = free_txd_idx;
++ ei_local->free_txd_tail = free_txd_idx;
++ ei_local->txd_pool_info[free_txd_idx] = NUM_TX_DESC;
++ ei_local->free_txd_num += 1;
++ return 1;
++}
++
++/*define qdma initial alloc*/
++/**
++ * @brief
++ *
++ * @param net_dev
++ *
++ * @return 0: fail
++ * 1: success
++ */
++bool qdma_tx_desc_alloc(void)
++{
++ struct net_device *dev = dev_raether;
++ END_DEVICE *ei_local = netdev_priv(dev);
++ struct QDMA_txdesc *free_txd = NULL;
++ unsigned int txd_idx;
++ int i = 0;
++
++
++ ei_local->txd_pool = pci_alloc_consistent(NULL, sizeof(struct QDMA_txdesc) * NUM_TX_DESC, &ei_local->phy_txd_pool);
++ printk("txd_pool=%p phy_txd_pool=%08X\n", ei_local->txd_pool , ei_local->phy_txd_pool);
++
++ if (ei_local->txd_pool == NULL) {
++ printk("adapter->txd_pool allocation failed!\n");
++ return 0;
++ }
++ printk("ei_local->skb_free start address is 0x%p.\n", ei_local->skb_free);
++ //set all txd_pool_info to 0.
++ for ( i = 0; i < NUM_TX_DESC; i++)
++ {
++ ei_local->skb_free[i]= 0;
++ ei_local->txd_pool_info[i] = i + 1;
++ ei_local->txd_pool[i].txd_info3.LS_bit = 1;
++ ei_local->txd_pool[i].txd_info3.OWN_bit = 1;
++ }
++
++ ei_local->free_txd_head = 0;
++ ei_local->free_txd_tail = NUM_TX_DESC - 1;
++ ei_local->free_txd_num = NUM_TX_DESC;
++
++
++ //get free txd from txd pool
++ txd_idx = get_free_txd(&free_txd);
++ if( txd_idx == NUM_TX_DESC) {
++ printk("get_free_txd fail\n");
++ return 0;
++ }
++
++ //add null TXD for transmit
++
++ /*kurtis test*/
++ ei_local->tx_dma_ptr = free_txd;
++ ei_local->tx_cpu_ptr = free_txd;
++ //ei_local->tx_dma_ptr = virt_to_phys(free_txd);
++ //ei_local->tx_cpu_ptr = virt_to_phys(free_txd);
++ sysRegWrite(QTX_CTX_PTR, ei_local->tx_cpu_ptr);
++ sysRegWrite(QTX_DTX_PTR, ei_local->tx_dma_ptr);
++
++ printk("kurtis: free_txd = 0x%x!!!\n", free_txd);
++ printk("kurtis: ei_local->tx_dma_ptr = 0x%x!!!\n", ei_local->tx_dma_ptr);
++
++ //get free txd from txd pool
++
++ txd_idx = get_free_txd(&free_txd);
++ if( txd_idx == NUM_TX_DESC) {
++ printk("get_free_txd fail\n");
++ return 0;
++ }
++ // add null TXD for release
++ //sysRegWrite(QTX_CRX_PTR, virt_to_phys(free_txd));
++ //sysRegWrite(QTX_DRX_PTR, virt_to_phys(free_txd));
++ sysRegWrite(QTX_CRX_PTR, free_txd);
++ sysRegWrite(QTX_DRX_PTR, free_txd);
++
++ printk("free_txd: %p, ei_local->cpu_ptr: %08X\n", free_txd, ei_local->tx_cpu_ptr);
++
++ printk(" POOL HEAD_PTR | DMA_PTR | CPU_PTR \n");
++ printk("----------------+---------+--------\n");
++#if 1
++ printk(" 0x%p 0x%08X 0x%08X\n",ei_local->txd_pool,
++ ei_local->tx_dma_ptr, ei_local->tx_cpu_ptr);
++#endif
++ return 1;
++}
++
++bool fq_qdma_init(void)
++{
++ struct QDMA_txdesc *free_head = NULL;
++ unsigned int free_head_phy;
++ unsigned int free_tail_phy;
++ unsigned int *free_page_head = NULL;
++ unsigned int free_page_head_phy;
++ int i;
++
++ free_head = pci_alloc_consistent(NULL, NUM_QDMA_PAGE * sizeof(struct QDMA_txdesc), &free_head_phy);
++ if (unlikely(free_head == NULL)){
++ printk(KERN_ERR "QDMA FQ decriptor not available...\n");
++ return 0;
++ }
++ memset(free_head, 0x0, sizeof(struct QDMA_txdesc) * NUM_QDMA_PAGE);
++
++ free_page_head = pci_alloc_consistent(NULL, NUM_QDMA_PAGE * QDMA_PAGE_SIZE, &free_page_head_phy);
++ if (unlikely(free_page_head == NULL)){
++ printk(KERN_ERR "QDMA FQ pager not available...\n");
++ return 0;
++ }
++ for (i=0; i < NUM_QDMA_PAGE; i++) {
++ free_head[i].txd_info1.SDP = (free_page_head_phy + (i * QDMA_PAGE_SIZE));
++ if(i < (NUM_QDMA_PAGE-1)){
++ free_head[i].txd_info2.NDP = (free_head_phy + ((i+1) * sizeof(struct QDMA_txdesc)));
++
++
++#if 0
++ printk("free_head_phy[%d] is 0x%x!!!\n",i, VIRT_TO_PHYS(&free_head[i]) );
++ printk("free_head[%d] is 0x%x!!!\n",i, &free_head[i] );
++ printk("free_head[%d].txd_info1.SDP is 0x%x!!!\n",i, free_head[i].txd_info1.SDP );
++ printk("free_head[%d].txd_info2.NDP is 0x%x!!!\n",i, free_head[i].txd_info2.NDP );
++#endif
++ }
++ free_head[i].txd_info3.SDL = QDMA_PAGE_SIZE;
++
++ }
++ free_tail_phy = (free_head_phy + (u32)((NUM_QDMA_PAGE-1) * sizeof(struct QDMA_txdesc)));
++
++ printk("free_head_phy is 0x%x!!!\n", free_head_phy);
++ printk("free_tail_phy is 0x%x!!!\n", free_tail_phy);
++ sysRegWrite(QDMA_FQ_HEAD, (u32)free_head_phy);
++ sysRegWrite(QDMA_FQ_TAIL, (u32)free_tail_phy);
++ sysRegWrite(QDMA_FQ_CNT, ((NUM_TX_DESC << 16) | NUM_QDMA_PAGE));
++ sysRegWrite(QDMA_FQ_BLEN, QDMA_PAGE_SIZE << 16);
++ return 1;
++}
++
++int fe_dma_init(struct net_device *dev)
++{
++
++ int i;
++ unsigned int regVal;
++ END_DEVICE* ei_local = netdev_priv(dev);
++
++ fq_qdma_init();
++
++ while(1)
++ {
++ regVal = sysRegRead(QDMA_GLO_CFG);
++ if((regVal & RX_DMA_BUSY))
++ {
++ printk("\n RX_DMA_BUSY !!! ");
++ continue;
++ }
++ if((regVal & TX_DMA_BUSY))
++ {
++ printk("\n TX_DMA_BUSY !!! ");
++ continue;
++ }
++ break;
++ }
++ /*tx desc alloc, add a NULL TXD to HW*/
++
++ qdma_tx_desc_alloc();
++
++
++ /* Initial RX Ring 0*/
++#ifdef CONFIG_32B_DESC
++ ei_local->rx_ring0 = kmalloc(NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL);
++ ei_local->phy_rx_ring0 = virt_to_phys(ei_local->rx_ring0);
++#else
++ ei_local->rx_ring0 = pci_alloc_consistent(NULL, NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring0);
++#endif
++ for (i = 0; i < NUM_QRX_DESC; i++) {
++ memset(&ei_local->rx_ring0[i],0,sizeof(struct PDMA_rxdesc));
++ ei_local->rx_ring0[i].rxd_info2.DDONE_bit = 0;
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++ ei_local->rx_ring0[i].rxd_info2.LS0 = 0;
++ ei_local->rx_ring0[i].rxd_info2.PLEN0 = MAX_RX_LENGTH;
++#else
++ ei_local->rx_ring0[i].rxd_info2.LS0 = 1;
++#endif
++ ei_local->rx_ring0[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx0_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++ }
++ printk("QDMA_RX:phy_rx_ring0 = 0x%08x, rx_ring0 = 0x%p\n",ei_local->phy_rx_ring0,ei_local->rx_ring0);
++
++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++ /* Initial RX Ring 1*/
++#ifdef CONFIG_32B_DESC
++ ei_local->rx_ring1 = kmalloc(NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL);
++ ei_local->phy_rx_ring1 = virt_to_phys(ei_local->rx_ring1);
++#else
++ ei_local->rx_ring1 = pci_alloc_consistent(NULL, NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring1);
++#endif
++ for (i = 0; i < NUM_QRX_DESC; i++) {
++ memset(&ei_local->rx_ring1[i],0,sizeof(struct PDMA_rxdesc));
++ ei_local->rx_ring1[i].rxd_info2.DDONE_bit = 0;
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++ ei_local->rx_ring0[i].rxd_info2.LS0 = 0;
++ ei_local->rx_ring0[i].rxd_info2.PLEN0 = MAX_RX_LENGTH;
++#else
++ ei_local->rx_ring1[i].rxd_info2.LS0 = 1;
++#endif
++ ei_local->rx_ring1[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx1_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++ }
++ printk("\nphy_rx_ring1 = 0x%08x, rx_ring1 = 0x%p\n",ei_local->phy_rx_ring1,ei_local->rx_ring1);
++#endif
++
++ regVal = sysRegRead(QDMA_GLO_CFG);
++ regVal &= 0x000000FF;
++ sysRegWrite(QDMA_GLO_CFG, regVal);
++ regVal=sysRegRead(QDMA_GLO_CFG);
++
++ /* Tell the adapter where the TX/RX rings are located. */
++
++ sysRegWrite(QRX_BASE_PTR_0, phys_to_bus((u32) ei_local->phy_rx_ring0));
++ sysRegWrite(QRX_MAX_CNT_0, cpu_to_le32((u32) NUM_QRX_DESC));
++ sysRegWrite(QRX_CRX_IDX_0, cpu_to_le32((u32) (NUM_QRX_DESC - 1)));
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ rx_calc_idx0 = rx_dma_owner_idx0 = sysRegRead(QRX_CRX_IDX_0);
++#endif
++ sysRegWrite(QDMA_RST_CFG, PST_DRX_IDX0);
++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++ sysRegWrite(QRX_BASE_PTR_1, phys_to_bus((u32) ei_local->phy_rx_ring1));
++ sysRegWrite(QRX_MAX_CNT_1, cpu_to_le32((u32) NUM_QRX_DESC));
++ sysRegWrite(QRX_CRX_IDX_1, cpu_to_le32((u32) (NUM_QRX_DESC - 1)));
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ rx_calc_idx1 = rx_dma_owner_idx1 = sysRegRead(QRX_CRX_IDX_1);
++#endif
++ sysRegWrite(QDMA_RST_CFG, PST_DRX_IDX1);
++#endif
++
++#if !defined (CONFIG_RAETH_QDMATX_QDMARX)
++ /* Initial PDMA RX Ring 0*/
++#ifdef CONFIG_32B_DESC
++ ei_local->rx_ring0 = kmalloc(NUM_RX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL);
++ ei_local->phy_rx_ring0 = virt_to_phys(ei_local->rx_ring0);
++#else
++ ei_local->rx_ring0 = pci_alloc_consistent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring0);
++#endif
++ for (i = 0; i < NUM_RX_DESC; i++) {
++ memset(&ei_local->rx_ring0[i],0,sizeof(struct PDMA_rxdesc));
++ ei_local->rx_ring0[i].rxd_info2.DDONE_bit = 0;
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++ ei_local->rx_ring0[i].rxd_info2.LS0 = 0;
++ ei_local->rx_ring0[i].rxd_info2.PLEN0 = MAX_RX_LENGTH;
++#else
++ ei_local->rx_ring0[i].rxd_info2.LS0 = 1;
++#endif
++ ei_local->rx_ring0[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx0_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++ }
++ printk("PDMA_RX:phy_rx_ring0 = 0x%08x, rx_ring0 = 0x%p\n",ei_local->phy_rx_ring0,ei_local->rx_ring0);
++
++ regVal = sysRegRead(PDMA_GLO_CFG);
++ regVal &= 0x000000FF;
++ sysRegWrite(PDMA_GLO_CFG, regVal);
++ regVal=sysRegRead(PDMA_GLO_CFG);
++
++ sysRegWrite(RX_BASE_PTR0, phys_to_bus((u32) ei_local->phy_rx_ring0));
++ sysRegWrite(RX_MAX_CNT0, cpu_to_le32((u32) NUM_RX_DESC));
++ sysRegWrite(RX_CALC_IDX0, cpu_to_le32((u32) (NUM_RX_DESC - 1)));
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ rx_calc_idx0 = sysRegRead(RX_CALC_IDX0);
++#endif
++ sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX0);
++
++#endif/*kurtis*/
++ /* Enable randon early drop and set drop threshold automatically */
++ sysRegWrite(QDMA_FC_THRES, 0x174444);
++ sysRegWrite(QDMA_HRED2, 0x0);
++ set_fe_dma_glo_cfg();
++
++ return 1;
++}
++
++inline int rt2880_eth_send(struct net_device* dev, struct sk_buff *skb, int gmac_no)
++{
++ unsigned int length=skb->len;
++ END_DEVICE* ei_local = netdev_priv(dev);
++
++ struct QDMA_txdesc *cpu_ptr;
++
++ struct QDMA_txdesc *dma_ptr __maybe_unused;
++ struct QDMA_txdesc *free_txd;
++ unsigned int ctx_offset = 0;
++ unsigned int dtx_offset = 0;
++#if defined (CONFIG_RAETH_TSO)
++ struct iphdr *iph = NULL;
++ struct QDMA_txdesc *init_cpu_ptr;
++ struct tcphdr *th = NULL;
++ struct skb_frag_struct *frag;
++ unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
++ unsigned int len, size, offset, frag_txd_num;
++ int init_txd_idx, i;
++#endif // CONFIG_RAETH_TSO //
++
++#if defined (CONFIG_RAETH_TSOV6)
++ struct ipv6hdr *ip6h = NULL;
++#endif
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++ PSEUDO_ADAPTER *pAd;
++#endif
++ cpu_ptr = (ei_local->tx_cpu_ptr);
++ ctx_offset = GET_TXD_OFFSET(&cpu_ptr);
++ cpu_ptr = phys_to_virt(ei_local->tx_cpu_ptr);
++ dma_ptr = phys_to_virt(ei_local->tx_dma_ptr);
++/*kurtis test*/
++ //dma_ptr = (ei_local->tx_dma_ptr);
++
++
++ /*only modify virtual address*/
++ //cpu_ptr = (ei_local->txd_pool) + (ctx_offset * sizeof(struct QDMA_txdesc));
++ cpu_ptr = (ei_local->txd_pool + (ctx_offset));
++
++ //dtx_offset = GET_TXD_OFFSET(&dma_ptr);
++ //dma_ptr = (ei_local->txd_pool) + (dtx_offset * sizeof(struct QDMA_txdesc));
++
++ //printk("eth_send ctx_offset = 0x%x!!!\n", ctx_offset);
++ //printk("eth_send dtx_offset = 0x%x!!!\n", dtx_offset);
++ //printk("eth_send ei_local->txd_pool = 0x%x!!!\n", ei_local->txd_pool);
++ //printk("eth_send cpu_ptr = 0x%x!!!\n", cpu_ptr);
++ //printk("eth_send ctx_offset = 0x%x!!!\n", ctx_offset);
++ //printk("eth_send ei_local->skb_free[ctx_offset] = 0x%x!!!\n", skb);
++
++
++ ei_local->skb_free[ctx_offset] = skb;
++#if defined (CONFIG_RAETH_TSO)
++ init_cpu_ptr = cpu_ptr;
++ init_txd_idx = ctx_offset;
++#endif
++
++#if !defined (CONFIG_RAETH_TSO)
++
++ //2. prepare data
++ cpu_ptr->txd_info1.SDP = virt_to_phys(skb->data);
++ cpu_ptr->txd_info3.SDL = skb->len;
++
++ if (gmac_no == 1) {
++ cpu_ptr->txd_info4.FPORT = 1;
++ }else {
++ cpu_ptr->txd_info4.FPORT = 2;
++ }
++
++
++ cpu_ptr->txd_info3.QID = M2Q_table[skb->mark];
++#if 0
++ iph = (struct iphdr *)skb_network_header(skb);
++ if (iph->tos == 0xe0)
++ cpu_ptr->txd_info3.QID = 3;
++ else if (iph->tos == 0xa0)
++ cpu_ptr->txd_info3.QID = 2;
++ else if (iph->tos == 0x20)
++ cpu_ptr->txd_info3.QID = 1;
++ else
++ cpu_ptr->txd_info3.QID = 0;
++#endif
++
++#if defined (CONFIG_RAETH_CHECKSUM_OFFLOAD) && ! defined(CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628)
++ if (skb->ip_summed == CHECKSUM_PARTIAL){
++ cpu_ptr->txd_info4.TUI_CO = 7;
++ }else {
++ cpu_ptr->txd_info4.TUI_CO = 0;
++ }
++#endif
++
++#ifdef CONFIG_RAETH_HW_VLAN_TX
++ if(vlan_tx_tag_present(skb)) {
++ cpu_ptr->txd_info4.VLAN_TAG = 0x10000 | vlan_tx_tag_get(skb);
++ }else {
++ cpu_ptr->txd_info4.VLAN_TAG = 0;
++ }
++#endif
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++ if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) {
++ if(ra_sw_nat_hook_rx!= NULL){
++ cpu_ptr->txd_info4.FPORT = 4; /* PPE */
++ FOE_MAGIC_TAG(skb) = 0;
++ }
++ }
++#endif
++#if 0
++ cpu_ptr->txd_info4.FPORT = 4; /* PPE */
++ cpu_ptr->txd_info4.UDF = 0x2F;
++#endif
++
++#if defined (CONFIG_MIPS)
++ dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE);
++#else
++ dma_sync_single_for_device(NULL, virt_to_phys(skb->data), skb->len, DMA_TO_DEVICE);
++#endif
++ cpu_ptr->txd_info3.SWC_bit = 1;
++
++ //3. get NULL TXD and decrease free_tx_num by 1.
++ ctx_offset = get_free_txd(&free_txd);
++ if(ctx_offset == NUM_TX_DESC) {
++ printk("get_free_txd fail\n"); // this should not happen. free_txd_num is 2 at least.
++ return 0;
++ }
++
++ //4. hook new TXD in the end of queue
++ //cpu_ptr->txd_info2.NDP = virt_to_phys(free_txd);
++ cpu_ptr->txd_info2.NDP = (free_txd);
++
++
++ //5. move CPU_PTR to new TXD
++ //ei_local->tx_cpu_ptr = virt_to_phys(free_txd);
++ ei_local->tx_cpu_ptr = (free_txd);
++ cpu_ptr->txd_info3.OWN_bit = 0;
++ sysRegWrite(QTX_CTX_PTR, ei_local->tx_cpu_ptr);
++
++#if 0
++ printk("----------------------------------------------\n");
++ printk("txd_info1:%08X \n",*(int *)&cpu_ptr->txd_info1);
++ printk("txd_info2:%08X \n",*(int *)&cpu_ptr->txd_info2);
++ printk("txd_info3:%08X \n",*(int *)&cpu_ptr->txd_info3);
++ printk("txd_info4:%08X \n",*(int *)&cpu_ptr->txd_info4);
++#endif
++
++#else //#if !defined (CONFIG_RAETH_TSO)
++ cpu_ptr->txd_info1.SDP = virt_to_phys(skb->data);
++ cpu_ptr->txd_info3.SDL = (length - skb->data_len);
++ cpu_ptr->txd_info3.LS_bit = nr_frags ? 0:1;
++ if (gmac_no == 1) {
++ cpu_ptr->txd_info4.FPORT = 1;
++ }else {
++ cpu_ptr->txd_info4.FPORT = 2;
++ }
++
++ cpu_ptr->txd_info4.TSO = 0;
++ cpu_ptr->txd_info3.QID = M2Q_table[skb->mark];
++#if defined (CONFIG_RAETH_CHECKSUM_OFFLOAD) && ! defined(CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628)
++ if (skb->ip_summed == CHECKSUM_PARTIAL){
++ cpu_ptr->txd_info4.TUI_CO = 7;
++ }else {
++ cpu_ptr->txd_info4.TUI_CO = 0;
++ }
++#endif
++
++#ifdef CONFIG_RAETH_HW_VLAN_TX
++ if(vlan_tx_tag_present(skb)) {
++ cpu_ptr->txd_info4.VLAN_TAG = 0x10000 | vlan_tx_tag_get(skb);
++ }else {
++ cpu_ptr->txd_info4.VLAN_TAG = 0;
++ }
++#endif
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++ if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) {
++ if(ra_sw_nat_hook_rx!= NULL){
++ cpu_ptr->txd_info4.FPORT = 4; /* PPE */
++ FOE_MAGIC_TAG(skb) = 0;
++ }
++ }
++#endif
++
++ cpu_ptr->txd_info3.SWC_bit = 1;
++
++ ctx_offset = get_free_txd(&free_txd);
++ if(ctx_offset == NUM_TX_DESC) {
++ printk("get_free_txd fail\n");
++ return 0;
++ }
++ //cpu_ptr->txd_info2.NDP = virt_to_phys(free_txd);
++ //ei_local->tx_cpu_ptr = virt_to_phys(free_txd);
++ cpu_ptr->txd_info2.NDP = free_txd;
++ ei_local->tx_cpu_ptr = free_txd;
++
++ if(nr_frags > 0) {
++ for(i=0;i<nr_frags;i++) {
++ // 1. set or get init value for current fragment
++ offset = 0;
++ frag = &skb_shinfo(skb)->frags[i];
++ len = frag->size;
++ frag_txd_num = cal_frag_txd_num(len); // calculate the needed TXD numbers for this fragment
++ for(frag_txd_num = frag_txd_num;frag_txd_num > 0; frag_txd_num --){
++ // 2. size will be assigned to SDL and can't be larger than MAX_TXD_LEN
++ if(len < MAX_TXD_LEN)
++ size = len;
++ else
++ size = MAX_TXD_LEN;
++
++ //3. Update TXD info
++ cpu_ptr = (ei_local->txd_pool + (ctx_offset));
++ cpu_ptr->txd_info3.QID = M2Q_table[skb->mark];
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)
++ cpu_ptr->txd_info1.SDP = pci_map_page(NULL, frag->page, frag->page_offset, frag->size, PCI_DMA_TODEVICE);
++#else
++ cpu_ptr->txd_info1.SDP = pci_map_page(NULL, frag->page.p, frag->page_offset + offset, size, PCI_DMA_TODEVICE);
++// printk(" frag->page = %08x. frag->page_offset = %08x. frag->size = % 08x.\n", frag->page, (frag->page_offset+offset), size);
++#endif
++ cpu_ptr->txd_info3.SDL = size;
++ if( (i==(nr_frags-1)) && (frag_txd_num == 1))
++ cpu_ptr->txd_info3.LS_bit = 1;
++ else
++ cpu_ptr->txd_info3.LS_bit = 0;
++ cpu_ptr->txd_info3.OWN_bit = 0;
++ cpu_ptr->txd_info3.SWC_bit = 1;
++ //4. Update skb_free for housekeeping
++ ei_local->skb_free[ctx_offset] = (cpu_ptr->txd_info3.LS_bit == 1)?skb:(struct sk_buff *)0xFFFFFFFF; //MAGIC ID
++
++ //5. Get next TXD
++ ctx_offset = get_free_txd(&free_txd);
++ //cpu_ptr->txd_info2.NDP = virt_to_phys(free_txd);
++ //ei_local->tx_cpu_ptr = virt_to_phys(free_txd);
++ cpu_ptr->txd_info2.NDP = free_txd;
++ ei_local->tx_cpu_ptr = free_txd;
++ //6. Update offset and len.
++ offset += size;
++ len -= size;
++ }
++ }
++ ei_local->skb_free[init_txd_idx]= (struct sk_buff *)0xFFFFFFFF; //MAGIC ID
++ }
++
++ if(skb_shinfo(skb)->gso_segs > 1) {
++
++// TsoLenUpdate(skb->len);
++
++ /* TCP over IPv4 */
++ iph = (struct iphdr *)skb_network_header(skb);
++#if defined (CONFIG_RAETH_TSOV6)
++ /* TCP over IPv6 */
++ ip6h = (struct ipv6hdr *)skb_network_header(skb);
++#endif
++ if((iph->version == 4) && (iph->protocol == IPPROTO_TCP)) {
++ th = (struct tcphdr *)skb_transport_header(skb);
++
++ init_cpu_ptr->txd_info4.TSO = 1;
++
++ th->check = htons(skb_shinfo(skb)->gso_size);
++#if defined (CONFIG_MIPS)
++ dma_cache_sync(NULL, th, sizeof(struct tcphdr), DMA_TO_DEVICE);
++#else
++ dma_sync_single_for_device(NULL, virt_to_phys(th), sizeof(struct tcphdr), DMA_TO_DEVICE);
++#endif
++ }
++
++#if defined (CONFIG_RAETH_TSOV6)
++ /* TCP over IPv6 */
++ //ip6h = (struct ipv6hdr *)skb_network_header(skb);
++ else if ((ip6h->version == 6) && (ip6h->nexthdr == NEXTHDR_TCP)) {
++ th = (struct tcphdr *)skb_transport_header(skb);
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++ init_cpu_ptr->txd_info4.TSO = 1;
++#else
++ init_cpu_ptr->txd_info4.TSO = 1;
++#endif
++ th->check = htons(skb_shinfo(skb)->gso_size);
++#if defined (CONFIG_MIPS)
++ dma_cache_sync(NULL, th, sizeof(struct tcphdr), DMA_TO_DEVICE);
++#else
++ dma_sync_single_for_device(NULL, virt_to_phys(th), sizeof(struct tcphdr), DMA_TO_DEVICE);
++#endif
++ }
++#endif
++ }
++
++
++// dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE);
++
++ init_cpu_ptr->txd_info3.OWN_bit = 0;
++#endif // CONFIG_RAETH_TSO //
++
++ sysRegWrite(QTX_CTX_PTR, ei_local->tx_cpu_ptr);
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++ if (gmac_no == 2) {
++ if (ei_local->PseudoDev != NULL) {
++ pAd = netdev_priv(ei_local->PseudoDev);
++ pAd->stat.tx_packets++;
++ pAd->stat.tx_bytes += length;
++ }
++ } else
++
++#endif
++ {
++ ei_local->stat.tx_packets++;
++ ei_local->stat.tx_bytes += skb->len;
++ }
++#ifdef CONFIG_RAETH_NAPI
++ if ( ei_local->tx_full == 1) {
++ ei_local->tx_full = 0;
++ netif_wake_queue(dev);
++ }
++#endif
++
++ return length;
++}
++
++int ei_start_xmit(struct sk_buff* skb, struct net_device *dev, int gmac_no)
++{
++ END_DEVICE *ei_local = netdev_priv(dev);
++ unsigned long flags;
++ unsigned int num_of_txd = 0;
++#if defined (CONFIG_RAETH_TSO)
++ unsigned int nr_frags = skb_shinfo(skb)->nr_frags, i;
++ struct skb_frag_struct *frag;
++#endif
++#ifdef CONFIG_PSEUDO_SUPPORT
++ PSEUDO_ADAPTER *pAd;
++#endif
++
++#if !defined(CONFIG_RA_NAT_NONE)
++ if(ra_sw_nat_hook_tx!= NULL)
++ {
++// spin_lock_irqsave(&ei_local->page_lock, flags);
++ if(ra_sw_nat_hook_tx(skb, gmac_no)==1){
++// spin_unlock_irqrestore(&ei_local->page_lock, flags);
++ }else{
++ kfree_skb(skb);
++// spin_unlock_irqrestore(&ei_local->page_lock, flags);
++ return 0;
++ }
++ }
++#endif
++
++#if defined(CONFIG_RALINK_MT7621) || defined(CONFIG_ARCH_MT7623)
++#define MIN_PKT_LEN 64
++ if (skb->len < MIN_PKT_LEN) {
++ if (skb_padto(skb, MIN_PKT_LEN)) {
++ printk("raeth: skb_padto failed\n");
++ return 0;
++ }
++ skb_put(skb, MIN_PKT_LEN - skb->len);
++ }
++#endif
++
++
++ dev->trans_start = jiffies; /* save the timestamp */
++ spin_lock_irqsave(&ei_local->page_lock, flags);
++#if defined (CONFIG_MIPS)
++ dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE);
++#else
++ dma_sync_single_for_device(NULL, virt_to_phys(skb->data), skb->len, DMA_TO_DEVICE);
++#endif
++
++
++//check free_txd_num before calling rt288_eth_send()
++
++#if defined (CONFIG_RAETH_TSO)
++ // num_of_txd = (nr_frags==0) ? 1 : (nr_frags + 1);
++ if(nr_frags != 0){
++ for(i=0;i<nr_frags;i++) {
++ frag = &skb_shinfo(skb)->frags[i];
++ num_of_txd += cal_frag_txd_num(frag->size);
++ }
++ }else
++ num_of_txd = 1;
++#else
++ num_of_txd = 1;
++#endif
++
++#if defined(CONFIG_RALINK_MT7621)
++ if((sysRegRead(0xbe00000c)&0xFFFF) == 0x0101) {
++ ei_xmit_housekeeping(0);
++ }
++#endif
++
++ ei_xmit_housekeeping(0);
++
++ //if ((ei_local->free_txd_num > num_of_txd + 1) && (ei_local->free_txd_num != NUM_TX_DESC))
++ if ((ei_local->free_txd_num > num_of_txd + 5) && (ei_local->free_txd_num != NUM_TX_DESC))
++ {
++ rt2880_eth_send(dev, skb, gmac_no); // need to modify rt2880_eth_send() for QDMA
++ if (ei_local->free_txd_num < 3)
++ {
++#if defined (CONFIG_RAETH_STOP_RX_WHEN_TX_FULL)
++ netif_stop_queue(dev);
++#ifdef CONFIG_PSEUDO_SUPPORT
++ netif_stop_queue(ei_local->PseudoDev);
++#endif
++ tx_ring_full = 1;
++#endif
++ }
++ } else {
++#ifdef CONFIG_PSEUDO_SUPPORT
++ if (gmac_no == 2)
++ {
++ if (ei_local->PseudoDev != NULL)
++ {
++ pAd = netdev_priv(ei_local->PseudoDev);
++ pAd->stat.tx_dropped++;
++ }
++ } else
++#endif
++ ei_local->stat.tx_dropped++;
++ kfree_skb(skb);
++ spin_unlock_irqrestore(&ei_local->page_lock, flags);
++ return 0;
++ }
++ spin_unlock_irqrestore(&ei_local->page_lock, flags);
++ return 0;
++}
++
++void ei_xmit_housekeeping(unsigned long unused)
++{
++ struct net_device *dev = dev_raether;
++ END_DEVICE *ei_local = netdev_priv(dev);
++#ifndef CONFIG_RAETH_NAPI
++ unsigned long reg_int_mask=0;
++#endif
++ struct QDMA_txdesc *dma_ptr = NULL;
++ struct QDMA_txdesc *cpu_ptr = NULL;
++ struct QDMA_txdesc *tmp_ptr = NULL;
++ unsigned int htx_offset = 0;
++ unsigned int ctx_offset = 0;
++ unsigned int dtx_offset = 0;
++
++ //dma_ptr = phys_to_virt(sysRegRead(QTX_DRX_PTR));
++ //cpu_ptr = phys_to_virt(sysRegRead(QTX_CRX_PTR));
++ //printk("kurtis:housekeeping QTX_DRX_PTR = 0x%x!!!\n", sysRegRead(QTX_DRX_PTR));
++ //printk("kurtis:housekeeping DMA_PTR = 0x%x!!!\n", dma_ptr);
++
++ cpu_ptr = sysRegRead(QTX_CRX_PTR);
++ dma_ptr = sysRegRead(QTX_DRX_PTR);
++
++ //printk("kurtis:housekeeping QTX_CRX_PTR = 0x%x!!!\n", cpu_ptr);
++ //printk("kurtis:housekeeping QTX_DRX_PTR = 0x%x!!!\n", dma_ptr);
++ ctx_offset = GET_TXD_OFFSET(&cpu_ptr);
++ dtx_offset = GET_TXD_OFFSET(&dma_ptr);
++ htx_offset = ctx_offset;
++ cpu_ptr = (ei_local->txd_pool + (ctx_offset));
++ dma_ptr = (ei_local->txd_pool + (dtx_offset));
++
++
++ //printk("kurtis:housekeeping CPU_PTR = 0x%x!!!\n", cpu_ptr);
++ //printk("kurtis:housekeeping DMA_PTR = 0x%x!!!\n", dma_ptr);
++
++/*temp mark*/
++#if 1
++
++
++ if(cpu_ptr != dma_ptr && (cpu_ptr->txd_info3.OWN_bit == 1)) {
++ while(cpu_ptr != dma_ptr && (cpu_ptr->txd_info3.OWN_bit == 1)) {
++
++ //1. keep cpu next TXD
++ //tmp_ptr = phys_to_virt(cpu_ptr->txd_info2.NDP);
++ tmp_ptr = cpu_ptr->txd_info2.NDP;
++ htx_offset = GET_TXD_OFFSET(&tmp_ptr);
++ //printk("kurtis:housekeeping cpu_ptr->txd_info2.NDP = 0x%x!!!\n", cpu_ptr->txd_info2.NDP);
++ //printk("kurtis:housekeeping tmp_ptr = 0x%x!!!\n", tmp_ptr);
++ //printk("kurtis:housekeeping htx_offset = 0x%x!!!\n", htx_offset);
++ //2. free skb meomry
++#if defined (CONFIG_RAETH_TSO)
++ if(ei_local->skb_free[htx_offset]!=(struct sk_buff *)0xFFFFFFFF) {
++ dev_kfree_skb_any(ei_local->skb_free[htx_offset]);
++ }
++#else
++ dev_kfree_skb_any(ei_local->skb_free[htx_offset]);
++#endif
++
++ //3. release TXD
++ //htx_offset = GET_TXD_OFFSET(&cpu_ptr);
++ //put_free_txd(htx_offset);
++ put_free_txd(ctx_offset);
++
++
++
++ netif_wake_queue(dev);
++#ifdef CONFIG_PSEUDO_SUPPORT
++ netif_wake_queue(ei_local->PseudoDev);
++#endif
++ tx_ring_full=0;
++
++ //4. update cpu_ptr to next ptr
++ //cpu_ptr = tmp_ptr;
++ cpu_ptr = (ei_local->txd_pool + htx_offset);
++ ctx_offset = htx_offset;
++ //cpu_ptr = (cpu_ptr + (htx_offset));
++ //printk("kurtis:housekeeping 4. update cpu_ptr = 0x%x!!!\n", cpu_ptr);
++ }
++ }
++ //sysRegWrite(QTX_CRX_PTR, virt_to_phys(cpu_ptr));
++ //sysRegWrite(QTX_CRX_PTR, cpu_ptr);
++ tmp_ptr = (ei_local->phy_txd_pool + (htx_offset << 4));
++ //printk("kurtis:housekeeping 5. update QTX_CRX_PTR = 0x%x!!!\n", tmp_ptr);
++ sysRegWrite(QTX_CRX_PTR, tmp_ptr);
++
++#endif
++
++#ifndef CONFIG_RAETH_NAPI
++ reg_int_mask=sysRegRead(QFE_INT_ENABLE);
++#if defined (DELAY_INT)
++ sysRegWrite(FE_INT_ENABLE, reg_int_mask| RLS_DLY_INT);
++#else
++
++ sysRegWrite(FE_INT_ENABLE, reg_int_mask | RLS_DONE_INT);
++#endif
++#endif //CONFIG_RAETH_NAPI//
++}
++
++EXPORT_SYMBOL(ei_start_xmit);
++EXPORT_SYMBOL(ei_xmit_housekeeping);
++EXPORT_SYMBOL(fe_dma_init);
++EXPORT_SYMBOL(rt2880_eth_send);
+diff --git a/drivers/net/ethernet/raeth/smb_hook.c b/drivers/net/ethernet/raeth/smb_hook.c
+new file mode 100644
+index 0000000..617139c
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/smb_hook.c
+@@ -0,0 +1,17 @@
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/skbuff.h>
++
++
++int (*smb_nf_local_in_hook)(struct sk_buff *skb) = NULL;
++int (*smb_nf_pre_routing_hook)(struct sk_buff *skb) = NULL;
++int (*smb_nf_local_out_hook)(struct sk_buff *skb) = NULL;
++int (*smb_nf_post_routing_hook)(struct sk_buff *skb) = NULL;
++EXPORT_SYMBOL(smb_nf_local_in_hook);
++EXPORT_SYMBOL(smb_nf_pre_routing_hook);
++EXPORT_SYMBOL(smb_nf_local_out_hook);
++EXPORT_SYMBOL(smb_nf_post_routing_hook);
++
++
+diff --git a/drivers/net/ethernet/raeth/smb_nf.c b/drivers/net/ethernet/raeth/smb_nf.c
+new file mode 100644
+index 0000000..86250eb
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/smb_nf.c
+@@ -0,0 +1,177 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++
++#include <linux/inetdevice.h>
++#include <linux/tcp.h>
++#include <linux/ip.h>
++#include <net/tcp.h>
++#include <net/ip.h>
++
++extern int (*smb_nf_local_in_hook)(struct sk_buff *skb);
++extern int (*smb_nf_pre_routing_hook)(struct sk_buff *skb);
++extern int (*smb_nf_local_out_hook)(struct sk_buff *skb);
++extern int (*smb_nf_post_routing_hook)(struct sk_buff *skb);
++
++struct net_device *lan_int = NULL;
++struct in_ifaddr *lan_ifa = NULL;
++
++
++int mtk_smb_nf_local_in_hook(struct sk_buff *skb)
++{
++ struct iphdr *iph = ip_hdr(skb);
++
++ if (skb->protocol == htons(ETH_P_IP)) {
++ struct iphdr *iph = ip_hdr(skb);
++
++ if (iph->protocol == IPPROTO_TCP) {
++ struct tcphdr *th = tcp_hdr(skb);
++ unsigned short sport, dport;
++
++ th = tcp_hdr(skb);
++ th = (struct tcphdr *)(((unsigned char *)iph) + iph->ihl*4);
++
++ if ((iph->daddr == lan_ifa->ifa_local)
++ && ((th->dest == 0xbd01) || (th->dest == 0x8900)
++ || (th->dest == 0x8a00) || (th->dest == 0x8b00)))
++ return 1;
++ else
++ return 0;
++ }
++
++ }
++
++ return 0;
++}
++
++int mtk_smb_nf_pre_routing_hook(struct sk_buff *skb)
++{
++ struct iphdr *iph = ip_hdr(skb);
++
++ if (skb->protocol == htons(ETH_P_IP)) {
++ struct iphdr *iph = ip_hdr(skb);
++
++ if (iph->protocol == IPPROTO_TCP) {
++ struct tcphdr *th = tcp_hdr(skb);
++ unsigned short sport, dport;
++
++ th = tcp_hdr(skb);
++ th = (struct tcphdr *)(((unsigned char *)iph) + iph->ihl*4);
++ if ((iph->daddr == lan_ifa->ifa_local)
++ && ((th->dest == 0xbd01) || (th->dest == 0x8900)
++ || (th->dest == 0x8a00) || (th->dest == 0x8b00)))
++ return 1;
++ else
++ return 0;
++ }
++
++ }
++
++ return 0;
++}
++
++int mtk_smb_nf_local_out_hook(struct sk_buff *skb)
++{
++ struct iphdr *iph = ip_hdr(skb);
++
++ if (iph->protocol == IPPROTO_TCP) {
++ struct tcphdr *th = tcp_hdr(skb);
++
++ th = tcp_hdr(skb);
++ th = (struct tcphdr *)(((unsigned char *)iph) + iph->ihl*4);
++
++ if ((iph->saddr == lan_ifa->ifa_local)
++ && ((th->source == 0xbd01) || (th->source == 0x8900)
++ || (th->source == 0x8a00) || (th->source == 0x8b00)))
++ return 1;
++ else
++ return 0;
++ }
++
++ return 0;
++}
++
++int mtk_smb_nf_post_routing_hook(struct sk_buff *skb)
++{
++ struct iphdr *iph = ip_hdr(skb);
++
++ if (skb->protocol == htons(ETH_P_IP)) {
++ struct iphdr *iph = ip_hdr(skb);
++
++ if (iph->protocol == IPPROTO_TCP) {
++ struct tcphdr *th = tcp_hdr(skb);
++
++ th = tcp_hdr(skb);
++ th = (struct tcphdr *)(((unsigned char *)iph) + iph->ihl*4);
++
++ if ((iph->saddr == lan_ifa->ifa_local)
++ && ((th->source == 0xbd01) || (th->source == 0x8900)
++ || (th->source == 0x8a00) || (th->source == 0x8b00)))
++ return 1;
++ else
++ return 0;
++ }
++
++ }
++
++ return 0;
++}
++
++int __init mtk_smb_hook_init(void)
++{
++ struct in_device *in_dev;
++ struct in_ifaddr **ifap = NULL;
++ struct in_ifaddr *ifa = NULL;
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++ lan_int = dev_get_by_name(&init_net, "br0");
++#else
++ lan_int = dev_get_by_name("br0");
++#endif
++ if (lan_int)
++ in_dev = __in_dev_get_rtnl(lan_int);
++ else
++ return 0;
++
++ if (in_dev) {
++ for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
++ ifap = &ifa->ifa_next) {
++ if (!strcmp("br0", ifa->ifa_label))
++ {
++ lan_ifa = ifa;
++ break; /* found */
++ }
++ }
++ }
++ else
++ return 0;
++
++ if (lan_ifa) {
++ smb_nf_local_in_hook = mtk_smb_nf_local_in_hook;
++ smb_nf_pre_routing_hook = mtk_smb_nf_pre_routing_hook;
++ smb_nf_local_out_hook = mtk_smb_nf_local_out_hook;
++ smb_nf_post_routing_hook = mtk_smb_nf_post_routing_hook;
++ }
++
++ printk("Samba Netfilter Hook Enabled\n");
++
++ return 0;
++}
++
++void mtk_smb_hook_cleanup(void)
++{
++ lan_int = NULL;
++ lan_ifa = NULL;
++ smb_nf_local_in_hook = NULL;
++ smb_nf_pre_routing_hook = NULL;
++ smb_nf_local_out_hook = NULL;
++ smb_nf_post_routing_hook = NULL;
++
++ return;
++}
++
++module_init(mtk_smb_hook_init);
++module_exit(mtk_smb_hook_cleanup);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/net/ethernet/raeth/sync_write.h b/drivers/net/ethernet/raeth/sync_write.h
+new file mode 100644
+index 0000000..8b800e6
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/sync_write.h
+@@ -0,0 +1,103 @@
++#ifndef _MT_SYNC_WRITE_H
++#define _MT_SYNC_WRITE_H
++
++#if defined(__KERNEL__)
++
++#include <linux/io.h>
++#include <asm/cacheflush.h>
++//#include <asm/system.h>
++
++/*
++ * Define macros.
++ */
++
++#define mt65xx_reg_sync_writel(v, a) \
++ do { \
++ __raw_writel((v), IOMEM((a))); \
++ dsb(); \
++ } while (0)
++
++#define mt65xx_reg_sync_writew(v, a) \
++ do { \
++ __raw_writew((v), IOMEM((a))); \
++ dsb(); \
++ } while (0)
++
++#define mt65xx_reg_sync_writeb(v, a) \
++ do { \
++ __raw_writeb((v), IOMEM((a))); \
++ dsb(); \
++ } while (0)
++
++#define mt_reg_sync_writel(v, a) \
++ do { \
++ __raw_writel((v), IOMEM((a))); \
++ dsb(); \
++ } while (0)
++
++#define mt_reg_sync_writew(v, a) \
++ do { \
++ __raw_writew((v), IOMEM((a))); \
++ dsb(); \
++ } while (0)
++
++#define mt_reg_sync_writeb(v, a) \
++ do { \
++ __raw_writeb((v), IOMEM((a))); \
++ dsb(); \
++ } while (0)
++
++
++#else /* __KERNEL__ */
++
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <unistd.h>
++#include <string.h>
++
++#define dsb() \
++ do { \
++ __asm__ __volatile__ ("dsb" : : : "memory"); \
++ } while (0)
++
++#define mt65xx_reg_sync_writel(v, a) \
++ do { \
++ *(volatile unsigned int *)(a) = (v); \
++ dsb(); \
++ } while (0)
++
++#define mt65xx_reg_sync_writew(v, a) \
++ do { \
++ *(volatile unsigned short *)(a) = (v); \
++ dsb(); \
++ } while (0)
++
++#define mt65xx_reg_sync_writeb(v, a) \
++ do { \
++ *(volatile unsigned char *)(a) = (v); \
++ dsb(); \
++ } while (0)
++
++#define mt_reg_sync_writel(v, a) \
++ do { \
++ *(volatile unsigned int *)(a) = (v); \
++ dsb(); \
++ } while (0)
++
++#define mt_reg_sync_writew(v, a) \
++ do { \
++ *(volatile unsigned short *)(a) = (v); \
++ dsb(); \
++ } while (0)
++
++#define mt_reg_sync_writeb(v, a) \
++ do { \
++ *(volatile unsigned char *)(a) = (v); \
++ dsb(); \
++ } while (0)
++
++
++#endif /* __KERNEL__ */
++
++#endif /* !_MT_SYNC_WRITE_H */
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0064-arm-mediatek-add-mt7623-pcie-support.patch b/target/linux/mediatek/patches/0064-arm-mediatek-add-mt7623-pcie-support.patch
new file mode 100644
index 0000000000..ee82f9c9d7
--- /dev/null
+++ b/target/linux/mediatek/patches/0064-arm-mediatek-add-mt7623-pcie-support.patch
@@ -0,0 +1,436 @@
+From 29ceb2449cb3622ccfba9eb1c77bf2ac4162464b Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 13:15:29 +0200
+Subject: [PATCH 64/76] arm: mediatek: add mt7623 pcie support
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/arm/mach-mediatek/Makefile | 2 +-
+ arch/arm/mach-mediatek/pcie.c | 383 +++++++++++++++++++++++++++++++++++++++
+ arch/arm/mach-mediatek/pcie.h | 14 ++
+ 3 files changed, 398 insertions(+), 1 deletion(-)
+ create mode 100644 arch/arm/mach-mediatek/pcie.c
+ create mode 100644 arch/arm/mach-mediatek/pcie.h
+
+diff --git a/arch/arm/mach-mediatek/Makefile b/arch/arm/mach-mediatek/Makefile
+index 2116460..aca28a2 100644
+--- a/arch/arm/mach-mediatek/Makefile
++++ b/arch/arm/mach-mediatek/Makefile
+@@ -1,4 +1,4 @@
+ ifeq ($(CONFIG_SMP),y)
+ obj-$(CONFIG_ARCH_MEDIATEK) += platsmp.o
+ endif
+-obj-$(CONFIG_ARCH_MEDIATEK) += mediatek.o
++obj-$(CONFIG_ARCH_MEDIATEK) += mediatek.o pcie.o
+diff --git a/arch/arm/mach-mediatek/pcie.c b/arch/arm/mach-mediatek/pcie.c
+new file mode 100644
+index 0000000..8394712
+--- /dev/null
++++ b/arch/arm/mach-mediatek/pcie.c
+@@ -0,0 +1,383 @@
++/*
++ * Mediatek MT7623 SoC PCIE support
++ *
++ * Copyright (C) 2015 Mediatek
++ * Copyright (C) 2015 John Crispin <blogic@openwrt.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ */
++
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/ioport.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/delay.h>
++#include <asm/irq.h>
++#include <asm/mach/pci.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_irq.h>
++#include <linux/of_pci.h>
++#include <linux/reset.h>
++#include <linux/platform_device.h>
++
++#include "pcie.h"
++
++#define PCICFG 0x00
++#define PCIINT 0x08
++#define PCIENA 0x0C
++#define CFGADDR 0x20
++#define CFGDATA 0x24
++#define MEMBASE 0x28
++#define IOBASE 0x2C
++
++#define BAR0SETUP 0x10
++#define IMBASEBAR0 0x18
++#define PCIE_CLASS 0x34
++#define PCIE_SISTAT 0x50
++
++#define MTK_PCIE_HIGH_PERF BIT(14)
++#define PCIEP0_BASE 0x2000
++#define PCIEP1_BASE 0x3000
++#define PCIEP2_BASE 0x4000
++
++#define PHY_P0_CTL 0x9000
++#define PHY_P1_CTL 0xA000
++#define PHY_P2_CTL 0x4000
++
++#define RSTCTL_PCIE0_RST BIT(24)
++#define RSTCTL_PCIE1_RST BIT(25)
++#define RSTCTL_PCIE2_RST BIT(26)
++
++static void __iomem *pcie_base;
++static int pcie_card_link;
++
++static struct mtk_pcie_port {
++ int id;
++ int enable;
++ u32 base;
++ u32 phy_base;
++ u32 perst_n;
++ u32 reset;
++ u32 interrupt;
++ u32 link;
++} mtk_pcie_port[] = {
++ { 0, 1, PCIEP0_BASE, PHY_P0_CTL, BIT(1), RSTCTL_PCIE0_RST, BIT(20) },
++ { 1, 1, PCIEP1_BASE, PHY_P1_CTL, BIT(2), RSTCTL_PCIE1_RST, BIT(21) },
++ { 2, 0, PCIEP2_BASE, PHY_P2_CTL, BIT(3), RSTCTL_PCIE2_RST, BIT(22) },
++};
++
++#define mtk_foreach_port(p) \
++ for (p = mtk_pcie_port; p != &mtk_pcie_port[ARRAY_SIZE(mtk_pcie_port)]; p++)
++
++#define mtk_foreach_port_enabled(p) \
++ mtk_foreach_port(p) \
++ if (p->enable)
++
++#define mtk_foreach_port_link(p) \
++ mtk_foreach_port(p) \
++ if (p->link)
++
++static struct mtk_phy_init {
++ uint32_t reg;
++ uint32_t mask;
++ uint32_t val;
++} mtk_phy_init[] = {
++ { 0xC00, 0x33000, 0x22000 },
++ { 0xB04, 0xe0000000, 0x40000000 },
++ { 0xB00, 0xe, 0x4 },
++ { 0xC3C, 0xffff0000, 0x3c0000 },
++ { 0xC48, 0xffff, 0x36 },
++ { 0xC0C, 0x30000000, 0x10000000 },
++ { 0xC08, 0x3800c0, 0xc0 },
++ { 0xC10, 0xf0000, 0x20000 },
++ { 0xC0C, 0xf000, 0x1000 },
++ { 0xC14, 0xf0000, 0xa0000 },
++};
++
++static inline void pcie_w32(u32 val, unsigned reg)
++{
++ iowrite32(val, pcie_base + reg);
++}
++
++static inline u32 pcie_r32(unsigned reg)
++{
++ return ioread32(pcie_base + reg);
++}
++
++static inline void pcie_m32(u32 mask, u32 val, unsigned reg)
++{
++ u32 v = pcie_r32(reg);
++
++ v &= mask;
++ v |= val;
++ pcie_w32(v, reg);
++}
++
++static int pcie_config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val)
++{
++ unsigned int slot = PCI_SLOT(devfn);
++ u8 func = PCI_FUNC(devfn);
++ u32 address;
++ u32 data;
++ u32 num = 0;
++
++ if (bus)
++ num = bus->number;
++
++ address = (((where & 0xF00) >> 8) << 24) | (num << 16) | (slot << 11) | (func << 8) | (where & 0xfc);
++ pcie_m32(0xf0000000, address, CFGADDR);
++ data = pcie_r32(CFGDATA);
++
++ switch (size) {
++ case 1:
++ *val = (data >> ((where & 3) << 3)) & 0xff;
++ break;
++ case 2:
++ *val = (data >> ((where & 3) << 3)) & 0xffff;
++ break;
++ case 4:
++ *val = data;
++ break;
++ }
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int pcie_config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
++{
++ unsigned int slot = PCI_SLOT(devfn);
++ u8 func = PCI_FUNC(devfn);
++ u32 address;
++ u32 data;
++ u32 num = 0;
++
++ if (bus)
++ num = bus->number;
++
++ address = (((where & 0xF00) >> 8) << 24) | (num << 16) | (slot << 11) | (func << 8) | (where & 0xfc);
++ pcie_m32(0xf0000000, address, CFGADDR);
++ data = pcie_r32(CFGDATA);
++
++ switch (size) {
++ case 1:
++ data = (data & ~(0xff << ((where & 3) << 3))) |
++ (val << ((where & 3) << 3));
++ break;
++ case 2:
++ data = (data & ~(0xffff << ((where & 3) << 3))) |
++ (val << ((where & 3) << 3));
++ break;
++ case 4:
++ data = val;
++ break;
++ }
++
++ pcie_w32(data, CFGDATA);
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops mtk_pcie_ops = {
++ .read = pcie_config_read,
++ .write = pcie_config_write,
++};
++
++static struct resource pci_mem = {
++ .name = "PCIe Memory space",
++ .start = MEM_DIRECT1,
++ .end = (u32) (MEM_DIRECT1 + (unsigned char *) 0x0fffffff),
++ .flags = IORESOURCE_MEM,
++};
++
++static struct resource pci_io = {
++ .name = "PCIe IO space",
++ .start = IO_WIN,
++ .end = (u32) (IO_WIN + (unsigned char *) 0x0ffff),
++ .flags = IORESOURCE_IO,
++};
++
++static int __init mtk_pcie_setup(int nr, struct pci_sys_data *sys)
++{
++ sys->mem_offset = 0;
++ sys->io_offset = 0;
++
++ request_resource(&ioport_resource, &pci_io);
++ request_resource(&iomem_resource, &pci_mem);
++
++ pci_add_resource_offset(&sys->resources, &pci_io, sys->io_offset);
++ pci_add_resource_offset(&sys->resources, &pci_mem, sys->mem_offset);
++
++ return 1;
++}
++
++static struct pci_bus * __init mtk_pcie_scan_bus(int nr, struct pci_sys_data *sys)
++{
++ return pci_scan_root_bus(NULL, sys->busnr, &mtk_pcie_ops, sys,
++ &sys->resources);
++}
++
++static int __init mtk_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++ u16 cmd;
++ u32 val;
++
++ if (dev->bus->number == 0) {
++ pcie_config_write(NULL, slot, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE);
++ pcie_config_read(NULL, slot, 0, PCI_BASE_ADDRESS_0, &val);
++ printk("BAR0 at bus %d, slot %d\n", dev->bus->number, slot);
++ }
++
++ printk("bus=0x%x, slot = 0x%x, pin=0x%x, irq=0x%x\n", dev->bus->number, slot, pin, dev->irq);
++
++ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x14);
++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xFF);
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ cmd = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
++
++ return dev->irq;
++}
++
++static void __init mtk_pcie_preinit(void)
++{
++ struct mtk_pcie_port *port;
++ u32 val = 0;
++ int i;
++
++ pcibios_min_io = 0;
++ pcibios_min_mem = 0;
++
++#if defined (CONFIG_PCIE_PORT2)
++ printk("%s: PCIe/USB3 combo PHY mode (%x) =%x\n", __func__, SYSCFG1, REGDATA(SYSCFG1));
++ REGDATA(SYSCFG1) &= ~(0x300000);
++ printk("%s: PCIe/USB3 combo PHY mode (%x) =%x\n", __func__, SYSCFG1, REGDATA(SYSCFG1));
++#endif
++
++ /* PCIe RC Reset */
++ val = 0;
++ mtk_foreach_port_enabled(port)
++ val |= port->reset;
++ REGDATA(RSTCTL) |= val;
++ mdelay(10);
++ REGDATA(RSTCTL) &= ~val;
++ mdelay(10);
++
++ /* Configure PCIe PHY */
++ mtk_foreach_port_enabled(port) {
++ for (i = 0; i < ARRAY_SIZE(mtk_phy_init); i++) {
++ u32 val = pcie_r32(port->phy_base + mtk_phy_init[i].reg);
++ val &= ~mtk_phy_init[i].mask;
++ val |= mtk_phy_init[i].val;
++ pcie_w32(val, port->phy_base + mtk_phy_init[i].reg);
++ }
++ mdelay(10);
++ }
++
++ /* Enable RC */
++ mtk_foreach_port_enabled(port) {
++ val = 0;
++ pcie_config_read(NULL, port->id, 0, 0x73c, &val);
++ val &= ~(0x9fff)<<16;
++ val |= 0x806c<<16;
++ pcie_config_write(NULL, port->id, 0, 0x73c, val);
++ }
++
++ /* PCIe EP reset */
++ val = 0;
++ mtk_foreach_port_enabled(port)
++ val |= port->perst_n;
++ val |= MTK_PCIE_HIGH_PERF;
++ pcie_w32(pcie_r32(PCICFG) | val, PCICFG);
++ mdelay(10);
++ pcie_w32(pcie_r32(PCICFG) & ~val, PCICFG);
++ mdelay(10);
++
++ /* check the link status */
++ val = 0;
++ mtk_foreach_port_enabled(port) {
++ if ((pcie_r32(port->base + PCIE_SISTAT) & 0x1))
++ port->link = 1;
++ else
++ val |= port->reset;
++ }
++ REGDATA(RSTCTL) |= val;
++
++ mtk_foreach_port_link(port)
++ pcie_card_link++;
++
++ printk("PCIe Link count = %d\n", pcie_card_link);
++ if (!pcie_card_link)
++ return;
++
++ pcie_w32(MEM_WIN, MEMBASE);
++ pcie_w32(IO_WIN, IOBASE);
++
++ mtk_foreach_port_link(port) {
++ pcie_m32(0, port->interrupt, PCIENA);
++ pcie_w32(0x7FFF0001, port->base + BAR0SETUP);
++ pcie_w32(MEMORY_BASE, port->base + IMBASEBAR0);
++ pcie_w32(0x06040001, port->base + PCIE_CLASS);
++ printk("PCIE%d Setup OK\n", port->id);
++ }
++ val = 0;
++
++ pcie_config_read(NULL, pcie_card_link - 1, 0, 0x4, &val);
++ pcie_config_write(NULL, pcie_card_link - 1, 0, 0x4, val|0x4);
++ pcie_config_read(NULL, pcie_card_link - 1, 0, 0x70c, &val);
++ val &= ~(0xff3) << 8;
++ val |= 0x50 << 8;
++ pcie_config_write(NULL, pcie_card_link - 1, 0, 0x70c, val);
++ pcie_config_read(NULL, pcie_card_link - 1, 0, 0x70c, &val);
++}
++
++static struct hw_pci mtk_pci __initdata = {
++ .nr_controllers = 1,
++ .map_irq = mtk_pcie_map_irq,
++ .setup = mtk_pcie_setup,
++ .scan = mtk_pcie_scan_bus,
++ .preinit = mtk_pcie_preinit,
++};
++
++extern void mt7623_ethifsys_init(void);
++static int mtk_pcie_probe(struct platform_device *pdev)
++{
++ struct resource *pcie_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++
++ pcie_base = devm_ioremap_resource(&pdev->dev, pcie_res);
++ if (!pcie_base)
++ return -ENOMEM;
++
++ mt7623_ethifsys_init();
++ pci_common_init_dev(&pdev->dev, &mtk_pci);
++
++ return 0;
++}
++
++static const struct of_device_id mtk_pcie_ids[] = {
++ { .compatible = "mediatek,mt7623-pcie" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, mtk_pcie_ids);
++
++static struct platform_driver mtk_pcie_driver = {
++ .probe = mtk_pcie_probe,
++ .driver = {
++ .name = "mt7623-pcie",
++ .owner = THIS_MODULE,
++ .of_match_table = of_match_ptr(mtk_pcie_ids),
++ },
++};
++
++static int __init mtk_pcie_init(void)
++{
++ return platform_driver_register(&mtk_pcie_driver);
++}
++
++late_initcall(mtk_pcie_init);
+diff --git a/arch/arm/mach-mediatek/pcie.h b/arch/arm/mach-mediatek/pcie.h
+new file mode 100644
+index 0000000..400a760e
+--- /dev/null
++++ b/arch/arm/mach-mediatek/pcie.h
+@@ -0,0 +1,14 @@
++#define SYSCTL_BASE 0xFA000000
++#define MEM_WIN 0x1A150000
++#define IO_WIN 0x1A160000
++#define MEM_DIRECT1 0x60000000
++#define MEMORY_BASE 0x80000000
++
++#define REGADDR(x, y) (x##_BASE + y)
++#define REGDATA(x) *((volatile unsigned int *)(x))
++
++#define SYSCFG1 REGADDR(SYSCTL, 0x14)
++#define RSTCTL REGADDR(SYSCTL, 0x34)
++
++
++
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0065-arm-mediatek-add-mt7623-smp-support.patch b/target/linux/mediatek/patches/0065-arm-mediatek-add-mt7623-smp-support.patch
new file mode 100644
index 0000000000..98f8acb63c
--- /dev/null
+++ b/target/linux/mediatek/patches/0065-arm-mediatek-add-mt7623-smp-support.patch
@@ -0,0 +1,38 @@
+From 3f181d60fcd80b0d98849076ed2aa43de2cb6d8c Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 13:16:27 +0200
+Subject: [PATCH 65/76] arm: mediatek: add mt7623 smp support
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/arm/mach-mediatek/platsmp.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/arch/arm/mach-mediatek/platsmp.c b/arch/arm/mach-mediatek/platsmp.c
+index e266b3d..81fdcff 100644
+--- a/arch/arm/mach-mediatek/platsmp.c
++++ b/arch/arm/mach-mediatek/platsmp.c
+@@ -45,6 +45,12 @@ static const struct mtk_smp_boot_info mtk_mt6589_boot = {
+ { 0x38, 0x3c, 0x40 },
+ };
+
++static const struct mtk_smp_boot_info mtk_mt7623_boot = {
++ 0x10202000, 0x34, 0x30,
++ { 0x534c4131, 0x4c415332, 0x41534c33 },
++ { 0x38, 0x3c, 0x40 },
++};
++
+ static const struct of_device_id mtk_tz_smp_boot_infos[] __initconst = {
+ { .compatible = "mediatek,mt8135", .data = &mtk_mt8135_tz_boot },
+ { .compatible = "mediatek,mt8127", .data = &mtk_mt8135_tz_boot },
+@@ -52,6 +58,7 @@ static const struct of_device_id mtk_tz_smp_boot_infos[] __initconst = {
+
+ static const struct of_device_id mtk_smp_boot_infos[] __initconst = {
+ { .compatible = "mediatek,mt6589", .data = &mtk_mt6589_boot },
++ { .compatible = "mediatek,mt7623", .data = &mtk_mt7623_boot },
+ };
+
+ static void __iomem *mtk_smp_base;
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0066-arm-mediatek-add-m7623-devicetree.patch b/target/linux/mediatek/patches/0066-arm-mediatek-add-m7623-devicetree.patch
new file mode 100644
index 0000000000..4516561b3f
--- /dev/null
+++ b/target/linux/mediatek/patches/0066-arm-mediatek-add-m7623-devicetree.patch
@@ -0,0 +1,551 @@
+From a6bf117b5fe3acd76bbc45cc87fd80f589136e59 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 13:14:42 +0200
+Subject: [PATCH 66/76] arm: mediatek: add m7623 devicetree
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/arm/boot/dts/Makefile | 1 +
+ arch/arm/boot/dts/mt7623-evb.dts | 162 ++++++++++++++++++
+ arch/arm/boot/dts/mt7623.dtsi | 348 ++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 511 insertions(+)
+ create mode 100644 arch/arm/boot/dts/mt7623-evb.dts
+ create mode 100644 arch/arm/boot/dts/mt7623.dtsi
+
+diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
+index 992736b..525392e 100644
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -658,6 +658,7 @@ dtb-$(CONFIG_MACH_DOVE) += \
+ dtb-$(CONFIG_ARCH_MEDIATEK) += \
+ mt6589-aquaris5.dtb \
+ mt6592-evb.dtb \
++ mt7623-evb.dtb \
+ mt8127-moose.dtb \
+ mt8135-evbp1.dtb
+ endif
+diff --git a/arch/arm/boot/dts/mt7623-evb.dts b/arch/arm/boot/dts/mt7623-evb.dts
+new file mode 100644
+index 0000000..759142f
+--- /dev/null
++++ b/arch/arm/boot/dts/mt7623-evb.dts
+@@ -0,0 +1,162 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Joe.C <yingjoe.chen@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++/dts-v1/;
++#include <dt-bindings/gpio/gpio.h>
++#include "mt7623.dtsi"
++
++/ {
++ model = "MediaTek MT7623 Evaluation Board";
++ compatible = "mediatek,mt7623-evb", "mediatek,mt7623";
++
++ chosen {
++ stdout-path = &uart2;
++ };
++
++ memory {
++ reg = <0 0x80000000 0 0x10000000>;
++ };
++
++ usb_p1_vbus: fixedregulator@0 {
++ compatible = "regulator-fixed";
++ regulator-name = "usb_vbus";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ gpio = <&pio 130 GPIO_ACTIVE_HIGH>;
++ enable-active-high;
++ };
++};
++
++
++&pio {
++ pinctrl_uart2_default: uart2@0 {
++ pins {
++ pinmux = <MT7623_PIN_14_GPIO14_FUNC_URXD2>,
++ <MT7623_PIN_15_GPIO15_FUNC_UTXD2>;
++ };
++ };
++
++ pinctrl_i2c0_default: i2c@0 {
++ pins {
++ pinmux = <MT7623_PIN_75_SDA0_FUNC_SDA0>,
++ <MT7623_PIN_76_SCL0_FUNC_SCL0>;
++ };
++ };
++
++ pinctrl_pcie_default: pcie@0 {
++ pins {
++ pinmux = <MT7623_PIN_24_EINT2_FUNC_PCIE2_PERST_N>,
++ <MT7623_PIN_208_AUD_EXT_CK1_FUNC_PCIE0_PERST_N>,
++ <MT7623_PIN_209_AUD_EXT_CK2_FUNC_PCIE1_PERST_N>,
++ <MT7623_PIN_250_GPIO250_FUNC_PCIE0_CLKREQ_N>,
++ <MT7623_PIN_251_GPIO251_FUNC_PCIE0_WAKE_N>,
++ <MT7623_PIN_252_GPIO252_FUNC_PCIE1_CLKREQ_N>,
++ <MT7623_PIN_253_GPIO253_FUNC_PCIE1_WAKE_N>,
++ <MT7623_PIN_254_GPIO254_FUNC_PCIE2_CLKREQ_N>,
++ <MT7623_PIN_255_GPIO255_FUNC_PCIE2_WAKE_N>;
++ };
++ };
++
++ pinctrl_spi_default: spi@0 {
++ pins {
++ pinmux = <MT7623_PIN_7_SPI1_CSN_FUNC_SPI1_CS>,
++ <MT7623_PIN_8_SPI1_MI_FUNC_SPI1_MI>,
++ <MT7623_PIN_9_SPI1_MO_FUNC_SPI1_MO>,
++ <MT7623_PIN_199_SPI1_CK_FUNC_SPI1_CK>;
++ bias-disable;
++ };
++ };
++};
++
++&thermal {
++ status = "okay";
++};
++
++&uart2 {
++ status = "okay";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_uart2_default>;
++};
++
++&i2c0 {
++ status = "okay";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_i2c0_default>;
++};
++
++&spi {
++ status = "okay";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_spi_default>;
++
++ m25p80@0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "mx25l12805d";
++ reg = <0 0 0 0>;
++ linux,modalias = "m25p80", "w25q128";
++ spi-max-frequency = <10000000>;
++
++ partition@0 {
++ label = "u-boot";
++ reg = <0x0 0x30000>;
++ read-only;
++ };
++
++ partition@30000 {
++ label = "u-boot-env";
++ reg = <0x30000 0x10000>;
++ read-only;
++ };
++
++ factory: partition@40000 {
++ label = "factory";
++ reg = <0x40000 0x10000>;
++ read-only;
++ };
++
++ partition@50000 {
++ label = "firmware";
++ reg = <0x50000 0xfb0000>;
++ };
++ };
++};
++
++&mmc0 {
++ status = "okay";
++
++// pinctrl-names = "default", "state_uhs";
++// pinctrl-0 = <&mmc0_pins_default>;
++// pinctrl-1 = <&mmc0_pins_uhs>;
++ bus-width = <8>;
++ max-frequency = <50000000>;
++ cap-mmc-highspeed;
++// vmmc-supply = <&mt6397_vemc_3v3_reg>;
++// vqmmc-supply = <&mt6397_vio18_reg>;
++ non-removable;
++};
++
++&u3phy {
++ reg-p1-vbus-supply = <&usb_p1_vbus>;
++};
++
++&pcie {
++ status = "okay";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_pcie_default>;
++};
+diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi
+new file mode 100644
+index 0000000..ba74ed9
+--- /dev/null
++++ b/arch/arm/boot/dts/mt7623.dtsi
+@@ -0,0 +1,348 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Joe.C <yingjoe.chen@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <dt-bindings/clock/mt7623-clk.h>
++#include <dt-bindings/interrupt-controller/irq.h>
++#include <dt-bindings/interrupt-controller/arm-gic.h>
++#include <dt-bindings/pinctrl/mt7623-pinfunc.h>
++#include <dt-bindings/reset-controller/mt7623-resets.h>
++#include "skeleton64.dtsi"
++
++/ {
++ compatible = "mediatek,mt7623";
++ interrupt-parent = <&sysirq>;
++
++ cpus {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ enable-method = "mediatek,mt65xx-smp";
++ cpu@0 {
++ device_type = "cpu";
++ compatible = "arm,cortex-a7";
++ reg = <0x0>;
++ };
++ cpu@1 {
++ device_type = "cpu";
++ compatible = "arm,cortex-a7";
++ reg = <0x1>;
++ };
++ cpu@2 {
++ device_type = "cpu";
++ compatible = "arm,cortex-a7";
++ reg = <0x2>;
++ };
++ cpu@3 {
++ device_type = "cpu";
++ compatible = "arm,cortex-a7";
++ reg = <0x3>;
++ };
++
++ };
++
++ clk26m: oscillator@0 {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ clock-frequency = <26000000>;
++ clock-output-names = "clk26m";
++ };
++
++ clk32k: oscillator@1 {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ clock-frequency = <32000>;
++ clock-output-names = "clk32k";
++ };
++
++ timer {
++ compatible = "arm,armv7-timer";
++ interrupt-parent = <&gic>;
++ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) |
++ IRQ_TYPE_LEVEL_LOW)>,
++ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) |
++ IRQ_TYPE_LEVEL_LOW)>,
++ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
++ IRQ_TYPE_LEVEL_LOW)>,
++ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
++ IRQ_TYPE_LEVEL_LOW)>;
++ clock-frequency = <13000000>;
++ arm,cpu-registers-not-fw-configured;
++ };
++
++ thermal-zones {
++ cpu_thermal: cpu_thermal {
++ polling-delay-passive = <1000>;
++ polling-delay = <5000>;
++
++ thermal-sensors = <&thermal 1>;
++ };
++ };
++
++ soc {
++ #address-cells = <2>;
++ #size-cells = <2>;
++ compatible = "simple-bus";
++ ranges;
++
++ topckgen: topckgen@10000000 {
++ compatible = "mediatek,mt7623-topckgen";
++ reg = <0 0x10000000 0 0x1000>;
++ #clock-cells = <1>;
++ };
++
++ infracfg: infracfg@10001000 {
++ compatible = "mediatek,mt7623-infracfg", "syscon";
++ reg = <0 0x10001000 0 0x1000>;
++ #clock-cells = <1>;
++ #reset-cells = <1>;
++ };
++
++ pericfg: pericfg@10003000 {
++ compatible = "mediatek,mt7623-pericfg", "syscon";
++ reg = <0 0x10003000 0 0x1000>;
++ #clock-cells = <1>;
++ #reset-cells = <1>;
++ };
++
++ /*
++ * Pinctrl access register at 0x10005000 through regmap.
++ * Register 0x1000b000 is used by EINT.
++ */
++ pio: pinctrl@10005000 {
++ compatible = "mediatek,mt7623-pinctrl";
++ reg = <0 0x1000b000 0 0x1000>;
++ mediatek,pctl-regmap = <&syscfg_pctl_a>;
++ pins-are-numbered;
++ gpio-controller;
++ #gpio-cells = <2>;
++ interrupt-controller;
++ #interrupt-cells = <2>;
++ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
++ };
++
++ syscfg_pctl_a: syscfg_pctl_a@10005000 {
++ compatible = "mediatek,mt7623-pctl-a-syscfg", "syscon";
++ reg = <0 0x10005000 0 0x1000>;
++ };
++
++ wdt: watchdog@10007000 {
++ compatible = "mediatek,mt7623-wdt", "mediatek,mt6589-wdt";
++ reg = <0 0x10007000 0 0x18>;
++ };
++
++ timer: timer@10008000 {
++ compatible = "mediatek,mt7623-timer",
++ "mediatek,mt6577-timer";
++ reg = <0 0x10008000 0 0x80>;
++ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_LOW>;
++ clocks = <&topckgen CLK_TOP_AXI_SEL>,
++ <&topckgen CLK_TOP_RTC_SEL>;
++ clock-names = "system-clk", "rtc-clk";
++ };
++
++ sysirq: interrupt-controller@10200100 {
++ compatible = "mediatek,mt7623-sysirq",
++ "mediatek,mt6577-sysirq";
++ interrupt-controller;
++ #interrupt-cells = <3>;
++ interrupt-parent = <&gic>;
++ reg = <0 0x10200100 0 0x1c>;
++ };
++
++ apmixedsys: apmixedsys@10209000 {
++ compatible = "mediatek,mt7623-apmixedsys";
++ reg = <0 0x10209000 0 0x1000>;
++ #clock-cells = <1>;
++ };
++
++ gic: interrupt-controller@10211000 {
++ compatible = "arm,cortex-a7-gic";
++ interrupt-controller;
++ #interrupt-cells = <3>;
++ interrupt-parent = <&gic>;
++ reg = <0 0x10211000 0 0x1000>,
++ <0 0x10212000 0 0x1000>,
++ <0 0x10214000 0 0x2000>,
++ <0 0x10216000 0 0x2000>;
++ };
++
++ auxadc: auxadc@11001000 {
++ compatible = "mediatek,mt7623-auxadc", "mediatek,mt8173-auxadc";
++ reg = <0 0x11001000 0 0x1000>;
++ };
++
++ uart0: serial@11006000 {
++ compatible = "mediatek,mt7623-uart","mediatek,mt6577-uart";
++ reg = <0 0x11002000 0 0x400>;
++ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_LOW>;
++ clocks = <&pericfg CLK_PERI_UART0_SEL>, <&pericfg CLK_PERI_UART0>;
++ clock-names = "baud", "bus";
++
++ status = "disabled";
++ };
++
++ uart1: serial@11007000 {
++ compatible = "mediatek,mt7623-uart","mediatek,mt6577-uart";
++ reg = <0 0x11003000 0 0x400>;
++ interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_LOW>;
++ clocks = <&pericfg CLK_PERI_UART1_SEL>, <&pericfg CLK_PERI_UART1>;
++ clock-names = "baud", "bus";
++
++ status = "disabled";
++ };
++
++ uart2: serial@11008000 {
++ compatible = "mediatek,mt7623-uart","mediatek,mt6577-uart";
++ reg = <0 0x11004000 0 0x400>;
++ interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_LOW>;
++ clocks = <&pericfg CLK_PERI_UART2_SEL>, <&pericfg CLK_PERI_UART2>;
++ clock-names = "baud", "bus";
++
++ status = "disabled";
++ };
++
++ uart3: serial@11009000 {
++ compatible = "mediatek,mt7623-uart","mediatek,mt6577-uart";
++ reg = <0 0x11005000 0 0x400>;
++ interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_LOW>;
++ clocks = <&pericfg CLK_PERI_UART3_SEL>, <&pericfg CLK_PERI_UART3>;
++ clock-names = "baud", "bus";
++
++ status = "disabled";
++ };
++
++ spi: spi@1100a000 {
++ compatible = "medi/THEatek,mt7623-spi", "mediatek,mt6589-spi";
++ reg = <0 0x1100a000 0 0x1000>;
++ interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_LOW>;
++ clocks = <&pericfg CLK_PERI_SPI0>;
++ clock-names = "main";
++
++ status = "disabled";
++ };
++
++ thermal: thermal@1100b000 {
++ #thermal-sensor-cells = <1>;
++ compatible = "mediatek,mt7623-thermal", "mediatek,mt8173-thermal";
++ reg = <0 0x1100b000 0 0x1000>;
++ interrupts = <0 38 IRQ_TYPE_LEVEL_LOW>;
++ clocks = <&pericfg CLK_PERI_THERM>, <&pericfg CLK_PERI_AUXADC>;
++ clock-names = "therm", "auxadc";
++ resets = <&pericfg MT7623_PERI_THERM_SW_RST>;
++ reset-names = "therm";
++ auxadc = <&auxadc>;
++ apmixedsys = <&apmixedsys>;
++
++ status = "disabled";
++ };
++
++ i2c0: i2c@11007000 {
++ compatible = "mediatek,mt7623-i2c", "mediatek,mt6577-i2c";
++ reg = <0 0x11007000 0 0x70>,
++ <0 0x11000300 0 0x80>;
++ interrupts = <0 44 IRQ_TYPE_LEVEL_LOW>;
++ clock-frequency = <400000>;
++ clock-div = <16>;
++ clocks = <&pericfg CLK_PERI_I2C0>, <&pericfg CLK_PERI_AP_DMA>;
++ clock-names = "main", "dma";
++
++ status = "disabled";
++ };
++
++ mmc0: mmc@11230000 {
++ compatible = "mediatek,mt7623-mmc",
++ "mediatek,mt8135-mmc";
++ reg = <0 0x11230000 0 0x1000>;
++ interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_LOW>;
++ clocks = <&pericfg CLK_PERI_MSDC20_1>,
++ <&topckgen CLK_TOP_MSDC30_0_SEL>;
++ clock-names = "source", "hclk";
++ status = "disabled";
++ };
++
++ usb: usb30@11270000 {
++ compatible = "mediatek,mt7623-xhci", "mediatek,mt8173-xhci", "generic-xhci";
++ reg = <0 0x11270000 0 0x1000>;
++ interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
++ usb-phy = <&u3phy>;
++ usb3-lpm-capable;
++ };
++
++ u3phy: usb-phy@11271000 {
++ compatible = "mediatek,mt7623-u3phy", "mediatek,mt8173-u3phy";
++ reg = <0 0x11271000 0 0x3000>,
++ <0 0x11280000 0 0x20000>;
++// power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
++// reg-vusb33-supply = <&mt6397_vusb_reg>;
++ clocks = <&pericfg CLK_PERI_USB0>,
++ <&pericfg CLK_PERI_USB1>,
++ <&topckgen CLK_TOP_USB20_SEL>;
++// <&apmixedsys CLK_APMIXED_REF2USB_TX>;
++ clock-names = "wakeup_deb_p0",
++ "wakeup_deb_p1",
++ "sys_mac";
++// "u3phya_ref";
++ disable-usb2-p1;
++ };
++ };
++
++ ethernet@1B100000 {
++ compatible = "mediatek,mt7623-net";
++ interrupts = <0 200 IRQ_TYPE_LEVEL_LOW>;
++ };
++
++ pcie: pcie@1a140000 {
++ compatible = "mediatek,mt7623-pcie";
++ reg = <0 0x1a140000 0 0x10000>;
++
++ #address-cells = <3>;
++ #size-cells = <2>;
++
++ device_type = "pci";
++
++ bus-range = <0 255>;
++ ranges = <
++ 0x02000000 0 0 0x00000000 0x60000000 0 0x10000000 /* pci memory */
++ 0x01000000 0 0 0x00000000 0x1A160000 0 0x00010000 /* io space */
++ >;
++
++ pcie0 {
++ reg = <0x0000 0 0 0 0>;
++
++ #address-cells = <3>;
++ #size-cells = <2>;
++
++ device_type = "pci";
++ };
++
++ pcie1 {
++ reg = <0x0800 0 0 0 0>;
++
++ #address-cells = <3>;
++ #size-cells = <2>;
++
++ device_type = "pci";
++ };
++
++ pcie2 {
++ reg = <0x1000 0 0 0 0>;
++
++ #address-cells = <3>;
++ #size-cells = <2>;
++
++ device_type = "pci";
++ };
++
++ status = "disabled";
++ };
++};
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0067-arm-mediatek-add-mt7623-support.patch b/target/linux/mediatek/patches/0067-arm-mediatek-add-mt7623-support.patch
new file mode 100644
index 0000000000..28193cc86c
--- /dev/null
+++ b/target/linux/mediatek/patches/0067-arm-mediatek-add-mt7623-support.patch
@@ -0,0 +1,118 @@
+From 89556b1a4d98fbfe498c8f26e988cbb8266f7dfe Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 13:17:35 +0200
+Subject: [PATCH 67/76] arm: mediatek: add mt7623 support
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/arm/mach-mediatek/Kconfig | 6 ++
+ arch/arm/mach-mediatek/mediatek.c | 2 +
+ .../dt-bindings/reset-controller/mt7623-resets.h | 59 ++++++++++++++++++++
+ 3 files changed, 67 insertions(+)
+ create mode 100644 include/dt-bindings/reset-controller/mt7623-resets.h
+
+diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig
+index 7704818..5393d25 100644
+--- a/arch/arm/mach-mediatek/Kconfig
++++ b/arch/arm/mach-mediatek/Kconfig
+@@ -17,6 +17,12 @@ config MACH_MT6592
+ bool "MediaTek MT6592 SoCs support"
+ default ARCH_MEDIATEK
+
++config MACH_MT7623
++ bool "MediaTek MT7623 SoCs support"
++ default ARCH_MEDIATEK
++ select ARCH_HAS_PCI
++ select PCI
++
+ config MACH_MT8127
+ bool "MediaTek MT8127 SoCs support"
+ default ARCH_MEDIATEK
+diff --git a/arch/arm/mach-mediatek/mediatek.c b/arch/arm/mach-mediatek/mediatek.c
+index 6b38d67..ab8cf21 100644
+--- a/arch/arm/mach-mediatek/mediatek.c
++++ b/arch/arm/mach-mediatek/mediatek.c
+@@ -29,6 +29,7 @@ static void __init mediatek_timer_init(void)
+ void __iomem *gpt_base = 0;
+
+ if (of_machine_is_compatible("mediatek,mt6589") ||
++ of_machine_is_compatible("mediatek,mt7623") ||
+ of_machine_is_compatible("mediatek,mt8135") ||
+ of_machine_is_compatible("mediatek,mt8127")) {
+ /* turn on GPT6 which ungates arch timer clocks */
+@@ -48,6 +49,7 @@ static void __init mediatek_timer_init(void)
+ static const char * const mediatek_board_dt_compat[] = {
+ "mediatek,mt6589",
+ "mediatek,mt6592",
++ "mediatek,mt7623",
+ "mediatek,mt8127",
+ "mediatek,mt8135",
+ NULL,
+diff --git a/include/dt-bindings/reset-controller/mt7623-resets.h b/include/dt-bindings/reset-controller/mt7623-resets.h
+new file mode 100644
+index 0000000..28a7d69
+--- /dev/null
++++ b/include/dt-bindings/reset-controller/mt7623-resets.h
+@@ -0,0 +1,59 @@
++/*
++ * Copyright (c) 2015 OpenWrt
++ * Author: John Crispin
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT7623
++#define _DT_BINDINGS_RESET_CONTROLLER_MT7623
++
++/* INFRACFG resets */
++#define MT7623_INFRA_EMI_REG_RST 0
++#define MT7623_INFRA_DRAMC0_A0_RST 1
++#define MT7623_INFRA_FHCTL_RST 2
++#define MT7623_INFRA_APCIRQ_EINT_RST 3
++#define MT7623_INFRA_APXGPT_RST 4
++#define MT7623_INFRA_SCPSYS_RST 5
++#define MT7623_INFRA_KP_RST 6
++#define MT7623_INFRA_PMIC_WRAP_RST 7
++#define MT7623_INFRA_MIPI_RST 8
++#define MT7623_INFRA_IRRX_RST 9
++#define MT7623_INFRA_CEC_RST 10
++#define MT7623_INFRA_EMI_RST 32
++#define MT7623_INFRA_DRAMC0_RST 34
++#define MT7623_INFRA_SMI_RST 37
++#define MT7623_INFRA_M4U_RST 38
++
++/* PERICFG resets */
++#define MT7623_PERI_UART0_SW_RST 0
++#define MT7623_PERI_UART1_SW_RST 1
++#define MT7623_PERI_UART2_SW_RST 2
++#define MT7623_PERI_UART3_SW_RST 3
++#define MT7623_PERI_GCPU_SW_RST 5
++#define MT7623_PERI_BTIF_SW_RST 6
++#define MT7623_PERI_PWM_SW_RST 8
++#define MT7623_PERI_AUXADC_SW_RST 10
++#define MT7623_PERI_DMA_SW_RST 11
++#define MT7623_PERI_NFI_SW_RST 14
++#define MT7623_PERI_NLI_SW_RST 15
++#define MT7623_PERI_THERM_SW_RST 16
++#define MT7623_PERI_MSDC0_SW_RST 17
++#define MT7623_PERI_MSDC1_SW_RST 19
++#define MT7623_PERI_MSDC2_SW_RST 20
++#define MT7623_PERI_I2C0_SW_RST 22
++#define MT7623_PERI_I2C1_SW_RST 23
++#define MT7623_PERI_I2C2_SW_RST 24
++#define MT7623_PERI_I2C3_SW_RST 25
++#define MT7623_PERI_USB_SW_RST 28
++#define MT7623_PERI_ETH_SW_RST 29
++#define MT7623_PERI_SPI0_SW_RST 33
++
++#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT7623 */
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0068-SDK_compat.patch b/target/linux/mediatek/patches/0068-SDK_compat.patch
new file mode 100644
index 0000000000..2800dbd009
--- /dev/null
+++ b/target/linux/mediatek/patches/0068-SDK_compat.patch
@@ -0,0 +1,1579 @@
+From 4c48177826502673737609ffa04b66051a1e0f75 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 17:05:12 +0200
+Subject: [PATCH 68/76] SDK_compat
+
+---
+ arch/arm/include/asm/mach/mt_irq.h | 174 ++++++++
+ arch/arm/include/asm/rt2880/mt_irq.h | 174 ++++++++
+ arch/arm/include/asm/rt2880/rt_mmap.h | 58 +++
+ arch/arm/include/asm/rt2880/surfboardint.h | 42 ++
+ arch/arm/include/asm/rt2880/x_define_irq.h | 160 +++++++
+ arch/arm/mach-mediatek/mediatek.c | 186 ++++++++
+ arch/arm/mach-mediatek/mt_reg_base.h | 640 ++++++++++++++++++++++++++++
+ arch/arm/mach-mediatek/rt_mmap.h | 58 +++
+ 8 files changed, 1492 insertions(+)
+ create mode 100644 arch/arm/include/asm/mach/mt_irq.h
+ create mode 100644 arch/arm/include/asm/rt2880/mt_irq.h
+ create mode 100644 arch/arm/include/asm/rt2880/rt_mmap.h
+ create mode 100644 arch/arm/include/asm/rt2880/surfboardint.h
+ create mode 100644 arch/arm/include/asm/rt2880/x_define_irq.h
+ create mode 100644 arch/arm/mach-mediatek/mt_reg_base.h
+ create mode 100644 arch/arm/mach-mediatek/rt_mmap.h
+
+diff --git a/arch/arm/include/asm/mach/mt_irq.h b/arch/arm/include/asm/mach/mt_irq.h
+new file mode 100644
+index 0000000..ff265e0
+--- /dev/null
++++ b/arch/arm/include/asm/mach/mt_irq.h
+@@ -0,0 +1,174 @@
++#ifndef __MT_IRQ_H
++#define __MT_IRQ_H
++
++#define GIC_PRIVATE_SIGNALS (32)
++#define NR_GIC_SGI (16)
++#define NR_GIC_PPI (16)
++#define GIC_PPI_OFFSET (27)
++#define MT_NR_PPI (5)
++#define MT_NR_SPI (224)
++#define NR_MT_IRQ_LINE (GIC_PPI_OFFSET + MT_NR_PPI + MT_NR_SPI)
++
++#define MT65xx_EDGE_SENSITIVE 0
++#define MT65xx_LEVEL_SENSITIVE 1
++
++#define MT65xx_POLARITY_LOW 0
++#define MT65xx_POLARITY_HIGH 1
++
++#define GIC_PPI_GLOBAL_TIMER (GIC_PPI_OFFSET + 0)
++#define GIC_PPI_LEGACY_FIQ (GIC_PPI_OFFSET + 1)
++#define GIC_PPI_PRIVATE_TIMER (GIC_PPI_OFFSET + 2)
++#define GIC_PPI_NS_PRIVATE_TIMER (GIC_PPI_OFFSET + 3)
++#define GIC_PPI_LEGACY_IRQ (GIC_PPI_OFFSET + 4)
++
++#define MT_BTIF_IRQ_ID (GIC_PRIVATE_SIGNALS + 50)
++#define MT_DMA_BTIF_TX_IRQ_ID (GIC_PRIVATE_SIGNALS + 71)
++#define MT_DMA_BTIF_RX_IRQ_ID (GIC_PRIVATE_SIGNALS + 72)
++
++#if !defined(CONFIG_MT8127_FPGA)
++
++#if !defined(__ASSEMBLY__)
++#define X_DEFINE_IRQ(__name, __num, __pol, __sens) __name = __num,
++enum
++{
++#include "x_define_irq.h"
++};
++#undef X_DEFINE_IRQ
++#define MT6582_AHB_SLAVE_HIF_IRQ_ID WF_HIF_IRQ_ID /* FIXME */
++
++#endif
++
++#else
++
++#define MT6582_USB0_IRQ_ID (GIC_PRIVATE_SIGNALS + 32)
++#define MT6582_USB1_IRQ_ID (GIC_PRIVATE_SIGNALS + 33)
++#define MT_PTP_THERM_IRQ_ID (GIC_PRIVATE_SIGNALS + 38)
++#define MT_MSDC0_IRQ_ID (GIC_PRIVATE_SIGNALS + 39)
++#define MT_MSDC1_IRQ_ID (GIC_PRIVATE_SIGNALS + 40)
++//#define MT_MSDC2_IRQ_ID (GIC_PRIVATE_SIGNALS + 41) //6582 take off
++//#define MT_MSDC3_IRQ_ID (GIC_PRIVATE_SIGNALS + 42) //6582 take off
++#define MT6582_AP_HIF_IRQ_ID (GIC_PRIVATE_SIGNALS + 43)
++#define MT_I2C0_IRQ_ID (GIC_PRIVATE_SIGNALS + 44)
++#define MT_I2C1_IRQ_ID (GIC_PRIVATE_SIGNALS + 45)
++#define MT_I2C2_IRQ_ID (GIC_PRIVATE_SIGNALS + 46)
++#define MT_UART1_IRQ_ID (GIC_PRIVATE_SIGNALS + 51)
++#define MT_UART2_IRQ_ID (GIC_PRIVATE_SIGNALS + 52)
++#define MT_UART3_IRQ_ID (GIC_PRIVATE_SIGNALS + 53)
++#define MT_UART4_IRQ_ID (GIC_PRIVATE_SIGNALS + 54)
++#define MT_NFIECC_IRQ_ID (GIC_PRIVATE_SIGNALS + 55)
++#define MT_NFI_IRQ_ID (GIC_PRIVATE_SIGNALS + 56)
++#define MT_GDMA1_IRQ_ID (GIC_PRIVATE_SIGNALS + 57)
++#define MT_GDMA2_IRQ_ID (GIC_PRIVATE_SIGNALS + 58)
++#define MT_DMA_UART0_TX_IRQ_ID (GIC_PRIVATE_SIGNALS + 63)
++#define MT_DMA_UART0_RX_IRQ_ID (GIC_PRIVATE_SIGNALS + 64)
++#define MT_DMA_UART1_TX_IRQ_ID (GIC_PRIVATE_SIGNALS + 65)
++#define MT_DMA_UART1_RX_IRQ_ID (GIC_PRIVATE_SIGNALS + 66)
++#define MT_DMA_UART2_TX_IRQ_ID (GIC_PRIVATE_SIGNALS + 67)
++#define MT_DMA_UART2_RX_IRQ_ID (GIC_PRIVATE_SIGNALS + 68)
++#define MT6582_SPI1_IRQ_ID (GIC_PRIVATE_SIGNALS + 78)
++//#define MT_MSDC4_IRQ_ID (GIC_PRIVATE_SIGNALS + 83) //6582 take off
++#define MT_PTP_FSM_IRQ_ID (GIC_PRIVATE_SIGNALS + 85)
++#define MT_WDT_IRQ_ID (GIC_PRIVATE_SIGNALS + 88)//TBD:For build pass
++#define MT_APARM_DOMAIN_IRQ_ID (GIC_PRIVATE_SIGNALS + 94)
++#define MT_APARM_DECERR_IRQ_ID (GIC_PRIVATE_SIGNALS + 95)
++#if 1 //cliff
++#define MT6582_GPT_IRQ_ID (GIC_PRIVATE_SIGNALS + 112)//10.2 update
++#define MT_EINT_IRQ_ID (GIC_PRIVATE_SIGNALS + 113)//10.2 update
++#else
++#define MT6582_GPT_IRQ_ID (GIC_PRIVATE_SIGNALS + 113)//10.2 update
++#define MT_EINT_IRQ_ID (GIC_PRIVATE_SIGNALS + 116)//10.2 update
++#endif
++#define MT6582_PMIC_WRAP_IRQ_ID (GIC_PRIVATE_SIGNALS + 115)//0x80
++#define MT_KP_IRQ_ID (GIC_PRIVATE_SIGNALS + 116)
++#define MT_SPM_IRQ_ID (GIC_PRIVATE_SIGNALS + 117)
++#define MT_SPM1_IRQ_ID (GIC_PRIVATE_SIGNALS + 118)
++#define MT_VENC_IRQ_ID (GIC_PRIVATE_SIGNALS + 139)
++#define MT_VDEC_IRQ_ID (GIC_PRIVATE_SIGNALS + 140)
++#define CAMERA_ISP_IRQ0_ID (GIC_PRIVATE_SIGNALS + 143) // cam_irq_b
++#define CAMERA_ISP_IRQ1_ID (GIC_PRIVATE_SIGNALS + 144) // cam_irq1_b
++#define CAMERA_ISP_IRQ2_ID (GIC_PRIVATE_SIGNALS + 145) // cam_irq2_b
++//#define CAMERA_ISP_IRQ3_ID (GIC_PRIVATE_SIGNALS + 144) // cam_irq3_b 6582 take off
++#define MT6582_JPEG_ENC_IRQ_ID (GIC_PRIVATE_SIGNALS + 141)
++//#define MT6582_JPEG_DEC_IRQ_ID (GIC_PRIVATE_SIGNALS + 148) //6582 take off
++/* Not sure and comments for early porting */
++#define MT_EINT_DIRECT0_IRQ_ID (GIC_PRIVATE_SIGNALS + 121)
++
++#if 0
++#define MT_MFG_IRQ_GP_ID (GIC_PRIVATE_SIGNALS + 170)
++#define MT_MFG_IRQ_GPMMU_ID (GIC_PRIVATE_SIGNALS + 171)
++#define MT_MFG_IRQ_PP0_ID (GIC_PRIVATE_SIGNALS + 172)
++#define MT_MFG_IRQ_PPMMU0_ID (GIC_PRIVATE_SIGNALS + 173)
++#define MT_MFG_IRQ_PP1_ID (GIC_PRIVATE_SIGNALS + 174)
++#define MT_MFG_IRQ_PPMMU1_ID (GIC_PRIVATE_SIGNALS + 175)
++#else
++#define MT_MFG_IRQ0_ID (GIC_PRIVATE_SIGNALS + 170)
++#define MT_MFG_IRQ1_ID (GIC_PRIVATE_SIGNALS + 171)
++#define MT_MFG_IRQ2_ID (GIC_PRIVATE_SIGNALS + 172)
++#define MT_MFG_IRQ3_ID (GIC_PRIVATE_SIGNALS + 173)
++#define MT_MFG_IRQ4_ID (GIC_PRIVATE_SIGNALS + 174)
++#define MT_MFG_IRQ5_ID (GIC_PRIVATE_SIGNALS + 175)
++#define MT_MFG_IRQ6_ID (GIC_PRIVATE_SIGNALS + 176)
++#define MT_MFG_IRQ7_ID (GIC_PRIVATE_SIGNALS + 177)
++#define MT_MFG_IRQ8_ID (GIC_PRIVATE_SIGNALS + 178)
++#define MT_MFG_IRQ9_ID (GIC_PRIVATE_SIGNALS + 179)
++#define MT_MFG_IRQ10_ID (GIC_PRIVATE_SIGNALS + 180)
++#endif
++
++
++#if 0
++#define MT6582_DISP_MUTEX_IRQ_ID (GIC_PRIVATE_SIGNALS + 160)
++#define MT6582_DISP_ROT_IRQ_ID (GIC_PRIVATE_SIGNALS + 161)
++#define MT6582_DISP_SCL_IRQ_ID (GIC_PRIVATE_SIGNALS + 162)
++#define MT6582_DISP_OVL_IRQ_ID (GIC_PRIVATE_SIGNALS + 163)
++#define MT6582_DISP_WDMA0_IRQ_ID (GIC_PRIVATE_SIGNALS + 164)
++#define MT6582_DISP_WDMA1_IRQ_ID (GIC_PRIVATE_SIGNALS + 165)
++#define MT6582_DISP_RDMA0_IRQ_ID (GIC_PRIVATE_SIGNALS + 166)
++#define MT6582_DISP_RDMA1_IRQ_ID (GIC_PRIVATE_SIGNALS + 167)
++#define MT6582_DISP_BLS_IRQ_ID (GIC_PRIVATE_SIGNALS + 168)
++#define MT6582_DISP_COLOR_IRQ_ID (GIC_PRIVATE_SIGNALS + 169)
++#define MT6582_DISP_TDSHP_IRQ_ID (GIC_PRIVATE_SIGNALS + 170)
++#define MT6582_DISP_DBI_IRQ_ID (GIC_PRIVATE_SIGNALS + 171)
++#define MT6582_DISP_DSI_IRQ_ID (GIC_PRIVATE_SIGNALS + 172)
++#define MT6582_DISP_DPI0_IRQ_ID (GIC_PRIVATE_SIGNALS + 173)
++#define MT6582_DISP_DPI1_IRQ_ID (GIC_PRIVATE_SIGNALS + 174)
++#define MT6582_DISP_CMDQ_IRQ_ID (GIC_PRIVATE_SIGNALS + 176)
++#else
++#define MT6582_DISP_MDP_RDMA_IRQ_ID (GIC_PRIVATE_SIGNALS+146)
++#define MT6582_DISP_MDP_RSZ0_IRQ_ID (GIC_PRIVATE_SIGNALS+147)
++#define MT6582_DISP_MDP_RSZ1_IRQ_ID (GIC_PRIVATE_SIGNALS+148)
++#define MT6582_DISP_MDP_TDSHP_IRQ_ID (GIC_PRIVATE_SIGNALS+149)
++#define MT6582_DISP_MDP_WDMA_IRQ_ID (GIC_PRIVATE_SIGNALS+150)
++#define MT6582_DISP_MDP_WROT_IRQ_ID (GIC_PRIVATE_SIGNALS+151)
++#define MT6582_DISP_RDMA_IRQ_ID (GIC_PRIVATE_SIGNALS+152)
++#define MT6582_DISP_OVL_IRQ_ID (GIC_PRIVATE_SIGNALS+153)
++#define MT6582_DISP_WDMA_IRQ_ID (GIC_PRIVATE_SIGNALS+154)
++#define MT6582_DISP_BLS_IRQ_ID (GIC_PRIVATE_SIGNALS+155)
++#define MT6582_DISP_COLOR_IRQ_ID (GIC_PRIVATE_SIGNALS+156)
++#define MT6582_DISP_DSI_IRQ_ID (GIC_PRIVATE_SIGNALS+157)
++#define MT6582_DISP_DPI0_IRQ_ID (GIC_PRIVATE_SIGNALS+158)
++#define MT6582_DISP_CMDQ_IRQ_ID (GIC_PRIVATE_SIGNALS+159)
++#define MT6582_DISP_CMDQ_SECURE_IRQ_ID (GIC_PRIVATE_SIGNALS+160)
++#define MT6582_DISP_MUTEX_IRQ_ID (GIC_PRIVATE_SIGNALS+161)
++#define MT6582_DISP_SMI_LARB0_IRQ_ID (GIC_PRIVATE_SIGNALS+162)
++#define MT_CIRQ_IRQ_ID (GIC_PRIVATE_SIGNALS+187)
++#endif
++#define MT6582_APARM_GPTTIMER_IRQ_LINE MT6582_GPT_IRQ_ID
++
++// MT6582 Wifi AHB Slave HIF
++#define MT6582_AHB_SLAVE_HIF_IRQ_ID (GIC_PRIVATE_SIGNALS + 160)
++#define MT6582_HIF_PDMA_IRQ_ID (GIC_PRIVATE_SIGNALS + 59)
++
++/* These are defined for solving compile errors only. They are not existing on FPGA */
++#define TS_IRQ_ID (GIC_PRIVATE_SIGNALS + 163)
++#define CONN_WDT_IRQ_ID (GIC_PRIVATE_SIGNALS + 163)
++#define LOWBATTERY_IRQ_ID (GIC_PRIVATE_SIGNALS + 163)
++#define MD_WDT_IRQ_ID (GIC_PRIVATE_SIGNALS + 163)
++
++#define WF_HIF_IRQ_ID (GIC_PRIVATE_SIGNALS + 184)
++#define MT_CONN2AP_BTIF_WAKEUP_IRQ_ID (GIC_PRIVATE_SIGNALS + 185)
++#define BT_CVSD_IRQ_ID (GIC_PRIVATE_SIGNALS + 186)
++
++#define CCIF0_AP_IRQ_ID (GIC_PRIVATE_SIGNALS + 100)
++#endif
++
++#endif
+diff --git a/arch/arm/include/asm/rt2880/mt_irq.h b/arch/arm/include/asm/rt2880/mt_irq.h
+new file mode 100644
+index 0000000..ff265e0
+--- /dev/null
++++ b/arch/arm/include/asm/rt2880/mt_irq.h
+@@ -0,0 +1,174 @@
++#ifndef __MT_IRQ_H
++#define __MT_IRQ_H
++
++#define GIC_PRIVATE_SIGNALS (32)
++#define NR_GIC_SGI (16)
++#define NR_GIC_PPI (16)
++#define GIC_PPI_OFFSET (27)
++#define MT_NR_PPI (5)
++#define MT_NR_SPI (224)
++#define NR_MT_IRQ_LINE (GIC_PPI_OFFSET + MT_NR_PPI + MT_NR_SPI)
++
++#define MT65xx_EDGE_SENSITIVE 0
++#define MT65xx_LEVEL_SENSITIVE 1
++
++#define MT65xx_POLARITY_LOW 0
++#define MT65xx_POLARITY_HIGH 1
++
++#define GIC_PPI_GLOBAL_TIMER (GIC_PPI_OFFSET + 0)
++#define GIC_PPI_LEGACY_FIQ (GIC_PPI_OFFSET + 1)
++#define GIC_PPI_PRIVATE_TIMER (GIC_PPI_OFFSET + 2)
++#define GIC_PPI_NS_PRIVATE_TIMER (GIC_PPI_OFFSET + 3)
++#define GIC_PPI_LEGACY_IRQ (GIC_PPI_OFFSET + 4)
++
++#define MT_BTIF_IRQ_ID (GIC_PRIVATE_SIGNALS + 50)
++#define MT_DMA_BTIF_TX_IRQ_ID (GIC_PRIVATE_SIGNALS + 71)
++#define MT_DMA_BTIF_RX_IRQ_ID (GIC_PRIVATE_SIGNALS + 72)
++
++#if !defined(CONFIG_MT8127_FPGA)
++
++#if !defined(__ASSEMBLY__)
++#define X_DEFINE_IRQ(__name, __num, __pol, __sens) __name = __num,
++enum
++{
++#include "x_define_irq.h"
++};
++#undef X_DEFINE_IRQ
++#define MT6582_AHB_SLAVE_HIF_IRQ_ID WF_HIF_IRQ_ID /* FIXME */
++
++#endif
++
++#else
++
++#define MT6582_USB0_IRQ_ID (GIC_PRIVATE_SIGNALS + 32)
++#define MT6582_USB1_IRQ_ID (GIC_PRIVATE_SIGNALS + 33)
++#define MT_PTP_THERM_IRQ_ID (GIC_PRIVATE_SIGNALS + 38)
++#define MT_MSDC0_IRQ_ID (GIC_PRIVATE_SIGNALS + 39)
++#define MT_MSDC1_IRQ_ID (GIC_PRIVATE_SIGNALS + 40)
++//#define MT_MSDC2_IRQ_ID (GIC_PRIVATE_SIGNALS + 41) //6582 take off
++//#define MT_MSDC3_IRQ_ID (GIC_PRIVATE_SIGNALS + 42) //6582 take off
++#define MT6582_AP_HIF_IRQ_ID (GIC_PRIVATE_SIGNALS + 43)
++#define MT_I2C0_IRQ_ID (GIC_PRIVATE_SIGNALS + 44)
++#define MT_I2C1_IRQ_ID (GIC_PRIVATE_SIGNALS + 45)
++#define MT_I2C2_IRQ_ID (GIC_PRIVATE_SIGNALS + 46)
++#define MT_UART1_IRQ_ID (GIC_PRIVATE_SIGNALS + 51)
++#define MT_UART2_IRQ_ID (GIC_PRIVATE_SIGNALS + 52)
++#define MT_UART3_IRQ_ID (GIC_PRIVATE_SIGNALS + 53)
++#define MT_UART4_IRQ_ID (GIC_PRIVATE_SIGNALS + 54)
++#define MT_NFIECC_IRQ_ID (GIC_PRIVATE_SIGNALS + 55)
++#define MT_NFI_IRQ_ID (GIC_PRIVATE_SIGNALS + 56)
++#define MT_GDMA1_IRQ_ID (GIC_PRIVATE_SIGNALS + 57)
++#define MT_GDMA2_IRQ_ID (GIC_PRIVATE_SIGNALS + 58)
++#define MT_DMA_UART0_TX_IRQ_ID (GIC_PRIVATE_SIGNALS + 63)
++#define MT_DMA_UART0_RX_IRQ_ID (GIC_PRIVATE_SIGNALS + 64)
++#define MT_DMA_UART1_TX_IRQ_ID (GIC_PRIVATE_SIGNALS + 65)
++#define MT_DMA_UART1_RX_IRQ_ID (GIC_PRIVATE_SIGNALS + 66)
++#define MT_DMA_UART2_TX_IRQ_ID (GIC_PRIVATE_SIGNALS + 67)
++#define MT_DMA_UART2_RX_IRQ_ID (GIC_PRIVATE_SIGNALS + 68)
++#define MT6582_SPI1_IRQ_ID (GIC_PRIVATE_SIGNALS + 78)
++//#define MT_MSDC4_IRQ_ID (GIC_PRIVATE_SIGNALS + 83) //6582 take off
++#define MT_PTP_FSM_IRQ_ID (GIC_PRIVATE_SIGNALS + 85)
++#define MT_WDT_IRQ_ID (GIC_PRIVATE_SIGNALS + 88)//TBD:For build pass
++#define MT_APARM_DOMAIN_IRQ_ID (GIC_PRIVATE_SIGNALS + 94)
++#define MT_APARM_DECERR_IRQ_ID (GIC_PRIVATE_SIGNALS + 95)
++#if 1 //cliff
++#define MT6582_GPT_IRQ_ID (GIC_PRIVATE_SIGNALS + 112)//10.2 update
++#define MT_EINT_IRQ_ID (GIC_PRIVATE_SIGNALS + 113)//10.2 update
++#else
++#define MT6582_GPT_IRQ_ID (GIC_PRIVATE_SIGNALS + 113)//10.2 update
++#define MT_EINT_IRQ_ID (GIC_PRIVATE_SIGNALS + 116)//10.2 update
++#endif
++#define MT6582_PMIC_WRAP_IRQ_ID (GIC_PRIVATE_SIGNALS + 115)//0x80
++#define MT_KP_IRQ_ID (GIC_PRIVATE_SIGNALS + 116)
++#define MT_SPM_IRQ_ID (GIC_PRIVATE_SIGNALS + 117)
++#define MT_SPM1_IRQ_ID (GIC_PRIVATE_SIGNALS + 118)
++#define MT_VENC_IRQ_ID (GIC_PRIVATE_SIGNALS + 139)
++#define MT_VDEC_IRQ_ID (GIC_PRIVATE_SIGNALS + 140)
++#define CAMERA_ISP_IRQ0_ID (GIC_PRIVATE_SIGNALS + 143) // cam_irq_b
++#define CAMERA_ISP_IRQ1_ID (GIC_PRIVATE_SIGNALS + 144) // cam_irq1_b
++#define CAMERA_ISP_IRQ2_ID (GIC_PRIVATE_SIGNALS + 145) // cam_irq2_b
++//#define CAMERA_ISP_IRQ3_ID (GIC_PRIVATE_SIGNALS + 144) // cam_irq3_b 6582 take off
++#define MT6582_JPEG_ENC_IRQ_ID (GIC_PRIVATE_SIGNALS + 141)
++//#define MT6582_JPEG_DEC_IRQ_ID (GIC_PRIVATE_SIGNALS + 148) //6582 take off
++/* Not sure and comments for early porting */
++#define MT_EINT_DIRECT0_IRQ_ID (GIC_PRIVATE_SIGNALS + 121)
++
++#if 0
++#define MT_MFG_IRQ_GP_ID (GIC_PRIVATE_SIGNALS + 170)
++#define MT_MFG_IRQ_GPMMU_ID (GIC_PRIVATE_SIGNALS + 171)
++#define MT_MFG_IRQ_PP0_ID (GIC_PRIVATE_SIGNALS + 172)
++#define MT_MFG_IRQ_PPMMU0_ID (GIC_PRIVATE_SIGNALS + 173)
++#define MT_MFG_IRQ_PP1_ID (GIC_PRIVATE_SIGNALS + 174)
++#define MT_MFG_IRQ_PPMMU1_ID (GIC_PRIVATE_SIGNALS + 175)
++#else
++#define MT_MFG_IRQ0_ID (GIC_PRIVATE_SIGNALS + 170)
++#define MT_MFG_IRQ1_ID (GIC_PRIVATE_SIGNALS + 171)
++#define MT_MFG_IRQ2_ID (GIC_PRIVATE_SIGNALS + 172)
++#define MT_MFG_IRQ3_ID (GIC_PRIVATE_SIGNALS + 173)
++#define MT_MFG_IRQ4_ID (GIC_PRIVATE_SIGNALS + 174)
++#define MT_MFG_IRQ5_ID (GIC_PRIVATE_SIGNALS + 175)
++#define MT_MFG_IRQ6_ID (GIC_PRIVATE_SIGNALS + 176)
++#define MT_MFG_IRQ7_ID (GIC_PRIVATE_SIGNALS + 177)
++#define MT_MFG_IRQ8_ID (GIC_PRIVATE_SIGNALS + 178)
++#define MT_MFG_IRQ9_ID (GIC_PRIVATE_SIGNALS + 179)
++#define MT_MFG_IRQ10_ID (GIC_PRIVATE_SIGNALS + 180)
++#endif
++
++
++#if 0
++#define MT6582_DISP_MUTEX_IRQ_ID (GIC_PRIVATE_SIGNALS + 160)
++#define MT6582_DISP_ROT_IRQ_ID (GIC_PRIVATE_SIGNALS + 161)
++#define MT6582_DISP_SCL_IRQ_ID (GIC_PRIVATE_SIGNALS + 162)
++#define MT6582_DISP_OVL_IRQ_ID (GIC_PRIVATE_SIGNALS + 163)
++#define MT6582_DISP_WDMA0_IRQ_ID (GIC_PRIVATE_SIGNALS + 164)
++#define MT6582_DISP_WDMA1_IRQ_ID (GIC_PRIVATE_SIGNALS + 165)
++#define MT6582_DISP_RDMA0_IRQ_ID (GIC_PRIVATE_SIGNALS + 166)
++#define MT6582_DISP_RDMA1_IRQ_ID (GIC_PRIVATE_SIGNALS + 167)
++#define MT6582_DISP_BLS_IRQ_ID (GIC_PRIVATE_SIGNALS + 168)
++#define MT6582_DISP_COLOR_IRQ_ID (GIC_PRIVATE_SIGNALS + 169)
++#define MT6582_DISP_TDSHP_IRQ_ID (GIC_PRIVATE_SIGNALS + 170)
++#define MT6582_DISP_DBI_IRQ_ID (GIC_PRIVATE_SIGNALS + 171)
++#define MT6582_DISP_DSI_IRQ_ID (GIC_PRIVATE_SIGNALS + 172)
++#define MT6582_DISP_DPI0_IRQ_ID (GIC_PRIVATE_SIGNALS + 173)
++#define MT6582_DISP_DPI1_IRQ_ID (GIC_PRIVATE_SIGNALS + 174)
++#define MT6582_DISP_CMDQ_IRQ_ID (GIC_PRIVATE_SIGNALS + 176)
++#else
++#define MT6582_DISP_MDP_RDMA_IRQ_ID (GIC_PRIVATE_SIGNALS+146)
++#define MT6582_DISP_MDP_RSZ0_IRQ_ID (GIC_PRIVATE_SIGNALS+147)
++#define MT6582_DISP_MDP_RSZ1_IRQ_ID (GIC_PRIVATE_SIGNALS+148)
++#define MT6582_DISP_MDP_TDSHP_IRQ_ID (GIC_PRIVATE_SIGNALS+149)
++#define MT6582_DISP_MDP_WDMA_IRQ_ID (GIC_PRIVATE_SIGNALS+150)
++#define MT6582_DISP_MDP_WROT_IRQ_ID (GIC_PRIVATE_SIGNALS+151)
++#define MT6582_DISP_RDMA_IRQ_ID (GIC_PRIVATE_SIGNALS+152)
++#define MT6582_DISP_OVL_IRQ_ID (GIC_PRIVATE_SIGNALS+153)
++#define MT6582_DISP_WDMA_IRQ_ID (GIC_PRIVATE_SIGNALS+154)
++#define MT6582_DISP_BLS_IRQ_ID (GIC_PRIVATE_SIGNALS+155)
++#define MT6582_DISP_COLOR_IRQ_ID (GIC_PRIVATE_SIGNALS+156)
++#define MT6582_DISP_DSI_IRQ_ID (GIC_PRIVATE_SIGNALS+157)
++#define MT6582_DISP_DPI0_IRQ_ID (GIC_PRIVATE_SIGNALS+158)
++#define MT6582_DISP_CMDQ_IRQ_ID (GIC_PRIVATE_SIGNALS+159)
++#define MT6582_DISP_CMDQ_SECURE_IRQ_ID (GIC_PRIVATE_SIGNALS+160)
++#define MT6582_DISP_MUTEX_IRQ_ID (GIC_PRIVATE_SIGNALS+161)
++#define MT6582_DISP_SMI_LARB0_IRQ_ID (GIC_PRIVATE_SIGNALS+162)
++#define MT_CIRQ_IRQ_ID (GIC_PRIVATE_SIGNALS+187)
++#endif
++#define MT6582_APARM_GPTTIMER_IRQ_LINE MT6582_GPT_IRQ_ID
++
++// MT6582 Wifi AHB Slave HIF
++#define MT6582_AHB_SLAVE_HIF_IRQ_ID (GIC_PRIVATE_SIGNALS + 160)
++#define MT6582_HIF_PDMA_IRQ_ID (GIC_PRIVATE_SIGNALS + 59)
++
++/* These are defined for solving compile errors only. They are not existing on FPGA */
++#define TS_IRQ_ID (GIC_PRIVATE_SIGNALS + 163)
++#define CONN_WDT_IRQ_ID (GIC_PRIVATE_SIGNALS + 163)
++#define LOWBATTERY_IRQ_ID (GIC_PRIVATE_SIGNALS + 163)
++#define MD_WDT_IRQ_ID (GIC_PRIVATE_SIGNALS + 163)
++
++#define WF_HIF_IRQ_ID (GIC_PRIVATE_SIGNALS + 184)
++#define MT_CONN2AP_BTIF_WAKEUP_IRQ_ID (GIC_PRIVATE_SIGNALS + 185)
++#define BT_CVSD_IRQ_ID (GIC_PRIVATE_SIGNALS + 186)
++
++#define CCIF0_AP_IRQ_ID (GIC_PRIVATE_SIGNALS + 100)
++#endif
++
++#endif
+diff --git a/arch/arm/include/asm/rt2880/rt_mmap.h b/arch/arm/include/asm/rt2880/rt_mmap.h
+new file mode 100644
+index 0000000..e86b3bb
+--- /dev/null
++++ b/arch/arm/include/asm/rt2880/rt_mmap.h
+@@ -0,0 +1,58 @@
++#define HIFSYS_BASE 0xFA000000 //for PCIe/USB
++#define ETHDMASYS_BASE 0xFB000000 //for I2S/PCM/GDMA/HSDMA/FE/GMAC
++
++#define HIFSYS_PCI_BASE 0xFA140000
++#define HIFSYS_USB_HOST_BASE 0xFA1C0000
++#define HIFSYS_USB_HOST2_BASE 0xFA240000
++
++#define ETHDMASYS_SYSCTL_BASE 0xFB000000
++#define ETHDMASYS_RBUS_MATRIXCTL_BASE 0xFB000400
++#define ETHDMASYS_I2S_BASE 0xFB000A00
++#define ETHDMASYS_PCM_BASE 0xFB002000
++#define ETHDMASYS_GDMA_BASE 0xFB002800
++#define ETHDMASYS_HS_DMA_BASE 0xFB007000
++#define ETHDMASYS_FRAME_ENGINE_BASE 0xFB100000
++#define ETHDMASYS_PPE_BASE 0xFB100C00
++#define ETHDMASYS_ETH_SW_BASE 0xFB110000
++#define ETHDMASYS_CRYPTO_ENGINE_BASE 0xFB240000
++
++//for backward-compatible
++#define RALINK_FRAME_ENGINE_BASE ETHDMASYS_FRAME_ENGINE_BASE
++#define RALINK_PPE_BASE ETHDMASYS_PPE_BASE
++#define RALINK_SYSCTL_BASE ETHDMASYS_SYSCTL_BASE
++#define RALINK_ETH_SW_BASE ETHDMASYS_ETH_SW_BASE
++#define RALINK_GDMA_BASE ETHDMASYS_GDMA_BASE
++#define RALINK_HS_DMA_BASE ETHDMASYS_HS_DMA_BASE
++#define RALINK_11N_MAC_BASE 0 //unused for rt_rdm usage
++
++//Reset Control Register
++#define RSTCTL_SYS_RST (1<<0)
++#define RSTCTL_MCM_RST (1<<2)
++#define RSTCTL_HSDMA_RST (1<<5)
++#define RSTCTL_FE_RST (1<<6)
++#define RSTCTL_SPDIF_RST (1<<7)
++#define RSTCTL_TIMER_RST (1<<8)
++#define RSTCTL_CIRQ_RST (1<<9)
++#define RSTCTL_MC_RST (1<<10)
++#define RSTCTL_PCM_RST (1<<11)
++#define RSTCTL_GPIO_RST (1<<13)
++#define RSTCTL_GDMA_RST (1<<14)
++#define RSTCTL_NAND_RST (1<<15)
++#define RSTCTL_I2C_RST (1<<16)
++#define RSTCTL_I2S_RST (1<<17)
++#define RSTCTL_SPI_RST (1<<18)
++#define RSTCTL_UART0_RST (1<<19)
++#define RSTCTL_UART1_RST (1<<20)
++#define RSTCTL_UART2_RST (1<<21)
++#define RSTCTL_UPHY_RST (1<<22)
++#define RSTCTL_ETH_RST (1<<23)
++#define RSTCTL_PCIE0_RST (1<<24)
++#define RSTCTL_PCIE1_RST (1<<25)
++#define RSTCTL_PCIE2_RST (1<<26)
++#define RSTCTL_AUX_STCK_RST (1<<28)
++#define RSTCTL_CRYPT_RST (1<<29)
++#define RSTCTL_SDXC_RST (1<<30)
++#define RSTCTL_PWM_RST (1<<31)
++
++//for backward-compatible
++#define RALINK_FE_RST RSTCTL_FE_RST
+diff --git a/arch/arm/include/asm/rt2880/surfboardint.h b/arch/arm/include/asm/rt2880/surfboardint.h
+new file mode 100644
+index 0000000..4581598
+--- /dev/null
++++ b/arch/arm/include/asm/rt2880/surfboardint.h
+@@ -0,0 +1,42 @@
++#include "mt_irq.h"
++
++//#define SURFBOARDINT_SYSCTL 0 /* SYSCTL */
++#define SURFBOARDINT_FE MT_FE_ORIG_IRQ_ID /* FE */
++#define SURFBOARDINT_PCM MT_PCM_IRQ_ID /* PCM */
++//#define SURFBOARDINT_GPIO 6 /* GPIO */
++#define SURFBOARDINT_HSGDMA MT_HSDMA_IRQ_ID /* HSGDMA */
++#define SURFBOARDINT_DMA MT_GDMA_IRQ_ID /* DMA */
++//#define SURFBOARDINT_PC 9 /* Performance counter */
++#define SURFBOARDINT_I2S MT_I2S_IRQ_ID /* I2S */
++//#define SURFBOARDINT_SPI 11 /* SPI */
++//#define SURFBOARDINT_AES 13 /* AES */
++//#define SURFBOARDINT_AESENGINE 13 /* AES Engine */
++#define SURFBOARDINT_CRYPTO MT_CRYPTO_IRQ_ID /* CryptoEngine */
++//#define SURFBOARDINT_SDXC 14 /* SDXC */
++//#define SURFBOARDINT_ESW 17 /* ESW */
++#define SURFBOARDINT_USB0 MT_SSUSB_XHCI0_IRQ_ID /* USB0 */
++#define SURFBOARDINT_USB1 MT_SSUSB_XHCI1_IRQ_ID /* USB1 */
++//#define SURFBOARDINT_UART_LITE1 20 /* UART Lite */
++//#define SURFBOARDINT_UART_LITE2 21 /* UART Lite */
++//#define SURFBOARDINT_UART_LITE3 22 /* UART Lite */
++//#define SURFBOARDINT_UART1 SURFBOARDINT_UART_LITE1
++//#define SURFBOARDINT_UART SURFBOARDINT_UART_LITE2
++//#define SURFBOARDINT_WDG 23 /* WDG timer */
++//#define SURFBOARDINT_TIMER0 24 /* Timer0 */
++//#define SURFBOARDINT_TIMER1 25 /* Timer1 */
++//#define SURFBOARDINT_ILL_ACC 35 /* illegal access */
++#define RALINK_INT_PCIE0 MT_PCIE0_IRQ_ID /* PCIE0 */
++#define RALINK_INT_PCIE1 MT_PCIE1_IRQ_ID /* PCIE1 */
++#define RALINK_INT_PCIE2 MT_PCIE2_IRQ_ID /* PCIE2 */
++
++// Wait for RD to define IRQ source
++
++//#define RALINK_INT_xxx MT_CRYPTO_RING0_IRQ_ID /* */
++//#define RALINK_INT_xxx MT_CRYPTO_RING1_IRQ_ID /* */
++//#define RALINK_INT_xxx MT_CRYPTO_RING2_IRQ_ID /* */
++//#define RALINK_INT_xxx MT_FE_PDMA_IRQ_ID /* */
++//#define RALINK_INT_xxx MT_FE_QDMA_IRQ_ID /* */
++//#define RALINK_INT_xxx MT_PCIE_LINK_DOWN_RST_IRQ_ID /* */
++
++
++
+diff --git a/arch/arm/include/asm/rt2880/x_define_irq.h b/arch/arm/include/asm/rt2880/x_define_irq.h
+new file mode 100644
+index 0000000..4b2e669
+--- /dev/null
++++ b/arch/arm/include/asm/rt2880/x_define_irq.h
+@@ -0,0 +1,160 @@
++/*
++ * This file is generated automatically according to the design of silicon.
++ * Don't modify it directly.
++ */
++
++X_DEFINE_IRQ(MT6582_USB0_IRQ_ID , 64, L,LEVEL)
++X_DEFINE_IRQ(MT6582_USB1_IRQ_ID , 65, L,LEVEL)
++X_DEFINE_IRQ(TS_IRQ_ID , 66, L,EDGE)
++X_DEFINE_IRQ(TS_BATCH_IRQ_ID , 67, L,EDGE)
++X_DEFINE_IRQ(LOWBATTERY_IRQ_ID , 68, L,EDGE)
++X_DEFINE_IRQ(PWM_IRQ_ID , 69, L,LEVEL)
++X_DEFINE_IRQ(THERM_CTRL_IRQ_ID , 70, L,LEVEL)
++X_DEFINE_IRQ(MT_MSDC0_IRQ_ID , 71, L,LEVEL)
++X_DEFINE_IRQ(MT_MSDC1_IRQ_ID , 72, L,LEVEL)
++X_DEFINE_IRQ(MT_MSDC2_IRQ_ID , 73, L,LEVEL)
++X_DEFINE_IRQ(MT_MSDC3_IRQ_ID , 74, L,LEVEL)
++X_DEFINE_IRQ(MT_I2C0_IRQ_ID , 76, L,LEVEL)
++X_DEFINE_IRQ(MT_I2C1_IRQ_ID , 77, L,LEVEL)
++X_DEFINE_IRQ(MT_I2C2_IRQ_ID , 78, L,LEVEL)
++X_DEFINE_IRQ(BITF_IRQ_ID , 82, L,LEVEL)
++X_DEFINE_IRQ(MT_UART1_IRQ_ID , 83, L,LEVEL)
++X_DEFINE_IRQ(MT_UART2_IRQ_ID , 84, L,LEVEL)
++X_DEFINE_IRQ(MT_UART3_IRQ_ID , 85, L,LEVEL)
++X_DEFINE_IRQ(MT_UART4_IRQ_ID , 86, L,LEVEL)
++X_DEFINE_IRQ(MT_NFIECC_IRQ_ID , 87, L,LEVEL)
++X_DEFINE_IRQ(MT_NFI_IRQ_ID , 88, L,LEVEL)
++X_DEFINE_IRQ(MT_GDMA1_IRQ_ID , 89, L,LEVEL)
++X_DEFINE_IRQ(MT_GDMA2_IRQ_ID , 90, L,LEVEL)
++X_DEFINE_IRQ(MT6582_HIF_PDMA_IRQ_ID , 91, L,LEVEL)
++X_DEFINE_IRQ(AP_DMA_I2C0_IRQ_ID , 92, L,LEVEL)
++X_DEFINE_IRQ(AP_DMA_I2C1_IRQ_ID , 93, L,LEVEL)
++X_DEFINE_IRQ(AP_DMA_I2C2_IRQ_ID , 94, L,LEVEL)
++X_DEFINE_IRQ(MT_DMA_UART0_TX_IRQ_ID , 95, L,LEVEL)
++X_DEFINE_IRQ(MT_DMA_UART0_RX_IRQ_ID , 96, L,LEVEL)
++X_DEFINE_IRQ(MT_DMA_UART1_TX_IRQ_ID , 97, L,LEVEL)
++X_DEFINE_IRQ(MT_DMA_UART1_RX_IRQ_ID , 98, L,LEVEL)
++X_DEFINE_IRQ(MT_DMA_UART2_TX_IRQ_ID , 99, L,LEVEL)
++X_DEFINE_IRQ(MT_DMA_UART2_RX_IRQ_ID , 100, L,LEVEL)
++X_DEFINE_IRQ(MT_DMA_UART3_TX_IRQ_ID , 101, L,LEVEL)
++X_DEFINE_IRQ(MT_DMA_UART3_RX_IRQ_ID , 102, L,LEVEL)
++X_DEFINE_IRQ(AP_DMA_BTIF_TX_IRQ_ID , 103, L,LEVEL)
++X_DEFINE_IRQ(AP_DMA_BTIF_RX_IRQ_ID , 104, L,LEVEL)
++X_DEFINE_IRQ(MT_GCPU_IRQ_ID , 105, L,LEVEL)
++X_DEFINE_IRQ(MT_GCPU_DMX_IRQ_ID , 106, L,LEVEL)
++X_DEFINE_IRQ(MT_GCPU_MMU_IRQ_ID , 107, L,LEVEL)
++X_DEFINE_IRQ(MT_GCPU_MMU_SEC_IRQ_ID , 108, L,LEVEL)
++X_DEFINE_IRQ(MT_ETHER_NIC_WRAP_IRQ_ID , 109, L,LEVEL)
++X_DEFINE_IRQ(MT6582_SPI1_IRQ_ID , 110, L,LEVEL)
++X_DEFINE_IRQ(MSDC0_WAKEUP_PS_IRQ_ID , 111, H,EDGE)
++X_DEFINE_IRQ(MSDC1_WAKEUP_PS_IRQ_ID , 112, H,EDGE)
++X_DEFINE_IRQ(MSDC2_WAKEUP_PS_IRQ_ID , 113, H,EDGE)
++X_DEFINE_IRQ(MT_CRYPTO_RING0_IRQ_ID , 114, H,LEVEL)
++X_DEFINE_IRQ(MT_CRYPTO_RING1_IRQ_ID , 115, H,LEVEL)
++X_DEFINE_IRQ(MT_CRYPTO_RING2_IRQ_ID , 116, H,LEVEL)
++X_DEFINE_IRQ(MT_PTP_FSM_IRQ_ID , 117, L,LEVEL)
++X_DEFINE_IRQ(BTIF_WAKEUP_IRQ_ID , 118, L,LEVEL)
++X_DEFINE_IRQ(MT_IRRX_IRQ_ID , 119, L,LEVEL)
++X_DEFINE_IRQ(MT_WDT_IRQ_ID , 120, L,EDGE)
++X_DEFINE_IRQ(MT_CRYPTO_RING3_IRQ_ID , 123, H,LEVEL)
++X_DEFINE_IRQ(DCC_APARM_IRQ_ID , 124, L,LEVEL)
++X_DEFINE_IRQ(APARM_CTI_IRQ_ID , 125, L,LEVEL)
++X_DEFINE_IRQ(MT_APARM_DOMAIN_IRQ_ID , 126, L,LEVEL)
++X_DEFINE_IRQ(MT_APARM_DECERR_IRQ_ID , 127, L,LEVEL)
++X_DEFINE_IRQ(DOMAIN_ABORT_IRQ_ID0 , 128, L,LEVEL)
++X_DEFINE_IRQ(MT_CRYPTO_IRQ_ID , 129, H,LEVEL)
++X_DEFINE_IRQ(MT_HSDMA_IRQ_ID , 130, H,LEVEL)
++X_DEFINE_IRQ(MT_GDMA_IRQ_ID , 131, H,LEVEL)
++X_DEFINE_IRQ(CCIF0_AP_IRQ_ID , 132, L,LEVEL)
++X_DEFINE_IRQ(MT_I2S_IRQ_ID , 134, H,LEVEL)
++X_DEFINE_IRQ(MT_PCM_IRQ_ID , 135, H,LEVEL)
++X_DEFINE_IRQ(AFE_MCU_IRQ_ID , 136, L,LEVEL)
++X_DEFINE_IRQ(M4U1_IRQ_ID , 138, L,LEVEL)
++X_DEFINE_IRQ(M4UL2_IRQ_ID , 139, L,LEVEL)
++X_DEFINE_IRQ(M4UL2_SEC_IRQ_ID , 140, L,LEVEL)
++X_DEFINE_IRQ(REFRESH_RATE_IRQ_ID , 141, L,EDGE)
++X_DEFINE_IRQ(MT6582_APARM_GPTTIMER_IRQ_LINE, 144, L,LEVEL)
++X_DEFINE_IRQ(MT_EINT_IRQ_ID , 145, H,LEVEL)
++X_DEFINE_IRQ(EINT_EVENT_IRQ_ID , 146, L,LEVEL)
++X_DEFINE_IRQ(MT6582_PMIC_WRAP_IRQ_ID , 147, H,LEVEL)
++X_DEFINE_IRQ(MT_KP_IRQ_ID , 148, L,EDGE)
++X_DEFINE_IRQ(MT_SPM_IRQ_ID , 149, L,LEVEL)
++X_DEFINE_IRQ(MT_SPM1_IRQ_ID , 150, L,LEVEL)
++X_DEFINE_IRQ(MT_SPM2_IRQ_ID , 151, L,LEVEL)
++X_DEFINE_IRQ(MT_SPM3_IRQ_ID , 152, L,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT0_IRQ_ID , 153, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT1_IRQ_ID , 154, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT2_IRQ_ID , 155, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT3_IRQ_ID , 156, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT4_IRQ_ID , 157, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT5_IRQ_ID , 158, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT6_IRQ_ID , 159, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT7_IRQ_ID , 160, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT8_IRQ_ID , 161, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT9_IRQ_ID , 162, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT10_IRQ_ID , 163, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT11_IRQ_ID , 164, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT12_IRQ_ID , 165, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT13_IRQ_ID , 166, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT14_IRQ_ID , 167, H,LEVEL)
++X_DEFINE_IRQ(SMI_LARB0_IRQ_ID , 168, L,LEVEL)
++X_DEFINE_IRQ(SMI_LARB1_IRQ_ID , 169, L,LEVEL)
++X_DEFINE_IRQ(SMI_LARB2_IRQ_ID , 170, L,LEVEL)
++X_DEFINE_IRQ(MT_VDEC_IRQ_ID , 171, L,LEVEL)
++X_DEFINE_IRQ(MT_VENC_IRQ_ID , 172, L,LEVEL)
++X_DEFINE_IRQ(MT6582_JPEG_ENC_IRQ_ID , 173, L,LEVEL)
++X_DEFINE_IRQ(SENINF_IRQ_ID , 174, L,LEVEL)
++X_DEFINE_IRQ(CAMERA_ISP_IRQ0_ID , 175, L,LEVEL)
++X_DEFINE_IRQ(CAMERA_ISP_IRQ1_ID , 176, L,LEVEL)
++X_DEFINE_IRQ(CAMERA_ISP_IRQ2_ID , 177, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_MDP_RDMA_IRQ_ID , 178, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_MDP_RSZ0_IRQ_ID , 179, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_MDP_RSZ1_IRQ_ID , 180, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_MDP_TDSHP_IRQ_ID , 181, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_MDP_WDMA_IRQ_ID , 182, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_MDP_WROT_IRQ_ID , 183, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_RDMA_IRQ_ID , 184, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_OVL_IRQ_ID , 185, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_WDMA_IRQ_ID , 186, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_BLS_IRQ_ID , 187, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_COLOR_IRQ_ID , 188, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_DSI_IRQ_ID , 189, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_DPI0_IRQ_ID , 190, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_CMDQ_IRQ_ID , 191, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_CMDQ_SECURE_IRQ_ID, 192, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_MUTEX_IRQ_ID , 193, L,LEVEL)
++X_DEFINE_IRQ(MM_DUMMY0_IRQ_ID , 194, L,LEVEL)
++X_DEFINE_IRQ(MM_DUMMY1_IRQ_ID , 195, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_RDMA1_IRQ_ID , 196, L,LEVEL)
++X_DEFINE_IRQ(MM_DUMMY3_IRQ_ID , 197, L,LEVEL)
++X_DEFINE_IRQ(MM_DUMMY4_IRQ_ID , 198, L,LEVEL)
++X_DEFINE_IRQ(MM_DUMMY5_IRQ_ID , 199, L,LEVEL)
++X_DEFINE_IRQ(MM_DUMMY6_IRQ_ID , 200, L,LEVEL)
++X_DEFINE_IRQ(MM_DUMMY7_IRQ_ID , 201, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ0_ID , 202, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ1_ID , 203, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ2_ID , 204, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ3_ID , 205, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ4_ID , 206, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ5_ID , 207, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ6_ID , 208, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ7_ID , 209, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ8_ID , 210, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ9_ID , 211, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ10_ID , 212, L,LEVEL)
++X_DEFINE_IRQ(MT_APXGPT_SECURE_IRQ_ID , 213, L,LEVEL)
++X_DEFINE_IRQ(MT_CEC_IRQ_ID , 214, L,LEVEL)
++X_DEFINE_IRQ(CONN_WDT_IRQ_ID , 215, L,EDGE)
++X_DEFINE_IRQ(WF_HIF_IRQ_ID , 216, L,LEVEL)
++X_DEFINE_IRQ(MT_CONN2AP_BTIF_WAKEUP_IRQ_ID , 217, L,LEVEL)
++X_DEFINE_IRQ(BT_CVSD_IRQ_ID , 218, L,LEVEL)
++X_DEFINE_IRQ(MT_CIRQ_IRQ_ID , 219, L,LEVEL)
++X_DEFINE_IRQ(MT_PCIE_LINK_DOWN_RST_IRQ_ID , 224, H,EDGE)
++X_DEFINE_IRQ(MT_PCIE0_IRQ_ID , 225, H,LEVEL)
++X_DEFINE_IRQ(MT_PCIE1_IRQ_ID , 226, H,LEVEL)
++X_DEFINE_IRQ(MT_PCIE2_IRQ_ID , 227, H,LEVEL)
++X_DEFINE_IRQ(MT_SSUSB_XHCI0_IRQ_ID , 228, H,LEVEL)
++X_DEFINE_IRQ(MT_SSUSB_XHCI1_IRQ_ID , 229, H,LEVEL)
++X_DEFINE_IRQ(MT_FE_PDMA_IRQ_ID , 230, H,LEVEL)
++X_DEFINE_IRQ(MT_FE_QDMA_IRQ_ID , 231, H,LEVEL)
++X_DEFINE_IRQ(MT_FE_ORIG_IRQ_ID , 232, H,LEVEL)
+diff --git a/arch/arm/mach-mediatek/mediatek.c b/arch/arm/mach-mediatek/mediatek.c
+index ab8cf21..c0e373b 100644
+--- a/arch/arm/mach-mediatek/mediatek.c
++++ b/arch/arm/mach-mediatek/mediatek.c
+@@ -19,6 +19,186 @@
+ #include <linux/of.h>
+ #include <linux/clk-provider.h>
+ #include <linux/clocksource.h>
++#include <asm/mach/map.h>
++#include "rt_mmap.h"
++#include "mt_reg_base.h"
++
++#define IO_VIRT_TO_PHYS(v) (0x10000000 | ((v) & 0x0fffffff))
++
++static struct map_desc mt_io_desc[] __initdata =
++{
++#if !defined(CONFIG_MT8127_FPGA)
++ {
++ .virtual = INFRA_BASE,
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(INFRA_BASE)),
++ .length = (SZ_1M - SZ_4K),
++ .type = MT_DEVICE
++ },
++ /* Skip the mapping of 0xF0130000~0xF013FFFF to protect access from APMCU */
++ {
++ .virtual = (DEBUGTOP_BASE - SZ_4K),
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS((DEBUGTOP_BASE - SZ_4K))),
++ .length = (0x30000 + SZ_4K),
++ .type = MT_DEVICE
++ },
++ {
++ .virtual = (DEBUGTOP_BASE + 0x40000),
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(DEBUGTOP_BASE + 0x40000)),
++ .length = 0xC0000,
++ .type = MT_DEVICE
++ },
++ {
++ .virtual = MCUSYS_CFGREG_BASE,
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(MCUSYS_CFGREG_BASE)),
++ .length = SZ_2M,
++ .type = MT_DEVICE
++ },
++ /* //// */
++ {
++ .virtual = AP_DMA_BASE,
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(AP_DMA_BASE)),
++ .length = SZ_2M + SZ_1M,
++ .type = MT_DEVICE
++ },
++ {
++ /* virtual 0xF2000000, physical 0x00200000 */
++ .virtual = SYSRAM_BASE,
++ .pfn = __phys_to_pfn(0x00200000),
++ .length = SZ_128K,
++ .type = MT_DEVICE
++ },
++ {
++ .virtual = G3D_CONFIG_BASE,
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(G3D_CONFIG_BASE)),
++ .length = SZ_128K,
++ .type = MT_DEVICE
++ },
++ {
++ .virtual = DISPSYS_BASE,
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(DISPSYS_BASE)),
++ .length = SZ_16M,
++ .type = MT_DEVICE
++ },
++ {
++ .virtual = IMGSYS_CONFG_BASE,
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(IMGSYS_CONFG_BASE)),
++ .length = SZ_16M,
++ .type = MT_DEVICE
++ },
++ {
++ .virtual = VDEC_GCON_BASE,
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(VDEC_GCON_BASE)),
++ .length = SZ_16M,
++ .type = MT_DEVICE
++ },
++ {
++ /* virtual 0xF7000000, physical 0x08000000 */
++ .virtual = DEVINFO_BASE,
++ .pfn = __phys_to_pfn(0x08000000),
++ .length = SZ_64K,
++ .type = MT_DEVICE
++ },
++ {
++ .virtual = CONN_BTSYS_PKV_BASE,
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(CONN_BTSYS_PKV_BASE)),
++ .length = SZ_1M,
++ .type = MT_DEVICE
++ },
++ {
++ /* virtual 0xF9000000, physical 0x00100000 */
++ .virtual = INTER_SRAM,
++ .pfn = __phys_to_pfn(0x00100000),
++ .length = SZ_64K,
++ .type = MT_DEVICE
++ },
++ {
++ .virtual = HIFSYS_BASE,
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(HIFSYS_BASE)),
++ .length = SZ_16M,
++ .type = MT_DEVICE
++ },
++ {
++ .virtual = ETHDMASYS_BASE,
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(ETHDMASYS_BASE)),
++ .length = SZ_16M,
++ .type = MT_DEVICE
++ },
++#if 0
++ {
++ .virtual = BDP_DISPSYS_BASE,
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(BDP_DISPSYS_BASE)),
++ .length = SZ_32K + SZ_16K,
++ .type = MT_DEVICE
++ },
++#endif
++#else
++ {
++ .virtual = INFRA_BASE,
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(INFRA_BASE)),
++ .length = SZ_4M,
++ .type = MT_DEVICE
++ },
++ {
++ .virtual = AP_DMA_BASE,
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(AP_DMA_BASE)),
++ .length = SZ_2M + SZ_1M,
++ .type = MT_DEVICE
++ },
++ #if 0
++ {
++ .virtual = MMSYS1_CONFIG_BASE,
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(MMSYS1_CONFIG_BASE)),
++ .length = SZ_16M,
++ .type = MT_DEVICE
++ },
++ #endif
++ {
++ /* From: 0xF2000000 to 0xF2020000*/
++ .virtual = SYSRAM_BASE,
++ .pfn = __phys_to_pfn(0x00200000),
++ .length = SZ_128K,
++ .type = MT_DEVICE
++ },
++ {
++ .virtual = DISPSYS_BASE,
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(DISPSYS_BASE)),
++ .length = SZ_16M,
++ .type = MT_DEVICE
++ },
++ {
++ .virtual = IMGSYS_CONFG_BASE,
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(IMGSYS_CONFG_BASE)),
++ .length = SZ_16M,
++ .type = MT_DEVICE
++ },
++ /* G3DSYS */
++ {
++ .virtual = G3D_CONFIG_BASE,
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(G3D_CONFIG_BASE)),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ },
++ {
++ .virtual = DEVINFO_BASE,
++ .pfn = __phys_to_pfn(0x08000000),
++ .length = SZ_64K,
++ .type = MT_DEVICE
++ },
++ {
++ .virtual = MALI_BASE,
++ .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(MALI_BASE)),
++ .length = SZ_64K,
++ .type = MT_DEVICE
++ },
++ {
++ .virtual = INTER_SRAM,
++ .pfn = __phys_to_pfn(0x00100000),
++ .length = SZ_64K,
++ .type = MT_DEVICE
++ },
++#endif
++};
++
+
+
+ #define GPT6_CON_MT65xx 0x10008060
+@@ -55,7 +235,13 @@ static const char * const mediatek_board_dt_compat[] = {
+ NULL,
+ };
+
++void __init mt_map_io(void)
++{
++ iotable_init(mt_io_desc, ARRAY_SIZE(mt_io_desc));
++}
++
+ DT_MACHINE_START(MEDIATEK_DT, "Mediatek Cortex-A7 (Device Tree)")
+ .dt_compat = mediatek_board_dt_compat,
+ .init_time = mediatek_timer_init,
++ .map_io = mt_map_io,
+ MACHINE_END
+diff --git a/arch/arm/mach-mediatek/mt_reg_base.h b/arch/arm/mach-mediatek/mt_reg_base.h
+new file mode 100644
+index 0000000..cf2bb9e
+--- /dev/null
++++ b/arch/arm/mach-mediatek/mt_reg_base.h
+@@ -0,0 +1,640 @@
++/*
++ * This file is generated automatically according to the design of silicon.
++ * Don't modify it directly.
++ */
++
++#ifndef __MT_REG_BASE
++#define __MT_REG_BASE
++
++#if !defined(CONFIG_MT8127_FPGA)
++
++// APB Module cksys
++#define INFRA_BASE (0xF0000000)
++
++// APB Module infracfg_ao
++#define INFRACFG_AO_BASE (0xF0001000)
++
++// APB Module fhctl
++#define FHCTL_BASE (0xF0002000)
++
++// APB Module pericfg
++#define PERICFG_BASE (0xF0003000)
++
++// APB Module dramc
++#define DRAMC0_BASE (0xF0004000)
++
++// APB Module gpio
++#define GPIO_BASE (0xF0005000)
++
++// APB Module sleep
++#define SPM_BASE (0xF0006000)
++
++// APB Module toprgu
++#define TOPRGU_BASE (0xF0007000)
++#define AP_RGU_BASE TOPRGU_BASE
++
++// APB Module apxgpt
++#define APMCU_GPTIMER_BASE (0xF0008000)
++
++// APB Module rsvd
++#define RSVD_BASE (0xF0009000)
++
++// APB Module sej
++#define HACC_BASE (0xF000A000)
++
++// APB Module ap_cirq_eint
++#define AP_CIRQ_EINT (0xF000B000)
++
++// APB Module ap_cirq_eint
++#define EINT_BASE (0xF000B000)
++
++// APB Module smi
++#define SMI1_BASE (0xF000C000)
++
++// APB Module pmic_wrap
++#define PWRAP_BASE (0xF000D000)
++
++// APB Module device_apc_ao
++#define DEVAPC_AO_BASE (0xF000E000)
++
++// APB Module ddrphy
++#define DDRPHY_BASE (0xF000F000)
++
++// APB Module vencpll
++#define VENCPLL_BASE (0xF000F000)
++
++// APB Module mipi_tx_config
++#define MIPI_CONFIG_BASE (0xF0010000)
++
++// APB Module LVDS ANA
++#define LVDS_ANA_BASE (0xF0010400)
++
++// APB Module mipi_rx_ana
++#define MIPI_RX_ANA_BASE (0xF0215000)
++
++// APB Module kp
++#define KP_BASE (0xF0011000)
++
++// APB Module dbgapb
++#define DEBUGTOP_BASE (0xF0100000)
++
++// APB Module mcucfg
++#define MCUSYS_CFGREG_BASE (0xF0200000)
++
++// APB Module infracfg
++#define INFRACFG_BASE (0xF0201000)
++
++// APB Module sramrom
++#define SRAMROM_BASE (0xF0202000)
++
++// APB Module emi
++#define EMI_BASE (0xF0203000)
++
++// APB Module sys_cirq
++#define SYS_CIRQ_BASE (0xF0204000)
++
++// APB Module m4u
++#define SMI_MMU_TOP_BASE (0xF0205000)
++
++// APB Module nb_mmu
++#define NB_MMU0_BASE (0xF0205200)
++
++// APB Module nb_mmu
++#define NB_MMU1_BASE (0xF0205800)
++
++// APB Module efusec
++#define EFUSEC_BASE (0xF0206000)
++
++// APB Module device_apc
++#define DEVAPC_BASE (0xF0207000)
++
++// APB Module mcu_biu_cfg
++#define MCU_BIU_BASE (0xF0208000)
++
++// APB Module apmixed
++#define APMIXEDSYS_BASE (0xF0209000)
++
++// APB Module ccif
++#define AP_CCIF_BASE (0xF020A000)
++
++// APB Module ccif
++#define MD_CCIF_BASE (0xF020B000)
++
++// APB Module gpio1
++#define GPIO1_BASE (0xF020C000)
++
++// APB Module infra_mbist
++#define INFRA_TOP_MBIST_CTRL_BASE (0xF020D000)
++
++// APB Module dramc_conf_nao
++#define DRAMC_NAO_BASE (0xF020E000)
++
++// APB Module trng
++#define TRNG_BASE (0xF020F000)
++
++// APB Module ca9
++#define CORTEXA7MP_BASE (0xF0210000)
++
++// APB Module ap_dma
++#define AP_DMA_BASE (0xF1000000)
++
++// APB Module auxadc
++#define AUXADC_BASE (0xF1001000)
++
++// APB Module uart
++#define UART1_BASE (0xF1002000)
++
++// APB Module uart
++#define UART2_BASE (0xF1003000)
++
++// APB Module uart
++#define UART3_BASE (0xF1004000)
++
++// APB Module uart
++#define UART4_BASE (0xF1005000)
++
++// APB Module pwm
++#define PWM_BASE (0xF1006000)
++
++// APB Module i2c
++#define I2C0_BASE (0xF1007000)
++
++// APB Module i2c
++#define I2C1_BASE (0xF1008000)
++
++// APB Module i2c
++#define I2C2_BASE (0xF1009000)
++
++// APB Module spi
++#define SPI0_BASE (0xF100A000)
++#define SPI1_BASE (0xF100A000)
++
++// APB Module therm_ctrl
++#define THERMAL_BASE (0xF100B000)
++
++// APB Module btif
++#define BTIF_BASE (0xF100C000)
++
++// APB Module nfi
++#define NFI_BASE (0xF100D000)
++
++// APB Module nfiecc_16bit
++#define NFIECC_BASE (0xF100E000)
++
++// APB Module nli_arb
++#define NLI_ARB_BASE (0xF100F000)
++
++// APB Module peri_pwrap_bridge
++#define PERI_PWRAP_BRIDGE_BASE (0xF1017000)
++
++// APB Module usb2
++#define USB_BASE (0xF1200000)
++#define USB1_BASE (0xF1270000)
++
++// APB Module usb_sif
++#define USB_SIF_BASE (0xF1210000)
++
++// APB Module msdc
++#define MSDC_0_BASE (0xF1230000)
++
++// APB Module msdc
++#define MSDC_1_BASE (0xF1240000)
++
++// APB Module msdc
++#define MSDC_2_BASE (0xF1250000)
++
++// APB Module msdc
++#define MSDC_3_BASE (0xF12C0000)
++
++// APB Module wcn_ahb
++#define WCN_AHB_BASE (0xF1260000)
++
++// ARB Module ethernet
++#define ETHERNET_BASE (0xF1280000)
++// APB Module mfg_top
++#define G3D_CONFIG_BASE (0xF3000000)
++
++// APB Module mali
++#define MALI_BASE (0xF3040000)
++
++// APB Module mali_tb_cmd
++#define MALI_TB_BASE (0xF301f000)
++
++// APB Module mmsys_config
++#define DISPSYS_BASE (0xF4000000)
++
++// APB Module mdp_rdma
++#define MDP_RDMA_BASE (0xF4001000)
++
++// APB Module mdp_rsz
++#define MDP_RSZ0_BASE (0xF4002000)
++
++// APB Module mdp_rsz
++#define MDP_RSZ1_BASE (0xF4003000)
++
++// APB Module disp_wdma
++#define MDP_WDMA_BASE (0xF4004000)
++
++// APB Module disp_wdma
++#define WDMA1_BASE (0xF4004000)
++
++// APB Module mdp_wrot
++#define MDP_WROT_BASE (0xF4005000)
++
++// APB Module mdp_tdshp
++#define MDP_TDSHP_BASE (0xF4006000)
++
++// APB Module ovl
++#define DISP_OVL_BASE (0xF4007000)
++
++// APB Module ovl
++#define OVL0_BASE (0xF4007000)
++
++// APB Module ovl
++#define OVL1_BASE (0xF4007000)
++
++// APB Module disp_rdma
++#define DISP_RDMA_BASE (0xF4008000)
++
++// APB Module disp_rdma
++#define R_DMA1_BASE (0xF4008000)
++
++// APB Module disp_rdma
++#define R_DMA0_BASE (0xF4008000)
++
++// APB Module disp_wdma
++#define DISP_WDMA_BASE (0xF4009000)
++
++// APB Module disp_wdma
++#define WDMA0_BASE (0xF4009000)
++
++// APB Module disp_bls
++#define DISP_BLS_BASE (0xF400A000)
++
++// APB Module disp_color_config
++#define DISP_COLOR_BASE (0xF400B000)
++
++// APB Module dsi
++#define DSI_BASE (0xF400C000)
++
++// APB Module disp_dpi
++#define DPI_BASE (0xF400D000)
++
++// APB Module disp_mutex
++#define MMSYS_MUTEX_BASE (0xF400E000)
++
++// APB Module mm_cmdq
++#define MMSYS_CMDQ_BASE (0xF400F000)
++
++#define DPI1_BASE (0xF4014000)
++
++
++// APB Module smi_larb
++#define SMI_LARB0_BASE (0xF4010000)
++
++// APB Module smi
++#define SMI_BASE (0xF4011000)
++
++// LVDS TX
++#define LVDS_TX_BASE (0xF4016200)
++
++// APB Module smi_larb
++#define SMILARB2_BASE (0xF5001000)
++
++// APB Module smi_larb
++#define SMI_LARB3_BASE (0xF5001000)
++
++// APB Module mmu
++#define SMI_LARB3_MMU_BASE (0xF5001800)
++
++// APB Module smi_larb
++#define SMI_LARB4_BASE (0xF5002000)
++
++// APB Module fake_eng
++#define FAKE_ENG_BASE (0xF5002000)
++
++// APB Module mmu
++#define SMI_LARB4_MMU_BASE (0xF5002800)
++
++// APB Module smi
++#define VENC_BASE (0xF5009000)
++
++// APB Module jpgenc
++#define JPGENC_BASE (0xF500A000)
++
++// APB Module vdecsys_config
++#define VDEC_GCON_BASE (0xF6000000)
++
++// APB Module smi_larb
++#define SMI_LARB1_BASE (0xF6010000)
++
++// APB Module mmu
++#define SMI_LARB1_MMU_BASE (0xF6010800)
++
++// APB Module vdtop
++#define VDEC_BASE (0xF6020000)
++
++// APB Module vdtop
++#define VDTOP_BASE (0xF6020000)
++
++// APB Module vld
++#define VLD_BASE (0xF6021000)
++
++// APB Module vld_top
++#define VLD_TOP_BASE (0xF6021800)
++
++// APB Module mc
++#define MC_BASE (0xF6022000)
++
++// APB Module avc_vld
++#define AVC_VLD_BASE (0xF6023000)
++
++// APB Module avc_mv
++#define AVC_MV_BASE (0xF6024000)
++
++// APB Module vdec_pp
++#define VDEC_PP_BASE (0xF6025000)
++
++// APB Module vp8_vld
++#define VP8_VLD_BASE (0xF6026800)
++
++// APB Module vp6
++#define VP6_BASE (0xF6027000)
++
++// APB Module vld2
++#define VLD2_BASE (0xF6027800)
++
++// APB Module mc_vmmu
++#define MC_VMMU_BASE (0xF6028000)
++
++// APB Module pp_vmmu
++#define PP_VMMU_BASE (0xF6029000)
++
++// APB Module imgsys
++#define IMGSYS_CONFG_BASE (0xF5000000)
++
++// APB Module cam
++#define CAMINF_BASE (0xF5000000)
++
++// APB Module csi2
++#define CSI2_BASE (0xF5000000)
++
++// APB Module seninf
++#define SENINF_BASE (0xF5000000)
++
++// APB Module seninf_tg
++#define SENINF_TG_BASE (0xF5000000)
++
++// APB Module seninf_top
++#define SENINF_TOP_BASE (0xF5000000)
++
++// APB Module mipi_rx_config
++#define MIPI_RX_CONFIG_BASE (0xF500C000)
++
++// APB Module scam
++#define SCAM_BASE (0xF5008000)
++
++// APB Module ncsi2
++#define NCSI2_BASE (0xF5008000)
++
++// APB Module ccir656
++#define CCIR656_BASE (0xF5000000)
++
++// APB Module n3d_ctl
++#define N3D_CTL_BASE (0xF5000000)
++
++// APB Module fdvt
++#define FDVT_BASE (0xF500B000)
++
++// APB Module audiosys
++#define AUDIO_BASE (0xF1221000)
++#define AUDIO_REG_BASE (0xF1220000)
++
++// CONNSYS
++#define CONN_BTSYS_PKV_BASE (0xF8000000)
++#define CONN_BTSYS_TIMCON_BASE (0xF8010000)
++#define CONN_BTSYS_RF_CONTROL_BASE (0xF8020000)
++#define CONN_BTSYS_MODEM_BASE (0xF8030000)
++#define CONN_BTSYS_BT_CONFIG_BASE (0xF8040000)
++#define CONN_MCU_CONFIG_BASE (0xF8070000)
++#define CONN_TOP_CR_BASE (0xF80B0000)
++#define CONN_HIF_CR_BASE (0xF80F0000)
++
++/*
++ * Addresses below are added manually.
++ * They cannot be mapped via IO_VIRT_TO_PHYS().
++ */
++
++#define GIC_CPU_BASE (CORTEXA7MP_BASE + 0x2000)
++#define GIC_DIST_BASE (CORTEXA7MP_BASE + 0x1000)
++#define SYSRAM_BASE 0xF2000000 /* L2 cache shared RAM */
++#define DEVINFO_BASE 0xF7000000
++#define INTER_SRAM 0xF9000000
++
++#else
++
++#define SMI_MMU_TOP_BASE 0xF0205000
++#define SMILARB2_BASE 0xF5001000
++
++/* on-chip SRAM */
++#define INTER_SRAM 0xF9000000
++
++/* infrasys */
++//#define TOPRGU_BASE 0xF0000000
++#define INFRA_BASE 0xF0000000
++#define INFRACFG_BASE 0xF0001000
++#define INFRACFG_AO_BASE 0xF0001000
++#define FHCTL_BASE 0xF0002000
++#define PERICFG_BASE 0xF0003000
++#define DRAMC0_BASE 0xF0004000
++#define DDRPHY_BASE 0xF000F000
++#define DRAMC_NAO_BASE 0xF020E000
++#define GPIO_BASE 0xF0005000
++#define GPIO1_BASE 0xF020C000
++#define TOPSM_BASE 0xF0006000
++#define SPM_BASE 0xF0006000
++#define TOPRGU_BASE 0xF0007000
++#define AP_RGU_BASE TOPRGU_BASE
++#define APMCU_GPTIMER_BASE 0xF0008000
++#define HACC_BASE 0xF000A000
++#define AP_CIRQ_EINT 0xF000B000
++#define SMI1_BASE 0xF000C000
++#define MIPI_CONFIG_BASE 0xF0010000
++// APB Module LVDS ANA
++#define LVDS_ANA_BASE (0xF0010400)
++
++
++#define KP_BASE 0xF0011000
++#if 0
++#define DEVICE_APC_0_BASE 0xF0010000
++#define DEVICE_APC_1_BASE 0xF0011000
++#define DEVICE_APC_2_BASE 0xF0012000
++#define DEVICE_APC_3_BASE 0xF0013000
++#define DEVICE_APC_4_BASE 0xF0014000
++#define SMI0_BASE 0xF0208000
++#endif
++#define EINT_BASE 0xF000B000
++
++
++#define DEBUGTOP_BASE 0xF0100000
++#define MCUSYS_CFGREG_BASE 0xF0200000
++#define SRAMROM_BASE 0xF0202000
++#define EMI_BASE 0xF0203000
++#define EFUSEC_BASE 0xF0206000
++#define MCU_BIU_BASE 0xF0208000
++#define APMIXED_BASE 0xF0209000
++#define APMIXEDSYS_BASE 0xF0209000
++#define AP_CCIF_BASE 0xF020A000
++#define MD_CCIF_BASE 0xF020B000
++#define INFRA_TOP_MBIST_CTRL_BASE 0xF020D000
++#define DRAMC_NAO_BASE 0xF020E000
++#define CORTEXA7MP_BASE 0xF0210000
++#define GIC_CPU_BASE (CORTEXA7MP_BASE + 0x2000)
++#define GIC_DIST_BASE (CORTEXA7MP_BASE + 0x1000)
++//#define SMI_LARB_BASE 0xF0211000
++//#define MCUSYS_AVS_BASE 0xF0212000
++
++/* perisys */
++/*avalaible*/
++#define AP_DMA_BASE 0xF1000000
++#define AUXADC_BASE 0xF1001000
++#define UART1_BASE 0xF1002000
++#define UART2_BASE 0xF1003000
++#define UART3_BASE 0xF1004000
++#define UART4_BASE 0xF1005000
++#define PWM_BASE 0xF1006000
++#define I2C0_BASE 0xF1007000
++#define I2C1_BASE 0xF1008000
++#define I2C2_BASE 0xF1009000
++#define SPI0_BASE 0xF100A000
++#define BTIF_BASE (0xF100C000)
++#define NFI_BASE 0xF100D000
++#define NFIECC_BASE 0xF100E000
++#define NLI_ARB_BASE 0xF100F000
++#define I2C3_BASE 0xF1010000 //FIXME 6582 take off
++#define SPI1_BASE 0xF100A000
++#define THERMAL_BASE 0xF100B000
++
++// APB Module pmic_wrap
++#define PWRAP_BASE (0xF000D000)
++
++#if 0
++//#define IRDA_BASE 0xF1007000
++#define I2C4_BASE 0xF1014000
++#define I2CDUAL_BASE 0xF1015000
++#define ACCDET_BASE 0xF1016000
++#define AP_HIF_BASE 0xF1017000
++#define MD_HIF_BASE 0xF1018000
++#define GCPU_BASE 0xF101B000
++#define GCPU_NS_BASE 0xF01C000
++#define GCPU_MMU_BASE 0xF01D000
++#define SATA_BASE 0xF01E000
++#define CEC_BASE 0xF01F000
++//#define SPI1_BASE 0xF1022000
++#endif
++
++#define USB1_BASE 0xF1270000
++#define USB2_BASE 0xF1200000
++#define USB_BASE 0xF1200000
++#define USB_SIF_BASE 0xF1210000
++//#define USB3_BASE 0xF1220000
++#define MSDC_0_BASE 0xF1230000
++#define MSDC_1_BASE 0xF1240000
++#define MSDC_2_BASE 0xF1250000
++#define MSDC_3_BASE 0xF12C0000
++#define MSDC_4_BASE 0xF1270000
++//#define ETHERNET_BASE 0xF1290000
++
++//#define ETB_BASE 0xF0111000
++//#define ETM_BASE 0xF017C000
++
++
++/* SMI common subsystem */
++#define SYSRAM_BASE 0xF2000000
++#define AUDIO_REG_BASE 0xF2030000
++#define MFG_AXI_BASE 0xF2060000
++#define CONN_MCU_CONFIG_BASE 0xF8070000
++#define AUDIO_BASE 0xF1200000 //0xF2071000
++#define MMSYS1_CONFIG_BASE 0xF2080000
++#define SMI_LARB0_BASE 0xF2081000
++// APB Module smi
++#define SMI_BASE (0xF4011000)
++#define SMI_LARB1_BASE 0xF2082000
++#define SMI_LARB2_BASE 0xF2083000
++#define VDEC_GCON_BASE 0xF6000000 //0xF4000000
++#define VDEC_BASE 0xF4020000
++#define VENC_TOP_BASE 0xF7000000
++#define VENC_BASE 0xF7002000
++#define JPGENC_BASE 0xF500A000
++#define R_DMA0_BASE 0xF2086000
++#define R_DMA1_BASE 0xF2087000
++#define VDO_ROT0_BASE 0xF2088000
++#define RGB_ROT0_BASE 0xF2089000
++#define VDO_ROT1_BASE 0xF208A000
++#define RGB_ROT1_BASE 0xF208B000
++//#define DPI_BASE 0xF208C000
++#define BRZ_BASE 0xF208D000
++#define JPG_DMA_BASE 0xF208E000
++#define OVL_DMA_BASE 0xF208F000
++#define CSI2_BASE 0xF2092000
++#define CRZ_BASE 0xF2093000
++#define VRZ0_BASE 0xF2094000
++#define IMGPROC_BASE 0xF2095000
++#define EIS_BASE 0xF2096000
++#define SPI_BASE 0xF2097000
++#define SCAM_BASE 0xF2098000
++#define PRZ0_BASE 0xF2099000
++#define PRZ1_BASE 0xF209A000
++#define JPG_CODEC_BASE 0xF209B000
++//#define DSI_BASE 0xF209C000
++#define TVC_BASE 0xF209D000
++#define TVE_BASE 0xF209E000
++#define TV_ROT_BASE 0xF209F000
++#define RGB_ROT2_BASE 0xF20A0000
++//#define LCD_BASE 0xF20A1000
++#define FD_BASE 0xF20A2000
++#define MIPI_CONFG_BASE 0xF20A3000
++#define VRZ1_BASE 0xF20A4000
++#define MMSYS2_CONFG_BASE 0xF20C0000
++#define SMI_LARB3_BASE 0xF20C1000
++#define MFG_APB_BASE 0xF20C4000
++#define G2D_BASE 0xF20C6000
++
++#define DISPSYS_BASE 0xF4000000
++#define ROT_BASE 0xF4001000
++#define SCL_BASE 0xF4002000
++#define OVL_BASE 0xF4007000
++#define WDMA0_BASE 0xF4009000
++#define WDMA1_BASE 0xF4005000
++#define RDMA0_BASE 0xF4008000
++//#define RDMA1_BASE 0xF4007000
++#define BLS_BASE 0xF400A000
++//#define GAMMA_BASE 0xF400000
++#define COLOR_BASE 0xF400B000
++#define TDSHP_BASE 0xF4006000
++#define LCD_BASE 0xF4012000// only exist on FPGA
++#define DSI_BASE 0xF400C000
++#define DPI_BASE 0xF400D000
++
++#define DPI1_BASE 0xF4014000
++
++// LVDS TX
++#define LVDS_TX_BASE (0xF4016200)
++
++#define SMILARB1_BASE 0xF4010000
++#define DISP_MUTEX_BASE 0xF400E000
++#define DISP_CMDQ_BASE 0xF400F000
++
++/* imgsys */
++#define IMGSYS_CONFG_BASE 0xF5000000
++#define CAMINF_BASE IMGSYS_CONFG_BASE
++
++/* G3DSYS */
++#define G3D_CONFIG_BASE 0xF3000000
++#define MALI_BASE 0xF3040000
++
++#define DEVINFO_BASE 0xF8000000
++
++#endif
++
++#endif
+diff --git a/arch/arm/mach-mediatek/rt_mmap.h b/arch/arm/mach-mediatek/rt_mmap.h
+new file mode 100644
+index 0000000..e86b3bb
+--- /dev/null
++++ b/arch/arm/mach-mediatek/rt_mmap.h
+@@ -0,0 +1,58 @@
++#define HIFSYS_BASE 0xFA000000 //for PCIe/USB
++#define ETHDMASYS_BASE 0xFB000000 //for I2S/PCM/GDMA/HSDMA/FE/GMAC
++
++#define HIFSYS_PCI_BASE 0xFA140000
++#define HIFSYS_USB_HOST_BASE 0xFA1C0000
++#define HIFSYS_USB_HOST2_BASE 0xFA240000
++
++#define ETHDMASYS_SYSCTL_BASE 0xFB000000
++#define ETHDMASYS_RBUS_MATRIXCTL_BASE 0xFB000400
++#define ETHDMASYS_I2S_BASE 0xFB000A00
++#define ETHDMASYS_PCM_BASE 0xFB002000
++#define ETHDMASYS_GDMA_BASE 0xFB002800
++#define ETHDMASYS_HS_DMA_BASE 0xFB007000
++#define ETHDMASYS_FRAME_ENGINE_BASE 0xFB100000
++#define ETHDMASYS_PPE_BASE 0xFB100C00
++#define ETHDMASYS_ETH_SW_BASE 0xFB110000
++#define ETHDMASYS_CRYPTO_ENGINE_BASE 0xFB240000
++
++//for backward-compatible
++#define RALINK_FRAME_ENGINE_BASE ETHDMASYS_FRAME_ENGINE_BASE
++#define RALINK_PPE_BASE ETHDMASYS_PPE_BASE
++#define RALINK_SYSCTL_BASE ETHDMASYS_SYSCTL_BASE
++#define RALINK_ETH_SW_BASE ETHDMASYS_ETH_SW_BASE
++#define RALINK_GDMA_BASE ETHDMASYS_GDMA_BASE
++#define RALINK_HS_DMA_BASE ETHDMASYS_HS_DMA_BASE
++#define RALINK_11N_MAC_BASE 0 //unused for rt_rdm usage
++
++//Reset Control Register
++#define RSTCTL_SYS_RST (1<<0)
++#define RSTCTL_MCM_RST (1<<2)
++#define RSTCTL_HSDMA_RST (1<<5)
++#define RSTCTL_FE_RST (1<<6)
++#define RSTCTL_SPDIF_RST (1<<7)
++#define RSTCTL_TIMER_RST (1<<8)
++#define RSTCTL_CIRQ_RST (1<<9)
++#define RSTCTL_MC_RST (1<<10)
++#define RSTCTL_PCM_RST (1<<11)
++#define RSTCTL_GPIO_RST (1<<13)
++#define RSTCTL_GDMA_RST (1<<14)
++#define RSTCTL_NAND_RST (1<<15)
++#define RSTCTL_I2C_RST (1<<16)
++#define RSTCTL_I2S_RST (1<<17)
++#define RSTCTL_SPI_RST (1<<18)
++#define RSTCTL_UART0_RST (1<<19)
++#define RSTCTL_UART1_RST (1<<20)
++#define RSTCTL_UART2_RST (1<<21)
++#define RSTCTL_UPHY_RST (1<<22)
++#define RSTCTL_ETH_RST (1<<23)
++#define RSTCTL_PCIE0_RST (1<<24)
++#define RSTCTL_PCIE1_RST (1<<25)
++#define RSTCTL_PCIE2_RST (1<<26)
++#define RSTCTL_AUX_STCK_RST (1<<28)
++#define RSTCTL_CRYPT_RST (1<<29)
++#define RSTCTL_SDXC_RST (1<<30)
++#define RSTCTL_PWM_RST (1<<31)
++
++//for backward-compatible
++#define RALINK_FE_RST RSTCTL_FE_RST
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0069-arm-mediatek-add-mt7623-support-to-pmic-wrapper.patch b/target/linux/mediatek/patches/0069-arm-mediatek-add-mt7623-support-to-pmic-wrapper.patch
new file mode 100644
index 0000000000..b724682433
--- /dev/null
+++ b/target/linux/mediatek/patches/0069-arm-mediatek-add-mt7623-support-to-pmic-wrapper.patch
@@ -0,0 +1,554 @@
+From 0ec1ddd9233579b6d6dc0df325e870c5560344be Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 28 Jun 2015 19:50:51 +0200
+Subject: [PATCH 69/76] arm: mediatek: add mt7623 support to pmic-wrapper
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/soc/mediatek/mtk-pmic-wrap.c | 345 +++++++++++++++++++++++++++++-----
+ 1 file changed, 296 insertions(+), 49 deletions(-)
+
+diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
+index f432291..9ff02a1 100644
+--- a/drivers/soc/mediatek/mtk-pmic-wrap.c
++++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
+@@ -31,6 +31,13 @@
+ #define PWRAP_MT8135_BRIDGE_WDT_UNIT 0x50
+ #define PWRAP_MT8135_BRIDGE_WDT_SRC_EN 0x54
+
++#define PWRAP_MT7623_AUXADC_CON21 0x076C
++#define PWRAP_MT7623_AUXADC_ADC12 0x072C
++#define PWRAP_MT7623_AUXADC_ADC13 0x072E
++#define PWRAP_MT7623_AUXADC_ADC14 0x0730
++#define PWRAP_MT7623_AUXADC_CON2 0x0746
++#define PWRAP_MT7623_AUXADC_CON3 0x0748
++
+ /* macro for wrapper status */
+ #define PWRAP_GET_WACS_RDATA(x) (((x) >> 0) & 0x0000ffff)
+ #define PWRAP_GET_WACS_FSM(x) (((x) >> 16) & 0x00000007)
+@@ -61,32 +68,104 @@
+ #define PWRAP_MAN_CMD_OP_OUTQ (0xa << 8)
+
+ /* macro for slave device wrapper registers */
+-#define PWRAP_DEW_BASE 0xbc00
+-#define PWRAP_DEW_EVENT_OUT_EN (PWRAP_DEW_BASE + 0x0)
+-#define PWRAP_DEW_DIO_EN (PWRAP_DEW_BASE + 0x2)
+-#define PWRAP_DEW_EVENT_SRC_EN (PWRAP_DEW_BASE + 0x4)
+-#define PWRAP_DEW_EVENT_SRC (PWRAP_DEW_BASE + 0x6)
+-#define PWRAP_DEW_EVENT_FLAG (PWRAP_DEW_BASE + 0x8)
+-#define PWRAP_DEW_READ_TEST (PWRAP_DEW_BASE + 0xa)
+-#define PWRAP_DEW_WRITE_TEST (PWRAP_DEW_BASE + 0xc)
+-#define PWRAP_DEW_CRC_EN (PWRAP_DEW_BASE + 0xe)
+-#define PWRAP_DEW_CRC_VAL (PWRAP_DEW_BASE + 0x10)
+-#define PWRAP_DEW_MON_GRP_SEL (PWRAP_DEW_BASE + 0x12)
+-#define PWRAP_DEW_MON_FLAG_SEL (PWRAP_DEW_BASE + 0x14)
+-#define PWRAP_DEW_EVENT_TEST (PWRAP_DEW_BASE + 0x16)
+-#define PWRAP_DEW_CIPHER_KEY_SEL (PWRAP_DEW_BASE + 0x18)
+-#define PWRAP_DEW_CIPHER_IV_SEL (PWRAP_DEW_BASE + 0x1a)
+-#define PWRAP_DEW_CIPHER_LOAD (PWRAP_DEW_BASE + 0x1c)
+-#define PWRAP_DEW_CIPHER_START (PWRAP_DEW_BASE + 0x1e)
+-#define PWRAP_DEW_CIPHER_RDY (PWRAP_DEW_BASE + 0x20)
+-#define PWRAP_DEW_CIPHER_MODE (PWRAP_DEW_BASE + 0x22)
+-#define PWRAP_DEW_CIPHER_SWRST (PWRAP_DEW_BASE + 0x24)
+-#define PWRAP_MT8173_DEW_CIPHER_IV0 (PWRAP_DEW_BASE + 0x26)
+-#define PWRAP_MT8173_DEW_CIPHER_IV1 (PWRAP_DEW_BASE + 0x28)
+-#define PWRAP_MT8173_DEW_CIPHER_IV2 (PWRAP_DEW_BASE + 0x2a)
+-#define PWRAP_MT8173_DEW_CIPHER_IV3 (PWRAP_DEW_BASE + 0x2c)
+-#define PWRAP_MT8173_DEW_CIPHER_IV4 (PWRAP_DEW_BASE + 0x2e)
+-#define PWRAP_MT8173_DEW_CIPHER_IV5 (PWRAP_DEW_BASE + 0x30)
++enum pwrap_dew_regs {
++ PWRAP_DEW_EVENT_OUT_EN,
++ PWRAP_DEW_DIO_EN,
++ PWRAP_DEW_EVENT_SRC_EN,
++ PWRAP_DEW_EVENT_SRC,
++ PWRAP_DEW_EVENT_FLAG,
++ PWRAP_DEW_READ_TEST,
++ PWRAP_DEW_WRITE_TEST,
++ PWRAP_DEW_CRC_EN,
++ PWRAP_DEW_CRC_VAL,
++ PWRAP_DEW_MON_GRP_SEL,
++ PWRAP_DEW_MON_FLAG_SEL,
++ PWRAP_DEW_EVENT_TEST,
++ PWRAP_DEW_CIPHER_KEY_SEL,
++ PWRAP_DEW_CIPHER_IV_SEL,
++ PWRAP_DEW_CIPHER_LOAD,
++ PWRAP_DEW_CIPHER_START,
++ PWRAP_DEW_CIPHER_RDY,
++ PWRAP_DEW_CIPHER_MODE,
++ PWRAP_DEW_CIPHER_SWRST,
++
++ /* MT7623 only regs */
++ PWRAP_DEW_CIPHER_EN,
++ PWRAP_DEW_RDDMY_NO,
++
++ /* MT8173 only regs */
++ PWRAP_DEW_CIPHER_IV0,
++ PWRAP_DEW_CIPHER_IV1,
++ PWRAP_DEW_CIPHER_IV2,
++ PWRAP_DEW_CIPHER_IV3,
++ PWRAP_DEW_CIPHER_IV4,
++ PWRAP_DEW_CIPHER_IV5,
++};
++
++static int mt7623_dew_regs[] = {
++ [PWRAP_DEW_DIO_EN] = 0x18a,
++ [PWRAP_DEW_READ_TEST] = 0x18c,
++ [PWRAP_DEW_WRITE_TEST] = 0x18e,
++ [PWRAP_DEW_CRC_EN] = 0x192,
++ [PWRAP_DEW_CRC_VAL] = 0x194,
++ [PWRAP_DEW_CIPHER_KEY_SEL] = 0x198,
++ [PWRAP_DEW_CIPHER_IV_SEL] = 0x19a,
++ [PWRAP_DEW_CIPHER_EN] = 0x19c,
++ [PWRAP_DEW_CIPHER_RDY] = 0x19e,
++ [PWRAP_DEW_CIPHER_MODE] = 0x1a0,
++ [PWRAP_DEW_CIPHER_SWRST] = 0x1a2,
++ [PWRAP_DEW_RDDMY_NO] = 0x1a4,
++};
++
++static int mt8135_dew_regs[] = {
++ [PWRAP_DEW_EVENT_OUT_EN] = 0x0,
++ [PWRAP_DEW_DIO_EN] = 0x2,
++ [PWRAP_DEW_EVENT_SRC_EN] = 0x4,
++ [PWRAP_DEW_EVENT_SRC] = 0x6,
++ [PWRAP_DEW_EVENT_FLAG] = 0x8,
++ [PWRAP_DEW_READ_TEST] = 0xa,
++ [PWRAP_DEW_WRITE_TEST] = 0xc,
++ [PWRAP_DEW_CRC_EN] = 0xe,
++ [PWRAP_DEW_CRC_VAL] = 0x10,
++ [PWRAP_DEW_MON_GRP_SEL] = 0x12,
++ [PWRAP_DEW_MON_FLAG_SEL] = 0x14,
++ [PWRAP_DEW_EVENT_TEST] = 0x16,
++ [PWRAP_DEW_CIPHER_KEY_SEL] = 0x18,
++ [PWRAP_DEW_CIPHER_IV_SEL] = 0x1a,
++ [PWRAP_DEW_CIPHER_LOAD] = 0x1c,
++ [PWRAP_DEW_CIPHER_START] = 0x1e,
++ [PWRAP_DEW_CIPHER_RDY] = 0x20,
++ [PWRAP_DEW_CIPHER_MODE] = 0x22,
++ [PWRAP_DEW_CIPHER_SWRST] = 0x24,
++};
++
++static int mt8173_dew_regs[] = {
++ [PWRAP_DEW_EVENT_OUT_EN] = 0x0,
++ [PWRAP_DEW_DIO_EN] = 0x2,
++ [PWRAP_DEW_EVENT_SRC_EN] = 0x4,
++ [PWRAP_DEW_EVENT_SRC] = 0x6,
++ [PWRAP_DEW_EVENT_FLAG] = 0x8,
++ [PWRAP_DEW_READ_TEST] = 0xa,
++ [PWRAP_DEW_WRITE_TEST] = 0xc,
++ [PWRAP_DEW_CRC_EN] = 0xe,
++ [PWRAP_DEW_CRC_VAL] = 0x10,
++ [PWRAP_DEW_MON_GRP_SEL] = 0x12,
++ [PWRAP_DEW_MON_FLAG_SEL] = 0x14,
++ [PWRAP_DEW_EVENT_TEST] = 0x16,
++ [PWRAP_DEW_CIPHER_KEY_SEL] = 0x18,
++ [PWRAP_DEW_CIPHER_IV_SEL] = 0x1a,
++ [PWRAP_DEW_CIPHER_LOAD] = 0x1c,
++ [PWRAP_DEW_CIPHER_START] = 0x1e,
++ [PWRAP_DEW_CIPHER_RDY] = 0x20,
++ [PWRAP_DEW_CIPHER_MODE] = 0x22,
++ [PWRAP_DEW_CIPHER_SWRST] = 0x24,
++ [PWRAP_DEW_CIPHER_IV0] = 0x26,
++ [PWRAP_DEW_CIPHER_IV1] = 0x28,
++ [PWRAP_DEW_CIPHER_IV2] = 0x2a,
++ [PWRAP_DEW_CIPHER_IV3] = 0x2c,
++ [PWRAP_DEW_CIPHER_IV4] = 0x2e,
++ [PWRAP_DEW_CIPHER_IV5] = 0x30,
++};
+
+ enum pwrap_regs {
+ PWRAP_MUX_SEL,
+@@ -162,7 +241,7 @@ enum pwrap_regs {
+ PWRAP_CIPHER_LOAD,
+ PWRAP_CIPHER_START,
+
+- /* MT8173 only regs */
++ /* MT7623/MT8173 only regs */
+ PWRAP_RDDMY,
+ PWRAP_SI_CK_CON,
+ PWRAP_DVFS_ADR0,
+@@ -183,6 +262,107 @@ enum pwrap_regs {
+ PWRAP_DVFS_WDATA7,
+ PWRAP_SPMINF_STA,
+ PWRAP_CIPHER_EN,
++
++ /* MT7623 only regs */
++ PWRAP_OP_TYPE,
++ PWRAP_MSB_FIRST,
++ PWRAP_TOP_CKCON1,
++ PWRAP_TOP_CKCON1_CLR,
++ PWRAP_ADC_CMD_ADDR,
++ PWRAP_ADC_CMD,
++ PWRAP_ADC_RDY_ADDR,
++ PWRAP_ADC_RDATA_ADDR1,
++ PWRAP_ADC_RDATA_ADDR2,
++};
++
++static int mt7623_regs[] = {
++ [PWRAP_MUX_SEL] = 0x0,
++ [PWRAP_WRAP_EN] = 0x4,
++ [PWRAP_DIO_EN] = 0x8,
++ [PWRAP_SIDLY] = 0xc,
++ [PWRAP_OP_TYPE] = 0x10,
++ [PWRAP_MSB_FIRST] = 0x14,
++ [PWRAP_RDDMY] = 0x18,
++ [PWRAP_SI_CK_CON] = 0x1c,
++ [PWRAP_CSHEXT_WRITE] = 0x20,
++ [PWRAP_CSHEXT_READ] = 0x24,
++ [PWRAP_CSLEXT_START] = 0x28,
++ [PWRAP_CSLEXT_END] = 0x2c,
++ [PWRAP_STAUPD_PRD] = 0x30,
++ [PWRAP_STAUPD_GRPEN] = 0x34,
++ [PWRAP_STAUPD_MAN_TRIG] = 0x38,
++ [PWRAP_STAUPD_STA] = 0x3C,
++ [PWRAP_WRAP_STA] = 0x44,
++ [PWRAP_HARB_INIT] = 0x48,
++ [PWRAP_HARB_HPRIO] = 0x4c,
++ [PWRAP_HIPRIO_ARB_EN] = 0x50,
++ [PWRAP_HARB_STA0] = 0x54,
++ [PWRAP_HARB_STA1] = 0x58,
++ [PWRAP_MAN_EN] = 0x5c,
++ [PWRAP_MAN_CMD] = 0x60,
++ [PWRAP_MAN_RDATA] = 0x6c,
++ [PWRAP_MAN_VLDCLR] = 0x68,
++ [PWRAP_WACS0_EN] = 0x6c,
++ [PWRAP_INIT_DONE0] = 0x70,
++ [PWRAP_WACS0_CMD] = 0x74,
++ [PWRAP_WACS0_RDATA] = 0x78,
++ [PWRAP_WACS0_VLDCLR] = 0x7c,
++ [PWRAP_WACS1_EN] = 0x80,
++ [PWRAP_INIT_DONE1] = 0x84,
++ [PWRAP_WACS1_CMD] = 0x88,
++ [PWRAP_WACS1_RDATA] = 0x9c,
++ [PWRAP_WACS1_VLDCLR] = 0x90,
++ [PWRAP_WACS2_EN] = 0x94,
++ [PWRAP_INIT_DONE2] = 0x98,
++ [PWRAP_WACS2_CMD] = 0x9c,
++ [PWRAP_WACS2_RDATA] = 0xa0,
++ [PWRAP_WACS2_VLDCLR] = 0xa4,
++ [PWRAP_INT_EN] = 0xa8,
++ [PWRAP_INT_FLG_RAW] = 0xac,
++ [PWRAP_INT_FLG] = 0xb0,
++ [PWRAP_INT_CLR] = 0xb4,
++ [PWRAP_SIG_ADR] = 0xb8,
++ [PWRAP_SIG_MODE] = 0xbc,
++ [PWRAP_SIG_VALUE] = 0xc0,
++ [PWRAP_SIG_ERRVAL] = 0xc4,
++ [PWRAP_CRC_EN] = 0xc8,
++ [PWRAP_TIMER_EN] = 0xcc,
++ [PWRAP_TIMER_STA] = 0xd0,
++ [PWRAP_WDT_UNIT] = 0xd4,
++ [PWRAP_WDT_SRC_EN] = 0xd8,
++ [PWRAP_WDT_FLG] = 0xdc,
++ [PWRAP_DEBUG_INT_SEL] = 0xe0,
++ [PWRAP_DVFS_ADR0] = 0xe4,
++ [PWRAP_DVFS_WDATA0] = 0xe8,
++ [PWRAP_DVFS_ADR1] = 0xec,
++ [PWRAP_DVFS_WDATA1] = 0xf0,
++ [PWRAP_DVFS_ADR2] = 0xf4,
++ [PWRAP_DVFS_WDATA2] = 0xf8,
++ [PWRAP_DVFS_ADR3] = 0xfc,
++ [PWRAP_DVFS_WDATA3] = 0x100,
++ [PWRAP_DVFS_ADR4] = 0x104,
++ [PWRAP_DVFS_WDATA4] = 0x108,
++ [PWRAP_DVFS_ADR5] = 0x10c,
++ [PWRAP_DVFS_WDATA5] = 0x110,
++ [PWRAP_DVFS_ADR6] = 0x114,
++ [PWRAP_DVFS_WDATA6] = 0x118,
++ [PWRAP_DVFS_ADR7] = 0x11c,
++ [PWRAP_DVFS_WDATA7] = 0x120,
++ [PWRAP_CIPHER_KEY_SEL] = 0x124,
++ [PWRAP_TOP_CKCON1] = 0x126,
++ [PWRAP_CIPHER_IV_SEL] = 0x128,
++ [PWRAP_TOP_CKCON1_CLR] = 0x12a,
++ [PWRAP_CIPHER_EN] = 0x12c,
++ [PWRAP_CIPHER_RDY] = 0x130,
++ [PWRAP_CIPHER_MODE] = 0x134,
++ [PWRAP_CIPHER_SWRST] = 0x138,
++ [PWRAP_DCM_EN] = 0x13c,
++ [PWRAP_DCM_DBC_PRD] = 0x140,
++ [PWRAP_ADC_CMD_ADDR] = 0x144,
++ [PWRAP_ADC_CMD] = 0x148,
++ [PWRAP_ADC_RDY_ADDR] = 0x14C,
++ [PWRAP_ADC_RDATA_ADDR1] = 0x150,
++ [PWRAP_ADC_RDATA_ADDR2] = 0x154,
+ };
+
+ static int mt8173_regs[] = {
+@@ -341,24 +521,39 @@ static int mt8135_regs[] = {
+ };
+
+ enum pwrap_type {
++ PWRAP_MT7623,
+ PWRAP_MT8135,
+ PWRAP_MT8173,
+ };
+
+ struct pmic_wrapper_type {
+ int *regs;
++ int *dew_regs;
++ u32 dew_base;
+ enum pwrap_type type;
+ u32 arb_en_all;
+ };
+
++static struct pmic_wrapper_type pwrap_mt7623 = {
++ .regs = mt7623_regs,
++ .dew_regs = mt7623_dew_regs,
++ .dew_base = 0x0,
++ .type = PWRAP_MT7623,
++ .arb_en_all = 0x3f,
++};
++
+ static struct pmic_wrapper_type pwrap_mt8135 = {
+ .regs = mt8135_regs,
++ .dew_regs = mt8135_dew_regs,
++ .dew_base = 0xbc00,
+ .type = PWRAP_MT8135,
+ .arb_en_all = 0x1ff,
+ };
+
+ static struct pmic_wrapper_type pwrap_mt8173 = {
+ .regs = mt8173_regs,
++ .dew_regs = mt8173_dew_regs,
++ .dew_base = 0xbc00,
+ .type = PWRAP_MT8173,
+ .arb_en_all = 0x3f,
+ };
+@@ -368,6 +563,8 @@ struct pmic_wrapper {
+ void __iomem *base;
+ struct regmap *regmap;
+ int *regs;
++ int *dew_regs;
++ u32 dew_base;
+ enum pwrap_type type;
+ u32 arb_en_all;
+ struct clk *clk_spi;
+@@ -378,6 +575,11 @@ struct pmic_wrapper {
+ void __iomem *bridge_base;
+ };
+
++static inline int pwrap_is_mt7623(struct pmic_wrapper *wrp)
++{
++ return wrp->type == PWRAP_MT7623;
++}
++
+ static inline int pwrap_is_mt8135(struct pmic_wrapper *wrp)
+ {
+ return wrp->type == PWRAP_MT8135;
+@@ -475,6 +677,16 @@ static int pwrap_read(struct pmic_wrapper *wrp, u32 adr, u32 *rdata)
+ return 0;
+ }
+
++static int pwrap_dew_write(struct pmic_wrapper *wrp, enum pwrap_dew_regs reg, u32 wdata)
++{
++ return pwrap_write(wrp, wrp->dew_base + wrp->dew_regs[reg], wdata);
++}
++
++static int pwrap_dew_read(struct pmic_wrapper *wrp, enum pwrap_dew_regs reg, u32 *rdata)
++{
++ return pwrap_read(wrp, wrp->dew_base + wrp->dew_regs[reg], rdata);
++}
++
+ static int pwrap_regmap_read(void *context, u32 adr, u32 *rdata)
+ {
+ return pwrap_read(context, adr, rdata);
+@@ -535,7 +747,7 @@ static int pwrap_init_sidly(struct pmic_wrapper *wrp)
+
+ for (i = 0; i < 4; i++) {
+ pwrap_writel(wrp, i, PWRAP_SIDLY);
+- pwrap_read(wrp, PWRAP_DEW_READ_TEST, &rdata);
++ pwrap_dew_read(wrp, PWRAP_DEW_READ_TEST, &rdata);
+ if (rdata == PWRAP_DEW_READ_TEST_VAL) {
+ dev_dbg(wrp->dev, "[Read Test] pass, SIDLY=%x\n", i);
+ pass |= 1 << i;
+@@ -561,6 +773,14 @@ static int pwrap_init_reg_clock(struct pmic_wrapper *wrp)
+ pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_READ);
+ pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_START);
+ pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_END);
++ } else if (pwrap_is_mt7623(wrp)) {
++ pwrap_writel(wrp, 0x3, PWRAP_TOP_CKCON1_CLR);
++ pwrap_dew_write(wrp, 0x8, PWRAP_DEW_RDDMY_NO);
++ pwrap_writel(wrp, 0x8, PWRAP_RDDMY);
++ pwrap_writel(wrp, 0x5, PWRAP_CSHEXT_WRITE);
++ pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_READ);
++ pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_START);
++ pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_END);
+ } else {
+ pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_WRITE);
+ pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_READ);
+@@ -581,7 +801,7 @@ static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp)
+ u32 rdata;
+ int ret;
+
+- ret = pwrap_read(wrp, PWRAP_DEW_CIPHER_RDY, &rdata);
++ ret = pwrap_dew_read(wrp, PWRAP_DEW_CIPHER_RDY, &rdata);
+ if (ret)
+ return 0;
+
+@@ -606,12 +826,16 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
+ }
+
+ /* Config cipher mode @PMIC */
+- pwrap_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x1);
+- pwrap_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x0);
+- pwrap_write(wrp, PWRAP_DEW_CIPHER_KEY_SEL, 0x1);
+- pwrap_write(wrp, PWRAP_DEW_CIPHER_IV_SEL, 0x2);
+- pwrap_write(wrp, PWRAP_DEW_CIPHER_LOAD, 0x1);
+- pwrap_write(wrp, PWRAP_DEW_CIPHER_START, 0x1);
++ pwrap_dew_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x1);
++ pwrap_dew_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x0);
++ pwrap_dew_write(wrp, PWRAP_DEW_CIPHER_KEY_SEL, 0x1);
++ pwrap_dew_write(wrp, PWRAP_DEW_CIPHER_IV_SEL, 0x2);
++ if (pwrap_is_mt7623(wrp)) {
++ pwrap_dew_write(wrp, PWRAP_DEW_CIPHER_EN, 0x1);
++ } else {
++ pwrap_dew_write(wrp, PWRAP_DEW_CIPHER_LOAD, 0x1);
++ pwrap_dew_write(wrp, PWRAP_DEW_CIPHER_START, 0x1);
++ }
+
+ /* wait for cipher data ready@AP */
+ ret = pwrap_wait_for_state(wrp, pwrap_is_cipher_ready);
+@@ -628,7 +852,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
+ }
+
+ /* wait for cipher mode idle */
+- pwrap_write(wrp, PWRAP_DEW_CIPHER_MODE, 0x1);
++ pwrap_dew_write(wrp, PWRAP_DEW_CIPHER_MODE, 0x1);
+ ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle);
+ if (ret) {
+ dev_err(wrp->dev, "cipher mode idle fail, ret=%d\n", ret);
+@@ -638,8 +862,8 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
+ pwrap_writel(wrp, 1, PWRAP_CIPHER_MODE);
+
+ /* Write Test */
+- if (pwrap_write(wrp, PWRAP_DEW_WRITE_TEST, PWRAP_DEW_WRITE_TEST_VAL) ||
+- pwrap_read(wrp, PWRAP_DEW_WRITE_TEST, &rdata) ||
++ if (pwrap_dew_write(wrp, PWRAP_DEW_WRITE_TEST, PWRAP_DEW_WRITE_TEST_VAL) ||
++ pwrap_dew_read(wrp, PWRAP_DEW_WRITE_TEST, &rdata) ||
+ (rdata != PWRAP_DEW_WRITE_TEST_VAL)) {
+ dev_err(wrp->dev, "rdata=0x%04X\n", rdata);
+ return -EFAULT;
+@@ -657,12 +881,17 @@ static int pwrap_init(struct pmic_wrapper *wrp)
+ if (wrp->rstc_bridge)
+ reset_control_reset(wrp->rstc_bridge);
+
+- if (pwrap_is_mt8173(wrp)) {
++ if (pwrap_is_mt7623(wrp) || pwrap_is_mt8173(wrp)) {
+ /* Enable DCM */
+ pwrap_writel(wrp, 3, PWRAP_DCM_EN);
+ pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD);
+ }
+
++ if (pwrap_is_mt7623(wrp)) {
++ pwrap_writel(wrp, 0, PWRAP_OP_TYPE);
++ pwrap_writel(wrp, 1, PWRAP_MSB_FIRST);
++ }
++
+ /* Reset SPI slave */
+ ret = pwrap_reset_spislave(wrp);
+ if (ret)
+@@ -674,6 +903,9 @@ static int pwrap_init(struct pmic_wrapper *wrp)
+
+ pwrap_writel(wrp, 1, PWRAP_WACS2_EN);
+
++ if (pwrap_is_mt7623(wrp))
++ pwrap_writel(wrp, 0xf, PWRAP_RDDMY);
++
+ ret = pwrap_init_reg_clock(wrp);
+ if (ret)
+ return ret;
+@@ -684,7 +916,7 @@ static int pwrap_init(struct pmic_wrapper *wrp)
+ return ret;
+
+ /* Enable dual IO mode */
+- pwrap_write(wrp, PWRAP_DEW_DIO_EN, 1);
++ pwrap_dew_write(wrp, PWRAP_DEW_DIO_EN, 1);
+
+ /* Check IDLE & INIT_DONE in advance */
+ ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle);
+@@ -696,7 +928,7 @@ static int pwrap_init(struct pmic_wrapper *wrp)
+ pwrap_writel(wrp, 1, PWRAP_DIO_EN);
+
+ /* Read Test */
+- pwrap_read(wrp, PWRAP_DEW_READ_TEST, &rdata);
++ pwrap_dew_read(wrp, PWRAP_DEW_READ_TEST, &rdata);
+ if (rdata != PWRAP_DEW_READ_TEST_VAL) {
+ dev_err(wrp->dev, "Read test failed after switch to DIO mode: 0x%04x != 0x%04x\n",
+ PWRAP_DEW_READ_TEST_VAL, rdata);
+@@ -709,12 +941,13 @@ static int pwrap_init(struct pmic_wrapper *wrp)
+ return ret;
+
+ /* Signature checking - using CRC */
+- if (pwrap_write(wrp, PWRAP_DEW_CRC_EN, 0x1))
++ if (pwrap_dew_write(wrp, PWRAP_DEW_CRC_EN, 0x1))
+ return -EFAULT;
+
+ pwrap_writel(wrp, 0x1, PWRAP_CRC_EN);
+ pwrap_writel(wrp, 0x0, PWRAP_SIG_MODE);
+- pwrap_writel(wrp, PWRAP_DEW_CRC_VAL, PWRAP_SIG_ADR);
++ pwrap_writel(wrp, wrp->dew_base + wrp->dew_regs[PWRAP_DEW_CRC_VAL],
++ PWRAP_SIG_ADR);
+ pwrap_writel(wrp, wrp->arb_en_all, PWRAP_HIPRIO_ARB_EN);
+
+ if (pwrap_is_mt8135(wrp))
+@@ -728,7 +961,16 @@ static int pwrap_init(struct pmic_wrapper *wrp)
+ pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT);
+ pwrap_writel(wrp, 0xffffffff, PWRAP_WDT_SRC_EN);
+ pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN);
+- pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN);
++// pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN);
++ pwrap_writel(wrp, ~(BIT(31) | BIT(2)), PWRAP_INT_EN);
++
++ if (pwrap_is_mt7623(wrp)) {
++ pwrap_writel(wrp, PWRAP_MT7623_AUXADC_CON21, PWRAP_ADC_CMD_ADDR);
++ pwrap_writel(wrp, 0x8000, PWRAP_ADC_CMD);
++ pwrap_writel(wrp, PWRAP_MT7623_AUXADC_ADC12, PWRAP_ADC_RDY_ADDR);
++ pwrap_writel(wrp, PWRAP_MT7623_AUXADC_ADC13, PWRAP_ADC_RDATA_ADDR1);
++ pwrap_writel(wrp, PWRAP_MT7623_AUXADC_ADC14, PWRAP_ADC_RDATA_ADDR2);
++ }
+
+ if (pwrap_is_mt8135(wrp)) {
+ /* enable pwrap events and pwrap bridge in AP side */
+@@ -743,15 +985,15 @@ static int pwrap_init(struct pmic_wrapper *wrp)
+ writel(0x7ff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INT_EN);
+
+ /* enable PMIC event out and sources */
+- if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) ||
+- pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) {
++ if (pwrap_dew_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) ||
++ pwrap_dew_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) {
+ dev_err(wrp->dev, "enable dewrap fail\n");
+ return -EFAULT;
+ }
+- } else {
++ } else if (!pwrap_is_mt7623(wrp)) {
+ /* PMIC_DEWRAP enables */
+- if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) ||
+- pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) {
++ if (pwrap_dew_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) ||
++ pwrap_dew_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) {
+ dev_err(wrp->dev, "enable dewrap fail\n");
+ return -EFAULT;
+ }
+@@ -795,6 +1037,9 @@ static const struct regmap_config pwrap_regmap_config = {
+
+ static struct of_device_id of_pwrap_match_tbl[] = {
+ {
++ .compatible = "mediatek,mt7623-pwrap",
++ .data = &pwrap_mt7623,
++ }, {
+ .compatible = "mediatek,mt8135-pwrap",
+ .data = &pwrap_mt8135,
+ }, {
+@@ -824,6 +1069,8 @@ static int pwrap_probe(struct platform_device *pdev)
+
+ type = of_id->data;
+ wrp->regs = type->regs;
++ wrp->dew_regs = type->dew_regs;
++ wrp->dew_base = type->dew_base;
+ wrp->type = type->type;
+ wrp->arb_en_all = type->arb_en_all;
+ wrp->dev = &pdev->dev;
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0070-clk-mediatek-Export-CPU-mux-clocks-for-CPU-frequency.patch b/target/linux/mediatek/patches/0070-clk-mediatek-Export-CPU-mux-clocks-for-CPU-frequency.patch
new file mode 100644
index 0000000000..87de0f9436
--- /dev/null
+++ b/target/linux/mediatek/patches/0070-clk-mediatek-Export-CPU-mux-clocks-for-CPU-frequency.patch
@@ -0,0 +1,199 @@
+From ac825c0dd7370ae1b9a1a4346f895728e09d9cc7 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Wed, 1 Jul 2015 07:58:44 +0200
+Subject: [PATCH 70/76] clk: mediatek: Export CPU mux clocks for CPU frequency
+ control
+
+This patch adds CPU mux clocks which are used by Mediatek cpufreq driver
+for intermediate clock source switching.
+
+Changes in v3:
+- Rebase to 4.2-rc1
+- Fix some issues of v2
+
+Changes in v2:
+- Remove use of .determine_rate callback
+
+Signed-off-by: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
+---
+ drivers/clk/mediatek/Makefile | 2 +-
+ drivers/clk/mediatek/clk-cpumux.c | 119 +++++++++++++++++++++++++++++++++++++
+ drivers/clk/mediatek/clk-cpumux.h | 30 ++++++++++
+ 3 files changed, 150 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/clk/mediatek/clk-cpumux.c
+ create mode 100644 drivers/clk/mediatek/clk-cpumux.h
+
+diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
+index 19a3763..fe07e26 100644
+--- a/drivers/clk/mediatek/Makefile
++++ b/drivers/clk/mediatek/Makefile
+@@ -1,4 +1,4 @@
+-obj-y += clk-mtk.o clk-pll.o clk-gate.o
++obj-y += clk-mtk.o clk-pll.o clk-gate.o clk-cpumux.o
+ obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+ obj-y += clk-mt7623.o
+ obj-y += clk-mt8135.o
+diff --git a/drivers/clk/mediatek/clk-cpumux.c b/drivers/clk/mediatek/clk-cpumux.c
+new file mode 100644
+index 0000000..593df45
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-cpumux.c
+@@ -0,0 +1,119 @@
++/*
++ * Copyright (c) 2015 Linaro Ltd.
++ * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#include <linux/clk-provider.h>
++#include <linux/mfd/syscon.h>
++#include <linux/slab.h>
++
++#include "clk-mtk.h"
++#include "clk-cpumux.h"
++
++static inline struct mtk_clk_cpumux *to_clk_mux(struct clk_hw *_hw)
++{
++ return container_of(_hw, struct mtk_clk_cpumux, hw);
++}
++
++static u8 clk_cpumux_get_parent(struct clk_hw *hw)
++{
++ struct mtk_clk_cpumux *mux = to_clk_mux(hw);
++ int num_parents = __clk_get_num_parents(hw->clk);
++ unsigned int val;
++
++ regmap_read(mux->regmap, mux->reg, &val);
++
++ val >>= mux->shift;
++ val &= mux->mask;
++
++ if (val >= num_parents)
++ return -EINVAL;
++
++ return val;
++}
++
++static int clk_cpumux_set_parent(struct clk_hw *hw, u8 index)
++{
++ struct mtk_clk_cpumux *mux = to_clk_mux(hw);
++ u32 mask, val;
++
++ val = index << mux->shift;
++ mask = mux->mask << mux->shift;
++
++ return regmap_update_bits(mux->regmap, mux->reg, mask, val);
++}
++
++static const struct clk_ops clk_cpumux_ops = {
++ .get_parent = clk_cpumux_get_parent,
++ .set_parent = clk_cpumux_set_parent,
++};
++
++static struct clk *mtk_clk_register_cpumux(const struct mtk_composite *mux,
++ struct regmap *regmap)
++{
++ struct mtk_clk_cpumux *cpumux;
++ struct clk *clk;
++ struct clk_init_data init;
++
++ cpumux = kzalloc(sizeof(*cpumux), GFP_KERNEL);
++ if (!cpumux)
++ return ERR_PTR(-ENOMEM);
++
++ init.name = mux->name;
++ init.ops = &clk_cpumux_ops;
++ init.parent_names = mux->parent_names;
++ init.num_parents = mux->num_parents;
++ init.flags = mux->flags;
++
++ cpumux->reg = mux->mux_reg;
++ cpumux->shift = mux->mux_shift;
++ cpumux->mask = BIT(mux->mux_width) - 1;
++ cpumux->regmap = regmap;
++ cpumux->hw.init = &init;
++
++ clk = clk_register(NULL, &cpumux->hw);
++ if (IS_ERR(clk))
++ kfree(cpumux);
++
++ return clk;
++}
++
++int mtk_clk_register_cpumuxes(struct device_node *node,
++ const struct mtk_composite *clks, int num,
++ struct clk_onecell_data *clk_data)
++{
++ int i;
++ struct clk *clk;
++ struct regmap *regmap;
++
++ regmap = syscon_node_to_regmap(node);
++ if (IS_ERR(regmap)) {
++ pr_err("Cannot find regmap for %s: %d\n", node->full_name,
++ PTR_ERR(regmap));
++ return PTR_ERR(regmap);
++ }
++
++ for (i = 0; i < num; i++) {
++ const struct mtk_composite *mux = &clks[i];
++
++ clk = mtk_clk_register_cpumux(mux, regmap);
++ if (IS_ERR(clk)) {
++ pr_err("Failed to register clk %s: %ld\n",
++ mux->name, PTR_ERR(clk));
++ continue;
++ }
++
++ clk_data->clks[mux->id] = clk;
++ }
++
++ return 0;
++}
+diff --git a/drivers/clk/mediatek/clk-cpumux.h b/drivers/clk/mediatek/clk-cpumux.h
+new file mode 100644
+index 0000000..dddaad5
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-cpumux.h
+@@ -0,0 +1,30 @@
++/*
++ * Copyright (c) 2015 Linaro Ltd.
++ * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#ifndef __DRV_CLK_CPUMUX_H
++#define __DRV_CLK_CPUMUX_H
++
++struct mtk_clk_cpumux {
++ struct clk_hw hw;
++ struct regmap *regmap;
++ u32 reg;
++ u32 mask;
++ u8 shift;
++};
++
++int mtk_clk_register_cpumuxes(struct device_node *node,
++ const struct mtk_composite *clks, int num,
++ struct clk_onecell_data *clk_data);
++
++#endif /* __DRV_CLK_CPUMUX_H */
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0071-clk.patch b/target/linux/mediatek/patches/0071-clk.patch
new file mode 100644
index 0000000000..f920dcee43
--- /dev/null
+++ b/target/linux/mediatek/patches/0071-clk.patch
@@ -0,0 +1,342 @@
+From c3a3617a8c37b43db7ff622a31f171d3ce870173 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 3 Jul 2015 05:44:57 +0200
+Subject: [PATCH 71/76] clk
+
+---
+ drivers/clk/mediatek/clk-mt7623.c | 194 ++++++++++++++++---------------------
+ 1 file changed, 83 insertions(+), 111 deletions(-)
+
+diff --git a/drivers/clk/mediatek/clk-mt7623.c b/drivers/clk/mediatek/clk-mt7623.c
+index 07843bb..d46b2ad 100644
+--- a/drivers/clk/mediatek/clk-mt7623.c
++++ b/drivers/clk/mediatek/clk-mt7623.c
+@@ -20,6 +20,7 @@
+
+ #include "clk-mtk.h"
+ #include "clk-gate.h"
++#include "clk-cpumux.h"
+
+ static DEFINE_SPINLOCK(mt7623_clk_lock);
+
+@@ -37,18 +38,11 @@ static void mtk_clk_enable_critical(void)
+ clk_prepare_enable(mt7623_top_clk_data->clks[CLK_TOP_RTC_SEL]);
+ }
+
+-static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
+- FACTOR(CLK_TOP_DSI0_LNTC_DSICLK, "dsi0_lntc_dsiclk", "clk_null", 1, 1),
+- FACTOR(CLK_TOP_HDMITX_CLKDIG_CTS, "hdmitx_clkdig_cts", "clk_null", 1, 1),
+- FACTOR(CLK_TOP_CLKPH_MCK, "clkph_mck", "clk_null", 1, 1),
+- FACTOR(CLK_TOP_CPUM_TCK_IN, "cpum_tck_in", "clk_null", 1, 1),
+-};
+-
+ static const struct mtk_fixed_factor top_divs[] __initconst = {
+- FACTOR(CLK_TOP_MAINPLL_806M, "mainpll_650m", "mainpll", 1, 2),
+- FACTOR(CLK_TOP_MAINPLL_537P3M, "mainpll_433p3m", "mainpll", 1, 3),
+- FACTOR(CLK_TOP_MAINPLL_322P4M, "mainpll_260m", "mainpll", 1, 5),
+- FACTOR(CLK_TOP_MAINPLL_230P3M, "mainpll_185p6m", "mainpll", 1, 7),
++ FACTOR(CLK_TOP_MAINPLL_650M, "mainpll_650m", "mainpll", 1, 2),
++ FACTOR(CLK_TOP_MAINPLL_433P3M, "mainpll_433p3m", "mainpll", 1, 3),
++ FACTOR(CLK_TOP_MAINPLL_260M, "mainpll_260m", "mainpll", 1, 5),
++ FACTOR(CLK_TOP_MAINPLL_185P6M, "mainpll_185p6m", "mainpll", 1, 7),
+
+ FACTOR(CLK_TOP_UNIVPLL_624M, "univpll_624m", "univpll", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL_416M, "univpll_416m", "univpll", 1, 3),
+@@ -61,13 +55,6 @@ static const struct mtk_fixed_factor top_divs[] __initconst = {
+ FACTOR(CLK_TOP_AUDPLL_D16, "audpll_d16", "audpll", 1, 16),
+ FACTOR(CLK_TOP_AUDPLL_24, "audpll_d24", "audpll", 1, 24),
+
+- FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
+- FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
+- FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
+- FACTOR(CLK_TOP_LVDS_ETH, "lvdspll_eth", "lvdspll", 1, 16),
+-
+- FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
+-
+ FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
+
+ FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "mainpll_650m", 1, 2),
+@@ -85,9 +72,6 @@ static const struct mtk_fixed_factor top_divs[] __initconst = {
+ FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll_260m", 1, 1),
+ FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll_185p6m", 1, 1),
+
+- FACTOR(CLK_TOP_TVDPLL_d2, "tvdpll_d2", "tvdpll", 1, 2),
+- FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4),
+-
+ FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_624m", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_624m", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_624m", 1, 8),
+@@ -110,9 +94,6 @@ static const struct mtk_fixed_factor top_divs[] __initconst = {
+
+ FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll_249p6m", 1, 1),
+ FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll_48m", 1, 1),
+-
+-
+- FACTOR(CLK_TOP_MEMPLL_MCK_D4, "mempll_mck_d4", "clkph_mck", 1, 4),
+ };
+
+ static const char * const axi_parents[] __initconst = {
+@@ -155,18 +136,6 @@ static const char * const pwm_parents[] __initconst = {
+ "univpll1_d4",
+ };
+
+-static const char * const vdec_parents[] __initconst = {
+- "clk26m",
+- "syspll1_d2",
+- "syspll_d5",
+- "syspll1_d4",
+- "univpll_d5",
+- "univpll2_d2",
+- "univpll2_d4",
+- "msdcpll_d2",
+- "mmpll_d2",
+-};
+-
+ static const char * const mfg_parents[] __initconst = {
+ "clk26m",
+ "mmpll_ck",
+@@ -178,17 +147,6 @@ static const char * const mfg_parents[] __initconst = {
+ "univpll1_d2",
+ };
+
+-static const char * const cam_parents[] __initconst = {
+- "clk26m",
+- "univpll_d26",
+- "univpll2_d2",
+- "syspll3_d2",
+- "syspll3_d4",
+- "msdcpll_d2",
+- "mmpll_d2",
+- "clk26m",
+-};
+-
+ static const char * const uart_parents[] __initconst = {
+ "clk26m",
+ "univpll2_d8",
+@@ -277,35 +235,6 @@ static const char * const scp_parents[] __initconst = {
+ "dmpll_d4",
+ };
+
+-static const char * const dpi0_parents[] __initconst = {
+- "clk26m",
+- "mipipll",
+- "mipipll_d2",
+- "mipipll_d4",
+- "lvdspll",
+- "lvdspll_d2",
+- "lvdspll_d4",
+- "lvdspll_d8",
+-};
+-
+-static const char * const dpi1_parents[] __initconst = {
+- "clk26m",
+- "tvdpll",
+- "tvdpll_d2",
+- "tvdpll_d4",
+-};
+-
+-static const char * const tve_parents[] __initconst = {
+- "clk26m",
+- "mipipll",
+- "mipipll_d2",
+- "mipipll_d4",
+- "clk26m",
+- "tvdpll",
+- "tvdpll_d2",
+- "tvdpll_d4",
+-};
+-
+ static const char * const apll_parents[] __initconst = {
+ "clk26m",
+ "audpll",
+@@ -317,17 +246,6 @@ static const char * const apll_parents[] __initconst = {
+ "clk26m",
+ };
+
+-static const char * const dpilvds_parents[] __initconst = {
+- "clk26m",
+- "lvdspll",
+- "lvdspll_d2",
+- "lvdspll_d4",
+- "lvdspll_d8",
+- "fpc_ck",
+- "clk26m",
+- "clk26m",
+-};
+-
+ static const char * const rtc_parents[] __initconst = {
+ "clk32k",
+ "external_32k",
+@@ -367,9 +285,7 @@ static const struct mtk_composite top_muxes[] __initconst = {
+ 0x0140, 24, 3, INVALID_MUX_GATE_BIT),
+ /* CLK_CFG_1 */
+ MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x0050, 0, 2, 7),
+- MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x0050, 8, 4, 15),
+ MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0050, 16, 3, 23),
+- MUX_GATE(CLK_TOP_CAM_SEL, "cam_sel", cam_parents, 0x0050, 24, 3, 31),
+ /* CLK_CFG_2 */
+ MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0060, 0, 1, 7),
+ MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0060, 8, 3, 15),
+@@ -384,12 +300,8 @@ static const struct mtk_composite top_muxes[] __initconst = {
+ /* CLK_CFG_4 */
+ MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmic_spi_parents, 0x0080, 0, 4, 7),
+ MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, 0x0080, 8, 2, 15),
+- MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x0080, 16, 3, 23),
+- MUX_GATE(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents, 0x0080, 24, 2, 31),
+ /* CLK_CFG_5 */
+- MUX_GATE(CLK_TOP_TVE_SEL, "tve_sel", tve_parents, 0x0090, 0, 3, 7),
+ MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents, 0x0090, 16, 3, 23),
+- MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x0090, 24, 3, 31),
+ /* CLK_CFG_6 */
+ MUX_GATE(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x00a0, 0, 2, 7),
+ MUX_GATE(CLK_TOP_NFI2X_SEL, "nfi2x_sel", nfi2x_parents, 0x00a0, 8, 3, 15),
+@@ -428,6 +340,17 @@ static const struct mtk_gate infra_clks[] __initconst = {
+ GATE_ICG(CLK_INFRA_PMIC_WRAP, "pmic_wrap_ck", "axi_sel", 23),
+ };
+
++static const char * const ca7_parents[] __initconst = {
++ "clk26m",
++ "armpll",
++ "mainpll",
++ "univpll"
++};
++
++static struct mtk_composite cpu_muxes[] __initdata = {
++ MUX(CLK_INFRA_CA7SEL, "infra_ca7_sel", ca7_parents, 0x0000, 2, 2),
++};
++
+ static const struct mtk_gate_regs peri0_cg_regs = {
+ .set_ofs = 0x0008,
+ .clr_ofs = 0x0010,
+@@ -499,6 +422,29 @@ static const struct mtk_gate peri_gates[] __initconst = {
+ GATE_PERI1(CLK_PERI_NFI_PAD, "nfi_pad_ck", "axi_sel", 2),
+ };
+
++static const struct mtk_gate_regs hifsys_cg_regs = {
++ .set_ofs = 0x0034,
++ .clr_ofs = 0x0014,
++ .sta_ofs = 0x0038,
++};
++
++#define GATE_HIFSYS(_id, _name, _parent, _shift) { \
++ .id = _id, \
++ .name = _name, \
++ .parent_name = _parent, \
++ .regs = &hifsys_cg_regs, \
++ .shift = _shift, \
++ .ops = &mtk_clk_gate_ops_setclr, \
++ }
++
++static const struct mtk_gate hifsys_gates[] __initconst = {
++ GATE_HIFSYS(CLK_HIFSYS_USB0_PHY, "usb0_phy_ck", "axi_sel", 21),
++ GATE_HIFSYS(CLK_HIFSYS_USB1_PHY, "usb1_phy_ck", "axi_sel", 22),
++ GATE_HIFSYS(CLK_HIFSYS_PCIE0, "pcie0_ck", "axi_sel", 24),
++ GATE_HIFSYS(CLK_HIFSYS_PCIE1, "pcie1_ck", "axi_sel", 25),
++ GATE_HIFSYS(CLK_HIFSYS_PCIE2, "pcie2_ck", "axi_sel", 26),
++};
++
+ static const char * const uart_ck_sel_parents[] __initconst = {
+ "clk26m",
+ "uart_sel",
+@@ -525,10 +471,9 @@ static void __init mtk_topckgen_init(struct device_node *node)
+
+ mt7623_top_clk_data = clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+
+- mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
+ mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+ mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
+- &mt7623_clk_lock, clk_data);
++ &mt7623_clk_lock, clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+@@ -547,7 +492,10 @@ static void __init mtk_infrasys_init(struct device_node *node)
+ clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+
+ mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+- clk_data);
++ clk_data);
++
++ mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes),
++ clk_data);
+
+ clk_prepare_enable(clk_data->clks[CLK_INFRA_M4U]);
+
+@@ -588,35 +536,59 @@ static void __init mtk_pericfg_init(struct device_node *node)
+ }
+ CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt7623-pericfg", mtk_pericfg_init);
+
+-#define MT7623_PLL_FMAX (2000 * MHZ)
+-#define CON0_MT7623_RST_BAR BIT(27)
++static void __init mtk_hifsys_init(struct device_node *node)
++{
++ struct clk_onecell_data *clk_data;
++ int r;
++ void __iomem *base;
++
++ base = of_iomap(node, 0);
++ if (!base) {
++ pr_err("%s(): ioremap failed\n", __func__);
++ return;
++ }
++
++ clk_data = mtk_alloc_clk_data(CLK_HIFSYS_NR_CLK);
++
++ mtk_clk_register_gates(node, hifsys_gates, ARRAY_SIZE(hifsys_gates),
++ clk_data);
++
++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++ if (r)
++ pr_err("%s(): could not register clock provider: %d\n",
++ __func__, r);
++
++ mtk_register_reset_controller(node, 1, 0x34);
++}
++CLK_OF_DECLARE(mtk_hifsys, "mediatek,mt7623-hifsys", mtk_hifsys_init);
++
++#define MT7623_PLL_FMAX (1300 * MHZ)
++#define CON0_MT7623_RST_BAR BIT(24)
+
+-#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \
++#define PLL(_id, _name, _con0_reg, _con1_reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pcw_shift, _pd_shift) { \
+ .id = _id, \
+ .name = _name, \
+- .reg = _reg, \
++ .reg = _con0_reg, \
+ .pwr_reg = _pwr_reg, \
+ .en_mask = _en_mask, \
+ .flags = _flags, \
+ .rst_bar_mask = CON0_MT7623_RST_BAR, \
+ .fmax = MT7623_PLL_FMAX, \
+ .pcwbits = _pcwbits, \
+- .pd_reg = _pd_reg, \
++ .pd_reg = _con0_reg, \
+ .pd_shift = _pd_shift, \
+- .tuner_reg = _tuner_reg, \
+- .pcw_reg = _pcw_reg, \
++ .pcw_reg = _con1_reg, \
+ .pcw_shift = _pcw_shift, \
+ }
+
+ static const struct mtk_pll_data plls[] = {
+- PLL(CLK_APMIXED_ARMPLL, "armpll", 0x200, 0x20c, 0x00000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
+- PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x210, 0x21c, 0x78000001, HAVE_RST_BAR, 21, 0x214, 6, 0x0, 0x214, 0),
+- PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x220, 0x22c, 0xFC000001, HAVE_RST_BAR, 7, 0x224, 6, 0x0, 0x224, 0),
+- PLL(CLK_APMIXED_MMPLL, "mmpll", 0x230, 0x23c, 0x00000001, 0, 21, 0x254, 6, 0x0, 0x258, 0),
+- PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 6, 0x0, 0x244, 0),
+- PLL(CLK_APMIXED_AUDPLL, "audpll", 0x250, 0x25c, 0x00000001, 0, 31, 0x2e8, 6, 0x2f8, 0x254, 0),
+- PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x260, 0x26c, 0x00000001, 0, 31, 0x294, 6, 0x0, 0x298, 0),
+- PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x270, 0x27c, 0x00000001, 0, 21, 0x2b0, 6, 0x0, 0x2b4, 0),
++ PLL(CLK_APMIXED_ARMPLL, "armpll", 0x200, 0x204, 0x20c, 0x00000001, 0, 21, 0, 4 ),
++ PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x210, 0x214, 0x21c, 0x78000001, HAVE_RST_BAR, 21, 0, 4 ),
++ PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x220, 0x224, 0x22c, 0xFC000001, HAVE_RST_BAR, 7, 14, 4 ),
++ PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x240, 0x244, 0x24c, 0x00000001, 0, 21, 0, 4 ),
++ PLL(CLK_APMIXED_AUDPLL, "audpll", 0x270, 0x274, 0x27c, 0x00000001, 0, 31, 0, 4 ),
++ PLL(CLK_APMIXED_TRGPLL, "trgpll", 0x280, 0x284, 0x28c, 0x00000001, 0, 31, 0, 4 ),
++ PLL(CLK_APMIXED_ETHPLL, "ethpll", 0x290, 0x294, 0x29c, 0x00000001, 0, 31, 0, 4 ),
+ };
+
+ static void __init mtk_apmixedsys_init(struct device_node *node)
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0072-mfd.patch b/target/linux/mediatek/patches/0072-mfd.patch
new file mode 100644
index 0000000000..cbcadb7de7
--- /dev/null
+++ b/target/linux/mediatek/patches/0072-mfd.patch
@@ -0,0 +1,1591 @@
+From 1a4dcc30578512d687528adcf963203faee50d83 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 3 Jul 2015 05:45:17 +0200
+Subject: [PATCH 72/76] mfd
+
+---
+ drivers/mfd/mt6323-core.c | 168 +++----
+ drivers/regulator/mt6323-regulator.c | 218 ++++----
+ include/linux/mfd/mt6323/core.h | 76 +--
+ include/linux/mfd/mt6323/registers.h | 745 +++++++++++++++-------------
+ include/linux/regulator/mt6323-regulator.h | 37 ++
+ 5 files changed, 636 insertions(+), 608 deletions(-)
+ create mode 100644 include/linux/regulator/mt6323-regulator.h
+
+diff --git a/drivers/mfd/mt6323-core.c b/drivers/mfd/mt6323-core.c
+index 012c620..9b7f5b9 100644
+--- a/drivers/mfd/mt6323-core.c
++++ b/drivers/mfd/mt6323-core.c
+@@ -18,111 +18,99 @@
+ #include <linux/of_irq.h>
+ #include <linux/regmap.h>
+ #include <linux/mfd/core.h>
+-#include <linux/mfd/mt6397/core.h>
+-#include <linux/mfd/mt6397/registers.h>
++#include <linux/mfd/mt6323/core.h>
++#include <linux/mfd/mt6323/registers.h>
+
+-static const struct mfd_cell mt6397_devs[] = {
++static const struct mfd_cell mt6323_devs[] = {
+ {
+- .name = "mt6397-rtc",
+- .of_compatible = "mediatek,mt6397-rtc",
+- }, {
+- .name = "mt6397-regulator",
+- .of_compatible = "mediatek,mt6397-regulator",
+- }, {
+- .name = "mt6397-codec",
+- .of_compatible = "mediatek,mt6397-codec",
+- }, {
+- .name = "mt6397-clk",
+- .of_compatible = "mediatek,mt6397-clk",
+- }, {
+- .name = "mediatek-mt6397-pinctrl",
+- .of_compatible = "mediatek,mt6397-pinctrl",
++ .name = "mt6323-regulator",
++ .of_compatible = "mediatek,mt6323-regulator",
+ },
+ };
+
+-static void mt6397_irq_lock(struct irq_data *data)
++static void mt6323_irq_lock(struct irq_data *data)
+ {
+- struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
++ struct mt6323_chip *mt6323 = irq_get_chip_data(data->irq);
+
+- mutex_lock(&mt6397->irqlock);
++ mutex_lock(&mt6323->irqlock);
+ }
+
+-static void mt6397_irq_sync_unlock(struct irq_data *data)
++static void mt6323_irq_sync_unlock(struct irq_data *data)
+ {
+- struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
++ struct mt6323_chip *mt6323 = irq_get_chip_data(data->irq);
+
+- regmap_write(mt6397->regmap, MT6397_INT_CON0, mt6397->irq_masks_cur[0]);
+- regmap_write(mt6397->regmap, MT6397_INT_CON1, mt6397->irq_masks_cur[1]);
++ regmap_write(mt6323->regmap, MT6323_INT_CON0, mt6323->irq_masks_cur[0]);
++ regmap_write(mt6323->regmap, MT6323_INT_CON1, mt6323->irq_masks_cur[1]);
+
+- mutex_unlock(&mt6397->irqlock);
++ mutex_unlock(&mt6323->irqlock);
+ }
+
+-static void mt6397_irq_disable(struct irq_data *data)
++static void mt6323_irq_disable(struct irq_data *data)
+ {
+- struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
++ struct mt6323_chip *mt6323 = irq_get_chip_data(data->irq);
+ int shift = data->hwirq & 0xf;
+ int reg = data->hwirq >> 4;
+
+- mt6397->irq_masks_cur[reg] &= ~BIT(shift);
++ mt6323->irq_masks_cur[reg] &= ~BIT(shift);
+ }
+
+-static void mt6397_irq_enable(struct irq_data *data)
++static void mt6323_irq_enable(struct irq_data *data)
+ {
+- struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
++ struct mt6323_chip *mt6323 = irq_get_chip_data(data->irq);
+ int shift = data->hwirq & 0xf;
+ int reg = data->hwirq >> 4;
+
+- mt6397->irq_masks_cur[reg] |= BIT(shift);
++ mt6323->irq_masks_cur[reg] |= BIT(shift);
+ }
+
+-static struct irq_chip mt6397_irq_chip = {
+- .name = "mt6397-irq",
+- .irq_bus_lock = mt6397_irq_lock,
+- .irq_bus_sync_unlock = mt6397_irq_sync_unlock,
+- .irq_enable = mt6397_irq_enable,
+- .irq_disable = mt6397_irq_disable,
++static struct irq_chip mt6323_irq_chip = {
++ .name = "mt6323-irq",
++ .irq_bus_lock = mt6323_irq_lock,
++ .irq_bus_sync_unlock = mt6323_irq_sync_unlock,
++ .irq_enable = mt6323_irq_enable,
++ .irq_disable = mt6323_irq_disable,
+ };
+
+-static void mt6397_irq_handle_reg(struct mt6397_chip *mt6397, int reg,
++static void mt6323_irq_handle_reg(struct mt6323_chip *mt6323, int reg,
+ int irqbase)
+ {
+ unsigned int status;
+ int i, irq, ret;
+
+- ret = regmap_read(mt6397->regmap, reg, &status);
++ ret = regmap_read(mt6323->regmap, reg, &status);
+ if (ret) {
+- dev_err(mt6397->dev, "Failed to read irq status: %d\n", ret);
++ dev_err(mt6323->dev, "Failed to read irq status: %d\n", ret);
+ return;
+ }
+
+ for (i = 0; i < 16; i++) {
+ if (status & BIT(i)) {
+- irq = irq_find_mapping(mt6397->irq_domain, irqbase + i);
++ irq = irq_find_mapping(mt6323->irq_domain, irqbase + i);
+ if (irq)
+ handle_nested_irq(irq);
+ }
+ }
+
+- regmap_write(mt6397->regmap, reg, status);
++ regmap_write(mt6323->regmap, reg, status);
+ }
+
+-static irqreturn_t mt6397_irq_thread(int irq, void *data)
++static irqreturn_t mt6323_irq_thread(int irq, void *data)
+ {
+- struct mt6397_chip *mt6397 = data;
++ struct mt6323_chip *mt6323 = data;
+
+- mt6397_irq_handle_reg(mt6397, MT6397_INT_STATUS0, 0);
+- mt6397_irq_handle_reg(mt6397, MT6397_INT_STATUS1, 16);
++ mt6323_irq_handle_reg(mt6323, MT6323_INT_STATUS0, 0);
++ mt6323_irq_handle_reg(mt6323, MT6323_INT_STATUS1, 16);
+
+ return IRQ_HANDLED;
+ }
+
+-static int mt6397_irq_domain_map(struct irq_domain *d, unsigned int irq,
++static int mt6323_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+ {
+- struct mt6397_chip *mt6397 = d->host_data;
++ struct mt6323_chip *mt6323 = d->host_data;
+
+- irq_set_chip_data(irq, mt6397);
+- irq_set_chip_and_handler(irq, &mt6397_irq_chip, handle_level_irq);
++ irq_set_chip_data(irq, mt6323);
++ irq_set_chip_and_handler(irq, &mt6323_irq_chip, handle_level_irq);
+ irq_set_nested_thread(irq, 1);
+ #ifdef CONFIG_ARM
+ set_irq_flags(irq, IRQF_VALID);
+@@ -133,98 +121,98 @@ static int mt6397_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ return 0;
+ }
+
+-static struct irq_domain_ops mt6397_irq_domain_ops = {
+- .map = mt6397_irq_domain_map,
++static struct irq_domain_ops mt6323_irq_domain_ops = {
++ .map = mt6323_irq_domain_map,
+ };
+
+-static int mt6397_irq_init(struct mt6397_chip *mt6397)
++static int mt6323_irq_init(struct mt6323_chip *mt6323)
+ {
+ int ret;
+
+- mutex_init(&mt6397->irqlock);
++ mutex_init(&mt6323->irqlock);
+
+ /* Mask all interrupt sources */
+- regmap_write(mt6397->regmap, MT6397_INT_CON0, 0x0);
+- regmap_write(mt6397->regmap, MT6397_INT_CON1, 0x0);
++ regmap_write(mt6323->regmap, MT6323_INT_CON0, 0x0);
++ regmap_write(mt6323->regmap, MT6323_INT_CON1, 0x0);
+
+- mt6397->irq_domain = irq_domain_add_linear(mt6397->dev->of_node,
+- MT6397_IRQ_NR, &mt6397_irq_domain_ops, mt6397);
+- if (!mt6397->irq_domain) {
+- dev_err(mt6397->dev, "could not create irq domain\n");
++ mt6323->irq_domain = irq_domain_add_linear(mt6323->dev->of_node,
++ MT6323_IRQ_NR, &mt6323_irq_domain_ops, mt6323);
++ if (!mt6323->irq_domain) {
++ dev_err(mt6323->dev, "could not create irq domain\n");
+ return -ENOMEM;
+ }
+
+- ret = devm_request_threaded_irq(mt6397->dev, mt6397->irq, NULL,
+- mt6397_irq_thread, IRQF_ONESHOT, "mt6397-pmic", mt6397);
++ ret = devm_request_threaded_irq(mt6323->dev, mt6323->irq, NULL,
++ mt6323_irq_thread, IRQF_ONESHOT, "mt6323-pmic", mt6323);
+ if (ret) {
+- dev_err(mt6397->dev, "failed to register irq=%d; err: %d\n",
+- mt6397->irq, ret);
++ dev_err(mt6323->dev, "failed to register irq=%d; err: %d\n",
++ mt6323->irq, ret);
+ return ret;
+ }
+
+ return 0;
+ }
+
+-static int mt6397_probe(struct platform_device *pdev)
++static int mt6323_probe(struct platform_device *pdev)
+ {
+ int ret;
+- struct mt6397_chip *mt6397;
++ struct mt6323_chip *mt6323;
+
+- mt6397 = devm_kzalloc(&pdev->dev, sizeof(*mt6397), GFP_KERNEL);
+- if (!mt6397)
++ mt6323 = devm_kzalloc(&pdev->dev, sizeof(*mt6323), GFP_KERNEL);
++ if (!mt6323)
+ return -ENOMEM;
+
+- mt6397->dev = &pdev->dev;
++ mt6323->dev = &pdev->dev;
+ /*
+- * mt6397 MFD is child device of soc pmic wrapper.
++ * mt6323 MFD is child device of soc pmic wrapper.
+ * Regmap is set from its parent.
+ */
+- mt6397->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+- if (!mt6397->regmap)
++ mt6323->regmap = dev_get_regmap(pdev->dev.parent, NULL);
++ if (!mt6323->regmap)
+ return -ENODEV;
+
+- platform_set_drvdata(pdev, mt6397);
++ platform_set_drvdata(pdev, mt6323);
+
+- mt6397->irq = platform_get_irq(pdev, 0);
+- if (mt6397->irq > 0) {
+- ret = mt6397_irq_init(mt6397);
++ mt6323->irq = platform_get_irq(pdev, 0);
++ if (mt6323->irq > 0) {
++ ret = mt6323_irq_init(mt6323);
+ if (ret)
+ return ret;
+ }
+
+- ret = mfd_add_devices(&pdev->dev, -1, mt6397_devs,
+- ARRAY_SIZE(mt6397_devs), NULL, 0, NULL);
++ ret = mfd_add_devices(&pdev->dev, -1, mt6323_devs,
++ ARRAY_SIZE(mt6323_devs), NULL, 0, NULL);
+ if (ret)
+ dev_err(&pdev->dev, "failed to add child devices: %d\n", ret);
+
+ return ret;
+ }
+
+-static int mt6397_remove(struct platform_device *pdev)
++static int mt6323_remove(struct platform_device *pdev)
+ {
+ mfd_remove_devices(&pdev->dev);
+
+ return 0;
+ }
+
+-static const struct of_device_id mt6397_of_match[] = {
+- { .compatible = "mediatek,mt6397" },
++static const struct of_device_id mt6323_of_match[] = {
++ { .compatible = "mediatek,mt6323" },
+ { }
+ };
+-MODULE_DEVICE_TABLE(of, mt6397_of_match);
++MODULE_DEVICE_TABLE(of, mt6323_of_match);
+
+-static struct platform_driver mt6397_driver = {
+- .probe = mt6397_probe,
+- .remove = mt6397_remove,
++static struct platform_driver mt6323_driver = {
++ .probe = mt6323_probe,
++ .remove = mt6323_remove,
+ .driver = {
+- .name = "mt6397",
+- .of_match_table = of_match_ptr(mt6397_of_match),
++ .name = "mt6323",
++ .of_match_table = of_match_ptr(mt6323_of_match),
+ },
+ };
+
+-module_platform_driver(mt6397_driver);
++module_platform_driver(mt6323_driver);
+
+ MODULE_AUTHOR("Flora Fu, MediaTek");
+-MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC");
++MODULE_DESCRIPTION("Driver for MediaTek MT6323 PMIC");
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS("platform:mt6397");
++MODULE_ALIAS("platform:mt6323");
+diff --git a/drivers/regulator/mt6323-regulator.c b/drivers/regulator/mt6323-regulator.c
+index a5b2f47..f5e3f67 100644
+--- a/drivers/regulator/mt6323-regulator.c
++++ b/drivers/regulator/mt6323-regulator.c
+@@ -16,15 +16,15 @@
+ #include <linux/of.h>
+ #include <linux/platform_device.h>
+ #include <linux/regmap.h>
+-#include <linux/mfd/mt6397/core.h>
+-#include <linux/mfd/mt6397/registers.h>
++#include <linux/mfd/mt6323/core.h>
++#include <linux/mfd/mt6323/registers.h>
+ #include <linux/regulator/driver.h>
+ #include <linux/regulator/machine.h>
+-#include <linux/regulator/mt6397-regulator.h>
++#include <linux/regulator/mt6323-regulator.h>
+ #include <linux/regulator/of_regulator.h>
+
+ /*
+- * MT6397 regulators' information
++ * MT6323 regulators' information
+ *
+ * @desc: standard fields of regulator description.
+ * @qi: Mask for query enable signal status of regulators
+@@ -32,7 +32,7 @@
+ * @vselctrl_reg: Register for controlling the buck control mode.
+ * @vselctrl_mask: Mask for query buck's voltage control mode.
+ */
+-struct mt6397_regulator_info {
++struct mt6323_regulator_info {
+ struct regulator_desc desc;
+ u32 qi;
+ u32 vselon_reg;
+@@ -40,15 +40,15 @@ struct mt6397_regulator_info {
+ u32 vselctrl_mask;
+ };
+
+-#define MT6397_BUCK(match, vreg, min, max, step, volt_ranges, enreg, \
++#define MT6323_BUCK(match, vreg, min, max, step, volt_ranges, enreg, \
+ vosel, vosel_mask, voselon, vosel_ctrl) \
+-[MT6397_ID_##vreg] = { \
++[MT6323_ID_##vreg] = { \
+ .desc = { \
+ .name = #vreg, \
+ .of_match = of_match_ptr(match), \
+- .ops = &mt6397_volt_range_ops, \
++ .ops = &mt6323_volt_range_ops, \
+ .type = REGULATOR_VOLTAGE, \
+- .id = MT6397_ID_##vreg, \
++ .id = MT6323_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = (max - min)/step + 1, \
+ .linear_ranges = volt_ranges, \
+@@ -64,15 +64,15 @@ struct mt6397_regulator_info {
+ .vselctrl_mask = BIT(1), \
+ }
+
+-#define MT6397_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel, \
++#define MT6323_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel, \
+ vosel_mask) \
+-[MT6397_ID_##vreg] = { \
++[MT6323_ID_##vreg] = { \
+ .desc = { \
+ .name = #vreg, \
+ .of_match = of_match_ptr(match), \
+- .ops = &mt6397_volt_table_ops, \
++ .ops = &mt6323_volt_table_ops, \
+ .type = REGULATOR_VOLTAGE, \
+- .id = MT6397_ID_##vreg, \
++ .id = MT6323_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = ARRAY_SIZE(ldo_volt_table), \
+ .volt_table = ldo_volt_table, \
+@@ -84,14 +84,14 @@ struct mt6397_regulator_info {
+ .qi = BIT(15), \
+ }
+
+-#define MT6397_REG_FIXED(match, vreg, enreg, enbit, volt) \
+-[MT6397_ID_##vreg] = { \
++#define MT6323_REG_FIXED(match, vreg, enreg, enbit, volt) \
++[MT6323_ID_##vreg] = { \
+ .desc = { \
+ .name = #vreg, \
+ .of_match = of_match_ptr(match), \
+- .ops = &mt6397_volt_fixed_ops, \
++ .ops = &mt6323_volt_fixed_ops, \
+ .type = REGULATOR_VOLTAGE, \
+- .id = MT6397_ID_##vreg, \
++ .id = MT6323_ID_##vreg, \
+ .owner = THIS_MODULE, \
+ .n_voltages = 1, \
+ .enable_reg = enreg, \
+@@ -106,50 +106,34 @@ static const struct regulator_linear_range buck_volt_range1[] = {
+ };
+
+ static const struct regulator_linear_range buck_volt_range2[] = {
+- REGULATOR_LINEAR_RANGE(800000, 0, 0x7f, 6250),
++ REGULATOR_LINEAR_RANGE(1400000, 0, 0x7f, 12500),
+ };
+
+ static const struct regulator_linear_range buck_volt_range3[] = {
+- REGULATOR_LINEAR_RANGE(1500000, 0, 0x1f, 20000),
++ REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000),
+ };
+
+ static const u32 ldo_volt_table1[] = {
+- 1500000, 1800000, 2500000, 2800000,
++ 1800000, 3300000,
+ };
+
+ static const u32 ldo_volt_table2[] = {
+- 1800000, 3300000,
++ 3000000, 3300000,
+ };
+
+ static const u32 ldo_volt_table3[] = {
+- 3000000, 3300000,
++ 1200000, 1300000, 1500000, 1800000, 2000000, 2800000, 3000000,
+ };
+
+ static const u32 ldo_volt_table4[] = {
+- 1220000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,
+-};
+-
+-static const u32 ldo_volt_table5[] = {
+ 1200000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,
+ };
+
+-static const u32 ldo_volt_table5_v2[] = {
+- 1200000, 1000000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,
+-};
+-
+-static const u32 ldo_volt_table6[] = {
+- 1200000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 2000000,
+-};
+-
+-static const u32 ldo_volt_table7[] = {
+- 1300000, 1500000, 1800000, 2000000, 2500000, 2800000, 3000000, 3300000,
+-};
+-
+-static int mt6397_get_status(struct regulator_dev *rdev)
++static int mt6323_get_status(struct regulator_dev *rdev)
+ {
+ int ret;
+ u32 regval;
+- struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
++ struct mt6323_regulator_info *info = rdev_get_drvdata(rdev);
+
+ ret = regmap_read(rdev->regmap, info->desc.enable_reg, &regval);
+ if (ret != 0) {
+@@ -160,7 +144,7 @@ static int mt6397_get_status(struct regulator_dev *rdev)
+ return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;
+ }
+
+-static struct regulator_ops mt6397_volt_range_ops = {
++static struct regulator_ops mt6323_volt_range_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+@@ -169,10 +153,10 @@ static struct regulator_ops mt6397_volt_range_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+- .get_status = mt6397_get_status,
++ .get_status = mt6323_get_status,
+ };
+
+-static struct regulator_ops mt6397_volt_table_ops = {
++static struct regulator_ops mt6323_volt_table_ops = {
+ .list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_iterate,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+@@ -181,90 +165,68 @@ static struct regulator_ops mt6397_volt_table_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+- .get_status = mt6397_get_status,
++ .get_status = mt6323_get_status,
+ };
+
+-static struct regulator_ops mt6397_volt_fixed_ops = {
++static struct regulator_ops mt6323_volt_fixed_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+- .get_status = mt6397_get_status,
++ .get_status = mt6323_get_status,
+ };
+
+-/* The array is indexed by id(MT6397_ID_XXX) */
+-static struct mt6397_regulator_info mt6397_regulators[] = {
+- MT6397_BUCK("buck_vpca15", VPCA15, 700000, 1493750, 6250,
+- buck_volt_range1, MT6397_VCA15_CON7, MT6397_VCA15_CON9, 0x7f,
+- MT6397_VCA15_CON10, MT6397_VCA15_CON5),
+- MT6397_BUCK("buck_vpca7", VPCA7, 700000, 1493750, 6250,
+- buck_volt_range1, MT6397_VPCA7_CON7, MT6397_VPCA7_CON9, 0x7f,
+- MT6397_VPCA7_CON10, MT6397_VPCA7_CON5),
+- MT6397_BUCK("buck_vsramca15", VSRAMCA15, 700000, 1493750, 6250,
+- buck_volt_range1, MT6397_VSRMCA15_CON7, MT6397_VSRMCA15_CON9,
+- 0x7f, MT6397_VSRMCA15_CON10, MT6397_VSRMCA15_CON5),
+- MT6397_BUCK("buck_vsramca7", VSRAMCA7, 700000, 1493750, 6250,
+- buck_volt_range1, MT6397_VSRMCA7_CON7, MT6397_VSRMCA7_CON9,
+- 0x7f, MT6397_VSRMCA7_CON10, MT6397_VSRMCA7_CON5),
+- MT6397_BUCK("buck_vcore", VCORE, 700000, 1493750, 6250,
+- buck_volt_range1, MT6397_VCORE_CON7, MT6397_VCORE_CON9, 0x7f,
+- MT6397_VCORE_CON10, MT6397_VCORE_CON5),
+- MT6397_BUCK("buck_vgpu", VGPU, 700000, 1493750, 6250, buck_volt_range1,
+- MT6397_VGPU_CON7, MT6397_VGPU_CON9, 0x7f,
+- MT6397_VGPU_CON10, MT6397_VGPU_CON5),
+- MT6397_BUCK("buck_vdrm", VDRM, 800000, 1593750, 6250, buck_volt_range2,
+- MT6397_VDRM_CON7, MT6397_VDRM_CON9, 0x7f,
+- MT6397_VDRM_CON10, MT6397_VDRM_CON5),
+- MT6397_BUCK("buck_vio18", VIO18, 1500000, 2120000, 20000,
+- buck_volt_range3, MT6397_VIO18_CON7, MT6397_VIO18_CON9, 0x1f,
+- MT6397_VIO18_CON10, MT6397_VIO18_CON5),
+- MT6397_REG_FIXED("ldo_vtcxo", VTCXO, MT6397_ANALDO_CON0, 10, 2800000),
+- MT6397_REG_FIXED("ldo_va28", VA28, MT6397_ANALDO_CON1, 14, 2800000),
+- MT6397_LDO("ldo_vcama", VCAMA, ldo_volt_table1,
+- MT6397_ANALDO_CON2, 15, MT6397_ANALDO_CON6, 0xC0),
+- MT6397_REG_FIXED("ldo_vio28", VIO28, MT6397_DIGLDO_CON0, 14, 2800000),
+- MT6397_REG_FIXED("ldo_vusb", VUSB, MT6397_DIGLDO_CON1, 14, 3300000),
+- MT6397_LDO("ldo_vmc", VMC, ldo_volt_table2,
+- MT6397_DIGLDO_CON2, 12, MT6397_DIGLDO_CON29, 0x10),
+- MT6397_LDO("ldo_vmch", VMCH, ldo_volt_table3,
+- MT6397_DIGLDO_CON3, 14, MT6397_DIGLDO_CON17, 0x80),
+- MT6397_LDO("ldo_vemc3v3", VEMC3V3, ldo_volt_table3,
+- MT6397_DIGLDO_CON4, 14, MT6397_DIGLDO_CON18, 0x10),
+- MT6397_LDO("ldo_vgp1", VGP1, ldo_volt_table4,
+- MT6397_DIGLDO_CON5, 15, MT6397_DIGLDO_CON19, 0xE0),
+- MT6397_LDO("ldo_vgp2", VGP2, ldo_volt_table5,
+- MT6397_DIGLDO_CON6, 15, MT6397_DIGLDO_CON20, 0xE0),
+- MT6397_LDO("ldo_vgp3", VGP3, ldo_volt_table5,
+- MT6397_DIGLDO_CON7, 15, MT6397_DIGLDO_CON21, 0xE0),
+- MT6397_LDO("ldo_vgp4", VGP4, ldo_volt_table5,
+- MT6397_DIGLDO_CON8, 15, MT6397_DIGLDO_CON22, 0xE0),
+- MT6397_LDO("ldo_vgp5", VGP5, ldo_volt_table6,
+- MT6397_DIGLDO_CON9, 15, MT6397_DIGLDO_CON23, 0xE0),
+- MT6397_LDO("ldo_vgp6", VGP6, ldo_volt_table5,
+- MT6397_DIGLDO_CON10, 15, MT6397_DIGLDO_CON33, 0xE0),
+- MT6397_LDO("ldo_vibr", VIBR, ldo_volt_table7,
+- MT6397_DIGLDO_CON24, 15, MT6397_DIGLDO_CON25, 0xE00),
++/* The array is indexed by id(MT6323_ID_XXX) */
++static struct mt6323_regulator_info mt6323_regulators[] = {
++ /* buck */
++ MT6323_BUCK("buck_vproc", VPROC, 700000, 1493750, 6250,
++ buck_volt_range1, MT6323_VPROC_CON7, MT6323_VPROC_CON9, 0x7f,
++ MT6323_VPROC_CON10, MT6323_VPROC_CON5),
++ MT6323_BUCK("buck_vsys", VSYS, 1400000, 3000000, 12500,
++ buck_volt_range2, MT6323_VSYS_CON7, MT6323_VSYS_CON9,
++ 0x7f, MT6323_VSYS_CON10, MT6323_VSYS_CON5),
++ MT6323_BUCK("buck_vpa", VPA, 500000, 3650000, 50000,
++ buck_volt_range3, MT6323_VPA_CON7, MT6323_VPA_CON9, 0x7f,
++ MT6323_VPA_CON10, MT6323_VPA_CON5),
++
++ /* analog */
++ MT6323_REG_FIXED("ldo_vtcxo", VTCXO, MT6323_ANALDO_CON1, 10, 2800000),
++ MT6323_REG_FIXED("ldo_va", VA, MT6323_ANALDO_CON2, 14, 2800000),
++ MT6323_REG_FIXED("ldo_vcn28", VCN28, MT6323_ANALDO_CON19, 12, 2800000),
++ MT6323_REG_FIXED("ldo_vcn33", VCN33, MT6323_ANALDO_CON21, 12, 3300000),
++
++ /* digital */
++ MT6323_REG_FIXED("ldo_vio28", VIO28, MT6323_DIGLDO_CON0, 15, 2800000),
++ MT6323_REG_FIXED("ldo_vusb", VUSB, MT6323_DIGLDO_CON2, 15, 3300000),
++ MT6323_LDO("ldo_vmc", VMC, ldo_volt_table1,
++ MT6323_DIGLDO_CON3, 12, MT6323_DIGLDO_CON24, 0x10),
++ MT6323_LDO("ldo_vmch", VMCH, ldo_volt_table2,
++ MT6323_DIGLDO_CON5, 14, MT6323_DIGLDO_CON26, 0x80),
++ MT6323_LDO("ldo_vgp1", VGP1, ldo_volt_table3,
++ MT6323_DIGLDO_CON7, 15, MT6323_DIGLDO_CON28, 0xE0),
++ MT6323_LDO("ldo_vgp2", VGP2, ldo_volt_table4,
++ MT6323_DIGLDO_CON8, 15, MT6323_DIGLDO_CON29, 0xE0),
+ };
+
+-static int mt6397_set_buck_vosel_reg(struct platform_device *pdev)
++static int mt6323_set_buck_vosel_reg(struct platform_device *pdev)
+ {
+- struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
++ struct mt6323_chip *mt6323 = dev_get_drvdata(pdev->dev.parent);
+ int i;
+ u32 regval;
+
+- for (i = 0; i < MT6397_MAX_REGULATOR; i++) {
+- if (mt6397_regulators[i].vselctrl_reg) {
+- if (regmap_read(mt6397->regmap,
+- mt6397_regulators[i].vselctrl_reg,
++ for (i = 0; i < MT6323_MAX_REGULATOR; i++) {
++ if (mt6323_regulators[i].vselctrl_reg) {
++ if (regmap_read(mt6323->regmap,
++ mt6323_regulators[i].vselctrl_reg,
+ &regval) < 0) {
+ dev_err(&pdev->dev,
+ "Failed to read buck ctrl\n");
+ return -EIO;
+ }
+
+- if (regval & mt6397_regulators[i].vselctrl_mask) {
+- mt6397_regulators[i].desc.vsel_reg =
+- mt6397_regulators[i].vselon_reg;
++ if (regval & mt6323_regulators[i].vselctrl_mask) {
++ mt6323_regulators[i].desc.vsel_reg =
++ mt6323_regulators[i].vselon_reg;
+ }
+ }
+ }
+@@ -272,44 +234,34 @@ static int mt6397_set_buck_vosel_reg(struct platform_device *pdev)
+ return 0;
+ }
+
+-static int mt6397_regulator_probe(struct platform_device *pdev)
++static int mt6323_regulator_probe(struct platform_device *pdev)
+ {
+- struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
++ struct mt6323_chip *mt6323 = dev_get_drvdata(pdev->dev.parent);
+ struct regulator_config config = {};
+ struct regulator_dev *rdev;
+ int i;
+- u32 reg_value, version;
++ u32 reg_value;
+
+ /* Query buck controller to select activated voltage register part */
+- if (mt6397_set_buck_vosel_reg(pdev))
++ if (mt6323_set_buck_vosel_reg(pdev))
+ return -EIO;
+
+ /* Read PMIC chip revision to update constraints and voltage table */
+- if (regmap_read(mt6397->regmap, MT6397_CID, &reg_value) < 0) {
++ if (regmap_read(mt6323->regmap, MT6323_CID, &reg_value) < 0) {
+ dev_err(&pdev->dev, "Failed to read Chip ID\n");
+ return -EIO;
+ }
+ dev_info(&pdev->dev, "Chip ID = 0x%x\n", reg_value);
+
+- version = (reg_value & 0xFF);
+- switch (version) {
+- case MT6397_REGULATOR_ID91:
+- mt6397_regulators[MT6397_ID_VGP2].desc.volt_table =
+- ldo_volt_table5_v2;
+- break;
+- default:
+- break;
+- }
+-
+- for (i = 0; i < MT6397_MAX_REGULATOR; i++) {
++ for (i = 0; i < MT6323_MAX_REGULATOR; i++) {
+ config.dev = &pdev->dev;
+- config.driver_data = &mt6397_regulators[i];
+- config.regmap = mt6397->regmap;
++ config.driver_data = &mt6323_regulators[i];
++ config.regmap = mt6323->regmap;
+ rdev = devm_regulator_register(&pdev->dev,
+- &mt6397_regulators[i].desc, &config);
++ &mt6323_regulators[i].desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register %s\n",
+- mt6397_regulators[i].desc.name);
++ mt6323_regulators[i].desc.name);
+ return PTR_ERR(rdev);
+ }
+ }
+@@ -317,16 +269,16 @@ static int mt6397_regulator_probe(struct platform_device *pdev)
+ return 0;
+ }
+
+-static struct platform_driver mt6397_regulator_driver = {
++static struct platform_driver mt6323_regulator_driver = {
+ .driver = {
+- .name = "mt6397-regulator",
++ .name = "mt6323-regulator",
+ },
+- .probe = mt6397_regulator_probe,
++ .probe = mt6323_regulator_probe,
+ };
+
+-module_platform_driver(mt6397_regulator_driver);
++module_platform_driver(mt6323_regulator_driver);
+
+ MODULE_AUTHOR("Flora Fu <flora.fu@mediatek.com>");
+-MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6397 PMIC");
++MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6323 PMIC");
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS("platform:mt6397-regulator");
++MODULE_ALIAS("platform:mt6323-regulator");
+diff --git a/include/linux/mfd/mt6323/core.h b/include/linux/mfd/mt6323/core.h
+index cf5265b..5bb2d32 100644
+--- a/include/linux/mfd/mt6323/core.h
++++ b/include/linux/mfd/mt6323/core.h
+@@ -12,46 +12,46 @@
+ * GNU General Public License for more details.
+ */
+
+-#ifndef __MFD_MT6397_CORE_H__
+-#define __MFD_MT6397_CORE_H__
++#ifndef __MFD_MT6323_CORE_H__
++#define __MFD_MT6323_CORE_H__
+
+-enum mt6397_irq_numbers {
+- MT6397_IRQ_SPKL_AB = 0,
+- MT6397_IRQ_SPKR_AB,
+- MT6397_IRQ_SPKL,
+- MT6397_IRQ_SPKR,
+- MT6397_IRQ_BAT_L,
+- MT6397_IRQ_BAT_H,
+- MT6397_IRQ_FG_BAT_L,
+- MT6397_IRQ_FG_BAT_H,
+- MT6397_IRQ_WATCHDOG,
+- MT6397_IRQ_PWRKEY,
+- MT6397_IRQ_THR_L,
+- MT6397_IRQ_THR_H,
+- MT6397_IRQ_VBATON_UNDET,
+- MT6397_IRQ_BVALID_DET,
+- MT6397_IRQ_CHRDET,
+- MT6397_IRQ_OV,
+- MT6397_IRQ_LDO,
+- MT6397_IRQ_HOMEKEY,
+- MT6397_IRQ_ACCDET,
+- MT6397_IRQ_AUDIO,
+- MT6397_IRQ_RTC,
+- MT6397_IRQ_PWRKEY_RSTB,
+- MT6397_IRQ_HDMI_SIFM,
+- MT6397_IRQ_HDMI_CEC,
+- MT6397_IRQ_VCA15,
+- MT6397_IRQ_VSRMCA15,
+- MT6397_IRQ_VCORE,
+- MT6397_IRQ_VGPU,
+- MT6397_IRQ_VIO18,
+- MT6397_IRQ_VPCA7,
+- MT6397_IRQ_VSRMCA7,
+- MT6397_IRQ_VDRM,
+- MT6397_IRQ_NR,
++enum mt6323_irq_numbers {
++ MT6323_IRQ_SPKL_AB = 0,
++ MT6323_IRQ_SPKR_AB,
++ MT6323_IRQ_SPKL,
++ MT6323_IRQ_SPKR,
++ MT6323_IRQ_BAT_L,
++ MT6323_IRQ_BAT_H,
++ MT6323_IRQ_FG_BAT_L,
++ MT6323_IRQ_FG_BAT_H,
++ MT6323_IRQ_WATCHDOG,
++ MT6323_IRQ_PWRKEY,
++ MT6323_IRQ_THR_L,
++ MT6323_IRQ_THR_H,
++ MT6323_IRQ_VBATON_UNDET,
++ MT6323_IRQ_BVALID_DET,
++ MT6323_IRQ_CHRDET,
++ MT6323_IRQ_OV,
++ MT6323_IRQ_LDO,
++ MT6323_IRQ_HOMEKEY,
++ MT6323_IRQ_ACCDET,
++ MT6323_IRQ_AUDIO,
++ MT6323_IRQ_RTC,
++ MT6323_IRQ_PWRKEY_RSTB,
++ MT6323_IRQ_HDMI_SIFM,
++ MT6323_IRQ_HDMI_CEC,
++ MT6323_IRQ_VCA15,
++ MT6323_IRQ_VSRMCA15,
++ MT6323_IRQ_VCORE,
++ MT6323_IRQ_VGPU,
++ MT6323_IRQ_VIO18,
++ MT6323_IRQ_VPCA7,
++ MT6323_IRQ_VSRMCA7,
++ MT6323_IRQ_VDRM,
++ MT6323_IRQ_NR,
+ };
+
+-struct mt6397_chip {
++struct mt6323_chip {
+ struct device *dev;
+ struct regmap *regmap;
+ int irq;
+@@ -61,4 +61,4 @@ struct mt6397_chip {
+ u16 irq_masks_cache[2];
+ };
+
+-#endif /* __MFD_MT6397_CORE_H__ */
++#endif /* __MFD_MT6323_CORE_H__ */
+diff --git a/include/linux/mfd/mt6323/registers.h b/include/linux/mfd/mt6323/registers.h
+index f23a0a6..4ee5e1f0 100644
+--- a/include/linux/mfd/mt6323/registers.h
++++ b/include/linux/mfd/mt6323/registers.h
+@@ -1,6 +1,5 @@
+ /*
+- * Copyright (c) 2014 MediaTek Inc.
+- * Author: Flora Fu, MediaTek
++ * Copyright (c) 2015 - John Crispin <blogic@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+@@ -12,351 +11,403 @@
+ * GNU General Public License for more details.
+ */
+
+-#ifndef __MFD_MT6397_REGISTERS_H__
+-#define __MFD_MT6397_REGISTERS_H__
++#ifndef __MFD_MT6323_REGISTERS_H__
++#define __MFD_MT6323_REGISTERS_H__
+
+ /* PMIC Registers */
+-#define MT6397_CID 0x0100
+-#define MT6397_TOP_CKPDN 0x0102
+-#define MT6397_TOP_CKPDN_SET 0x0104
+-#define MT6397_TOP_CKPDN_CLR 0x0106
+-#define MT6397_TOP_CKPDN2 0x0108
+-#define MT6397_TOP_CKPDN2_SET 0x010A
+-#define MT6397_TOP_CKPDN2_CLR 0x010C
+-#define MT6397_TOP_GPIO_CKPDN 0x010E
+-#define MT6397_TOP_RST_CON 0x0114
+-#define MT6397_WRP_CKPDN 0x011A
+-#define MT6397_WRP_RST_CON 0x0120
+-#define MT6397_TOP_RST_MISC 0x0126
+-#define MT6397_TOP_CKCON1 0x0128
+-#define MT6397_TOP_CKCON2 0x012A
+-#define MT6397_TOP_CKTST1 0x012C
+-#define MT6397_TOP_CKTST2 0x012E
+-#define MT6397_OC_DEG_EN 0x0130
+-#define MT6397_OC_CTL0 0x0132
+-#define MT6397_OC_CTL1 0x0134
+-#define MT6397_OC_CTL2 0x0136
+-#define MT6397_INT_RSV 0x0138
+-#define MT6397_TEST_CON0 0x013A
+-#define MT6397_TEST_CON1 0x013C
+-#define MT6397_STATUS0 0x013E
+-#define MT6397_STATUS1 0x0140
+-#define MT6397_PGSTATUS 0x0142
+-#define MT6397_CHRSTATUS 0x0144
+-#define MT6397_OCSTATUS0 0x0146
+-#define MT6397_OCSTATUS1 0x0148
+-#define MT6397_OCSTATUS2 0x014A
+-#define MT6397_HDMI_PAD_IE 0x014C
+-#define MT6397_TEST_OUT_L 0x014E
+-#define MT6397_TEST_OUT_H 0x0150
+-#define MT6397_TDSEL_CON 0x0152
+-#define MT6397_RDSEL_CON 0x0154
+-#define MT6397_GPIO_SMT_CON0 0x0156
+-#define MT6397_GPIO_SMT_CON1 0x0158
+-#define MT6397_GPIO_SMT_CON2 0x015A
+-#define MT6397_GPIO_SMT_CON3 0x015C
+-#define MT6397_DRV_CON0 0x015E
+-#define MT6397_DRV_CON1 0x0160
+-#define MT6397_DRV_CON2 0x0162
+-#define MT6397_DRV_CON3 0x0164
+-#define MT6397_DRV_CON4 0x0166
+-#define MT6397_DRV_CON5 0x0168
+-#define MT6397_DRV_CON6 0x016A
+-#define MT6397_DRV_CON7 0x016C
+-#define MT6397_DRV_CON8 0x016E
+-#define MT6397_DRV_CON9 0x0170
+-#define MT6397_DRV_CON10 0x0172
+-#define MT6397_DRV_CON11 0x0174
+-#define MT6397_DRV_CON12 0x0176
+-#define MT6397_INT_CON0 0x0178
+-#define MT6397_INT_CON1 0x017E
+-#define MT6397_INT_STATUS0 0x0184
+-#define MT6397_INT_STATUS1 0x0186
+-#define MT6397_FQMTR_CON0 0x0188
+-#define MT6397_FQMTR_CON1 0x018A
+-#define MT6397_FQMTR_CON2 0x018C
+-#define MT6397_EFUSE_DOUT_0_15 0x01C4
+-#define MT6397_EFUSE_DOUT_16_31 0x01C6
+-#define MT6397_EFUSE_DOUT_32_47 0x01C8
+-#define MT6397_EFUSE_DOUT_48_63 0x01CA
+-#define MT6397_SPI_CON 0x01CC
+-#define MT6397_TOP_CKPDN3 0x01CE
+-#define MT6397_TOP_CKCON3 0x01D4
+-#define MT6397_EFUSE_DOUT_64_79 0x01D6
+-#define MT6397_EFUSE_DOUT_80_95 0x01D8
+-#define MT6397_EFUSE_DOUT_96_111 0x01DA
+-#define MT6397_EFUSE_DOUT_112_127 0x01DC
+-#define MT6397_EFUSE_DOUT_128_143 0x01DE
+-#define MT6397_EFUSE_DOUT_144_159 0x01E0
+-#define MT6397_EFUSE_DOUT_160_175 0x01E2
+-#define MT6397_EFUSE_DOUT_176_191 0x01E4
+-#define MT6397_EFUSE_DOUT_192_207 0x01E6
+-#define MT6397_EFUSE_DOUT_208_223 0x01E8
+-#define MT6397_EFUSE_DOUT_224_239 0x01EA
+-#define MT6397_EFUSE_DOUT_240_255 0x01EC
+-#define MT6397_EFUSE_DOUT_256_271 0x01EE
+-#define MT6397_EFUSE_DOUT_272_287 0x01F0
+-#define MT6397_EFUSE_DOUT_288_300 0x01F2
+-#define MT6397_EFUSE_DOUT_304_319 0x01F4
+-#define MT6397_BUCK_CON0 0x0200
+-#define MT6397_BUCK_CON1 0x0202
+-#define MT6397_BUCK_CON2 0x0204
+-#define MT6397_BUCK_CON3 0x0206
+-#define MT6397_BUCK_CON4 0x0208
+-#define MT6397_BUCK_CON5 0x020A
+-#define MT6397_BUCK_CON6 0x020C
+-#define MT6397_BUCK_CON7 0x020E
+-#define MT6397_BUCK_CON8 0x0210
+-#define MT6397_BUCK_CON9 0x0212
+-#define MT6397_VCA15_CON0 0x0214
+-#define MT6397_VCA15_CON1 0x0216
+-#define MT6397_VCA15_CON2 0x0218
+-#define MT6397_VCA15_CON3 0x021A
+-#define MT6397_VCA15_CON4 0x021C
+-#define MT6397_VCA15_CON5 0x021E
+-#define MT6397_VCA15_CON6 0x0220
+-#define MT6397_VCA15_CON7 0x0222
+-#define MT6397_VCA15_CON8 0x0224
+-#define MT6397_VCA15_CON9 0x0226
+-#define MT6397_VCA15_CON10 0x0228
+-#define MT6397_VCA15_CON11 0x022A
+-#define MT6397_VCA15_CON12 0x022C
+-#define MT6397_VCA15_CON13 0x022E
+-#define MT6397_VCA15_CON14 0x0230
+-#define MT6397_VCA15_CON15 0x0232
+-#define MT6397_VCA15_CON16 0x0234
+-#define MT6397_VCA15_CON17 0x0236
+-#define MT6397_VCA15_CON18 0x0238
+-#define MT6397_VSRMCA15_CON0 0x023A
+-#define MT6397_VSRMCA15_CON1 0x023C
+-#define MT6397_VSRMCA15_CON2 0x023E
+-#define MT6397_VSRMCA15_CON3 0x0240
+-#define MT6397_VSRMCA15_CON4 0x0242
+-#define MT6397_VSRMCA15_CON5 0x0244
+-#define MT6397_VSRMCA15_CON6 0x0246
+-#define MT6397_VSRMCA15_CON7 0x0248
+-#define MT6397_VSRMCA15_CON8 0x024A
+-#define MT6397_VSRMCA15_CON9 0x024C
+-#define MT6397_VSRMCA15_CON10 0x024E
+-#define MT6397_VSRMCA15_CON11 0x0250
+-#define MT6397_VSRMCA15_CON12 0x0252
+-#define MT6397_VSRMCA15_CON13 0x0254
+-#define MT6397_VSRMCA15_CON14 0x0256
+-#define MT6397_VSRMCA15_CON15 0x0258
+-#define MT6397_VSRMCA15_CON16 0x025A
+-#define MT6397_VSRMCA15_CON17 0x025C
+-#define MT6397_VSRMCA15_CON18 0x025E
+-#define MT6397_VSRMCA15_CON19 0x0260
+-#define MT6397_VSRMCA15_CON20 0x0262
+-#define MT6397_VSRMCA15_CON21 0x0264
+-#define MT6397_VCORE_CON0 0x0266
+-#define MT6397_VCORE_CON1 0x0268
+-#define MT6397_VCORE_CON2 0x026A
+-#define MT6397_VCORE_CON3 0x026C
+-#define MT6397_VCORE_CON4 0x026E
+-#define MT6397_VCORE_CON5 0x0270
+-#define MT6397_VCORE_CON6 0x0272
+-#define MT6397_VCORE_CON7 0x0274
+-#define MT6397_VCORE_CON8 0x0276
+-#define MT6397_VCORE_CON9 0x0278
+-#define MT6397_VCORE_CON10 0x027A
+-#define MT6397_VCORE_CON11 0x027C
+-#define MT6397_VCORE_CON12 0x027E
+-#define MT6397_VCORE_CON13 0x0280
+-#define MT6397_VCORE_CON14 0x0282
+-#define MT6397_VCORE_CON15 0x0284
+-#define MT6397_VCORE_CON16 0x0286
+-#define MT6397_VCORE_CON17 0x0288
+-#define MT6397_VCORE_CON18 0x028A
+-#define MT6397_VGPU_CON0 0x028C
+-#define MT6397_VGPU_CON1 0x028E
+-#define MT6397_VGPU_CON2 0x0290
+-#define MT6397_VGPU_CON3 0x0292
+-#define MT6397_VGPU_CON4 0x0294
+-#define MT6397_VGPU_CON5 0x0296
+-#define MT6397_VGPU_CON6 0x0298
+-#define MT6397_VGPU_CON7 0x029A
+-#define MT6397_VGPU_CON8 0x029C
+-#define MT6397_VGPU_CON9 0x029E
+-#define MT6397_VGPU_CON10 0x02A0
+-#define MT6397_VGPU_CON11 0x02A2
+-#define MT6397_VGPU_CON12 0x02A4
+-#define MT6397_VGPU_CON13 0x02A6
+-#define MT6397_VGPU_CON14 0x02A8
+-#define MT6397_VGPU_CON15 0x02AA
+-#define MT6397_VGPU_CON16 0x02AC
+-#define MT6397_VGPU_CON17 0x02AE
+-#define MT6397_VGPU_CON18 0x02B0
+-#define MT6397_VIO18_CON0 0x0300
+-#define MT6397_VIO18_CON1 0x0302
+-#define MT6397_VIO18_CON2 0x0304
+-#define MT6397_VIO18_CON3 0x0306
+-#define MT6397_VIO18_CON4 0x0308
+-#define MT6397_VIO18_CON5 0x030A
+-#define MT6397_VIO18_CON6 0x030C
+-#define MT6397_VIO18_CON7 0x030E
+-#define MT6397_VIO18_CON8 0x0310
+-#define MT6397_VIO18_CON9 0x0312
+-#define MT6397_VIO18_CON10 0x0314
+-#define MT6397_VIO18_CON11 0x0316
+-#define MT6397_VIO18_CON12 0x0318
+-#define MT6397_VIO18_CON13 0x031A
+-#define MT6397_VIO18_CON14 0x031C
+-#define MT6397_VIO18_CON15 0x031E
+-#define MT6397_VIO18_CON16 0x0320
+-#define MT6397_VIO18_CON17 0x0322
+-#define MT6397_VIO18_CON18 0x0324
+-#define MT6397_VPCA7_CON0 0x0326
+-#define MT6397_VPCA7_CON1 0x0328
+-#define MT6397_VPCA7_CON2 0x032A
+-#define MT6397_VPCA7_CON3 0x032C
+-#define MT6397_VPCA7_CON4 0x032E
+-#define MT6397_VPCA7_CON5 0x0330
+-#define MT6397_VPCA7_CON6 0x0332
+-#define MT6397_VPCA7_CON7 0x0334
+-#define MT6397_VPCA7_CON8 0x0336
+-#define MT6397_VPCA7_CON9 0x0338
+-#define MT6397_VPCA7_CON10 0x033A
+-#define MT6397_VPCA7_CON11 0x033C
+-#define MT6397_VPCA7_CON12 0x033E
+-#define MT6397_VPCA7_CON13 0x0340
+-#define MT6397_VPCA7_CON14 0x0342
+-#define MT6397_VPCA7_CON15 0x0344
+-#define MT6397_VPCA7_CON16 0x0346
+-#define MT6397_VPCA7_CON17 0x0348
+-#define MT6397_VPCA7_CON18 0x034A
+-#define MT6397_VSRMCA7_CON0 0x034C
+-#define MT6397_VSRMCA7_CON1 0x034E
+-#define MT6397_VSRMCA7_CON2 0x0350
+-#define MT6397_VSRMCA7_CON3 0x0352
+-#define MT6397_VSRMCA7_CON4 0x0354
+-#define MT6397_VSRMCA7_CON5 0x0356
+-#define MT6397_VSRMCA7_CON6 0x0358
+-#define MT6397_VSRMCA7_CON7 0x035A
+-#define MT6397_VSRMCA7_CON8 0x035C
+-#define MT6397_VSRMCA7_CON9 0x035E
+-#define MT6397_VSRMCA7_CON10 0x0360
+-#define MT6397_VSRMCA7_CON11 0x0362
+-#define MT6397_VSRMCA7_CON12 0x0364
+-#define MT6397_VSRMCA7_CON13 0x0366
+-#define MT6397_VSRMCA7_CON14 0x0368
+-#define MT6397_VSRMCA7_CON15 0x036A
+-#define MT6397_VSRMCA7_CON16 0x036C
+-#define MT6397_VSRMCA7_CON17 0x036E
+-#define MT6397_VSRMCA7_CON18 0x0370
+-#define MT6397_VSRMCA7_CON19 0x0372
+-#define MT6397_VSRMCA7_CON20 0x0374
+-#define MT6397_VSRMCA7_CON21 0x0376
+-#define MT6397_VDRM_CON0 0x0378
+-#define MT6397_VDRM_CON1 0x037A
+-#define MT6397_VDRM_CON2 0x037C
+-#define MT6397_VDRM_CON3 0x037E
+-#define MT6397_VDRM_CON4 0x0380
+-#define MT6397_VDRM_CON5 0x0382
+-#define MT6397_VDRM_CON6 0x0384
+-#define MT6397_VDRM_CON7 0x0386
+-#define MT6397_VDRM_CON8 0x0388
+-#define MT6397_VDRM_CON9 0x038A
+-#define MT6397_VDRM_CON10 0x038C
+-#define MT6397_VDRM_CON11 0x038E
+-#define MT6397_VDRM_CON12 0x0390
+-#define MT6397_VDRM_CON13 0x0392
+-#define MT6397_VDRM_CON14 0x0394
+-#define MT6397_VDRM_CON15 0x0396
+-#define MT6397_VDRM_CON16 0x0398
+-#define MT6397_VDRM_CON17 0x039A
+-#define MT6397_VDRM_CON18 0x039C
+-#define MT6397_BUCK_K_CON0 0x039E
+-#define MT6397_BUCK_K_CON1 0x03A0
+-#define MT6397_ANALDO_CON0 0x0400
+-#define MT6397_ANALDO_CON1 0x0402
+-#define MT6397_ANALDO_CON2 0x0404
+-#define MT6397_ANALDO_CON3 0x0406
+-#define MT6397_ANALDO_CON4 0x0408
+-#define MT6397_ANALDO_CON5 0x040A
+-#define MT6397_ANALDO_CON6 0x040C
+-#define MT6397_ANALDO_CON7 0x040E
+-#define MT6397_DIGLDO_CON0 0x0410
+-#define MT6397_DIGLDO_CON1 0x0412
+-#define MT6397_DIGLDO_CON2 0x0414
+-#define MT6397_DIGLDO_CON3 0x0416
+-#define MT6397_DIGLDO_CON4 0x0418
+-#define MT6397_DIGLDO_CON5 0x041A
+-#define MT6397_DIGLDO_CON6 0x041C
+-#define MT6397_DIGLDO_CON7 0x041E
+-#define MT6397_DIGLDO_CON8 0x0420
+-#define MT6397_DIGLDO_CON9 0x0422
+-#define MT6397_DIGLDO_CON10 0x0424
+-#define MT6397_DIGLDO_CON11 0x0426
+-#define MT6397_DIGLDO_CON12 0x0428
+-#define MT6397_DIGLDO_CON13 0x042A
+-#define MT6397_DIGLDO_CON14 0x042C
+-#define MT6397_DIGLDO_CON15 0x042E
+-#define MT6397_DIGLDO_CON16 0x0430
+-#define MT6397_DIGLDO_CON17 0x0432
+-#define MT6397_DIGLDO_CON18 0x0434
+-#define MT6397_DIGLDO_CON19 0x0436
+-#define MT6397_DIGLDO_CON20 0x0438
+-#define MT6397_DIGLDO_CON21 0x043A
+-#define MT6397_DIGLDO_CON22 0x043C
+-#define MT6397_DIGLDO_CON23 0x043E
+-#define MT6397_DIGLDO_CON24 0x0440
+-#define MT6397_DIGLDO_CON25 0x0442
+-#define MT6397_DIGLDO_CON26 0x0444
+-#define MT6397_DIGLDO_CON27 0x0446
+-#define MT6397_DIGLDO_CON28 0x0448
+-#define MT6397_DIGLDO_CON29 0x044A
+-#define MT6397_DIGLDO_CON30 0x044C
+-#define MT6397_DIGLDO_CON31 0x044E
+-#define MT6397_DIGLDO_CON32 0x0450
+-#define MT6397_DIGLDO_CON33 0x045A
+-#define MT6397_SPK_CON0 0x0600
+-#define MT6397_SPK_CON1 0x0602
+-#define MT6397_SPK_CON2 0x0604
+-#define MT6397_SPK_CON3 0x0606
+-#define MT6397_SPK_CON4 0x0608
+-#define MT6397_SPK_CON5 0x060A
+-#define MT6397_SPK_CON6 0x060C
+-#define MT6397_SPK_CON7 0x060E
+-#define MT6397_SPK_CON8 0x0610
+-#define MT6397_SPK_CON9 0x0612
+-#define MT6397_SPK_CON10 0x0614
+-#define MT6397_SPK_CON11 0x0616
+-#define MT6397_AUDDAC_CON0 0x0700
+-#define MT6397_AUDBUF_CFG0 0x0702
+-#define MT6397_AUDBUF_CFG1 0x0704
+-#define MT6397_AUDBUF_CFG2 0x0706
+-#define MT6397_AUDBUF_CFG3 0x0708
+-#define MT6397_AUDBUF_CFG4 0x070A
+-#define MT6397_IBIASDIST_CFG0 0x070C
+-#define MT6397_AUDACCDEPOP_CFG0 0x070E
+-#define MT6397_AUD_IV_CFG0 0x0710
+-#define MT6397_AUDCLKGEN_CFG0 0x0712
+-#define MT6397_AUDLDO_CFG0 0x0714
+-#define MT6397_AUDLDO_CFG1 0x0716
+-#define MT6397_AUDNVREGGLB_CFG0 0x0718
+-#define MT6397_AUD_NCP0 0x071A
+-#define MT6397_AUDPREAMP_CON0 0x071C
+-#define MT6397_AUDADC_CON0 0x071E
+-#define MT6397_AUDADC_CON1 0x0720
+-#define MT6397_AUDADC_CON2 0x0722
+-#define MT6397_AUDADC_CON3 0x0724
+-#define MT6397_AUDADC_CON4 0x0726
+-#define MT6397_AUDADC_CON5 0x0728
+-#define MT6397_AUDADC_CON6 0x072A
+-#define MT6397_AUDDIGMI_CON0 0x072C
+-#define MT6397_AUDLSBUF_CON0 0x072E
+-#define MT6397_AUDLSBUF_CON1 0x0730
+-#define MT6397_AUDENCSPARE_CON0 0x0732
+-#define MT6397_AUDENCCLKSQ_CON0 0x0734
+-#define MT6397_AUDPREAMPGAIN_CON0 0x0736
+-#define MT6397_ZCD_CON0 0x0738
+-#define MT6397_ZCD_CON1 0x073A
+-#define MT6397_ZCD_CON2 0x073C
+-#define MT6397_ZCD_CON3 0x073E
+-#define MT6397_ZCD_CON4 0x0740
+-#define MT6397_ZCD_CON5 0x0742
+-#define MT6397_NCP_CLKDIV_CON0 0x0744
+-#define MT6397_NCP_CLKDIV_CON1 0x0746
++#define MT6323_CHR_CON0 0x0000
++#define MT6323_CHR_CON1 0x0002
++#define MT6323_CHR_CON2 0x0004
++#define MT6323_CHR_CON3 0x0006
++#define MT6323_CHR_CON4 0x0008
++#define MT6323_CHR_CON5 0x000A
++#define MT6323_CHR_CON6 0x000C
++#define MT6323_CHR_CON7 0x000E
++#define MT6323_CHR_CON8 0x0010
++#define MT6323_CHR_CON9 0x0012
++#define MT6323_CHR_CON10 0x0014
++#define MT6323_CHR_CON11 0x0016
++#define MT6323_CHR_CON12 0x0018
++#define MT6323_CHR_CON13 0x001A
++#define MT6323_CHR_CON14 0x001C
++#define MT6323_CHR_CON15 0x001E
++#define MT6323_CHR_CON16 0x0020
++#define MT6323_CHR_CON17 0x0022
++#define MT6323_CHR_CON18 0x0024
++#define MT6323_CHR_CON19 0x0026
++#define MT6323_CHR_CON20 0x0028
++#define MT6323_CHR_CON21 0x002A
++#define MT6323_CHR_CON22 0x002C
++#define MT6323_CHR_CON23 0x002E
++#define MT6323_CHR_CON24 0x0030
++#define MT6323_CHR_CON25 0x0032
++#define MT6323_CHR_CON26 0x0034
++#define MT6323_CHR_CON27 0x0036
++#define MT6323_CHR_CON28 0x0038
++#define MT6323_CHR_CON29 0x003A
++#define MT6323_STRUP_CON0 0x003C
++#define MT6323_STRUP_CON2 0x003E
++#define MT6323_STRUP_CON3 0x0040
++#define MT6323_STRUP_CON4 0x0042
++#define MT6323_STRUP_CON5 0x0044
++#define MT6323_STRUP_CON6 0x0046
++#define MT6323_STRUP_CON7 0x0048
++#define MT6323_STRUP_CON8 0x004A
++#define MT6323_STRUP_CON9 0x004C
++#define MT6323_STRUP_CON10 0x004E
++#define MT6323_STRUP_CON11 0x0050
++#define MT6323_SPK_CON0 0x0052
++#define MT6323_SPK_CON1 0x0054
++#define MT6323_SPK_CON2 0x0056
++#define MT6323_SPK_CON6 0x005E
++#define MT6323_SPK_CON7 0x0060
++#define MT6323_SPK_CON8 0x0062
++#define MT6323_SPK_CON9 0x0064
++#define MT6323_SPK_CON10 0x0066
++#define MT6323_SPK_CON11 0x0068
++#define MT6323_SPK_CON12 0x006A
++#define MT6323_CID 0x0100
++#define MT6323_TOP_CKPDN0 0x0102
++#define MT6323_TOP_CKPDN0_SET 0x0104
++#define MT6323_TOP_CKPDN0_CLR 0x0106
++#define MT6323_TOP_CKPDN1 0x0108
++#define MT6323_TOP_CKPDN1_SET 0x010A
++#define MT6323_TOP_CKPDN1_CLR 0x010C
++#define MT6323_TOP_CKPDN2 0x010E
++#define MT6323_TOP_CKPDN2_SET 0x0110
++#define MT6323_TOP_CKPDN2_CLR 0x0112
++#define MT6323_TOP_RST_CON 0x0114
++#define MT6323_TOP_RST_CON_SET 0x0116
++#define MT6323_TOP_RST_CON_CLR 0x0118
++#define MT6323_TOP_RST_MISC 0x011A
++#define MT6323_TOP_RST_MISC_SET 0x011C
++#define MT6323_TOP_RST_MISC_CLR 0x011E
++#define MT6323_TOP_CKCON0 0x0120
++#define MT6323_TOP_CKCON0_SET 0x0122
++#define MT6323_TOP_CKCON0_CLR 0x0124
++#define MT6323_TOP_CKCON1 0x0126
++#define MT6323_TOP_CKCON1_SET 0x0128
++#define MT6323_TOP_CKCON1_CLR 0x012A
++#define MT6323_TOP_CKTST0 0x012C
++#define MT6323_TOP_CKTST1 0x012E
++#define MT6323_TOP_CKTST2 0x0130
++#define MT6323_TEST_OUT 0x0132
++#define MT6323_TEST_CON0 0x0134
++#define MT6323_TEST_CON1 0x0136
++#define MT6323_EN_STATUS0 0x0138
++#define MT6323_EN_STATUS1 0x013A
++#define MT6323_OCSTATUS0 0x013C
++#define MT6323_OCSTATUS1 0x013E
++#define MT6323_PGSTATUS 0x0140
++#define MT6323_CHRSTATUS 0x0142
++#define MT6323_TDSEL_CON 0x0144
++#define MT6323_RDSEL_CON 0x0146
++#define MT6323_SMT_CON0 0x0148
++#define MT6323_SMT_CON1 0x014A
++#define MT6323_SMT_CON2 0x014C
++#define MT6323_SMT_CON3 0x014E
++#define MT6323_SMT_CON4 0x0150
++#define MT6323_DRV_CON0 0x0152
++#define MT6323_DRV_CON1 0x0154
++#define MT6323_DRV_CON2 0x0156
++#define MT6323_DRV_CON3 0x0158
++#define MT6323_DRV_CON4 0x015A
++#define MT6323_SIMLS1_CON 0x015C
++#define MT6323_SIMLS2_CON 0x015E
++#define MT6323_INT_CON0 0x0160
++#define MT6323_INT_CON0_SET 0x0162
++#define MT6323_INT_CON0_CLR 0x0164
++#define MT6323_INT_CON1 0x0166
++#define MT6323_INT_CON1_SET 0x0168
++#define MT6323_INT_CON1_CLR 0x016A
++#define MT6323_INT_MISC_CON 0x016C
++#define MT6323_INT_MISC_CON_SET 0x016E
++#define MT6323_INT_MISC_CON_CLR 0x0170
++#define MT6323_INT_STATUS0 0x0172
++#define MT6323_INT_STATUS1 0x0174
++#define MT6323_OC_GEAR_0 0x0176
++#define MT6323_OC_GEAR_1 0x0178
++#define MT6323_OC_GEAR_2 0x017A
++#define MT6323_OC_CTL_VPROC 0x017C
++#define MT6323_OC_CTL_VSYS 0x017E
++#define MT6323_OC_CTL_VPA 0x0180
++#define MT6323_FQMTR_CON0 0x0182
++#define MT6323_FQMTR_CON1 0x0184
++#define MT6323_FQMTR_CON2 0x0186
++#define MT6323_RG_SPI_CON 0x0188
++#define MT6323_DEW_DIO_EN 0x018A
++#define MT6323_DEW_READ_TEST 0x018C
++#define MT6323_DEW_WRITE_TEST 0x018E
++#define MT6323_DEW_CRC_SWRST 0x0190
++#define MT6323_DEW_CRC_EN 0x0192
++#define MT6323_DEW_CRC_VAL 0x0194
++#define MT6323_DEW_DBG_MON_SEL 0x0196
++#define MT6323_DEW_CIPHER_KEY_SEL 0x0198
++#define MT6323_DEW_CIPHER_IV_SEL 0x019A
++#define MT6323_DEW_CIPHER_EN 0x019C
++#define MT6323_DEW_CIPHER_RDY 0x019E
++#define MT6323_DEW_CIPHER_MODE 0x01A0
++#define MT6323_DEW_CIPHER_SWRST 0x01A2
++#define MT6323_DEW_RDDMY_NO 0x01A4
++#define MT6323_DEW_RDATA_DLY_SEL 0x01A6
++#define MT6323_BUCK_CON0 0x0200
++#define MT6323_BUCK_CON1 0x0202
++#define MT6323_BUCK_CON2 0x0204
++#define MT6323_BUCK_CON3 0x0206
++#define MT6323_BUCK_CON4 0x0208
++#define MT6323_BUCK_CON5 0x020A
++#define MT6323_VPROC_CON0 0x020C
++#define MT6323_VPROC_CON1 0x020E
++#define MT6323_VPROC_CON2 0x0210
++#define MT6323_VPROC_CON3 0x0212
++#define MT6323_VPROC_CON4 0x0214
++#define MT6323_VPROC_CON5 0x0216
++#define MT6323_VPROC_CON7 0x021A
++#define MT6323_VPROC_CON8 0x021C
++#define MT6323_VPROC_CON9 0x021E
++#define MT6323_VPROC_CON10 0x0220
++#define MT6323_VPROC_CON11 0x0222
++#define MT6323_VPROC_CON12 0x0224
++#define MT6323_VPROC_CON13 0x0226
++#define MT6323_VPROC_CON14 0x0228
++#define MT6323_VPROC_CON15 0x022A
++#define MT6323_VPROC_CON18 0x0230
++#define MT6323_VSYS_CON0 0x0232
++#define MT6323_VSYS_CON1 0x0234
++#define MT6323_VSYS_CON2 0x0236
++#define MT6323_VSYS_CON3 0x0238
++#define MT6323_VSYS_CON4 0x023A
++#define MT6323_VSYS_CON5 0x023C
++#define MT6323_VSYS_CON7 0x0240
++#define MT6323_VSYS_CON8 0x0242
++#define MT6323_VSYS_CON9 0x0244
++#define MT6323_VSYS_CON10 0x0246
++#define MT6323_VSYS_CON11 0x0248
++#define MT6323_VSYS_CON12 0x024A
++#define MT6323_VSYS_CON13 0x024C
++#define MT6323_VSYS_CON14 0x024E
++#define MT6323_VSYS_CON15 0x0250
++#define MT6323_VSYS_CON18 0x0256
++#define MT6323_VPA_CON0 0x0300
++#define MT6323_VPA_CON1 0x0302
++#define MT6323_VPA_CON2 0x0304
++#define MT6323_VPA_CON3 0x0306
++#define MT6323_VPA_CON4 0x0308
++#define MT6323_VPA_CON5 0x030A
++#define MT6323_VPA_CON7 0x030E
++#define MT6323_VPA_CON8 0x0310
++#define MT6323_VPA_CON9 0x0312
++#define MT6323_VPA_CON10 0x0314
++#define MT6323_VPA_CON11 0x0316
++#define MT6323_VPA_CON12 0x0318
++#define MT6323_VPA_CON14 0x031C
++#define MT6323_VPA_CON16 0x0320
++#define MT6323_VPA_CON17 0x0322
++#define MT6323_VPA_CON18 0x0324
++#define MT6323_VPA_CON19 0x0326
++#define MT6323_VPA_CON20 0x0328
++#define MT6323_BUCK_K_CON0 0x032A
++#define MT6323_BUCK_K_CON1 0x032C
++#define MT6323_BUCK_K_CON2 0x032E
++#define MT6323_ISINK0_CON0 0x0330
++#define MT6323_ISINK0_CON1 0x0332
++#define MT6323_ISINK0_CON2 0x0334
++#define MT6323_ISINK0_CON3 0x0336
++#define MT6323_ISINK1_CON0 0x0338
++#define MT6323_ISINK1_CON1 0x033A
++#define MT6323_ISINK1_CON2 0x033C
++#define MT6323_ISINK1_CON3 0x033E
++#define MT6323_ISINK2_CON0 0x0340
++#define MT6323_ISINK2_CON1 0x0342
++#define MT6323_ISINK2_CON2 0x0344
++#define MT6323_ISINK2_CON3 0x0346
++#define MT6323_ISINK3_CON0 0x0348
++#define MT6323_ISINK3_CON1 0x034A
++#define MT6323_ISINK3_CON2 0x034C
++#define MT6323_ISINK3_CON3 0x034E
++#define MT6323_ISINK_ANA0 0x0350
++#define MT6323_ISINK_ANA1 0x0352
++#define MT6323_ISINK_PHASE_DLY 0x0354
++#define MT6323_ISINK_EN_CTRL 0x0356
++#define MT6323_ANALDO_CON0 0x0400
++#define MT6323_ANALDO_CON1 0x0402
++#define MT6323_ANALDO_CON2 0x0404
++#define MT6323_ANALDO_CON3 0x0406
++#define MT6323_ANALDO_CON4 0x0408
++#define MT6323_ANALDO_CON5 0x040A
++#define MT6323_ANALDO_CON6 0x040C
++#define MT6323_ANALDO_CON7 0x040E
++#define MT6323_ANALDO_CON8 0x0410
++#define MT6323_ANALDO_CON10 0x0412
++#define MT6323_ANALDO_CON15 0x0414
++#define MT6323_ANALDO_CON16 0x0416
++#define MT6323_ANALDO_CON17 0x0418
++#define MT6323_ANALDO_CON18 0x041A
++#define MT6323_ANALDO_CON19 0x041C
++#define MT6323_ANALDO_CON20 0x041E
++#define MT6323_ANALDO_CON21 0x0420
++#define MT6323_DIGLDO_CON0 0x0500
++#define MT6323_DIGLDO_CON2 0x0502
++#define MT6323_DIGLDO_CON3 0x0504
++#define MT6323_DIGLDO_CON5 0x0506
++#define MT6323_DIGLDO_CON6 0x0508
++#define MT6323_DIGLDO_CON7 0x050A
++#define MT6323_DIGLDO_CON8 0x050C
++#define MT6323_DIGLDO_CON9 0x050E
++#define MT6323_DIGLDO_CON10 0x0510
++#define MT6323_DIGLDO_CON11 0x0512
++#define MT6323_DIGLDO_CON12 0x0514
++#define MT6323_DIGLDO_CON13 0x0516
++#define MT6323_DIGLDO_CON14 0x0518
++#define MT6323_DIGLDO_CON15 0x051A
++#define MT6323_DIGLDO_CON16 0x051C
++#define MT6323_DIGLDO_CON17 0x051E
++#define MT6323_DIGLDO_CON18 0x0520
++#define MT6323_DIGLDO_CON19 0x0522
++#define MT6323_DIGLDO_CON20 0x0524
++#define MT6323_DIGLDO_CON21 0x0526
++#define MT6323_DIGLDO_CON23 0x0528
++#define MT6323_DIGLDO_CON24 0x052A
++#define MT6323_DIGLDO_CON26 0x052C
++#define MT6323_DIGLDO_CON27 0x052E
++#define MT6323_DIGLDO_CON28 0x0530
++#define MT6323_DIGLDO_CON29 0x0532
++#define MT6323_DIGLDO_CON30 0x0534
++#define MT6323_DIGLDO_CON31 0x0536
++#define MT6323_DIGLDO_CON32 0x0538
++#define MT6323_DIGLDO_CON33 0x053A
++#define MT6323_DIGLDO_CON34 0x053C
++#define MT6323_DIGLDO_CON35 0x053E
++#define MT6323_DIGLDO_CON36 0x0540
++#define MT6323_DIGLDO_CON39 0x0542
++#define MT6323_DIGLDO_CON40 0x0544
++#define MT6323_DIGLDO_CON41 0x0546
++#define MT6323_DIGLDO_CON42 0x0548
++#define MT6323_DIGLDO_CON43 0x054A
++#define MT6323_DIGLDO_CON44 0x054C
++#define MT6323_DIGLDO_CON45 0x054E
++#define MT6323_DIGLDO_CON46 0x0550
++#define MT6323_DIGLDO_CON47 0x0552
++#define MT6323_DIGLDO_CON48 0x0554
++#define MT6323_DIGLDO_CON49 0x0556
++#define MT6323_DIGLDO_CON50 0x0558
++#define MT6323_DIGLDO_CON51 0x055A
++#define MT6323_DIGLDO_CON52 0x055C
++#define MT6323_DIGLDO_CON53 0x055E
++#define MT6323_DIGLDO_CON54 0x0560
++#define MT6323_EFUSE_CON0 0x0600
++#define MT6323_EFUSE_CON1 0x0602
++#define MT6323_EFUSE_CON2 0x0604
++#define MT6323_EFUSE_CON3 0x0606
++#define MT6323_EFUSE_CON4 0x0608
++#define MT6323_EFUSE_CON5 0x060A
++#define MT6323_EFUSE_CON6 0x060C
++#define MT6323_EFUSE_VAL_0_15 0x060E
++#define MT6323_EFUSE_VAL_16_31 0x0610
++#define MT6323_EFUSE_VAL_32_47 0x0612
++#define MT6323_EFUSE_VAL_48_63 0x0614
++#define MT6323_EFUSE_VAL_64_79 0x0616
++#define MT6323_EFUSE_VAL_80_95 0x0618
++#define MT6323_EFUSE_VAL_96_111 0x061A
++#define MT6323_EFUSE_VAL_112_127 0x061C
++#define MT6323_EFUSE_VAL_128_143 0x061E
++#define MT6323_EFUSE_VAL_144_159 0x0620
++#define MT6323_EFUSE_VAL_160_175 0x0622
++#define MT6323_EFUSE_VAL_176_191 0x0624
++#define MT6323_EFUSE_DOUT_0_15 0x0626
++#define MT6323_EFUSE_DOUT_16_31 0x0628
++#define MT6323_EFUSE_DOUT_32_47 0x062A
++#define MT6323_EFUSE_DOUT_48_63 0x062C
++#define MT6323_EFUSE_DOUT_64_79 0x062E
++#define MT6323_EFUSE_DOUT_80_95 0x0630
++#define MT6323_EFUSE_DOUT_96_111 0x0632
++#define MT6323_EFUSE_DOUT_112_127 0x0634
++#define MT6323_EFUSE_DOUT_128_143 0x0636
++#define MT6323_EFUSE_DOUT_144_159 0x0638
++#define MT6323_EFUSE_DOUT_160_175 0x063A
++#define MT6323_EFUSE_DOUT_176_191 0x063C
++#define MT6323_EFUSE_CON7 0x063E
++#define MT6323_EFUSE_CON8 0x0640
++#define MT6323_EFUSE_CON9 0x0642
++#define MT6323_RTC_MIX_CON0 0x0644
++#define MT6323_RTC_MIX_CON1 0x0646
++#define MT6323_AUDTOP_CON0 0x0700
++#define MT6323_AUDTOP_CON1 0x0702
++#define MT6323_AUDTOP_CON2 0x0704
++#define MT6323_AUDTOP_CON3 0x0706
++#define MT6323_AUDTOP_CON4 0x0708
++#define MT6323_AUDTOP_CON5 0x070A
++#define MT6323_AUDTOP_CON6 0x070C
++#define MT6323_AUDTOP_CON7 0x070E
++#define MT6323_AUDTOP_CON8 0x0710
++#define MT6323_AUDTOP_CON9 0x0712
++#define MT6323_AUXADC_ADC0 0x0714
++#define MT6323_AUXADC_ADC1 0x0716
++#define MT6323_AUXADC_ADC2 0x0718
++#define MT6323_AUXADC_ADC3 0x071A
++#define MT6323_AUXADC_ADC4 0x071C
++#define MT6323_AUXADC_ADC5 0x071E
++#define MT6323_AUXADC_ADC6 0x0720
++#define MT6323_AUXADC_ADC7 0x0722
++#define MT6323_AUXADC_ADC8 0x0724
++#define MT6323_AUXADC_ADC9 0x0726
++#define MT6323_AUXADC_ADC10 0x0728
++#define MT6323_AUXADC_ADC11 0x072A
++#define MT6323_AUXADC_ADC12 0x072C
++#define MT6323_AUXADC_ADC13 0x072E
++#define MT6323_AUXADC_ADC14 0x0730
++#define MT6323_AUXADC_ADC15 0x0732
++#define MT6323_AUXADC_ADC16 0x0734
++#define MT6323_AUXADC_ADC17 0x0736
++#define MT6323_AUXADC_ADC18 0x0738
++#define MT6323_AUXADC_ADC19 0x073A
++#define MT6323_AUXADC_ADC20 0x073C
++#define MT6323_AUXADC_RSV1 0x073E
++#define MT6323_AUXADC_RSV2 0x0740
++#define MT6323_AUXADC_CON0 0x0742
++#define MT6323_AUXADC_CON1 0x0744
++#define MT6323_AUXADC_CON2 0x0746
++#define MT6323_AUXADC_CON3 0x0748
++#define MT6323_AUXADC_CON4 0x074A
++#define MT6323_AUXADC_CON5 0x074C
++#define MT6323_AUXADC_CON6 0x074E
++#define MT6323_AUXADC_CON7 0x0750
++#define MT6323_AUXADC_CON8 0x0752
++#define MT6323_AUXADC_CON9 0x0754
++#define MT6323_AUXADC_CON10 0x0756
++#define MT6323_AUXADC_CON11 0x0758
++#define MT6323_AUXADC_CON12 0x075A
++#define MT6323_AUXADC_CON13 0x075C
++#define MT6323_AUXADC_CON14 0x075E
++#define MT6323_AUXADC_CON15 0x0760
++#define MT6323_AUXADC_CON16 0x0762
++#define MT6323_AUXADC_CON17 0x0764
++#define MT6323_AUXADC_CON18 0x0766
++#define MT6323_AUXADC_CON19 0x0768
++#define MT6323_AUXADC_CON20 0x076A
++#define MT6323_AUXADC_CON21 0x076C
++#define MT6323_AUXADC_CON22 0x076E
++#define MT6323_AUXADC_CON23 0x0770
++#define MT6323_AUXADC_CON24 0x0772
++#define MT6323_AUXADC_CON25 0x0774
++#define MT6323_AUXADC_CON26 0x0776
++#define MT6323_AUXADC_CON27 0x0778
++#define MT6323_ACCDET_CON0 0x077A
++#define MT6323_ACCDET_CON1 0x077C
++#define MT6323_ACCDET_CON2 0x077E
++#define MT6323_ACCDET_CON3 0x0780
++#define MT6323_ACCDET_CON4 0x0782
++#define MT6323_ACCDET_CON5 0x0784
++#define MT6323_ACCDET_CON6 0x0786
++#define MT6323_ACCDET_CON7 0x0788
++#define MT6323_ACCDET_CON8 0x078A
++#define MT6323_ACCDET_CON9 0x078C
++#define MT6323_ACCDET_CON10 0x078E
++#define MT6323_ACCDET_CON11 0x0790
++#define MT6323_ACCDET_CON12 0x0792
++#define MT6323_ACCDET_CON13 0x0794
++#define MT6323_ACCDET_CON14 0x0796
++#define MT6323_ACCDET_CON15 0x0798
++#define MT6323_ACCDET_CON16 0x079A
+
+-#endif /* __MFD_MT6397_REGISTERS_H__ */
++#endif
+diff --git a/include/linux/regulator/mt6323-regulator.h b/include/linux/regulator/mt6323-regulator.h
+new file mode 100644
+index 0000000..620b0e3
+--- /dev/null
++++ b/include/linux/regulator/mt6323-regulator.h
+@@ -0,0 +1,37 @@
++/*
++ * Copyright (c) 2015 MediaTek Inc.
++ * Author: John Crispin <blogic@openwrt.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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.
++ */
++
++#ifndef __LINUX_REGULATOR_MT6323_H
++#define __LINUX_REGULATOR_MT6323_H
++
++enum {
++ MT6323_ID_VPROC = 0,
++ MT6323_ID_VSYS,
++ MT6323_ID_VPA,
++ MT6323_ID_VTCXO,
++ MT6323_ID_VA,
++ MT6323_ID_VCN28,
++ MT6323_ID_VCN33,
++ MT6323_ID_VIO28,
++ MT6323_ID_VUSB,
++ MT6323_ID_VMC,
++ MT6323_ID_VMCH,
++ MT6323_ID_VGP1,
++ MT6323_ID_VGP2,
++ MT6323_ID_RG_MAX,
++};
++
++#define MT6323_MAX_REGULATOR MT6323_ID_RG_MAX
++
++#endif /* __LINUX_REGULATOR_MT6323_H */
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0073-clk.patch b/target/linux/mediatek/patches/0073-clk.patch
new file mode 100644
index 0000000000..a3b36a5dae
--- /dev/null
+++ b/target/linux/mediatek/patches/0073-clk.patch
@@ -0,0 +1,200 @@
+From a4df453fbfa6199ad33435cee6ce2dfcc65321b0 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 3 Jul 2015 05:45:58 +0200
+Subject: [PATCH 73/76] clk
+
+---
+ include/dt-bindings/clock/mt7623-clk.h | 158 +++++++++++++++-----------------
+ 1 file changed, 73 insertions(+), 85 deletions(-)
+
+diff --git a/include/dt-bindings/clock/mt7623-clk.h b/include/dt-bindings/clock/mt7623-clk.h
+index cb1e8a9..410ef31 100644
+--- a/include/dt-bindings/clock/mt7623-clk.h
++++ b/include/dt-bindings/clock/mt7623-clk.h
+@@ -17,96 +17,76 @@
+
+ /* TOPCKGEN */
+
+-#define CLK_TOP_AUDPLL_24 1
+-#define CLK_TOP_AUDPLL_D16 2
+-#define CLK_TOP_AUDPLL_D4 3
+-#define CLK_TOP_AUDPLL_D8 4
+-#define CLK_TOP_CLKPH_MCK 5
+-#define CLK_TOP_CPUM_TCK_IN 6
+-#define CLK_TOP_DSI0_LNTC_DSICLK 7
+-#define CLK_TOP_HDMITX_CLKDIG_CTS 8
+-#define CLK_TOP_LVDS_ETH 9
+-#define CLK_TOP_LVDSPLL_D2 10
+-#define CLK_TOP_LVDSPLL_D4 11
+-#define CLK_TOP_LVDSPLL_D8 12
+-#define CLK_TOP_MAINPLL_230P3M 13
+-#define CLK_TOP_MAINPLL_322P4M 14
+-#define CLK_TOP_MAINPLL_537P3M 15
+-#define CLK_TOP_MAINPLL_806M 16
+-#define CLK_TOP_MEMPLL_MCK_D4 17
+-#define CLK_TOP_MMPLL_D2 18
+-#define CLK_TOP_MSDCPLL_D2 19
+-#define CLK_TOP_SYSPLL1_D16 20
+-#define CLK_TOP_SYSPLL1_D2 21
+-#define CLK_TOP_SYSPLL1_D4 22
+-#define CLK_TOP_SYSPLL1_D8 23
+-#define CLK_TOP_SYSPLL2_D2 24
+-#define CLK_TOP_SYSPLL2_D4 25
+-#define CLK_TOP_SYSPLL2_D8 26
+-#define CLK_TOP_SYSPLL3_D2 27
+-#define CLK_TOP_SYSPLL3_D4 28
+-#define CLK_TOP_SYSPLL4_D2 29
+-#define CLK_TOP_SYSPLL4_D4 30
+-#define CLK_TOP_SYSPLL_D3 31
+-#define CLK_TOP_SYSPLL_D5 32
+-#define CLK_TOP_SYSPLL_D7 33
+-#define CLK_TOP_TVDPLL_d2 34
+-#define CLK_TOP_TVDPLL_D4 35
+-#define CLK_TOP_UNIVPLL_178P3M 36
+-#define CLK_TOP_UNIVPLL1_D10 37
+-#define CLK_TOP_UNIVPLL1_D2 38
+-#define CLK_TOP_UNIVPLL1_D4 39
+-#define CLK_TOP_UNIVPLL1_D6 40
+-#define CLK_TOP_UNIVPLL1_D8 41
+-#define CLK_TOP_UNIVPLL_249P6M 42
+-#define CLK_TOP_UNIVPLL2_D2 43
+-#define CLK_TOP_UNIVPLL2_D4 44
+-#define CLK_TOP_UNIVPLL2_D6 45
+-#define CLK_TOP_UNIVPLL2_D8 46
+-#define CLK_TOP_UNIVPLL_416M 47
+-#define CLK_TOP_UNIVPLL_48M 48
+-#define CLK_TOP_UNIVPLL_624M 49
+-#define CLK_TOP_UNIVPLL_D26 50
+-#define CLK_TOP_UNIVPLL_D5 51
+-#define CLK_TOP_APLL_SEL 52
++#define CLK_TOP_MAINPLL_650M 1
++#define CLK_TOP_MAINPLL_433P3M 2
++#define CLK_TOP_MAINPLL_260M 3
++#define CLK_TOP_MAINPLL_185P6M 4
++#define CLK_TOP_UNIVPLL_624M 5
++#define CLK_TOP_UNIVPLL_416M 6
++#define CLK_TOP_UNIVPLL_249P6M 7
++#define CLK_TOP_UNIVPLL_178P3M 8
++#define CLK_TOP_UNIVPLL_48M 9
++#define CLK_TOP_AUDPLL_D4 10
++#define CLK_TOP_AUDPLL_D8 11
++#define CLK_TOP_AUDPLL_D16 12
++#define CLK_TOP_AUDPLL_24 13
++#define CLK_TOP_MSDCPLL_D2 14
++#define CLK_TOP_SYSPLL1_D2 15
++#define CLK_TOP_SYSPLL1_D4 16
++#define CLK_TOP_SYSPLL1_D8 17
++#define CLK_TOP_SYSPLL1_D16 18
++#define CLK_TOP_SYSPLL2_D2 19
++#define CLK_TOP_SYSPLL2_D4 20
++#define CLK_TOP_SYSPLL2_D8 21
++#define CLK_TOP_SYSPLL3_D2 22
++#define CLK_TOP_SYSPLL3_D4 23
++#define CLK_TOP_SYSPLL4_D2 24
++#define CLK_TOP_SYSPLL4_D4 25
++#define CLK_TOP_SYSPLL_D3 26
++#define CLK_TOP_SYSPLL_D5 27
++#define CLK_TOP_SYSPLL_D7 28
++#define CLK_TOP_UNIVPLL1_D2 29
++#define CLK_TOP_UNIVPLL1_D4 30
++#define CLK_TOP_UNIVPLL1_D6 31
++#define CLK_TOP_UNIVPLL1_D8 32
++#define CLK_TOP_UNIVPLL1_D10 33
++#define CLK_TOP_UNIVPLL2_D2 34
++#define CLK_TOP_UNIVPLL2_D4 35
++#define CLK_TOP_UNIVPLL2_D6 36
++#define CLK_TOP_UNIVPLL2_D8 37
++#define CLK_TOP_UNIVPLL_D5 38
++#define CLK_TOP_UNIVPLL_D26 39
++#define CLK_TOP_AXI_SEL 40
++#define CLK_TOP_MEM_SEL 41
++#define CLK_TOP_DDR_SEL 42
++#define CLK_TOP_MM_SEL 43
++#define CLK_TOP_PWM_SEL 44
++#define CLK_TOP_MFG_SEL 45
++#define CLK_TOP_UART_SEL 46
++#define CLK_TOP_SPI_SEL 47
++#define CLK_TOP_USB20_SEL 48
++#define CLK_TOP_MSDC30_0_SEL 49
++#define CLK_TOP_MSDC30_1_SEL 50
++#define CLK_TOP_MSDC30_2_SEL 51
++#define CLK_TOP_AUDIO_SEL 52
+ #define CLK_TOP_AUDIO_INTBUS_SEL 53
+-#define CLK_TOP_AUDIO_SEL 54
+-#define CLK_TOP_AXI_SEL 55
+-#define CLK_TOP_CAM_SEL 56
+-#define CLK_TOP_DDR_SEL 57
+-#define CLK_TOP_DPI0_SEL 58
+-#define CLK_TOP_DPI1_SEL 59
+-#define CLK_TOP_DPILVDS_SEL 60
+-#define CLK_TOP_ETH_SEL 61
+-#define CLK_TOP_MEM_SEL 62
+-#define CLK_TOP_MFG_SEL 63
+-#define CLK_TOP_MM_SEL 64
+-#define CLK_TOP_MSDC30_0_SEL 65
+-#define CLK_TOP_MSDC30_1_SEL 66
+-#define CLK_TOP_MSDC30_2_SEL 67
+-#define CLK_TOP_NFI2X_SEL 68
+-#define CLK_TOP_PMICSPI_SEL 69
+-#define CLK_TOP_PWM_SEL 70
+-#define CLK_TOP_RTC_SEL 71
+-#define CLK_TOP_SCP_SEL 72
+-#define CLK_TOP_SPI_SEL 73
+-#define CLK_TOP_TVE_SEL 74
+-#define CLK_TOP_UART_SEL 75
+-#define CLK_TOP_USB20_SEL 76
+-#define CLK_TOP_VDEC_SEL 77
+-#define CLK_TOP_NR_CLK 78
++#define CLK_TOP_PMICSPI_SEL 54
++#define CLK_TOP_SCP_SEL 55
++#define CLK_TOP_APLL_SEL 56
++#define CLK_TOP_RTC_SEL 57
++#define CLK_TOP_NFI2X_SEL 58
++#define CLK_TOP_ETH_SEL 59
++#define CLK_TOP_NR_CLK 60
+
+ /* APMIXED_SYS */
+
+ #define CLK_APMIXED_ARMPLL 1
+ #define CLK_APMIXED_MAINPLL 2
+-#define CLK_APMIXED_MSDCPLL 3
+-#define CLK_APMIXED_UNIVPLL 4
+-#define CLK_APMIXED_MMPLL 5
+-#define CLK_APMIXED_VENCPLL 6
+-#define CLK_APMIXED_TVDPLL 7
+-#define CLK_APMIXED_LVDSPLL 8
+-#define CLK_APMIXED_AUDPLL 9
++#define CLK_APMIXED_UNIVPLL 3
++#define CLK_APMIXED_MSDCPLL 4
++#define CLK_APMIXED_AUDPLL 5
++#define CLK_APMIXED_TRGPLL 6
++#define CLK_APMIXED_ETHPLL 7
+
+ /* INFRA_SYS */
+
+@@ -124,7 +104,8 @@
+ #define CLK_INFRA_IRRX 19
+ #define CLK_INFRA_PMICSPI 22
+ #define CLK_INFRA_PMIC_WRAP 23
+-#define CLK_INFRA_NR_CLK 24
++#define CLK_INFRA_CA7SEL 24
++#define CLK_INFRA_NR_CLK 25
+
+ /* PERI_SYS */
+
+@@ -169,5 +150,12 @@
+ #define CLK_PERI_UART3_SEL 38
+ #define CLK_PERI_NR_CLK 39
+
++#define CLK_HIFSYS_USB0_PHY 1
++#define CLK_HIFSYS_USB1_PHY 2
++#define CLK_HIFSYS_PCIE0 3
++#define CLK_HIFSYS_PCIE1 4
++#define CLK_HIFSYS_PCIE2 5
++#define CLK_HIFSYS_NR_CLK 6
++
+ #endif /* _DT_BINDINGS_CLK_MT7623_H */
+
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0074-dts.patch b/target/linux/mediatek/patches/0074-dts.patch
new file mode 100644
index 0000000000..eddafb61cd
--- /dev/null
+++ b/target/linux/mediatek/patches/0074-dts.patch
@@ -0,0 +1,182 @@
+From df59c3b7030b6d7802fe5e5abda81467fcdf2178 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 3 Jul 2015 05:46:13 +0200
+Subject: [PATCH 74/76] dts
+
+---
+ arch/arm/boot/dts/mt7623-evb.dts | 124 +++++++++++++++++++++++++++++++++++++-
+ arch/arm/boot/dts/mt7623.dtsi | 11 ++++
+ 2 files changed, 133 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/mt7623-evb.dts
++++ b/arch/arm/boot/dts/mt7623-evb.dts
+@@ -145,8 +145,8 @@
+ bus-width = <8>;
+ max-frequency = <50000000>;
+ cap-mmc-highspeed;
+-// vmmc-supply = <&mt6397_vemc_3v3_reg>;
+-// vqmmc-supply = <&mt6397_vio18_reg>;
++// vmmc-supply = <&mt6323_vemc_3v3_reg>;
++// vqmmc-supply = <&mt6323_vio18_reg>;
+ non-removable;
+ };
+
+@@ -160,3 +160,123 @@
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie_default>;
+ };
++
++&pwrap {
++ pmic: mt6323 {
++ compatible = "mediatek,mt6323";
++
++ mt6323regulator: mt6323regulator {
++ compatible = "mediatek,mt6323-regulator";
++
++ mt6323_vproc_reg: buck_vproc {
++ regulator-compatible = "buck_vproc";
++ regulator-name = "vproc";
++ regulator-min-microvolt = < 700000>;
++ regulator-max-microvolt = <1493750>;
++ regulator-ramp-delay = <6250>;
++ regulator-always-on;
++ };
++
++ mt6323_vsys_reg: buck_vsys {
++ regulator-compatible = "buck_vsys";
++ regulator-name = "vsys";
++ regulator-min-microvolt = <1400000>;
++ regulator-max-microvolt = <3000000>;
++ regulator-ramp-delay = <12500>;
++ regulator-always-on;
++ };
++
++ mt6323_vpa_reg: buck_vpa {
++ regulator-compatible = "buck_vpa";
++ regulator-name = "vpa";
++ regulator-min-microvolt = < 500000>;
++ regulator-max-microvolt = <3650000>;
++ regulator-ramp-delay = <50000>;
++ regulator-always-on;
++ };
++
++ mt6323_vtcxo_reg: ldo_vtcxo {
++ regulator-compatible = "ldo_vtcxo";
++ regulator-name = "vtcxo";
++ regulator-always-on;
++ };
++
++ mt6323_va_reg: ldo_va {
++ regulator-compatible = "ldo_va";
++ regulator-name = "va";
++ regulator-always-on;
++ };
++
++ mt6323_vcn28_reg: ldo_vcn28 {
++ regulator-compatible = "ldo_vcn28";
++ regulator-name = "vcn28";
++ regulator-always-on;
++ };
++
++ mt6323_vcn33_reg: ldo_vcn33 {
++ regulator-compatible = "ldo_vcn33";
++ regulator-name = "vcn33";
++ regulator-always-on;
++ };
++
++ mt6323_vcama_reg: ldo_vcama {
++ regulator-compatible = "ldo_vcama";
++ regulator-name = "vcama";
++ regulator-min-microvolt = <1500000>;
++ regulator-max-microvolt = <2800000>;
++ regulator-enable-ramp-delay = <218>;
++ };
++
++ mt6323_vio28_reg: ldo_vio28 {
++ regulator-compatible = "ldo_vio28";
++ regulator-name = "vio28";
++ regulator-always-on;
++ };
++
++ mt6323_vusb_reg: ldo_vusb {
++ regulator-compatible = "ldo_vusb";
++ regulator-name = "vusb";
++ };
++
++ mt6323_vmc_reg: ldo_vmc {
++ regulator-compatible = "ldo_vmc";
++ regulator-name = "vmc";
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-enable-ramp-delay = <218>;
++ };
++
++ mt6323_vmch_reg: ldo_vmch {
++ regulator-compatible = "ldo_vmch";
++ regulator-name = "vmch";
++ regulator-min-microvolt = <3000000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-enable-ramp-delay = <218>;
++ };
++
++ mt6323_vemc_3v3_reg: ldo_vemc3v3 {
++ regulator-compatible = "ldo_vemc3v3";
++ regulator-name = "vemc_3v3";
++ regulator-min-microvolt = <3000000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-enable-ramp-delay = <218>;
++ };
++
++ mt6323_vgp1_reg: ldo_vgp1 {
++ regulator-compatible = "ldo_vgp1";
++ regulator-name = "vcamd";
++ regulator-min-microvolt = <1220000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-enable-ramp-delay = <240>;
++ };
++
++ mt6323_vgp2_reg: ldo_vgp2 {
++ regulator-compatible = "ldo_vgp2";
++ regulator-name = "vcamio";
++ regulator-min-microvolt = <1000000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-enable-ramp-delay = <218>;
++ };
++ };
++ };
++};
+--- a/arch/arm/boot/dts/mt7623.dtsi
++++ b/arch/arm/boot/dts/mt7623.dtsi
+@@ -150,6 +150,17 @@
+ clock-names = "system-clk", "rtc-clk";
+ };
+
++ pwrap: pwrap@1000f000 {
++ compatible = "mediatek,mt7623-pwrap";
++ reg = <0 0x1000f000 0 0x1000>;
++ reg-names = "pwrap";
++ interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
++ resets = <&infracfg MT7623_INFRA_PMIC_WRAP_RST>;
++ reset-names = "pwrap";
++ clocks = <&clk26m>, <&clk26m>;
++ clock-names = "spi", "wrap";
++ };
++
+ sysirq: interrupt-controller@10200100 {
+ compatible = "mediatek,mt7623-sysirq",
+ "mediatek,mt6577-sysirq";
+@@ -311,6 +322,7 @@
+ device_type = "pci";
+
+ bus-range = <0 255>;
++ status = "disabled";
+ ranges = <
+ 0x02000000 0 0 0x00000000 0x60000000 0 0x10000000 /* pci memory */
+ 0x01000000 0 0 0x00000000 0x1A160000 0 0x00010000 /* io space */
+@@ -343,6 +355,5 @@
+ device_type = "pci";
+ };
+
+- status = "disabled";
+ };
+ };
diff --git a/target/linux/mediatek/patches/0075-sd.patch b/target/linux/mediatek/patches/0075-sd.patch
new file mode 100644
index 0000000000..1dcfae397f
--- /dev/null
+++ b/target/linux/mediatek/patches/0075-sd.patch
@@ -0,0 +1,55 @@
+From a5982c5e4b58c4335e789969e04f9e24b894f510 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 3 Jul 2015 05:46:39 +0200
+Subject: [PATCH 75/76] sd
+
+---
+ drivers/mmc/host/mtk-sd.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
+index 7c20f28..be2b00c 100644
+--- a/drivers/mmc/host/mtk-sd.c
++++ b/drivers/mmc/host/mtk-sd.c
+@@ -227,11 +227,13 @@ struct mt_gpdma_desc {
+ #define GPDMA_DESC_BDP (0x1 << 1)
+ #define GPDMA_DESC_CHECKSUM (0xff << 8) /* bit8 ~ bit15 */
+ #define GPDMA_DESC_INT (0x1 << 16)
++#define GPDMA_DESC_GPDH4B (0x1 << 24)
++#define GPDMA_DESC_BDH4B (0x1 << 28)
+ u32 next;
+ u32 ptr;
+ u32 gpd_data_len;
+-#define GPDMA_DESC_BUFLEN (0xffff) /* bit0 ~ bit15 */
+-#define GPDMA_DESC_EXTLEN (0xff << 16) /* bit16 ~ bit23 */
++#define GPDMA_DESC_BUFLEN (0xffffff) /* bit0 ~ bit15 */
++#define GPDMA_DESC_EXTLEN (0xff << 24) /* bit16 ~ bit23 */
+ u32 arg;
+ u32 blknum;
+ u32 cmd;
+@@ -243,10 +245,12 @@ struct mt_bdma_desc {
+ #define BDMA_DESC_CHECKSUM (0xff << 8) /* bit8 ~ bit15 */
+ #define BDMA_DESC_BLKPAD (0x1 << 17)
+ #define BDMA_DESC_DWPAD (0x1 << 18)
++#define BDMA_DESC_GPDH4B (0x1 << 24)
++#define BDMA_DESC_BDH4B (0x1 << 28)
+ u32 next;
+ u32 ptr;
+ u32 bd_data_len;
+-#define BDMA_DESC_BUFLEN (0xffff) /* bit0 ~ bit15 */
++#define BDMA_DESC_BUFLEN (0xffffff) /* bit0 ~ bit15 */
+ };
+
+ struct msdc_dma {
+@@ -1115,7 +1119,7 @@ static void msdc_init_hw(struct msdc_host *host)
+ sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL, 1);
+ writel(0x403c004f, host->base + MSDC_PATCH_BIT);
+ sdr_set_field(host->base + MSDC_PATCH_BIT, MSDC_CKGEN_MSDC_DLY_SEL, 1);
+- writel(0xffff0089, host->base + MSDC_PATCH_BIT1);
++// writel(0xffff0089, host->base + MSDC_PATCH_BIT1);
+ /* Configure to enable SDIO mode.
+ * it's must otherwise sdio cmd5 failed
+ */
+--
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0076-reset.patch b/target/linux/mediatek/patches/0076-reset.patch
new file mode 100644
index 0000000000..615777920c
--- /dev/null
+++ b/target/linux/mediatek/patches/0076-reset.patch
@@ -0,0 +1,30 @@
+From 1671d902f8dcfce70f920ad3dfebb1031a7a38de Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 3 Jul 2015 05:46:51 +0200
+Subject: [PATCH 76/76] reset
+
+---
+ include/dt-bindings/reset-controller/mt7623-resets.h | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/include/dt-bindings/reset-controller/mt7623-resets.h b/include/dt-bindings/reset-controller/mt7623-resets.h
+index 28a7d69..3e0f39a 100644
+--- a/include/dt-bindings/reset-controller/mt7623-resets.h
++++ b/include/dt-bindings/reset-controller/mt7623-resets.h
+@@ -56,4 +56,13 @@
+ #define MT7623_PERI_ETH_SW_RST 29
+ #define MT7623_PERI_SPI0_SW_RST 33
+
++/* high speed interface resets */
++#define MT7623_HIFSYS_UHOST0_SW_RST 3
++#define MT7623_HIFSYS_UHOST1_SW_RST 4
++#define MT7623_HIFSYS_UPHY0_SW_RST 21
++#define MT7623_HIFSYS_UPHY1_SW_RST 22
++#define MT7623_HIFSYS_PCIE0_SW_RST 24
++#define MT7623_HIFSYS_PCIE0_SW_RST 25
++#define MT7623_HIFSYS_PCIE0_SW_RST 26
++
+ #endif /* _DT_BINDINGS_RESET_CONTROLLER_MT7623 */
+--
+1.7.10.4
+