b/arch/arm64/boot/dts/nvidia/tegra210-nintendo-switch.dts
@@ -1656,7 +1656,7 @@
max77620: max77620@3c {
compatible = "maxim,max77620";
reg = <0x3c>;
- interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_LOW>;
#interrupt-cells = <2>;
interrupt-controller;
@@ -1945,8 +1945,8 @@
max77621_cpu: pmic@1b {
compatible = "maxim,max77621";
reg = <0x1b>;
- interrupt-parent = <&gpio>;
- interrupts = <TEGRA_GPIO(K, 6) IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&gpio>;
+ interrupts = <TEGRA_GPIO(K, 6) IRQ_TYPE_LEVEL_LOW>;
regulator-name = "PPVAR_CPU";
// smaug: 800000..1231250
regulator-min-microvolt = <800000>;
@@ -1969,8 +1969,8 @@
max77621_gpu: pmic@1c {
compatible = "maxim,max77621";
reg = <0x1c>;
- interrupt-parent = <&gpio>;
- interrupts = <TEGRA_GPIO(K, 7) IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&gpio>;
+ interrupts = <TEGRA_GPIO(K, 7) IRQ_TYPE_LEVEL_LOW>;
regulator-name = "PPVAR_GPU";
regulator-min-microvolt = <840000>;
regulator-max-microvolt = <1150000>;
@@ -240,7 +240,10 @@ static void regmap_irq_enable(struct irq_data *data)
if (d->chip->clear_on_unmask)
d->clear_status = true;
- d->mask_buf[irq_data->reg_offset / map->reg_stride] &= ~mask;
+ if (!irq_data->mask_offset)
+ d->mask_buf[irq_data->reg_offset / map->reg_stride] &= ~mask;
+ else
+ d->mask_buf[irq_data->mask_offset / map->reg_stride] &= ~mask;
}
static void regmap_irq_disable(struct irq_data *data)
@@ -249,7 +252,10 @@ static void regmap_irq_disable(struct irq_data *data)
struct regmap *map = d->map;
const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq);
- d->mask_buf[irq_data->reg_offset / map->reg_stride] |= irq_data->mask;
+ if (!irq_data->mask_offset)
+ d->mask_buf[irq_data->reg_offset / map->reg_stride] |=
irq_data->mask;
+ else
+ d->mask_buf[irq_data->mask_offset / map->reg_stride]
|= irq_data->mask;
}
static int regmap_irq_set_type(struct irq_data *data, unsigned int type)
me@archlinux ~/Development/tegra/linux switch-5.0 ●✚ git diff
HEAD drivers/
@@ -240,7 +240,10 @@ static void regmap_irq_enable(struct irq_data *data)
if (d->chip->clear_on_unmask)
d->clear_status = true;
- d->mask_buf[irq_data->reg_offset / map->reg_stride] &= ~mask;
+ if (!irq_data->mask_offset)
+ d->mask_buf[irq_data->reg_offset / map->reg_stride] &= ~mask;
+ else
+ d->mask_buf[irq_data->mask_offset / map->reg_stride] &= ~mask;
}
static void regmap_irq_disable(struct irq_data *data)
@@ -249,7 +252,10 @@ static void regmap_irq_disable(struct irq_data *data)
struct regmap *map = d->map;
const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq);
- d->mask_buf[irq_data->reg_offset / map->reg_stride] |= irq_data->mask;
+ if (!irq_data->mask_offset)
+ d->mask_buf[irq_data->reg_offset / map->reg_stride] |=
irq_data->mask;
+ else
+ d->mask_buf[irq_data->mask_offset / map->reg_stride]
|= irq_data->mask;
}
static int regmap_irq_set_type(struct irq_data *data, unsigned int type)
@@ -585,8 +591,10 @@ int regmap_add_irq_chip(struct regmap *map, int
irq, int irq_flags,
mutex_init(&d->lock);
for (i = 0; i < chip->num_irqs; i++)
- d->mask_buf_def[chip->irqs[i].reg_offset / map->reg_stride]
- |= chip->irqs[i].mask;
+ if (!chip->irqs[i].mask_offset)
+ d->mask_buf_def[chip->irqs[i].reg_offset /
map->reg_stride] |= chip->irqs[i].mask;
+ else
+ d->mask_buf_def[chip->irqs[i].mask_offset /
map->reg_stride] |= chip->irqs[i].mask;
/* Mask all the interrupts by default */
for (i = 0; i < chip->num_regs; i++) {
@@ -191,6 +191,17 @@ config INPUT_MAX77693_HAPTIC
To compile this driver as module, choose M here: the
module will be called max77693-haptic.
+config INPUT_MAX77620_ONOFF
+ tristate "MAX77620 ONOFF support"
+ depends on MFD_MAX77620
+ help
+ Support the ONOFF block of MAX77620 PMICs as an input device
+ reporting power button status.
+
+ To compile this driver as a module, choose M here: the module
+ will be called max77620_onoff.
+
+
config INPUT_MAX8925_ONKEY
tristate "MAX8925 ONKEY support"
depends on MFD_MAX8925
@@ -44,6 +44,7 @@ obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o
obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o
obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
obj-$(CONFIG_INPUT_MAX77693_HAPTIC) += max77693-haptic.o
+obj-$(CONFIG_INPUT_MAX77620_ONOFF) += max77620-onoff.o
obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o
obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o
obj-$(CONFIG_INPUT_MC13783_PWRBUTTON) += mc13783-pwrbutton.o
b/drivers/input/misc/max77620-onoff.c
new file mode 100644
@@ -0,0 +1,149 @@
+/**re--
+ * MAX77620 ONKEY driver
+ *ore--
+ * Copyright (C) 2009 Marvell International Ltd.
+ * Haojian Zhuang <haojian.zhuang@marvell.com>
+ *ore--
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of this
+ * archive for more details.
+ *ore--
+ * 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.
+ *ore--
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */re--
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/interrupt.h>
+#include <linux/regmap.h>
+#include <linux/mfd/max77620.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+
+#define POWERKEY_PRESSED (1 << 2) /* 0/1 -- up/down */
+
+struct max77620_onoff_info {
+ struct input_dev *input;
+ struct regmap *regmap;
+ unsigned int code;
+};
+
+/*
+ * MAX77620 gives us an interrupt when ONKEY is pressed or released.
+ * max77620_set_bits() operates I2C bus and may sleep. So implement
+ * it in thread IRQ handler.
+ */
+static irqreturn_t max77620_onoff_handler(int irq, void *data)
+{
+ struct max77620_onoff_info *info = data;
+ u32 state;
+
+ regmap_read(info->regmap, MAX77620_REG_ONOFFSTAT, &state);
+
+ input_report_key(info->input, info->code, state & POWERKEY_PRESSED);
+ input_sync(info->input);
+
+ return IRQ_HANDLED;
+}
+
+static int max77620_onoff_probe(struct platform_device *pdev)
+{
+ struct max77620_onoff_info *info;
+ int irq[2], error;
+
+ irq[0] = platform_get_irq(pdev, 0);
+ if (irq[0] < 0) {
+ dev_err(&pdev->dev, "No IRQ resource!\n");
+ return -EINVAL;
+ }
+
+ irq[1] = platform_get_irq(pdev, 1);
+ if (irq[1] < 0) {
+ dev_err(&pdev->dev, "No IRQ resource!\n");
+ return -EINVAL;
+ }
+
+ info = devm_kzalloc(&pdev->dev, sizeof(struct max77620_onoff_info),
+ GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!info->regmap) {
+ dev_err(&pdev->dev, "Failed to get parent regmap\n");
+ return -ENODEV;
+ }
+
+ error = device_property_read_u32(&pdev->dev, "linux,code", &info->code);
+ if (error)
+ info->code = KEY_POWER;
+
+ info->input = devm_input_allocate_device(&pdev->dev);
+ if (!info->input)
+ return -ENOMEM;
+
+ info->input->name = "max77620_onoff";
+ info->input->phys = "max77620_onoff/input0";
+ info->input->id.bustype = BUS_I2C;
+ info->input->dev.parent = &pdev->dev;
+ input_set_capability(info->input, EV_KEY, info->code);
+
+ error = devm_request_threaded_irq(&pdev->dev, irq[0], NULL,
+ max77620_onoff_handler, IRQF_ONESHOT,
+ "en0-up", info);
+ if (error < 0) {
+ dev_err(&pdev->dev, "Failed to request IRQ: #%d: %d\n",
+ irq[0], error);
+ return error;
+ }
+
+ error = devm_request_threaded_irq(&pdev->dev, irq[1], NULL,
+ max77620_onoff_handler, IRQF_ONESHOT,
+ "en0-down", info);
+ if (error < 0) {
+ dev_err(&pdev->dev, "Failed to request IRQ: #%d: %d\n",
+ irq[1], error);
+ return error;
+ }
+
+ error = input_register_device(info->input);
+ if (error) {
+ dev_err(&pdev->dev, "Can't register input device: %d\n", error);
+ return error;
+ }
+
+ platform_set_drvdata(pdev, info);
+// device_init_wakeup(&pdev->dev, 1);
+
+ return 0;
+}
+
+static int max77620_onoff_remove(struct platform_device *pdev)
+{
+ device_init_wakeup(&pdev->dev, 0);
+
+ return 0;
+}
+
+static struct platform_driver max77620_onoff_driver = {
+ .driver = {
+ .name = "max77620-onoff",
+ },
+ .probe = max77620_onoff_probe,
+ .remove = max77620_onoff_remove,
+};
+module_platform_driver(max77620_onoff_driver);
+
+MODULE_DESCRIPTION("Maxim MAX77620 ONOFF driver");
+MODULE_AUTHOR("Billy Laws <blaws05@gmail.com>");
+MODULE_LICENSE("GPL");
@@ -36,6 +36,12 @@
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
+#include <linux/delay.h>
+
+static const struct resource onoff_resources[] = {
+ DEFINE_RES_IRQ(MAX77620_IRQ_ONOFF_EN0_R),
+ DEFINE_RES_IRQ(MAX77620_IRQ_ONOFF_EN0_F),
+};
static const struct resource gpio_resources[] = {
DEFINE_RES_IRQ(MAX77620_IRQ_TOP_GPIO),
@@ -65,14 +71,21 @@ static const struct regmap_irq max77620_top_irqs[] = {
REGMAP_IRQ_REG(MAX77620_IRQ_LBT_MBATLOW, 1, MAX77620_IRQ_LBM_MASK),
REGMAP_IRQ_REG(MAX77620_IRQ_LBT_TJALRM1, 1, MAX77620_IRQ_TJALRM1_MASK),
REGMAP_IRQ_REG(MAX77620_IRQ_LBT_TJALRM2, 1, MAX77620_IRQ_TJALRM2_MASK),
+ REGMAP_IRQ_REG2(MAX77620_IRQ_ONOFF_EN0_R, 6, 5,
MAX77620_IRQ_ONOFF_EN0_R_MASK),
+ REGMAP_IRQ_REG2(MAX77620_IRQ_ONOFF_EN0_F, 6, 5,
MAX77620_IRQ_ONOFF_EN0_F_MASK),
};
+
static const struct mfd_cell max77620_children[] = {
{ .name = "max77620-pinctrl", },
{ .name = "max77620-clock", },
{ .name = "max77620-pmic", },
{ .name = "max77620-watchdog", },
{
+ .name = "max77620-onoff",
+ .resources = onoff_resources,
+ .num_resources = ARRAY_SIZE(onoff_resources),
+ }, {
.name = "max77620-gpio",