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: 28+ 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 ` [PATCH v2 2/7] watchdog: w83627hf: Enable watchdog only once Guenter Roeck
2013-03-19 17:26 ` Pádraig Brady
2013-03-19 20:02 ` Guenter Roeck
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-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-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox