diff options
Diffstat (limited to 'drivers/mfd/motorola-cpcap.c')
| -rw-r--r-- | drivers/mfd/motorola-cpcap.c | 108 |
1 files changed, 91 insertions, 17 deletions
diff --git a/drivers/mfd/motorola-cpcap.c b/drivers/mfd/motorola-cpcap.c index d2cc1eabac05..d8243b956f87 100644 --- a/drivers/mfd/motorola-cpcap.c +++ b/drivers/mfd/motorola-cpcap.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Motorola CPCAP PMIC core driver * * Copyright (C) 2016 Tony Lindgren <tony@atomide.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/device.h> @@ -14,10 +11,11 @@ #include <linux/irq.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/mod_devicetable.h> #include <linux/regmap.h> #include <linux/sysfs.h> +#include <linux/mfd/core.h> #include <linux/mfd/motorola-cpcap.h> #include <linux/spi/spi.h> @@ -99,7 +97,7 @@ static struct regmap_irq_chip cpcap_irq_chip[CPCAP_NR_IRQ_CHIPS] = { .ack_base = CPCAP_REG_MI1, .mask_base = CPCAP_REG_MIM1, .use_ack = true, - .ack_invert = true, + .clear_ack = true, }, { .name = "cpcap-m2", @@ -108,7 +106,7 @@ static struct regmap_irq_chip cpcap_irq_chip[CPCAP_NR_IRQ_CHIPS] = { .ack_base = CPCAP_REG_MI2, .mask_base = CPCAP_REG_MIM2, .use_ack = true, - .ack_invert = true, + .clear_ack = true, }, { .name = "cpcap1-4", @@ -117,7 +115,7 @@ static struct regmap_irq_chip cpcap_irq_chip[CPCAP_NR_IRQ_CHIPS] = { .ack_base = CPCAP_REG_INT1, .mask_base = CPCAP_REG_INTM1, .use_ack = true, - .ack_invert = true, + .clear_ack = true, }, }; @@ -173,9 +171,9 @@ static int cpcap_init_irq(struct cpcap_ddata *cpcap) int ret; cpcap->irqs = devm_kzalloc(&cpcap->spi->dev, - sizeof(*cpcap->irqs) * - CPCAP_NR_IRQ_REG_BANKS * - cpcap->regmap_conf->val_bits, + array3_size(sizeof(*cpcap->irqs), + CPCAP_NR_IRQ_REG_BANKS, + cpcap->regmap_conf->val_bits), GFP_KERNEL); if (!cpcap->irqs) return -ENOMEM; @@ -204,6 +202,13 @@ static const struct of_device_id cpcap_of_match[] = { }; MODULE_DEVICE_TABLE(of, cpcap_of_match); +static const struct spi_device_id cpcap_spi_ids[] = { + { .name = "cpcap", }, + { .name = "6556002", }, + {}, +}; +MODULE_DEVICE_TABLE(spi, cpcap_spi_ids); + static const struct regmap_config cpcap_regmap_config = { .reg_bits = 16, .reg_stride = 4, @@ -216,16 +221,78 @@ static const struct regmap_config cpcap_regmap_config = { .val_format_endian = REGMAP_ENDIAN_LITTLE, }; +static int cpcap_suspend(struct device *dev) +{ + struct spi_device *spi = to_spi_device(dev); + + disable_irq(spi->irq); + + return 0; +} + +static int cpcap_resume(struct device *dev) +{ + struct spi_device *spi = to_spi_device(dev); + + enable_irq(spi->irq); + + return 0; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(cpcap_pm, cpcap_suspend, cpcap_resume); + +static const struct mfd_cell cpcap_mfd_devices[] = { + { + .name = "cpcap_adc", + .of_compatible = "motorola,mapphone-cpcap-adc", + }, { + .name = "cpcap_battery", + .of_compatible = "motorola,cpcap-battery", + }, { + .name = "cpcap-charger", + .of_compatible = "motorola,mapphone-cpcap-charger", + }, { + .name = "cpcap-regulator", + .of_compatible = "motorola,mapphone-cpcap-regulator", + }, { + .name = "cpcap-rtc", + .of_compatible = "motorola,cpcap-rtc", + }, { + .name = "cpcap-pwrbutton", + .of_compatible = "motorola,cpcap-pwrbutton", + }, { + .name = "cpcap-usb-phy", + .of_compatible = "motorola,mapphone-cpcap-usb-phy", + }, { + .name = "cpcap-led", + .id = 0, + .of_compatible = "motorola,cpcap-led-red", + }, { + .name = "cpcap-led", + .id = 1, + .of_compatible = "motorola,cpcap-led-green", + }, { + .name = "cpcap-led", + .id = 2, + .of_compatible = "motorola,cpcap-led-blue", + }, { + .name = "cpcap-led", + .id = 3, + .of_compatible = "motorola,cpcap-led-adl", + }, { + .name = "cpcap-led", + .id = 4, + .of_compatible = "motorola,cpcap-led-cp", + }, { + .name = "cpcap-codec", + } +}; + static int cpcap_probe(struct spi_device *spi) { - const struct of_device_id *match; struct cpcap_ddata *cpcap; int ret; - match = of_match_device(of_match_ptr(cpcap_of_match), &spi->dev); - if (!match) - return -ENODEV; - cpcap = devm_kzalloc(&spi->dev, sizeof(*cpcap), GFP_KERNEL); if (!cpcap) return -ENOMEM; @@ -260,15 +327,22 @@ static int cpcap_probe(struct spi_device *spi) if (ret) return ret; - return devm_of_platform_populate(&cpcap->spi->dev); + /* Parent SPI controller uses DMA, CPCAP and child devices do not */ + spi->dev.coherent_dma_mask = 0; + spi->dev.dma_mask = &spi->dev.coherent_dma_mask; + + return devm_mfd_add_devices(&spi->dev, 0, cpcap_mfd_devices, + ARRAY_SIZE(cpcap_mfd_devices), NULL, 0, NULL); } static struct spi_driver cpcap_driver = { .driver = { .name = "cpcap-core", .of_match_table = cpcap_of_match, + .pm = pm_sleep_ptr(&cpcap_pm), }, .probe = cpcap_probe, + .id_table = cpcap_spi_ids, }; module_spi_driver(cpcap_driver); |
