Unverified Commit c67bb844 authored by Mark Brown's avatar Mark Brown
Browse files

regulator: Use container_of_const() when all types are

Merge series from Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>:

Use container_of_const(), which is preferred over container_of(), when
the argument 'ptr' and returned pointer are already const, for better
code safety and readability.

Some drivers already have const everywhere, so container_of_const can be
directly used. In few other drivers, the final pointer can be constified
that way.
parents fba27fe5 6341646f
Loading
Loading
Loading
Loading
+161 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/nxp,pf1550.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: NXP PF1550 Power Management IC

maintainers:
  - Samuel Kayode <samuel.kayode@savoirfairelinux.com>

description:
  PF1550 PMIC provides battery charging and power supply for low power IoT and
  wearable applications. This device consists of an i2c controlled MFD that
  includes regulators, battery charging and an onkey/power button.

$ref: /schemas/power/supply/power-supply.yaml

properties:
  compatible:
    const: nxp,pf1550

  reg:
    maxItems: 1

  interrupts:
    maxItems: 1

  wakeup-source: true

  regulators:
    type: object
    additionalProperties: false

    patternProperties:
      "^(ldo[1-3]|sw[1-3]|vrefddr)$":
        type: object
        $ref: /schemas/regulator/regulator.yaml
        description:
          regulator configuration for ldo1-3, buck converters(sw1-3)
          and DDR termination reference voltage (vrefddr)
        unevaluatedProperties: false

  monitored-battery:
    description: |
      A phandle to a monitored battery node that contains a valid value
      for:
      constant-charge-voltage-max-microvolt.

  nxp,thermal-regulation-celsius:
    description:
      Temperature threshold for thermal regulation of charger in celsius.
    enum: [ 80, 95, 110, 125 ]

  nxp,min-system-microvolt:
    description:
      System specific lower limit voltage.
    enum: [ 3500000, 3700000, 4300000 ]

  nxp,disable-key-power:
    type: boolean
    description:
      Disable power-down using a long key-press. The onkey driver will remove
      support for the KEY_POWER key press when triggered using a long press of
      the onkey.

required:
  - compatible
  - reg
  - interrupts

unevaluatedProperties: false

examples:
  - |
    #include <dt-bindings/interrupt-controller/irq.h>
    #include <dt-bindings/input/linux-event-codes.h>

    battery: battery-cell {
        compatible = "simple-battery";
        constant-charge-voltage-max-microvolt = <4400000>;
    };

    i2c {
        #address-cells = <1>;
        #size-cells = <0>;

        pmic@8 {
            compatible = "nxp,pf1550";
            reg = <0x8>;

            interrupt-parent = <&gpio1>;
            interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
            wakeup-source;
            monitored-battery = <&battery>;
            nxp,min-system-microvolt = <4300000>;
            nxp,thermal-regulation-celsius = <80>;

            regulators {
                sw1_reg: sw1 {
                    regulator-name = "sw1";
                    regulator-min-microvolt = <600000>;
                    regulator-max-microvolt = <1387500>;
                    regulator-always-on;
                    regulator-ramp-delay = <6250>;

                    regulator-state-mem {
                        regulator-on-in-suspend;
                        regulator-suspend-min-microvolt = <1270000>;
                    };
                };

                sw2_reg: sw2 {
                    regulator-name = "sw2";
                    regulator-min-microvolt = <600000>;
                    regulator-max-microvolt = <1387500>;
                    regulator-always-on;

                    regulator-state-mem {
                        regulator-on-in-suspend;
                    };
                };

                sw3_reg: sw3 {
                    regulator-name = "sw3";
                    regulator-min-microvolt = <1800000>;
                    regulator-max-microvolt = <3300000>;
                    regulator-always-on;

                    regulator-state-mem {
                        regulator-on-in-suspend;
                    };
                };

                vldo1_reg: ldo1 {
                    regulator-name = "ldo1";
                    regulator-min-microvolt = <750000>;
                    regulator-max-microvolt = <3300000>;
                    regulator-always-on;

                    regulator-state-mem {
                        regulator-off-in-suspend;
                    };
                };

                vldo2_reg: ldo2 {
                    regulator-name = "ldo2";
                    regulator-min-microvolt = <1800000>;
                    regulator-max-microvolt = <3300000>;
                    regulator-always-on;
                };

                vldo3_reg: ldo3 {
                    regulator-name = "ldo3";
                    regulator-min-microvolt = <750000>;
                    regulator-max-microvolt = <3300000>;
                    regulator-always-on;
                };
            };
        };
    };
