diff options
Diffstat (limited to 'drivers/mfd/qcom-pm8xxx.c')
| -rw-r--r-- | drivers/mfd/qcom-pm8xxx.c | 73 |
1 files changed, 29 insertions, 44 deletions
diff --git a/drivers/mfd/qcom-pm8xxx.c b/drivers/mfd/qcom-pm8xxx.c index acd172ddcbd6..1149f7102a36 100644 --- a/drivers/mfd/qcom-pm8xxx.c +++ b/drivers/mfd/qcom-pm8xxx.c @@ -65,7 +65,7 @@ struct pm_irq_data { int num_irqs; struct irq_chip *irq_chip; - void (*irq_handler)(struct irq_desc *desc); + irq_handler_t irq_handler; }; struct pm_irq_chip { @@ -103,8 +103,9 @@ static int pm8xxx_config_irq(struct pm_irq_chip *chip, unsigned int bp, unsigned int cp) { int rc; + unsigned long flags; - spin_lock(&chip->pm_irq_lock); + spin_lock_irqsave(&chip->pm_irq_lock, flags); rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp); if (rc) { pr_err("Failed Selecting Block %d rc=%d\n", bp, rc); @@ -116,13 +117,13 @@ pm8xxx_config_irq(struct pm_irq_chip *chip, unsigned int bp, unsigned int cp) if (rc) pr_err("Failed Configuring IRQ rc=%d\n", rc); bail: - spin_unlock(&chip->pm_irq_lock); + spin_unlock_irqrestore(&chip->pm_irq_lock, flags); return rc; } static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block) { - int pmirq, irq, i, ret = 0; + int pmirq, i, ret = 0; unsigned int bits; ret = pm8xxx_read_block_irq(chip, block, &bits); @@ -139,8 +140,7 @@ static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block) for (i = 0; i < 8; i++) { if (bits & (1 << i)) { pmirq = block * 8 + i; - irq = irq_find_mapping(chip->irqdomain, pmirq); - generic_handle_irq(irq); + generic_handle_domain_irq(chip->irqdomain, pmirq); } } return 0; @@ -170,19 +170,16 @@ static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master) return ret; } -static void pm8xxx_irq_handler(struct irq_desc *desc) +static irqreturn_t pm8xxx_irq_handler(int irq, void *data) { - struct pm_irq_chip *chip = irq_desc_get_handler_data(desc); - struct irq_chip *irq_chip = irq_desc_get_chip(desc); + struct pm_irq_chip *chip = data; unsigned int root; int i, ret, masters = 0; - chained_irq_enter(irq_chip, desc); - ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_ROOT, &root); if (ret) { pr_err("Can't read root status ret=%d\n", ret); - return; + return IRQ_NONE; } /* on pm8xxx series masters start from bit 1 of the root */ @@ -193,13 +190,13 @@ static void pm8xxx_irq_handler(struct irq_desc *desc) if (masters & (1 << i)) pm8xxx_irq_master_handler(chip, i); - chained_irq_exit(irq_chip, desc); + return IRQ_HANDLED; } static void pm8821_irq_block_handler(struct pm_irq_chip *chip, int master, int block) { - int pmirq, irq, i, ret; + int pmirq, i, ret; unsigned int bits; ret = regmap_read(chip->regmap, @@ -216,8 +213,7 @@ static void pm8821_irq_block_handler(struct pm_irq_chip *chip, for (i = 0; i < 8; i++) { if (bits & BIT(i)) { pmirq = block * 8 + i; - irq = irq_find_mapping(chip->irqdomain, pmirq); - generic_handle_irq(irq); + generic_handle_domain_irq(chip->irqdomain, pmirq); } } } @@ -232,19 +228,17 @@ static inline void pm8821_irq_master_handler(struct pm_irq_chip *chip, pm8821_irq_block_handler(chip, master, block); } -static void pm8821_irq_handler(struct irq_desc *desc) +static irqreturn_t pm8821_irq_handler(int irq, void *data) { - struct pm_irq_chip *chip = irq_desc_get_handler_data(desc); - struct irq_chip *irq_chip = irq_desc_get_chip(desc); + struct pm_irq_chip *chip = data; unsigned int master; int ret; - chained_irq_enter(irq_chip, desc); ret = regmap_read(chip->regmap, PM8821_SSBI_REG_ADDR_IRQ_MASTER0, &master); if (ret) { pr_err("Failed to read master 0 ret=%d\n", ret); - goto done; + return IRQ_NONE; } /* bits 1 through 7 marks the first 7 blocks in master 0 */ @@ -253,19 +247,18 @@ static void pm8821_irq_handler(struct irq_desc *desc) /* bit 0 marks if master 1 contains any bits */ if (!(master & BIT(0))) - goto done; + return IRQ_NONE; ret = regmap_read(chip->regmap, PM8821_SSBI_REG_ADDR_IRQ_MASTER1, &master); if (ret) { pr_err("Failed to read master 1 ret=%d\n", ret); - goto done; + return IRQ_NONE; } pm8821_irq_master_handler(chip, 1, master); -done: - chained_irq_exit(irq_chip, desc); + return IRQ_HANDLED; } static void pm8xxx_irq_mask_ack(struct irq_data *d) @@ -329,6 +322,7 @@ static int pm8xxx_irq_get_irqchip_state(struct irq_data *d, struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d); unsigned int pmirq = irqd_to_hwirq(d); unsigned int bits; + unsigned long flags; int irq_bit; u8 block; int rc; @@ -339,7 +333,7 @@ static int pm8xxx_irq_get_irqchip_state(struct irq_data *d, block = pmirq / 8; irq_bit = pmirq % 8; - spin_lock(&chip->pm_irq_lock); + spin_lock_irqsave(&chip->pm_irq_lock, flags); rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, block); if (rc) { pr_err("Failed Selecting Block %d rc=%d\n", block, rc); @@ -354,7 +348,7 @@ static int pm8xxx_irq_get_irqchip_state(struct irq_data *d, *state = !!(bits & BIT(irq_bit)); bail: - spin_unlock(&chip->pm_irq_lock); + spin_unlock_irqrestore(&chip->pm_irq_lock, flags); return rc; } @@ -505,7 +499,6 @@ static const struct pm_irq_data pm8821_data = { }; static const struct of_device_id pm8xxx_id_table[] = { - { .compatible = "qcom,pm8018", .data = &pm8xxx_data}, { .compatible = "qcom,pm8058", .data = &pm8xxx_data}, { .compatible = "qcom,pm8821", .data = &pm8821_data}, { .compatible = "qcom,pm8921", .data = &pm8xxx_data}, @@ -519,7 +512,6 @@ static int pm8xxx_probe(struct platform_device *pdev) struct regmap *regmap; int irq, rc; unsigned int val; - u32 rev; struct pm_irq_chip *chip; data = of_device_get_match_data(&pdev->dev); @@ -544,7 +536,6 @@ static int pm8xxx_probe(struct platform_device *pdev) return rc; } pr_info("PMIC revision 1: %02X\n", val); - rev = val; /* Read PMIC chip revision 2 */ rc = regmap_read(regmap, REG_HWREV_2, &val); @@ -554,7 +545,6 @@ static int pm8xxx_probe(struct platform_device *pdev) return rc; } pr_info("PMIC revision 2: %02X\n", val); - rev |= val << BITS_PER_BYTE; chip = devm_kzalloc(&pdev->dev, struct_size(chip, config, data->num_irqs), @@ -569,21 +559,20 @@ static int pm8xxx_probe(struct platform_device *pdev) chip->pm_irq_data = data; spin_lock_init(&chip->pm_irq_lock); - chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node, - data->num_irqs, - &pm8xxx_irq_domain_ops, - chip); + chip->irqdomain = irq_domain_create_linear(dev_fwnode(&pdev->dev), data->num_irqs, + &pm8xxx_irq_domain_ops, chip); if (!chip->irqdomain) return -ENODEV; - irq_set_chained_handler_and_data(irq, data->irq_handler, chip); + rc = devm_request_irq(&pdev->dev, irq, data->irq_handler, 0, dev_name(&pdev->dev), chip); + if (rc) + return rc; + irq_set_irq_wake(irq, 1); rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); - if (rc) { - irq_set_chained_handler_and_data(irq, NULL, NULL); + if (rc) irq_domain_remove(chip->irqdomain); - } return rc; } @@ -594,16 +583,12 @@ static int pm8xxx_remove_child(struct device *dev, void *unused) return 0; } -static int pm8xxx_remove(struct platform_device *pdev) +static void pm8xxx_remove(struct platform_device *pdev) { - int irq = platform_get_irq(pdev, 0); struct pm_irq_chip *chip = platform_get_drvdata(pdev); device_for_each_child(&pdev->dev, NULL, pm8xxx_remove_child); - irq_set_chained_handler_and_data(irq, NULL, NULL); irq_domain_remove(chip->irqdomain); - - return 0; } static struct platform_driver pm8xxx_driver = { |
