mirror of
				https://github.com/Ysurac/openmptcprouter.git
				synced 2025-03-09 15:40:20 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			846 lines
		
	
	
	
		
			24 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			846 lines
		
	
	
	
		
			24 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From 83ffbaceffed1cd47a6f67fb20e39737dfb2d01a Mon Sep 17 00:00:00 2001
 | 
						|
From: Frank Wunderlich <frank-w@public-files.de>
 | 
						|
Date: Tue, 28 Aug 2018 18:14:56 +0200
 | 
						|
Subject: [PATCH 07/77] [wifi] adding wifi-related changes outside
 | 
						|
 driver-directory
 | 
						|
 | 
						|
---
 | 
						|
 arch/arm/boot/dts/mt7623.dtsi                 |  41 +-
 | 
						|
 arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts |  42 ++
 | 
						|
 drivers/soc/mediatek/mtk-pmic-wrap.c          |  12 +
 | 
						|
 drivers/watchdog/mtk_wdt.c                    | 377 +++++++++++++++++-
 | 
						|
 include/linux/wakelock.h                      |  67 ++++
 | 
						|
 include/net/genetlink.h                       |  44 ++
 | 
						|
 include/soc/mediatek/pmic_wrap.h              |  19 +
 | 
						|
 include/uapi/linux/genetlink.h                |   1 +
 | 
						|
 8 files changed, 588 insertions(+), 15 deletions(-)
 | 
						|
 create mode 100644 include/linux/wakelock.h
 | 
						|
 create mode 100644 include/soc/mediatek/pmic_wrap.h
 | 
						|
 | 
						|
diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi
 | 
						|
index 04228cf9ddbb..af6b6228f8a8 100644
 | 
						|
--- a/arch/arm/boot/dts/mt7623.dtsi
 | 
						|
+++ b/arch/arm/boot/dts/mt7623.dtsi
 | 
						|
@@ -266,6 +266,8 @@
 | 
						|
 		compatible = "mediatek,mt7623-wdt",
 | 
						|
 			     "mediatek,mt6589-wdt";
 | 
						|
 		reg = <0 0x10007000 0 0x100>;
 | 
						|
+		interrupts = <GIC_SPI 88 IRQ_TYPE_EDGE_FALLING>;
 | 
						|
+		#reset-cells = <1>;
 | 
						|
 	};
 | 
						|
 
 | 
						|
 	timer: timer@10008000 {
 | 
						|
@@ -494,13 +496,26 @@
 | 
						|
 			     "mediatek,mtk-btif";
 | 
						|
 		reg = <0 0x1100c000 0 0x1000>;
 | 
						|
 		interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_LOW>;
 | 
						|
-		clocks = <&pericfg CLK_PERI_BTIF>;
 | 
						|
-		clock-names = "main";
 | 
						|
+		clocks = <&pericfg CLK_PERI_BTIF>, <&pericfg CLK_PERI_AP_DMA>;
 | 
						|
+		clock-names = "main", "apdmac";
 | 
						|
 		reg-shift = <2>;
 | 
						|
 		reg-io-width = <4>;
 | 
						|
 		status = "disabled";
 | 
						|
 	};
 | 
						|
 
 | 
						|
+	btif_tx: btif_tx@11000780 {
 | 
						|
+		compatible = "mediatek,btif_tx";
 | 
						|
+		reg = <0 0x11000780 0 0x80>;
 | 
						|
+		interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_LOW>;
 | 
						|
+		status = "okay";
 | 
						|
+	};
 | 
						|
+	btif_rx: btif_rx@11000800 {
 | 
						|
+		compatible = "mediatek,btif_rx";
 | 
						|
+		reg = <0 0x11000800 0 0x80>;
 | 
						|
+		interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_LOW>;
 | 
						|
+		status = "okay";
 | 
						|
+	};
 | 
						|
+
 | 
						|
 	nandc: nfi@1100d000 {
 | 
						|
 		compatible = "mediatek,mt7623-nfc",
 | 
						|
 			     "mediatek,mt2701-nfc";
 | 
						|
@@ -683,6 +698,28 @@
 | 
						|
 		status = "disabled";
 | 
						|
 	};
 | 
						|
 
 | 
						|
+	consys: consys@18070000 {
 | 
						|
+		compatible = "mediatek,mt7623-consys";
 | 
						|
+		reg = <0 0x18070000 0 0x0200>,  /*CONN_MCU_CONFIG_BASE      */
 | 
						|
+			<0 0x10001000 0 0x1600>;  /*TOPCKGEN_BASE             */
 | 
						|
+		clocks = <&infracfg CLK_INFRA_CONNMCU>;
 | 
						|
+		clock-names = "consysbus";
 | 
						|
+		power-domains = <&scpsys MT2701_POWER_DOMAIN_CONN>;
 | 
						|
+		interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_LOW>,  /* BGF_EINT */
 | 
						|
+					<GIC_SPI 163 IRQ_TYPE_LEVEL_LOW>;  /* WDT_EINT */
 | 
						|
+		resets = <&watchdog MT2701_TOPRGU_CONN_MCU_RST>;
 | 
						|
+		reset-names = "connsys";
 | 
						|
+		status="disabled";
 | 
						|
+	};
 | 
						|
+	wifi:wifi@180f0000 {
 | 
						|
+		compatible = "mediatek,mt7623-wifi",
 | 
						|
+					"mediatek,wifi";
 | 
						|
+		reg = <0 0x180f0000 0 0x005c>;
 | 
						|
+		interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_LOW>;
 | 
						|
+		clocks = <&pericfg CLK_PERI_AP_DMA>;
 | 
						|
+		clock-names = "wifi-dma";
 | 
						|
+	};
 | 
						|