+11 −0
Original line number Diff line number Diff line
@@ -18636,6 +18636,17 @@ S: Maintained
F:	Documentation/devicetree/bindings/regulator/nxp,pf5300.yaml
F:	drivers/regulator/pf530x-regulator.c
NXP PF1550 PMIC MFD DRIVER
M:	Samuel Kayode <samuel.kayode@savoirfairelinux.com>
L:	imx@lists.linux.dev
S:	Maintained
F:	Documentation/devicetree/bindings/mfd/nxp,pf1550.yaml
F:	drivers/input/misc/pf1550-onkey.c
F:	drivers/mfd/pf1550.c
F:	drivers/power/supply/pf1550-charger.c
F:	drivers/regulator/pf1550-regulator.c
F:	include/linux/mfd/pfd1550.h
NXP PF8100/PF8121A/PF8200 PMIC REGULATOR DEVICE DRIVER
M:	Jagan Teki <jagan@amarulasolutions.com>
S:	Maintained
+11 −0
Original line number Diff line number Diff line
@@ -190,6 +190,17 @@ config INPUT_PCSPKR
	  To compile this driver as a module, choose M here: the
	  module will be called pcspkr.

config INPUT_PF1550_ONKEY
	tristate "NXP PF1550 Onkey support"
	depends on MFD_PF1550
	help
	  Say Y here if you want support for PF1550 PMIC. Onkey can trigger
	  release and 1s(push hold), 2s, 3s, 4s, 8s interrupt for long press
	  detect.

	  To compile this driver as a module, choose M here. The module will be
	  called pf1550-onkey.

config INPUT_PM8941_PWRKEY
	tristate "Qualcomm PM8941 power key support"
	depends on MFD_SPMI_PMIC
+1 −0
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ obj-$(CONFIG_INPUT_PALMAS_PWRBUTTON) += palmas-pwrbutton.o
obj-$(CONFIG_INPUT_PCAP)		+= pcap_keys.o
obj-$(CONFIG_INPUT_PCF8574)		+= pcf8574_keypad.o
obj-$(CONFIG_INPUT_PCSPKR)		+= pcspkr.o
obj-$(CONFIG_INPUT_PF1550_ONKEY)	+= pf1550-onkey.o
obj-$(CONFIG_INPUT_PM8941_PWRKEY)	+= pm8941-pwrkey.o
obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR)	+= pm8xxx-vibrator.o
obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY)	+= pmic8xxx-pwrkey.o
+197 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * Driver for the PF1550 ONKEY
 * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
 *
 * Portions Copyright (c) 2025 Savoir-faire Linux Inc.
 * Samuel Kayode <samuel.kayode@savoirfairelinux.com>
 */

#include <linux/err.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mfd/pf1550.h>
#include <linux/platform_device.h>

#define PF1550_ONKEY_IRQ_NR	6

struct onkey_drv_data {
	struct device *dev;
	const struct pf1550_ddata *pf1550;
	bool wakeup;
	struct input_dev *input;
};

static irqreturn_t pf1550_onkey_irq_handler(int irq, void *data)
{
	struct onkey_drv_data *onkey = data;
	struct platform_device *pdev = to_platform_device(onkey->dev);
	int i, state, irq_type = -1;

	for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++)
		if (irq == platform_get_irq(pdev, i))
			irq_type = i;

	switch (irq_type) {
	case PF1550_ONKEY_IRQ_PUSHI:
		state = 0;
		break;
	case PF1550_ONKEY_IRQ_1SI:
	case PF1550_ONKEY_IRQ_2SI:
	case PF1550_ONKEY_IRQ_3SI:
	case PF1550_ONKEY_IRQ_4SI:
	case PF1550_ONKEY_IRQ_8SI:
		state = 1;
		break;
	default:
		dev_err(onkey->dev, "onkey interrupt: irq %d occurred\n",
			irq_type);
		return IRQ_HANDLED;
	}

	input_event(onkey->input, EV_KEY, KEY_POWER, state);
	input_sync(onkey->input);

	return IRQ_HANDLED;
}

