lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20170227101809.10177-1-hdegoede@redhat.com>
Date:   Mon, 27 Feb 2017 11:18:09 +0100
From:   Hans de Goede <hdegoede@...hat.com>
To:     Lee Jones <lee.jones@...aro.org>
Cc:     Hans de Goede <hdegoede@...hat.com>, linux-kernel@...r.kernel.org,
        Bin Gao <bin.gao@...el.com>,
        Felipe Balbi <felipe.balbi@...ux.intel.com>
Subject: [PATCH] mfd: Add Cherrytrail WhiskeyCove PMIC driver

Add mfd driver for Intel CHT WhiskeyCove PMIC, based on various non
upstreamed CHT WhiskeyCove PMIC patches. For now this just adds a minimal
version which implements just enough to get ACPI PMIC opregion support to
work, so that suspend/resume will work on machines with this PMIC.

Cc: Bin Gao <bin.gao@...el.com>
Cc: Felipe Balbi <felipe.balbi@...ux.intel.com>
Signed-off-by: Hans de Goede <hdegoede@...hat.com>
---
 drivers/mfd/Makefile               |   2 +-
 drivers/mfd/intel_soc_pmic_chtwc.c | 175 +++++++++++++++++++++++++++++++++++++
 include/linux/mfd/intel_chtwc.h    |  75 ++++++++++++++++
 3 files changed, 251 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mfd/intel_soc_pmic_chtwc.c
 create mode 100644 include/linux/mfd/intel_chtwc.h

diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index dda4d4f..472ab88 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -205,7 +205,7 @@ obj-$(CONFIG_MFD_DLN2)		+= dln2.o
 obj-$(CONFIG_MFD_RT5033)	+= rt5033.o
 obj-$(CONFIG_MFD_SKY81452)	+= sky81452.o
 
-intel-soc-pmic-objs		:= intel_soc_pmic_core.o intel_soc_pmic_crc.o
+intel-soc-pmic-objs		:= intel_soc_pmic_core.o intel_soc_pmic_crc.o intel_soc_pmic_chtwc.o
 intel-soc-pmic-$(CONFIG_INTEL_PMC_IPC)	+= intel_soc_pmic_bxtwc.o
 obj-$(CONFIG_INTEL_SOC_PMIC)	+= intel-soc-pmic.o
 obj-$(CONFIG_MFD_MT6397)	+= mt6397-core.o
