tps68470.c (5964B)
1// SPDX-License-Identifier: GPL-2.0 2/* Author: Dan Scally <djrscally@gmail.com> */ 3 4#include <linux/i2c.h> 5#include <linux/kernel.h> 6#include <linux/mfd/core.h> 7#include <linux/mfd/tps68470.h> 8#include <linux/platform_device.h> 9#include <linux/platform_data/tps68470.h> 10#include <linux/regmap.h> 11#include <linux/string.h> 12 13#include "common.h" 14#include "tps68470.h" 15 16#define DESIGNED_FOR_CHROMEOS 1 17#define DESIGNED_FOR_WINDOWS 2 18 19#define TPS68470_WIN_MFD_CELL_COUNT 3 20 21static const struct mfd_cell tps68470_cros[] = { 22 { .name = "tps68470-gpio" }, 23 { .name = "tps68470_pmic_opregion" }, 24}; 25 26static const struct regmap_config tps68470_regmap_config = { 27 .reg_bits = 8, 28 .val_bits = 8, 29 .max_register = TPS68470_REG_MAX, 30}; 31 32static int tps68470_chip_init(struct device *dev, struct regmap *regmap) 33{ 34 unsigned int version; 35 int ret; 36 37 /* Force software reset */ 38 ret = regmap_write(regmap, TPS68470_REG_RESET, TPS68470_REG_RESET_MASK); 39 if (ret) 40 return ret; 41 42 ret = regmap_read(regmap, TPS68470_REG_REVID, &version); 43 if (ret) { 44 dev_err(dev, "Failed to read revision register: %d\n", ret); 45 return ret; 46 } 47 48 dev_info(dev, "TPS68470 REVID: 0x%02x\n", version); 49 50 return 0; 51} 52 53/** skl_int3472_tps68470_calc_type: Check what platform a device is designed for 54 * @adev: A pointer to a &struct acpi_device 55 * 56 * Check CLDB buffer against the PMIC's adev. If present, then we check 57 * the value of control_logic_type field and follow one of the 58 * following scenarios: 59 * 60 * 1. No CLDB - likely ACPI tables designed for ChromeOS. We 61 * create platform devices for the GPIOs and OpRegion drivers. 62 * 63 * 2. CLDB, with control_logic_type = 2 - probably ACPI tables 64 * made for Windows 2-in-1 platforms. Register pdevs for GPIO, 65 * Clock and Regulator drivers to bind to. 66 * 67 * 3. Any other value in control_logic_type, we should never have 68 * gotten to this point; fail probe and return. 69 * 70 * Return: 71 * * 1 Device intended for ChromeOS 72 * * 2 Device intended for Windows 73 * * -EINVAL Where @adev has an object named CLDB but it does not conform to 74 * our expectations 75 */ 76static int skl_int3472_tps68470_calc_type(struct acpi_device *adev) 77{ 78 struct int3472_cldb cldb = { 0 }; 79 int ret; 80 81 /* 82 * A CLDB buffer that exists, but which does not match our expectations 83 * should trigger an error so we don't blindly continue. 84 */ 85 ret = skl_int3472_fill_cldb(adev, &cldb); 86 if (ret && ret != -ENODEV) 87 return ret; 88 89 if (ret) 90 return DESIGNED_FOR_CHROMEOS; 91 92 if (cldb.control_logic_type != 2) 93 return -EINVAL; 94 95 return DESIGNED_FOR_WINDOWS; 96} 97 98static int skl_int3472_tps68470_probe(struct i2c_client *client) 99{ 100 struct acpi_device *adev = ACPI_COMPANION(&client->dev); 101 const struct int3472_tps68470_board_data *board_data; 102 struct tps68470_clk_platform_data clk_pdata = {}; 103 struct mfd_cell *cells; 104 struct regmap *regmap; 105 int device_type; 106 int ret; 107 108 ret = skl_int3472_get_sensor_adev_and_name(&client->dev, NULL, 109 &clk_pdata.consumer_dev_name); 110 if (ret) 111 return ret; 112 113 regmap = devm_regmap_init_i2c(client, &tps68470_regmap_config); 114 if (IS_ERR(regmap)) { 115 dev_err(&client->dev, "Failed to create regmap: %ld\n", PTR_ERR(regmap)); 116 return PTR_ERR(regmap); 117 } 118 119 i2c_set_clientdata(client, regmap); 120 121 ret = tps68470_chip_init(&client->dev, regmap); 122 if (ret < 0) { 123 dev_err(&client->dev, "TPS68470 init error %d\n", ret); 124 return ret; 125 } 126 127 device_type = skl_int3472_tps68470_calc_type(adev); 128 switch (device_type) { 129 case DESIGNED_FOR_WINDOWS: 130 board_data = int3472_tps68470_get_board_data(dev_name(&client->dev)); 131 if (!board_data) 132 return dev_err_probe(&client->dev, -ENODEV, "No board-data found for this model\n"); 133 134 cells = kcalloc(TPS68470_WIN_MFD_CELL_COUNT, sizeof(*cells), GFP_KERNEL); 135 if (!cells) 136 return -ENOMEM; 137 138 /* 139 * The order of the cells matters here! The clk must be first 140 * because the regulator depends on it. The gpios must be last, 141 * acpi_gpiochip_add() calls acpi_dev_clear_dependencies() and 142 * the clk + regulators must be ready when this happens. 143 */ 144 cells[0].name = "tps68470-clk"; 145 cells[0].platform_data = &clk_pdata; 146 cells[0].pdata_size = sizeof(clk_pdata); 147 cells[1].name = "tps68470-regulator"; 148 cells[1].platform_data = (void *)board_data->tps68470_regulator_pdata; 149 cells[1].pdata_size = sizeof(struct tps68470_regulator_platform_data); 150 cells[2].name = "tps68470-gpio"; 151 152 gpiod_add_lookup_table(board_data->tps68470_gpio_lookup_table); 153 154 ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, 155 cells, TPS68470_WIN_MFD_CELL_COUNT, 156 NULL, 0, NULL); 157 kfree(cells); 158 159 if (ret) 160 gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table); 161 162 break; 163 case DESIGNED_FOR_CHROMEOS: 164 ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, 165 tps68470_cros, ARRAY_SIZE(tps68470_cros), 166 NULL, 0, NULL); 167 break; 168 default: 169 dev_err(&client->dev, "Failed to add MFD devices\n"); 170 return device_type; 171 } 172 173 /* 174 * No acpi_dev_clear_dependencies() here, since the acpi_gpiochip_add() 175 * for the GPIO cell already does this. 176 */ 177 178 return ret; 179} 180 181static int skl_int3472_tps68470_remove(struct i2c_client *client) 182{ 183 const struct int3472_tps68470_board_data *board_data; 184 185 board_data = int3472_tps68470_get_board_data(dev_name(&client->dev)); 186 if (board_data) 187 gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table); 188 189 return 0; 190} 191 192static const struct acpi_device_id int3472_device_id[] = { 193 { "INT3472", 0 }, 194 { } 195}; 196MODULE_DEVICE_TABLE(acpi, int3472_device_id); 197 198static struct i2c_driver int3472_tps68470 = { 199 .driver = { 200 .name = "int3472-tps68470", 201 .acpi_match_table = int3472_device_id, 202 }, 203 .probe_new = skl_int3472_tps68470_probe, 204 .remove = skl_int3472_tps68470_remove, 205}; 206module_i2c_driver(int3472_tps68470); 207 208MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI TPS68470 Device Driver"); 209MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>"); 210MODULE_LICENSE("GPL v2"); 211MODULE_SOFTDEP("pre: clk-tps68470 tps68470-regulator");