acpi_i2c.c revision 1.11 1 1.11 thorpej /* $NetBSD: acpi_i2c.c,v 1.11 2021/01/26 01:23:08 thorpej Exp $ */
2 1.1 bouyer
3 1.1 bouyer /*-
4 1.11 thorpej * Copyright (c) 2017, 2021 The NetBSD Foundation, Inc.
5 1.1 bouyer * All rights reserved.
6 1.1 bouyer *
7 1.1 bouyer * This code is derived from software contributed to The NetBSD Foundation
8 1.1 bouyer * by Manuel Bouyer.
9 1.1 bouyer *
10 1.1 bouyer * Redistribution and use in source and binary forms, with or without
11 1.1 bouyer * modification, are permitted provided that the following conditions
12 1.1 bouyer * are met:
13 1.1 bouyer * 1. Redistributions of source code must retain the above copyright
14 1.1 bouyer * notice, this list of conditions and the following disclaimer.
15 1.1 bouyer * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 bouyer * notice, this list of conditions and the following disclaimer in the
17 1.1 bouyer * documentation and/or other materials provided with the distribution.
18 1.1 bouyer *
19 1.1 bouyer * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 bouyer * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 bouyer * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 bouyer * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 bouyer * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 bouyer * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 bouyer * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 bouyer * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 bouyer * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 bouyer * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 bouyer * POSSIBILITY OF SUCH DAMAGE.
30 1.1 bouyer */
31 1.1 bouyer
32 1.1 bouyer #include <sys/cdefs.h>
33 1.11 thorpej __KERNEL_RCSID(0, "$NetBSD: acpi_i2c.c,v 1.11 2021/01/26 01:23:08 thorpej Exp $");
34 1.1 bouyer
35 1.1 bouyer #include <dev/acpi/acpireg.h>
36 1.1 bouyer #include <dev/acpi/acpivar.h>
37 1.1 bouyer #include <dev/acpi/acpi_i2c.h>
38 1.9 jmcneill #include <dev/i2c/i2cvar.h>
39 1.1 bouyer
40 1.11 thorpej #include <sys/kmem.h>
41 1.11 thorpej
42 1.2 bouyer #define _COMPONENT ACPI_BUS_COMPONENT
43 1.2 bouyer ACPI_MODULE_NAME ("acpi_i2c")
44 1.2 bouyer
45 1.1 bouyer struct acpi_i2c_context {
46 1.1 bouyer uint16_t i2c_addr;
47 1.1 bouyer };
48 1.1 bouyer
49 1.1 bouyer static ACPI_STATUS
50 1.1 bouyer acpi_i2c_resource_parse_callback(ACPI_RESOURCE *res, void *context)
51 1.1 bouyer {
52 1.1 bouyer struct acpi_i2c_context *i2cc = context;
53 1.1 bouyer
54 1.1 bouyer switch (res->Type) {
55 1.1 bouyer case ACPI_RESOURCE_TYPE_END_TAG:
56 1.1 bouyer break;
57 1.1 bouyer case ACPI_RESOURCE_TYPE_SERIAL_BUS:
58 1.1 bouyer switch (res->Data.I2cSerialBus.Type) {
59 1.1 bouyer case ACPI_RESOURCE_SERIAL_TYPE_I2C:
60 1.1 bouyer i2cc->i2c_addr = res->Data.I2cSerialBus.SlaveAddress;
61 1.1 bouyer break;
62 1.1 bouyer }
63 1.1 bouyer break;
64 1.1 bouyer case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
65 1.1 bouyer break;
66 1.1 bouyer default:
67 1.8 msaitoh printf("resource type 0x%x ignored\n", res->Type);
68 1.1 bouyer }
69 1.1 bouyer return_ACPI_STATUS(AE_OK);
70 1.1 bouyer }
71 1.1 bouyer
72 1.1 bouyer static void
73 1.1 bouyer acpi_enter_i2c_device(struct acpi_devnode *ad, prop_array_t array)
74 1.1 bouyer {
75 1.1 bouyer prop_dictionary_t dev;
76 1.1 bouyer struct acpi_i2c_context i2cc;
77 1.1 bouyer ACPI_STATUS rv;
78 1.1 bouyer const char *name;
79 1.11 thorpej char *clist;
80 1.11 thorpej size_t clist_size;
81 1.1 bouyer
82 1.1 bouyer memset(&i2cc, 0, sizeof(i2cc));
83 1.1 bouyer rv = AcpiWalkResources(ad->ad_handle, "_CRS",
84 1.1 bouyer acpi_i2c_resource_parse_callback, &i2cc);
85 1.1 bouyer if (ACPI_FAILURE(rv)) {
86 1.1 bouyer aprint_error("ACPI: unable to get resources "
87 1.1 bouyer "for %s: %s\n", ad->ad_name,
88 1.1 bouyer AcpiFormatException(rv));
89 1.1 bouyer return;
90 1.1 bouyer }
91 1.1 bouyer if (i2cc.i2c_addr == 0)
92 1.1 bouyer return;
93 1.1 bouyer dev = prop_dictionary_create();
94 1.1 bouyer if (dev == NULL) {
95 1.1 bouyer aprint_error("ignoring device %s (no memory)\n",
96 1.1 bouyer ad->ad_name);
97 1.1 bouyer return;
98 1.1 bouyer }
99 1.11 thorpej clist = acpi_pack_compat_list(ad->ad_devinfo, &clist_size);
100 1.11 thorpej if (clist == NULL) {
101 1.11 thorpej prop_object_release(dev);
102 1.11 thorpej aprint_error("ignoring device %s (no _HID or _CID)\n",
103 1.11 thorpej ad->ad_name);
104 1.11 thorpej return;
105 1.11 thorpej }
106 1.11 thorpej if ((ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0)
107 1.1 bouyer name = ad->ad_name;
108 1.1 bouyer else
109 1.1 bouyer name = ad->ad_devinfo->HardwareId.String;
110 1.6 thorpej prop_dictionary_set_string(dev, "name", name);
111 1.1 bouyer prop_dictionary_set_uint32(dev, "addr", i2cc.i2c_addr);
112 1.1 bouyer prop_dictionary_set_uint64(dev, "cookie", (uintptr_t)ad->ad_handle);
113 1.9 jmcneill prop_dictionary_set_uint32(dev, "cookietype", I2C_COOKIE_ACPI);
114 1.11 thorpej prop_dictionary_set_data(dev, "compatible", clist, clist_size);
115 1.11 thorpej kmem_free(clist, clist_size);
116 1.11 thorpej
117 1.1 bouyer prop_array_add(array, dev);
118 1.1 bouyer prop_object_release(dev);
119 1.1 bouyer }
120 1.1 bouyer
121 1.1 bouyer prop_array_t
122 1.10 jmcneill acpi_enter_i2c_devs(device_t dev, struct acpi_devnode *devnode)
123 1.1 bouyer {
124 1.1 bouyer struct acpi_devnode *ad;
125 1.1 bouyer prop_array_t array = prop_array_create();
126 1.1 bouyer
127 1.1 bouyer if (array == NULL)
128 1.1 bouyer return NULL;
129 1.1 bouyer
130 1.1 bouyer SIMPLEQ_FOREACH(ad, &devnode->ad_child_head, ad_child_list) {
131 1.1 bouyer if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE)
132 1.1 bouyer continue;
133 1.4 christos if (!acpi_device_present(ad->ad_handle))
134 1.4 christos continue;
135 1.1 bouyer acpi_enter_i2c_device(ad, array);
136 1.1 bouyer }
137 1.10 jmcneill
138 1.10 jmcneill if (dev != NULL) {
139 1.10 jmcneill acpi_claim_childdevs(dev, devnode);
140 1.10 jmcneill }
141 1.10 jmcneill
142 1.1 bouyer return array;
143 1.1 bouyer }
144