diff --git a/drivers/mfd/intel_soc_pmic_chtwc.c b/drivers/mfd/intel_soc_pmic_chtwc.c
new file mode 100644
index 0000000..d362ba3
--- /dev/null
+++ b/drivers/mfd/intel_soc_pmic_chtwc.c
@@ -0,0 +1,175 @@
+/*
+ * MFD core driver for Intel Cherrytrail Whiskey Cove PMIC
+ * Copyright (C) 2017 Hans de Goede <hdegoede@...hat.com>
+ *
+ * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
+ * Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/intel_chtwc.h>
+#include <linux/mfd/intel_soc_pmic.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+/* PMIC device registers */
+#define REG_ADDR_MASK		0xff00
+#define REG_ADDR_SHIFT		8
+#define REG_OFFSET_MASK		0xff
+
+/* Whiskey Cove PMIC share same ACPI ID between different platforms */
+#define CHT_WC_HRV		3
+
+static struct mfd_cell cht_wc_dev[] = {
+	{
+		.name = "cht_wcove_region",
+	},
+};
+
+/*
+ * The CHT Whiskey Cove covers multiple i2c addresses, with a 1 byte
+ * register address space per i2c address, so we use 16 bit register
+ * addresses where the high 8 bits contain the i2c client address.
+ */
+static int cht_wc_byte_reg_read(void *context, unsigned int reg,
+				unsigned int *val)
+{
+	struct i2c_client *client = context;
+	int ret, orig_addr = client->addr;
+
+	if (reg & REG_ADDR_MASK)
+		client->addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT;
+	else
+		client->addr = CHT_WC_DEVICE1_ADDR;
+	ret = i2c_smbus_read_byte_data(client, reg & REG_OFFSET_MASK);
+	client->addr = orig_addr;
+
+	if (ret < 0)
+		return ret;
+
+	*val = ret;
+	return 0;
+}
+
+static int cht_wc_byte_reg_write(void *context, unsigned int reg,
+				 unsigned int val)
+{
+	struct i2c_client *client = context;
+	int ret, orig_addr = client->addr;
+
+	if (reg & REG_ADDR_MASK)
+		client->addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT;
+	else
+		client->addr = CHT_WC_DEVICE1_ADDR;
+	ret = i2c_smbus_write_byte_data(client, reg & REG_OFFSET_MASK, val);
+	client->addr = orig_addr;
+
+	return ret;
+}
+
+static const struct regmap_config cht_wc_regmap_cfg = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.reg_write = cht_wc_byte_reg_write,
+	.reg_read = cht_wc_byte_reg_read,
+};
+
+static int cht_wc_probe(struct i2c_client *client,
+			const struct i2c_device_id *i2c_id)
+{
+	struct device *dev = &client->dev;
+	struct intel_soc_pmic *pmic;
+	acpi_handle handle;
+	acpi_status status;
+	unsigned long long hrv;
+	int ret;
+
+	handle = ACPI_HANDLE(dev);
+	status = acpi_evaluate_integer(handle, "_HRV", NULL, &hrv);
+	if (ACPI_FAILURE(status)) {
+		dev_err(dev, "Failed to get PMIC hardware revision\n");
+		return -ENODEV;
+	}
+	if (hrv != CHT_WC_HRV) {
+		dev_err(dev, "Invalid PMIC hardware revision: %llu\n", hrv);
+		return -ENODEV;
+	}
+	if (client->irq < 0) {
+		dev_err(dev, "Invalid IRQ\n");
+		return -ENODEV;
+	}
+
+	pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
+	if (!pmic)
+		return -ENOMEM;
+
+	pmic->irq = client->irq;
+	pmic->dev = dev;
+	i2c_set_clientdata(client, pmic);
+
+	pmic->regmap = devm_regmap_init(dev, NULL, client, &cht_wc_regmap_cfg);
+	if (IS_ERR(pmic->regmap)) {
+		ret = PTR_ERR(pmic->regmap);
+		dev_err(dev, "Failed to initialise regmap: %d\n", ret);
+		return ret;
+	}
+
+	ret = mfd_add_devices(dev, -1, cht_wc_dev, ARRAY_SIZE(cht_wc_dev),
+			      NULL, 0, NULL);
+	if (ret) {
+		dev_err(dev, "Failed to add devices: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int cht_wc_remove(struct i2c_client *client)
+{
+	struct intel_soc_pmic *pmic = i2c_get_clientdata(client);
+
+	mfd_remove_devices(pmic->dev);
+
+	return 0;
+}
+
+static const struct i2c_device_id cht_wc_i2c_id[] = {
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, cht_wc_i2c_id);
+
+static const struct acpi_device_id cht_wc_acpi_ids[] = {
+	{ "INT34D3", },
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, cht_wc_acpi_ids);
+
+static struct i2c_driver cht_wc_driver = {
+	.driver	= {
+		.name	= "CHT Whiskey Cove PMIC",
+		.acpi_match_table = ACPI_PTR(cht_wc_acpi_ids),
+	},
+	.probe = cht_wc_probe,
+	.remove	= cht_wc_remove,
+	.id_table = cht_wc_i2c_id,
+};
+
+module_i2c_driver(cht_wc_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Hans de Goede <hdegoede@...hat.com>");
diff --git a/include/linux/mfd/intel_chtwc.h b/include/linux/mfd/intel_chtwc.h
new file mode 100644
index 0000000..1fb356f
--- /dev/null
+++ b/include/linux/mfd/intel_chtwc.h
@@ -0,0 +1,75 @@
+/*
+ * intel_chtwc.h - Header file for Intel Cherrytrail Whiskey Cove PMIC
+ *
+ * Copyright (C) 2017 Hans de Goede <hdegoede@...hat.com>
+ *
+ * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
+ * Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 __INTEL_CHTWC_H__
+#define __INTEL_CHTWC_H__
+
+#define CHT_WC_DEVICE1_ADDR		0x6e
+
+#define CHT_WC_V1P05A_CTRL		0x6e3b
+#define CHT_WC_V1P15_CTRL		0x6e3c
+#define CHT_WC_V1P05A_VSEL		0x6e3d
+#define CHT_WC_V1P15_VSEL		0x6e3e
+#define CHT_WC_V1P8A_CTRL		0x6e56
+#define CHT_WC_V1P8SX_CTRL		0x6e57
+#define CHT_WC_VDDQ_CTRL		0x6e58
+#define CHT_WC_V1P2A_CTRL		0x6e59
+#define CHT_WC_V1P2SX_CTRL		0x6e5a
+#define CHT_WC_V1P8A_VSEL		0x6e5b
+#define CHT_WC_VDDQ_VSEL		0x6e5c
+#define CHT_WC_V2P8SX_CTRL		0x6e5d
+#define CHT_WC_V3P3A_CTRL		0x6e5e
+#define CHT_WC_V3P3SD_CTRL		0x6e5f
+#define CHT_WC_VSDIO_CTRL		0x6e67
+#define CHT_WC_V3P3A_VSEL		0x6e68
+#define CHT_WC_VPROG1A_CTRL		0x6e90
+#define CHT_WC_VPROG1B_CTRL		0x6e91
+#define CHT_WC_VPROG1F_CTRL		0x6e95
+#define CHT_WC_VPROG2D_CTRL		0x6e99
+#define CHT_WC_VPROG3A_CTRL		0x6e9a
+#define CHT_WC_VPROG3B_CTRL		0x6e9b
+#define CHT_WC_VPROG4A_CTRL		0x6e9c
+#define CHT_WC_VPROG4B_CTRL		0x6e9d
+#define CHT_WC_VPROG4C_CTRL		0x6e9e
+#define CHT_WC_VPROG4D_CTRL		0x6e9f
+#define CHT_WC_VPROG5A_CTRL		0x6ea0
+#define CHT_WC_VPROG5B_CTRL		0x6ea1
+#define CHT_WC_VPROG6A_CTRL		0x6ea2
+#define CHT_WC_VPROG6B_CTRL		0x6ea3
+#define CHT_WC_VPROG1A_VSEL		0x6ec0
+#define CHT_WC_VPROG1B_VSEL		0x6ec1
+#define CHT_WC_V1P8SX_VSEL		0x6ec2
+#define CHT_WC_V1P2SX_VSEL		0x6ec3
+#define CHT_WC_V1P2A_VSEL		0x6ec4
+#define CHT_WC_VPROG1F_VSEL		0x6ec5
+#define CHT_WC_VSDIO_VSEL		0x6ec6
+#define CHT_WC_V2P8SX_VSEL		0x6ec7
+#define CHT_WC_V3P3SD_VSEL		0x6ec8
+#define CHT_WC_VPROG2D_VSEL		0x6ec9
+#define CHT_WC_VPROG3A_VSEL		0x6eca
+#define CHT_WC_VPROG3B_VSEL		0x6ecb
+#define CHT_WC_VPROG4A_VSEL		0x6ecc
+#define CHT_WC_VPROG4B_VSEL		0x6ecd
+#define CHT_WC_VPROG4C_VSEL		0x6ece
+#define CHT_WC_VPROG4D_VSEL		0x6ecf
+#define CHT_WC_VPROG5A_VSEL		0x6ed0
+#define CHT_WC_VPROG5B_VSEL		0x6ed1
+#define CHT_WC_VPROG6A_VSEL		0x6ed2
+#define CHT_WC_VPROG6B_VSEL		0x6ed3
+
+#endif
-- 
2.9.3

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