xref: /linux/drivers/platform/x86/x86-android-tablets/acer.c (revision e3966940559d52aa1800a008dcfeec218dd31f88)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Board info for Acer X86 tablets which ship with Android as the factory image
4  * and which have broken DSDT tables. The factory kernels shipped on these
5  * devices typically have a bunch of things hardcoded, rather than specified
6  * in their DSDT.
7  *
8  * Copyright (C) 2021-2025 Hans de Goede <hansg@kernel.org>
9  */
10 
11 #include <linux/gpio/machine.h>
12 #include <linux/gpio/property.h>
13 #include <linux/platform_device.h>
14 #include <linux/property.h>
15 
16 #include "shared-psy-info.h"
17 #include "x86-android-tablets.h"
18 
19 /* Acer Iconia One 8 A1-840 (non FHD version) */
20 static const struct property_entry acer_a1_840_bq24190_props[] = {
21 	PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_4v2_battery_node),
22 	PROPERTY_ENTRY_BOOL("omit-battery-class"),
23 	PROPERTY_ENTRY_BOOL("disable-reset"),
24 	{ }
25 };
26 
27 static const struct software_node acer_a1_840_bq24190_node = {
28 	.properties = acer_a1_840_bq24190_props,
29 };
30 
31 static const struct property_entry acer_a1_840_touchscreen_props[] = {
32 	PROPERTY_ENTRY_U32("touchscreen-size-x", 800),
33 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
34 	PROPERTY_ENTRY_GPIO("reset-gpios", &baytrail_gpiochip_nodes[1], 26, GPIO_ACTIVE_LOW),
35 	{ }
36 };
37 
38 static const struct software_node acer_a1_840_touchscreen_node = {
39 	.properties = acer_a1_840_touchscreen_props,
40 };
41 
42 static const struct x86_i2c_client_info acer_a1_840_i2c_clients[] __initconst = {
43 	{
44 		/* BQ24297 charger IC */
45 		.board_info = {
46 			.type = "bq24297",
47 			.addr = 0x6b,
48 			.dev_name = "bq24297",
49 			.swnode = &acer_a1_840_bq24190_node,
50 			.platform_data = &bq24190_pdata,
51 		},
52 		.adapter_path = "\\_SB_.I2C1",
53 		.irq_data = {
54 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
55 			.chip = "INT33FC:02",
56 			.index = 2,
57 			.trigger = ACPI_EDGE_SENSITIVE,
58 			.polarity = ACPI_ACTIVE_LOW,
59 			.con_id = "bq24297_irq",
60 		},
61 	}, {
62 		/* MPU6515 sensors */
63 		.board_info = {
64 			.type = "mpu6515",
65 			.addr = 0x69,
66 			.dev_name = "mpu6515",
67 		},
68 		.adapter_path = "\\_SB_.I2C3",
69 		.irq_data = {
70 			.type = X86_ACPI_IRQ_TYPE_APIC,
71 			.index = 0x47,
72 			.trigger = ACPI_EDGE_SENSITIVE,
73 			.polarity = ACPI_ACTIVE_HIGH,
74 		},
75 	}, {
76 		/* FT5416 touchscreen controller */
77 		.board_info = {
78 			.type = "edt-ft5x06",
79 			.addr = 0x38,
80 			.dev_name = "ft5416",
81 			.swnode = &acer_a1_840_touchscreen_node,
82 		},
83 		.adapter_path = "\\_SB_.I2C4",
84 		.irq_data = {
85 			.type = X86_ACPI_IRQ_TYPE_APIC,
86 			.index = 0x45,
87 			.trigger = ACPI_EDGE_SENSITIVE,
88 			.polarity = ACPI_ACTIVE_HIGH,
89 		},
90 	}
91 };
92 
93 static const struct property_entry acer_a1_840_int3496_props[] __initconst = {
94 	PROPERTY_ENTRY_GPIO("mux-gpios", &baytrail_gpiochip_nodes[2], 1, GPIO_ACTIVE_HIGH),
95 	PROPERTY_ENTRY_GPIO("id-gpios", &baytrail_gpiochip_nodes[2], 18, GPIO_ACTIVE_HIGH),
96 	{ }
97 };
98 
99 static const struct platform_device_info acer_a1_840_pdevs[] __initconst = {
100 	{
101 		/* For micro USB ID pin handling */
102 		.name = "intel-int3496",
103 		.id = PLATFORM_DEVID_NONE,
104 		.properties = acer_a1_840_int3496_props,
105 	},
106 };
107 
108 /* Properties for the Dollar Cove TI PMIC battery MFD child used as fuel-gauge */
109 static const struct property_entry acer_a1_840_fg_props[] = {
110 	PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_4v2_battery_node),
111 	PROPERTY_ENTRY_STRING_ARRAY_LEN("supplied-from", bq24190_psy, 1),
112 	PROPERTY_ENTRY_GPIO("charged-gpios", &baytrail_gpiochip_nodes[2], 10, GPIO_ACTIVE_HIGH),
113 	{ }
114 };
115 
116 static struct device *acer_a1_840_fg_dev;
117 static struct fwnode_handle *acer_a1_840_fg_node;
118 
119 static int __init acer_a1_840_init(struct device *dev)
120 {
121 	int ret;
122 
123 	acer_a1_840_fg_dev = bus_find_device_by_name(&platform_bus_type, NULL, "chtdc_ti_battery");
124 	if (!acer_a1_840_fg_dev)
125 		return dev_err_probe(dev, -EPROBE_DEFER, "getting chtdc_ti_battery dev\n");
126 
127 	acer_a1_840_fg_node = fwnode_create_software_node(acer_a1_840_fg_props, NULL);
128 	if (IS_ERR(acer_a1_840_fg_node)) {
129 		ret = PTR_ERR(acer_a1_840_fg_node);
130 		goto err_put;
131 	}
132 
133 	ret = device_add_software_node(acer_a1_840_fg_dev,
134 				       to_software_node(acer_a1_840_fg_node));
135 	if (ret)
136 		goto err_put;
137 
138 	return 0;
139 
140 err_put:
141 	fwnode_handle_put(acer_a1_840_fg_node);
142 	acer_a1_840_fg_node = NULL;
143 	put_device(acer_a1_840_fg_dev);
144 	acer_a1_840_fg_dev = NULL;
145 	return ret;
146 }
147 
148 static void acer_a1_840_exit(void)
149 {
150 	device_remove_software_node(acer_a1_840_fg_dev);
151 	/*
152 	 * Skip fwnode_handle_put(acer_a1_840_fg_node), instead leak the node.
153 	 * The intel_dc_ti_battery driver may still reference the strdup-ed
154 	 * "supplied-from" string. This string will be free-ed if the node
155 	 * is released.
156 	 */
157 	acer_a1_840_fg_node = NULL;
158 	put_device(acer_a1_840_fg_dev);
159 	acer_a1_840_fg_dev = NULL;
160 }
161 
162 static const char * const acer_a1_840_modules[] __initconst = {
163 	"bq24190_charger",	/* For the Vbus regulator for intel-int3496 */
164 	NULL
165 };
166 
167 const struct x86_dev_info acer_a1_840_info __initconst = {
168 	.i2c_client_info = acer_a1_840_i2c_clients,
169 	.i2c_client_count = ARRAY_SIZE(acer_a1_840_i2c_clients),
170 	.pdev_info = acer_a1_840_pdevs,
171 	.pdev_count = ARRAY_SIZE(acer_a1_840_pdevs),
172 	.gpiochip_type = X86_GPIOCHIP_BAYTRAIL,
173 	.swnode_group = generic_lipo_4v2_battery_swnodes,
174 	.modules = acer_a1_840_modules,
175 	.init = acer_a1_840_init,
176 	.exit = acer_a1_840_exit,
177 };
178 
179 /* Acer Iconia One 7 B1-750 has an Android factory image with everything hardcoded */
180 static const char * const acer_b1_750_mount_matrix[] = {
181 	"-1", "0", "0",
182 	"0", "1", "0",
183 	"0", "0", "1"
184 };
185 
186 static const struct property_entry acer_b1_750_bma250e_props[] = {
187 	PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", acer_b1_750_mount_matrix),
188 	{ }
189 };
190 
191 static const struct software_node acer_b1_750_bma250e_node = {
192 	.properties = acer_b1_750_bma250e_props,
193 };
194 
195 static const struct property_entry acer_b1_750_novatek_props[] = {
196 	PROPERTY_ENTRY_GPIO("reset-gpios", &baytrail_gpiochip_nodes[1], 26, GPIO_ACTIVE_LOW),
197 	{ }
198 };
199 
200 static const struct software_node acer_b1_750_novatek_node = {
201 	.properties = acer_b1_750_novatek_props,
202 };
203 
204 static const struct x86_i2c_client_info acer_b1_750_i2c_clients[] __initconst = {
205 	{
206 		/* Novatek NVT-ts touchscreen */
207 		.board_info = {
208 			.type = "nt11205-ts",
209 			.addr = 0x34,
210 			.dev_name = "NVT-ts",
211 			.swnode = &acer_b1_750_novatek_node,
212 		},
213 		.adapter_path = "\\_SB_.I2C4",
214 		.irq_data = {
215 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
216 			.chip = "INT33FC:02",
217 			.index = 3,
218 			.trigger = ACPI_EDGE_SENSITIVE,
219 			.polarity = ACPI_ACTIVE_LOW,
220 			.con_id = "NVT-ts_irq",
221 		},
222 	}, {
223 		/* BMA250E accelerometer */
224 		.board_info = {
225 			.type = "bma250e",
226 			.addr = 0x18,
227 			.swnode = &acer_b1_750_bma250e_node,
228 		},
229 		.adapter_path = "\\_SB_.I2C3",
230 		.irq_data = {
231 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
232 			.chip = "INT33FC:02",
233 			.index = 25,
234 			.trigger = ACPI_LEVEL_SENSITIVE,
235 			.polarity = ACPI_ACTIVE_HIGH,
236 			.con_id = "bma250e_irq",
237 		},
238 	},
239 };
240 
241 const struct x86_dev_info acer_b1_750_info __initconst = {
242 	.i2c_client_info = acer_b1_750_i2c_clients,
243 	.i2c_client_count = ARRAY_SIZE(acer_b1_750_i2c_clients),
244 	.pdev_info = int3496_pdevs,
245 	.pdev_count = 1,
246 	.gpiochip_type = X86_GPIOCHIP_BAYTRAIL,
247 };
248