meta-st-stm32mp/recipes-kernel/linux/linux-stm32mp/4.19/4.19.9/0022-ARM-stm32mp1-r0-rc2-MF...

782 lines
22 KiB
Diff

From aed35270f0be1c5c61a028d7c183e60269f3abe3 Mon Sep 17 00:00:00 2001
From: Christophe Priouzeau <christophe.priouzeau@st.com>
Date: Mon, 26 Nov 2018 14:41:37 +0100
Subject: [PATCH 22/52] ARM-stm32mp1-r0-rc2-MFD-IRQ
---
.../interrupt-controller/st,stm32-exti.txt | 34 +++++-
.../devicetree/bindings/mfd/st,stpmic1.txt | 2 +-
Documentation/devicetree/bindings/mfd/syscon.txt | 1 +
drivers/irqchip/irq-stm32-exti.c | 133 ++++++++++++++++++---
drivers/mfd/stm32-pwr.c | 131 +++++++++-----------
drivers/mfd/stpmic1.c | 16 +--
drivers/mfd/syscon.c | 19 +++
drivers/mfd/wm8994-core.c | 15 +++
include/linux/mfd/stpmic1.h | 1 -
9 files changed, 247 insertions(+), 105 deletions(-)
diff --git a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt
index 6a36bf6..abcf816 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt
@@ -14,7 +14,23 @@ Required properties:
(only needed for exti controller with multiple exti under
same parent interrupt: st,stm32-exti and st,stm32h7-exti)
-Example:
+Optional properties:
+
+- hwlocks: reference to a phandle of a hardware spinlock provider node.
+
+Exti could have several parent interrupt controllers. In this case child nodes
+are used to describe those "extra" parent controllers. Properties to use are:
+
+- interrupt-controller: Indentifies the node as an interrupt controller
+- #interrupt-cells: Specifies the number of cells to encode an interrupt
+ specifier, shall be 2
+- interrupt-parent: Phandle to the interrupt parent node.
+- st,irq-number: Interrupt number mapped on the parent.
+
+See example 2.
+
+
+Example 1:
exti: interrupt-controller@40013c00 {
compatible = "st,stm32-exti";
@@ -23,3 +39,19 @@ exti: interrupt-controller@40013c00 {
reg = <0x40013C00 0x400>;
interrupts = <1>, <2>, <3>, <6>, <7>, <8>, <9>, <10>, <23>, <40>, <41>, <42>, <62>, <76>;
};
+
+Example 2:
+
+exti: interrupt-controller@5000d000 {
+ compatible = "st,stm32mp1-exti", "syscon";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ reg = <0x5000d000 0x400>;
+
+ exti_pwr: exti-pwr {
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&pwr>;
+ st,irq-number = <6>;
+ };
+};
diff --git a/Documentation/devicetree/bindings/mfd/st,stpmic1.txt b/Documentation/devicetree/bindings/mfd/st,stpmic1.txt
index 54b64e2..0fab08a 100644
--- a/Documentation/devicetree/bindings/mfd/st,stpmic1.txt
+++ b/Documentation/devicetree/bindings/mfd/st,stpmic1.txt
@@ -4,7 +4,6 @@ Required parent device properties:
- compatible: "st,stpmic1"
- reg: The I2C slave address for the STPMIC1 chip.
- interrupts: The interrupt lines the device is connected to.
- The second interrupt is used for wake-up.
- #interrupt-cells: Should be 2.
- interrupt-controller: Describes the STPMIC1 as an interrupt
controller (has its own domain). Interrupt number are the following:
@@ -81,6 +80,7 @@ Optional parent device properties:
-bit 5: SW_OUT discharge is enabled
-bit 6: VBUS_OTG detection is enabled
-bit 7: BOOST_OVP is disabled
+- wakeup-source: bool flag to indicate this device has wakeup capabilities
STPMIC1 consists in a varied group of sub-devices.
Each sub-device binding is be described in own documentation file.
diff --git a/Documentation/devicetree/bindings/mfd/syscon.txt b/Documentation/devicetree/bindings/mfd/syscon.txt
index 25d9e9c..a9aaa51 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.txt
+++ b/Documentation/devicetree/bindings/mfd/syscon.txt
@@ -17,6 +17,7 @@ Optional property:
- reg-io-width: the size (in bytes) of the IO accesses that should be
performed on the device.
- hwlocks: reference to a phandle of a hardware spinlock provider node.
+- clocks: phandle to the syscon clock
Examples:
gpr: iomuxc-gpr@20e0000 {
diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
index e185ed8..9cc15f1 100644
--- a/drivers/irqchip/irq-stm32-exti.c
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -6,6 +6,7 @@
*/
#include <linux/bitops.h>
+#include <linux/hwspinlock.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
@@ -20,6 +21,8 @@
#define IRQS_PER_BANK 32
+#define HWSPINLOCK_TIMEOUT 5 /* msec */
+
struct stm32_exti_bank {
u32 imr_ofst;
u32 emr_ofst;
@@ -47,6 +50,7 @@ struct stm32_exti_drv_data {
struct stm32_exti_chip_data {
struct stm32_exti_host_data *host_data;
const struct stm32_exti_bank *reg_bank;
+ struct hwspinlock *hwlock;
struct raw_spinlock rlock;
u32 wake_active;
u32 mask_cache;
@@ -275,25 +279,34 @@ static int stm32_irq_set_type(struct irq_data *d, unsigned int type)
struct stm32_exti_chip_data *chip_data = gc->private;
const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
u32 rtsr, ftsr;
- int err;
+ int err = 0;
irq_gc_lock(gc);
+ if (chip_data->hwlock)
+ err = hwspin_lock_timeout(chip_data->hwlock,
+ HWSPINLOCK_TIMEOUT);
+
+ if (err)
+ goto unlock;
+
rtsr = irq_reg_readl(gc, stm32_bank->rtsr_ofst);
ftsr = irq_reg_readl(gc, stm32_bank->ftsr_ofst);
err = stm32_exti_set_type(d, type, &rtsr, &ftsr);
- if (err) {
- irq_gc_unlock(gc);
- return err;
- }
+ if (err)
+ goto unspinlock;
irq_reg_writel(gc, rtsr, stm32_bank->rtsr_ofst);
irq_reg_writel(gc, ftsr, stm32_bank->ftsr_ofst);
+unspinlock:
+ if (chip_data->hwlock)
+ hwspin_unlock(chip_data->hwlock);
+unlock:
irq_gc_unlock(gc);
- return 0;
+ return err;
}
static void stm32_chip_suspend(struct stm32_exti_chip_data *chip_data,
@@ -457,22 +470,36 @@ static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type)
const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
void __iomem *base = chip_data->host_data->base;
u32 rtsr, ftsr;
- int err;
+ int err = 0;
raw_spin_lock(&chip_data->rlock);
+
+ if (chip_data->hwlock)
+ err = hwspin_lock_timeout(chip_data->hwlock,
+ HWSPINLOCK_TIMEOUT);
+
+ if (err)
+ goto unlock;
+
rtsr = readl_relaxed(base + stm32_bank->rtsr_ofst);
ftsr = readl_relaxed(base + stm32_bank->ftsr_ofst);
err = stm32_exti_set_type(d, type, &rtsr, &ftsr);
- if (err) {
- raw_spin_unlock(&chip_data->rlock);
- return err;
- }
+ if (err)
+ goto unspinlock;
writel_relaxed(rtsr, base + stm32_bank->rtsr_ofst);
writel_relaxed(ftsr, base + stm32_bank->ftsr_ofst);
+
+unspinlock:
+ if (chip_data->hwlock)
+ hwspin_unlock(chip_data->hwlock);
+unlock:
raw_spin_unlock(&chip_data->rlock);
+ if (d->parent_data->chip)
+ irq_chip_set_type_parent(d, type);
+
return 0;
}
@@ -490,6 +517,9 @@ static int stm32_exti_h_set_wake(struct irq_data *d, unsigned int on)
raw_spin_unlock(&chip_data->rlock);
+ if (d->parent_data->chip)
+ irq_chip_set_wake_parent(d, on);
+
return 0;
}
@@ -502,6 +532,12 @@ static int stm32_exti_h_set_affinity(struct irq_data *d,
return -EINVAL;
}
+static void stm32_exti_h_ack(struct irq_data *d)
+{
+ if (d->parent_data->chip)
+ irq_chip_ack_parent(d);
+}
+
#ifdef CONFIG_PM
static int stm32_exti_h_suspend(void)
{
@@ -547,6 +583,7 @@ static inline void stm32_exti_h_syscore_init(void) {}
static struct irq_chip stm32_exti_h_chip = {
.name = "stm32-exti-h",
.irq_eoi = stm32_exti_h_eoi,
+ .irq_ack = stm32_exti_h_ack,
.irq_mask = stm32_exti_h_mask,
.irq_unmask = stm32_exti_h_unmask,
.irq_retrigger = irq_chip_retrigger_hierarchy,
@@ -574,15 +611,29 @@ static int stm32_exti_h_domain_alloc(struct irq_domain *dm,
irq_domain_set_hwirq_and_chip(dm, virq, hwirq,
&stm32_exti_h_chip, chip_data);
- p_irq = stm32_exti_to_irq(host_data->drv_data, hwirq);
- if (p_irq >= 0) {
+ /*
+ * EXTI 55 to 60 are mapped to PWR interrupt controller.
+ * The hwirq translation is done diferently than for GIC.
+ */
+ if (hwirq >= 55 && hwirq <= 60) {
p_fwspec.fwnode = dm->parent->fwnode;
- p_fwspec.param_count = 3;
- p_fwspec.param[0] = GIC_SPI;
- p_fwspec.param[1] = p_irq;
- p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH;
+ p_fwspec.param_count = 2;
+ p_fwspec.param[0] = hwirq - 55;
+ p_fwspec.param[1] = fwspec->param[1];
return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec);
+ } else {
+ p_irq = stm32_exti_to_irq(host_data->drv_data, hwirq);
+ if (p_irq >= 0) {
+ p_fwspec.fwnode = dm->parent->fwnode;
+ p_fwspec.param_count = 3;
+ p_fwspec.param[0] = GIC_SPI;
+ p_fwspec.param[1] = p_irq;
+ p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH;
+
+ return irq_domain_alloc_irqs_parent(dm, virq, 1,
+ &p_fwspec);
+ }
}
return 0;
@@ -665,6 +716,7 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
int nr_irqs, ret, i;
struct irq_chip_generic *gc;
struct irq_domain *domain;
+ struct hwspinlock *hwlock = NULL;
host_data = stm32_exti_host_init(drv_data, node);
if (!host_data)
@@ -687,12 +739,22 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
goto out_free_domain;
}
+ /* hwspinlock is optional */
+ ret = of_hwspin_lock_get_id(node, 0);
+ if (ret < 0) {
+ if (ret == -EPROBE_DEFER)
+ goto out_free_domain;
+ } else {
+ hwlock = hwspin_lock_request_specific(ret);
+ }
+
for (i = 0; i < drv_data->bank_nr; i++) {
const struct stm32_exti_bank *stm32_bank;
struct stm32_exti_chip_data *chip_data;
stm32_bank = drv_data->exti_banks[i];
chip_data = stm32_exti_chip_init(host_data, i, node);
+ chip_data->hwlock = hwlock;
gc = irq_get_domain_generic_chip(domain, i * IRQS_PER_BANK);
@@ -760,11 +822,12 @@ __init stm32_exti_hierarchy_init(const struct stm32_exti_drv_data *drv_data,
{
struct irq_domain *parent_domain, *domain;
struct stm32_exti_host_data *host_data;
+ struct device_node *child;
int ret, i;
parent_domain = irq_find_host(parent);
if (!parent_domain) {
- pr_err("interrupt-parent not found\n");
+ pr_err("GIC interrupt-parent not found\n");
return -EINVAL;
}
@@ -786,6 +849,40 @@ __init stm32_exti_hierarchy_init(const struct stm32_exti_drv_data *drv_data,
goto out_unmap;
}
+ for_each_child_of_node(node, child) {
+ struct device_node *parent_node;
+ u32 nirqs;
+
+ parent_node = of_irq_find_parent(child);
+ parent_domain = irq_find_host(parent_node);
+
+ if (!parent_domain) {
+ pr_err("%s: child interrupt-parent not found\n",
+ child->name);
+ ret = -EINVAL;
+ goto out_unmap;
+ }
+
+ ret = of_property_read_u32(child, "st,irq-number", &nirqs);
+ if (ret != 0 || nirqs == 0) {
+ pr_err("%s: Missing or bad irq-number property\n"
+ , __func__);
+ ret = -EINVAL;
+ goto out_unmap;
+ }
+
+ domain = irq_domain_add_hierarchy(parent_domain, 0, nirqs,
+ child,
+ &stm32_exti_h_domain_ops,
+ host_data);
+ if (!domain) {
+ pr_err("%s: Could not register exti domain.\n",
+ node->name);
+ ret = -ENOMEM;
+ goto out_unmap;
+ }
+ }
+
stm32_exti_h_syscore_init();
return 0;
diff --git a/drivers/mfd/stm32-pwr.c b/drivers/mfd/stm32-pwr.c
index 377e2f5..206a933 100644
--- a/drivers/mfd/stm32-pwr.c
+++ b/drivers/mfd/stm32-pwr.c
@@ -5,7 +5,9 @@
*/
#include <linux/arm-smccc.h>
+#include <linux/irqchip.h>
#include <linux/irqchip/chained_irq.h>
+#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <asm/exception.h>
@@ -45,7 +47,6 @@ enum wkup_pull_setting {
} \
struct stm32_pwr_data {
- struct device *dev; /* self device */
void __iomem *base; /* IO Memory base address */
struct irq_domain *domain; /* Domain for this controller */
int irq; /* Parent interrupt */
@@ -53,25 +54,19 @@ struct stm32_pwr_data {
static void stm32_pwr_irq_ack(struct irq_data *d)
{
- struct stm32_pwr_data *priv = d->domain->host_data;
-
- dev_dbg(priv->dev, "irq:%lu\n", d->hwirq);
+ pr_debug("irq:%lu\n", d->hwirq);
SMC(STM32_SVC_PWR, STM32_SET_BITS, WKUPCR, BIT(d->hwirq));
}
static void stm32_pwr_irq_mask(struct irq_data *d)
{
- struct stm32_pwr_data *priv = d->domain->host_data;
-
- dev_dbg(priv->dev, "irq:%lu\n", d->hwirq);
+ pr_debug("irq:%lu\n", d->hwirq);
SMC(STM32_SVC_PWR, STM32_CLEAR_BITS, MPUWKUPENR, BIT(d->hwirq));
}
static void stm32_pwr_irq_unmask(struct irq_data *d)
{
- struct stm32_pwr_data *priv = d->domain->host_data;
-
- dev_dbg(priv->dev, "irq:%lu\n", d->hwirq);
+ pr_debug("irq:%lu\n", d->hwirq);
SMC(STM32_SVC_PWR, STM32_SET_BITS, MPUWKUPENR, BIT(d->hwirq));
}
@@ -79,7 +74,7 @@ static int stm32_pwr_irq_set_wake(struct irq_data *d, unsigned int on)
{
struct stm32_pwr_data *priv = d->domain->host_data;
- dev_dbg(priv->dev, "irq:%lu on:%d\n", d->hwirq, on);
+ pr_debug("irq:%lu on:%d\n", d->hwirq, on);
if (on)
enable_irq_wake(priv->irq);
else
@@ -95,7 +90,7 @@ static int stm32_pwr_irq_set_type(struct irq_data *d, unsigned int flow_type)
u32 wkupcr;
int en;
- dev_dbg(priv->dev, "irq:%lu\n", d->hwirq);
+ pr_debug("irq:%lu\n", d->hwirq);
en = readl_relaxed(priv->base + MPUWKUPENR) & BIT(pin_id);
/* reference manual request to disable the wakeup pin while
@@ -115,6 +110,7 @@ static int stm32_pwr_irq_set_type(struct irq_data *d, unsigned int flow_type)
default:
return -EINVAL;
}
+
SMC(STM32_SVC_PWR, STM32_WRITE, WKUPCR, wkupcr);
if (en)
@@ -124,7 +120,7 @@ static int stm32_pwr_irq_set_type(struct irq_data *d, unsigned int flow_type)
}
static struct irq_chip stm32_pwr_irq_chip = {
- .name = "stm32_pwr-irq",
+ .name = "stm32-pwr-irq",
.irq_ack = stm32_pwr_irq_ack,
.irq_mask = stm32_pwr_irq_mask,
.irq_unmask = stm32_pwr_irq_unmask,
@@ -132,29 +128,23 @@ static struct irq_chip stm32_pwr_irq_chip = {
.irq_set_wake = stm32_pwr_irq_set_wake,
};
-static int stm32_pwr_irq_map(struct irq_domain *h, unsigned int virq,
- irq_hw_number_t hw)
-{
- irq_set_chip_and_handler(virq, &stm32_pwr_irq_chip, handle_edge_irq);
- return 0;
-}
-
static int stm32_pwr_irq_set_pull_config(struct irq_domain *d, int pin_id,
enum wkup_pull_setting config)
{
struct stm32_pwr_data *priv = d->host_data;
u32 wkupcr;
- dev_dbg(priv->dev, "irq:%d pull config:0x%x\n", pin_id, config);
+ pr_debug("irq:%d pull config:0x%x\n", pin_id, config);
if (config >= WKUP_PULL_RESERVED) {
- dev_err(priv->dev, "%s: bad irq pull config\n", __func__);
+ pr_err("%s: bad irq pull config\n", __func__);
return -EINVAL;
}
wkupcr = readl_relaxed(priv->base + WKUPCR);
wkupcr &= ~((WKUP_PULL_MASK) << (WKUP_PULL_SHIFT + pin_id * 2));
wkupcr |= (config & WKUP_PULL_MASK) << (WKUP_PULL_SHIFT + pin_id * 2);
+
SMC(STM32_SVC_PWR, STM32_WRITE, WKUPCR, wkupcr);
return 0;
@@ -164,10 +154,8 @@ static int stm32_pwr_xlate(struct irq_domain *d, struct device_node *ctrlr,
const u32 *intspec, unsigned int intsize,
irq_hw_number_t *out_hwirq, unsigned int *out_type)
{
- struct stm32_pwr_data *priv = d->host_data;
-
if (WARN_ON(intsize < 3)) {
- dev_err(priv->dev, "%s: bad irq config parameters\n", __func__);
+ pr_err("%s: bad irq config parameters\n", __func__);
return -EINVAL;
}
@@ -177,9 +165,23 @@ static int stm32_pwr_xlate(struct irq_domain *d, struct device_node *ctrlr,
return stm32_pwr_irq_set_pull_config(d, intspec[0], intspec[2]);
}
+static int stm32_pwr_alloc(struct irq_domain *d, unsigned int virq,
+ unsigned int nr_irqs, void *data)
+{
+ struct irq_fwspec *fwspec = data;
+ irq_hw_number_t hwirq;
+
+ hwirq = fwspec->param[0];
+ irq_domain_set_info(d, virq, hwirq, &stm32_pwr_irq_chip, d->host_data,
+ handle_edge_irq, NULL, NULL);
+
+ return 0;
+}
+
static const struct irq_domain_ops stm32_pwr_irq_domain_ops = {
- .map = stm32_pwr_irq_map,
+ .alloc = stm32_pwr_alloc,
.xlate = stm32_pwr_xlate,
+ .free = irq_domain_free_irqs_common,
};
/*
@@ -195,9 +197,10 @@ static void stm32_pwr_handle_irq(struct irq_desc *desc)
wkupfr = readl_relaxed(priv->base + WKUPFR);
wkupenr = readl_relaxed(priv->base + MPUWKUPENR);
+
for (i = 0; i < NB_WAKEUPPINS; i++) {
if ((wkupfr & BIT(i)) && (wkupenr & BIT(i))) {
- dev_dbg(priv->dev, "handle wkup irq:%d\n", i);
+ pr_debug("handle wkup irq:%d\n", i);
generic_handle_irq(irq_find_mapping(priv->domain, i));
}
}
@@ -205,27 +208,21 @@ static void stm32_pwr_handle_irq(struct irq_desc *desc)
chained_irq_exit(chip, desc);
}
-static int stm32_pwr_probe(struct platform_device *pdev)
+static int __init stm32_pwr_init(struct device_node *np,
+ struct device_node *parent)
{
- struct device *dev = &pdev->dev;
- struct device_node *np = pdev->dev.of_node;
struct stm32_pwr_data *priv;
-
- struct resource *res;
int ret;
- priv = devm_kzalloc(dev, sizeof(struct stm32_pwr_data), GFP_KERNEL);
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
- platform_set_drvdata(pdev, priv);
- priv->dev = dev;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->base = devm_ioremap_resource(&pdev->dev, res);
+ priv->base = of_iomap(np, 0);
if (IS_ERR(priv->base)) {
- dev_err(dev, "%s: Unable to map IO memory\n", __func__);
- return PTR_ERR(priv->base);
+ pr_err("%s: Unable to map IO memory\n", __func__);
+ ret = PTR_ERR(priv->base);
+ goto out_free;
}
/* Disable all wake-up pins */
@@ -236,52 +233,38 @@ static int stm32_pwr_probe(struct platform_device *pdev)
priv->domain = irq_domain_add_linear(np, NB_WAKEUPPINS,
&stm32_pwr_irq_domain_ops, priv);
if (!priv->domain) {
- dev_err(dev, "%s: Unable to add irq domain!\n", __func__);
- goto out;
+ pr_err("%s: Unable to add irq domain!\n", __func__);
+ ret = -ENOMEM;
+ goto out_unmap;
}
- ret = platform_get_irq(pdev, 0);
- if (ret < 0) {
- dev_err(dev, "failed to get PWR IRQ\n");
- goto err;
+ priv->irq = irq_of_parse_and_map(np, 0);
+ if (priv->irq < 0) {
+ pr_err("failed to get PWR IRQ\n");
+ ret = priv->irq;
+ goto out_domain;
}
- priv->irq = ret;
irq_set_chained_handler_and_data(priv->irq,
stm32_pwr_handle_irq, priv);
-out:
+ of_node_clear_flag(np, OF_POPULATED);
+
return 0;
-err:
+
+out_domain:
irq_domain_remove(priv->domain);
+out_unmap:
+ iounmap(priv->base);
+out_free:
+ kfree(priv);
return ret;
}
-static int stm32_pwr_remove(struct platform_device *pdev)
+static int __init stm32_pwr_of_init(struct device_node *np,
+ struct device_node *parent)
{
- struct stm32_pwr_data *priv = platform_get_drvdata(pdev);
-
- irq_domain_remove(priv->domain);
- return 0;
+ return stm32_pwr_init(np, parent);
}
-static const struct of_device_id stm32_pwr_match[] = {
- { .compatible = "st,stm32mp1-pwr" },
- {},
-};
-
-static struct platform_driver stm32_pwr_driver = {
- .probe = stm32_pwr_probe,
- .remove = stm32_pwr_remove,
- .driver = {
- .name = "stm32-pwr",
- .owner = THIS_MODULE,
- .of_match_table = stm32_pwr_match,
- },
-};
-
-static int __init stm32_pwr_init(void)
-{
- return platform_driver_register(&stm32_pwr_driver);
-}
-arch_initcall(stm32_pwr_init);
+IRQCHIP_DECLARE(stm32mp1_pwr_irq, "st,stm32mp1-pwr", stm32_pwr_of_init);
diff --git a/drivers/mfd/stpmic1.c b/drivers/mfd/stpmic1.c
index 5bf6328..648315d 100644
--- a/drivers/mfd/stpmic1.c
+++ b/drivers/mfd/stpmic1.c
@@ -268,13 +268,8 @@ static int stpmic1_probe(struct i2c_client *i2c,
return ddata->irq;
}
- ddata->irq_wake = of_irq_get(np, STPMIC1_WAKEUP_IRQ);
- if (ddata->irq_wake > 0) {
+ if (of_property_read_bool(np, "wakeup-source"))
device_init_wakeup(dev, true);
- ret = dev_pm_set_dedicated_wake_irq(dev, ddata->irq_wake);
- if (ret)
- dev_warn(dev, "failed to set up wakeup irq");
- }
if (!of_property_read_u32(np, "st,main-control-register", &reg)) {
ret = regmap_update_bits(ddata->regmap,
@@ -371,8 +366,8 @@ static int stpmic1_suspend(struct device *dev)
struct stpmic1 *pmic_dev = i2c_get_clientdata(i2c);
disable_irq(pmic_dev->irq);
- if ((pmic_dev->irq_wake > 0) && device_may_wakeup(dev))
- enable_irq_wake(pmic_dev->irq_wake);
+ if (device_may_wakeup(dev))
+ enable_irq_wake(pmic_dev->irq);
return 0;
}
@@ -387,9 +382,10 @@ static int stpmic1_resume(struct device *dev)
if (ret)
return ret;
+ if (device_may_wakeup(dev))
+ disable_irq_wake(pmic_dev->irq);
+
enable_irq(pmic_dev->irq);
- if ((pmic_dev->irq_wake > 0) && device_may_wakeup(dev))
- disable_irq_wake(pmic_dev->irq_wake);
return 0;
}
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index b6d05cd..a0ba4ff 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -12,6 +12,7 @@
* (at your option) any later version.
*/
+#include <linux/clk.h>
#include <linux/err.h>
#include <linux/hwspinlock.h>
#include <linux/io.h>
@@ -45,6 +46,7 @@ static const struct regmap_config syscon_regmap_config = {
static struct syscon *of_syscon_register(struct device_node *np)
{
+ struct clk *clk;
struct syscon *syscon;
struct regmap *regmap;
void __iomem *base;
@@ -119,6 +121,18 @@ static struct syscon *of_syscon_register(struct device_node *np)
goto err_regmap;
}
+ clk = of_clk_get(np, 0);
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ /* clock is optional */
+ if (ret != -ENOENT)
+ goto err_clk;
+ } else {
+ ret = regmap_mmio_attach_clk(regmap, clk);
+ if (ret)
+ goto err_attach;
+ }
+
syscon->regmap = regmap;
syscon->np = np;
@@ -128,6 +142,11 @@ static struct syscon *of_syscon_register(struct device_node *np)
return syscon;
+err_attach:
+ if (!IS_ERR(clk))
+ clk_put(clk);
+err_clk:
+ regmap_exit(regmap);
err_regmap:
iounmap(base);
err_map:
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index 22bd652..755863a 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -12,6 +12,7 @@
*
*/
+#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -314,6 +315,20 @@ static int wm8994_set_pdata_from_of(struct wm8994 *wm8994)
if (pdata->ldo[1].enable < 0)
pdata->ldo[1].enable = 0;
+ pdata->mclk1 = devm_clk_get(wm8994->dev, "MCLK1");
+ if (IS_ERR(pdata->mclk1)) {
+ if (PTR_ERR(pdata->mclk1) != -ENOENT)
+ return PTR_ERR(pdata->mclk1);
+ pdata->mclk1 = NULL;
+ }
+
+ pdata->mclk2 = devm_clk_get(wm8994->dev, "MCLK2");
+ if (IS_ERR(pdata->mclk2)) {
+ if (PTR_ERR(pdata->mclk2) != -ENOENT)
+ return PTR_ERR(pdata->mclk2);
+ pdata->mclk2 = NULL;
+ }
+
return 0;
}
#else
diff --git a/include/linux/mfd/stpmic1.h b/include/linux/mfd/stpmic1.h
index 4abe5f1..fa3f99f 100644
--- a/include/linux/mfd/stpmic1.h
+++ b/include/linux/mfd/stpmic1.h
@@ -206,7 +206,6 @@ struct stpmic1 {
struct device *dev;
struct regmap *regmap;
int irq;
- int irq_wake;
struct regmap_irq_chip_data *irq_data;
};
--
2.7.4