+
 | 
						|
 	hifsys: syscon@1a000000 {
 | 
						|
 		compatible = "mediatek,mt7623-hifsys",
 | 
						|
 			     "mediatek,mt2701-hifsys",
 | 
						|
diff --git a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts
 | 
						|
index 2b760f90f38c..465fb887b2ca 100644
 | 
						|
--- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts
 | 
						|
+++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts
 | 
						|
@@ -84,6 +84,18 @@
 | 
						|
 		};
 | 
						|
 	};
 | 
						|
 
 | 
						|
+	reserved-memory {
 | 
						|
+		#address-cells = <2>;
 | 
						|
+		#size-cells = <2>;
 | 
						|
+		ranges;
 | 
						|
+		consys-reserve-memory {
 | 
						|
+			compatible = "mediatek,consys-reserve-memory";
 | 
						|
+			no-map;
 | 
						|
+			size = <0 0x100000>;
 | 
						|
+			alignment = <0 0x100000>;
 | 
						|
+		};
 | 
						|
+	};
 | 
						|
+
 | 
						|
 	leds {
 | 
						|
 		compatible = "gpio-leds";
 | 
						|
 		pinctrl-names = "default";
 | 
						|
@@ -259,6 +271,36 @@
 | 
						|
 	};
 | 
						|
 };
 | 
						|
 
 | 
						|
+&pio {
 | 
						|
+	consys_pins_default: consys_pins_default {
 | 
						|
+		adie {
 | 
						|
+			pinmux = <MT7623_PIN_60_WB_RSTB_FUNC_WB_RSTB>,
 | 
						|
+				<MT7623_PIN_61_GPIO61_FUNC_TEST_FD>,
 | 
						|
+				<MT7623_PIN_62_GPIO62_FUNC_TEST_FC>,
 | 
						|
+				<MT7623_PIN_63_WB_SCLK_FUNC_WB_SCLK>,
 | 
						|
+				<MT7623_PIN_64_WB_SDATA_FUNC_WB_SDATA>,
 | 
						|
+				<MT7623_PIN_65_WB_SEN_FUNC_WB_SEN>,
 | 
						|
+				<MT7623_PIN_66_WB_CRTL0_FUNC_WB_CRTL0>,
 | 
						|
+				<MT7623_PIN_67_WB_CRTL1_FUNC_WB_CRTL1>,
 | 
						|
+				<MT7623_PIN_68_WB_CRTL2_FUNC_WB_CRTL2>,
 | 
						|
+				<MT7623_PIN_69_WB_CRTL3_FUNC_WB_CRTL3>,
 | 
						|
+				<MT7623_PIN_70_WB_CRTL4_FUNC_WB_CRTL4>,
 | 
						|
+				<MT7623_PIN_71_WB_CRTL5_FUNC_WB_CRTL5>;
 | 
						|
+				bias-disable;
 | 
						|
+		};
 | 
						|
+	};
 | 
						|
+};
 | 
						|
+&consys {
 | 
						|
+	mediatek,pwrap-regmap = <&pwrap>;
 | 
						|
+	pinctrl-names = "default";
 | 
						|
+	pinctrl-0 = <&consys_pins_default>;
 | 
						|
+	vcn18-supply = <&mt6323_vcn18_reg>;
 | 
						|
+	vcn28-supply = <&mt6323_vcn28_reg>;
 | 
						|
+	vcn33_bt-supply = <&mt6323_vcn33_bt_reg>;
 | 
						|
+	vcn33_wifi-supply = <&mt6323_vcn33_wifi_reg>;
 | 
						|
+	status = "okay";
 | 
						|
+};
 | 
						|
