^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * I2C driver for the X-Powers' Power Management ICs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * AXP20x typically comprises an adaptive USB-Compatible PWM charger, BUCK DC-DC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * as well as configurable GPIOs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * This driver supports the I2C variants.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright (C) 2014 Carlo Caione
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Author: Carlo Caione <carlo@caione.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/mfd/axp20x.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static int axp20x_i2c_probe(struct i2c_client *i2c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct axp20x_dev *axp20x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) axp20x = devm_kzalloc(&i2c->dev, sizeof(*axp20x), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) if (!axp20x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) axp20x->dev = &i2c->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) axp20x->irq = i2c->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) dev_set_drvdata(axp20x->dev, axp20x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) ret = axp20x_match_device(axp20x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) axp20x->regmap = devm_regmap_init_i2c(i2c, axp20x->regmap_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (IS_ERR(axp20x->regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) ret = PTR_ERR(axp20x->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return axp20x_device_probe(axp20x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static int axp20x_i2c_remove(struct i2c_client *i2c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct axp20x_dev *axp20x = i2c_get_clientdata(i2c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return axp20x_device_remove(axp20x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static const struct of_device_id axp20x_i2c_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) { .compatible = "x-powers,axp152", .data = (void *)AXP152_ID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) { .compatible = "x-powers,axp202", .data = (void *)AXP202_ID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) { .compatible = "x-powers,axp209", .data = (void *)AXP209_ID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) { .compatible = "x-powers,axp221", .data = (void *)AXP221_ID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static const struct i2c_device_id axp20x_i2c_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) { "axp152", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) { "axp202", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) { "axp209", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) { "axp221", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) { "axp223", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) { "axp803", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) { "axp806", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #ifdef CONFIG_ACPI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static const struct acpi_device_id axp20x_i2c_acpi_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) .id = "INT33F4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .driver_data = AXP288_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) MODULE_DEVICE_TABLE(acpi, axp20x_i2c_acpi_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static struct i2c_driver axp20x_i2c_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .name = "axp20x-i2c",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .of_match_table = of_match_ptr(axp20x_i2c_of_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .acpi_match_table = ACPI_PTR(axp20x_i2c_acpi_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .probe = axp20x_i2c_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .remove = axp20x_i2c_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .id_table = axp20x_i2c_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) module_i2c_driver(axp20x_i2c_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) MODULE_DESCRIPTION("PMIC MFD I2C driver for AXP20X");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) MODULE_LICENSE("GPL");