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) */
20static 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
27static const struct software_node acer_a1_840_bq24190_node = {
28 .properties = acer_a1_840_bq24190_props,
29};
30
31static 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
38static const struct software_node acer_a1_840_touchscreen_node = {
39 .properties = acer_a1_840_touchscreen_props,
40};
41
42static 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
93static 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
99static 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 */
109static 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
116static struct device *acer_a1_840_fg_dev;
117static struct fwnode_handle *acer_a1_840_fg_node;
118
119static 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(bus: &platform_bus_type, NULL, name: "chtdc_ti_battery");
124 if (!acer_a1_840_fg_dev)
125 return dev_err_probe(dev, err: -EPROBE_DEFER, fmt: "getting chtdc_ti_battery dev\n");
126
127 acer_a1_840_fg_node = fwnode_create_software_node(properties: acer_a1_840_fg_props, NULL);
128 if (IS_ERR(ptr: acer_a1_840_fg_node)) {
129 ret = PTR_ERR(ptr: acer_a1_840_fg_node);
130 goto err_put;
131 }
132
133 ret = device_add_software_node(dev: acer_a1_840_fg_dev,
134 node: to_software_node(fwnode: acer_a1_840_fg_node));
135 if (ret)
136 goto err_put;
137
138 return 0;
139
140err_put:
141 fwnode_handle_put(fwnode: acer_a1_840_fg_node);
142 acer_a1_840_fg_node = NULL;
143 put_device(dev: acer_a1_840_fg_dev);
144 acer_a1_840_fg_dev = NULL;
145 return ret;
146}
147
148static void acer_a1_840_exit(void)
149{
150 device_remove_software_node(dev: 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(dev: acer_a1_840_fg_dev);
159 acer_a1_840_fg_dev = NULL;
160}
161
162static const char * const acer_a1_840_modules[] __initconst = {
163 "bq24190_charger", /* For the Vbus regulator for intel-int3496 */
164 NULL
165};
166
167const 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 */
180static const char * const acer_b1_750_mount_matrix[] = {
181 "-1", "0", "0",
182 "0", "1", "0",
183 "0", "0", "1"
184};
185
186static const struct property_entry acer_b1_750_bma250e_props[] = {
187 PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", acer_b1_750_mount_matrix),
188 { }
189};
190
191static const struct software_node acer_b1_750_bma250e_node = {
192 .properties = acer_b1_750_bma250e_props,
193};
194
195static 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
200static const struct software_node acer_b1_750_novatek_node = {
201 .properties = acer_b1_750_novatek_props,
202};
203
204static 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
241const 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

source code of linux/drivers/platform/x86/x86-android-tablets/acer.c