From 83ffbaceffed1cd47a6f67fb20e39737dfb2d01a Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Tue, 28 Aug 2018 18:14:56 +0200 Subject: [PATCH] [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 04228cf9ddbbc..af6b6228f8a80 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 = ; + #reset-cells = <1>; }; timer: timer@10008000 { @@ -494,13 +496,26 @@ "mediatek,mtk-btif"; reg = <0 0x1100c000 0 0x1000>; interrupts = ; - 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 = ; + status = "okay"; + }; + btif_rx: btif_rx@11000800 { + compatible = "mediatek,btif_rx"; + reg = <0 0x11000800 0 0x80>; + interrupts = ; + 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 = , /* BGF_EINT */ + ; /* 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 = ; + 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 2b760f90f38c8..465fb887b2ca6 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 = , + , + , + , + , + , + , + , + , + , + , + ; + 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 4e931fdf4d091..6600396ee2993 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 4baf64f21aa11..6a361f808aed1 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 * + * 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 #include #include +#include #include #include #include +#include +#include +#include #include +#include #include +#ifdef CONFIG_FIQ_GLUE +#include +#include +#endif #include #include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_MT6397_MISC +#include +#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 0000000000000..f4a698a228803 --- /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 +#include + +/* 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 decf6012a4016..6471da92334ad 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 0000000000000..5b5c85272c58b --- /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 877f7fa954666..6a176b3d43f9b 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)