static int pf1550_onkey_probe(struct platform_device *pdev)
{
	struct onkey_drv_data *onkey;
	struct input_dev *input;
	bool key_power = false;
	int i, irq, error;

	onkey = devm_kzalloc(&pdev->dev, sizeof(*onkey), GFP_KERNEL);
	if (!onkey)
		return -ENOMEM;

	onkey->dev = &pdev->dev;

	onkey->pf1550 = dev_get_drvdata(pdev->dev.parent);
	if (!onkey->pf1550->regmap)
		return dev_err_probe(&pdev->dev, -ENODEV,
				     "failed to get regmap\n");

	onkey->wakeup = device_property_read_bool(pdev->dev.parent,
						  "wakeup-source");

	if (device_property_read_bool(pdev->dev.parent,
				      "nxp,disable-key-power")) {
		error = regmap_clear_bits(onkey->pf1550->regmap,
					  PF1550_PMIC_REG_PWRCTRL1,
					  PF1550_ONKEY_RST_EN);
		if (error)
			return dev_err_probe(&pdev->dev, error,
					     "failed: disable turn system off");
	} else {
		key_power = true;
	}

	input = devm_input_allocate_device(&pdev->dev);
	if (!input)
		return dev_err_probe(&pdev->dev, -ENOMEM,
				     "failed to allocate the input device\n");

	input->name = pdev->name;
	input->phys = "pf1550-onkey/input0";
	input->id.bustype = BUS_HOST;

	if (key_power)
		input_set_capability(input, EV_KEY, KEY_POWER);

	onkey->input = input;
	platform_set_drvdata(pdev, onkey);

	for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++) {
		irq = platform_get_irq(pdev, i);
		if (irq < 0)
			return irq;

		error = devm_request_threaded_irq(&pdev->dev, irq, NULL,
						  pf1550_onkey_irq_handler,
						  IRQF_NO_SUSPEND,
						  "pf1550-onkey", onkey);
		if (error)
			return dev_err_probe(&pdev->dev, error,
					     "failed: irq request (IRQ: %d)\n",
					     i);
	}

	error = input_register_device(input);
	if (error)
		return dev_err_probe(&pdev->dev, error,
				     "failed to register input device\n");

	device_init_wakeup(&pdev->dev, onkey->wakeup);

	return 0;
}

static int pf1550_onkey_suspend(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct onkey_drv_data *onkey = platform_get_drvdata(pdev);
	int i, irq;

	if (!device_may_wakeup(&pdev->dev))
		regmap_write(onkey->pf1550->regmap,
			     PF1550_PMIC_REG_ONKEY_INT_MASK0,
			     ONKEY_IRQ_PUSHI | ONKEY_IRQ_1SI | ONKEY_IRQ_2SI |
			     ONKEY_IRQ_3SI | ONKEY_IRQ_4SI | ONKEY_IRQ_8SI);
	else
		for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++) {
			irq = platform_get_irq(pdev, i);
			if (irq > 0)
				enable_irq_wake(irq);
		}

	return 0;
}

static int pf1550_onkey_resume(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct onkey_drv_data *onkey = platform_get_drvdata(pdev);
	int i, irq;

	if (!device_may_wakeup(&pdev->dev))
		regmap_write(onkey->pf1550->regmap,
			     PF1550_PMIC_REG_ONKEY_INT_MASK0,
			     ~((u8)(ONKEY_IRQ_PUSHI | ONKEY_IRQ_1SI |
			     ONKEY_IRQ_2SI | ONKEY_IRQ_3SI | ONKEY_IRQ_4SI |
			     ONKEY_IRQ_8SI)));
	else
		for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++) {
			irq = platform_get_irq(pdev, i);
			if (irq > 0)
				disable_irq_wake(irq);
		}

	return 0;
}

static SIMPLE_DEV_PM_OPS(pf1550_onkey_pm_ops, pf1550_onkey_suspend,
			 pf1550_onkey_resume);

static const struct platform_device_id pf1550_onkey_id[] = {
	{ "pf1550-onkey", },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, pf1550_onkey_id);

static struct platform_driver pf1550_onkey_driver = {
	.driver = {
		.name = "pf1550-onkey",
		.pm   = pm_sleep_ptr(&pf1550_onkey_pm_ops),
	},
	.probe = pf1550_onkey_probe,
	.id_table = pf1550_onkey_id,
};
module_platform_driver(pf1550_onkey_driver);

MODULE_AUTHOR("Freescale Semiconductor");
MODULE_DESCRIPTION("PF1550 onkey Driver");
MODULE_LICENSE("GPL");
Loading