diff options
Diffstat (limited to 'drivers/mfd/axp20x.c')
-rw-r--r-- | drivers/mfd/axp20x.c | 105 |
1 files changed, 25 insertions, 80 deletions
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index 9842199e2e6c..a57d6e940610 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -1,10 +1,14 @@ /* - * axp20x.c - MFD core driver for the X-Powers' Power Management ICs + * MFD core driver for the X-Powers' Power Management ICs * * AXP20x typically comprises an adaptive USB-Compatible PWM charger, BUCK DC-DC * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature * as well as configurable GPIOs. * + * This file contains the interface independent core functions. + * + * Copyright (C) 2014 Carlo Caione + * * Author: Carlo Caione <carlo@caione.org> * * This program is free software; you can redistribute it and/or modify @@ -13,18 +17,15 @@ */ #include <linux/err.h> -#include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> -#include <linux/slab.h> #include <linux/regulator/consumer.h> #include <linux/mfd/axp20x.h> #include <linux/mfd/core.h> #include <linux/of_device.h> -#include <linux/of_irq.h> #include <linux/acpi.h> #define AXP20X_OFF 0x80 @@ -34,6 +35,7 @@ static const char * const axp20x_model_names[] = { "AXP202", "AXP209", "AXP221", + "AXP223", "AXP288", }; @@ -376,32 +378,6 @@ static const struct regmap_irq axp288_regmap_irqs[] = { INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1), }; -static const struct of_device_id axp20x_of_match[] = { - { .compatible = "x-powers,axp152", .data = (void *) AXP152_ID }, - { .compatible = "x-powers,axp202", .data = (void *) AXP202_ID }, - { .compatible = "x-powers,axp209", .data = (void *) AXP209_ID }, - { .compatible = "x-powers,axp221", .data = (void *) AXP221_ID }, - { }, -}; -MODULE_DEVICE_TABLE(of, axp20x_of_match); - -/* - * This is useless for OF-enabled devices, but it is needed by I2C subsystem - */ -static const struct i2c_device_id axp20x_i2c_id[] = { - { }, -}; -MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id); - -static const struct acpi_device_id axp20x_acpi_match[] = { - { - .id = "INT33F4", - .driver_data = AXP288_ID, - }, - { }, -}; -MODULE_DEVICE_TABLE(acpi, axp20x_acpi_match); - static const struct regmap_irq_chip axp152_regmap_irq_chip = { .name = "axp152_irq_chip", .status_base = AXP152_IRQ1_STATE, @@ -606,25 +582,26 @@ static void axp20x_power_off(void) AXP20X_OFF); } -static int axp20x_match_device(struct axp20x_dev *axp20x, struct device *dev) +int axp20x_match_device(struct axp20x_dev *axp20x) { + struct device *dev = axp20x->dev; const struct acpi_device_id *acpi_id; const struct of_device_id *of_id; if (dev->of_node) { - of_id = of_match_device(axp20x_of_match, dev); + of_id = of_match_device(dev->driver->of_match_table, dev); if (!of_id) { dev_err(dev, "Unable to match OF ID\n"); return -ENODEV; } - axp20x->variant = (long) of_id->data; + axp20x->variant = (long)of_id->data; } else { acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev); if (!acpi_id || !acpi_id->driver_data) { dev_err(dev, "Unable to match ACPI ID and data\n"); return -ENODEV; } - axp20x->variant = (long) acpi_id->driver_data; + axp20x->variant = (long)acpi_id->driver_data; } switch (axp20x->variant) { @@ -642,6 +619,7 @@ static int axp20x_match_device(struct axp20x_dev *axp20x, struct device *dev) axp20x->regmap_irq_chip = &axp20x_regmap_irq_chip; break; case AXP221_ID: + case AXP223_ID: axp20x->nr_cells = ARRAY_SIZE(axp22x_cells); axp20x->cells = axp22x_cells; axp20x->regmap_cfg = &axp22x_regmap_config; @@ -658,51 +636,31 @@ static int axp20x_match_device(struct axp20x_dev *axp20x, struct device *dev) return -EINVAL; } dev_info(dev, "AXP20x variant %s found\n", - axp20x_model_names[axp20x->variant]); + axp20x_model_names[axp20x->variant]); return 0; } +EXPORT_SYMBOL(axp20x_match_device); -static int axp20x_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +int axp20x_device_probe(struct axp20x_dev *axp20x) { - struct axp20x_dev *axp20x; int ret; - axp20x = devm_kzalloc(&i2c->dev, sizeof(*axp20x), GFP_KERNEL); - if (!axp20x) - return -ENOMEM; - - ret = axp20x_match_device(axp20x, &i2c->dev); - if (ret) - return ret; - - axp20x->i2c_client = i2c; - axp20x->dev = &i2c->dev; - dev_set_drvdata(axp20x->dev, axp20x); - - axp20x->regmap = devm_regmap_init_i2c(i2c, axp20x->regmap_cfg); - if (IS_ERR(axp20x->regmap)) { - ret = PTR_ERR(axp20x->regmap); - dev_err(&i2c->dev, "regmap init failed: %d\n", ret); - return ret; - } - - ret = regmap_add_irq_chip(axp20x->regmap, i2c->irq, + ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq, IRQF_ONESHOT | IRQF_SHARED, -1, axp20x->regmap_irq_chip, &axp20x->regmap_irqc); if (ret) { - dev_err(&i2c->dev, "failed to add irq chip: %d\n", ret); + dev_err(axp20x->dev, "failed to add irq chip: %d\n", ret); return ret; } ret = mfd_add_devices(axp20x->dev, -1, axp20x->cells, - axp20x->nr_cells, NULL, 0, NULL); + axp20x->nr_cells, NULL, 0, NULL); if (ret) { - dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret); - regmap_del_irq_chip(i2c->irq, axp20x->regmap_irqc); + dev_err(axp20x->dev, "failed to add MFD devices: %d\n", ret); + regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc); return ret; } @@ -711,38 +669,25 @@ static int axp20x_i2c_probe(struct i2c_client *i2c, pm_power_off = axp20x_power_off; } - dev_info(&i2c->dev, "AXP20X driver loaded\n"); + dev_info(axp20x->dev, "AXP20X driver loaded\n"); return 0; } +EXPORT_SYMBOL(axp20x_device_probe); -static int axp20x_i2c_remove(struct i2c_client *i2c) +int axp20x_device_remove(struct axp20x_dev *axp20x) { - struct axp20x_dev *axp20x = i2c_get_clientdata(i2c); - if (axp20x == axp20x_pm_power_off) { axp20x_pm_power_off = NULL; pm_power_off = NULL; } mfd_remove_devices(axp20x->dev); - regmap_del_irq_chip(axp20x->i2c_client->irq, axp20x->regmap_irqc); + regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc); return 0; } - -static struct i2c_driver axp20x_i2c_driver = { - .driver = { - .name = "axp20x", - .of_match_table = of_match_ptr(axp20x_of_match), - .acpi_match_table = ACPI_PTR(axp20x_acpi_match), - }, - .probe = axp20x_i2c_probe, - .remove = axp20x_i2c_remove, - .id_table = axp20x_i2c_id, -}; - -module_i2c_driver(axp20x_i2c_driver); +EXPORT_SYMBOL(axp20x_device_remove); MODULE_DESCRIPTION("PMIC MFD core driver for AXP20X"); MODULE_AUTHOR("Carlo Caione <carlo@caione.org>"); |