1 // SPDX-License-Identifier: GPL-2.0+
2 // Driver to instantiate Chromebook i2c/smbus devices.
4 // Copyright (C) 2012 Google, Inc.
5 // Author: Benson Leung <bleung@chromium.org>
7 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9 #include <linux/acpi.h>
10 #include <linux/dmi.h>
11 #include <linux/i2c.h>
12 #include <linux/input.h>
13 #include <linux/interrupt.h>
14 #include <linux/ioport.h>
15 #include <linux/module.h>
16 #include <linux/pci.h>
17 #include <linux/platform_device.h>
18 #include <linux/property.h>
20 #define ATMEL_TP_I2C_ADDR 0x4b
21 #define ATMEL_TP_I2C_BL_ADDR 0x25
22 #define ATMEL_TS_I2C_ADDR 0x4a
23 #define ATMEL_TS_I2C_BL_ADDR 0x26
24 #define CYAPA_TP_I2C_ADDR 0x67
25 #define ELAN_TP_I2C_ADDR 0x15
26 #define ISL_ALS_I2C_ADDR 0x44
27 #define TAOS_ALS_I2C_ADDR 0x29
29 static const char *i2c_adapter_names
[] = {
33 "Synopsys DesignWare I2C adapter",
36 /* Keep this enum consistent with i2c_adapter_names */
37 enum i2c_adapter_type
{
38 I2C_ADAPTER_SMBUS
= 0,
41 I2C_ADAPTER_DESIGNWARE
,
44 struct i2c_peripheral
{
45 struct i2c_board_info board_info
;
46 unsigned short alt_addr
;
49 unsigned long irqflags
;
50 struct resource irq_resource
;
52 enum i2c_adapter_type type
;
55 const struct property_entry
*properties
;
57 struct i2c_client
*client
;
60 struct acpi_peripheral
{
61 char hid
[ACPI_ID_LEN
];
62 struct software_node swnode
;
63 struct i2c_client
*client
;
66 struct chromeos_laptop
{
68 * Note that we can't mark this pointer as const because
69 * i2c_new_scanned_device() changes passed in I2C board info, so.
71 struct i2c_peripheral
*i2c_peripherals
;
72 unsigned int num_i2c_peripherals
;
74 struct acpi_peripheral
*acpi_peripherals
;
75 unsigned int num_acpi_peripherals
;
78 static const struct chromeos_laptop
*cros_laptop
;
80 static struct i2c_client
*
81 chromes_laptop_instantiate_i2c_device(struct i2c_adapter
*adapter
,
82 struct i2c_board_info
*info
,
83 unsigned short alt_addr
)
85 const unsigned short addr_list
[] = { info
->addr
, I2C_CLIENT_END
};
86 struct i2c_client
*client
;
89 * Add the i2c device. If we can't detect it at the primary
90 * address we scan secondary addresses. In any case the client
91 * structure gets assigned primary address.
93 client
= i2c_new_scanned_device(adapter
, info
, addr_list
, NULL
);
94 if (IS_ERR(client
) && alt_addr
) {
95 struct i2c_board_info dummy_info
= {
96 I2C_BOARD_INFO("dummy", info
->addr
),
98 const unsigned short alt_addr_list
[] = {
99 alt_addr
, I2C_CLIENT_END
101 struct i2c_client
*dummy
;
103 dummy
= i2c_new_scanned_device(adapter
, &dummy_info
,
104 alt_addr_list
, NULL
);
105 if (!IS_ERR(dummy
)) {
106 pr_debug("%d-%02x is probed at %02x\n",
107 adapter
->nr
, info
->addr
, dummy
->addr
);
108 i2c_unregister_device(dummy
);
109 client
= i2c_new_client_device(adapter
, info
);
113 if (IS_ERR(client
)) {
115 pr_debug("failed to register device %d-%02x\n",
116 adapter
->nr
, info
->addr
);
118 pr_debug("added i2c device %d-%02x\n",
119 adapter
->nr
, info
->addr
);
125 static bool chromeos_laptop_match_adapter_devid(struct device
*dev
, u32 devid
)
127 struct pci_dev
*pdev
;
129 if (!dev_is_pci(dev
))
132 pdev
= to_pci_dev(dev
);
133 return devid
== pci_dev_id(pdev
);
136 static void chromeos_laptop_check_adapter(struct i2c_adapter
*adapter
)
138 struct i2c_peripheral
*i2c_dev
;
141 for (i
= 0; i
< cros_laptop
->num_i2c_peripherals
; i
++) {
142 i2c_dev
= &cros_laptop
->i2c_peripherals
[i
];
144 /* Skip devices already created */
148 if (strncmp(adapter
->name
, i2c_adapter_names
[i2c_dev
->type
],
149 strlen(i2c_adapter_names
[i2c_dev
->type
])))
152 if (i2c_dev
->pci_devid
&&
153 !chromeos_laptop_match_adapter_devid(adapter
->dev
.parent
,
154 i2c_dev
->pci_devid
)) {
159 chromes_laptop_instantiate_i2c_device(adapter
,
160 &i2c_dev
->board_info
,
165 static bool chromeos_laptop_adjust_client(struct i2c_client
*client
)
167 struct acpi_peripheral
*acpi_dev
;
168 struct acpi_device_id acpi_ids
[2] = { };
172 if (!has_acpi_companion(&client
->dev
))
175 for (i
= 0; i
< cros_laptop
->num_acpi_peripherals
; i
++) {
176 acpi_dev
= &cros_laptop
->acpi_peripherals
[i
];
178 memcpy(acpi_ids
[0].id
, acpi_dev
->hid
, ACPI_ID_LEN
);
180 if (acpi_match_device(acpi_ids
, &client
->dev
)) {
181 error
= device_add_software_node(&client
->dev
, &acpi_dev
->swnode
);
183 dev_err(&client
->dev
,
184 "failed to add properties: %d\n",
189 acpi_dev
->client
= client
;
198 static void chromeos_laptop_detach_i2c_client(struct i2c_client
*client
)
200 struct acpi_peripheral
*acpi_dev
;
201 struct i2c_peripheral
*i2c_dev
;
204 if (has_acpi_companion(&client
->dev
))
205 for (i
= 0; i
< cros_laptop
->num_acpi_peripherals
; i
++) {
206 acpi_dev
= &cros_laptop
->acpi_peripherals
[i
];
208 if (acpi_dev
->client
== client
) {
209 acpi_dev
->client
= NULL
;
214 for (i
= 0; i
< cros_laptop
->num_i2c_peripherals
; i
++) {
215 i2c_dev
= &cros_laptop
->i2c_peripherals
[i
];
217 if (i2c_dev
->client
== client
) {
218 i2c_dev
->client
= NULL
;
224 static int chromeos_laptop_i2c_notifier_call(struct notifier_block
*nb
,
225 unsigned long action
, void *data
)
227 struct device
*dev
= data
;
230 case BUS_NOTIFY_ADD_DEVICE
:
231 if (dev
->type
== &i2c_adapter_type
)
232 chromeos_laptop_check_adapter(to_i2c_adapter(dev
));
233 else if (dev
->type
== &i2c_client_type
)
234 chromeos_laptop_adjust_client(to_i2c_client(dev
));
237 case BUS_NOTIFY_REMOVED_DEVICE
:
238 if (dev
->type
== &i2c_client_type
)
239 chromeos_laptop_detach_i2c_client(to_i2c_client(dev
));
246 static struct notifier_block chromeos_laptop_i2c_notifier
= {
247 .notifier_call
= chromeos_laptop_i2c_notifier_call
,
250 #define DECLARE_CROS_LAPTOP(_name) \
251 static const struct chromeos_laptop _name __initconst = { \
252 .i2c_peripherals = _name##_peripherals, \
253 .num_i2c_peripherals = ARRAY_SIZE(_name##_peripherals), \
256 #define DECLARE_ACPI_CROS_LAPTOP(_name) \
257 static const struct chromeos_laptop _name __initconst = { \
258 .acpi_peripherals = _name##_peripherals, \
259 .num_acpi_peripherals = ARRAY_SIZE(_name##_peripherals), \
262 static struct i2c_peripheral samsung_series_5_550_peripherals
[] __initdata
= {
266 I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR
),
267 .flags
= I2C_CLIENT_WAKE
,
269 .dmi_name
= "trackpad",
270 .type
= I2C_ADAPTER_SMBUS
,
275 I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR
),
277 .dmi_name
= "lightsensor",
278 .type
= I2C_ADAPTER_SMBUS
,
281 DECLARE_CROS_LAPTOP(samsung_series_5_550
);
283 static struct i2c_peripheral samsung_series_5_peripherals
[] __initdata
= {
287 I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR
),
289 .type
= I2C_ADAPTER_SMBUS
,
292 DECLARE_CROS_LAPTOP(samsung_series_5
);
294 static const int chromebook_pixel_tp_keys
[] __initconst
= {
303 static const struct property_entry
304 chromebook_pixel_trackpad_props
[] __initconst
= {
305 PROPERTY_ENTRY_STRING("compatible", "atmel,maxtouch"),
306 PROPERTY_ENTRY_U32_ARRAY("linux,gpio-keymap", chromebook_pixel_tp_keys
),
310 static const struct property_entry
311 chromebook_atmel_touchscreen_props
[] __initconst
= {
312 PROPERTY_ENTRY_STRING("compatible", "atmel,maxtouch"),
316 static struct i2c_peripheral chromebook_pixel_peripherals
[] __initdata
= {
320 I2C_BOARD_INFO("atmel_mxt_ts",
322 .flags
= I2C_CLIENT_WAKE
,
324 .dmi_name
= "touchscreen",
325 .irqflags
= IRQF_TRIGGER_FALLING
,
326 .type
= I2C_ADAPTER_PANEL
,
327 .alt_addr
= ATMEL_TS_I2C_BL_ADDR
,
328 .properties
= chromebook_atmel_touchscreen_props
,
333 I2C_BOARD_INFO("atmel_mxt_tp",
335 .flags
= I2C_CLIENT_WAKE
,
337 .dmi_name
= "trackpad",
338 .irqflags
= IRQF_TRIGGER_FALLING
,
339 .type
= I2C_ADAPTER_VGADDC
,
340 .alt_addr
= ATMEL_TP_I2C_BL_ADDR
,
341 .properties
= chromebook_pixel_trackpad_props
,
346 I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR
),
348 .dmi_name
= "lightsensor",
349 .type
= I2C_ADAPTER_PANEL
,
352 DECLARE_CROS_LAPTOP(chromebook_pixel
);
354 static struct i2c_peripheral hp_chromebook_14_peripherals
[] __initdata
= {
358 I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR
),
359 .flags
= I2C_CLIENT_WAKE
,
361 .dmi_name
= "trackpad",
362 .type
= I2C_ADAPTER_DESIGNWARE
,
365 DECLARE_CROS_LAPTOP(hp_chromebook_14
);
367 static struct i2c_peripheral dell_chromebook_11_peripherals
[] __initdata
= {
371 I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR
),
372 .flags
= I2C_CLIENT_WAKE
,
374 .dmi_name
= "trackpad",
375 .type
= I2C_ADAPTER_DESIGNWARE
,
377 /* Elan Touchpad option. */
380 I2C_BOARD_INFO("elan_i2c", ELAN_TP_I2C_ADDR
),
381 .flags
= I2C_CLIENT_WAKE
,
383 .dmi_name
= "trackpad",
384 .type
= I2C_ADAPTER_DESIGNWARE
,
387 DECLARE_CROS_LAPTOP(dell_chromebook_11
);
389 static struct i2c_peripheral toshiba_cb35_peripherals
[] __initdata
= {
393 I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR
),
394 .flags
= I2C_CLIENT_WAKE
,
396 .dmi_name
= "trackpad",
397 .type
= I2C_ADAPTER_DESIGNWARE
,
400 DECLARE_CROS_LAPTOP(toshiba_cb35
);
402 static struct i2c_peripheral acer_c7_chromebook_peripherals
[] __initdata
= {
406 I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR
),
407 .flags
= I2C_CLIENT_WAKE
,
409 .dmi_name
= "trackpad",
410 .type
= I2C_ADAPTER_SMBUS
,
413 DECLARE_CROS_LAPTOP(acer_c7_chromebook
);
415 static struct i2c_peripheral acer_ac700_peripherals
[] __initdata
= {
419 I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR
),
421 .type
= I2C_ADAPTER_SMBUS
,
424 DECLARE_CROS_LAPTOP(acer_ac700
);
426 static struct i2c_peripheral acer_c720_peripherals
[] __initdata
= {
430 I2C_BOARD_INFO("atmel_mxt_ts",
432 .flags
= I2C_CLIENT_WAKE
,
434 .dmi_name
= "touchscreen",
435 .irqflags
= IRQF_TRIGGER_FALLING
,
436 .type
= I2C_ADAPTER_DESIGNWARE
,
437 .pci_devid
= PCI_DEVID(0, PCI_DEVFN(0x15, 0x2)),
438 .alt_addr
= ATMEL_TS_I2C_BL_ADDR
,
439 .properties
= chromebook_atmel_touchscreen_props
,
444 I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR
),
445 .flags
= I2C_CLIENT_WAKE
,
447 .dmi_name
= "trackpad",
448 .type
= I2C_ADAPTER_DESIGNWARE
,
449 .pci_devid
= PCI_DEVID(0, PCI_DEVFN(0x15, 0x1)),
451 /* Elan Touchpad option. */
454 I2C_BOARD_INFO("elan_i2c", ELAN_TP_I2C_ADDR
),
455 .flags
= I2C_CLIENT_WAKE
,
457 .dmi_name
= "trackpad",
458 .type
= I2C_ADAPTER_DESIGNWARE
,
459 .pci_devid
= PCI_DEVID(0, PCI_DEVFN(0x15, 0x1)),
464 I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR
),
466 .dmi_name
= "lightsensor",
467 .type
= I2C_ADAPTER_DESIGNWARE
,
468 .pci_devid
= PCI_DEVID(0, PCI_DEVFN(0x15, 0x2)),
471 DECLARE_CROS_LAPTOP(acer_c720
);
473 static struct i2c_peripheral
474 hp_pavilion_14_chromebook_peripherals
[] __initdata
= {
478 I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR
),
479 .flags
= I2C_CLIENT_WAKE
,
481 .dmi_name
= "trackpad",
482 .type
= I2C_ADAPTER_SMBUS
,
485 DECLARE_CROS_LAPTOP(hp_pavilion_14_chromebook
);
487 static struct i2c_peripheral cr48_peripherals
[] __initdata
= {
491 I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR
),
493 .type
= I2C_ADAPTER_SMBUS
,
496 DECLARE_CROS_LAPTOP(cr48
);
498 static const u32 samus_touchpad_buttons
[] __initconst
= {
505 static const struct property_entry samus_trackpad_props
[] __initconst
= {
506 PROPERTY_ENTRY_STRING("compatible", "atmel,maxtouch"),
507 PROPERTY_ENTRY_U32_ARRAY("linux,gpio-keymap", samus_touchpad_buttons
),
511 static struct acpi_peripheral samus_peripherals
[] __initdata
= {
516 .properties
= samus_trackpad_props
,
523 .properties
= chromebook_atmel_touchscreen_props
,
527 DECLARE_ACPI_CROS_LAPTOP(samus
);
529 static struct acpi_peripheral generic_atmel_peripherals
[] __initdata
= {
534 .properties
= chromebook_pixel_trackpad_props
,
541 .properties
= chromebook_atmel_touchscreen_props
,
545 DECLARE_ACPI_CROS_LAPTOP(generic_atmel
);
547 static const struct dmi_system_id chromeos_laptop_dmi_table
[] __initconst
= {
549 .ident
= "Samsung Series 5 550",
551 DMI_MATCH(DMI_SYS_VENDOR
, "SAMSUNG"),
552 DMI_MATCH(DMI_PRODUCT_NAME
, "Lumpy"),
554 .driver_data
= (void *)&samsung_series_5_550
,
557 .ident
= "Samsung Series 5",
559 DMI_MATCH(DMI_PRODUCT_NAME
, "Alex"),
561 .driver_data
= (void *)&samsung_series_5
,
564 .ident
= "Chromebook Pixel",
566 DMI_MATCH(DMI_SYS_VENDOR
, "GOOGLE"),
567 DMI_MATCH(DMI_PRODUCT_NAME
, "Link"),
569 .driver_data
= (void *)&chromebook_pixel
,
574 DMI_MATCH(DMI_BIOS_VENDOR
, "coreboot"),
575 DMI_MATCH(DMI_PRODUCT_NAME
, "Wolf"),
577 .driver_data
= (void *)&dell_chromebook_11
,
580 .ident
= "HP Chromebook 14",
582 DMI_MATCH(DMI_BIOS_VENDOR
, "coreboot"),
583 DMI_MATCH(DMI_PRODUCT_NAME
, "Falco"),
585 .driver_data
= (void *)&hp_chromebook_14
,
588 .ident
= "Toshiba CB35",
590 DMI_MATCH(DMI_BIOS_VENDOR
, "coreboot"),
591 DMI_MATCH(DMI_PRODUCT_NAME
, "Leon"),
593 .driver_data
= (void *)&toshiba_cb35
,
596 .ident
= "Acer C7 Chromebook",
598 DMI_MATCH(DMI_PRODUCT_NAME
, "Parrot"),
600 .driver_data
= (void *)&acer_c7_chromebook
,
603 .ident
= "Acer AC700",
605 DMI_MATCH(DMI_PRODUCT_NAME
, "ZGB"),
607 .driver_data
= (void *)&acer_ac700
,
610 .ident
= "Acer C720",
612 DMI_MATCH(DMI_PRODUCT_NAME
, "Peppy"),
614 .driver_data
= (void *)&acer_c720
,
617 .ident
= "HP Pavilion 14 Chromebook",
619 DMI_MATCH(DMI_PRODUCT_NAME
, "Butterfly"),
621 .driver_data
= (void *)&hp_pavilion_14_chromebook
,
626 DMI_MATCH(DMI_PRODUCT_NAME
, "Mario"),
628 .driver_data
= (void *)&cr48
,
630 /* Devices with peripherals incompletely described in ACPI */
632 .ident
= "Chromebook Pro",
634 DMI_MATCH(DMI_SYS_VENDOR
, "Google"),
635 DMI_MATCH(DMI_PRODUCT_NAME
, "Caroline"),
637 .driver_data
= (void *)&samus
,
640 .ident
= "Google Pixel 2 (2015)",
642 DMI_MATCH(DMI_SYS_VENDOR
, "GOOGLE"),
643 DMI_MATCH(DMI_PRODUCT_NAME
, "Samus"),
645 .driver_data
= (void *)&samus
,
648 .ident
= "Samsung Chromebook 3",
650 DMI_MATCH(DMI_SYS_VENDOR
, "GOOGLE"),
651 DMI_MATCH(DMI_PRODUCT_NAME
, "Celes"),
653 .driver_data
= (void *)&samus
,
657 * Other Chromebooks with Atmel touch controllers:
659 * - Clapper, Expresso, Rambi, Glimmer (touchscreen)
661 .ident
= "Other Chromebook",
664 * This will match all Google devices, not only devices
665 * with Atmel, but we will validate that the device
666 * actually has matching peripherals.
668 DMI_MATCH(DMI_SYS_VENDOR
, "GOOGLE"),
670 .driver_data
= (void *)&generic_atmel
,
674 MODULE_DEVICE_TABLE(dmi
, chromeos_laptop_dmi_table
);
676 static int __init
chromeos_laptop_scan_peripherals(struct device
*dev
, void *data
)
680 if (dev
->type
== &i2c_adapter_type
) {
681 chromeos_laptop_check_adapter(to_i2c_adapter(dev
));
682 } else if (dev
->type
== &i2c_client_type
) {
683 if (chromeos_laptop_adjust_client(to_i2c_client(dev
))) {
685 * Now that we have needed properties re-trigger
686 * driver probe in case driver was initialized
687 * earlier and probe failed.
689 error
= device_attach(dev
);
692 "%s: device_attach() failed: %d\n",
700 static int __init
chromeos_laptop_get_irq_from_dmi(const char *dmi_name
)
702 const struct dmi_device
*dmi_dev
;
703 const struct dmi_dev_onboard
*dev_data
;
705 dmi_dev
= dmi_find_device(DMI_DEV_TYPE_DEV_ONBOARD
, dmi_name
, NULL
);
707 pr_err("failed to find DMI device '%s'\n", dmi_name
);
711 dev_data
= dmi_dev
->device_data
;
713 pr_err("failed to get data from DMI for '%s'\n", dmi_name
);
717 return dev_data
->instance
;
720 static int __init
chromeos_laptop_setup_irq(struct i2c_peripheral
*i2c_dev
)
724 if (i2c_dev
->dmi_name
) {
725 irq
= chromeos_laptop_get_irq_from_dmi(i2c_dev
->dmi_name
);
729 i2c_dev
->irq_resource
= (struct resource
)
730 DEFINE_RES_NAMED(irq
, 1, NULL
,
731 IORESOURCE_IRQ
| i2c_dev
->irqflags
);
732 i2c_dev
->board_info
.resources
= &i2c_dev
->irq_resource
;
733 i2c_dev
->board_info
.num_resources
= 1;
740 chromeos_laptop_prepare_i2c_peripherals(struct chromeos_laptop
*cros_laptop
,
741 const struct chromeos_laptop
*src
)
743 struct i2c_peripheral
*i2c_peripherals
;
744 struct i2c_peripheral
*i2c_dev
;
745 struct i2c_board_info
*info
;
749 if (!src
->num_i2c_peripherals
)
752 i2c_peripherals
= kmemdup_array(src
->i2c_peripherals
,
753 src
->num_i2c_peripherals
,
754 sizeof(*i2c_peripherals
), GFP_KERNEL
);
755 if (!i2c_peripherals
)
758 for (i
= 0; i
< src
->num_i2c_peripherals
; i
++) {
759 i2c_dev
= &i2c_peripherals
[i
];
760 info
= &i2c_dev
->board_info
;
762 error
= chromeos_laptop_setup_irq(i2c_dev
);
766 /* Create primary fwnode for the device - copies everything */
767 if (i2c_dev
->properties
) {
768 info
->fwnode
= fwnode_create_software_node(i2c_dev
->properties
, NULL
);
769 if (IS_ERR(info
->fwnode
)) {
770 error
= PTR_ERR(info
->fwnode
);
776 cros_laptop
->i2c_peripherals
= i2c_peripherals
;
777 cros_laptop
->num_i2c_peripherals
= src
->num_i2c_peripherals
;
783 i2c_dev
= &i2c_peripherals
[i
];
784 info
= &i2c_dev
->board_info
;
785 if (!IS_ERR_OR_NULL(info
->fwnode
))
786 fwnode_remove_software_node(info
->fwnode
);
788 kfree(i2c_peripherals
);
793 chromeos_laptop_prepare_acpi_peripherals(struct chromeos_laptop
*cros_laptop
,
794 const struct chromeos_laptop
*src
)
796 struct acpi_peripheral
*acpi_peripherals
;
797 struct acpi_peripheral
*acpi_dev
;
798 const struct acpi_peripheral
*src_dev
;
799 int n_peripherals
= 0;
803 for (i
= 0; i
< src
->num_acpi_peripherals
; i
++) {
804 if (acpi_dev_present(src
->acpi_peripherals
[i
].hid
, NULL
, -1))
811 acpi_peripherals
= kcalloc(n_peripherals
,
812 sizeof(*src
->acpi_peripherals
),
814 if (!acpi_peripherals
)
817 acpi_dev
= acpi_peripherals
;
818 for (i
= 0; i
< src
->num_acpi_peripherals
; i
++) {
819 src_dev
= &src
->acpi_peripherals
[i
];
820 if (!acpi_dev_present(src_dev
->hid
, NULL
, -1))
823 *acpi_dev
= *src_dev
;
825 /* We need to deep-copy properties */
826 if (src_dev
->swnode
.properties
) {
827 acpi_dev
->swnode
.properties
=
828 property_entries_dup(src_dev
->swnode
.properties
);
829 if (IS_ERR(acpi_dev
->swnode
.properties
)) {
830 error
= PTR_ERR(acpi_dev
->swnode
.properties
);
838 cros_laptop
->acpi_peripherals
= acpi_peripherals
;
839 cros_laptop
->num_acpi_peripherals
= n_peripherals
;
845 acpi_dev
= &acpi_peripherals
[i
];
846 if (!IS_ERR_OR_NULL(acpi_dev
->swnode
.properties
))
847 property_entries_free(acpi_dev
->swnode
.properties
);
850 kfree(acpi_peripherals
);
854 static void chromeos_laptop_destroy(const struct chromeos_laptop
*cros_laptop
)
856 const struct acpi_peripheral
*acpi_dev
;
857 struct i2c_peripheral
*i2c_dev
;
860 for (i
= 0; i
< cros_laptop
->num_i2c_peripherals
; i
++) {
861 i2c_dev
= &cros_laptop
->i2c_peripherals
[i
];
862 i2c_unregister_device(i2c_dev
->client
);
865 for (i
= 0; i
< cros_laptop
->num_acpi_peripherals
; i
++) {
866 acpi_dev
= &cros_laptop
->acpi_peripherals
[i
];
868 if (acpi_dev
->client
)
869 device_remove_software_node(&acpi_dev
->client
->dev
);
871 property_entries_free(acpi_dev
->swnode
.properties
);
874 kfree(cros_laptop
->i2c_peripherals
);
875 kfree(cros_laptop
->acpi_peripherals
);
879 static struct chromeos_laptop
* __init
880 chromeos_laptop_prepare(const struct chromeos_laptop
*src
)
882 struct chromeos_laptop
*cros_laptop
;
885 cros_laptop
= kzalloc(sizeof(*cros_laptop
), GFP_KERNEL
);
887 return ERR_PTR(-ENOMEM
);
889 error
= chromeos_laptop_prepare_i2c_peripherals(cros_laptop
, src
);
891 error
= chromeos_laptop_prepare_acpi_peripherals(cros_laptop
,
895 chromeos_laptop_destroy(cros_laptop
);
896 return ERR_PTR(error
);
902 static int __init
chromeos_laptop_init(void)
904 const struct dmi_system_id
*dmi_id
;
907 dmi_id
= dmi_first_match(chromeos_laptop_dmi_table
);
909 pr_debug("unsupported system\n");
913 pr_debug("DMI Matched %s\n", dmi_id
->ident
);
915 cros_laptop
= chromeos_laptop_prepare((void *)dmi_id
->driver_data
);
916 if (IS_ERR(cros_laptop
))
917 return PTR_ERR(cros_laptop
);
919 if (!cros_laptop
->num_i2c_peripherals
&&
920 !cros_laptop
->num_acpi_peripherals
) {
921 pr_debug("no relevant devices detected\n");
923 goto err_destroy_cros_laptop
;
926 error
= bus_register_notifier(&i2c_bus_type
,
927 &chromeos_laptop_i2c_notifier
);
929 pr_err("failed to register i2c bus notifier: %d\n",
931 goto err_destroy_cros_laptop
;
935 * Scan adapters that have been registered and clients that have
936 * been created before we installed the notifier to make sure
937 * we do not miss any devices.
939 i2c_for_each_dev(NULL
, chromeos_laptop_scan_peripherals
);
943 err_destroy_cros_laptop
:
944 chromeos_laptop_destroy(cros_laptop
);
948 static void __exit
chromeos_laptop_exit(void)
950 bus_unregister_notifier(&i2c_bus_type
, &chromeos_laptop_i2c_notifier
);
951 chromeos_laptop_destroy(cros_laptop
);
954 module_init(chromeos_laptop_init
);
955 module_exit(chromeos_laptop_exit
);
957 MODULE_DESCRIPTION("Chrome OS Laptop driver");
958 MODULE_AUTHOR("Benson Leung <bleung@chromium.org>");
959 MODULE_LICENSE("GPL");