+
 | 
						|
 &pcie {
 | 
						|
 	pinctrl-names = "default";
 | 
						|
 	pinctrl-0 = <&pcie_default>;
 | 
						|
diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
 | 
						|
index 4e931fdf4d09..6600396ee299 100644
 | 
						|
--- a/drivers/soc/mediatek/mtk-pmic-wrap.c
 | 
						|
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
 | 
						|
@@ -1530,6 +1530,18 @@ static const struct of_device_id of_pwrap_match_tbl[] = {
 | 
						|
 };
 | 
						|
 MODULE_DEVICE_TABLE(of, of_pwrap_match_tbl);
 | 
						|
 
 | 
						|
+struct regmap *pwrap_node_to_regmap(struct device_node *np)
 | 
						|
+{
 | 
						|
+	struct platform_device *pdev;
 | 
						|
+	struct pmic_wrapper *wrp;
 | 
						|
+	pdev = of_find_device_by_node(np);
 | 
						|
+	if (!pdev)
 | 
						|
+		return ERR_PTR(-ENODEV);
 | 
						|
+	wrp = platform_get_drvdata(pdev);
 | 
						|
+	return wrp->regmap;
 | 
						|
+}
 | 
						|
+EXPORT_SYMBOL_GPL(pwrap_node_to_regmap);
 | 
						|
+
 | 
						|
 static int pwrap_probe(struct platform_device *pdev)
 | 
						|
 {
 | 
						|
 	int ret, irq;
 | 
						|
diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c
 | 
						|
index 4baf64f21aa1..6a361f808aed 100644
 | 
						|
--- a/drivers/watchdog/mtk_wdt.c
 | 
						|
+++ b/drivers/watchdog/mtk_wdt.c
 | 
						|
@@ -1,4 +1,3 @@
 | 
						|
-// SPDX-License-Identifier: GPL-2.0+
 | 
						|
 /*
 | 
						|
  * Mediatek Watchdog Driver
 | 
						|
  *
 | 
						|
@@ -6,20 +5,51 @@
 | 
						|
  *
 | 
						|
  * Matthias Brugger <matthias.bgg@gmail.com>
 | 
						|
  *
 | 
						|
+ * This program is free software; you can redistribute it and/or modify
 | 
						|
+ * it under the terms of the GNU General Public License as published by
 | 
						|
+ * the Free Software Foundation; either version 2 of the License, or
 | 
						|
+ * (at your option) any later version.
 | 
						|
+ *
 | 
						|
+ * This program is distributed in the hope that it will be useful,
 | 
						|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
+ * GNU General Public License for more details.
 | 
						|
+ *
 | 
						|
  * Based on sunxi_wdt.c
 | 
						|
  */
 | 
						|
 
 | 
						|
 #include <linux/err.h>
 | 
						|
 #include <linux/init.h>
 | 
						|
 #include <linux/io.h>
 | 
						|
+#include <linux/interrupt.h>
 | 
						|
 #include <linux/kernel.h>
 | 
						|
 #include <linux/module.h>
 | 
						|
 #include <linux/moduleparam.h>
 | 
						|
+#include <linux/init.h>
 | 
						|
+#include <linux/proc_fs.h>
 | 
						|
+#include <linux/uaccess.h>
 | 
						|
 #include <linux/of.h>
 | 
						|
+#include <linux/of_irq.h>
 | 
						|
 #include <linux/platform_device.h>
 | 
						|
+#ifdef CONFIG_FIQ_GLUE
 | 
						|
+#include <linux/irqchip/mtk-gic-extend.h>
 | 
						|
+#include <mt-plat/aee.h>
 | 
						|
+#endif
 | 
						|
 #include <linux/types.h>
 | 
						|
 #include <linux/watchdog.h>
 | 
						|
+#include <linux/notifier.h>
 | 
						|
+#include <linux/reboot.h>
 | 
						|
 #include <linux/delay.h>
 | 
						|
+#include <linux/reset-controller.h>
 | 
						|
+#include <linux/reset.h>
 | 
						|
+#include <linux/sched.h>
 | 
						|
+#include <linux/sched/debug.h>
 | 
						|
+#include <linux/sched/signal.h>
 | 
						|
+#include <asm/system_misc.h>
 | 
						|
+#include <linux/seq_file.h>
 | 
						|
+#ifdef CONFIG_MT6397_MISC
 | 
						|
+#include <linux/mfd/mt6397/rtc_misc.h>
 | 
						|
+#endif
 | 
						|
 
 | 
						|
 #define WDT_MAX_TIMEOUT		31
 | 
						|
 #define WDT_MIN_TIMEOUT		1
 | 
						|
@@ -38,37 +68,167 @@
 | 
						|
 #define WDT_MODE_EXRST_EN	(1 << 2)
 | 
						|
 #define WDT_MODE_IRQ_EN		(1 << 3)
 | 
						|
 #define WDT_MODE_AUTO_START	(1 << 4)
 | 
						|
+#define WDT_MODE_IRQ_LVL	(1 << 5)
 | 
						|
 #define WDT_MODE_DUAL_EN	(1 << 6)
 | 
						|
 #define WDT_MODE_KEY		0x22000000
 | 
						|
 
 | 
						|
+#define WDT_STATUS		0x0c
 | 
						|
+#define WDT_NONRST_REG		0x20
 | 
						|
+#define WDT_NONRST_REG2		0x24
 | 
						|
+
 | 
						|
 #define WDT_SWRST		0x14
 | 
						|
 #define WDT_SWRST_KEY		0x1209
 | 
						|
 
 | 
						|
+#define WDT_SWSYSRST		0x18
 | 
						|
+#define WDT_SWSYSRST_KEY	0x88000000
 | 
						|
+
 | 
						|
+#define WDT_REQ_MODE 0x30
 | 
						|
+#define WDT_REQ_MODE_KEY 0x33000000
 | 
						|
+#define WDT_REQ_IRQ_EN 0x34
 | 
						|
+#define WDT_REQ_IRQ_KEY 0x44000000
 | 
						|
+#define WDT_REQ_MODE_DEBUG_EN 0x80000
 | 
						|
+
 | 
						|
+
 | 
						|
 #define DRV_NAME		"mtk-wdt"
 | 
						|
-#define DRV_VERSION		"1.0"
 | 
						|
+#define DRV_VERSION		"2.0"
 | 
						|
 
 | 
						|
 static bool nowayout = WATCHDOG_NOWAYOUT;
 | 
						|
-static unsigned int timeout;
 | 
						|
+static unsigned int timeout = WDT_MAX_TIMEOUT;
 | 
						|
+
 | 
						|
+struct toprgu_reset {
 | 
						|
+	spinlock_t lock;
 | 
						|
+	void __iomem *toprgu_swrst_base;
 | 
						|
+	int regofs;
 | 
						|
+	struct reset_controller_dev rcdev;
 | 
						|
+};
 | 
						|
 
 | 
						|
 struct mtk_wdt_dev {
 | 
						|
 	struct watchdog_device wdt_dev;
 | 
						|
 	void __iomem *wdt_base;
 | 
						|
+	int wdt_irq_id;
 | 
						|
+	struct notifier_block restart_handler;
 | 
						|
+	struct toprgu_reset reset_controller;
 | 
						|
 };
 | 
						|
 
 | 
						|
-static int mtk_wdt_restart(struct watchdog_device *wdt_dev,
 | 
						|
-			   unsigned long action, void *data)
 | 
						|
+static void __iomem *toprgu_base;
 | 
						|
+static struct watchdog_device *wdt_dev;
 | 
						|
+
 | 
						|
+static int toprgu_reset_assert(struct reset_controller_dev *rcdev,
 | 
						|
+			      unsigned long id)
 | 
						|
 {
 | 
						|
-	struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
 | 
						|
+	unsigned int tmp;
 | 
						|
+	unsigned long flags;
 | 
						|
+	struct toprgu_reset *data = container_of(rcdev, struct toprgu_reset, rcdev);
 | 
						|
+
 | 
						|
+	spin_lock_irqsave(&data->lock, flags);
 | 
						|
+
 | 
						|
+	tmp = __raw_readl(data->toprgu_swrst_base + data->regofs);
 | 
						|
+	tmp |= BIT(id);
 | 
						|
+	tmp |= WDT_SWSYSRST_KEY;
 | 
						|
+	writel(tmp, data->toprgu_swrst_base + data->regofs);
 | 
						|
+
 | 
						|
+	spin_unlock_irqrestore(&data->lock, flags);
 | 
						|
+
 | 
						|
+	return 0;
 | 
						|
+}
 | 
						|
+
 | 
						|
+static int toprgu_reset_deassert(struct reset_controller_dev *rcdev,
 | 
						|
+				unsigned long id)
 | 
						|
+{
 | 
						|
+	unsigned int tmp;
 | 
						|
+	unsigned long flags;
 | 
						|
+	struct toprgu_reset *data = container_of(rcdev, struct toprgu_reset, rcdev);
 | 
						|
+
 | 
						|
+	spin_lock_irqsave(&data->lock, flags);
 | 
						|
+
 | 
						|
+	tmp = __raw_readl(data->toprgu_swrst_base + data->regofs);
 | 
						|
+	tmp &= ~BIT(id);
 | 
						|
+	tmp |= WDT_SWSYSRST_KEY;
 | 
						|
+	writel(tmp, data->toprgu_swrst_base + data->regofs);
 | 
						|
+
 | 
						|
+	spin_unlock_irqrestore(&data->lock, flags);
 | 
						|
+
 | 
						|
+	return 0;
 | 
						|
+}
 | 
						|
+
 | 
						|
+static int toprgu_reset(struct reset_controller_dev *rcdev,
 | 
						|
+			      unsigned long id)
 | 
						|
+{
 | 
						|
+	int ret;
 | 
						|
+
 | 
						|
+	ret = toprgu_reset_assert(rcdev, id);
 | 
						|
+	if (ret)
 | 
						|
+		return ret;
 | 
						|
+
 | 
						|
+	return toprgu_reset_deassert(rcdev, id);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static struct reset_control_ops toprgu_reset_ops = {
 | 
						|
+	.assert = toprgu_reset_assert,
 | 
						|
+	.deassert = toprgu_reset_deassert,
 | 
						|
+	.reset = toprgu_reset,
 | 
						|
+};
 | 
						|
+
 | 
						|
+static void toprgu_register_reset_controller(struct platform_device *pdev, int regofs)
 | 
						|
+{
 | 
						|
+	int ret;
 | 
						|
+	struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev);
 | 
						|
+
 | 
						|
+	spin_lock_init(&mtk_wdt->reset_controller.lock);
 | 
						|
+
 | 
						|
+	mtk_wdt->reset_controller.toprgu_swrst_base = mtk_wdt->wdt_base;
 | 
						|
+	mtk_wdt->reset_controller.regofs = regofs;
 | 
						|
+	mtk_wdt->reset_controller.rcdev.owner = THIS_MODULE;
 | 
						|
+	mtk_wdt->reset_controller.rcdev.nr_resets = 15;
 | 
						|
+	mtk_wdt->reset_controller.rcdev.ops = &toprgu_reset_ops;
 | 
						|
+	mtk_wdt->reset_controller.rcdev.of_node = pdev->dev.of_node;
 | 
						|
+
 | 
						|
+	ret = reset_controller_register(&mtk_wdt->reset_controller.rcdev);
 | 
						|
+	if (ret)
 | 
						|
+		pr_err("could not register toprgu reset controller: %d\n", ret);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static int mtk_reset_handler(struct notifier_block *this, unsigned long mode,
 | 
						|
+				void *cmd)
 | 
						|
+{
 | 
						|
+	struct mtk_wdt_dev *mtk_wdt;
 | 
						|
 	void __iomem *wdt_base;
 | 
						|
+	u32 reg;
 | 
						|
 
 | 
						|
+	mtk_wdt = container_of(this, struct mtk_wdt_dev, restart_handler);
 | 
						|
 	wdt_base = mtk_wdt->wdt_base;
 | 
						|
 
 | 
						|
-	while (1) {
 | 
						|
-		writel(WDT_SWRST_KEY, wdt_base + WDT_SWRST);
 | 
						|
-		mdelay(5);
 | 
						|
+	/* WDT_STATUS will be cleared to  zero after writing to WDT_MODE, so we backup it in WDT_NONRST_REG,
 | 
						|
+	  * and then print it out in mtk_wdt_probe() after reset
 | 
						|
+	  */
 | 
						|
+	writel(__raw_readl(wdt_base + WDT_STATUS), wdt_base + WDT_NONRST_REG);
 | 
						|
+
 | 
						|
+	reg = ioread32(wdt_base + WDT_MODE);
 | 
						|
+	reg &= ~(WDT_MODE_DUAL_EN | WDT_MODE_IRQ_EN | WDT_MODE_EN);
 | 
						|
+	reg |= WDT_MODE_KEY;
 | 
						|
+	iowrite32(reg, wdt_base + WDT_MODE);
 | 
						|
+
 | 
						|
+	if (cmd && !strcmp(cmd, "rpmbpk")) {
 | 
						|
+		iowrite32(ioread32(wdt_base + WDT_NONRST_REG2) | (1 << 0), wdt_base + WDT_NONRST_REG2);
 | 
						|
+	} else if (cmd && !strcmp(cmd, "recovery")) {
 | 
						|
+		iowrite32(ioread32(wdt_base + WDT_NONRST_REG2) | (1 << 1), wdt_base + WDT_NONRST_REG2);
 | 
						|
+		#ifdef CONFIG_MT6397_MISC
 | 
						|
+		mtk_misc_mark_recovery();
 | 
						|
+		#endif
 | 
						|
+	} else if (cmd && !strcmp(cmd, "bootloader")) {
 | 
						|
+		iowrite32(ioread32(wdt_base + WDT_NONRST_REG2) | (1 << 2), wdt_base + WDT_NONRST_REG2);
 | 
						|
+		#ifdef CONFIG_MT6397_MISC
 | 
						|
+		mtk_misc_mark_fast();
 | 
						|
+		#endif
 | 
						|
 	}
 | 
						|
 
 | 
						|
-	return 0;
 | 
						|
+	if (!arm_pm_restart) {
 | 
						|
+		while (1) {
 | 
						|
+			writel(WDT_SWRST_KEY, wdt_base + WDT_SWRST);
 | 
						|
+			mdelay(5);
 | 
						|
+		}
 | 
						|
+	}
 | 
						|
+	return NOTIFY_DONE;
 | 
						|
 }
 | 
						|
 
 | 
						|
 static int mtk_wdt_ping(struct watchdog_device *wdt_dev)
 | 
						|
@@ -77,6 +237,7 @@ static int mtk_wdt_ping(struct watchdog_device *wdt_dev)
 | 
						|
 	void __iomem *wdt_base = mtk_wdt->wdt_base;
 | 
						|
 
 | 
						|
 	iowrite32(WDT_RST_RELOAD, wdt_base + WDT_RST);
 | 
						|
+	printk_deferred("[WDK]: kick Ex WDT\n");
 | 
						|
 
 | 
						|
 	return 0;
 | 
						|
 }
 | 
						|
@@ -128,7 +289,8 @@ static int mtk_wdt_start(struct watchdog_device *wdt_dev)
 | 
						|
 		return ret;
 | 
						|
 
 | 
						|
 	reg = ioread32(wdt_base + WDT_MODE);
 | 
						|
-	reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN);
 | 
						|
+	reg |= (WDT_MODE_DUAL_EN | WDT_MODE_IRQ_EN | WDT_MODE_EXRST_EN);
 | 
						|
+	reg &= ~(WDT_MODE_IRQ_LVL | WDT_MODE_EXT_POL_HIGH);
 | 
						|
 	reg |= (WDT_MODE_EN | WDT_MODE_KEY);
 | 
						|
 	iowrite32(reg, wdt_base + WDT_MODE);
 | 
						|
 
 | 
						|
@@ -148,13 +310,56 @@ static const struct watchdog_ops mtk_wdt_ops = {
 | 
						|
 	.stop		= mtk_wdt_stop,
 | 
						|
 	.ping		= mtk_wdt_ping,
 | 
						|
 	.set_timeout	= mtk_wdt_set_timeout,
 | 
						|
-	.restart	= mtk_wdt_restart,
 | 
						|
 };
 | 
						|
 
 | 
						|
+#ifdef CONFIG_FIQ_GLUE
 | 
						|
+static void wdt_fiq(void *arg, void *regs, void *svc_sp)
 | 
						|
+{
 | 
						|
+	unsigned int wdt_mode_val;
 | 
						|
+	void __iomem *wdt_base = ((struct mtk_wdt_dev *)arg)->wdt_base;
 | 
						|
+
 | 
						|
+	wdt_mode_val = __raw_readl(wdt_base + WDT_STATUS);
 | 
						|
+	writel(wdt_mode_val, wdt_base + WDT_NONRST_REG);
 | 
						|
+
 | 
						|
+	aee_wdt_fiq_info(arg, regs, svc_sp);
 | 
						|
+}
 | 
						|
+#else
 | 
						|
+static void wdt_report_info(void)
 | 
						|
+{
 | 
						|
+	struct task_struct *task;
 | 
						|
+
 | 
						|
+	task = &init_task;
 | 
						|
+	pr_debug("Qwdt: -- watchdog time out\n");
 | 
						|
+
 | 
						|
+	for_each_process(task) {
 | 
						|
+		if (task->state == 0) {
 | 
						|
+			pr_debug("PID: %d, name: %s\n backtrace:\n", task->pid, task->comm);
 | 
						|
+			show_stack(task, NULL);
 | 
						|
+			pr_debug("\n");
 | 
						|
+		}
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	pr_debug("backtrace of current task:\n");
 | 
						|
+	show_stack(NULL, NULL);
 | 
						|
+	pr_debug("Qwdt: -- watchdog time out\n");
 | 
						|
+}
 | 
						|
+
 | 
						|
+static irqreturn_t mtk_wdt_isr(int irq, void *dev_id)
 | 
						|
+{
 | 
						|
+	pr_err("fwq mtk_wdt_isr\n");
 | 
						|
+
 | 
						|
+	wdt_report_info();
 | 
						|
+	BUG();
 | 
						|
+
 | 
						|
+	return IRQ_HANDLED;
 | 
						|
+}
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 static int mtk_wdt_probe(struct platform_device *pdev)
 | 
						|
 {
 | 
						|
 	struct mtk_wdt_dev *mtk_wdt;
 | 
						|
 	struct resource *res;
 | 
						|
+	unsigned int tmp;
 | 
						|
 	int err;
 | 
						|
 
 | 
						|
 	mtk_wdt = devm_kzalloc(&pdev->dev, sizeof(*mtk_wdt), GFP_KERNEL);
 | 
						|
@@ -165,9 +370,32 @@ static int mtk_wdt_probe(struct platform_device *pdev)
 | 
						|
 
 | 
						|
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 | 
						|
 	mtk_wdt->wdt_base = devm_ioremap_resource(&pdev->dev, res);
 | 
						|
+
 | 
						|
 	if (IS_ERR(mtk_wdt->wdt_base))
 | 
						|
 		return PTR_ERR(mtk_wdt->wdt_base);
 | 
						|
 
 | 
						|
+	pr_err("MTK_WDT_NONRST_REG(%x)\n", __raw_readl(mtk_wdt->wdt_base + WDT_NONRST_REG));
 | 
						|
+
 | 
						|
+	mtk_wdt->wdt_irq_id = irq_of_parse_and_map(pdev->dev.of_node, 0);
 | 
						|
+	if (!mtk_wdt->wdt_irq_id) {
 | 
						|
+		pr_err("RGU get IRQ ID failed\n");
 | 
						|
+		return -ENODEV;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+#ifndef CONFIG_FIQ_GLUE
 | 
						|
+	err = request_irq(mtk_wdt->wdt_irq_id, (irq_handler_t)mtk_wdt_isr, IRQF_TRIGGER_NONE, DRV_NAME, mtk_wdt);
 | 
						|
+#else
 | 
						|
+	mtk_wdt->wdt_irq_id = get_hardware_irq(mtk_wdt->wdt_irq_id);
 | 
						|
+	err = request_fiq(mtk_wdt->wdt_irq_id, wdt_fiq, IRQF_TRIGGER_FALLING, mtk_wdt);
 | 
						|
+#endif
 | 
						|
+	if (err != 0) {
 | 
						|
+		pr_err("mtk_wdt_probe : failed to request irq (%d)\n", err);
 | 
						|
+		return err;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	toprgu_base = mtk_wdt->wdt_base;
 | 
						|
+	wdt_dev = &mtk_wdt->wdt_dev;
 | 
						|
+
 | 
						|
 	mtk_wdt->wdt_dev.info = &mtk_wdt_info;
 | 
						|
 	mtk_wdt->wdt_dev.ops = &mtk_wdt_ops;
 | 
						|
 	mtk_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT;
 | 
						|
@@ -177,7 +405,6 @@ static int mtk_wdt_probe(struct platform_device *pdev)
 | 
						|
 
 | 
						|
 	watchdog_init_timeout(&mtk_wdt->wdt_dev, timeout, &pdev->dev);
 | 
						|
 	watchdog_set_nowayout(&mtk_wdt->wdt_dev, nowayout);
 | 
						|
-	watchdog_set_restart_priority(&mtk_wdt->wdt_dev, 128);
 | 
						|
 
 | 
						|
 	watchdog_set_drvdata(&mtk_wdt->wdt_dev, mtk_wdt);
 | 
						|
 
 | 
						|
@@ -187,9 +414,40 @@ static int mtk_wdt_probe(struct platform_device *pdev)
 | 
						|
 	if (unlikely(err))
 | 
						|
 		return err;
 | 
						|
 
 | 
						|
+	mtk_wdt->restart_handler.notifier_call = mtk_reset_handler;
 | 
						|
+	mtk_wdt->restart_handler.priority = 128;
 | 
						|
+
 | 
						|
+	if (arm_pm_restart) {
 | 
						|
+		dev_info(&pdev->dev, "register restart_handler on reboot_notifier_list for psci reset\n");
 | 
						|
+		err = register_reboot_notifier(&mtk_wdt->restart_handler);
 | 
						|
+		if (err != 0)
 | 
						|
+			dev_warn(&pdev->dev,
 | 
						|
+				"cannot register reboot notifier (err=%d)\n", err);
 | 
						|
+	} else {
 | 
						|
+		err = register_restart_handler(&mtk_wdt->restart_handler);
 | 
						|
+		if (err)
 | 
						|
+			dev_warn(&pdev->dev,
 | 
						|
+				"cannot register restart handler (err=%d)\n", err);
 | 
						|
+	}
 | 
						|
+
 | 
						|
 	dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n",
 | 
						|
 			mtk_wdt->wdt_dev.timeout, nowayout);
 | 
						|
 
 | 
						|
+	writel(WDT_REQ_MODE_KEY | (__raw_readl(mtk_wdt->wdt_base + WDT_REQ_MODE) &
 | 
						|
+		(~WDT_REQ_MODE_DEBUG_EN)), mtk_wdt->wdt_base + WDT_REQ_MODE);
 | 
						|
+
 | 
						|
+	toprgu_register_reset_controller(pdev, WDT_SWSYSRST);
 | 
						|
+
 | 
						|
+	/* enable scpsys thermal and thermal_controller request, and set to reset directly mode */
 | 
						|
+	tmp = ioread32(mtk_wdt->wdt_base + WDT_REQ_MODE) | (1 << 18) | (1 << 0);
 | 
						|
+	tmp |= WDT_REQ_MODE_KEY;
 | 
						|
+	iowrite32(tmp, mtk_wdt->wdt_base + WDT_REQ_MODE);
 | 
						|
+
 | 
						|
+	tmp = ioread32(mtk_wdt->wdt_base + WDT_REQ_IRQ_EN);
 | 
						|
+	tmp &= ~((1 << 18) | (1 << 0));
 | 
						|
+	tmp |= WDT_REQ_IRQ_KEY;
 | 
						|
+	iowrite32(tmp, mtk_wdt->wdt_base + WDT_REQ_IRQ_EN);
 | 
						|
+
 | 
						|
 	return 0;
 | 
						|
 }
 | 
						|
 
 | 
						|
@@ -205,8 +463,12 @@ static int mtk_wdt_remove(struct platform_device *pdev)
 | 
						|
 {
 | 
						|
 	struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev);
 | 
						|
 
 | 
						|
+	unregister_restart_handler(&mtk_wdt->restart_handler);
 | 
						|
+
 | 
						|
 	watchdog_unregister_device(&mtk_wdt->wdt_dev);
 | 
						|
 
 | 
						|
+	reset_controller_unregister(&mtk_wdt->reset_controller.rcdev);
 | 
						|
+
 | 
						|
 	return 0;
 | 
						|
 }
 | 
						|
 
 | 
						|
@@ -258,6 +520,95 @@ static struct platform_driver mtk_wdt_driver = {
 | 
						|
 
 | 
						|
 module_platform_driver(mtk_wdt_driver);
 | 
						|
 
 | 
						|
+static int wk_proc_cmd_read(struct seq_file *s, void *v)
 | 
						|
+{
 | 
						|
+	unsigned int enabled = 1;
 | 
						|
+
 | 
						|
+	if (!(ioread32(toprgu_base + WDT_MODE) & WDT_MODE_EN))
 | 
						|
+		enabled = 0;
 | 
						|
+
 | 
						|
+	seq_printf(s, "enabled timeout\n%-4d %-8d\n", enabled, wdt_dev->timeout);
 | 
						|
+
 | 
						|
+	return 0;
 | 
						|
+}
 | 
						|
+
 | 
						|
+static int wk_proc_cmd_open(struct inode *inode, struct file *file)
 | 
						|
+{
 | 
						|
+	return single_open(file, wk_proc_cmd_read, NULL);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static ssize_t wk_proc_cmd_write(struct file *file, const char *buf, size_t count, loff_t *data)
 | 
						|
+{
 | 
						|
+	int ret;
 | 
						|
+	int enable;
 | 
						|
+	int timeout;
 | 
						|
+	char wk_cmd_buf[256];
 | 
						|
+
 | 
						|
+	if (count == 0)
 | 
						|
+		return -1;
 | 
						|
+
 | 
						|
+	if (count > 255)
 | 
						|
+		count = 255;
 | 
						|
+
 | 
						|
+	ret = copy_from_user(wk_cmd_buf, buf, count);
 | 
						|
+	if (ret < 0)
 | 
						|
+		return -1;
 | 
						|
+
 | 
						|
+	wk_cmd_buf[count] = '\0';
 | 
						|
+
 | 
						|
+	pr_debug("Write %s\n", wk_cmd_buf);
 | 
						|
+
 | 
						|
+	ret = sscanf(wk_cmd_buf, "%d %d", &enable, &timeout);
 | 
						|
+	if (ret != 2)
 | 
						|
+		pr_debug("%s: expect 2 numbers\n", __func__);
 | 
						|
+
 | 
						|
+	pr_debug("[WDK] enable=%d  timeout=%d\n", enable, timeout);
 | 
						|
+
 | 
						|
+	if (timeout > 20 && timeout <= WDT_MAX_TIMEOUT) {
 | 
						|
+		wdt_dev->timeout = timeout;
 | 
						|
+		mtk_wdt_set_timeout(wdt_dev, wdt_dev->timeout);
 | 
						|
+	} else {
 | 
						|
+		pr_err("[WDK] The timeout(%d) should bigger than 20 and not bigger than %d\n",
 | 
						|
+				timeout, WDT_MAX_TIMEOUT);
 | 
						|
+
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	if (enable == 1) {
 | 
						|
+		mtk_wdt_start(wdt_dev);
 | 
						|
+		set_bit(WDOG_ACTIVE, &wdt_dev->status);
 | 
						|
+		pr_err("[WDK] enable wdt\n");
 | 
						|
+	} else if (enable == 0) {
 | 
						|
+		mtk_wdt_stop(wdt_dev);
 | 
						|
+		clear_bit(WDOG_ACTIVE, &wdt_dev->status);
 | 
						|
+		pr_err("[WDK] disable wdt\n");
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	return count;
 | 
						|
+}
 | 
						|
+
 | 
						|
+static const struct file_operations wk_proc_cmd_fops = {
 | 
						|
+	.owner = THIS_MODULE,
 | 
						|
+	.open = wk_proc_cmd_open,
 | 
						|
+	.read = seq_read,
 | 
						|
+	.write = wk_proc_cmd_write,
 | 
						|
+	.llseek = seq_lseek,
 | 
						|
+	.release = single_release,
 | 
						|
+};
 | 
						|
+
 | 
						|
+static int __init wk_proc_init(void)
 | 
						|
+{
 | 
						|
+	struct proc_dir_entry *de = proc_create("wdk", 0660, NULL, &wk_proc_cmd_fops);
 | 
						|
+
 | 
						|
+	if (!de)
 | 
						|
+		pr_err("[wk_proc_init]: create /proc/wdk failed\n");
 | 
						|
+
 | 
						|
+	pr_debug("[WDK] Initialize proc\n");
 | 
						|
+
 | 
						|
+	return 0;
 | 
						|
+}
 | 
						|
+
 | 
						|
+late_initcall(wk_proc_init);
 | 
						|
+
 | 
						|
 module_param(timeout, uint, 0);
 | 
						|
 MODULE_PARM_DESC(timeout, "Watchdog heartbeat in seconds");
 | 
						|
 
 | 
						|
diff --git a/include/linux/wakelock.h b/include/linux/wakelock.h
 | 
						|
new file mode 100644
 | 
						|
index 000000000000..f4a698a22880
 | 
						|
--- /dev/null
 | 
						|
+++ b/include/linux/wakelock.h
 | 
						|
@@ -0,0 +1,67 @@
 | 
						|
+/* include/linux/wakelock.h
 | 
						|
+ *
 | 
						|
+ * Copyright (C) 2007-2012 Google, Inc.
 | 
						|
+ *
 | 
						|
+ * 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 _LINUX_WAKELOCK_H
 | 
						|
+#define _LINUX_WAKELOCK_H
 | 
						|
+
 | 
						|
+#include <linux/ktime.h>
 | 
						|
+#include <linux/device.h>
 | 
						|
+
 | 
						|
+/* A wake_lock prevents the system from entering suspend or other low power
 | 
						|
+ * states when active. If the type is set to WAKE_LOCK_SUSPEND, the wake_lock
 | 
						|
+ * prevents a full system suspend.
 | 
						|
+ */
 | 
						|
+
 | 
						|
+enum {
 | 
						|
+	WAKE_LOCK_SUSPEND, /* Prevent suspend */
 | 
						|
+	WAKE_LOCK_TYPE_COUNT
 | 
						|
+};
 | 
						|
+
 | 
						|
+struct wake_lock {
 | 
						|
+	struct wakeup_source ws;
 | 
						|
+};
 | 
						|
+
 | 
						|
+static inline void wake_lock_init(struct wake_lock *lock, int type,
 | 
						|
+				  const char *name)
 | 
						|
+{
 | 
						|
+	wakeup_source_init(&lock->ws, name);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static inline void wake_lock_destroy(struct wake_lock *lock)
 | 
						|
+{
 | 
						|
+	wakeup_source_trash(&lock->ws);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static inline void wake_lock(struct wake_lock *lock)
 | 
						|
+{
 | 
						|
+	__pm_stay_awake(&lock->ws);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static inline void wake_lock_timeout(struct wake_lock *lock, long timeout)
 | 
						|
+{
 | 
						|
+	__pm_wakeup_event(&lock->ws, jiffies_to_msecs(timeout));
 | 
						|
+}
 | 
						|
+
 | 
						|
+static inline void wake_unlock(struct wake_lock *lock)
 | 
						|
+{
 | 
						|
+	__pm_relax(&lock->ws);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static inline int wake_lock_active(struct wake_lock *lock)
 | 
						|
+{
 | 
						|
+	return lock->ws.active;
 | 
						|
+}
 | 
						|
+
 | 
						|
+#endif
 | 
						|
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
 | 
						|
index decf6012a401..6471da92334a 100644
 | 
						|
--- a/include/net/genetlink.h
 | 
						|
+++ b/include/net/genetlink.h
 | 
						|
@@ -144,6 +144,50 @@ struct genl_ops {
 | 
						|
 };
 | 
						|
 
 | 
						|
 int genl_register_family(struct genl_family *family);
 | 
						|
+
 | 
						|
+/**
 | 
						|
+ * genl_register_family_with_ops - register a generic netlink family with ops
 | 
						|
+ * @family: generic netlink family
 | 
						|
+ * @ops: operations to be registered
 | 
						|
+ * @n_ops: number of elements to register
 | 
						|
+ *
 | 
						|
+ * Registers the specified family and operations from the specified table.
 | 
						|
+ * Only one family may be registered with the same family name or identifier.
 | 
						|
+ *
 | 
						|
+ * The family id may equal GENL_ID_GENERATE causing an unique id to
 | 
						|
+ * be automatically generated and assigned.
 | 
						|
+ *
 | 
						|
+ * Either a doit or dumpit callback must be specified for every registered
 | 
						|
+ * operation or the function will fail. Only one operation structure per
 | 
						|
+ * command identifier may be registered.
 | 
						|
+ *
 | 
						|
+ * See include/net/genetlink.h for more documenation on the operations
 | 
						|
+ * structure.
 | 
						|
+ *
 | 
						|
+ * Return 0 on success or a negative error code.
 | 
						|
+ */
 | 
						|
+static inline int
 | 
						|
+_genl_register_family_with_ops_grps(struct genl_family *family,
 | 
						|
+				    const struct genl_ops *ops, size_t n_ops,
 | 
						|
+				    const struct genl_multicast_group *mcgrps,
 | 
						|
+				    size_t n_mcgrps)
 | 
						|
+{
 | 
						|
+	family->module = THIS_MODULE;
 | 
						|
+	family->ops = ops;
 | 
						|
+	family->n_ops = n_ops;
 | 
						|
+	family->mcgrps = mcgrps;
 | 
						|
+	family->n_mcgrps = n_mcgrps;
 | 
						|
+	return genl_register_family(family);
 | 
						|
+}
 | 
						|
+#define genl_register_family_with_ops(family, ops)			\
 | 
						|
+	_genl_register_family_with_ops_grps((family),			\
 | 
						|
+					    (ops), ARRAY_SIZE(ops),	\
 | 
						|
+					    NULL, 0)
 | 
						|
+#define genl_register_family_with_ops_groups(family, ops, grps)	\
 | 
						|
+	_genl_register_family_with_ops_grps((family),			\
 | 
						|
+					    (ops), ARRAY_SIZE(ops),	\
 | 
						|
+					    (grps), ARRAY_SIZE(grps))
 | 
						|
+
 | 
						|
 int genl_unregister_family(const struct genl_family *family);
 | 
						|
 void genl_notify(const struct genl_family *family, struct sk_buff *skb,
 | 
						|
 		 struct genl_info *info, u32 group, gfp_t flags);
 | 
						|
diff --git a/include/soc/mediatek/pmic_wrap.h b/include/soc/mediatek/pmic_wrap.h
 | 
						|
new file mode 100644
 | 
						|
index 000000000000..5b5c85272c58
 | 
						|
--- /dev/null
 | 
						|
+++ b/include/soc/mediatek/pmic_wrap.h
 | 
						|
@@ -0,0 +1,19 @@
 | 
						|
+/*
 | 
						|
+ * Copyright (C) 2015 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.
 | 
						|
+ */
 | 
						|
+
 | 
						|
+#ifndef __SOC_MEDIATEK_PMIC_WRAP_H
 | 
						|
+#define __SOC_MEDIATEK_PMIC_WRAP_H
 | 
						|
+
 | 
						|
+extern struct regmap *pwrap_node_to_regmap(struct device_node *np);
 | 
						|
+
 | 
						|
+#endif /* __SOC_MEDIATEK_PMIC_WRAP_H */
 | 
						|
diff --git a/include/uapi/linux/genetlink.h b/include/uapi/linux/genetlink.h
 | 
						|
index 877f7fa95466..6a176b3d43f9 100644
 | 
						|
--- a/include/uapi/linux/genetlink.h
 | 
						|
+++ b/include/uapi/linux/genetlink.h
 | 
						|
@@ -27,6 +27,7 @@ struct genlmsghdr {
 | 
						|
 /*
 | 
						|
  * List of reserved static generic netlink identifiers:
 | 
						|
  */
 | 
						|
+#define GENL_ID_GENERATE	0
 | 
						|
 #define GENL_ID_CTRL		NLMSG_MIN_TYPE
 | 
						|
 #define GENL_ID_VFS_DQUOT	(NLMSG_MIN_TYPE + 1)
 | 
						|
 #define GENL_ID_PMCRAID		(NLMSG_MIN_TYPE + 2)
 | 
						|
-- 
 | 
						|
2.19.1
 | 
						|
 |