Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Author: Dan Scally <djrscally@gmail.com> */
0003 
0004 #include <linux/i2c.h>
0005 #include <linux/kernel.h>
0006 #include <linux/mfd/core.h>
0007 #include <linux/mfd/tps68470.h>
0008 #include <linux/platform_device.h>
0009 #include <linux/platform_data/tps68470.h>
0010 #include <linux/regmap.h>
0011 #include <linux/string.h>
0012 
0013 #include "common.h"
0014 #include "tps68470.h"
0015 
0016 #define DESIGNED_FOR_CHROMEOS       1
0017 #define DESIGNED_FOR_WINDOWS        2
0018 
0019 #define TPS68470_WIN_MFD_CELL_COUNT 3
0020 
0021 static const struct mfd_cell tps68470_cros[] = {
0022     { .name = "tps68470-gpio" },
0023     { .name = "tps68470_pmic_opregion" },
0024 };
0025 
0026 static const struct regmap_config tps68470_regmap_config = {
0027     .reg_bits = 8,
0028     .val_bits = 8,
0029     .max_register = TPS68470_REG_MAX,
0030 };
0031 
0032 static int tps68470_chip_init(struct device *dev, struct regmap *regmap)
0033 {
0034     unsigned int version;
0035     int ret;
0036 
0037     /* Force software reset */
0038     ret = regmap_write(regmap, TPS68470_REG_RESET, TPS68470_REG_RESET_MASK);
0039     if (ret)
0040         return ret;
0041 
0042     ret = regmap_read(regmap, TPS68470_REG_REVID, &version);
0043     if (ret) {
0044         dev_err(dev, "Failed to read revision register: %d\n", ret);
0045         return ret;
0046     }
0047 
0048     dev_info(dev, "TPS68470 REVID: 0x%02x\n", version);
0049 
0050     return 0;
0051 }
0052 
0053 /** skl_int3472_tps68470_calc_type: Check what platform a device is designed for
0054  * @adev: A pointer to a &struct acpi_device
0055  *
0056  * Check CLDB buffer against the PMIC's adev. If present, then we check
0057  * the value of control_logic_type field and follow one of the
0058  * following scenarios:
0059  *
0060  *  1. No CLDB - likely ACPI tables designed for ChromeOS. We
0061  *  create platform devices for the GPIOs and OpRegion drivers.
0062  *
0063  *  2. CLDB, with control_logic_type = 2 - probably ACPI tables
0064  *  made for Windows 2-in-1 platforms. Register pdevs for GPIO,
0065  *  Clock and Regulator drivers to bind to.
0066  *
0067  *  3. Any other value in control_logic_type, we should never have
0068  *  gotten to this point; fail probe and return.
0069  *
0070  * Return:
0071  * * 1      Device intended for ChromeOS
0072  * * 2      Device intended for Windows
0073  * * -EINVAL    Where @adev has an object named CLDB but it does not conform to
0074  *      our expectations
0075  */
0076 static int skl_int3472_tps68470_calc_type(struct acpi_device *adev)
0077 {
0078     struct int3472_cldb cldb = { 0 };
0079     int ret;
0080 
0081     /*
0082      * A CLDB buffer that exists, but which does not match our expectations
0083      * should trigger an error so we don't blindly continue.
0084      */
0085     ret = skl_int3472_fill_cldb(adev, &cldb);
0086     if (ret && ret != -ENODEV)
0087         return ret;
0088 
0089     if (ret)
0090         return DESIGNED_FOR_CHROMEOS;
0091 
0092     if (cldb.control_logic_type != 2)
0093         return -EINVAL;
0094 
0095     return DESIGNED_FOR_WINDOWS;
0096 }
0097 
0098 static int skl_int3472_tps68470_probe(struct i2c_client *client)
0099 {
0100     struct acpi_device *adev = ACPI_COMPANION(&client->dev);
0101     const struct int3472_tps68470_board_data *board_data;
0102     struct tps68470_clk_platform_data clk_pdata = {};
0103     struct mfd_cell *cells;
0104     struct regmap *regmap;
0105     int device_type;
0106     int ret;
0107 
0108     ret = skl_int3472_get_sensor_adev_and_name(&client->dev, NULL,
0109                            &clk_pdata.consumer_dev_name);
0110     if (ret)
0111         return ret;
0112 
0113     regmap = devm_regmap_init_i2c(client, &tps68470_regmap_config);
0114     if (IS_ERR(regmap)) {
0115         dev_err(&client->dev, "Failed to create regmap: %ld\n", PTR_ERR(regmap));
0116         return PTR_ERR(regmap);
0117     }
0118 
0119     i2c_set_clientdata(client, regmap);
0120 
0121     ret = tps68470_chip_init(&client->dev, regmap);
0122     if (ret < 0) {
0123         dev_err(&client->dev, "TPS68470 init error %d\n", ret);
0124         return ret;
0125     }
0126 
0127     device_type = skl_int3472_tps68470_calc_type(adev);
0128     switch (device_type) {
0129     case DESIGNED_FOR_WINDOWS:
0130         board_data = int3472_tps68470_get_board_data(dev_name(&client->dev));
0131         if (!board_data)
0132             return dev_err_probe(&client->dev, -ENODEV, "No board-data found for this model\n");
0133 
0134         cells = kcalloc(TPS68470_WIN_MFD_CELL_COUNT, sizeof(*cells), GFP_KERNEL);
0135         if (!cells)
0136             return -ENOMEM;
0137 
0138         /*
0139          * The order of the cells matters here! The clk must be first
0140          * because the regulator depends on it. The gpios must be last,
0141          * acpi_gpiochip_add() calls acpi_dev_clear_dependencies() and
0142          * the clk + regulators must be ready when this happens.
0143          */
0144         cells[0].name = "tps68470-clk";
0145         cells[0].platform_data = &clk_pdata;
0146         cells[0].pdata_size = sizeof(clk_pdata);
0147         cells[1].name = "tps68470-regulator";
0148         cells[1].platform_data = (void *)board_data->tps68470_regulator_pdata;
0149         cells[1].pdata_size = sizeof(struct tps68470_regulator_platform_data);
0150         cells[2].name = "tps68470-gpio";
0151 
0152         gpiod_add_lookup_table(board_data->tps68470_gpio_lookup_table);
0153 
0154         ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
0155                        cells, TPS68470_WIN_MFD_CELL_COUNT,
0156                        NULL, 0, NULL);
0157         kfree(cells);
0158 
0159         if (ret)
0160             gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table);
0161 
0162         break;
0163     case DESIGNED_FOR_CHROMEOS:
0164         ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
0165                        tps68470_cros, ARRAY_SIZE(tps68470_cros),
0166                        NULL, 0, NULL);
0167         break;
0168     default:
0169         dev_err(&client->dev, "Failed to add MFD devices\n");
0170         return device_type;
0171     }
0172 
0173     /*
0174      * No acpi_dev_clear_dependencies() here, since the acpi_gpiochip_add()
0175      * for the GPIO cell already does this.
0176      */
0177 
0178     return ret;
0179 }
0180 
0181 static int skl_int3472_tps68470_remove(struct i2c_client *client)
0182 {
0183     const struct int3472_tps68470_board_data *board_data;
0184 
0185     board_data = int3472_tps68470_get_board_data(dev_name(&client->dev));
0186     if (board_data)
0187         gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table);
0188 
0189     return 0;
0190 }
0191 
0192 static const struct acpi_device_id int3472_device_id[] = {
0193     { "INT3472", 0 },
0194     { }
0195 };
0196 MODULE_DEVICE_TABLE(acpi, int3472_device_id);
0197 
0198 static struct i2c_driver int3472_tps68470 = {
0199     .driver = {
0200         .name = "int3472-tps68470",
0201         .acpi_match_table = int3472_device_id,
0202     },
0203     .probe_new = skl_int3472_tps68470_probe,
0204     .remove = skl_int3472_tps68470_remove,
0205 };
0206 module_i2c_driver(int3472_tps68470);
0207 
0208 MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI TPS68470 Device Driver");
0209 MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>");
0210 MODULE_LICENSE("GPL v2");
0211 MODULE_SOFTDEP("pre: clk-tps68470 tps68470-regulator");