Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1305741 > unrolled thread
| Started by | richard.dorsch@gmail.com |
|---|---|
| First post | 2016-01-11 00:40 +0100 |
| Last post | 2016-01-11 02:00 +0100 |
| Articles | 5 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH v3 0/6] Add Advantech iManager EC driver set richard.dorsch@gmail.com - 2016-01-11 00:40 +0100
[PATCH v3 6/6] Add Advantech iManager Watchdog driver richard.dorsch@gmail.com - 2016-01-11 00:40 +0100
[PATCH v3 5/6] Add Advantech iManager Backlight driver richard.dorsch@gmail.com - 2016-01-11 00:40 +0100
Re: [PATCH v3 5/6] Add Advantech iManager Backlight driver Lee Jones <lee.jones@linaro.org> - 2016-01-11 11:30 +0100
Re: [PATCH v3 0/6] Add Advantech iManager EC driver set Guenter Roeck <linux@roeck-us.net> - 2016-01-11 02:00 +0100
| From | richard.dorsch@gmail.com |
|---|---|
| Date | 2016-01-11 00:40 +0100 |
| Subject | [PATCH v3 0/6] Add Advantech iManager EC driver set |
| Message-ID | <qPxKy-2yK-7@gated-at.bofh.it> |
From: Richard Vidal-Dorsch <richard.dorsch@gmail.com> The Advantech iManager is an embedded controller (depending on board type, ITE it8518/it8528) on which a custom firmware runs. All drivers (GPIO, I2C, HWmon, Watchdog, and backlight) are being managed by the imanager mfd driver. The imanager mfd driver acts as a 'gateway' and handles all communications between the EC and sub-drivers (GPIO, I2C, ...). The feature specific communication portions are split up into core files such as imanager-ec-[gpio, i2c, ...]. Changes from v2: I forgot to remove .owner from other drivers too... silly me! - Remove .owner from platform_driver in: drivers/gpio/imanager-bl drivers/gpio/imanager-core.c drivers/gpio/imanager-i2c.c drivers/gpio/imanager-hwmon.c Changes from v1: - Remove .owner from platform_driver in drivers/gpio/imanager-gpio.c - Remove .owner from platform_driver in drivers/gpio/imanager-wdt.c - Replace 2015 by 2016 in all files Richard Vidal-Dorsch (6): Add Advantech iManager MFD core driver Add Advantech iManager GPIO driver Add Advantech iManager HWmon driver Add Advantech iManager I2C driver Add Advantech iManager Backlight driver Add Advantech iManager Watchdog driver Documentation/devicetree/bindings/mfd/imanager.txt | 33 + Documentation/hwmon/imanager | 59 + Documentation/i2c/busses/i2c-imanager | 48 + MAINTAINERS | 13 + drivers/gpio/Kconfig | 8 + drivers/gpio/Makefile | 2 + drivers/gpio/imanager-ec-gpio.c | 98 ++ drivers/gpio/imanager-gpio.c | 181 +++ drivers/hwmon/Kconfig | 12 + drivers/hwmon/Makefile | 2 + drivers/hwmon/imanager-ec-hwmon.c | 606 +++++++++ drivers/hwmon/imanager-hwmon.c | 1057 +++++++++++++++ drivers/i2c/busses/Kconfig | 11 + drivers/i2c/busses/Makefile | 2 + drivers/i2c/busses/imanager-ec-i2c.c | 466 +++++++ drivers/i2c/busses/imanager-i2c.c | 239 ++++ drivers/mfd/Kconfig | 20 + drivers/mfd/Makefile | 2 + drivers/mfd/imanager-core.c | 287 +++++ drivers/mfd/imanager-ec.c | 1345 ++++++++++++++++++++ drivers/video/backlight/Kconfig | 12 + drivers/video/backlight/Makefile | 2 + drivers/video/backlight/imanager-bl.c | 198 +++ drivers/video/backlight/imanager-ec-bl.c | 118 ++ drivers/watchdog/Kconfig | 12 + drivers/watchdog/Makefile | 2 + drivers/watchdog/imanager-ec-wdt.c | 170 +++ drivers/watchdog/imanager-wdt.c | 333 +++++ include/linux/mfd/imanager/backlight.h | 37 + include/linux/mfd/imanager/core.h | 31 + include/linux/mfd/imanager/ec.h | 210 +++ include/linux/mfd/imanager/gpio.h | 27 + include/linux/mfd/imanager/hwmon.h | 120 ++ include/linux/mfd/imanager/i2c.h | 55 + include/linux/mfd/imanager/wdt.h | 37 + 35 files changed, 5855 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/imanager.txt create mode 100644 Documentation/hwmon/imanager create mode 100644 Documentation/i2c/busses/i2c-imanager create mode 100644 drivers/gpio/imanager-ec-gpio.c create mode 100644 drivers/gpio/imanager-gpio.c create mode 100644 drivers/hwmon/imanager-ec-hwmon.c create mode 100644 drivers/hwmon/imanager-hwmon.c create mode 100644 drivers/i2c/busses/imanager-ec-i2c.c create mode 100644 drivers/i2c/busses/imanager-i2c.c create mode 100644 drivers/mfd/imanager-core.c create mode 100644 drivers/mfd/imanager-ec.c create mode 100644 drivers/video/backlight/imanager-bl.c create mode 100644 drivers/video/backlight/imanager-ec-bl.c create mode 100644 drivers/watchdog/imanager-ec-wdt.c create mode 100644 drivers/watchdog/imanager-wdt.c create mode 100644 include/linux/mfd/imanager/backlight.h create mode 100644 include/linux/mfd/imanager/core.h create mode 100644 include/linux/mfd/imanager/ec.h create mode 100644 include/linux/mfd/imanager/gpio.h create mode 100644 include/linux/mfd/imanager/hwmon.h create mode 100644 include/linux/mfd/imanager/i2c.h create mode 100644 include/linux/mfd/imanager/wdt.h -- 2.7.0
[toc] | [next] | [standalone]
| From | richard.dorsch@gmail.com |
|---|---|
| Date | 2016-01-11 00:40 +0100 |
| Subject | [PATCH v3 6/6] Add Advantech iManager Watchdog driver |
| Message-ID | <qPxKy-2yK-19@gated-at.bofh.it> |
| In reply to | #1305741 |
From: Richard Vidal-Dorsch <richard.dorsch@gmail.com>
Signed-off-by: Richard Vidal-Dorsch <richard.dorsch@gmail.com>
---
drivers/watchdog/Kconfig | 12 ++
drivers/watchdog/Makefile | 2 +
drivers/watchdog/imanager-ec-wdt.c | 170 +++++++++++++++++++
drivers/watchdog/imanager-wdt.c | 333 +++++++++++++++++++++++++++++++++++++
include/linux/mfd/imanager/wdt.h | 37 +++++
5 files changed, 554 insertions(+)
create mode 100644 drivers/watchdog/imanager-ec-wdt.c
create mode 100644 drivers/watchdog/imanager-wdt.c
create mode 100644 include/linux/mfd/imanager/wdt.h
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 1c427be..e555127 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -846,6 +846,18 @@ config ITCO_VENDOR_SUPPORT
devices. At this moment we only have additional support for some
SuperMicro Inc. motherboards.
+config IMANAGER_WDT
+ tristate "Advantech iManager Watchdog"
+ depends on MFD_IMANAGER
+ select WATCHDOG_CORE
+ help
+ This driver provides support for Advantech iManager watchdog
+ of Advantech SOM, MIO, AIMB, and PCM modules/boards.
+ Requires mfd-core and imanager-core to function properly.
+
+ This driver can also be built as a module. If so, the module
+ will be called imanager_wdt.
+
config IT8712F_WDT
tristate "IT8712F (Smart Guardian) Watchdog Timer"
depends on X86
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 53d4827..647eca87 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -100,6 +100,8 @@ obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o
ifeq ($(CONFIG_ITCO_VENDOR_SUPPORT),y)
obj-$(CONFIG_ITCO_WDT) += iTCO_vendor_support.o
endif
+imanager_wdt-objs := imanager-wdt.o imanager-ec-wdt.o
+obj-$(CONFIG_IMANAGER_WDT) += imanager_wdt.o
obj-$(CONFIG_IT8712F_WDT) += it8712f_wdt.o
obj-$(CONFIG_IT87_WDT) += it87_wdt.o
obj-$(CONFIG_HP_WATCHDOG) += hpwdt.o
diff --git a/drivers/watchdog/imanager-ec-wdt.c b/drivers/watchdog/imanager-ec-wdt.c
new file mode 100644
index 0000000..9c94b21
--- /dev/null
+++ b/drivers/watchdog/imanager-ec-wdt.c
@@ -0,0 +1,170 @@
+/*
+ * Advantech iManager Watchdog core
+ *
+ * Copyright (C) 2016 Advantech Co., Ltd., Irvine, CA, USA
+ * Author: Richard Vidal-Dorsch <richard.dorsch@advantech.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.
+ *
+ * Note: Current release only implements RESET of the EC WDT.
+ * In other words, no PWR button, NMI, SCI, IRQ, or WDPin support yet!
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/bug.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/byteorder/generic.h>
+#include <linux/swab.h>
+#include <linux/mfd/imanager/ec.h>
+#include <linux/mfd/imanager/wdt.h>
+
+/* Timer resolution */
+#define WDT_FREQ 10 /* Hz */
+
+enum wdt_ctrl {
+ START = 1,
+ STOP,
+ RST,
+ GET_TIMEOUT,
+ SET_TIMEOUT,
+ STOPBOOT = 8,
+};
+
+struct wdt_event_delay {
+ u16 delay,
+ pwrbtn,
+ nmi,
+ reset,
+ wdpin,
+ sci,
+ dummy;
+};
+
+static const struct imanager_watchdog_device *wd;
+
+static inline int set_timer(enum wdt_ctrl ctrl)
+{
+ if (WARN_ON(ctrl == SET_TIMEOUT))
+ return -EINVAL;
+
+ return imanager_msg_write(EC_CMD_WDT_CTRL, ctrl, NULL);
+}
+
+static int
+wdt_ctrl(enum wdt_ctrl ctrl, enum wdt_event type, unsigned int timeout)
+{
+ u16 val;
+ int ret;
+ struct ec_message msg = {
+ .rlen = 0,
+ .wlen = 0,
+ };
+ u8 *fevent = &msg.u.data[0];
+ struct wdt_event_delay *event =
+ (struct wdt_event_delay *)&msg.u.data[1];
+
+ switch (ctrl) {
+ case SET_TIMEOUT:
+ memset(event, 0xff, sizeof(*event));
+ msg.wlen = sizeof(*event);
+ *fevent = 0;
+ val = (!timeout) ? 0xffff : swab16(timeout * WDT_FREQ);
+
+ switch (type) {
+ case DELAY:
+ event->delay = val;
+ break;
+ case PWRBTN:
+ event->pwrbtn = val;
+ break;
+ case NMI:
+ event->nmi = val;
+ break;
+ case RESET:
+ event->reset = val;
+ break;
+ case WDPIN:
+ event->wdpin = val;
+ break;
+ case SCI:
+ event->sci = val;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = imanager_msg_write(EC_CMD_WDT_CTRL, SET_TIMEOUT, &msg);
+ if (ret < 0) {
+ pr_err("Failed to set timeout\n");
+ return ret;
+ }
+ break;
+ case START:
+ case STOP:
+ case RST:
+ case STOPBOOT:
+ /* simple command, no data */
+ return imanager_msg_write(EC_CMD_WDT_CTRL, ctrl, NULL);
+ default:
+ return -EINVAL;
+ }
+
+ return timeout;
+}
+
+int wdt_core_start_timer(void)
+{
+ return set_timer(START);
+}
+
+int wdt_core_stop_timer(void)
+{
+ return set_timer(STOP);
+}
+
+int wdt_core_reset_timer(void)
+{
+ return set_timer(RST);
+}
+
+int wdt_core_stop_boot_timer(void)
+{
+ return set_timer(STOPBOOT);
+}
+
+inline int wdt_core_set_timeout(enum wdt_event type, u32 timeout)
+{
+ return wdt_ctrl(SET_TIMEOUT, type, timeout);
+}
+
+int wdt_core_disable_all(void)
+{
+ struct ec_message msg = {
+ .rlen = 0,
+ .wlen = sizeof(struct wdt_event_delay),
+ };
+ struct wdt_event_delay *event =
+ (struct wdt_event_delay *)&msg.u.data[1];
+
+ memset(event, 0xff, sizeof(*event));
+
+ return (wdt_core_stop_timer() ||
+ wdt_core_stop_boot_timer() ||
+ imanager_msg_write(EC_CMD_WDT_CTRL, SET_TIMEOUT, &msg));
+}
+
+int wdt_core_init(void)
+{
+ wd = imanager_get_watchdog_device();
+ if (!wd)
+ return -ENODEV;
+
+ return 0;
+}
+
diff --git a/drivers/watchdog/imanager-wdt.c b/drivers/watchdog/imanager-wdt.c
new file mode 100644
index 0000000..10f8e22
--- /dev/null
+++ b/drivers/watchdog/imanager-wdt.c
@@ -0,0 +1,333 @@
+/*
+ * Advantech iManager Watchdog driver
+ *
+ * Copyright (C) 2016 Advantech Co., Ltd., Irvine, CA, USA
+ * Author: Richard Vidal-Dorsch <richard.dorsch@advantech.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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/imanager/core.h>
+#include <linux/mfd/imanager/wdt.h>
+
+#define WATCHDOG_TIMEOUT 30 /* in seconds */
+
+static unsigned long last_updated = -1;
+
+static uint timeout = WATCHDOG_TIMEOUT;
+module_param(timeout, uint, 0);
+MODULE_PARM_DESC(timeout,
+ "Watchdog timeout in seconds. 1 <= timeout <= 65534, default="
+ __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout,
+ "Watchdog cannot be stopped once started (default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static int wdt_start_timer(void)
+{
+ int ret;
+
+ ret = wdt_core_start_timer();
+ if (ret < 0)
+ return ret;
+
+ last_updated = jiffies;
+
+ return 0;
+}
+
+static int wdt_stop_timer(void)
+{
+ int ret;
+
+ ret = wdt_core_stop_timer();
+ if (ret < 0)
+ return ret;
+
+ last_updated = 0;
+
+ return 0;
+}
+
+static int wdt_ping(void)
+{
+ int ret;
+
+ ret = wdt_core_reset_timer();
+ if (ret < 0)
+ return ret;
+
+ last_updated = jiffies;
+
+ return 0;
+}
+
+static int imanager_wdt_set(unsigned int _timeout)
+{
+ int ret;
+
+ if (timeout != _timeout)
+ timeout = _timeout;
+
+ ret = wdt_core_set_timeout(PWRBTN, timeout);
+ if (ret < 0)
+ return ret;
+
+ if (last_updated != 0)
+ last_updated = jiffies;
+
+ return 0;
+}
+
+static int imanager_wdt_set_timeout(struct watchdog_device *wdt_dev,
+ unsigned int timeout)
+{
+ struct imanager_device_data *idev = watchdog_get_drvdata(wdt_dev);
+ int ret = 0;
+
+ mutex_lock(&idev->lock);
+
+ ret = imanager_wdt_set(timeout);
+ if (ret < 0)
+ dev_err(wdt_dev->dev, "Failed to set timeout\n");
+ mutex_unlock(&idev->lock);
+
+ return ret;
+}
+
+static unsigned int imanager_wdt_get_timeleft(struct watchdog_device *wdt_dev)
+{
+ unsigned int timeleft = 0;
+ unsigned long time_diff = ((jiffies - last_updated) / HZ);
+
+ if (last_updated && (timeout > time_diff))
+ timeleft = timeout - time_diff;
+
+ return timeleft;
+}
+
+static int imanager_wdt_start(struct watchdog_device *wdt_dev)
+{
+ struct imanager_device_data *idev = watchdog_get_drvdata(wdt_dev);
+ int ret = 0;
+
+ mutex_lock(&idev->lock);
+
+ ret = wdt_start_timer();
+ if (ret < 0)
+ dev_err(wdt_dev->dev, "Failed to start timer\n");
+
+ mutex_unlock(&idev->lock);
+
+ return ret;
+}
+
+static int imanager_wdt_stop(struct watchdog_device *wdt_dev)
+{
+ struct imanager_device_data *idev = watchdog_get_drvdata(wdt_dev);
+ int ret = 0;
+
+ mutex_lock(&idev->lock);
+
+ ret = wdt_stop_timer();
+ if (ret < 0)
+ dev_err(wdt_dev->dev, "Failed to stop timer\n");
+
+ mutex_unlock(&idev->lock);
+
+ return ret;
+}
+
+static int imanager_wdt_ping(struct watchdog_device *wdt_dev)
+{
+ struct imanager_device_data *idev = watchdog_get_drvdata(wdt_dev);
+ int ret = 0;
+
+ mutex_lock(&idev->lock);
+
+ ret = wdt_ping();
+ if (ret < 0)
+ dev_err(wdt_dev->dev, "Failed to reset timer\n");
+
+ mutex_unlock(&idev->lock);
+
+ return ret;
+}
+
+static long imanager_wdt_ioctl(struct watchdog_device *wdt_dev,
+ unsigned int cmd, unsigned long arg)
+{
+ struct imanager_device_data *idev = watchdog_get_drvdata(wdt_dev);
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ int ret = 0;
+ int timeval, options;
+ static const struct watchdog_info ident = {
+ .options = WDIOF_KEEPALIVEPING |
+ WDIOF_SETTIMEOUT |
+ WDIOF_MAGICCLOSE,
+ .firmware_version = 0,
+ .identity = "imanager_wdt",
+ };
+
+ mutex_lock(&idev->lock);
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ if (copy_to_user(argp, &ident, sizeof(ident)))
+ ret = -EFAULT;
+ break;
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ ret = put_user(0, p);
+ break;
+ case WDIOC_SETOPTIONS:
+ if (get_user(options, p)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ if (options & WDIOS_DISABLECARD)
+ wdt_stop_timer();
+ if (options & WDIOS_ENABLECARD) {
+ wdt_ping();
+ wdt_start_timer();
+ }
+ break;
+ case WDIOC_KEEPALIVE:
+ wdt_ping();
+ break;
+ case WDIOC_SETTIMEOUT:
+ if (get_user(timeval, p)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ if (imanager_wdt_set(timeval)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ wdt_ping();
+ /* Fall through */
+ case WDIOC_GETTIMEOUT:
+ ret = put_user(timeout, p);
+ break;
+ case WDIOC_GETTIMELEFT:
+ timeval = imanager_wdt_get_timeleft(wdt_dev);
+ ret = put_user(timeval, p);
+ break;
+ default:
+ ret = -ENOTTY;
+ }
+
+out:
+ mutex_unlock(&idev->lock);
+
+ return ret;
+}
+
+static const struct watchdog_info imanager_wdt_info = {
+ .options = WDIOF_SETTIMEOUT |
+ WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
+ .identity = "imanager_wdt",
+ .firmware_version = 0,
+};
+
+static const struct watchdog_ops imanager_wdt_ops = {
+ .owner = THIS_MODULE,
+ .start = imanager_wdt_start,
+ .stop = imanager_wdt_stop,
+ .ping = imanager_wdt_ping,
+ .set_timeout = imanager_wdt_set_timeout,
+ .get_timeleft = imanager_wdt_get_timeleft,
+ .ioctl = imanager_wdt_ioctl,
+};
+
+static struct watchdog_device imanager_wdt_dev = {
+ .info = &imanager_wdt_info,
+ .ops = &imanager_wdt_ops,
+ .timeout = WATCHDOG_TIMEOUT,
+ .min_timeout = 1,
+ .max_timeout = 0xfffe,
+};
+
+static int imanager_wdt_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct imanager_device_data *idev = dev_get_drvdata(dev->parent);
+ int ret;
+
+ if (!idev) {
+ dev_err(dev, "Invalid platform data\n");
+ return -EINVAL;
+ }
+
+ watchdog_set_nowayout(&imanager_wdt_dev, nowayout);
+ watchdog_set_drvdata(&imanager_wdt_dev, idev);
+
+ ret = watchdog_register_device(&imanager_wdt_dev);
+ if (ret) {
+ dev_err(dev, "Failed to register watchdog device\n");
+ return ret;
+ }
+
+ ret = wdt_core_init();
+ if (ret) {
+ dev_err(dev, "Failed to initialize watchdog core\n");
+ goto unregister_driver;
+ }
+
+ wdt_core_disable_all();
+
+ imanager_wdt_set_timeout(&imanager_wdt_dev, timeout);
+
+ dev_info(dev, "Driver loaded (timeout=%d seconds)\n", timeout);
+
+ return 0;
+
+unregister_driver:
+ watchdog_unregister_device(&imanager_wdt_dev);
+ platform_set_drvdata(pdev, NULL);
+
+ return ret;
+}
+
+static int imanager_wdt_remove(struct platform_device *pdev)
+{
+ wdt_core_disable_all();
+
+ watchdog_unregister_device(&imanager_wdt_dev);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver imanager_wdt_driver = {
+ .driver = {
+ .name = "imanager_wdt",
+ },
+ .probe = imanager_wdt_probe,
+ .remove = imanager_wdt_remove,
+};
+
+module_platform_driver(imanager_wdt_driver);
+
+MODULE_DESCRIPTION("Advantech iManager Watchdog Driver");
+MODULE_AUTHOR("Richard Vidal-Dorsch <richard.dorsch at advantech.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:imanager_wdt");
diff --git a/include/linux/mfd/imanager/wdt.h b/include/linux/mfd/imanager/wdt.h
new file mode 100644
index 0000000..eb709b7
--- /dev/null
+++ b/include/linux/mfd/imanager/wdt.h
@@ -0,0 +1,37 @@
+/*
+ * Advantech iManager Watchdog core
+ *
+ * Copyright (C) 2016 Advantech Co., Ltd., Irvine, CA, USA
+ * Author: Richard Vidal-Dorsch <richard.dorsch@advantech.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.
+ */
+
+#ifndef __WDT_H__
+#define __WDT_H__
+
+#include <linux/types.h>
+
+enum wdt_event {
+ DELAY,
+ PWRBTN,
+ NMI,
+ RESET,
+ WDPIN,
+ SCI,
+};
+
+int wdt_core_init(void);
+
+int wdt_core_set_timeout(enum wdt_event type, u32 timeout);
+
+int wdt_core_disable_all(void);
+int wdt_core_start_timer(void);
+int wdt_core_stop_timer(void);
+int wdt_core_reset_timer(void);
+int wdt_core_stop_boot_timer(void);
+
+#endif
--
2.7.0
[toc] | [prev] | [next] | [standalone]
| From | richard.dorsch@gmail.com |
|---|---|
| Date | 2016-01-11 00:40 +0100 |
| Subject | [PATCH v3 5/6] Add Advantech iManager Backlight driver |
| Message-ID | <qPxKy-2yK-21@gated-at.bofh.it> |
| In reply to | #1305741 |
From: Richard Vidal-Dorsch <richard.dorsch@gmail.com>
Signed-off-by: Richard Vidal-Dorsch <richard.dorsch@gmail.com>
---
drivers/video/backlight/Kconfig | 12 ++
drivers/video/backlight/Makefile | 2 +
drivers/video/backlight/imanager-bl.c | 198 +++++++++++++++++++++++++++++++
drivers/video/backlight/imanager-ec-bl.c | 118 ++++++++++++++++++
include/linux/mfd/imanager/backlight.h | 37 ++++++
5 files changed, 367 insertions(+)
create mode 100644 drivers/video/backlight/imanager-bl.c
create mode 100644 drivers/video/backlight/imanager-ec-bl.c
create mode 100644 include/linux/mfd/imanager/backlight.h
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 5ffa4b4..8003573 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -251,6 +251,18 @@ config BACKLIGHT_HP700
If you have an HP Jornada 700 series,
say Y to include backlight control driver.
+config BACKLIGHT_IMANAGER
+ tristate "Advantech iManager backlight/brightness"
+ depends on MFD_IMANAGER
+ help
+ This enables support for Advantech iManager Backlight and
+ Brightness control of some Advantech SOM, MIO, AIMB, and
+ PCM modules/boards.
+ Requires mfd-core and imanager-core to function properly.
+
+ This driver can also be built as a module. If so, the module
+ will be called imanager_bl.
+
config BACKLIGHT_CARILLO_RANCH
tristate "Intel Carillo Ranch Backlight Driver"
depends on LCD_CLASS_DEVICE && PCI && X86 && FB_LE80578
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 16ec534..15bf136 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -26,6 +26,8 @@ obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o
obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o
obj-$(CONFIG_BACKLIGHT_AS3711) += as3711_bl.o
obj-$(CONFIG_BACKLIGHT_BD6107) += bd6107.o
+imanager_bl-objs := imanager-bl.o imanager-ec-bl.o
+obj-$(CONFIG_BACKLIGHT_IMANAGER) += imanager_bl.o
obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o
diff --git a/drivers/video/backlight/imanager-bl.c b/drivers/video/backlight/imanager-bl.c
new file mode 100644
index 0000000..9950fec
--- /dev/null
+++ b/drivers/video/backlight/imanager-bl.c
@@ -0,0 +1,198 @@
+/*
+ * Advantech iManager Backlight driver
+ * Partially derived from wm831x_bl
+ *
+ * Copyright (C) 2016 Advantech Co., Ltd., Irvine, CA, USA
+ * Author: Richard Vidal-Dorsch <richard.dorsch@advantech.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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
+#include <linux/pwm.h>
+#include <linux/mfd/imanager/core.h>
+#include <linux/mfd/imanager/backlight.h>
+
+#define BL_MAX_BRIGHTNESS 100
+
+static bool polarity = PWM_POLARITY_NORMAL;
+module_param(polarity, bool, 0);
+MODULE_PARM_DESC(polarity, "Select backlight polarity (inverted := 1)");
+
+static ushort unit = UNIT_1;
+module_param(unit, ushort, 0);
+MODULE_PARM_DESC(unit, "Select backlight control unit [0, 1] (defaults to 0)");
+
+struct imanager_backlight_data {
+ struct imanager_device_data *idev;
+ struct backlight_device *bl;
+};
+
+static int get_brightness(struct backlight_device *dev)
+{
+ struct imanager_backlight_data *data = bl_get_data(dev);
+ int ret;
+
+ mutex_lock(&data->idev->lock);
+
+ ret = bl_core_get_pulse_width(unit);
+ /* Reverse percentage if polarity is set */
+ if (polarity)
+ ret = 100 - ret;
+
+ mutex_unlock(&data->idev->lock);
+
+ return ret;
+}
+
+static int set_brightness(struct backlight_device *dev)
+{
+ struct imanager_backlight_data *data = bl_get_data(dev);
+ u8 brightness = (u8) dev->props.brightness;
+ int ret;
+
+ if (brightness > BL_MAX_BRIGHTNESS)
+ return -EINVAL;
+
+ if (dev->props.power != FB_BLANK_UNBLANK)
+ brightness = 0;
+
+ if (dev->props.fb_blank != FB_BLANK_UNBLANK)
+ brightness = 0;
+
+ if (dev->props.state & BL_CORE_SUSPENDED)
+ brightness = 0;
+
+ mutex_lock(&data->idev->lock);
+
+ /* Inversed percentage if polarity is set */
+ if (polarity)
+ brightness = 100 - brightness;
+ ret = bl_core_set_pulse_width(unit, brightness);
+
+ mutex_unlock(&data->idev->lock);
+
+ return ret;
+}
+
+static const struct backlight_ops imanager_bl_ops = {
+ .options = BL_CORE_SUSPENDRESUME,
+ .get_brightness = get_brightness,
+ .update_status = set_brightness,
+};
+
+static int imanager_backlight_init(struct device *dev,
+ struct imanager_backlight_data *data)
+{
+ struct backlight_device *bd;
+ struct backlight_properties props;
+
+ memset(&props, 0, sizeof(props));
+ props.type = BACKLIGHT_PLATFORM;
+ props.max_brightness = BL_MAX_BRIGHTNESS;
+ bd = backlight_device_register("imanager_backlight", dev, data,
+ &imanager_bl_ops, &props);
+
+ if (IS_ERR(bd)) {
+ data->bl = NULL;
+ dev_err(dev, "Unable to register backlight device\n");
+ return PTR_ERR(bd);
+ }
+
+ data->bl = bd;
+
+ bd->props.brightness = get_brightness(bd);
+ bd->props.power = FB_BLANK_UNBLANK;
+ backlight_update_status(bd);
+
+ return 0;
+}
+
+static int imanager_backlight_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct imanager_device_data *idev = dev_get_drvdata(dev->parent);
+ struct imanager_backlight_data *data;
+ int ret;
+
+ if (!idev) {
+ dev_err(dev, "Invalid platform data\n");
+ return -EINVAL;
+ }
+
+ ret = bl_core_init();
+ if (ret) {
+ dev_err(dev, "Failed to initialize backlight core\n");
+ return -EIO;
+ }
+
+ ret = bl_core_set_state(unit, BL_CTRL_ENABLE);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enable backlight control (%d)\n",
+ unit);
+ return -EIO;
+ }
+
+ if (polarity)
+ ret = bl_core_set_polarity(PWM_POLARITY_INVERSED);
+ else
+ ret = bl_core_set_polarity(PWM_POLARITY_NORMAL);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set backlight polarity\n");
+ return -EIO;
+ }
+
+ /* init brightness to 60% */
+ bl_core_set_pulse_width(unit, 60);
+
+ data = devm_kzalloc(dev, sizeof(struct imanager_backlight_data),
+ GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->idev = idev;
+
+ ret = imanager_backlight_init(dev, data);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, data);
+
+ return 0;
+}
+
+static int imanager_backlight_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct imanager_backlight_data *data = dev_get_drvdata(dev);
+
+ backlight_device_unregister(data->bl);
+
+ return 0;
+}
+
+static struct platform_driver imanager_backlight_driver = {
+ .driver = {
+ .name = "imanager_backlight",
+ },
+ .probe = imanager_backlight_probe,
+ .remove = imanager_backlight_remove,
+};
+
+module_platform_driver(imanager_backlight_driver);
+
+MODULE_DESCRIPTION("Advantech iManager Backlight driver");
+MODULE_AUTHOR("Richard Vidal-Dorsch <richard.dorsch at advantech.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:imanager_backlight");
diff --git a/drivers/video/backlight/imanager-ec-bl.c b/drivers/video/backlight/imanager-ec-bl.c
new file mode 100644
index 0000000..04d2478
--- /dev/null
+++ b/drivers/video/backlight/imanager-ec-bl.c
@@ -0,0 +1,118 @@
+/*
+ * Advantech iManager Backlight/Brightness Core
+ *
+ * Copyright (C) 2016 Advantech Co., Ltd., Irvine, CA, USA
+ * Author: Richard Vidal-Dorsch <richard.dorsch@advantech.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.
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/bug.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/byteorder/generic.h>
+#include <linux/mfd/imanager/ec.h>
+#include <linux/mfd/imanager/backlight.h>
+
+struct brightness_level {
+ u32 value : 7, /* Brightness Value - LSB [6..0] */
+ enable : 1; /* Brightness Enable - MSB [7] */
+};
+
+struct backlight_ctrl {
+ u32 enable : 1, /* Backlight Control Enable - LSB [0] */
+ pwmpol : 1, /* PWM Polarity - bit [1] */
+ blpol : 1, /* Backlight Polarity - bit [2] */
+ dnc : 5; /* Don't care - bit [7..3] */
+};
+
+static const struct imanager_backlight_device *bl;
+
+int bl_core_get_pulse_width(u32 unit)
+{
+ int ret;
+
+ if (WARN_ON(unit >= EC_BLC_MAX_NUM))
+ return -EINVAL;
+
+ ret = imanager_read_byte(EC_CMD_HWP_RD, bl->attr[unit].did);
+ if (ret < 0)
+ pr_err("Failed reading PWM (unit=%d)\n", unit);
+
+ return ret;
+}
+
+int bl_core_set_pulse_width(u32 unit, u32 pwm)
+{
+ int ret;
+
+ if (WARN_ON(unit >= EC_BLC_MAX_NUM))
+ return -EINVAL;
+
+ pwm = pwm > 100 ? 100 : pwm;
+
+ ret = imanager_write_byte(EC_CMD_HWP_WR, bl->attr[unit].did, pwm);
+ if (ret < 0)
+ pr_err("Failed writing PWM (val=%d, unit=%d)\n", pwm, unit);
+
+ return ret;
+}
+
+int bl_core_set_state(u32 unit, bool enable)
+{
+ int ret;
+ u8 val8;
+ struct brightness_level *pl = (struct brightness_level *)&val8;
+
+ if (WARN_ON(unit >= EC_BLC_MAX_NUM))
+ return -EINVAL;
+
+ ret = imanager_acpiram_read_byte(bl->brightness[unit]);
+ if (ret < 0)
+ return ret;
+ val8 = ret;
+
+ pl->enable = enable ? 1 : 0;
+
+ ret = imanager_acpiram_write_byte(bl->attr[unit].did, val8);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int bl_core_set_polarity(u32 polarity)
+{
+ int ret;
+ u8 val8;
+ struct backlight_ctrl *ctrl = (struct backlight_ctrl *)&val8;
+
+ ret = imanager_acpiram_read_byte(EC_ACPIRAM_BLC_CTRL);
+ if (ret < 0)
+ return ret;
+ val8 = ret;
+
+ ctrl->blpol = polarity ? 1 : 0;
+
+ ret = imanager_acpiram_write_byte(EC_ACPIRAM_BLC_CTRL, val8);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int bl_core_init(void)
+{
+ bl = imanager_get_backlight_device();
+ if (!bl)
+ return -ENODEV;
+
+ return 0;
+}
+
diff --git a/include/linux/mfd/imanager/backlight.h b/include/linux/mfd/imanager/backlight.h
new file mode 100644
index 0000000..93ea7cf5
--- /dev/null
+++ b/include/linux/mfd/imanager/backlight.h
@@ -0,0 +1,37 @@
+/*
+ * Advantech iManager Backlight core
+ *
+ * Copyright (C) 2016 Advantech Co., Ltd., Irvine, CA, USA
+ * Author: Richard Vidal-Dorsch <richard.dorsch@advantech.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.
+ */
+
+#ifndef __BACKLIGHT_H__
+#define __BACKLIGHT_H__
+
+#include <linux/types.h>
+
+enum backlight_control {
+ BL_CTRL_DISABLE,
+ BL_CTRL_ENABLE,
+};
+
+enum backlight_unit {
+ UNIT_1,
+ UNIT_2,
+};
+
+int bl_core_init(void);
+
+int bl_core_set_state(u32 unit, bool enable);
+
+int bl_core_set_polarity(u32 polarity);
+
+int bl_core_get_pulse_width(u32 unit);
+int bl_core_set_pulse_width(u32 unit, u32 pwm);
+
+#endif
--
2.7.0
[toc] | [prev] | [next] | [standalone]
| From | Lee Jones <lee.jones@linaro.org> |
|---|---|
| Date | 2016-01-11 11:30 +0100 |
| Subject | Re: [PATCH v3 5/6] Add Advantech iManager Backlight driver |
| Message-ID | <qPHTB-Yo-25@gated-at.bofh.it> |
| In reply to | #1305743 |
On Sun, 10 Jan 2016, richard.dorsch@gmail.com wrote: > From: Richard Vidal-Dorsch <richard.dorsch@gmail.com> > > Signed-off-by: Richard Vidal-Dorsch <richard.dorsch@gmail.com> > --- > drivers/video/backlight/Kconfig | 12 ++ > drivers/video/backlight/Makefile | 2 + > drivers/video/backlight/imanager-bl.c | 198 +++++++++++++++++++++++++++++++ > drivers/video/backlight/imanager-ec-bl.c | 118 ++++++++++++++++++ > include/linux/mfd/imanager/backlight.h | 37 ++++++ > 5 files changed, 367 insertions(+) > create mode 100644 drivers/video/backlight/imanager-bl.c > create mode 100644 drivers/video/backlight/imanager-ec-bl.c > create mode 100644 include/linux/mfd/imanager/backlight.h How do you expect this to be reviewed if you don't send it to the reviewer? [...] -- Lee Jones Linaro STMicroelectronics Landing Team Lead Linaro.org │ Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog
[toc] | [prev] | [next] | [standalone]
| From | Guenter Roeck <linux@roeck-us.net> |
|---|---|
| Date | 2016-01-11 02:00 +0100 |
| Message-ID | <qPyZX-3hi-3@gated-at.bofh.it> |
| In reply to | #1305741 |
On 01/10/2016 03:31 PM, richard.dorsch@gmail.com wrote: > From: Richard Vidal-Dorsch <richard.dorsch@gmail.com> > > The Advantech iManager is an embedded controller (depending on board type, > ITE it8518/it8528) on which a custom firmware runs. All drivers (GPIO, I2C, > HWmon, Watchdog, and backlight) are being managed by the imanager mfd driver. > The imanager mfd driver acts as a 'gateway' and handles all communications > between the EC and sub-drivers (GPIO, I2C, ...). The feature specific > communication portions are split up into core files such as > imanager-ec-[gpio, i2c, ...]. > > Changes from v2: > I forgot to remove .owner from other drivers too... silly me! > - Remove .owner from platform_driver in: > drivers/gpio/imanager-bl > drivers/gpio/imanager-core.c > drivers/gpio/imanager-i2c.c > drivers/gpio/imanager-hwmon.c > Hi Richard, in case there are more alerts from the 0day build system, or minor feedback from others, please give us time to actually review the code before resending the series. I have not even had time to look into v1 (and I bet no one else had either), and you already sent v3, just to remove various .owner fields. Also, please be a bit patient. The commit window just opened, meaning all maintainers will be busy preparing to send pull requests to Linus. Thanks, Guenter
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web