From: Guenter Roeck <linux@roeck-us.net>
To: Wim Van Sebroeck <wim@iguana.be>
Cc: linux-watchdog@vger.kernel.org, linux-kernel@vger.kernel.org,
"Samuel Ortiz" <sameo@linux.intel.com>,
"Pádraig Brady" <P@draigBrady.com>
Subject: mfd: Core driver for Winbond chips
Date: Sat, 23 Mar 2013 10:49:14 -0700 [thread overview]
Message-ID: <20130323174914.GA21563@roeck-us.net> (raw)
In-Reply-To: <20130323002810.GA26245@roeck-us.net>
MFD core driver for various variants of Winbond/Nuvoton SuperIO chips.
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
drivers/mfd/Kconfig | 22 +++
drivers/mfd/Makefile | 1 +
drivers/mfd/w83627hf-core.c | 324 ++++++++++++++++++++++++++++++++++++++++++
include/linux/mfd/w83627hf.h | 131 +++++++++++++++++
4 files changed, 478 insertions(+)
create mode 100644 drivers/mfd/w83627hf-core.c
create mode 100644 include/linux/mfd/w83627hf.h
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index c346941..a141ef6 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1119,6 +1119,28 @@ config MFD_AS3711
help
Support for the AS3711 PMIC from AMS
+config MFD_W83627HF
+ tristate "Winbond W83627HF and compatibles"
+ select MFD_CORE
+ help
+ If you say yes here you add support for the Winbond W836X7 and Nuvoton
+ NCT677X series of super-IO chips. The following chips are supported:
+ W83627F/HF/G/HG/DHG/DHG-P/EHF/EHG/S/SF/THF/UHG/UG
+ W83637HF
+ W83667HG/HG-B
+ W83687THF
+ W83697HF
+ NCT6775
+ NCT6776
+ NCT6779
+
+ This is a multi functional device and this support defines a new
+ platform device only. See other configuration submenus in order to
+ enable the drivers of Winbond chip's functionalities.
+
+ This driver can also be built as a module. If so, the module
+ will be called w83627hf-core.
+
endmenu
endif
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index b90409c..3e9e830 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_MFD_MC13XXX_I2C) += mc13xxx-i2c.o
obj-$(CONFIG_MFD_CORE) += mfd-core.o
obj-$(CONFIG_EZX_PCAP) += ezx-pcap.o
+obj-$(CONFIG_MFD_W83627HF) += w83627hf-core.o
obj-$(CONFIG_MCP) += mcp-core.o
obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
diff --git a/drivers/mfd/w83627hf-core.c b/drivers/mfd/w83627hf-core.c
new file mode 100644
index 0000000..d0be5b9
--- /dev/null
+++ b/drivers/mfd/w83627hf-core.c
@@ -0,0 +1,324 @@
+/*
+ * w83627hf.c - platform device support
+ *
+ * Copyright (c) 2013 Guenter Roeck <linux@roeck-us.net>
+ *
+ * Based on earlier work by Rodolfo Giometti
+ *
+ * Copyright (c) 2009-2011 Rodolfo Giometti <giometti@linux.it>
+ *
+ * Based on drivers/hwmon/w83627hf.c
+ *
+ * Original copyright note:
+ * Copyright (c) 1998 - 2003 Frodo Looijaard <frodol@dds.nl>,
+ * Philip Edelbrock <phil@netroedge.com>,
+ * and Mark Studebaker <mdsxyz123@yahoo.com>
+ * Ported to 2.6 by Bernhard C. Schrenk <clemy@clemy.org>
+ * Copyright (c) 2007 Jean Delvare <khali@linux-fr.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/ioport.h>
+#include <linux/acpi.h>
+#include <linux/io.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/w83627hf.h>
+
+static unsigned short force_id;
+module_param(force_id, ushort, 0);
+MODULE_PARM_DESC(force_id, "Override the detected device ID");
+
+/*
+ * Devices definitions
+ */
+
+static struct platform_device *pdev;
+
+struct w83627hf_chip_data {
+ const char * const name;
+ const char * const chip;
+ const char * const hwmon_drvname;
+};
+
+static const struct w83627hf_chip_data w83627hf_chip_data[] = {
+ [w83627hf] = {
+ .name = __stringify(w83627hf),
+ .chip = "W83627HF",
+ .hwmon_drvname = W83627HF_HWMON_DRVNAME,
+ },
+ [w83627s] = {
+ .name = __stringify(w83627s),
+ .chip = "W83627S",
+ },
+ [w83627thf] = {
+ .name = __stringify(w83627thf),
+ .chip = "W83627THF",
+ .hwmon_drvname = W83627HF_HWMON_DRVNAME,
+ },
+ [w83697hf] = {
+ .name = __stringify(w83697hf),
+ .chip = "W83697HF",
+ .hwmon_drvname = W83627HF_HWMON_DRVNAME,
+ },
+ [w83697ug] = {
+ .name = __stringify(w83697ug),
+ .chip = "W83697SF/UG",
+ },
+ [w83637hf] = {
+ .name = __stringify(w83637hf),
+ .chip = "W83637HF",
+ .hwmon_drvname = W83627HF_HWMON_DRVNAME,
+ },
+ [w83687thf] = {
+ .name = __stringify(w83687thf),
+ .chip = "W83687THF",
+ .hwmon_drvname = W83627HF_HWMON_DRVNAME,
+ },
+ [w83627ehf] = {
+ .name = __stringify(w83627ehf),
+ .chip = "W83627EHF",
+ .hwmon_drvname = W83627EHF_HWMON_DRVNAME,
+ },
+ [w83627dhg] = {
+ .name = __stringify(w83627dhg),
+ .chip = "W83627DHG",
+ .hwmon_drvname = W83627EHF_HWMON_DRVNAME,
+ },
+ [w83627dhg_p] = {
+ .name = __stringify(w83627dhg),
+ .chip = "W83627DHG-P",
+ .hwmon_drvname = W83627EHF_HWMON_DRVNAME,
+ },
+ [w83627uhg] = {
+ .name = __stringify(w83627uhg),
+ .chip = "W83627UHG",
+ .hwmon_drvname = W83627EHF_HWMON_DRVNAME,
+ },
+ [w83667hg] = {
+ .name = __stringify(w83667hg),
+ .chip = "W83667HG",
+ .hwmon_drvname = W83627EHF_HWMON_DRVNAME,
+ },
+ [w83667hg_b] = {
+ .name = __stringify(w83667hg),
+ .chip = "W83667HG-B",
+ .hwmon_drvname = W83627EHF_HWMON_DRVNAME,
+ },
+ [nct6775] = {
+ .name = __stringify(nct6775),
+ .chip = "NCT6775",
+ .hwmon_drvname = NCT6775_HWMON_DRVNAME,
+ },
+ [nct6776] = {
+ .name = __stringify(nct6776),
+ .chip = "NCT6776",
+ .hwmon_drvname = NCT6775_HWMON_DRVNAME,
+ },
+ [nct6779] = {
+ .name = __stringify(nct6779),
+ .chip = "NCT6779",
+ .hwmon_drvname = NCT6775_HWMON_DRVNAME,
+ },
+};
+
+#define MFD_NUM_CELLS 2
+
+static struct mfd_cell mfd_cells[MFD_NUM_CELLS];
+
+#define W83627HF_CR_DEVID 0x20
+
+#define W83627HF_G_DEVID 0x5210
+#define W83627HF_J_DEVID 0x5230
+#define W83627HF_UD_DEVID 0x5240
+#define W83627S_DEVID 0x5950
+#define W83627THF_DEVID 0x8280
+#define W83697HF_DEVID 0x6010
+#define W83697SF_DEVID 0x6800
+#define W83697UG_DEVID 0x6810
+#define W83637HF_DEVID 0x7080
+#define W83687THF_DEVID 0x8540
+#define W83627EHF_DEVID 0x8850
+#define W83627EHG_DEVID 0x8860
+#define W83627DHG_DEVID 0xa020
+#define W83627DHG_P_DEVID 0xb070
+#define W83627UHG_DEVID 0xa230
+#define W83667HG_DEVID 0xa510
+#define W83667HG_B_DEVID 0xb350
+#define NCT6775_DEVID 0xb470
+#define NCT6776_DEVID 0xc330
+#define NCT6779_DEVID 0xc560
+
+#define DEVID_MASK 0xfff0
+
+static int __init w83627hf_find(int sioaddr,
+ struct w83627hf_platform_data *pdata)
+{
+ int err = 0;
+ u16 val;
+
+ err = superio_enter(sioaddr);
+ if (err)
+ return err;
+
+ val = force_id ? : ((superio_inb(sioaddr, W83627HF_CR_DEVID) << 8) |
+ superio_inb(sioaddr, W83627HF_CR_DEVID + 1));
+
+ switch (val & DEVID_MASK) {
+ case W83627HF_G_DEVID:
+ case W83627HF_J_DEVID:
+ case W83627HF_UD_DEVID:
+ pdata->type = w83627hf;
+ break;
+ case W83627S_DEVID:
+ pdata->type = w83627s;
+ break;
+ case W83627THF_DEVID:
+ pdata->type = w83627thf;
+ break;
+ case W83697HF_DEVID:
+ pdata->type = w83697hf;
+ break;
+ case W83697SF_DEVID:
+ case W83697UG_DEVID:
+ pdata->type = w83697ug;
+ break;
+ case W83637HF_DEVID:
+ pdata->type = w83637hf;
+ break;
+ case W83687THF_DEVID:
+ pdata->type = w83687thf;
+ break;
+ case W83627EHF_DEVID:
+ case W83627EHG_DEVID:
+ pdata->type = w83627ehf;
+ break;
+ case W83627DHG_DEVID:
+ pdata->type = w83627dhg;
+ break;
+ case W83627DHG_P_DEVID:
+ pdata->type = w83627dhg_p;
+ break;
+ case W83627UHG_DEVID:
+ pdata->type = w83627uhg;
+ break;
+ case W83667HG_DEVID:
+ pdata->type = w83667hg;
+ break;
+ case W83667HG_B_DEVID:
+ pdata->type = w83667hg_b;
+ break;
+ case NCT6775_DEVID:
+ pdata->type = nct6775;
+ break;
+ case NCT6776_DEVID:
+ pdata->type = nct6776;
+ break;
+ case NCT6779_DEVID:
+ pdata->type = nct6779;
+ break;
+ case 0xfff0: /* No device at all */
+ err = -ENODEV;
+ goto exit;
+ default:
+ err = -ENODEV;
+ pr_debug("Unsupported chip (DEVID=0x%04x)\n", val);
+ goto exit;
+ }
+ pdata->sioaddr = sioaddr;
+ pdata->name = w83627hf_chip_data[pdata->type].name;
+ pr_info("Found %s at %#x\n", w83627hf_chip_data[pdata->type].chip,
+ sioaddr);
+exit:
+ superio_exit(sioaddr);
+ return err;
+}
+
+static int __init w83627hf_device_add(struct w83627hf_platform_data *pdata)
+{
+ int err;
+ int cells = 0;
+
+ pdev = platform_device_alloc(W83627HF_CORE_DRVNAME, 0);
+ if (!pdev)
+ return -ENOMEM;
+
+ err = platform_device_add_data(pdev, pdata,
+ sizeof(struct w83627hf_platform_data));
+ if (err)
+ goto exit_device_put;
+
+ if (w83627hf_chip_data[pdata->type].hwmon_drvname) {
+ mfd_cells[cells].name =
+ w83627hf_chip_data[pdata->type].hwmon_drvname;
+ cells++;
+ }
+
+ mfd_cells[cells].name = W83627HF_WDT_DRVNAME;
+ cells++;
+
+ err = platform_device_add(pdev);
+ if (err)
+ goto exit_device_put;
+
+ err = mfd_add_devices(&pdev->dev, pdev->id, mfd_cells, cells,
+ NULL, -1, NULL);
+ if (err)
+ goto exit_device_unregister;
+
+ return 0;
+
+exit_device_unregister:
+ platform_device_unregister(pdev);
+exit_device_put:
+ platform_device_put(pdev);
+ return err;
+}
+
+static int __init w83627hf_init(void)
+{
+ struct w83627hf_platform_data pdata;
+ int ret;
+
+ ret = w83627hf_find(0x2e, &pdata);
+ if (ret) {
+ ret = w83627hf_find(0x4e, &pdata);
+ if (ret)
+ return -ENODEV;
+ }
+
+ /* Sets global pdev as a side effect */
+ return w83627hf_device_add(&pdata);
+}
+
+static void __exit w83627hf_exit(void)
+{
+ mfd_remove_devices(&pdev->dev);
+ platform_device_unregister(pdev);
+}
+
+MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
+MODULE_DESCRIPTION("W83627HF multi-function core driver");
+MODULE_LICENSE("GPL");
+
+module_init(w83627hf_init);
+module_exit(w83627hf_exit);
diff --git a/include/linux/mfd/w83627hf.h b/include/linux/mfd/w83627hf.h
new file mode 100644
index 0000000..6379126
--- /dev/null
+++ b/include/linux/mfd/w83627hf.h
@@ -0,0 +1,131 @@
+/*
+ * w83627hf.h - platform device support, header file
+ * Copyright (c) 2009 Rodolfo Giometti <giometti@linux.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/mutex.h>
+#include <linux/io.h>
+
+#define W83627HF_CORE_DRVNAME "w83627hf_core"
+#define W83627HF_HWMON_DRVNAME "w83627hf_hwmon"
+#define W83627EHF_HWMON_DRVNAME "w83627ehf_hwmon"
+#define NCT6775_HWMON_DRVNAME "nct6775_hwmon"
+
+#define W83627HF_WDT_DRVNAME "w83627hf_wdt"
+
+enum chips {
+ w83627hf,
+ w83627s,
+ w83627thf,
+ w83697hf,
+ w83697ug,
+ w83637hf,
+ w83687thf,
+ w83627ehf,
+ w83627dhg,
+ w83627dhg_p,
+ w83627uhg,
+ w83667hg,
+ w83667hg_b,
+ nct6775,
+ nct6776,
+ nct6779,
+};
+
+struct w83627hf_platform_data {
+ int sioaddr;
+ enum chips type;
+ const char *name;
+};
+
+#define W83627HF_SELECT 0x07
+
+/* logical device numbers for superio_select */
+#define W83627HF_LD_FDC 0x00
+#define W83627HF_LD_PRT 0x01
+#define W83627HF_LD_UART1 0x02
+#define W83627HF_LD_UART2 0x03
+#define W83627HF_LD_KBC 0x05
+#define W83627HF_LD_CIR 0x06 /* w83627hf only */
+#define W83627HF_LD_GAME 0x07
+#define W83627HF_LD_MIDI 0x07
+#define W83627HF_LD_GPIO1 0x07
+#define W83627HF_LD_GPIO5 0x07 /* w83627thf only */
+#define W83627HF_LD_GPIO2 0x08
+#define W83627HF_LD_WDT 0x08
+#define W83627HF_LD_GPIO3 0x09
+#define W83627HF_LD_GPIO4 0x09 /* w83627thf only */
+#define W83627HF_LD_ACPI 0x0a
+#define W83627HF_LD_HWM 0x0b
+
+#define W83627HF_CR_ENABLE 0x30 /* Logical device enable register */
+
+#define W83627THF_GPIO5_IOSR 0xf3 /* w83627thf only */
+#define W83627THF_GPIO5_DR 0xf4 /* w83627thf only */
+
+#define W83687THF_VID_EN 0x29 /* w83687thf only */
+#define W83687THF_VID_CFG 0xF0 /* w83687thf only */
+#define W83687THF_VID_DATA 0xF1 /* w83687thf only */
+
+/*
+ * Common configuration registers access functions.
+ *
+ * These registers are special and they must me accessed by using a well
+ * specified protocol. Client drivers __must__ do as follow in order to
+ * get access correctly to these registers:
+ *
+ * superio_enter()
+ * superio_select()/superio_outb()/superio_inb()
+ * suprio_exit();
+ *
+ */
+
+static inline int superio_enter(int sioaddr)
+{
+ if (!request_muxed_region(sioaddr, 2, KBUILD_MODNAME))
+ return -EBUSY;
+
+ outb(0x87, sioaddr);
+ outb(0x87, sioaddr);
+
+ return 0;
+}
+
+static inline void superio_select(int sioaddr, int ld)
+{
+ outb(W83627HF_SELECT, sioaddr);
+ outb(ld, sioaddr + 1);
+}
+
+static inline void superio_outb(int sioaddr, int reg, int val)
+{
+ outb(reg, sioaddr);
+ outb(val, sioaddr + 1);
+}
+
+static inline int superio_inb(int sioaddr, int reg)
+{
+ outb(reg, sioaddr);
+ return inb(sioaddr + 1);
+}
+
+static inline void superio_exit(int sioaddr)
+{
+ outb(0xAA, sioaddr);
+
+ release_region(sioaddr, 2);
+}
--
1.7.9.7
next prev parent reply other threads:[~2013-03-24 2:18 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-03-10 23:14 [PATCH v2 0/8] watchdog: w83627hf: Convert to watchdog infrastructure Guenter Roeck
2013-03-10 23:14 ` [PATCH v2 1/7] " Guenter Roeck
2013-03-10 23:14 ` Guenter Roeck
2013-03-10 23:14 ` [PATCH v2 2/7] watchdog: w83627hf: Enable watchdog only once Guenter Roeck
2013-03-19 17:26 ` Pádraig Brady
2013-03-19 17:26 ` Pádraig Brady
2013-03-19 20:02 ` Guenter Roeck
2013-03-19 20:02 ` Guenter Roeck
2013-03-21 18:40 ` Pádraig Brady
2013-03-21 18:40 ` Pádraig Brady
2013-03-10 23:14 ` [PATCH v2 3/7] watchdog: w83627hf: Enable watchdog device only if not already enabled Guenter Roeck
2013-03-10 23:14 ` [PATCH v2 4/7] watchdog: w83627hf: Use helper functions to access superio registers Guenter Roeck
2013-03-10 23:14 ` [PATCH v2 5/7] watchdog: w83627hf: Auto-detect IO address and supported chips Guenter Roeck
2013-03-10 23:14 ` [PATCH v2 6/7] watchdog: w83627hf: Add support for W83697HF and W83697UG Guenter Roeck
2013-03-10 23:15 ` [PATCH v2 7/7] watchdog: Remove drivers " Guenter Roeck
2013-03-10 23:15 ` Guenter Roeck
2013-03-22 20:52 ` [PATCH v2 0/8] watchdog: w83627hf: Convert to watchdog infrastructure Wim Van Sebroeck
2013-03-22 21:09 ` [RFC] winbond Super-I/O MFD driver Wim Van Sebroeck
2013-03-22 21:09 ` Wim Van Sebroeck
2013-03-23 0:28 ` [PATCH v2 0/8] watchdog: w83627hf: Convert to watchdog infrastructure Guenter Roeck
2013-03-23 12:57 ` Wim Van Sebroeck
2013-03-23 15:01 ` Guenter Roeck
2013-03-23 15:15 ` mfd: Core driver for W836{2389}7[T]HF Guenter Roeck
2013-03-23 17:49 ` Guenter Roeck [this message]
2013-03-24 2:39 ` mfd: Core driver for Winbond chips Guenter Roeck
2013-04-09 9:37 ` Samuel Ortiz
2013-04-09 11:36 ` Guenter Roeck
2013-04-09 11:45 ` Wim Van Sebroeck
2013-04-09 16:18 ` Guenter Roeck
2013-04-09 17:31 ` Wim Van Sebroeck
2013-04-10 0:36 ` Guenter Roeck
2013-04-10 20:59 ` Wim Van Sebroeck
2013-04-29 15:00 ` Guenter Roeck
2013-04-09 11:37 ` Wim Van Sebroeck
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130323174914.GA21563@roeck-us.net \
--to=linux@roeck-us.net \
--cc=P@draigBrady.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-watchdog@vger.kernel.org \
--cc=sameo@linux.intel.com \
--cc=wim@iguana.be \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.