summaryrefslogtreecommitdiffstats
path: root/drivers/mfd/axp20x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/axp20x.c')
-rw-r--r--drivers/mfd/axp20x.c66
1 files changed, 27 insertions, 39 deletions
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index 87603eeaa2..deaa969bab 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -22,7 +22,8 @@
#include <linux/mfd/axp20x.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/property.h>
#include <linux/reboot.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@@ -1131,25 +1132,10 @@ static int axp20x_power_off(struct sys_off_data *data)
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(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;
- } 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;
- }
+ const struct mfd_cell *cells_no_irq = NULL;
+ int nr_cells_no_irq = 0;
+ axp20x->variant = (long)device_get_match_data(dev);
switch (axp20x->variant) {
case AXP152_ID:
axp20x->nr_cells = ARRAY_SIZE(axp152_cells);
@@ -1207,14 +1193,15 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
* if there is no interrupt line.
*/
if (of_property_read_bool(axp20x->dev->of_node,
- "x-powers,self-working-mode") &&
- axp20x->irq > 0) {
+ "x-powers,self-working-mode")) {
axp20x->nr_cells = ARRAY_SIZE(axp806_self_working_cells);
axp20x->cells = axp806_self_working_cells;
} else {
axp20x->nr_cells = ARRAY_SIZE(axp806_cells);
axp20x->cells = axp806_cells;
}
+ nr_cells_no_irq = ARRAY_SIZE(axp806_cells);
+ cells_no_irq = axp806_cells;
axp20x->regmap_cfg = &axp806_regmap_config;
axp20x->regmap_irq_chip = &axp806_regmap_irq_chip;
break;
@@ -1238,24 +1225,8 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
break;
case AXP15060_ID:
- /*
- * Don't register the power key part if there is no interrupt
- * line.
- *
- * Since most use cases of AXP PMICs are Allwinner SOCs, board
- * designers follow Allwinner's reference design and connects
- * IRQ line to SOC, there's no need for those variants to deal
- * with cases that IRQ isn't connected. However, AXP15660 is
- * used by some other vendors' SOCs that didn't connect IRQ
- * line, we need to deal with this case.
- */
- if (axp20x->irq > 0) {
- axp20x->nr_cells = ARRAY_SIZE(axp15060_cells);
- axp20x->cells = axp15060_cells;
- } else {
- axp20x->nr_cells = ARRAY_SIZE(axp_regulator_only_cells);
- axp20x->cells = axp_regulator_only_cells;
- }
+ axp20x->nr_cells = ARRAY_SIZE(axp15060_cells);
+ axp20x->cells = axp15060_cells;
axp20x->regmap_cfg = &axp15060_regmap_config;
axp20x->regmap_irq_chip = &axp15060_regmap_irq_chip;
break;
@@ -1263,6 +1234,23 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
return -EINVAL;
}
+
+ /*
+ * Use an alternative cell array when no interrupt line is connected,
+ * since IRQs are required by some drivers.
+ * The default is the safe "regulator-only", as this works fine without
+ * an interrupt specified.
+ */
+ if (axp20x->irq <= 0) {
+ if (cells_no_irq) {
+ axp20x->nr_cells = nr_cells_no_irq;
+ axp20x->cells = cells_no_irq;
+ } else {
+ axp20x->nr_cells = ARRAY_SIZE(axp_regulator_only_cells);
+ axp20x->cells = axp_regulator_only_cells;
+ }
+ }
+
dev_info(dev, "AXP20x variant %s found\n",
axp20x_model_names[axp20x->variant]);