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