Add a device_t parameter to acpi_enter_i2c_devs. If non-NULL, all child acpi_devnodes will be claimed by that device so we don't later try to attach a duplicate device to that node at acpinodebus.diff -r1.1 -r1.2 src/sys/arch/arm/broadcom/bcm2835_bsc_acpi.c
(jmcneill)
--- src/sys/arch/arm/broadcom/bcm2835_bsc_acpi.c 2020/03/31 12:23:17 1.1
+++ src/sys/arch/arm/broadcom/bcm2835_bsc_acpi.c 2021/01/26 00:19:52 1.2
@@ -1,189 +1,189 @@ | @@ -1,189 +1,189 @@ | |||
1 | /* $NetBSD: bcm2835_bsc_acpi.c,v 1.1 2020/03/31 12:23:17 jmcneill Exp $ */ | 1 | /* $NetBSD: bcm2835_bsc_acpi.c,v 1.2 2021/01/26 00:19:52 jmcneill Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2020 Jared McNeill <jmcneill@invisible.ca> | 4 | * Copyright (c) 2020 Jared McNeill <jmcneill@invisible.ca> | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
15 | * | 15 | * | |
16 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 16 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
17 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 17 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
26 | * POSSIBILITY OF SUCH DAMAGE. | 26 | * POSSIBILITY OF SUCH DAMAGE. | |
27 | */ | 27 | */ | |
28 | 28 | |||
29 | #include <sys/cdefs.h> | 29 | #include <sys/cdefs.h> | |
30 | __KERNEL_RCSID(0, "$NetBSD: bcm2835_bsc_acpi.c,v 1.1 2020/03/31 12:23:17 jmcneill Exp $"); | 30 | __KERNEL_RCSID(0, "$NetBSD: bcm2835_bsc_acpi.c,v 1.2 2021/01/26 00:19:52 jmcneill Exp $"); | |
31 | 31 | |||
32 | #include <sys/param.h> | 32 | #include <sys/param.h> | |
33 | #include <sys/bus.h> | 33 | #include <sys/bus.h> | |
34 | #include <sys/cpu.h> | 34 | #include <sys/cpu.h> | |
35 | #include <sys/device.h> | 35 | #include <sys/device.h> | |
36 | 36 | |||
37 | #include <dev/acpi/acpireg.h> | 37 | #include <dev/acpi/acpireg.h> | |
38 | #include <dev/acpi/acpivar.h> | 38 | #include <dev/acpi/acpivar.h> | |
39 | #include <dev/acpi/acpi_intr.h> | 39 | #include <dev/acpi/acpi_intr.h> | |
40 | #include <dev/acpi/acpi_i2c.h> | 40 | #include <dev/acpi/acpi_i2c.h> | |
41 | 41 | |||
42 | #include <arm/broadcom/bcm2835var.h> | 42 | #include <arm/broadcom/bcm2835var.h> | |
43 | #include <arm/broadcom/bcm2835_mbox.h> | 43 | #include <arm/broadcom/bcm2835_mbox.h> | |
44 | #include <arm/broadcom/bcm2835_bscvar.h> | 44 | #include <arm/broadcom/bcm2835_bscvar.h> | |
45 | 45 | |||
46 | #include <evbarm/rpi/vcio.h> | 46 | #include <evbarm/rpi/vcio.h> | |
47 | #include <evbarm/rpi/vcpm.h> | 47 | #include <evbarm/rpi/vcpm.h> | |
48 | #include <evbarm/rpi/vcprop.h> | 48 | #include <evbarm/rpi/vcprop.h> | |
49 | 49 | |||
50 | static int bsciic_acpi_match(device_t, cfdata_t, void *); | 50 | static int bsciic_acpi_match(device_t, cfdata_t, void *); | |
51 | static void bsciic_acpi_attach(device_t, device_t, void *); | 51 | static void bsciic_acpi_attach(device_t, device_t, void *); | |
52 | 52 | |||
53 | static u_int bsciic_acpi_vpu_clock_rate(void); | 53 | static u_int bsciic_acpi_vpu_clock_rate(void); | |
54 | 54 | |||
55 | CFATTACH_DECL_NEW(bsciic_acpi, sizeof(struct bsciic_softc), bsciic_acpi_match, bsciic_acpi_attach, NULL, NULL); | 55 | CFATTACH_DECL_NEW(bsciic_acpi, sizeof(struct bsciic_softc), bsciic_acpi_match, bsciic_acpi_attach, NULL, NULL); | |
56 | 56 | |||
57 | static const char * const compatible[] = { | 57 | static const char * const compatible[] = { | |
58 | "BCM2841", | 58 | "BCM2841", | |
59 | NULL | 59 | NULL | |
60 | }; | 60 | }; | |
61 | 61 | |||
62 | static struct { | 62 | static struct { | |
63 | struct vcprop_buffer_hdr vb_hdr; | 63 | struct vcprop_buffer_hdr vb_hdr; | |
64 | struct vcprop_tag_clockrate vbt_vpuclockrate; | 64 | struct vcprop_tag_clockrate vbt_vpuclockrate; | |
65 | struct vcprop_tag end; | 65 | struct vcprop_tag end; | |
66 | } vb_vpu __cacheline_aligned = { | 66 | } vb_vpu __cacheline_aligned = { | |
67 | .vb_hdr = { | 67 | .vb_hdr = { | |
68 | .vpb_len = sizeof(vb_vpu), | 68 | .vpb_len = sizeof(vb_vpu), | |
69 | .vpb_rcode = VCPROP_PROCESS_REQUEST | 69 | .vpb_rcode = VCPROP_PROCESS_REQUEST | |
70 | }, | 70 | }, | |
71 | .vbt_vpuclockrate = { | 71 | .vbt_vpuclockrate = { | |
72 | .tag = { | 72 | .tag = { | |
73 | .vpt_tag = VCPROPTAG_GET_CLOCKRATE, | 73 | .vpt_tag = VCPROPTAG_GET_CLOCKRATE, | |
74 | .vpt_len = VCPROPTAG_LEN(vb_vpu.vbt_vpuclockrate), | 74 | .vpt_len = VCPROPTAG_LEN(vb_vpu.vbt_vpuclockrate), | |
75 | .vpt_rcode = VCPROPTAG_REQUEST | 75 | .vpt_rcode = VCPROPTAG_REQUEST | |
76 | }, | 76 | }, | |
77 | .id = VCPROP_CLK_CORE | 77 | .id = VCPROP_CLK_CORE | |
78 | }, | 78 | }, | |
79 | .end = { | 79 | .end = { | |
80 | .vpt_tag = VCPROPTAG_NULL | 80 | .vpt_tag = VCPROPTAG_NULL | |
81 | } | 81 | } | |
82 | }; | 82 | }; | |
83 | 83 | |||
84 | static int | 84 | static int | |
85 | bsciic_acpi_match(device_t parent, cfdata_t cf, void *aux) | 85 | bsciic_acpi_match(device_t parent, cfdata_t cf, void *aux) | |
86 | { | 86 | { | |
87 | struct acpi_attach_args *aa = aux; | 87 | struct acpi_attach_args *aa = aux; | |
88 | 88 | |||
89 | if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) | 89 | if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) | |
90 | return 0; | 90 | return 0; | |
91 | 91 | |||
92 | return acpi_match_hid(aa->aa_node->ad_devinfo, compatible); | 92 | return acpi_match_hid(aa->aa_node->ad_devinfo, compatible); | |
93 | } | 93 | } | |
94 | 94 | |||
95 | static void | 95 | static void | |
96 | bsciic_acpi_attach(device_t parent, device_t self, void *aux) | 96 | bsciic_acpi_attach(device_t parent, device_t self, void *aux) | |
97 | { | 97 | { | |
98 | struct bsciic_softc * const sc = device_private(self); | 98 | struct bsciic_softc * const sc = device_private(self); | |
99 | struct acpi_attach_args *aa = aux; | 99 | struct acpi_attach_args *aa = aux; | |
100 | struct i2cbus_attach_args iba; | 100 | struct i2cbus_attach_args iba; | |
101 | struct acpi_resources res; | 101 | struct acpi_resources res; | |
102 | struct acpi_mem *mem; | 102 | struct acpi_mem *mem; | |
103 | struct acpi_irq *irq; | 103 | struct acpi_irq *irq; | |
104 | ACPI_STATUS rv; | 104 | ACPI_STATUS rv; | |
105 | ACPI_INTEGER clock_freq; | 105 | ACPI_INTEGER clock_freq; | |
106 | void *ih; | 106 | void *ih; | |
107 | 107 | |||
108 | sc->sc_dev = self; | 108 | sc->sc_dev = self; | |
109 | 109 | |||
110 | rv = acpi_resource_parse(sc->sc_dev, aa->aa_node->ad_handle, "_CRS", | 110 | rv = acpi_resource_parse(sc->sc_dev, aa->aa_node->ad_handle, "_CRS", | |
111 | &res, &acpi_resource_parse_ops_default); | 111 | &res, &acpi_resource_parse_ops_default); | |
112 | if (ACPI_FAILURE(rv)) | 112 | if (ACPI_FAILURE(rv)) | |
113 | return; | 113 | return; | |
114 | 114 | |||
115 | mem = acpi_res_mem(&res, 0); | 115 | mem = acpi_res_mem(&res, 0); | |
116 | if (mem == NULL) { | 116 | if (mem == NULL) { | |
117 | aprint_error_dev(self, "couldn't find mem resource\n"); | 117 | aprint_error_dev(self, "couldn't find mem resource\n"); | |
118 | goto done; | 118 | goto done; | |
119 | } | 119 | } | |
120 | 120 | |||
121 | irq = acpi_res_irq(&res, 0); | 121 | irq = acpi_res_irq(&res, 0); | |
122 | if (irq == NULL) { | 122 | if (irq == NULL) { | |
123 | aprint_error_dev(self, "couldn't find irq resource\n"); | 123 | aprint_error_dev(self, "couldn't find irq resource\n"); | |
124 | goto done; | 124 | goto done; | |
125 | } | 125 | } | |
126 | 126 | |||
127 | sc->sc_dev = self; | 127 | sc->sc_dev = self; | |
128 | sc->sc_iot = aa->aa_memt; | 128 | sc->sc_iot = aa->aa_memt; | |
129 | if (bus_space_map(aa->aa_memt, mem->ar_base, mem->ar_length, 0, &sc->sc_ioh) != 0) { | 129 | if (bus_space_map(aa->aa_memt, mem->ar_base, mem->ar_length, 0, &sc->sc_ioh) != 0) { | |
130 | aprint_error_dev(self, "couldn't map registers\n"); | 130 | aprint_error_dev(self, "couldn't map registers\n"); | |
131 | goto done; | 131 | goto done; | |
132 | } | 132 | } | |
133 | 133 | |||
134 | sc->sc_frequency = bsciic_acpi_vpu_clock_rate(); | 134 | sc->sc_frequency = bsciic_acpi_vpu_clock_rate(); | |
135 | if (sc->sc_frequency == 0) { | 135 | if (sc->sc_frequency == 0) { | |
136 | aprint_error_dev(self, "couldn't determine parent clock rate\n"); | 136 | aprint_error_dev(self, "couldn't determine parent clock rate\n"); | |
137 | goto done; | 137 | goto done; | |
138 | } | 138 | } | |
139 | 139 | |||
140 | rv = acpi_dsd_integer(aa->aa_node->ad_handle, "clock-frequency", &clock_freq); | 140 | rv = acpi_dsd_integer(aa->aa_node->ad_handle, "clock-frequency", &clock_freq); | |
141 | if (ACPI_SUCCESS(rv)) | 141 | if (ACPI_SUCCESS(rv)) | |
142 | sc->sc_clkrate = clock_freq; | 142 | sc->sc_clkrate = clock_freq; | |
143 | else | 143 | else | |
144 | sc->sc_clkrate = 100000; | 144 | sc->sc_clkrate = 100000; | |
145 | 145 | |||
146 | bsciic_attach(sc); | 146 | bsciic_attach(sc); | |
147 | 147 | |||
148 | ih = acpi_intr_establish(self, (uint64_t)aa->aa_node->ad_handle, | 148 | ih = acpi_intr_establish(self, (uint64_t)aa->aa_node->ad_handle, | |
149 | IPL_VM, true, bsciic_intr, sc, device_xname(self)); | 149 | IPL_VM, true, bsciic_intr, sc, device_xname(self)); | |
150 | if (ih == NULL) { | 150 | if (ih == NULL) { | |
151 | aprint_error_dev(self, "couldn't install interrupt handler\n"); | 151 | aprint_error_dev(self, "couldn't install interrupt handler\n"); | |
152 | goto done; | 152 | goto done; | |
153 | } | 153 | } | |
154 | 154 | |||
155 | iic_tag_init(&sc->sc_i2c); | 155 | iic_tag_init(&sc->sc_i2c); | |
156 | sc->sc_i2c.ic_cookie = sc; | 156 | sc->sc_i2c.ic_cookie = sc; | |
157 | sc->sc_i2c.ic_acquire_bus = bsciic_acquire_bus; | 157 | sc->sc_i2c.ic_acquire_bus = bsciic_acquire_bus; | |
158 | sc->sc_i2c.ic_release_bus = bsciic_release_bus; | 158 | sc->sc_i2c.ic_release_bus = bsciic_release_bus; | |
159 | sc->sc_i2c.ic_exec = bsciic_exec; | 159 | sc->sc_i2c.ic_exec = bsciic_exec; | |
160 | 160 | |||
161 | memset(&iba, 0, sizeof(iba)); | 161 | memset(&iba, 0, sizeof(iba)); | |
162 | iba.iba_tag = &sc->sc_i2c; | 162 | iba.iba_tag = &sc->sc_i2c; | |
163 | iba.iba_child_devices = acpi_enter_i2c_devs(aa->aa_node); | 163 | iba.iba_child_devices = acpi_enter_i2c_devs(self, aa->aa_node); | |
164 | config_found_ia(self, "i2cbus", &iba, iicbus_print); | 164 | config_found_ia(self, "i2cbus", &iba, iicbus_print); | |
165 | 165 | |||
166 | done: | 166 | done: | |
167 | acpi_resource_cleanup(&res); | 167 | acpi_resource_cleanup(&res); | |
168 | } | 168 | } | |
169 | 169 | |||
170 | static u_int | 170 | static u_int | |
171 | bsciic_acpi_vpu_clock_rate(void) | 171 | bsciic_acpi_vpu_clock_rate(void) | |
172 | { | 172 | { | |
173 | uint32_t res; | 173 | uint32_t res; | |
174 | int error; | 174 | int error; | |
175 | 175 | |||
176 | error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_vpu, | 176 | error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_vpu, | |
177 | sizeof(vb_vpu), &res); | 177 | sizeof(vb_vpu), &res); | |
178 | if (error != 0) { | 178 | if (error != 0) { | |
179 | printf("%s: mbox request failed (%d)\n", __func__, error); | 179 | printf("%s: mbox request failed (%d)\n", __func__, error); | |
180 | return 0; | 180 | return 0; | |
181 | } | 181 | } | |
182 | 182 | |||
183 | if (!vcprop_buffer_success_p(&vb_vpu.vb_hdr) || | 183 | if (!vcprop_buffer_success_p(&vb_vpu.vb_hdr) || | |
184 | !vcprop_tag_success_p(&vb_vpu.vbt_vpuclockrate.tag) || | 184 | !vcprop_tag_success_p(&vb_vpu.vbt_vpuclockrate.tag) || | |
185 | vb_vpu.vbt_vpuclockrate.rate < 0) | 185 | vb_vpu.vbt_vpuclockrate.rate < 0) | |
186 | return 0; | 186 | return 0; | |
187 | 187 | |||
188 | return vb_vpu.vbt_vpuclockrate.rate; | 188 | return vb_vpu.vbt_vpuclockrate.rate; | |
189 | } | 189 | } |
--- src/sys/arch/x86/pci/dwiic_pci.c 2018/09/26 19:06:33 1.2
+++ src/sys/arch/x86/pci/dwiic_pci.c 2021/01/26 00:19:52 1.3
@@ -1,215 +1,215 @@ | @@ -1,215 +1,215 @@ | |||
1 | /* $NetBSD: dwiic_pci.c,v 1.2 2018/09/26 19:06:33 jakllsch Exp $ */ | 1 | /* $NetBSD: dwiic_pci.c,v 1.3 2021/01/26 00:19:52 jmcneill Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2017 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2017 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Manuel Bouyer. | 8 | * by Manuel Bouyer. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | /* | 31 | /* | |
32 | * Synopsys DesignWare I2C controller, PCI front-end | 32 | * Synopsys DesignWare I2C controller, PCI front-end | |
33 | */ | 33 | */ | |
34 | 34 | |||
35 | #include <sys/cdefs.h> | 35 | #include <sys/cdefs.h> | |
36 | __KERNEL_RCSID(0, "$NetBSD: dwiic_pci.c,v 1.2 2018/09/26 19:06:33 jakllsch Exp $"); | 36 | __KERNEL_RCSID(0, "$NetBSD: dwiic_pci.c,v 1.3 2021/01/26 00:19:52 jmcneill Exp $"); | |
37 | 37 | |||
38 | #include <sys/param.h> | 38 | #include <sys/param.h> | |
39 | #include <sys/systm.h> | 39 | #include <sys/systm.h> | |
40 | 40 | |||
41 | #include <dev/pci/pcireg.h> | 41 | #include <dev/pci/pcireg.h> | |
42 | #include <dev/pci/pcivar.h> | 42 | #include <dev/pci/pcivar.h> | |
43 | #include <dev/pci/pcidevs.h> | 43 | #include <dev/pci/pcidevs.h> | |
44 | 44 | |||
45 | #include <dev/acpi/acpivar.h> | 45 | #include <dev/acpi/acpivar.h> | |
46 | #include <dev/acpi/acpi_pci.h> | 46 | #include <dev/acpi/acpi_pci.h> | |
47 | #include <dev/acpi/acpi_util.h> | 47 | #include <dev/acpi/acpi_util.h> | |
48 | #include <dev/acpi/acpi_i2c.h> | 48 | #include <dev/acpi/acpi_i2c.h> | |
49 | 49 | |||
50 | #include <dev/ic/dwiic_var.h> | 50 | #include <dev/ic/dwiic_var.h> | |
51 | #include <arch/x86/pci/lpssreg.h> | 51 | #include <arch/x86/pci/lpssreg.h> | |
52 | 52 | |||
53 | //#define DWIIC_DEBUG | 53 | //#define DWIIC_DEBUG | |
54 | 54 | |||
55 | #ifdef DWIIC_DEBUG | 55 | #ifdef DWIIC_DEBUG | |
56 | #define DPRINTF(x) printf x | 56 | #define DPRINTF(x) printf x | |
57 | #else | 57 | #else | |
58 | #define DPRINTF(x) | 58 | #define DPRINTF(x) | |
59 | #endif | 59 | #endif | |
60 | 60 | |||
61 | struct pci_dwiic_softc { | 61 | struct pci_dwiic_softc { | |
62 | struct dwiic_softc sc_dwiic; | 62 | struct dwiic_softc sc_dwiic; | |
63 | pci_chipset_tag_t sc_pc; | 63 | pci_chipset_tag_t sc_pc; | |
64 | pcitag_t sc_ptag; | 64 | pcitag_t sc_ptag; | |
65 | struct acpi_devnode *sc_acpinode; | 65 | struct acpi_devnode *sc_acpinode; | |
66 | }; | 66 | }; | |
67 | 67 | |||
68 | static uint32_t | 68 | static uint32_t | |
69 | lpss_read(struct pci_dwiic_softc *sc, int offset) | 69 | lpss_read(struct pci_dwiic_softc *sc, int offset) | |
70 | { | 70 | { | |
71 | u_int32_t b = bus_space_read_4(sc->sc_dwiic.sc_iot, sc->sc_dwiic.sc_ioh, | 71 | u_int32_t b = bus_space_read_4(sc->sc_dwiic.sc_iot, sc->sc_dwiic.sc_ioh, | |
72 | offset); | 72 | offset); | |
73 | return b; | 73 | return b; | |
74 | } | 74 | } | |
75 | 75 | |||
76 | static void | 76 | static void | |
77 | lpss_write(struct pci_dwiic_softc *sc, int offset, uint32_t val) | 77 | lpss_write(struct pci_dwiic_softc *sc, int offset, uint32_t val) | |
78 | { | 78 | { | |
79 | bus_space_write_4(sc->sc_dwiic.sc_iot, sc->sc_dwiic.sc_ioh, | 79 | bus_space_write_4(sc->sc_dwiic.sc_iot, sc->sc_dwiic.sc_ioh, | |
80 | offset, val); | 80 | offset, val); | |
81 | } | 81 | } | |
82 | 82 | |||
83 | static int pci_dwiic_match(device_t, cfdata_t, void *); | 83 | static int pci_dwiic_match(device_t, cfdata_t, void *); | |
84 | static void pci_dwiic_attach(device_t, device_t, void *); | 84 | static void pci_dwiic_attach(device_t, device_t, void *); | |
85 | static bool dwiic_pci_power(struct dwiic_softc *, bool); | 85 | static bool dwiic_pci_power(struct dwiic_softc *, bool); | |
86 | 86 | |||
87 | CFATTACH_DECL_NEW(pcidwiic, sizeof(struct pci_dwiic_softc), | 87 | CFATTACH_DECL_NEW(pcidwiic, sizeof(struct pci_dwiic_softc), | |
88 | pci_dwiic_match, pci_dwiic_attach, dwiic_detach, NULL); | 88 | pci_dwiic_match, pci_dwiic_attach, dwiic_detach, NULL); | |
89 | 89 | |||
90 | 90 | |||
91 | int | 91 | int | |
92 | pci_dwiic_match(device_t parent, cfdata_t match, void *aux) | 92 | pci_dwiic_match(device_t parent, cfdata_t match, void *aux) | |
93 | { | 93 | { | |
94 | struct pci_attach_args *pa = aux; | 94 | struct pci_attach_args *pa = aux; | |
95 | 95 | |||
96 | if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL) | 96 | if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL) | |
97 | return 0; | 97 | return 0; | |
98 | 98 | |||
99 | if (PCI_PRODUCT(pa->pa_id) < PCI_PRODUCT_INTEL_100SERIES_LP_I2C_0 || | 99 | if (PCI_PRODUCT(pa->pa_id) < PCI_PRODUCT_INTEL_100SERIES_LP_I2C_0 || | |
100 | PCI_PRODUCT(pa->pa_id) > PCI_PRODUCT_INTEL_100SERIES_LP_I2C_3) | 100 | PCI_PRODUCT(pa->pa_id) > PCI_PRODUCT_INTEL_100SERIES_LP_I2C_3) | |
101 | return 0; | 101 | return 0; | |
102 | 102 | |||
103 | return 1; | 103 | return 1; | |
104 | } | 104 | } | |
105 | 105 | |||
106 | void | 106 | void | |
107 | pci_dwiic_attach(device_t parent, device_t self, void *aux) | 107 | pci_dwiic_attach(device_t parent, device_t self, void *aux) | |
108 | { | 108 | { | |
109 | struct pci_dwiic_softc *sc = device_private(self); | 109 | struct pci_dwiic_softc *sc = device_private(self); | |
110 | struct pci_attach_args *pa = aux; | 110 | struct pci_attach_args *pa = aux; | |
111 | const char *intrstr; | 111 | const char *intrstr; | |
112 | pci_intr_handle_t intrhandle; | 112 | pci_intr_handle_t intrhandle; | |
113 | char intrbuf[PCI_INTRSTR_LEN]; | 113 | char intrbuf[PCI_INTRSTR_LEN]; | |
114 | pcireg_t memtype; | 114 | pcireg_t memtype; | |
115 | pcireg_t csr; | 115 | pcireg_t csr; | |
116 | uint32_t caps; | 116 | uint32_t caps; | |
117 | 117 | |||
118 | sc->sc_dwiic.sc_dev = self; | 118 | sc->sc_dwiic.sc_dev = self; | |
119 | sc->sc_dwiic.sc_power = dwiic_pci_power; | 119 | sc->sc_dwiic.sc_power = dwiic_pci_power; | |
120 | sc->sc_dwiic.sc_type = dwiic_type_sunrisepoint; | 120 | sc->sc_dwiic.sc_type = dwiic_type_sunrisepoint; | |
121 | 121 | |||
122 | sc->sc_pc = pa->pa_pc; | 122 | sc->sc_pc = pa->pa_pc; | |
123 | sc->sc_ptag = pa->pa_tag; | 123 | sc->sc_ptag = pa->pa_tag; | |
124 | 124 | |||
125 | /* register access not enabled by BIOS */ | 125 | /* register access not enabled by BIOS */ | |
126 | csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); | 126 | csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); | |
127 | pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, | 127 | pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, | |
128 | csr | PCI_COMMAND_MEM_ENABLE); | 128 | csr | PCI_COMMAND_MEM_ENABLE); | |
129 | 129 | |||
130 | memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_BAR0); | 130 | memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_BAR0); | |
131 | if (pci_mapreg_map(pa, PCI_BAR0, memtype, 0, &sc->sc_dwiic.sc_iot, | 131 | if (pci_mapreg_map(pa, PCI_BAR0, memtype, 0, &sc->sc_dwiic.sc_iot, | |
132 | &sc->sc_dwiic.sc_ioh, NULL, NULL) != 0) { | 132 | &sc->sc_dwiic.sc_ioh, NULL, NULL) != 0) { | |
133 | aprint_error(": can't map register space\n"); | 133 | aprint_error(": can't map register space\n"); | |
134 | goto out; | 134 | goto out; | |
135 | } | 135 | } | |
136 | dwiic_pci_power(&sc->sc_dwiic, 1); | 136 | dwiic_pci_power(&sc->sc_dwiic, 1); | |
137 | 137 | |||
138 | caps = lpss_read(sc, LPSS_CAP); | 138 | caps = lpss_read(sc, LPSS_CAP); | |
139 | 139 | |||
140 | aprint_naive(": I2C controller\n"); | 140 | aprint_naive(": I2C controller\n"); | |
141 | aprint_normal(": I2C controller instance %d\n", | 141 | aprint_normal(": I2C controller instance %d\n", | |
142 | (int)(caps & LPSS_CAP_INSTANCE)); | 142 | (int)(caps & LPSS_CAP_INSTANCE)); | |
143 | 143 | |||
144 | if (pci_intr_map(pa, &intrhandle)) { | 144 | if (pci_intr_map(pa, &intrhandle)) { | |
145 | aprint_error_dev(self, "can't map interrupt\n"); | 145 | aprint_error_dev(self, "can't map interrupt\n"); | |
146 | goto out; | 146 | goto out; | |
147 | } | 147 | } | |
148 | intrstr = pci_intr_string(pa->pa_pc, intrhandle, | 148 | intrstr = pci_intr_string(pa->pa_pc, intrhandle, | |
149 | intrbuf, sizeof(intrbuf)); | 149 | intrbuf, sizeof(intrbuf)); | |
150 | 150 | |||
151 | sc->sc_dwiic.sc_ih = pci_intr_establish(pa->pa_pc, intrhandle, | 151 | sc->sc_dwiic.sc_ih = pci_intr_establish(pa->pa_pc, intrhandle, | |
152 | IPL_VM, dwiic_intr, sc); | 152 | IPL_VM, dwiic_intr, sc); | |
153 | if (sc->sc_dwiic.sc_ih == NULL) { | 153 | if (sc->sc_dwiic.sc_ih == NULL) { | |
154 | aprint_error_dev(self, "couldn't establish interrupt"); | 154 | aprint_error_dev(self, "couldn't establish interrupt"); | |
155 | if (intrstr != NULL) | 155 | if (intrstr != NULL) | |
156 | aprint_error(" at %s", intrstr); | 156 | aprint_error(" at %s", intrstr); | |
157 | aprint_error("\n"); | 157 | aprint_error("\n"); | |
158 | goto out; | 158 | goto out; | |
159 | } | 159 | } | |
160 | aprint_normal_dev(self, "interrupting at %s\n", intrstr); | 160 | aprint_normal_dev(self, "interrupting at %s\n", intrstr); | |
161 | 161 | |||
162 | lpss_write(sc, LPSS_RESET, LPSS_RESET_CTRL_REL); | 162 | lpss_write(sc, LPSS_RESET, LPSS_RESET_CTRL_REL); | |
163 | lpss_write(sc, LPSS_REMAP_LO, | 163 | lpss_write(sc, LPSS_REMAP_LO, | |
164 | pci_conf_read(sc->sc_pc, sc->sc_ptag, PCI_BAR0)); | 164 | pci_conf_read(sc->sc_pc, sc->sc_ptag, PCI_BAR0)); | |
165 | lpss_write(sc, LPSS_REMAP_HI, | 165 | lpss_write(sc, LPSS_REMAP_HI, | |
166 | pci_conf_read(sc->sc_pc, sc->sc_ptag, PCI_BAR0 + 0x4)); | 166 | pci_conf_read(sc->sc_pc, sc->sc_ptag, PCI_BAR0 + 0x4)); | |
167 | 167 | |||
168 | sc->sc_acpinode = acpi_pcidev_find(0 /*XXX segment*/, | 168 | sc->sc_acpinode = acpi_pcidev_find(0 /*XXX segment*/, | |
169 | pa->pa_bus, pa->pa_device, pa->pa_function); | 169 | pa->pa_bus, pa->pa_device, pa->pa_function); | |
170 | 170 | |||
171 | if (sc->sc_acpinode) { | 171 | if (sc->sc_acpinode) { | |
172 | sc->sc_dwiic.sc_iba.iba_child_devices = | 172 | sc->sc_dwiic.sc_iba.iba_child_devices = | |
173 | acpi_enter_i2c_devs(sc->sc_acpinode); | 173 | acpi_enter_i2c_devs(NULL, sc->sc_acpinode); | |
174 | } else { | 174 | } else { | |
175 | aprint_verbose_dev(self, "no matching ACPI node\n"); | 175 | aprint_verbose_dev(self, "no matching ACPI node\n"); | |
176 | } | 176 | } | |
177 | 177 | |||
178 | dwiic_attach(&sc->sc_dwiic); | 178 | dwiic_attach(&sc->sc_dwiic); | |
179 | 179 | |||
180 | config_found_ia(self, "i2cbus", &sc->sc_dwiic.sc_iba, iicbus_print); | 180 | config_found_ia(self, "i2cbus", &sc->sc_dwiic.sc_iba, iicbus_print); | |
181 | 181 | |||
182 | pmf_device_register(self, dwiic_suspend, dwiic_resume); | 182 | pmf_device_register(self, dwiic_suspend, dwiic_resume); | |
183 | 183 | |||
184 | out: | 184 | out: | |
185 | return; | 185 | return; | |
186 | } | 186 | } | |
187 | 187 | |||
188 | static bool | 188 | static bool | |
189 | dwiic_pci_power(struct dwiic_softc *dwsc, bool power) | 189 | dwiic_pci_power(struct dwiic_softc *dwsc, bool power) | |
190 | { | 190 | { | |
191 | struct pci_dwiic_softc *sc = (void *)dwsc; | 191 | struct pci_dwiic_softc *sc = (void *)dwsc; | |
192 | pcireg_t pmreg; | 192 | pcireg_t pmreg; | |
193 | 193 | |||
194 | printf("status 0x%x\n", pci_conf_read(sc->sc_pc, sc->sc_ptag, PCI_COMMAND_STATUS_REG)); | 194 | printf("status 0x%x\n", pci_conf_read(sc->sc_pc, sc->sc_ptag, PCI_COMMAND_STATUS_REG)); | |
195 | printf("reset 0x%x\n", lpss_read(sc, LPSS_RESET)); | 195 | printf("reset 0x%x\n", lpss_read(sc, LPSS_RESET)); | |
196 | printf("rlo 0x%x\n", lpss_read(sc, LPSS_REMAP_LO)); | 196 | printf("rlo 0x%x\n", lpss_read(sc, LPSS_REMAP_LO)); | |
197 | printf("rho 0x%x\n", lpss_read(sc, LPSS_REMAP_HI)); | 197 | printf("rho 0x%x\n", lpss_read(sc, LPSS_REMAP_HI)); | |
198 | 198 | |||
199 | if (!power) | 199 | if (!power) | |
200 | lpss_write(sc, LPSS_CLKGATE, LPSS_CLKGATE_CTRL_OFF); | 200 | lpss_write(sc, LPSS_CLKGATE, LPSS_CLKGATE_CTRL_OFF); | |
201 | if (pci_get_capability(sc->sc_pc, sc->sc_ptag, PCI_CAP_PWRMGMT, | 201 | if (pci_get_capability(sc->sc_pc, sc->sc_ptag, PCI_CAP_PWRMGMT, | |
202 | &pmreg, NULL)) { | 202 | &pmreg, NULL)) { | |
203 | DPRINTF(("%s: power status 0x%x", device_xname(dwsc->sc_dev), | 203 | DPRINTF(("%s: power status 0x%x", device_xname(dwsc->sc_dev), | |
204 | pci_conf_read(sc->sc_pc, sc->sc_ptag, pmreg + PCI_PMCSR))); | 204 | pci_conf_read(sc->sc_pc, sc->sc_ptag, pmreg + PCI_PMCSR))); | |
205 | pci_conf_write(sc->sc_pc, sc->sc_ptag, pmreg + PCI_PMCSR, | 205 | pci_conf_write(sc->sc_pc, sc->sc_ptag, pmreg + PCI_PMCSR, | |
206 | power ? PCI_PMCSR_STATE_D0 : PCI_PMCSR_STATE_D3); | 206 | power ? PCI_PMCSR_STATE_D0 : PCI_PMCSR_STATE_D3); | |
207 | DELAY(10000); /* 10 milliseconds */ | 207 | DELAY(10000); /* 10 milliseconds */ | |
208 | DPRINTF((" -> 0x%x\n", | 208 | DPRINTF((" -> 0x%x\n", | |
209 | pci_conf_read(sc->sc_pc, sc->sc_ptag, pmreg + PCI_PMCSR))); | 209 | pci_conf_read(sc->sc_pc, sc->sc_ptag, pmreg + PCI_PMCSR))); | |
210 | } | 210 | } | |
211 | if (power) { | 211 | if (power) { | |
212 | lpss_write(sc, LPSS_CLKGATE, LPSS_CLKGATE_CTRL_ON); | 212 | lpss_write(sc, LPSS_CLKGATE, LPSS_CLKGATE_CTRL_ON); | |
213 | } | 213 | } | |
214 | return true; | 214 | return true; | |
215 | } | 215 | } |
--- src/sys/dev/acpi/acpi_i2c.c 2021/01/25 12:15:32 1.9
+++ src/sys/dev/acpi/acpi_i2c.c 2021/01/26 00:19:53 1.10
@@ -1,244 +1,249 @@ | @@ -1,244 +1,249 @@ | |||
1 | /* $NetBSD: acpi_i2c.c,v 1.9 2021/01/25 12:15:32 jmcneill Exp $ */ | 1 | /* $NetBSD: acpi_i2c.c,v 1.10 2021/01/26 00:19:53 jmcneill Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2017 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2017 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Manuel Bouyer. | 8 | * by Manuel Bouyer. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | __KERNEL_RCSID(0, "$NetBSD: acpi_i2c.c,v 1.9 2021/01/25 12:15:32 jmcneill Exp $"); | 33 | __KERNEL_RCSID(0, "$NetBSD: acpi_i2c.c,v 1.10 2021/01/26 00:19:53 jmcneill Exp $"); | |
34 | 34 | |||
35 | #include <dev/acpi/acpireg.h> | 35 | #include <dev/acpi/acpireg.h> | |
36 | #include <dev/acpi/acpivar.h> | 36 | #include <dev/acpi/acpivar.h> | |
37 | #include <dev/acpi/acpi_i2c.h> | 37 | #include <dev/acpi/acpi_i2c.h> | |
38 | #include <dev/i2c/i2cvar.h> | 38 | #include <dev/i2c/i2cvar.h> | |
39 | 39 | |||
40 | #define _COMPONENT ACPI_BUS_COMPONENT | 40 | #define _COMPONENT ACPI_BUS_COMPONENT | |
41 | ACPI_MODULE_NAME ("acpi_i2c") | 41 | ACPI_MODULE_NAME ("acpi_i2c") | |
42 | 42 | |||
43 | static void | 43 | static void | |
44 | acpi_enter_i2c_hid(struct acpi_devnode *devnode, prop_dictionary_t dev) | 44 | acpi_enter_i2c_hid(struct acpi_devnode *devnode, prop_dictionary_t dev) | |
45 | { | 45 | { | |
46 | ACPI_OBJECT_LIST arg; | 46 | ACPI_OBJECT_LIST arg; | |
47 | ACPI_OBJECT obj[4]; | 47 | ACPI_OBJECT obj[4]; | |
48 | ACPI_OBJECT *osc; | 48 | ACPI_OBJECT *osc; | |
49 | ACPI_BUFFER buf; | 49 | ACPI_BUFFER buf; | |
50 | ACPI_STATUS rv; | 50 | ACPI_STATUS rv; | |
51 | /* 3cdff6f7-4267-4555-ad05-b30a3d8938de */ | 51 | /* 3cdff6f7-4267-4555-ad05-b30a3d8938de */ | |
52 | static uint8_t i2c_hid_guid[] = { | 52 | static uint8_t i2c_hid_guid[] = { | |
53 | 0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45, | 53 | 0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45, | |
54 | 0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE, | 54 | 0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE, | |
55 | }; | 55 | }; | |
56 | 56 | |||
57 | arg.Count = 4; | 57 | arg.Count = 4; | |
58 | arg.Pointer = obj; | 58 | arg.Pointer = obj; | |
59 | 59 | |||
60 | obj[0].Type = ACPI_TYPE_BUFFER; | 60 | obj[0].Type = ACPI_TYPE_BUFFER; | |
61 | obj[0].Buffer.Length = sizeof(i2c_hid_guid); | 61 | obj[0].Buffer.Length = sizeof(i2c_hid_guid); | |
62 | obj[0].Buffer.Pointer = i2c_hid_guid; | 62 | obj[0].Buffer.Pointer = i2c_hid_guid; | |
63 | 63 | |||
64 | /* rev */ | 64 | /* rev */ | |
65 | obj[1].Type = ACPI_TYPE_INTEGER; | 65 | obj[1].Type = ACPI_TYPE_INTEGER; | |
66 | obj[1].Integer.Value = 1; | 66 | obj[1].Integer.Value = 1; | |
67 | 67 | |||
68 | /* func */ | 68 | /* func */ | |
69 | obj[2].Type = ACPI_TYPE_INTEGER; | 69 | obj[2].Type = ACPI_TYPE_INTEGER; | |
70 | obj[2].Integer.Value = 1; | 70 | obj[2].Integer.Value = 1; | |
71 | 71 | |||
72 | obj[3].Type = ACPI_TYPE_PACKAGE; | 72 | obj[3].Type = ACPI_TYPE_PACKAGE; | |
73 | obj[3].Buffer.Length = 0; | 73 | obj[3].Buffer.Length = 0; | |
74 | 74 | |||
75 | buf.Pointer = NULL; | 75 | buf.Pointer = NULL; | |
76 | buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER; | 76 | buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER; | |
77 | 77 | |||
78 | rv = AcpiEvaluateObject(devnode->ad_handle, "_DSM", &arg, &buf); | 78 | rv = AcpiEvaluateObject(devnode->ad_handle, "_DSM", &arg, &buf); | |
79 | 79 | |||
80 | if (ACPI_FAILURE(rv)) { | 80 | if (ACPI_FAILURE(rv)) { | |
81 | aprint_error("failed to evaluate _DSM for %s: %s\n", | 81 | aprint_error("failed to evaluate _DSM for %s: %s\n", | |
82 | devnode->ad_name, AcpiFormatException(rv)); | 82 | devnode->ad_name, AcpiFormatException(rv)); | |
83 | return; | 83 | return; | |
84 | } | 84 | } | |
85 | 85 | |||
86 | osc = buf.Pointer; | 86 | osc = buf.Pointer; | |
87 | if (osc->Type != ACPI_TYPE_INTEGER) { | 87 | if (osc->Type != ACPI_TYPE_INTEGER) { | |
88 | aprint_error("bad _DSM return type %d for %s\n", | 88 | aprint_error("bad _DSM return type %d for %s\n", | |
89 | osc->Type, devnode->ad_name); | 89 | osc->Type, devnode->ad_name); | |
90 | return; | 90 | return; | |
91 | } | 91 | } | |
92 | prop_dictionary_set_uint32(dev, "hid-descr-addr", osc->Integer.Value); | 92 | prop_dictionary_set_uint32(dev, "hid-descr-addr", osc->Integer.Value); | |
93 | } | 93 | } | |
94 | 94 | |||
95 | struct acpi_i2c_id { | 95 | struct acpi_i2c_id { | |
96 | const char *id; | 96 | const char *id; | |
97 | const char *compat; | 97 | const char *compat; | |
98 | const int compatlen; | 98 | const int compatlen; | |
99 | void (*parse)(struct acpi_devnode *, prop_dictionary_t); | 99 | void (*parse)(struct acpi_devnode *, prop_dictionary_t); | |
100 | }; | 100 | }; | |
101 | 101 | |||
102 | static const struct acpi_i2c_id acpi_i2c_ids[] = { | 102 | static const struct acpi_i2c_id acpi_i2c_ids[] = { | |
103 | { | 103 | { | |
104 | .id = "PNP0C50", | 104 | .id = "PNP0C50", | |
105 | .compat = "hid-over-i2c", | 105 | .compat = "hid-over-i2c", | |
106 | .compatlen = 13, | 106 | .compatlen = 13, | |
107 | .parse = acpi_enter_i2c_hid | 107 | .parse = acpi_enter_i2c_hid | |
108 | }, | 108 | }, | |
109 | { | 109 | { | |
110 | .id = "ACPI0C50", | 110 | .id = "ACPI0C50", | |
111 | .compat = "hid-over-i2c", | 111 | .compat = "hid-over-i2c", | |
112 | .compatlen = 13, | 112 | .compatlen = 13, | |
113 | .parse = acpi_enter_i2c_hid | 113 | .parse = acpi_enter_i2c_hid | |
114 | }, | 114 | }, | |
115 | { | 115 | { | |
116 | .id = "NXP0002", | 116 | .id = "NXP0002", | |
117 | .compat = "nxp,pca9547", | 117 | .compat = "nxp,pca9547", | |
118 | .compatlen = 12, | 118 | .compatlen = 12, | |
119 | .parse = NULL | 119 | .parse = NULL | |
120 | }, | 120 | }, | |
121 | { | 121 | { | |
122 | .id = NULL, | 122 | .id = NULL, | |
123 | .compat = NULL, | 123 | .compat = NULL, | |
124 | .compatlen = 0, | 124 | .compatlen = 0, | |
125 | .parse = NULL | 125 | .parse = NULL | |
126 | } | 126 | } | |
127 | }; | 127 | }; | |
128 | 128 | |||
129 | static const struct acpi_i2c_id * | 129 | static const struct acpi_i2c_id * | |
130 | acpi_i2c_search(const char *name) | 130 | acpi_i2c_search(const char *name) | |
131 | { | 131 | { | |
132 | int i; | 132 | int i; | |
133 | for (i = 0; acpi_i2c_ids[i].id != NULL; i++) { | 133 | for (i = 0; acpi_i2c_ids[i].id != NULL; i++) { | |
134 | if (strcmp(name, acpi_i2c_ids[i].id) == 0) | 134 | if (strcmp(name, acpi_i2c_ids[i].id) == 0) | |
135 | return &acpi_i2c_ids[i]; | 135 | return &acpi_i2c_ids[i]; | |
136 | } | 136 | } | |
137 | return NULL; | 137 | return NULL; | |
138 | } | 138 | } | |
139 | 139 | |||
140 | struct acpi_i2c_context { | 140 | struct acpi_i2c_context { | |
141 | uint16_t i2c_addr; | 141 | uint16_t i2c_addr; | |
142 | }; | 142 | }; | |
143 | 143 | |||
144 | static ACPI_STATUS | 144 | static ACPI_STATUS | |
145 | acpi_i2c_resource_parse_callback(ACPI_RESOURCE *res, void *context) | 145 | acpi_i2c_resource_parse_callback(ACPI_RESOURCE *res, void *context) | |
146 | { | 146 | { | |
147 | struct acpi_i2c_context *i2cc = context; | 147 | struct acpi_i2c_context *i2cc = context; | |
148 | 148 | |||
149 | switch (res->Type) { | 149 | switch (res->Type) { | |
150 | case ACPI_RESOURCE_TYPE_END_TAG: | 150 | case ACPI_RESOURCE_TYPE_END_TAG: | |
151 | break; | 151 | break; | |
152 | case ACPI_RESOURCE_TYPE_SERIAL_BUS: | 152 | case ACPI_RESOURCE_TYPE_SERIAL_BUS: | |
153 | switch (res->Data.I2cSerialBus.Type) { | 153 | switch (res->Data.I2cSerialBus.Type) { | |
154 | case ACPI_RESOURCE_SERIAL_TYPE_I2C: | 154 | case ACPI_RESOURCE_SERIAL_TYPE_I2C: | |
155 | i2cc->i2c_addr = res->Data.I2cSerialBus.SlaveAddress; | 155 | i2cc->i2c_addr = res->Data.I2cSerialBus.SlaveAddress; | |
156 | break; | 156 | break; | |
157 | } | 157 | } | |
158 | break; | 158 | break; | |
159 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | 159 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | |
160 | break; | 160 | break; | |
161 | default: | 161 | default: | |
162 | printf("resource type 0x%x ignored\n", res->Type); | 162 | printf("resource type 0x%x ignored\n", res->Type); | |
163 | } | 163 | } | |
164 | return_ACPI_STATUS(AE_OK); | 164 | return_ACPI_STATUS(AE_OK); | |
165 | } | 165 | } | |
166 | 166 | |||
167 | static void | 167 | static void | |
168 | acpi_enter_i2c_device(struct acpi_devnode *ad, prop_array_t array) | 168 | acpi_enter_i2c_device(struct acpi_devnode *ad, prop_array_t array) | |
169 | { | 169 | { | |
170 | prop_dictionary_t dev; | 170 | prop_dictionary_t dev; | |
171 | struct acpi_i2c_context i2cc; | 171 | struct acpi_i2c_context i2cc; | |
172 | ACPI_STATUS rv; | 172 | ACPI_STATUS rv; | |
173 | int cidi; | 173 | int cidi; | |
174 | ACPI_PNP_DEVICE_ID_LIST *idlist; | 174 | ACPI_PNP_DEVICE_ID_LIST *idlist; | |
175 | const char *name; | 175 | const char *name; | |
176 | static const struct acpi_i2c_id *i2c_id; | 176 | static const struct acpi_i2c_id *i2c_id; | |
177 | 177 | |||
178 | memset(&i2cc, 0, sizeof(i2cc)); | 178 | memset(&i2cc, 0, sizeof(i2cc)); | |
179 | rv = AcpiWalkResources(ad->ad_handle, "_CRS", | 179 | rv = AcpiWalkResources(ad->ad_handle, "_CRS", | |
180 | acpi_i2c_resource_parse_callback, &i2cc); | 180 | acpi_i2c_resource_parse_callback, &i2cc); | |
181 | if (ACPI_FAILURE(rv)) { | 181 | if (ACPI_FAILURE(rv)) { | |
182 | aprint_error("ACPI: unable to get resources " | 182 | aprint_error("ACPI: unable to get resources " | |
183 | "for %s: %s\n", ad->ad_name, | 183 | "for %s: %s\n", ad->ad_name, | |
184 | AcpiFormatException(rv)); | 184 | AcpiFormatException(rv)); | |
185 | return; | 185 | return; | |
186 | } | 186 | } | |
187 | if (i2cc.i2c_addr == 0) | 187 | if (i2cc.i2c_addr == 0) | |
188 | return; | 188 | return; | |
189 | dev = prop_dictionary_create(); | 189 | dev = prop_dictionary_create(); | |
190 | if (dev == NULL) { | 190 | if (dev == NULL) { | |
191 | aprint_error("ignoring device %s (no memory)\n", | 191 | aprint_error("ignoring device %s (no memory)\n", | |
192 | ad->ad_name); | 192 | ad->ad_name); | |
193 | return; | 193 | return; | |
194 | } | 194 | } | |
195 | if ((ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0) | 195 | if ((ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0) | |
196 | name = ad->ad_name; | 196 | name = ad->ad_name; | |
197 | else | 197 | else | |
198 | name = ad->ad_devinfo->HardwareId.String; | 198 | name = ad->ad_devinfo->HardwareId.String; | |
199 | prop_dictionary_set_string(dev, "name", name); | 199 | prop_dictionary_set_string(dev, "name", name); | |
200 | prop_dictionary_set_uint32(dev, "addr", i2cc.i2c_addr); | 200 | prop_dictionary_set_uint32(dev, "addr", i2cc.i2c_addr); | |
201 | prop_dictionary_set_uint64(dev, "cookie", (uintptr_t)ad->ad_handle); | 201 | prop_dictionary_set_uint64(dev, "cookie", (uintptr_t)ad->ad_handle); | |
202 | prop_dictionary_set_uint32(dev, "cookietype", I2C_COOKIE_ACPI); | 202 | prop_dictionary_set_uint32(dev, "cookietype", I2C_COOKIE_ACPI); | |
203 | /* first search by name, then by CID */ | 203 | /* first search by name, then by CID */ | |
204 | i2c_id = acpi_i2c_search(name); | 204 | i2c_id = acpi_i2c_search(name); | |
205 | idlist = &ad->ad_devinfo->CompatibleIdList; | 205 | idlist = &ad->ad_devinfo->CompatibleIdList; | |
206 | for (cidi = 0; | 206 | for (cidi = 0; | |
207 | cidi < idlist->Count && i2c_id == NULL; | 207 | cidi < idlist->Count && i2c_id == NULL; | |
208 | cidi++) { | 208 | cidi++) { | |
209 | i2c_id = acpi_i2c_search(idlist->Ids[cidi].String); | 209 | i2c_id = acpi_i2c_search(idlist->Ids[cidi].String); | |
210 | } | 210 | } | |
211 | if (i2c_id != NULL) { | 211 | if (i2c_id != NULL) { | |
212 | if (i2c_id->compat != NULL) { | 212 | if (i2c_id->compat != NULL) { | |
213 | prop_data_t data; | 213 | prop_data_t data; | |
214 | data = prop_data_create_copy(i2c_id->compat, | 214 | data = prop_data_create_copy(i2c_id->compat, | |
215 | i2c_id->compatlen); | 215 | i2c_id->compatlen); | |
216 | prop_dictionary_set(dev, "compatible", data); | 216 | prop_dictionary_set(dev, "compatible", data); | |
217 | prop_object_release(data); | 217 | prop_object_release(data); | |
218 | } | 218 | } | |
219 | if (i2c_id->parse != NULL) | 219 | if (i2c_id->parse != NULL) | |
220 | i2c_id->parse(ad, dev); | 220 | i2c_id->parse(ad, dev); | |
221 | } | 221 | } | |
222 | prop_array_add(array, dev); | 222 | prop_array_add(array, dev); | |
223 | prop_object_release(dev); | 223 | prop_object_release(dev); | |
224 | } | 224 | } | |
225 | 225 | |||
226 | 226 | |||
227 | prop_array_t | 227 | prop_array_t | |
228 | acpi_enter_i2c_devs(struct acpi_devnode *devnode) | 228 | acpi_enter_i2c_devs(device_t dev, struct acpi_devnode *devnode) | |
229 | { | 229 | { | |
230 | struct acpi_devnode *ad; | 230 | struct acpi_devnode *ad; | |
231 | prop_array_t array = prop_array_create(); | 231 | prop_array_t array = prop_array_create(); | |
232 | 232 | |||
233 | if (array == NULL) | 233 | if (array == NULL) | |
234 | return NULL; | 234 | return NULL; | |
235 | 235 | |||
236 | SIMPLEQ_FOREACH(ad, &devnode->ad_child_head, ad_child_list) { | 236 | SIMPLEQ_FOREACH(ad, &devnode->ad_child_head, ad_child_list) { | |
237 | if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE) | 237 | if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE) | |
238 | continue; | 238 | continue; | |
239 | if (!acpi_device_present(ad->ad_handle)) | 239 | if (!acpi_device_present(ad->ad_handle)) | |
240 | continue; | 240 | continue; | |
241 | acpi_enter_i2c_device(ad, array); | 241 | acpi_enter_i2c_device(ad, array); | |
242 | } | 242 | } | |
243 | ||||
244 | if (dev != NULL) { | |||
245 | acpi_claim_childdevs(dev, devnode); | |||
246 | } | |||
247 | ||||
243 | return array; | 248 | return array; | |
244 | } | 249 | } |
--- src/sys/dev/acpi/acpi_util.h 2021/01/14 14:35:53 1.9
+++ src/sys/dev/acpi/acpi_util.h 2021/01/26 00:19:53 1.10
@@ -1,105 +1,107 @@ | @@ -1,105 +1,107 @@ | |||
1 | /* $NetBSD: acpi_util.h,v 1.9 2021/01/14 14:35:53 thorpej Exp $ */ | 1 | /* $NetBSD: acpi_util.h,v 1.10 2021/01/26 00:19:53 jmcneill Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Charles M. Hannum of By Noon Software, Inc. | 8 | * by Charles M. Hannum of By Noon Software, Inc. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | /* | 32 | /* | |
33 | * Copyright 2001, 2003 Wasabi Systems, Inc. | 33 | * Copyright 2001, 2003 Wasabi Systems, Inc. | |
34 | * All rights reserved. | 34 | * All rights reserved. | |
35 | * | 35 | * | |
36 | * Written by Jason R. Thorpe for Wasabi Systems, Inc. | 36 | * Written by Jason R. Thorpe for Wasabi Systems, Inc. | |
37 | * | 37 | * | |
38 | * Redistribution and use in source and binary forms, with or without | 38 | * Redistribution and use in source and binary forms, with or without | |
39 | * modification, are permitted provided that the following conditions | 39 | * modification, are permitted provided that the following conditions | |
40 | * are met: | 40 | * are met: | |
41 | * 1. Redistributions of source code must retain the above copyright | 41 | * 1. Redistributions of source code must retain the above copyright | |
42 | * notice, this list of conditions and the following disclaimer. | 42 | * notice, this list of conditions and the following disclaimer. | |
43 | * 2. Redistributions in binary form must reproduce the above copyright | 43 | * 2. Redistributions in binary form must reproduce the above copyright | |
44 | * notice, this list of conditions and the following disclaimer in the | 44 | * notice, this list of conditions and the following disclaimer in the | |
45 | * documentation and/or other materials provided with the distribution. | 45 | * documentation and/or other materials provided with the distribution. | |
46 | * 3. All advertising materials mentioning features or use of this software | 46 | * 3. All advertising materials mentioning features or use of this software | |
47 | * must display the following acknowledgement: | 47 | * must display the following acknowledgement: | |
48 | * This product includes software developed for the NetBSD Project by | 48 | * This product includes software developed for the NetBSD Project by | |
49 | * Wasabi Systems, Inc. | 49 | * Wasabi Systems, Inc. | |
50 | * 4. The name of Wasabi Systems, Inc. may not be used to endorse | 50 | * 4. The name of Wasabi Systems, Inc. may not be used to endorse | |
51 | * or promote products derived from this software without specific prior | 51 | * or promote products derived from this software without specific prior | |
52 | * written permission. | 52 | * written permission. | |
53 | * | 53 | * | |
54 | * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND | 54 | * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND | |
55 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 55 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
56 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 56 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
57 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC | 57 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC | |
58 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 58 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
59 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 59 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
60 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 60 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
61 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 61 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
62 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 62 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
63 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 63 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
64 | * POSSIBILITY OF SUCH DAMAGE. | 64 | * POSSIBILITY OF SUCH DAMAGE. | |
65 | */ | 65 | */ | |
66 | 66 | |||
67 | #ifndef _SYS_DEV_ACPI_ACPI_UTIL_H | 67 | #ifndef _SYS_DEV_ACPI_ACPI_UTIL_H | |
68 | #define _SYS_DEV_ACPI_ACPI_UTIL_H | 68 | #define _SYS_DEV_ACPI_ACPI_UTIL_H | |
69 | 69 | |||
70 | ACPI_STATUS acpi_eval_integer(ACPI_HANDLE, const char *, ACPI_INTEGER *); | 70 | ACPI_STATUS acpi_eval_integer(ACPI_HANDLE, const char *, ACPI_INTEGER *); | |
71 | ACPI_STATUS acpi_eval_set_integer(ACPI_HANDLE handle, const char *path, | 71 | ACPI_STATUS acpi_eval_set_integer(ACPI_HANDLE handle, const char *path, | |
72 | ACPI_INTEGER arg); | 72 | ACPI_INTEGER arg); | |
73 | ACPI_STATUS acpi_eval_string(ACPI_HANDLE, const char *, char **); | 73 | ACPI_STATUS acpi_eval_string(ACPI_HANDLE, const char *, char **); | |
74 | ACPI_STATUS acpi_eval_struct(ACPI_HANDLE, const char *, ACPI_BUFFER *); | 74 | ACPI_STATUS acpi_eval_struct(ACPI_HANDLE, const char *, ACPI_BUFFER *); | |
75 | ACPI_STATUS acpi_eval_reference_handle(ACPI_OBJECT *, ACPI_HANDLE *); | 75 | ACPI_STATUS acpi_eval_reference_handle(ACPI_OBJECT *, ACPI_HANDLE *); | |
76 | 76 | |||
77 | ACPI_STATUS acpi_foreach_package_object(ACPI_OBJECT *, | 77 | ACPI_STATUS acpi_foreach_package_object(ACPI_OBJECT *, | |
78 | ACPI_STATUS (*)(ACPI_OBJECT *, void *), void *); | 78 | ACPI_STATUS (*)(ACPI_OBJECT *, void *), void *); | |
79 | ACPI_STATUS acpi_get(ACPI_HANDLE, ACPI_BUFFER *, | 79 | ACPI_STATUS acpi_get(ACPI_HANDLE, ACPI_BUFFER *, | |
80 | ACPI_STATUS (*)(ACPI_HANDLE, ACPI_BUFFER *)); | 80 | ACPI_STATUS (*)(ACPI_HANDLE, ACPI_BUFFER *)); | |
81 | 81 | |||
82 | struct acpi_devnode *acpi_match_node(ACPI_HANDLE handle); | 82 | struct acpi_devnode *acpi_match_node(ACPI_HANDLE handle); | |
83 | void acpi_match_node_init(struct acpi_devnode *ad); | 83 | void acpi_match_node_init(struct acpi_devnode *ad); | |
84 | 84 | |||
85 | const char *acpi_name(ACPI_HANDLE); | 85 | const char *acpi_name(ACPI_HANDLE); | |
86 | int acpi_match_hid(ACPI_DEVICE_INFO *, const char * const *); | 86 | int acpi_match_hid(ACPI_DEVICE_INFO *, const char * const *); | |
87 | int acpi_match_class(ACPI_HANDLE, uint8_t, uint8_t, uint8_t); | 87 | int acpi_match_class(ACPI_HANDLE, uint8_t, uint8_t, uint8_t); | |
88 | ACPI_HANDLE acpi_match_cpu_info(struct cpu_info *); | 88 | ACPI_HANDLE acpi_match_cpu_info(struct cpu_info *); | |
89 | struct cpu_info *acpi_match_cpu_handle(ACPI_HANDLE); | 89 | struct cpu_info *acpi_match_cpu_handle(ACPI_HANDLE); | |
90 | 90 | |||
91 | char *acpi_pack_compat_list(ACPI_DEVICE_INFO *, size_t *); | 91 | char *acpi_pack_compat_list(ACPI_DEVICE_INFO *, size_t *); | |
92 | 92 | |||
93 | ACPI_STATUS acpi_dsd_integer(ACPI_HANDLE, const char *, ACPI_INTEGER *); | 93 | ACPI_STATUS acpi_dsd_integer(ACPI_HANDLE, const char *, ACPI_INTEGER *); | |
94 | ACPI_STATUS acpi_dsd_string(ACPI_HANDLE, const char *, char **); | 94 | ACPI_STATUS acpi_dsd_string(ACPI_HANDLE, const char *, char **); | |
95 | 95 | |||
96 | ACPI_STATUS acpi_dsm(ACPI_HANDLE, uint8_t *, ACPI_INTEGER, | 96 | ACPI_STATUS acpi_dsm(ACPI_HANDLE, uint8_t *, ACPI_INTEGER, | |
97 | ACPI_INTEGER, const ACPI_OBJECT *, ACPI_OBJECT **); | 97 | ACPI_INTEGER, const ACPI_OBJECT *, ACPI_OBJECT **); | |
98 | ACPI_STATUS acpi_dsm_typed(ACPI_HANDLE, uint8_t *, ACPI_INTEGER, | 98 | ACPI_STATUS acpi_dsm_typed(ACPI_HANDLE, uint8_t *, ACPI_INTEGER, | |
99 | ACPI_INTEGER, const ACPI_OBJECT *, | 99 | ACPI_INTEGER, const ACPI_OBJECT *, | |
100 | ACPI_OBJECT_TYPE, ACPI_OBJECT **); | 100 | ACPI_OBJECT_TYPE, ACPI_OBJECT **); | |
101 | ACPI_STATUS acpi_dsm_integer(ACPI_HANDLE, uint8_t *, ACPI_INTEGER, | 101 | ACPI_STATUS acpi_dsm_integer(ACPI_HANDLE, uint8_t *, ACPI_INTEGER, | |
102 | ACPI_INTEGER, const ACPI_OBJECT *, | 102 | ACPI_INTEGER, const ACPI_OBJECT *, | |
103 | ACPI_INTEGER *); | 103 | ACPI_INTEGER *); | |
104 | 104 | |||
105 | ACPI_STATUS acpi_claim_childdevs(device_t, struct acpi_devnode *); | |||
106 | ||||
105 | #endif /* !_SYS_DEV_ACPI_ACPI_UTIL_H */ | 107 | #endif /* !_SYS_DEV_ACPI_ACPI_UTIL_H */ |
--- src/sys/dev/acpi/acpi_i2c.h 2017/12/10 16:51:30 1.1
+++ src/sys/dev/acpi/acpi_i2c.h 2021/01/26 00:19:53 1.2
@@ -1,38 +1,38 @@ | @@ -1,38 +1,38 @@ | |||
1 | /* $NetBSD: acpi_i2c.h,v 1.1 2017/12/10 16:51:30 bouyer Exp $ */ | 1 | /* $NetBSD: acpi_i2c.h,v 1.2 2021/01/26 00:19:53 jmcneill Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2017 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2017 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Manuel Bouyer. | 8 | * by Manuel Bouyer. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | 32 | |||
33 | #ifndef _SYS_DEV_ACPI_ACPI_I2C_H | 33 | #ifndef _SYS_DEV_ACPI_ACPI_I2C_H | |
34 | #define _SYS_DEV_ACPI_ACPI_I2C_H | 34 | #define _SYS_DEV_ACPI_ACPI_I2C_H | |
35 | #include <prop/proplib.h> | 35 | #include <prop/proplib.h> | |
36 | 36 | |||
37 | prop_array_t acpi_enter_i2c_devs(struct acpi_devnode *); | 37 | prop_array_t acpi_enter_i2c_devs(device_t, struct acpi_devnode *); | |
38 | #endif /* _SYS_DEV_ACPI_ACPI_I2C_H */ | 38 | #endif /* _SYS_DEV_ACPI_ACPI_I2C_H */ |
--- src/sys/dev/acpi/acpi_util.c 2021/01/14 14:35:53 1.20
+++ src/sys/dev/acpi/acpi_util.c 2021/01/26 00:19:53 1.21
@@ -1,866 +1,882 @@ | @@ -1,866 +1,882 @@ | |||
1 | /* $NetBSD: acpi_util.c,v 1.20 2021/01/14 14:35:53 thorpej Exp $ */ | 1 | /* $NetBSD: acpi_util.c,v 1.21 2021/01/26 00:19:53 jmcneill Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2003, 2007, 2021 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2003, 2007, 2021 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Charles M. Hannum of By Noon Software, Inc. | 8 | * by Charles M. Hannum of By Noon Software, Inc. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | /* | 32 | /* | |
33 | * Copyright 2001, 2003 Wasabi Systems, Inc. | 33 | * Copyright 2001, 2003 Wasabi Systems, Inc. | |
34 | * All rights reserved. | 34 | * All rights reserved. | |
35 | * | 35 | * | |
36 | * Written by Jason R. Thorpe for Wasabi Systems, Inc. | 36 | * Written by Jason R. Thorpe for Wasabi Systems, Inc. | |
37 | * | 37 | * | |
38 | * Redistribution and use in source and binary forms, with or without | 38 | * Redistribution and use in source and binary forms, with or without | |
39 | * modification, are permitted provided that the following conditions | 39 | * modification, are permitted provided that the following conditions | |
40 | * are met: | 40 | * are met: | |
41 | * 1. Redistributions of source code must retain the above copyright | 41 | * 1. Redistributions of source code must retain the above copyright | |
42 | * notice, this list of conditions and the following disclaimer. | 42 | * notice, this list of conditions and the following disclaimer. | |
43 | * 2. Redistributions in binary form must reproduce the above copyright | 43 | * 2. Redistributions in binary form must reproduce the above copyright | |
44 | * notice, this list of conditions and the following disclaimer in the | 44 | * notice, this list of conditions and the following disclaimer in the | |
45 | * documentation and/or other materials provided with the distribution. | 45 | * documentation and/or other materials provided with the distribution. | |
46 | * 3. All advertising materials mentioning features or use of this software | 46 | * 3. All advertising materials mentioning features or use of this software | |
47 | * must display the following acknowledgement: | 47 | * must display the following acknowledgement: | |
48 | * This product includes software developed for the NetBSD Project by | 48 | * This product includes software developed for the NetBSD Project by | |
49 | * Wasabi Systems, Inc. | 49 | * Wasabi Systems, Inc. | |
50 | * 4. The name of Wasabi Systems, Inc. may not be used to endorse | 50 | * 4. The name of Wasabi Systems, Inc. may not be used to endorse | |
51 | * or promote products derived from this software without specific prior | 51 | * or promote products derived from this software without specific prior | |
52 | * written permission. | 52 | * written permission. | |
53 | * | 53 | * | |
54 | * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND | 54 | * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND | |
55 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 55 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
56 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 56 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
57 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC | 57 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC | |
58 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 58 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
59 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 59 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
60 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 60 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
61 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 61 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
62 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 62 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
63 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 63 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
64 | * POSSIBILITY OF SUCH DAMAGE. | 64 | * POSSIBILITY OF SUCH DAMAGE. | |
65 | */ | 65 | */ | |
66 | 66 | |||
67 | #include <sys/cdefs.h> | 67 | #include <sys/cdefs.h> | |
68 | __KERNEL_RCSID(0, "$NetBSD: acpi_util.c,v 1.20 2021/01/14 14:35:53 thorpej Exp $"); | 68 | __KERNEL_RCSID(0, "$NetBSD: acpi_util.c,v 1.21 2021/01/26 00:19:53 jmcneill Exp $"); | |
69 | 69 | |||
70 | #include <sys/param.h> | 70 | #include <sys/param.h> | |
71 | #include <sys/kmem.h> | 71 | #include <sys/kmem.h> | |
72 | #include <sys/cpu.h> | 72 | #include <sys/cpu.h> | |
73 | 73 | |||
74 | #include <dev/acpi/acpireg.h> | 74 | #include <dev/acpi/acpireg.h> | |
75 | #include <dev/acpi/acpivar.h> | 75 | #include <dev/acpi/acpivar.h> | |
76 | #include <dev/acpi/acpi_intr.h> | 76 | #include <dev/acpi/acpi_intr.h> | |
77 | 77 | |||
78 | #include <machine/acpi_machdep.h> | 78 | #include <machine/acpi_machdep.h> | |
79 | 79 | |||
80 | #define _COMPONENT ACPI_BUS_COMPONENT | 80 | #define _COMPONENT ACPI_BUS_COMPONENT | |
81 | ACPI_MODULE_NAME ("acpi_util") | 81 | ACPI_MODULE_NAME ("acpi_util") | |
82 | 82 | |||
83 | static void acpi_clean_node(ACPI_HANDLE, void *); | 83 | static void acpi_clean_node(ACPI_HANDLE, void *); | |
84 | 84 | |||
85 | static const char * const acpicpu_ids[] = { | 85 | static const char * const acpicpu_ids[] = { | |
86 | "ACPI0007", | 86 | "ACPI0007", | |
87 | NULL | 87 | NULL | |
88 | }; | 88 | }; | |
89 | 89 | |||
90 | /* | 90 | /* | |
91 | * Evaluate an integer object. | 91 | * Evaluate an integer object. | |
92 | */ | 92 | */ | |
93 | ACPI_STATUS | 93 | ACPI_STATUS | |
94 | acpi_eval_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER *valp) | 94 | acpi_eval_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER *valp) | |
95 | { | 95 | { | |
96 | ACPI_OBJECT obj; | 96 | ACPI_OBJECT obj; | |
97 | ACPI_BUFFER buf; | 97 | ACPI_BUFFER buf; | |
98 | ACPI_STATUS rv; | 98 | ACPI_STATUS rv; | |
99 | 99 | |||
100 | if (handle == NULL) | 100 | if (handle == NULL) | |
101 | handle = ACPI_ROOT_OBJECT; | 101 | handle = ACPI_ROOT_OBJECT; | |
102 | 102 | |||
103 | (void)memset(&obj, 0, sizeof(obj)); | 103 | (void)memset(&obj, 0, sizeof(obj)); | |
104 | buf.Pointer = &obj; | 104 | buf.Pointer = &obj; | |
105 | buf.Length = sizeof(obj); | 105 | buf.Length = sizeof(obj); | |
106 | 106 | |||
107 | rv = AcpiEvaluateObject(handle, path, NULL, &buf); | 107 | rv = AcpiEvaluateObject(handle, path, NULL, &buf); | |
108 | 108 | |||
109 | if (ACPI_FAILURE(rv)) | 109 | if (ACPI_FAILURE(rv)) | |
110 | return rv; | 110 | return rv; | |
111 | 111 | |||
112 | /* Check that evaluation produced a return value. */ | 112 | /* Check that evaluation produced a return value. */ | |
113 | if (buf.Length == 0) | 113 | if (buf.Length == 0) | |
114 | return AE_NULL_OBJECT; | 114 | return AE_NULL_OBJECT; | |
115 | 115 | |||
116 | if (obj.Type != ACPI_TYPE_INTEGER) | 116 | if (obj.Type != ACPI_TYPE_INTEGER) | |
117 | return AE_TYPE; | 117 | return AE_TYPE; | |
118 | 118 | |||
119 | if (valp != NULL) | 119 | if (valp != NULL) | |
120 | *valp = obj.Integer.Value; | 120 | *valp = obj.Integer.Value; | |
121 | 121 | |||
122 | return AE_OK; | 122 | return AE_OK; | |
123 | } | 123 | } | |
124 | 124 | |||
125 | /* | 125 | /* | |
126 | * Evaluate an integer object with a single integer input parameter. | 126 | * Evaluate an integer object with a single integer input parameter. | |
127 | */ | 127 | */ | |
128 | ACPI_STATUS | 128 | ACPI_STATUS | |
129 | acpi_eval_set_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER val) | 129 | acpi_eval_set_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER val) | |
130 | { | 130 | { | |
131 | ACPI_OBJECT_LIST arg; | 131 | ACPI_OBJECT_LIST arg; | |
132 | ACPI_OBJECT obj; | 132 | ACPI_OBJECT obj; | |
133 | 133 | |||
134 | if (handle == NULL) | 134 | if (handle == NULL) | |
135 | handle = ACPI_ROOT_OBJECT; | 135 | handle = ACPI_ROOT_OBJECT; | |
136 | 136 | |||
137 | obj.Type = ACPI_TYPE_INTEGER; | 137 | obj.Type = ACPI_TYPE_INTEGER; | |
138 | obj.Integer.Value = val; | 138 | obj.Integer.Value = val; | |
139 | 139 | |||
140 | arg.Count = 1; | 140 | arg.Count = 1; | |
141 | arg.Pointer = &obj; | 141 | arg.Pointer = &obj; | |
142 | 142 | |||
143 | return AcpiEvaluateObject(handle, path, &arg, NULL); | 143 | return AcpiEvaluateObject(handle, path, &arg, NULL); | |
144 | } | 144 | } | |
145 | 145 | |||
146 | /* | 146 | /* | |
147 | * Evaluate a (Unicode) string object. | 147 | * Evaluate a (Unicode) string object. | |
148 | */ | 148 | */ | |
149 | ACPI_STATUS | 149 | ACPI_STATUS | |
150 | acpi_eval_string(ACPI_HANDLE handle, const char *path, char **stringp) | 150 | acpi_eval_string(ACPI_HANDLE handle, const char *path, char **stringp) | |
151 | { | 151 | { | |
152 | ACPI_OBJECT *obj; | 152 | ACPI_OBJECT *obj; | |
153 | ACPI_BUFFER buf; | 153 | ACPI_BUFFER buf; | |
154 | ACPI_STATUS rv; | 154 | ACPI_STATUS rv; | |
155 | 155 | |||
156 | rv = acpi_eval_struct(handle, path, &buf); | 156 | rv = acpi_eval_struct(handle, path, &buf); | |
157 | 157 | |||
158 | if (ACPI_FAILURE(rv)) | 158 | if (ACPI_FAILURE(rv)) | |
159 | return rv; | 159 | return rv; | |
160 | 160 | |||
161 | obj = buf.Pointer; | 161 | obj = buf.Pointer; | |
162 | 162 | |||
163 | if (obj->Type != ACPI_TYPE_STRING) { | 163 | if (obj->Type != ACPI_TYPE_STRING) { | |
164 | rv = AE_TYPE; | 164 | rv = AE_TYPE; | |
165 | goto out; | 165 | goto out; | |
166 | } | 166 | } | |
167 | 167 | |||
168 | if (obj->String.Length == 0) { | 168 | if (obj->String.Length == 0) { | |
169 | rv = AE_BAD_DATA; | 169 | rv = AE_BAD_DATA; | |
170 | goto out; | 170 | goto out; | |
171 | } | 171 | } | |
172 | 172 | |||
173 | *stringp = ACPI_ALLOCATE(obj->String.Length + 1); | 173 | *stringp = ACPI_ALLOCATE(obj->String.Length + 1); | |
174 | 174 | |||
175 | if (*stringp == NULL) { | 175 | if (*stringp == NULL) { | |
176 | rv = AE_NO_MEMORY; | 176 | rv = AE_NO_MEMORY; | |
177 | goto out; | 177 | goto out; | |
178 | } | 178 | } | |
179 | 179 | |||
180 | (void)memcpy(*stringp, obj->String.Pointer, obj->String.Length); | 180 | (void)memcpy(*stringp, obj->String.Pointer, obj->String.Length); | |
181 | 181 | |||
182 | (*stringp)[obj->String.Length] = '\0'; | 182 | (*stringp)[obj->String.Length] = '\0'; | |
183 | 183 | |||
184 | out: | 184 | out: | |
185 | ACPI_FREE(buf.Pointer); | 185 | ACPI_FREE(buf.Pointer); | |
186 | 186 | |||
187 | return rv; | 187 | return rv; | |
188 | } | 188 | } | |
189 | 189 | |||
190 | /* | 190 | /* | |
191 | * Evaluate a structure. Caller must free buf.Pointer by ACPI_FREE(). | 191 | * Evaluate a structure. Caller must free buf.Pointer by ACPI_FREE(). | |
192 | */ | 192 | */ | |
193 | ACPI_STATUS | 193 | ACPI_STATUS | |
194 | acpi_eval_struct(ACPI_HANDLE handle, const char *path, ACPI_BUFFER *buf) | 194 | acpi_eval_struct(ACPI_HANDLE handle, const char *path, ACPI_BUFFER *buf) | |
195 | { | 195 | { | |
196 | 196 | |||
197 | if (handle == NULL) | 197 | if (handle == NULL) | |
198 | handle = ACPI_ROOT_OBJECT; | 198 | handle = ACPI_ROOT_OBJECT; | |
199 | 199 | |||
200 | buf->Pointer = NULL; | 200 | buf->Pointer = NULL; | |
201 | buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER; | 201 | buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER; | |
202 | 202 | |||
203 | return AcpiEvaluateObject(handle, path, NULL, buf); | 203 | return AcpiEvaluateObject(handle, path, NULL, buf); | |
204 | } | 204 | } | |
205 | 205 | |||
206 | /* | 206 | /* | |
207 | * Evaluate a reference handle from an element in a package. | 207 | * Evaluate a reference handle from an element in a package. | |
208 | */ | 208 | */ | |
209 | ACPI_STATUS | 209 | ACPI_STATUS | |
210 | acpi_eval_reference_handle(ACPI_OBJECT *elm, ACPI_HANDLE *handle) | 210 | acpi_eval_reference_handle(ACPI_OBJECT *elm, ACPI_HANDLE *handle) | |
211 | { | 211 | { | |
212 | 212 | |||
213 | if (elm == NULL || handle == NULL) | 213 | if (elm == NULL || handle == NULL) | |
214 | return AE_BAD_PARAMETER; | 214 | return AE_BAD_PARAMETER; | |
215 | 215 | |||
216 | switch (elm->Type) { | 216 | switch (elm->Type) { | |
217 | 217 | |||
218 | case ACPI_TYPE_ANY: | 218 | case ACPI_TYPE_ANY: | |
219 | case ACPI_TYPE_LOCAL_REFERENCE: | 219 | case ACPI_TYPE_LOCAL_REFERENCE: | |
220 | 220 | |||
221 | if (elm->Reference.Handle == NULL) | 221 | if (elm->Reference.Handle == NULL) | |
222 | return AE_NULL_ENTRY; | 222 | return AE_NULL_ENTRY; | |
223 | 223 | |||
224 | *handle = elm->Reference.Handle; | 224 | *handle = elm->Reference.Handle; | |
225 | 225 | |||
226 | return AE_OK; | 226 | return AE_OK; | |
227 | 227 | |||
228 | case ACPI_TYPE_STRING: | 228 | case ACPI_TYPE_STRING: | |
229 | return AcpiGetHandle(NULL, elm->String.Pointer, handle); | 229 | return AcpiGetHandle(NULL, elm->String.Pointer, handle); | |
230 | 230 | |||
231 | default: | 231 | default: | |
232 | return AE_TYPE; | 232 | return AE_TYPE; | |
233 | } | 233 | } | |
234 | } | 234 | } | |
235 | 235 | |||
236 | /* | 236 | /* | |
237 | * Iterate over all objects in a package, and pass them all | 237 | * Iterate over all objects in a package, and pass them all | |
238 | * to a function. If the called function returns non-AE_OK, | 238 | * to a function. If the called function returns non-AE_OK, | |
239 | * the iteration is stopped and that value is returned. | 239 | * the iteration is stopped and that value is returned. | |
240 | */ | 240 | */ | |
241 | ACPI_STATUS | 241 | ACPI_STATUS | |
242 | acpi_foreach_package_object(ACPI_OBJECT *pkg, | 242 | acpi_foreach_package_object(ACPI_OBJECT *pkg, | |
243 | ACPI_STATUS (*func)(ACPI_OBJECT *, void *), void *arg) | 243 | ACPI_STATUS (*func)(ACPI_OBJECT *, void *), void *arg) | |
244 | { | 244 | { | |
245 | ACPI_STATUS rv = AE_OK; | 245 | ACPI_STATUS rv = AE_OK; | |
246 | uint32_t i; | 246 | uint32_t i; | |
247 | 247 | |||
248 | if (pkg == NULL) | 248 | if (pkg == NULL) | |
249 | return AE_BAD_PARAMETER; | 249 | return AE_BAD_PARAMETER; | |
250 | 250 | |||
251 | if (pkg->Type != ACPI_TYPE_PACKAGE) | 251 | if (pkg->Type != ACPI_TYPE_PACKAGE) | |
252 | return AE_TYPE; | 252 | return AE_TYPE; | |
253 | 253 | |||
254 | for (i = 0; i < pkg->Package.Count; i++) { | 254 | for (i = 0; i < pkg->Package.Count; i++) { | |
255 | 255 | |||
256 | rv = (*func)(&pkg->Package.Elements[i], arg); | 256 | rv = (*func)(&pkg->Package.Elements[i], arg); | |
257 | 257 | |||
258 | if (ACPI_FAILURE(rv)) | 258 | if (ACPI_FAILURE(rv)) | |
259 | break; | 259 | break; | |
260 | } | 260 | } | |
261 | 261 | |||
262 | return rv; | 262 | return rv; | |
263 | } | 263 | } | |
264 | 264 | |||
265 | /* | 265 | /* | |
266 | * Fetch data info the specified (empty) ACPI buffer. | 266 | * Fetch data info the specified (empty) ACPI buffer. | |
267 | * Caller must free buf.Pointer by ACPI_FREE(). | 267 | * Caller must free buf.Pointer by ACPI_FREE(). | |
268 | */ | 268 | */ | |
269 | ACPI_STATUS | 269 | ACPI_STATUS | |
270 | acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf, | 270 | acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf, | |
271 | ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *)) | 271 | ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *)) | |
272 | { | 272 | { | |
273 | 273 | |||
274 | buf->Pointer = NULL; | 274 | buf->Pointer = NULL; | |
275 | buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER; | 275 | buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER; | |
276 | 276 | |||
277 | return (*getit)(handle, buf); | 277 | return (*getit)(handle, buf); | |
278 | } | 278 | } | |
279 | 279 | |||
280 | /* | 280 | /* | |
281 | * Return a complete pathname from a handle. | 281 | * Return a complete pathname from a handle. | |
282 | * | 282 | * | |
283 | * Note that the function uses static data storage; | 283 | * Note that the function uses static data storage; | |
284 | * if the data is needed for future use, it should be | 284 | * if the data is needed for future use, it should be | |
285 | * copied before any subsequent calls overwrite it. | 285 | * copied before any subsequent calls overwrite it. | |
286 | */ | 286 | */ | |
287 | const char * | 287 | const char * | |
288 | acpi_name(ACPI_HANDLE handle) | 288 | acpi_name(ACPI_HANDLE handle) | |
289 | { | 289 | { | |
290 | static char name[80]; | 290 | static char name[80]; | |
291 | ACPI_BUFFER buf; | 291 | ACPI_BUFFER buf; | |
292 | ACPI_STATUS rv; | 292 | ACPI_STATUS rv; | |
293 | 293 | |||
294 | if (handle == NULL) | 294 | if (handle == NULL) | |
295 | handle = ACPI_ROOT_OBJECT; | 295 | handle = ACPI_ROOT_OBJECT; | |
296 | 296 | |||
297 | buf.Pointer = name; | 297 | buf.Pointer = name; | |
298 | buf.Length = sizeof(name); | 298 | buf.Length = sizeof(name); | |
299 | 299 | |||
300 | rv = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf); | 300 | rv = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf); | |
301 | 301 | |||
302 | if (ACPI_FAILURE(rv)) | 302 | if (ACPI_FAILURE(rv)) | |
303 | return "UNKNOWN"; | 303 | return "UNKNOWN"; | |
304 | 304 | |||
305 | return name; | 305 | return name; | |
306 | } | 306 | } | |
307 | 307 | |||
308 | /* | 308 | /* | |
309 | * Pack _HID and _CID ID strings into an OpenFirmware-like | 309 | * Pack _HID and _CID ID strings into an OpenFirmware-like | |
310 | * string list. | 310 | * string list. | |
311 | */ | 311 | */ | |
312 | char * | 312 | char * | |
313 | acpi_pack_compat_list(ACPI_DEVICE_INFO *ad, size_t *sizep) | 313 | acpi_pack_compat_list(ACPI_DEVICE_INFO *ad, size_t *sizep) | |
314 | { | 314 | { | |
315 | KASSERT(sizep != NULL); | 315 | KASSERT(sizep != NULL); | |
316 | 316 | |||
317 | char *strlist, *cp; | 317 | char *strlist, *cp; | |
318 | size_t len = 0; | 318 | size_t len = 0; | |
319 | uint32_t i; | 319 | uint32_t i; | |
320 | 320 | |||
321 | /* | 321 | /* | |
322 | * First calculate the total size required. | 322 | * First calculate the total size required. | |
323 | * N.B. PNP Device ID length includes terminating NUL. | 323 | * N.B. PNP Device ID length includes terminating NUL. | |
324 | */ | 324 | */ | |
325 | if ((ad->Valid & ACPI_VALID_HID) != 0) { | 325 | if ((ad->Valid & ACPI_VALID_HID) != 0) { | |
326 | len += ad->HardwareId.Length; | 326 | len += ad->HardwareId.Length; | |
327 | } | 327 | } | |
328 | 328 | |||
329 | if ((ad->Valid & ACPI_VALID_CID) != 0) { | 329 | if ((ad->Valid & ACPI_VALID_CID) != 0) { | |
330 | for (i = 0; i < ad->CompatibleIdList.Count; i++) { | 330 | for (i = 0; i < ad->CompatibleIdList.Count; i++) { | |
331 | len += ad->CompatibleIdList.Ids[i].Length; | 331 | len += ad->CompatibleIdList.Ids[i].Length; | |
332 | } | 332 | } | |
333 | } | 333 | } | |
334 | 334 | |||
335 | *sizep = len; | 335 | *sizep = len; | |
336 | if (len == 0) { | 336 | if (len == 0) { | |
337 | return NULL; | 337 | return NULL; | |
338 | } | 338 | } | |
339 | 339 | |||
340 | cp = strlist = kmem_alloc(len, KM_SLEEP); | 340 | cp = strlist = kmem_alloc(len, KM_SLEEP); | |
341 | 341 | |||
342 | if ((ad->Valid & ACPI_VALID_HID) != 0) { | 342 | if ((ad->Valid & ACPI_VALID_HID) != 0) { | |
343 | memcpy(cp, ad->HardwareId.String, ad->HardwareId.Length); | 343 | memcpy(cp, ad->HardwareId.String, ad->HardwareId.Length); | |
344 | cp += ad->HardwareId.Length; | 344 | cp += ad->HardwareId.Length; | |
345 | } | 345 | } | |
346 | 346 | |||
347 | if ((ad->Valid & ACPI_VALID_CID) != 0) { | 347 | if ((ad->Valid & ACPI_VALID_CID) != 0) { | |
348 | for (i = 0; i < ad->CompatibleIdList.Count; i++) { | 348 | for (i = 0; i < ad->CompatibleIdList.Count; i++) { | |
349 | memcpy(cp, ad->CompatibleIdList.Ids[i].String, | 349 | memcpy(cp, ad->CompatibleIdList.Ids[i].String, | |
350 | ad->CompatibleIdList.Ids[i].Length); | 350 | ad->CompatibleIdList.Ids[i].Length); | |
351 | cp += ad->CompatibleIdList.Ids[i].Length; | 351 | cp += ad->CompatibleIdList.Ids[i].Length; | |
352 | } | 352 | } | |
353 | } | 353 | } | |
354 | 354 | |||
355 | KASSERT((size_t)(cp - strlist) == len); | 355 | KASSERT((size_t)(cp - strlist) == len); | |
356 | 356 | |||
357 | return strlist; | 357 | return strlist; | |
358 | } | 358 | } | |
359 | 359 | |||
360 | 360 | |||
361 | /* | 361 | /* | |
362 | * Match given IDs against _HID and _CIDs. | 362 | * Match given IDs against _HID and _CIDs. | |
363 | */ | 363 | */ | |
364 | int | 364 | int | |
365 | acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids) | 365 | acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids) | |
366 | { | 366 | { | |
367 | uint32_t i, n; | 367 | uint32_t i, n; | |
368 | char *id; | 368 | char *id; | |
369 | 369 | |||
370 | while (*ids) { | 370 | while (*ids) { | |
371 | 371 | |||
372 | if ((ad->Valid & ACPI_VALID_HID) != 0) { | 372 | if ((ad->Valid & ACPI_VALID_HID) != 0) { | |
373 | 373 | |||
374 | if (pmatch(ad->HardwareId.String, *ids, NULL) == 2) | 374 | if (pmatch(ad->HardwareId.String, *ids, NULL) == 2) | |
375 | return 1; | 375 | return 1; | |
376 | } | 376 | } | |
377 | 377 | |||
378 | if ((ad->Valid & ACPI_VALID_CID) != 0) { | 378 | if ((ad->Valid & ACPI_VALID_CID) != 0) { | |
379 | 379 | |||
380 | n = ad->CompatibleIdList.Count; | 380 | n = ad->CompatibleIdList.Count; | |
381 | 381 | |||
382 | for (i = 0; i < n; i++) { | 382 | for (i = 0; i < n; i++) { | |
383 | 383 | |||
384 | id = ad->CompatibleIdList.Ids[i].String; | 384 | id = ad->CompatibleIdList.Ids[i].String; | |
385 | 385 | |||
386 | if (pmatch(id, *ids, NULL) == 2) | 386 | if (pmatch(id, *ids, NULL) == 2) | |
387 | return 1; | 387 | return 1; | |
388 | } | 388 | } | |
389 | } | 389 | } | |
390 | 390 | |||
391 | ids++; | 391 | ids++; | |
392 | } | 392 | } | |
393 | 393 | |||
394 | return 0; | 394 | return 0; | |
395 | } | 395 | } | |
396 | 396 | |||
397 | /* | 397 | /* | |
398 | * Match a PCI-defined bass-class, sub-class, and programming interface | 398 | * Match a PCI-defined bass-class, sub-class, and programming interface | |
399 | * against a handle's _CLS object. | 399 | * against a handle's _CLS object. | |
400 | */ | 400 | */ | |
401 | int | 401 | int | |
402 | acpi_match_class(ACPI_HANDLE handle, uint8_t pci_class, uint8_t pci_subclass, | 402 | acpi_match_class(ACPI_HANDLE handle, uint8_t pci_class, uint8_t pci_subclass, | |
403 | uint8_t pci_interface) | 403 | uint8_t pci_interface) | |
404 | { | 404 | { | |
405 | ACPI_BUFFER buf; | 405 | ACPI_BUFFER buf; | |
406 | ACPI_OBJECT *obj; | 406 | ACPI_OBJECT *obj; | |
407 | ACPI_STATUS rv; | 407 | ACPI_STATUS rv; | |
408 | int match = 0; | 408 | int match = 0; | |
409 | 409 | |||
410 | rv = acpi_eval_struct(handle, "_CLS", &buf); | 410 | rv = acpi_eval_struct(handle, "_CLS", &buf); | |
411 | if (ACPI_FAILURE(rv)) | 411 | if (ACPI_FAILURE(rv)) | |
412 | goto done; | 412 | goto done; | |
413 | 413 | |||
414 | obj = buf.Pointer; | 414 | obj = buf.Pointer; | |
415 | if (obj->Type != ACPI_TYPE_PACKAGE) | 415 | if (obj->Type != ACPI_TYPE_PACKAGE) | |
416 | goto done; | 416 | goto done; | |
417 | if (obj->Package.Count != 3) | 417 | if (obj->Package.Count != 3) | |
418 | goto done; | 418 | goto done; | |
419 | if (obj->Package.Elements[0].Type != ACPI_TYPE_INTEGER || | 419 | if (obj->Package.Elements[0].Type != ACPI_TYPE_INTEGER || | |
420 | obj->Package.Elements[1].Type != ACPI_TYPE_INTEGER || | 420 | obj->Package.Elements[1].Type != ACPI_TYPE_INTEGER || | |
421 | obj->Package.Elements[2].Type != ACPI_TYPE_INTEGER) | 421 | obj->Package.Elements[2].Type != ACPI_TYPE_INTEGER) | |
422 | goto done; | 422 | goto done; | |
423 | 423 | |||
424 | match = obj->Package.Elements[0].Integer.Value == pci_class && | 424 | match = obj->Package.Elements[0].Integer.Value == pci_class && | |
425 | obj->Package.Elements[1].Integer.Value == pci_subclass && | 425 | obj->Package.Elements[1].Integer.Value == pci_subclass && | |
426 | obj->Package.Elements[2].Integer.Value == pci_interface; | 426 | obj->Package.Elements[2].Integer.Value == pci_interface; | |
427 | 427 | |||
428 | done: | 428 | done: | |
429 | if (buf.Pointer) | 429 | if (buf.Pointer) | |
430 | ACPI_FREE(buf.Pointer); | 430 | ACPI_FREE(buf.Pointer); | |
431 | return match; | 431 | return match; | |
432 | } | 432 | } | |
433 | 433 | |||
434 | /* | 434 | /* | |
435 | * Match a device node from a handle. | 435 | * Match a device node from a handle. | |
436 | */ | 436 | */ | |
437 | struct acpi_devnode * | 437 | struct acpi_devnode * | |
438 | acpi_match_node(ACPI_HANDLE handle) | 438 | acpi_match_node(ACPI_HANDLE handle) | |
439 | { | 439 | { | |
440 | struct acpi_devnode *ad; | 440 | struct acpi_devnode *ad; | |
441 | ACPI_STATUS rv; | 441 | ACPI_STATUS rv; | |
442 | 442 | |||
443 | if (handle == NULL) | 443 | if (handle == NULL) | |
444 | return NULL; | 444 | return NULL; | |
445 | 445 | |||
446 | rv = AcpiGetData(handle, acpi_clean_node, (void **)&ad); | 446 | rv = AcpiGetData(handle, acpi_clean_node, (void **)&ad); | |
447 | 447 | |||
448 | if (ACPI_FAILURE(rv)) | 448 | if (ACPI_FAILURE(rv)) | |
449 | return NULL; | 449 | return NULL; | |
450 | 450 | |||
451 | return ad; | 451 | return ad; | |
452 | } | 452 | } | |
453 | 453 | |||
454 | /* | 454 | /* | |
455 | * Permanently associate a device node with a handle. | 455 | * Permanently associate a device node with a handle. | |
456 | */ | 456 | */ | |
457 | void | 457 | void | |
458 | acpi_match_node_init(struct acpi_devnode *ad) | 458 | acpi_match_node_init(struct acpi_devnode *ad) | |
459 | { | 459 | { | |
460 | (void)AcpiAttachData(ad->ad_handle, acpi_clean_node, ad); | 460 | (void)AcpiAttachData(ad->ad_handle, acpi_clean_node, ad); | |
461 | } | 461 | } | |
462 | 462 | |||
463 | static void | 463 | static void | |
464 | acpi_clean_node(ACPI_HANDLE handle, void *aux) | 464 | acpi_clean_node(ACPI_HANDLE handle, void *aux) | |
465 | { | 465 | { | |
466 | /* Nothing. */ | 466 | /* Nothing. */ | |
467 | } | 467 | } | |
468 | 468 | |||
469 | /* | 469 | /* | |
470 | * Match a handle from a cpu_info. Returns NULL on failure. | 470 | * Match a handle from a cpu_info. Returns NULL on failure. | |
471 | * | 471 | * | |
472 | * Note that acpi_match_node() can be used if the device node | 472 | * Note that acpi_match_node() can be used if the device node | |
473 | * is also required. | 473 | * is also required. | |
474 | */ | 474 | */ | |
475 | ACPI_HANDLE | 475 | ACPI_HANDLE | |
476 | acpi_match_cpu_info(struct cpu_info *ci) | 476 | acpi_match_cpu_info(struct cpu_info *ci) | |
477 | { | 477 | { | |
478 | struct acpi_softc *sc = acpi_softc; | 478 | struct acpi_softc *sc = acpi_softc; | |
479 | struct acpi_devnode *ad; | 479 | struct acpi_devnode *ad; | |
480 | ACPI_INTEGER val; | 480 | ACPI_INTEGER val; | |
481 | ACPI_OBJECT *obj; | 481 | ACPI_OBJECT *obj; | |
482 | ACPI_BUFFER buf; | 482 | ACPI_BUFFER buf; | |
483 | ACPI_HANDLE hdl; | 483 | ACPI_HANDLE hdl; | |
484 | ACPI_STATUS rv; | 484 | ACPI_STATUS rv; | |
485 | 485 | |||
486 | if (sc == NULL || acpi_active == 0) | 486 | if (sc == NULL || acpi_active == 0) | |
487 | return NULL; | 487 | return NULL; | |
488 | 488 | |||
489 | /* | 489 | /* | |
490 | * CPUs are declared in the ACPI namespace | 490 | * CPUs are declared in the ACPI namespace | |
491 | * either as a Processor() or as a Device(). | 491 | * either as a Processor() or as a Device(). | |
492 | * In both cases the MADT entries are used | 492 | * In both cases the MADT entries are used | |
493 | * for the match (see ACPI 4.0, section 8.4). | 493 | * for the match (see ACPI 4.0, section 8.4). | |
494 | */ | 494 | */ | |
495 | SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) { | 495 | SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) { | |
496 | 496 | |||
497 | hdl = ad->ad_handle; | 497 | hdl = ad->ad_handle; | |
498 | 498 | |||
499 | switch (ad->ad_type) { | 499 | switch (ad->ad_type) { | |
500 | 500 | |||
501 | case ACPI_TYPE_DEVICE: | 501 | case ACPI_TYPE_DEVICE: | |
502 | 502 | |||
503 | if (acpi_match_hid(ad->ad_devinfo, acpicpu_ids) == 0) | 503 | if (acpi_match_hid(ad->ad_devinfo, acpicpu_ids) == 0) | |
504 | break; | 504 | break; | |
505 | 505 | |||
506 | rv = acpi_eval_integer(hdl, "_UID", &val); | 506 | rv = acpi_eval_integer(hdl, "_UID", &val); | |
507 | 507 | |||
508 | if (ACPI_SUCCESS(rv) && val == ci->ci_acpiid) | 508 | if (ACPI_SUCCESS(rv) && val == ci->ci_acpiid) | |
509 | return hdl; | 509 | return hdl; | |
510 | 510 | |||
511 | break; | 511 | break; | |
512 | 512 | |||
513 | case ACPI_TYPE_PROCESSOR: | 513 | case ACPI_TYPE_PROCESSOR: | |
514 | 514 | |||
515 | rv = acpi_eval_struct(hdl, NULL, &buf); | 515 | rv = acpi_eval_struct(hdl, NULL, &buf); | |
516 | 516 | |||
517 | if (ACPI_FAILURE(rv)) | 517 | if (ACPI_FAILURE(rv)) | |
518 | break; | 518 | break; | |
519 | 519 | |||
520 | obj = buf.Pointer; | 520 | obj = buf.Pointer; | |
521 | 521 | |||
522 | if (obj->Processor.ProcId == ci->ci_acpiid) { | 522 | if (obj->Processor.ProcId == ci->ci_acpiid) { | |
523 | ACPI_FREE(buf.Pointer); | 523 | ACPI_FREE(buf.Pointer); | |
524 | return hdl; | 524 | return hdl; | |
525 | } | 525 | } | |
526 | 526 | |||
527 | ACPI_FREE(buf.Pointer); | 527 | ACPI_FREE(buf.Pointer); | |
528 | break; | 528 | break; | |
529 | } | 529 | } | |
530 | } | 530 | } | |
531 | 531 | |||
532 | return NULL; | 532 | return NULL; | |
533 | } | 533 | } | |
534 | 534 | |||
535 | /* | 535 | /* | |
536 | * Match a CPU from a handle. Returns NULL on failure. | 536 | * Match a CPU from a handle. Returns NULL on failure. | |
537 | */ | 537 | */ | |
538 | struct cpu_info * | 538 | struct cpu_info * | |
539 | acpi_match_cpu_handle(ACPI_HANDLE hdl) | 539 | acpi_match_cpu_handle(ACPI_HANDLE hdl) | |
540 | { | 540 | { | |
541 | struct cpu_info *ci; | 541 | struct cpu_info *ci; | |
542 | ACPI_DEVICE_INFO *di; | 542 | ACPI_DEVICE_INFO *di; | |
543 | CPU_INFO_ITERATOR cii; | 543 | CPU_INFO_ITERATOR cii; | |
544 | ACPI_INTEGER val; | 544 | ACPI_INTEGER val; | |
545 | ACPI_OBJECT *obj; | 545 | ACPI_OBJECT *obj; | |
546 | ACPI_BUFFER buf; | 546 | ACPI_BUFFER buf; | |
547 | ACPI_STATUS rv; | 547 | ACPI_STATUS rv; | |
548 | 548 | |||
549 | ci = NULL; | 549 | ci = NULL; | |
550 | di = NULL; | 550 | di = NULL; | |
551 | buf.Pointer = NULL; | 551 | buf.Pointer = NULL; | |
552 | 552 | |||
553 | rv = AcpiGetObjectInfo(hdl, &di); | 553 | rv = AcpiGetObjectInfo(hdl, &di); | |
554 | 554 | |||
555 | if (ACPI_FAILURE(rv)) | 555 | if (ACPI_FAILURE(rv)) | |
556 | return NULL; | 556 | return NULL; | |
557 | 557 | |||
558 | switch (di->Type) { | 558 | switch (di->Type) { | |
559 | 559 | |||
560 | case ACPI_TYPE_DEVICE: | 560 | case ACPI_TYPE_DEVICE: | |
561 | 561 | |||
562 | if (acpi_match_hid(di, acpicpu_ids) == 0) | 562 | if (acpi_match_hid(di, acpicpu_ids) == 0) | |
563 | goto out; | 563 | goto out; | |
564 | 564 | |||
565 | rv = acpi_eval_integer(hdl, "_UID", &val); | 565 | rv = acpi_eval_integer(hdl, "_UID", &val); | |
566 | 566 | |||
567 | if (ACPI_FAILURE(rv)) | 567 | if (ACPI_FAILURE(rv)) | |
568 | goto out; | 568 | goto out; | |
569 | 569 | |||
570 | break; | 570 | break; | |
571 | 571 | |||
572 | case ACPI_TYPE_PROCESSOR: | 572 | case ACPI_TYPE_PROCESSOR: | |
573 | 573 | |||
574 | rv = acpi_eval_struct(hdl, NULL, &buf); | 574 | rv = acpi_eval_struct(hdl, NULL, &buf); | |
575 | 575 | |||
576 | if (ACPI_FAILURE(rv)) | 576 | if (ACPI_FAILURE(rv)) | |
577 | goto out; | 577 | goto out; | |
578 | 578 | |||
579 | obj = buf.Pointer; | 579 | obj = buf.Pointer; | |
580 | val = obj->Processor.ProcId; | 580 | val = obj->Processor.ProcId; | |
581 | break; | 581 | break; | |
582 | 582 | |||
583 | default: | 583 | default: | |
584 | goto out; | 584 | goto out; | |
585 | } | 585 | } | |
586 | 586 | |||
587 | for (CPU_INFO_FOREACH(cii, ci)) { | 587 | for (CPU_INFO_FOREACH(cii, ci)) { | |
588 | 588 | |||
589 | if (ci->ci_acpiid == val) | 589 | if (ci->ci_acpiid == val) | |
590 | goto out; | 590 | goto out; | |
591 | } | 591 | } | |
592 | 592 | |||
593 | ci = NULL; | 593 | ci = NULL; | |
594 | 594 | |||
595 | out: | 595 | out: | |
596 | if (di != NULL) | 596 | if (di != NULL) | |
597 | ACPI_FREE(di); | 597 | ACPI_FREE(di); | |
598 | 598 | |||
599 | if (buf.Pointer != NULL) | 599 | if (buf.Pointer != NULL) | |
600 | ACPI_FREE(buf.Pointer); | 600 | ACPI_FREE(buf.Pointer); | |
601 | 601 | |||
602 | return ci; | 602 | return ci; | |
603 | } | 603 | } | |
604 | 604 | |||
605 | struct acpi_irq_handler { | 605 | struct acpi_irq_handler { | |
606 | uint32_t aih_irq; | 606 | uint32_t aih_irq; | |
607 | void *aih_ih; | 607 | void *aih_ih; | |
608 | }; | 608 | }; | |
609 | 609 | |||
610 | void * | 610 | void * | |
611 | acpi_intr_establish(device_t dev, uint64_t c, int ipl, bool mpsafe, | 611 | acpi_intr_establish(device_t dev, uint64_t c, int ipl, bool mpsafe, | |
612 | int (*intr)(void *), void *iarg, const char *xname) | 612 | int (*intr)(void *), void *iarg, const char *xname) | |
613 | { | 613 | { | |
614 | ACPI_STATUS rv; | 614 | ACPI_STATUS rv; | |
615 | ACPI_HANDLE hdl = (void *)(uintptr_t)c; | 615 | ACPI_HANDLE hdl = (void *)(uintptr_t)c; | |
616 | struct acpi_resources res; | 616 | struct acpi_resources res; | |
617 | struct acpi_irq *irq; | 617 | struct acpi_irq *irq; | |
618 | void *aih = NULL; | 618 | void *aih = NULL; | |
619 | 619 | |||
620 | rv = acpi_resource_parse(dev, hdl, "_CRS", &res, | 620 | rv = acpi_resource_parse(dev, hdl, "_CRS", &res, | |
621 | &acpi_resource_parse_ops_quiet); | 621 | &acpi_resource_parse_ops_quiet); | |
622 | if (ACPI_FAILURE(rv)) | 622 | if (ACPI_FAILURE(rv)) | |
623 | return NULL; | 623 | return NULL; | |
624 | 624 | |||
625 | irq = acpi_res_irq(&res, 0); | 625 | irq = acpi_res_irq(&res, 0); | |
626 | if (irq == NULL) | 626 | if (irq == NULL) | |
627 | goto end; | 627 | goto end; | |
628 | 628 | |||
629 | aih = acpi_intr_establish_irq(dev, irq, ipl, mpsafe, | 629 | aih = acpi_intr_establish_irq(dev, irq, ipl, mpsafe, | |
630 | intr, iarg, xname); | 630 | intr, iarg, xname); | |
631 | 631 | |||
632 | end: | 632 | end: | |
633 | acpi_resource_cleanup(&res); | 633 | acpi_resource_cleanup(&res); | |
634 | 634 | |||
635 | return aih; | 635 | return aih; | |
636 | } | 636 | } | |
637 | 637 | |||
638 | void * | 638 | void * | |
639 | acpi_intr_establish_irq(device_t dev, struct acpi_irq *irq, int ipl, | 639 | acpi_intr_establish_irq(device_t dev, struct acpi_irq *irq, int ipl, | |
640 | bool mpsafe, int (*intr)(void *), void *iarg, const char *xname) | 640 | bool mpsafe, int (*intr)(void *), void *iarg, const char *xname) | |
641 | { | 641 | { | |
642 | struct acpi_irq_handler *aih; | 642 | struct acpi_irq_handler *aih; | |
643 | void *ih; | 643 | void *ih; | |
644 | 644 | |||
645 | const int type = (irq->ar_type == ACPI_EDGE_SENSITIVE) ? IST_EDGE : IST_LEVEL; | 645 | const int type = (irq->ar_type == ACPI_EDGE_SENSITIVE) ? IST_EDGE : IST_LEVEL; | |
646 | ih = acpi_md_intr_establish(irq->ar_irq, ipl, type, intr, iarg, mpsafe, xname); | 646 | ih = acpi_md_intr_establish(irq->ar_irq, ipl, type, intr, iarg, mpsafe, xname); | |
647 | if (ih == NULL) | 647 | if (ih == NULL) | |
648 | return NULL; | 648 | return NULL; | |
649 | 649 | |||
650 | aih = kmem_alloc(sizeof(struct acpi_irq_handler), KM_SLEEP); | 650 | aih = kmem_alloc(sizeof(struct acpi_irq_handler), KM_SLEEP); | |
651 | aih->aih_irq = irq->ar_irq; | 651 | aih->aih_irq = irq->ar_irq; | |
652 | aih->aih_ih = ih; | 652 | aih->aih_ih = ih; | |
653 | 653 | |||
654 | return aih; | 654 | return aih; | |
655 | } | 655 | } | |
656 | 656 | |||
657 | void | 657 | void | |
658 | acpi_intr_mask(void *c) | 658 | acpi_intr_mask(void *c) | |
659 | { | 659 | { | |
660 | struct acpi_irq_handler * const aih = c; | 660 | struct acpi_irq_handler * const aih = c; | |
661 | 661 | |||
662 | acpi_md_intr_mask(aih->aih_ih); | 662 | acpi_md_intr_mask(aih->aih_ih); | |
663 | } | 663 | } | |
664 | 664 | |||
665 | void | 665 | void | |
666 | acpi_intr_unmask(void *c) | 666 | acpi_intr_unmask(void *c) | |
667 | { | 667 | { | |
668 | struct acpi_irq_handler * const aih = c; | 668 | struct acpi_irq_handler * const aih = c; | |
669 | 669 | |||
670 | acpi_md_intr_unmask(aih->aih_ih); | 670 | acpi_md_intr_unmask(aih->aih_ih); | |
671 | } | 671 | } | |
672 | 672 | |||
673 | void | 673 | void | |
674 | acpi_intr_disestablish(void *c) | 674 | acpi_intr_disestablish(void *c) | |
675 | { | 675 | { | |
676 | struct acpi_irq_handler *aih = c; | 676 | struct acpi_irq_handler *aih = c; | |
677 | 677 | |||
678 | acpi_md_intr_disestablish(aih->aih_ih); | 678 | acpi_md_intr_disestablish(aih->aih_ih); | |
679 | kmem_free(aih, sizeof(struct acpi_irq_handler)); | 679 | kmem_free(aih, sizeof(struct acpi_irq_handler)); | |
680 | } | 680 | } | |
681 | 681 | |||
682 | const char * | 682 | const char * | |
683 | acpi_intr_string(void *c, char *buf, size_t size) | 683 | acpi_intr_string(void *c, char *buf, size_t size) | |
684 | { | 684 | { | |
685 | struct acpi_irq_handler *aih = c; | 685 | struct acpi_irq_handler *aih = c; | |
686 | intr_handle_t ih = aih->aih_irq; | 686 | intr_handle_t ih = aih->aih_irq; | |
687 | 687 | |||
688 | return intr_string(ih, buf, size); | 688 | return intr_string(ih, buf, size); | |
689 | } | 689 | } | |
690 | 690 | |||
691 | /* | 691 | /* | |
692 | * Device-Specific Data (_DSD) support | 692 | * Device-Specific Data (_DSD) support | |
693 | */ | 693 | */ | |
694 | 694 | |||
695 | static UINT8 acpi_dsd_uuid[ACPI_UUID_LENGTH] = { | 695 | static UINT8 acpi_dsd_uuid[ACPI_UUID_LENGTH] = { | |
696 | 0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d, | 696 | 0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d, | |
697 | 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01 | 697 | 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01 | |
698 | }; | 698 | }; | |
699 | 699 | |||
700 | static ACPI_STATUS | 700 | static ACPI_STATUS | |
701 | acpi_dsd_property(ACPI_HANDLE handle, const char *prop, ACPI_BUFFER *pbuf, ACPI_OBJECT_TYPE type, ACPI_OBJECT **ret) | 701 | acpi_dsd_property(ACPI_HANDLE handle, const char *prop, ACPI_BUFFER *pbuf, ACPI_OBJECT_TYPE type, ACPI_OBJECT **ret) | |
702 | { | 702 | { | |
703 | ACPI_OBJECT *obj, *uuid, *props, *pobj, *propkey, *propval; | 703 | ACPI_OBJECT *obj, *uuid, *props, *pobj, *propkey, *propval; | |
704 | ACPI_STATUS rv; | 704 | ACPI_STATUS rv; | |
705 | int n; | 705 | int n; | |
706 | 706 | |||
707 | rv = AcpiEvaluateObjectTyped(handle, "_DSD", NULL, pbuf, ACPI_TYPE_PACKAGE); | 707 | rv = AcpiEvaluateObjectTyped(handle, "_DSD", NULL, pbuf, ACPI_TYPE_PACKAGE); | |
708 | if (ACPI_FAILURE(rv)) | 708 | if (ACPI_FAILURE(rv)) | |
709 | return rv; | 709 | return rv; | |
710 | 710 | |||
711 | props = NULL; | 711 | props = NULL; | |
712 | obj = (ACPI_OBJECT *)pbuf->Pointer; | 712 | obj = (ACPI_OBJECT *)pbuf->Pointer; | |
713 | for (n = 0; (n + 1) < obj->Package.Count; n += 2) { | 713 | for (n = 0; (n + 1) < obj->Package.Count; n += 2) { | |
714 | uuid = &obj->Package.Elements[n]; | 714 | uuid = &obj->Package.Elements[n]; | |
715 | if (uuid->Buffer.Length == ACPI_UUID_LENGTH && | 715 | if (uuid->Buffer.Length == ACPI_UUID_LENGTH && | |
716 | memcmp(uuid->Buffer.Pointer, acpi_dsd_uuid, ACPI_UUID_LENGTH) == 0) { | 716 | memcmp(uuid->Buffer.Pointer, acpi_dsd_uuid, ACPI_UUID_LENGTH) == 0) { | |
717 | props = &obj->Package.Elements[n + 1]; | 717 | props = &obj->Package.Elements[n + 1]; | |
718 | break; | 718 | break; | |
719 | } | 719 | } | |
720 | } | 720 | } | |
721 | if (props == NULL) | 721 | if (props == NULL) | |
722 | return AE_NOT_FOUND; | 722 | return AE_NOT_FOUND; | |
723 | 723 | |||
724 | for (n = 0; n < props->Package.Count; n++) { | 724 | for (n = 0; n < props->Package.Count; n++) { | |
725 | pobj = &props->Package.Elements[n]; | 725 | pobj = &props->Package.Elements[n]; | |
726 | if (pobj->Type != ACPI_TYPE_PACKAGE || pobj->Package.Count != 2) | 726 | if (pobj->Type != ACPI_TYPE_PACKAGE || pobj->Package.Count != 2) | |
727 | continue; | 727 | continue; | |
728 | propkey = (ACPI_OBJECT *)&pobj->Package.Elements[0]; | 728 | propkey = (ACPI_OBJECT *)&pobj->Package.Elements[0]; | |
729 | propval = (ACPI_OBJECT *)&pobj->Package.Elements[1]; | 729 | propval = (ACPI_OBJECT *)&pobj->Package.Elements[1]; | |
730 | if (propkey->Type != ACPI_TYPE_STRING) | 730 | if (propkey->Type != ACPI_TYPE_STRING) | |
731 | continue; | 731 | continue; | |
732 | if (strcmp(propkey->String.Pointer, prop) != 0) | 732 | if (strcmp(propkey->String.Pointer, prop) != 0) | |
733 | continue; | 733 | continue; | |
734 | 734 | |||
735 | if (propval->Type != type) { | 735 | if (propval->Type != type) { | |
736 | return AE_TYPE; | 736 | return AE_TYPE; | |
737 | } else { | 737 | } else { | |
738 | *ret = propval; | 738 | *ret = propval; | |
739 | return AE_OK; | 739 | return AE_OK; | |
740 | } | 740 | } | |
741 | break; | 741 | break; | |
742 | } | 742 | } | |
743 | 743 | |||
744 | return AE_NOT_FOUND; | 744 | return AE_NOT_FOUND; | |
745 | } | 745 | } | |
746 | 746 | |||
747 | ACPI_STATUS | 747 | ACPI_STATUS | |
748 | acpi_dsd_integer(ACPI_HANDLE handle, const char *prop, ACPI_INTEGER *val) | 748 | acpi_dsd_integer(ACPI_HANDLE handle, const char *prop, ACPI_INTEGER *val) | |
749 | { | 749 | { | |
750 | ACPI_OBJECT *propval; | 750 | ACPI_OBJECT *propval; | |
751 | ACPI_STATUS rv; | 751 | ACPI_STATUS rv; | |
752 | ACPI_BUFFER buf; | 752 | ACPI_BUFFER buf; | |
753 | 753 | |||
754 | buf.Pointer = NULL; | 754 | buf.Pointer = NULL; | |
755 | buf.Length = ACPI_ALLOCATE_BUFFER; | 755 | buf.Length = ACPI_ALLOCATE_BUFFER; | |
756 | 756 | |||
757 | rv = acpi_dsd_property(handle, prop, &buf, ACPI_TYPE_INTEGER, &propval); | 757 | rv = acpi_dsd_property(handle, prop, &buf, ACPI_TYPE_INTEGER, &propval); | |
758 | if (ACPI_SUCCESS(rv)) | 758 | if (ACPI_SUCCESS(rv)) | |
759 | *val = propval->Integer.Value; | 759 | *val = propval->Integer.Value; | |
760 | 760 | |||
761 | if (buf.Pointer != NULL) | 761 | if (buf.Pointer != NULL) | |
762 | ACPI_FREE(buf.Pointer); | 762 | ACPI_FREE(buf.Pointer); | |
763 | return rv; | 763 | return rv; | |
764 | } | 764 | } | |
765 | 765 | |||
766 | ACPI_STATUS | 766 | ACPI_STATUS | |
767 | acpi_dsd_string(ACPI_HANDLE handle, const char *prop, char **val) | 767 | acpi_dsd_string(ACPI_HANDLE handle, const char *prop, char **val) | |
768 | { | 768 | { | |
769 | ACPI_OBJECT *propval; | 769 | ACPI_OBJECT *propval; | |
770 | ACPI_STATUS rv; | 770 | ACPI_STATUS rv; | |
771 | ACPI_BUFFER buf; | 771 | ACPI_BUFFER buf; | |
772 | 772 | |||
773 | buf.Pointer = NULL; | 773 | buf.Pointer = NULL; | |
774 | buf.Length = ACPI_ALLOCATE_BUFFER; | 774 | buf.Length = ACPI_ALLOCATE_BUFFER; | |
775 | 775 | |||
776 | rv = acpi_dsd_property(handle, prop, &buf, ACPI_TYPE_STRING, &propval); | 776 | rv = acpi_dsd_property(handle, prop, &buf, ACPI_TYPE_STRING, &propval); | |
777 | if (ACPI_SUCCESS(rv)) | 777 | if (ACPI_SUCCESS(rv)) | |
778 | *val = kmem_strdup(propval->String.Pointer, KM_SLEEP); | 778 | *val = kmem_strdup(propval->String.Pointer, KM_SLEEP); | |
779 | 779 | |||
780 | if (buf.Pointer != NULL) | 780 | if (buf.Pointer != NULL) | |
781 | ACPI_FREE(buf.Pointer); | 781 | ACPI_FREE(buf.Pointer); | |
782 | return rv; | 782 | return rv; | |
783 | } | 783 | } | |
784 | 784 | |||
785 | /* | 785 | /* | |
786 | * Device Specific Method (_DSM) support | 786 | * Device Specific Method (_DSM) support | |
787 | */ | 787 | */ | |
788 | 788 | |||
789 | ACPI_STATUS | 789 | ACPI_STATUS | |
790 | acpi_dsm_typed(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev, | 790 | acpi_dsm_typed(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev, | |
791 | ACPI_INTEGER func, const ACPI_OBJECT *arg3, ACPI_OBJECT_TYPE return_type, | 791 | ACPI_INTEGER func, const ACPI_OBJECT *arg3, ACPI_OBJECT_TYPE return_type, | |
792 | ACPI_OBJECT **return_obj) | 792 | ACPI_OBJECT **return_obj) | |
793 | { | 793 | { | |
794 | ACPI_OBJECT_LIST arg; | 794 | ACPI_OBJECT_LIST arg; | |
795 | ACPI_OBJECT obj[4]; | 795 | ACPI_OBJECT obj[4]; | |
796 | ACPI_BUFFER buf; | 796 | ACPI_BUFFER buf; | |
797 | ACPI_STATUS status; | 797 | ACPI_STATUS status; | |
798 | 798 | |||
799 | arg.Count = 4; | 799 | arg.Count = 4; | |
800 | arg.Pointer = obj; | 800 | arg.Pointer = obj; | |
801 | 801 | |||
802 | obj[0].Type = ACPI_TYPE_BUFFER; | 802 | obj[0].Type = ACPI_TYPE_BUFFER; | |
803 | obj[0].Buffer.Length = ACPI_UUID_LENGTH; | 803 | obj[0].Buffer.Length = ACPI_UUID_LENGTH; | |
804 | obj[0].Buffer.Pointer = uuid; | 804 | obj[0].Buffer.Pointer = uuid; | |
805 | 805 | |||
806 | obj[1].Type = ACPI_TYPE_INTEGER; | 806 | obj[1].Type = ACPI_TYPE_INTEGER; | |
807 | obj[1].Integer.Value = rev; | 807 | obj[1].Integer.Value = rev; | |
808 | 808 | |||
809 | obj[2].Type = ACPI_TYPE_INTEGER; | 809 | obj[2].Type = ACPI_TYPE_INTEGER; | |
810 | obj[2].Integer.Value = func; | 810 | obj[2].Integer.Value = func; | |
811 | 811 | |||
812 | if (arg3 != NULL) { | 812 | if (arg3 != NULL) { | |
813 | obj[3] = *arg3; | 813 | obj[3] = *arg3; | |
814 | } else { | 814 | } else { | |
815 | obj[3].Type = ACPI_TYPE_PACKAGE; | 815 | obj[3].Type = ACPI_TYPE_PACKAGE; | |
816 | obj[3].Package.Count = 0; | 816 | obj[3].Package.Count = 0; | |
817 | obj[3].Package.Elements = NULL; | 817 | obj[3].Package.Elements = NULL; | |
818 | } | 818 | } | |
819 | 819 | |||
820 | buf.Pointer = NULL; | 820 | buf.Pointer = NULL; | |
821 | buf.Length = ACPI_ALLOCATE_BUFFER; | 821 | buf.Length = ACPI_ALLOCATE_BUFFER; | |
822 | 822 | |||
823 | if (return_obj == NULL && return_type == ACPI_TYPE_ANY) { | 823 | if (return_obj == NULL && return_type == ACPI_TYPE_ANY) { | |
824 | status = AcpiEvaluateObject(handle, "_DSM", &arg, NULL); | 824 | status = AcpiEvaluateObject(handle, "_DSM", &arg, NULL); | |
825 | } else { | 825 | } else { | |
826 | *return_obj = NULL; | 826 | *return_obj = NULL; | |
827 | status = AcpiEvaluateObjectTyped(handle, "_DSM", &arg, &buf, | 827 | status = AcpiEvaluateObjectTyped(handle, "_DSM", &arg, &buf, | |
828 | return_type); | 828 | return_type); | |
829 | } | 829 | } | |
830 | if (ACPI_FAILURE(status)) { | 830 | if (ACPI_FAILURE(status)) { | |
831 | return status; | 831 | return status; | |
832 | } | 832 | } | |
833 | if (return_obj != NULL) { | 833 | if (return_obj != NULL) { | |
834 | *return_obj = buf.Pointer; | 834 | *return_obj = buf.Pointer; | |
835 | } else if (buf.Pointer != NULL) { | 835 | } else if (buf.Pointer != NULL) { | |
836 | ACPI_FREE(buf.Pointer); | 836 | ACPI_FREE(buf.Pointer); | |
837 | } | 837 | } | |
838 | return AE_OK; | 838 | return AE_OK; | |
839 | } | 839 | } | |
840 | 840 | |||
841 | ACPI_STATUS | 841 | ACPI_STATUS | |
842 | acpi_dsm_integer(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev, | 842 | acpi_dsm_integer(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev, | |
843 | ACPI_INTEGER func, const ACPI_OBJECT *arg3, ACPI_INTEGER *ret) | 843 | ACPI_INTEGER func, const ACPI_OBJECT *arg3, ACPI_INTEGER *ret) | |
844 | { | 844 | { | |
845 | ACPI_OBJECT *obj; | 845 | ACPI_OBJECT *obj; | |
846 | ACPI_STATUS status; | 846 | ACPI_STATUS status; | |
847 | 847 | |||
848 | status = acpi_dsm_typed(handle, uuid, rev, func, arg3, | 848 | status = acpi_dsm_typed(handle, uuid, rev, func, arg3, | |
849 | ACPI_TYPE_INTEGER, &obj); | 849 | ACPI_TYPE_INTEGER, &obj); | |
850 | if (ACPI_FAILURE(status)) { | 850 | if (ACPI_FAILURE(status)) { | |
851 | return status; | 851 | return status; | |
852 | } | 852 | } | |
853 | 853 | |||
854 | *ret = obj->Integer.Value; | 854 | *ret = obj->Integer.Value; | |
855 | ACPI_FREE(obj); | 855 | ACPI_FREE(obj); | |
856 | 856 | |||
857 | return AE_OK; | 857 | return AE_OK; | |
858 | } | 858 | } | |
859 | 859 | |||
860 | ACPI_STATUS | 860 | ACPI_STATUS | |
861 | acpi_dsm(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev, | 861 | acpi_dsm(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev, | |
862 | ACPI_INTEGER func, const ACPI_OBJECT *arg3, ACPI_OBJECT **return_obj) | 862 | ACPI_INTEGER func, const ACPI_OBJECT *arg3, ACPI_OBJECT **return_obj) | |
863 | { | 863 | { | |
864 | return acpi_dsm_typed(handle, uuid, rev, func, arg3, ACPI_TYPE_ANY, | 864 | return acpi_dsm_typed(handle, uuid, rev, func, arg3, ACPI_TYPE_ANY, | |
865 | return_obj); | 865 | return_obj); | |
866 | } | 866 | } | |
867 | ||||
868 | ACPI_STATUS | |||
869 | acpi_claim_childdevs(device_t dev, struct acpi_devnode *devnode) | |||
870 | { | |||
871 | struct acpi_devnode *ad; | |||
872 | ||||
873 | SIMPLEQ_FOREACH(ad, &devnode->ad_child_head, ad_child_list) { | |||
874 | if (ad->ad_device != NULL) | |||
875 | continue; | |||
876 | aprint_debug(dev, "claiming %s\n", acpi_name(ad->ad_handle)); | |||
877 | ad->ad_device = dev; | |||
878 | acpi_claim_childdevs(dev, ad); | |||
879 | } | |||
880 | ||||
881 | return AE_OK; | |||
882 | } |
--- src/sys/dev/acpi/dwiic_acpi.c 2021/01/24 16:33:48 1.5
+++ src/sys/dev/acpi/dwiic_acpi.c 2021/01/26 00:19:53 1.6
@@ -1,182 +1,182 @@ | @@ -1,182 +1,182 @@ | |||
1 | /* $NetBSD: dwiic_acpi.c,v 1.5 2021/01/24 16:33:48 jmcneill Exp $ */ | 1 | /* $NetBSD: dwiic_acpi.c,v 1.6 2021/01/26 00:19:53 jmcneill Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2018 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2018 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Jared McNeill <jmcneill@invisible.ca>. | 8 | * by Jared McNeill <jmcneill@invisible.ca>. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | __KERNEL_RCSID(0, "$NetBSD: dwiic_acpi.c,v 1.5 2021/01/24 16:33:48 jmcneill Exp $"); | 33 | __KERNEL_RCSID(0, "$NetBSD: dwiic_acpi.c,v 1.6 2021/01/26 00:19:53 jmcneill Exp $"); | |
34 | 34 | |||
35 | #include <sys/param.h> | 35 | #include <sys/param.h> | |
36 | #include <sys/bus.h> | 36 | #include <sys/bus.h> | |
37 | #include <sys/cpu.h> | 37 | #include <sys/cpu.h> | |
38 | #include <sys/device.h> | 38 | #include <sys/device.h> | |
39 | 39 | |||
40 | #include <dev/acpi/acpireg.h> | 40 | #include <dev/acpi/acpireg.h> | |
41 | #include <dev/acpi/acpivar.h> | 41 | #include <dev/acpi/acpivar.h> | |
42 | #include <dev/acpi/acpi_intr.h> | 42 | #include <dev/acpi/acpi_intr.h> | |
43 | #include <dev/acpi/acpi_i2c.h> | 43 | #include <dev/acpi/acpi_i2c.h> | |
44 | 44 | |||
45 | #include <dev/ic/dwiic_var.h> | 45 | #include <dev/ic/dwiic_var.h> | |
46 | 46 | |||
47 | struct dwiic_acpi_param { | 47 | struct dwiic_acpi_param { | |
48 | uint16_t hcnt; | 48 | uint16_t hcnt; | |
49 | uint16_t lcnt; | 49 | uint16_t lcnt; | |
50 | uint32_t ht; | 50 | uint32_t ht; | |
51 | }; | 51 | }; | |
52 | 52 | |||
53 | static int dwiic_acpi_match(device_t, cfdata_t, void *); | 53 | static int dwiic_acpi_match(device_t, cfdata_t, void *); | |
54 | static void dwiic_acpi_attach(device_t, device_t, void *); | 54 | static void dwiic_acpi_attach(device_t, device_t, void *); | |
55 | 55 | |||
56 | static void dwiic_acpi_parse_param(struct dwiic_softc *, ACPI_HANDLE, | 56 | static void dwiic_acpi_parse_param(struct dwiic_softc *, ACPI_HANDLE, | |
57 | const char *, struct dwiic_acpi_param *); | 57 | const char *, struct dwiic_acpi_param *); | |
58 | static void dwiic_acpi_configure(struct dwiic_softc *, ACPI_HANDLE); | 58 | static void dwiic_acpi_configure(struct dwiic_softc *, ACPI_HANDLE); | |
59 | 59 | |||
60 | CFATTACH_DECL_NEW(dwiic_acpi, sizeof(struct dwiic_softc), dwiic_acpi_match, dwiic_acpi_attach, NULL, NULL); | 60 | CFATTACH_DECL_NEW(dwiic_acpi, sizeof(struct dwiic_softc), dwiic_acpi_match, dwiic_acpi_attach, NULL, NULL); | |
61 | 61 | |||
62 | static const char * const compatible[] = { | 62 | static const char * const compatible[] = { | |
63 | "AMD0010", /* AMD FCH */ | 63 | "AMD0010", /* AMD FCH */ | |
64 | "AMDI0010", /* AMD FCH */ | 64 | "AMDI0010", /* AMD FCH */ | |
65 | "AMDI0510", /* AMD Seattle */ | 65 | "AMDI0510", /* AMD Seattle */ | |
66 | "APMC0D0F", /* Ampere eMAG */ | 66 | "APMC0D0F", /* Ampere eMAG */ | |
67 | NULL | 67 | NULL | |
68 | }; | 68 | }; | |
69 | 69 | |||
70 | static int | 70 | static int | |
71 | dwiic_acpi_match(device_t parent, cfdata_t cf, void *aux) | 71 | dwiic_acpi_match(device_t parent, cfdata_t cf, void *aux) | |
72 | { | 72 | { | |
73 | struct acpi_attach_args *aa = aux; | 73 | struct acpi_attach_args *aa = aux; | |
74 | 74 | |||
75 | if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) | 75 | if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) | |
76 | return 0; | 76 | return 0; | |
77 | 77 | |||
78 | return acpi_match_hid(aa->aa_node->ad_devinfo, compatible); | 78 | return acpi_match_hid(aa->aa_node->ad_devinfo, compatible); | |
79 | } | 79 | } | |
80 | 80 | |||
81 | static void | 81 | static void | |
82 | dwiic_acpi_attach(device_t parent, device_t self, void *aux) | 82 | dwiic_acpi_attach(device_t parent, device_t self, void *aux) | |
83 | { | 83 | { | |
84 | struct dwiic_softc * const sc = device_private(self); | 84 | struct dwiic_softc * const sc = device_private(self); | |
85 | struct acpi_attach_args *aa = aux; | 85 | struct acpi_attach_args *aa = aux; | |
86 | struct acpi_resources res; | 86 | struct acpi_resources res; | |
87 | struct acpi_mem *mem; | 87 | struct acpi_mem *mem; | |
88 | struct acpi_irq *irq; | 88 | struct acpi_irq *irq; | |
89 | ACPI_STATUS rv; | 89 | ACPI_STATUS rv; | |
90 | int error; | 90 | int error; | |
91 | void *ih; | 91 | void *ih; | |
92 | 92 | |||
93 | sc->sc_dev = self; | 93 | sc->sc_dev = self; | |
94 | sc->sc_type = dwiic_type_generic; | 94 | sc->sc_type = dwiic_type_generic; | |
95 | sc->sc_iot = aa->aa_memt; | 95 | sc->sc_iot = aa->aa_memt; | |
96 | 96 | |||
97 | rv = acpi_resource_parse(sc->sc_dev, aa->aa_node->ad_handle, "_CRS", | 97 | rv = acpi_resource_parse(sc->sc_dev, aa->aa_node->ad_handle, "_CRS", | |
98 | &res, &acpi_resource_parse_ops_default); | 98 | &res, &acpi_resource_parse_ops_default); | |
99 | if (ACPI_FAILURE(rv)) | 99 | if (ACPI_FAILURE(rv)) | |
100 | return; | 100 | return; | |
101 | 101 | |||
102 | mem = acpi_res_mem(&res, 0); | 102 | mem = acpi_res_mem(&res, 0); | |
103 | if (mem == NULL) { | 103 | if (mem == NULL) { | |
104 | aprint_error_dev(self, "couldn't find mem resource\n"); | 104 | aprint_error_dev(self, "couldn't find mem resource\n"); | |
105 | goto done; | 105 | goto done; | |
106 | } | 106 | } | |
107 | 107 | |||
108 | irq = acpi_res_irq(&res, 0); | 108 | irq = acpi_res_irq(&res, 0); | |
109 | if (irq == NULL) { | 109 | if (irq == NULL) { | |
110 | aprint_error_dev(self, "couldn't find irq resource\n"); | 110 | aprint_error_dev(self, "couldn't find irq resource\n"); | |
111 | goto done; | 111 | goto done; | |
112 | } | 112 | } | |
113 | 113 | |||
114 | error = bus_space_map(sc->sc_iot, mem->ar_base, mem->ar_length, 0, &sc->sc_ioh); | 114 | error = bus_space_map(sc->sc_iot, mem->ar_base, mem->ar_length, 0, &sc->sc_ioh); | |
115 | if (error) { | 115 | if (error) { | |
116 | aprint_error_dev(self, "couldn't map registers\n"); | 116 | aprint_error_dev(self, "couldn't map registers\n"); | |
117 | return; | 117 | return; | |
118 | } | 118 | } | |
119 | 119 | |||
120 | ih = acpi_intr_establish(self, | 120 | ih = acpi_intr_establish(self, | |
121 | (uint64_t)(uintptr_t)aa->aa_node->ad_handle, | 121 | (uint64_t)(uintptr_t)aa->aa_node->ad_handle, | |
122 | IPL_VM, true, dwiic_intr, sc, device_xname(self)); | 122 | IPL_VM, true, dwiic_intr, sc, device_xname(self)); | |
123 | if (ih == NULL) { | 123 | if (ih == NULL) { | |
124 | aprint_error_dev(self, "couldn't install interrupt handler\n"); | 124 | aprint_error_dev(self, "couldn't install interrupt handler\n"); | |
125 | bus_space_unmap(sc->sc_iot, sc->sc_ioh, mem->ar_length); | 125 | bus_space_unmap(sc->sc_iot, sc->sc_ioh, mem->ar_length); | |
126 | goto done; | 126 | goto done; | |
127 | } | 127 | } | |
128 | 128 | |||
129 | dwiic_acpi_configure(sc, aa->aa_node->ad_handle); | 129 | dwiic_acpi_configure(sc, aa->aa_node->ad_handle); | |
130 | 130 | |||
131 | sc->sc_iba.iba_child_devices = acpi_enter_i2c_devs(aa->aa_node); | 131 | sc->sc_iba.iba_child_devices = acpi_enter_i2c_devs(self, aa->aa_node); | |
132 | 132 | |||
133 | dwiic_attach(sc); | 133 | dwiic_attach(sc); | |
134 | 134 | |||
135 | config_found_ia(self, "i2cbus", &sc->sc_iba, iicbus_print); | 135 | config_found_ia(self, "i2cbus", &sc->sc_iba, iicbus_print); | |
136 | 136 | |||
137 | pmf_device_register(self, dwiic_suspend, dwiic_resume); | 137 | pmf_device_register(self, dwiic_suspend, dwiic_resume); | |
138 | 138 | |||
139 | done: | 139 | done: | |
140 | acpi_resource_cleanup(&res); | 140 | acpi_resource_cleanup(&res); | |
141 | } | 141 | } | |
142 | 142 | |||
143 | static void | 143 | static void | |
144 | dwiic_acpi_parse_param(struct dwiic_softc *sc, ACPI_HANDLE handle, const char *path, | 144 | dwiic_acpi_parse_param(struct dwiic_softc *sc, ACPI_HANDLE handle, const char *path, | |
145 | struct dwiic_acpi_param *param) | 145 | struct dwiic_acpi_param *param) | |
146 | { | 146 | { | |
147 | ACPI_BUFFER buf; | 147 | ACPI_BUFFER buf; | |
148 | ACPI_OBJECT *obj; | 148 | ACPI_OBJECT *obj; | |
149 | 149 | |||
150 | memset(param, 0, sizeof(*param)); | 150 | memset(param, 0, sizeof(*param)); | |
151 | 151 | |||
152 | if (ACPI_FAILURE(acpi_eval_struct(handle, path, &buf))) | 152 | if (ACPI_FAILURE(acpi_eval_struct(handle, path, &buf))) | |
153 | return; | 153 | return; | |
154 | 154 | |||
155 | obj = buf.Pointer; | 155 | obj = buf.Pointer; | |
156 | if (obj->Type != ACPI_TYPE_PACKAGE || obj->Package.Count != 3) | 156 | if (obj->Type != ACPI_TYPE_PACKAGE || obj->Package.Count != 3) | |
157 | goto done; | 157 | goto done; | |
158 | 158 | |||
159 | param->hcnt = (uint16_t)obj->Package.Elements[0].Integer.Value; | 159 | param->hcnt = (uint16_t)obj->Package.Elements[0].Integer.Value; | |
160 | param->lcnt = (uint16_t)obj->Package.Elements[1].Integer.Value; | 160 | param->lcnt = (uint16_t)obj->Package.Elements[1].Integer.Value; | |
161 | param->ht = (uint32_t)obj->Package.Elements[2].Integer.Value; | 161 | param->ht = (uint32_t)obj->Package.Elements[2].Integer.Value; | |
162 | 162 | |||
163 | done: | 163 | done: | |
164 | ACPI_FREE(buf.Pointer); | 164 | ACPI_FREE(buf.Pointer); | |
165 | } | 165 | } | |
166 | 166 | |||
167 | static void | 167 | static void | |
168 | dwiic_acpi_configure(struct dwiic_softc *sc, ACPI_HANDLE handle) | 168 | dwiic_acpi_configure(struct dwiic_softc *sc, ACPI_HANDLE handle) | |
169 | { | 169 | { | |
170 | struct dwiic_acpi_param sscn, fmcn; | 170 | struct dwiic_acpi_param sscn, fmcn; | |
171 | 171 | |||
172 | dwiic_acpi_parse_param(sc, handle, "SSCN", &sscn); | 172 | dwiic_acpi_parse_param(sc, handle, "SSCN", &sscn); | |
173 | sc->ss_hcnt = sscn.hcnt; | 173 | sc->ss_hcnt = sscn.hcnt; | |
174 | sc->ss_lcnt = sscn.lcnt; | 174 | sc->ss_lcnt = sscn.lcnt; | |
175 | 175 | |||
176 | dwiic_acpi_parse_param(sc, handle, "FMCN", &fmcn); | 176 | dwiic_acpi_parse_param(sc, handle, "FMCN", &fmcn); | |
177 | sc->fs_hcnt = fmcn.hcnt; | 177 | sc->fs_hcnt = fmcn.hcnt; | |
178 | sc->fs_lcnt = fmcn.lcnt; | 178 | sc->fs_lcnt = fmcn.lcnt; | |
179 | 179 | |||
180 | /* XXX */ | 180 | /* XXX */ | |
181 | sc->sda_hold_time = fmcn.ht; | 181 | sc->sda_hold_time = fmcn.ht; | |
182 | } | 182 | } |
--- src/sys/dev/acpi/nxpiic_acpi.c 2021/01/25 12:09:58 1.2
+++ src/sys/dev/acpi/nxpiic_acpi.c 2021/01/26 00:19:53 1.3
@@ -1,183 +1,183 @@ | @@ -1,183 +1,183 @@ | |||
1 | /* $NetBSD: nxpiic_acpi.c,v 1.2 2021/01/25 12:09:58 jmcneill Exp $ */ | 1 | /* $NetBSD: nxpiic_acpi.c,v 1.3 2021/01/26 00:19:53 jmcneill Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2021 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2021 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Jared McNeill <jmcneill@invisible.ca>. | 8 | * by Jared McNeill <jmcneill@invisible.ca>. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | __KERNEL_RCSID(0, "$NetBSD: nxpiic_acpi.c,v 1.2 2021/01/25 12:09:58 jmcneill Exp $"); | 33 | __KERNEL_RCSID(0, "$NetBSD: nxpiic_acpi.c,v 1.3 2021/01/26 00:19:53 jmcneill Exp $"); | |
34 | 34 | |||
35 | #include <sys/param.h> | 35 | #include <sys/param.h> | |
36 | #include <sys/bus.h> | 36 | #include <sys/bus.h> | |
37 | #include <sys/cpu.h> | 37 | #include <sys/cpu.h> | |
38 | #include <sys/device.h> | 38 | #include <sys/device.h> | |
39 | 39 | |||
40 | #include <dev/acpi/acpireg.h> | 40 | #include <dev/acpi/acpireg.h> | |
41 | #include <dev/acpi/acpivar.h> | 41 | #include <dev/acpi/acpivar.h> | |
42 | #include <dev/acpi/acpi_intr.h> | 42 | #include <dev/acpi/acpi_intr.h> | |
43 | #include <dev/acpi/acpi_i2c.h> | 43 | #include <dev/acpi/acpi_i2c.h> | |
44 | 44 | |||
45 | #include <dev/i2c/motoi2cvar.h> | 45 | #include <dev/i2c/motoi2cvar.h> | |
46 | #include <dev/i2c/motoi2creg.h> | 46 | #include <dev/i2c/motoi2creg.h> | |
47 | 47 | |||
48 | #define NXPIIC_SPEED_STD 100000 | 48 | #define NXPIIC_SPEED_STD 100000 | |
49 | 49 | |||
50 | static const struct clk_div { | 50 | static const struct clk_div { | |
51 | int scl_div; | 51 | int scl_div; | |
52 | uint8_t ibc; | 52 | uint8_t ibc; | |
53 | } nxpiic_clk_div[] = { | 53 | } nxpiic_clk_div[] = { | |
54 | { 20, 0x00 }, { 22, 0x01 }, { 24, 0x02 }, { 26, 0x03 }, | 54 | { 20, 0x00 }, { 22, 0x01 }, { 24, 0x02 }, { 26, 0x03 }, | |
55 | { 28, 0x04 }, { 30, 0x05 }, { 32, 0x09 }, { 34, 0x06 }, | 55 | { 28, 0x04 }, { 30, 0x05 }, { 32, 0x09 }, { 34, 0x06 }, | |
56 | { 36, 0x0a }, { 40, 0x07 }, { 44, 0x0c }, { 48, 0x0d }, | 56 | { 36, 0x0a }, { 40, 0x07 }, { 44, 0x0c }, { 48, 0x0d }, | |
57 | { 52, 0x43 }, { 56, 0x0e }, { 60, 0x45 }, { 64, 0x12 }, | 57 | { 52, 0x43 }, { 56, 0x0e }, { 60, 0x45 }, { 64, 0x12 }, | |
58 | { 68, 0x0f }, { 72, 0x13 }, { 80, 0x14 }, { 88, 0x15 }, | 58 | { 68, 0x0f }, { 72, 0x13 }, { 80, 0x14 }, { 88, 0x15 }, | |
59 | { 96, 0x19 }, { 104, 0x16 }, { 112, 0x1a }, { 128, 0x17 }, | 59 | { 96, 0x19 }, { 104, 0x16 }, { 112, 0x1a }, { 128, 0x17 }, | |
60 | { 136, 0x4f }, { 144, 0x1c }, { 160, 0x1d }, { 176, 0x55 }, | 60 | { 136, 0x4f }, { 144, 0x1c }, { 160, 0x1d }, { 176, 0x55 }, | |
61 | { 192, 0x1e }, { 208, 0x56 }, { 224, 0x22 }, { 228, 0x24 }, | 61 | { 192, 0x1e }, { 208, 0x56 }, { 224, 0x22 }, { 228, 0x24 }, | |
62 | { 240, 0x1f }, { 256, 0x23 }, { 288, 0x5c }, { 320, 0x25 }, | 62 | { 240, 0x1f }, { 256, 0x23 }, { 288, 0x5c }, { 320, 0x25 }, | |
63 | { 384, 0x26 }, { 448, 0x2a }, { 480, 0x27 }, { 512, 0x2b }, | 63 | { 384, 0x26 }, { 448, 0x2a }, { 480, 0x27 }, { 512, 0x2b }, | |
64 | { 576, 0x2c }, { 640, 0x2d }, { 768, 0x31 }, { 896, 0x32 }, | 64 | { 576, 0x2c }, { 640, 0x2d }, { 768, 0x31 }, { 896, 0x32 }, | |
65 | { 960, 0x2f }, { 1024, 0x33 }, { 1152, 0x34 }, { 1280, 0x35 }, | 65 | { 960, 0x2f }, { 1024, 0x33 }, { 1152, 0x34 }, { 1280, 0x35 }, | |
66 | { 1536, 0x36 }, { 1792, 0x3a }, { 1920, 0x37 }, { 2048, 0x3b }, | 66 | { 1536, 0x36 }, { 1792, 0x3a }, { 1920, 0x37 }, { 2048, 0x3b }, | |
67 | { 2304, 0x3c }, { 2560, 0x3d }, { 3072, 0x3e }, { 3584, 0x7a }, | 67 | { 2304, 0x3c }, { 2560, 0x3d }, { 3072, 0x3e }, { 3584, 0x7a }, | |
68 | { 3840, 0x3f }, { 4096, 0x7B }, { 5120, 0x7d }, { 6144, 0x7e }, | 68 | { 3840, 0x3f }, { 4096, 0x7B }, { 5120, 0x7d }, { 6144, 0x7e }, | |
69 | }; | 69 | }; | |
70 | 70 | |||
71 | struct nxpiic_softc { | 71 | struct nxpiic_softc { | |
72 | device_t sc_dev; | 72 | device_t sc_dev; | |
73 | struct motoi2c_softc sc_motoi2c; | 73 | struct motoi2c_softc sc_motoi2c; | |
74 | }; | 74 | }; | |
75 | 75 | |||
76 | static int nxpiic_acpi_match(device_t, cfdata_t, void *); | 76 | static int nxpiic_acpi_match(device_t, cfdata_t, void *); | |
77 | static void nxpiic_acpi_attach(device_t, device_t, void *); | 77 | static void nxpiic_acpi_attach(device_t, device_t, void *); | |
78 | 78 | |||
79 | static uint8_t nxpiic_acpi_iord(struct motoi2c_softc *, bus_size_t); | 79 | static uint8_t nxpiic_acpi_iord(struct motoi2c_softc *, bus_size_t); | |
80 | static void nxpiic_acpi_iowr(struct motoi2c_softc *, bus_size_t, uint8_t); | 80 | static void nxpiic_acpi_iowr(struct motoi2c_softc *, bus_size_t, uint8_t); | |
81 | 81 | |||
82 | CFATTACH_DECL_NEW(nxpiic_acpi, sizeof(struct nxpiic_softc), | 82 | CFATTACH_DECL_NEW(nxpiic_acpi, sizeof(struct nxpiic_softc), | |
83 | nxpiic_acpi_match, nxpiic_acpi_attach, NULL, NULL); | 83 | nxpiic_acpi_match, nxpiic_acpi_attach, NULL, NULL); | |
84 | 84 | |||
85 | static const char * const compatible[] = { | 85 | static const char * const compatible[] = { | |
86 | "NXP0001", | 86 | "NXP0001", | |
87 | NULL | 87 | NULL | |
88 | }; | 88 | }; | |
89 | 89 | |||
90 | static int | 90 | static int | |
91 | nxpiic_acpi_match(device_t parent, cfdata_t cf, void *aux) | 91 | nxpiic_acpi_match(device_t parent, cfdata_t cf, void *aux) | |
92 | { | 92 | { | |
93 | struct acpi_attach_args *aa = aux; | 93 | struct acpi_attach_args *aa = aux; | |
94 | 94 | |||
95 | if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) | 95 | if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) | |
96 | return 0; | 96 | return 0; | |
97 | 97 | |||
98 | return acpi_match_hid(aa->aa_node->ad_devinfo, compatible); | 98 | return acpi_match_hid(aa->aa_node->ad_devinfo, compatible); | |
99 | } | 99 | } | |
100 | 100 | |||
101 | static void | 101 | static void | |
102 | nxpiic_acpi_attach(device_t parent, device_t self, void *aux) | 102 | nxpiic_acpi_attach(device_t parent, device_t self, void *aux) | |
103 | { | 103 | { | |
104 | struct nxpiic_softc * const sc = device_private(self); | 104 | struct nxpiic_softc * const sc = device_private(self); | |
105 | struct motoi2c_softc * const msc = &sc->sc_motoi2c; | 105 | struct motoi2c_softc * const msc = &sc->sc_motoi2c; | |
106 | struct motoi2c_settings settings; | 106 | struct motoi2c_settings settings; | |
107 | struct acpi_attach_args *aa = aux; | 107 | struct acpi_attach_args *aa = aux; | |
108 | struct acpi_resources res; | 108 | struct acpi_resources res; | |
109 | struct acpi_mem *mem; | 109 | struct acpi_mem *mem; | |
110 | ACPI_INTEGER clock_freq; | 110 | ACPI_INTEGER clock_freq; | |
111 | ACPI_STATUS rv; | 111 | ACPI_STATUS rv; | |
112 | int error, n; | 112 | int error, n; | |
113 | 113 | |||
114 | sc->sc_dev = self; | 114 | sc->sc_dev = self; | |
115 | msc->sc_iot = aa->aa_memt; | 115 | msc->sc_iot = aa->aa_memt; | |
116 | 116 | |||
117 | rv = acpi_resource_parse(sc->sc_dev, aa->aa_node->ad_handle, "_CRS", | 117 | rv = acpi_resource_parse(sc->sc_dev, aa->aa_node->ad_handle, "_CRS", | |
118 | &res, &acpi_resource_parse_ops_default); | 118 | &res, &acpi_resource_parse_ops_default); | |
119 | if (ACPI_FAILURE(rv)) | 119 | if (ACPI_FAILURE(rv)) | |
120 | return; | 120 | return; | |
121 | 121 | |||
122 | mem = acpi_res_mem(&res, 0); | 122 | mem = acpi_res_mem(&res, 0); | |
123 | if (mem == NULL) { | 123 | if (mem == NULL) { | |
124 | aprint_error_dev(self, "couldn't find mem resource\n"); | 124 | aprint_error_dev(self, "couldn't find mem resource\n"); | |
125 | goto done; | 125 | goto done; | |
126 | } | 126 | } | |
127 | 127 | |||
128 | rv = acpi_dsd_integer(aa->aa_node->ad_handle, "clock-frequency", | 128 | rv = acpi_dsd_integer(aa->aa_node->ad_handle, "clock-frequency", | |
129 | &clock_freq); | 129 | &clock_freq); | |
130 | if (ACPI_FAILURE(rv) || clock_freq == 0) { | 130 | if (ACPI_FAILURE(rv) || clock_freq == 0) { | |
131 | aprint_error_dev(self, "couldn't get clock frequency\n"); | 131 | aprint_error_dev(self, "couldn't get clock frequency\n"); | |
132 | goto done; | 132 | goto done; | |
133 | } | 133 | } | |
134 | aprint_debug_dev(self, "bus clock %u Hz\n", (u_int)clock_freq); | 134 | aprint_debug_dev(self, "bus clock %u Hz\n", (u_int)clock_freq); | |
135 | 135 | |||
136 | error = bus_space_map(msc->sc_iot, mem->ar_base, mem->ar_length, 0, | 136 | error = bus_space_map(msc->sc_iot, mem->ar_base, mem->ar_length, 0, | |
137 | &msc->sc_ioh); | 137 | &msc->sc_ioh); | |
138 | if (error) { | 138 | if (error) { | |
139 | aprint_error_dev(self, "couldn't map registers\n"); | 139 | aprint_error_dev(self, "couldn't map registers\n"); | |
140 | return; | 140 | return; | |
141 | } | 141 | } | |
142 | 142 | |||
143 | settings.i2c_adr = MOTOI2C_ADR_DEFAULT; | 143 | settings.i2c_adr = MOTOI2C_ADR_DEFAULT; | |
144 | settings.i2c_dfsrr = MOTOI2C_DFSRR_DEFAULT; | 144 | settings.i2c_dfsrr = MOTOI2C_DFSRR_DEFAULT; | |
145 | for (n = 0; n < __arraycount(nxpiic_clk_div) - 1; n++) { | 145 | for (n = 0; n < __arraycount(nxpiic_clk_div) - 1; n++) { | |
146 | if (clock_freq / nxpiic_clk_div[n].scl_div < NXPIIC_SPEED_STD) | 146 | if (clock_freq / nxpiic_clk_div[n].scl_div < NXPIIC_SPEED_STD) | |
147 | break; | 147 | break; | |
148 | } | 148 | } | |
149 | settings.i2c_fdr = nxpiic_clk_div[n].ibc; | 149 | settings.i2c_fdr = nxpiic_clk_div[n].ibc; | |
150 | 150 | |||
151 | msc->sc_flags |= MOTOI2C_F_ENABLE_INV | MOTOI2C_F_STATUS_W1C; | 151 | msc->sc_flags |= MOTOI2C_F_ENABLE_INV | MOTOI2C_F_STATUS_W1C; | |
152 | msc->sc_iord = nxpiic_acpi_iord; | 152 | msc->sc_iord = nxpiic_acpi_iord; | |
153 | msc->sc_iowr = nxpiic_acpi_iowr; | 153 | msc->sc_iowr = nxpiic_acpi_iowr; | |
154 | msc->sc_child_devices = acpi_enter_i2c_devs(aa->aa_node); | 154 | msc->sc_child_devices = acpi_enter_i2c_devs(self, aa->aa_node); | |
155 | 155 | |||
156 | motoi2c_attach_common(self, msc, &settings); | 156 | motoi2c_attach_common(self, msc, &settings); | |
157 | 157 | |||
158 | done: | 158 | done: | |
159 | acpi_resource_cleanup(&res); | 159 | acpi_resource_cleanup(&res); | |
160 | 160 | |||
161 | } | 161 | } | |
162 | 162 | |||
163 | static uint8_t | 163 | static uint8_t | |
164 | nxpiic_acpi_iord(struct motoi2c_softc *msc, bus_size_t off) | 164 | nxpiic_acpi_iord(struct motoi2c_softc *msc, bus_size_t off) | |
165 | { | 165 | { | |
166 | KASSERT((off & 3) == 0); | 166 | KASSERT((off & 3) == 0); | |
167 | 167 | |||
168 | if (off >= I2CDFSRR) | 168 | if (off >= I2CDFSRR) | |
169 | return 0; | 169 | return 0; | |
170 | 170 | |||
171 | return bus_space_read_1(msc->sc_iot, msc->sc_ioh, off >> 2); | 171 | return bus_space_read_1(msc->sc_iot, msc->sc_ioh, off >> 2); | |
172 | } | 172 | } | |
173 | 173 | |||
174 | static void | 174 | static void | |
175 | nxpiic_acpi_iowr(struct motoi2c_softc *msc, bus_size_t off, uint8_t val) | 175 | nxpiic_acpi_iowr(struct motoi2c_softc *msc, bus_size_t off, uint8_t val) | |
176 | { | 176 | { | |
177 | KASSERT((off & 3) == 0); | 177 | KASSERT((off & 3) == 0); | |
178 | 178 | |||
179 | if (off >= I2CDFSRR) | 179 | if (off >= I2CDFSRR) | |
180 | return; | 180 | return; | |
181 | 181 | |||
182 | bus_space_write_1(msc->sc_iot, msc->sc_ioh, off >> 2, val); | 182 | bus_space_write_1(msc->sc_iot, msc->sc_ioh, off >> 2, val); | |
183 | } | 183 | } |
--- src/sys/dev/i2c/i2cmux.c 2021/01/25 12:18:18 1.3
+++ src/sys/dev/i2c/i2cmux.c 2021/01/26 00:19:53 1.4
@@ -1,316 +1,316 @@ | @@ -1,316 +1,316 @@ | |||
1 | /* $NetBSD: i2cmux.c,v 1.3 2021/01/25 12:18:18 jmcneill Exp $ */ | 1 | /* $NetBSD: i2cmux.c,v 1.4 2021/01/26 00:19:53 jmcneill Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2020 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2020 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Jason R. Thorpe. | 8 | * by Jason R. Thorpe. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #if defined(__i386__) || defined(__amd64__) || defined(__aarch64__) | 32 | #if defined(__i386__) || defined(__amd64__) || defined(__aarch64__) | |
33 | #include "acpica.h" | 33 | #include "acpica.h" | |
34 | #endif | 34 | #endif | |
35 | 35 | |||
36 | #include <sys/cdefs.h> | 36 | #include <sys/cdefs.h> | |
37 | __KERNEL_RCSID(0, "$NetBSD: i2cmux.c,v 1.3 2021/01/25 12:18:18 jmcneill Exp $"); | 37 | __KERNEL_RCSID(0, "$NetBSD: i2cmux.c,v 1.4 2021/01/26 00:19:53 jmcneill Exp $"); | |
38 | 38 | |||
39 | #include <sys/types.h> | 39 | #include <sys/types.h> | |
40 | #include <sys/device.h> | 40 | #include <sys/device.h> | |
41 | #include <sys/kernel.h> | 41 | #include <sys/kernel.h> | |
42 | #include <sys/kmem.h> | 42 | #include <sys/kmem.h> | |
43 | 43 | |||
44 | #include <dev/fdt/fdtvar.h> | 44 | #include <dev/fdt/fdtvar.h> | |
45 | #include <dev/i2c/i2cvar.h> | 45 | #include <dev/i2c/i2cvar.h> | |
46 | #include <dev/i2c/i2cmuxvar.h> | 46 | #include <dev/i2c/i2cmuxvar.h> | |
47 | 47 | |||
48 | #if NACPICA > 0 | 48 | #if NACPICA > 0 | |
49 | #include <dev/acpi/acpivar.h> | 49 | #include <dev/acpi/acpivar.h> | |
50 | #include <dev/acpi/acpi_i2c.h> | 50 | #include <dev/acpi/acpi_i2c.h> | |
51 | #endif | 51 | #endif | |
52 | 52 | |||
53 | /* | 53 | /* | |
54 | * i2c mux | 54 | * i2c mux | |
55 | * | 55 | * | |
56 | * This works by interposing a set of virtual controllers behind the real | 56 | * This works by interposing a set of virtual controllers behind the real | |
57 | * i2c controller. We provide our own acquire and release functions that | 57 | * i2c controller. We provide our own acquire and release functions that | |
58 | * perform the following tasks: | 58 | * perform the following tasks: | |
59 | * | 59 | * | |
60 | * acquire -> acquire parent controller, program mux | 60 | * acquire -> acquire parent controller, program mux | |
61 | * | 61 | * | |
62 | * release -> idle mux, release parent controller | 62 | * release -> idle mux, release parent controller | |
63 | * | 63 | * | |
64 | * All of the actual I/O operations are transparently passed through. | 64 | * All of the actual I/O operations are transparently passed through. | |
65 | * | 65 | * | |
66 | * N.B. the locking order; the generic I2C layer has already acquired | 66 | * N.B. the locking order; the generic I2C layer has already acquired | |
67 | * our virtual controller's mutex before calling our acquire function, | 67 | * our virtual controller's mutex before calling our acquire function, | |
68 | * and we will then acquire the real controller's mutex when we acquire | 68 | * and we will then acquire the real controller's mutex when we acquire | |
69 | * the bus, so the order is: | 69 | * the bus, so the order is: | |
70 | * | 70 | * | |
71 | * mux virtual controller -> parent controller | 71 | * mux virtual controller -> parent controller | |
72 | * | 72 | * | |
73 | * These are common routines used by various i2c mux controller | 73 | * These are common routines used by various i2c mux controller | |
74 | * implementations (gpio, pin mux, i2c device, etc.). | 74 | * implementations (gpio, pin mux, i2c device, etc.). | |
75 | */ | 75 | */ | |
76 | 76 | |||
77 | /*****************************************************************************/ | 77 | /*****************************************************************************/ | |
78 | 78 | |||
79 | static int | 79 | static int | |
80 | iicmux_acquire_bus(void * const v, int const flags) | 80 | iicmux_acquire_bus(void * const v, int const flags) | |
81 | { | 81 | { | |
82 | struct iicmux_bus * const bus = v; | 82 | struct iicmux_bus * const bus = v; | |
83 | struct iicmux_softc * const sc = bus->mux; | 83 | struct iicmux_softc * const sc = bus->mux; | |
84 | int error; | 84 | int error; | |
85 | 85 | |||
86 | error = iic_acquire_bus(sc->sc_i2c_parent, flags); | 86 | error = iic_acquire_bus(sc->sc_i2c_parent, flags); | |
87 | if (error) { | 87 | if (error) { | |
88 | return error; | 88 | return error; | |
89 | } | 89 | } | |
90 | 90 | |||
91 | error = sc->sc_config->acquire_bus(bus, flags); | 91 | error = sc->sc_config->acquire_bus(bus, flags); | |
92 | if (error) { | 92 | if (error) { | |
93 | iic_release_bus(sc->sc_i2c_parent, flags); | 93 | iic_release_bus(sc->sc_i2c_parent, flags); | |
94 | } | 94 | } | |
95 | 95 | |||
96 | return error; | 96 | return error; | |
97 | } | 97 | } | |
98 | 98 | |||
99 | static void | 99 | static void | |
100 | iicmux_release_bus(void * const v, int const flags) | 100 | iicmux_release_bus(void * const v, int const flags) | |
101 | { | 101 | { | |
102 | struct iicmux_bus * const bus = v; | 102 | struct iicmux_bus * const bus = v; | |
103 | struct iicmux_softc * const sc = bus->mux; | 103 | struct iicmux_softc * const sc = bus->mux; | |
104 | 104 | |||
105 | sc->sc_config->release_bus(bus, flags); | 105 | sc->sc_config->release_bus(bus, flags); | |
106 | iic_release_bus(sc->sc_i2c_parent, flags); | 106 | iic_release_bus(sc->sc_i2c_parent, flags); | |
107 | } | 107 | } | |
108 | 108 | |||
109 | static int | 109 | static int | |
110 | iicmux_exec(void * const v, i2c_op_t const op, i2c_addr_t const addr, | 110 | iicmux_exec(void * const v, i2c_op_t const op, i2c_addr_t const addr, | |
111 | const void * const cmdbuf, size_t const cmdlen, void * const databuf, | 111 | const void * const cmdbuf, size_t const cmdlen, void * const databuf, | |
112 | size_t const datalen, int const flags) | 112 | size_t const datalen, int const flags) | |
113 | { | 113 | { | |
114 | struct iicmux_bus * const bus = v; | 114 | struct iicmux_bus * const bus = v; | |
115 | struct iicmux_softc * const sc = bus->mux; | 115 | struct iicmux_softc * const sc = bus->mux; | |
116 | 116 | |||
117 | return iic_exec(sc->sc_i2c_parent, op, addr, cmdbuf, cmdlen, | 117 | return iic_exec(sc->sc_i2c_parent, op, addr, cmdbuf, cmdlen, | |
118 | databuf, datalen, flags); | 118 | databuf, datalen, flags); | |
119 | } | 119 | } | |
120 | 120 | |||
121 | /*****************************************************************************/ | 121 | /*****************************************************************************/ | |
122 | 122 | |||
123 | static int | 123 | static int | |
124 | iicmux_count_children(struct iicmux_softc * const sc) | 124 | iicmux_count_children(struct iicmux_softc * const sc) | |
125 | { | 125 | { | |
126 | char name[32]; | 126 | char name[32]; | |
127 | int child, count; | 127 | int child, count; | |
128 | 128 | |||
129 | restart: | 129 | restart: | |
130 | for (child = OF_child(sc->sc_i2c_mux_phandle), count = 0; child; | 130 | for (child = OF_child(sc->sc_i2c_mux_phandle), count = 0; child; | |
131 | child = OF_peer(child)) { | 131 | child = OF_peer(child)) { | |
132 | if (OF_getprop(child, "name", name, sizeof(name)) <= 0) { | 132 | if (OF_getprop(child, "name", name, sizeof(name)) <= 0) { | |
133 | continue; | 133 | continue; | |
134 | } | 134 | } | |
135 | if (strcmp(name, "i2c-mux") == 0) { | 135 | if (strcmp(name, "i2c-mux") == 0) { | |
136 | /* | 136 | /* | |
137 | * The node we encountered is the acutal parent | 137 | * The node we encountered is the acutal parent | |
138 | * of the i2c bus children. Stash its phandle | 138 | * of the i2c bus children. Stash its phandle | |
139 | * and restart the enumeration. | 139 | * and restart the enumeration. | |
140 | */ | 140 | */ | |
141 | sc->sc_i2c_mux_phandle = child; | 141 | sc->sc_i2c_mux_phandle = child; | |
142 | goto restart; | 142 | goto restart; | |
143 | } | 143 | } | |
144 | count++; | 144 | count++; | |
145 | } | 145 | } | |
146 | 146 | |||
147 | return count; | 147 | return count; | |
148 | } | 148 | } | |
149 | 149 | |||
150 | /* XXX iicbus_print() should be able to do this. */ | 150 | /* XXX iicbus_print() should be able to do this. */ | |
151 | static int | 151 | static int | |
152 | iicmux_print(void * const aux, const char * const pnp) | 152 | iicmux_print(void * const aux, const char * const pnp) | |
153 | { | 153 | { | |
154 | i2c_tag_t const tag = aux; | 154 | i2c_tag_t const tag = aux; | |
155 | struct iicmux_bus * const bus = tag->ic_cookie; | 155 | struct iicmux_bus * const bus = tag->ic_cookie; | |
156 | int rv; | 156 | int rv; | |
157 | 157 | |||
158 | rv = iicbus_print(aux, pnp); | 158 | rv = iicbus_print(aux, pnp); | |
159 | aprint_normal(" bus %d", bus->busidx); | 159 | aprint_normal(" bus %d", bus->busidx); | |
160 | 160 | |||
161 | return rv; | 161 | return rv; | |
162 | } | 162 | } | |
163 | 163 | |||
164 | static void | 164 | static void | |
165 | iicmux_attach_bus(struct iicmux_softc * const sc, | 165 | iicmux_attach_bus(struct iicmux_softc * const sc, | |
166 | uintptr_t const handle, enum i2c_cookie_type handletype, int const busidx) | 166 | uintptr_t const handle, enum i2c_cookie_type handletype, int const busidx) | |
167 | { | 167 | { | |
168 | struct iicmux_bus * const bus = &sc->sc_busses[busidx]; | 168 | struct iicmux_bus * const bus = &sc->sc_busses[busidx]; | |
169 | 169 | |||
170 | bus->mux = sc; | 170 | bus->mux = sc; | |
171 | bus->busidx = busidx; | 171 | bus->busidx = busidx; | |
172 | bus->handle = handle; | 172 | bus->handle = handle; | |
173 | bus->handletype = handletype; | 173 | bus->handletype = handletype; | |
174 | 174 | |||
175 | bus->bus_data = sc->sc_config->get_bus_info(bus); | 175 | bus->bus_data = sc->sc_config->get_bus_info(bus); | |
176 | if (bus->bus_data == NULL) { | 176 | if (bus->bus_data == NULL) { | |
177 | aprint_error_dev(sc->sc_dev, | 177 | aprint_error_dev(sc->sc_dev, | |
178 | "unable to get info for bus %d\n", busidx); | 178 | "unable to get info for bus %d\n", busidx); | |
179 | return; | 179 | return; | |
180 | } | 180 | } | |
181 | 181 | |||
182 | iic_tag_init(&bus->controller); | 182 | iic_tag_init(&bus->controller); | |
183 | bus->controller.ic_cookie = bus; | 183 | bus->controller.ic_cookie = bus; | |
184 | bus->controller.ic_acquire_bus = iicmux_acquire_bus; | 184 | bus->controller.ic_acquire_bus = iicmux_acquire_bus; | |
185 | bus->controller.ic_release_bus = iicmux_release_bus; | 185 | bus->controller.ic_release_bus = iicmux_release_bus; | |
186 | bus->controller.ic_exec = iicmux_exec; | 186 | bus->controller.ic_exec = iicmux_exec; | |
187 | 187 | |||
188 | switch (handletype) { | 188 | switch (handletype) { | |
189 | case I2C_COOKIE_OF: | 189 | case I2C_COOKIE_OF: | |
190 | fdtbus_register_i2c_controller(&bus->controller, | 190 | fdtbus_register_i2c_controller(&bus->controller, | |
191 | (int)bus->handle); | 191 | (int)bus->handle); | |
192 | 192 | |||
193 | fdtbus_attach_i2cbus(sc->sc_dev, (int)bus->handle, | 193 | fdtbus_attach_i2cbus(sc->sc_dev, (int)bus->handle, | |
194 | &bus->controller, iicmux_print); | 194 | &bus->controller, iicmux_print); | |
195 | break; | 195 | break; | |
196 | #if NACPICA > 0 | 196 | #if NACPICA > 0 | |
197 | case I2C_COOKIE_ACPI: { | 197 | case I2C_COOKIE_ACPI: { | |
198 | struct acpi_devnode *ad = acpi_match_node((ACPI_HANDLE)handle); | 198 | struct acpi_devnode *ad = acpi_match_node((ACPI_HANDLE)handle); | |
199 | KASSERT(ad != NULL); | 199 | KASSERT(ad != NULL); | |
200 | struct i2cbus_attach_args iba = { | 200 | struct i2cbus_attach_args iba = { | |
201 | .iba_tag = &bus->controller, | 201 | .iba_tag = &bus->controller, | |
202 | .iba_child_devices = acpi_enter_i2c_devs(ad) | 202 | .iba_child_devices = acpi_enter_i2c_devs(NULL, ad) | |
203 | }; | 203 | }; | |
204 | config_found_ia(sc->sc_dev, "i2cbus", &iba, iicbus_print); | 204 | config_found_ia(sc->sc_dev, "i2cbus", &iba, iicbus_print); | |
205 | } break; | 205 | } break; | |
206 | #endif | 206 | #endif | |
207 | default: | 207 | default: | |
208 | aprint_error_dev(sc->sc_dev, "unknown handle type\n"); | 208 | aprint_error_dev(sc->sc_dev, "unknown handle type\n"); | |
209 | break; | 209 | break; | |
210 | } | 210 | } | |
211 | } | 211 | } | |
212 | 212 | |||
213 | static void | 213 | static void | |
214 | iicmux_attach_fdt(struct iicmux_softc * const sc) | 214 | iicmux_attach_fdt(struct iicmux_softc * const sc) | |
215 | { | 215 | { | |
216 | /* | 216 | /* | |
217 | * We start out assuming that the i2c bus nodes are children of | 217 | * We start out assuming that the i2c bus nodes are children of | |
218 | * our own node. We'll adjust later if we encounter an "i2c-mux" | 218 | * our own node. We'll adjust later if we encounter an "i2c-mux" | |
219 | * node when counting our children. If we encounter such a node, | 219 | * node when counting our children. If we encounter such a node, | |
220 | * then it's that node that is the parent of the i2c bus children. | 220 | * then it's that node that is the parent of the i2c bus children. | |
221 | */ | 221 | */ | |
222 | sc->sc_i2c_mux_phandle = (int)sc->sc_handle; | 222 | sc->sc_i2c_mux_phandle = (int)sc->sc_handle; | |
223 | 223 | |||
224 | sc->sc_nbusses = iicmux_count_children(sc); | 224 | sc->sc_nbusses = iicmux_count_children(sc); | |
225 | if (sc->sc_nbusses == 0) { | 225 | if (sc->sc_nbusses == 0) { | |
226 | return; | 226 | return; | |
227 | } | 227 | } | |
228 | 228 | |||
229 | sc->sc_busses = kmem_zalloc(sizeof(*sc->sc_busses) * sc->sc_nbusses, | 229 | sc->sc_busses = kmem_zalloc(sizeof(*sc->sc_busses) * sc->sc_nbusses, | |
230 | KM_SLEEP); | 230 | KM_SLEEP); | |
231 | 231 | |||
232 | int child, idx; | 232 | int child, idx; | |
233 | for (child = OF_child(sc->sc_i2c_mux_phandle), idx = 0; child; | 233 | for (child = OF_child(sc->sc_i2c_mux_phandle), idx = 0; child; | |
234 | child = OF_peer(child), idx++) { | 234 | child = OF_peer(child), idx++) { | |
235 | KASSERT(idx < sc->sc_nbusses); | 235 | KASSERT(idx < sc->sc_nbusses); | |
236 | iicmux_attach_bus(sc, child, I2C_COOKIE_OF, idx); | 236 | iicmux_attach_bus(sc, child, I2C_COOKIE_OF, idx); | |
237 | } | 237 | } | |
238 | } | 238 | } | |
239 | 239 | |||
240 | #if NACPICA > 0 | 240 | #if NACPICA > 0 | |
241 | static void | 241 | static void | |
242 | iicmux_attach_acpi(struct iicmux_softc * const sc) | 242 | iicmux_attach_acpi(struct iicmux_softc * const sc) | |
243 | { | 243 | { | |
244 | ACPI_HANDLE hdl = (ACPI_HANDLE)sc->sc_handle; | 244 | ACPI_HANDLE hdl = (ACPI_HANDLE)sc->sc_handle; | |
245 | struct acpi_devnode *devnode, *ad; | 245 | struct acpi_devnode *devnode, *ad; | |
246 | int idx; | 246 | int idx; | |
247 | 247 | |||
248 | devnode = acpi_match_node(hdl); | 248 | devnode = acpi_match_node(hdl); | |
249 | KASSERT(devnode != NULL); | 249 | KASSERT(devnode != NULL); | |
250 | 250 | |||
251 | /* Count child busses */ | 251 | /* Count child busses */ | |
252 | sc->sc_nbusses = 0; | 252 | sc->sc_nbusses = 0; | |
253 | SIMPLEQ_FOREACH(ad, &devnode->ad_child_head, ad_child_list) { | 253 | SIMPLEQ_FOREACH(ad, &devnode->ad_child_head, ad_child_list) { | |
254 | if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE || | 254 | if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE || | |
255 | !acpi_device_present(ad->ad_handle)) { | 255 | !acpi_device_present(ad->ad_handle)) { | |
256 | continue; | 256 | continue; | |
257 | } | 257 | } | |
258 | sc->sc_nbusses++; | 258 | sc->sc_nbusses++; | |
259 | } | 259 | } | |
260 | 260 | |||
261 | sc->sc_busses = kmem_zalloc(sizeof(*sc->sc_busses) * sc->sc_nbusses, | 261 | sc->sc_busses = kmem_zalloc(sizeof(*sc->sc_busses) * sc->sc_nbusses, | |
262 | KM_SLEEP); | 262 | KM_SLEEP); | |
263 | 263 | |||
264 | /* Attach child busses */ | 264 | /* Attach child busses */ | |
265 | idx = 0; | 265 | idx = 0; | |
266 | SIMPLEQ_FOREACH(ad, &devnode->ad_child_head, ad_child_list) { | 266 | SIMPLEQ_FOREACH(ad, &devnode->ad_child_head, ad_child_list) { | |
267 | if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE || | 267 | if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE || | |
268 | !acpi_device_present(ad->ad_handle)) { | 268 | !acpi_device_present(ad->ad_handle)) { | |
269 | continue; | 269 | continue; | |
270 | } | 270 | } | |
271 | iicmux_attach_bus(sc, (uintptr_t)ad->ad_handle, | 271 | iicmux_attach_bus(sc, (uintptr_t)ad->ad_handle, | |
272 | I2C_COOKIE_ACPI, idx); | 272 | I2C_COOKIE_ACPI, idx); | |
273 | idx++; | 273 | idx++; | |
274 | } | 274 | } | |
275 | } | 275 | } | |
276 | #endif | 276 | #endif | |
277 | 277 | |||
278 | void | 278 | void | |
279 | iicmux_attach(struct iicmux_softc * const sc) | 279 | iicmux_attach(struct iicmux_softc * const sc) | |
280 | { | 280 | { | |
281 | /* | 281 | /* | |
282 | * We expect sc->sc_handle, sc->sc_config, and sc->sc_i2c_parent | 282 | * We expect sc->sc_handle, sc->sc_config, and sc->sc_i2c_parent | |
283 | * to be initialized by the front-end. | 283 | * to be initialized by the front-end. | |
284 | */ | 284 | */ | |
285 | KASSERT(sc->sc_handle > 0); | 285 | KASSERT(sc->sc_handle > 0); | |
286 | KASSERT(sc->sc_config != NULL); | 286 | KASSERT(sc->sc_config != NULL); | |
287 | KASSERT(sc->sc_i2c_parent != NULL); | 287 | KASSERT(sc->sc_i2c_parent != NULL); | |
288 | 288 | |||
289 | /* | 289 | /* | |
290 | * Gather up all of the various bits of information needed | 290 | * Gather up all of the various bits of information needed | |
291 | * for this particular type of i2c mux. | 291 | * for this particular type of i2c mux. | |
292 | */ | 292 | */ | |
293 | sc->sc_mux_data = sc->sc_config->get_mux_info(sc); | 293 | sc->sc_mux_data = sc->sc_config->get_mux_info(sc); | |
294 | if (sc->sc_mux_data == NULL) { | 294 | if (sc->sc_mux_data == NULL) { | |
295 | aprint_error_dev(sc->sc_dev, "unable to get info for mux\n"); | 295 | aprint_error_dev(sc->sc_dev, "unable to get info for mux\n"); | |
296 | return; | 296 | return; | |
297 | } | 297 | } | |
298 | 298 | |||
299 | /* | 299 | /* | |
300 | * Do configuration method (OF, ACPI) specific setup. | 300 | * Do configuration method (OF, ACPI) specific setup. | |
301 | */ | 301 | */ | |
302 | switch (sc->sc_handletype) { | 302 | switch (sc->sc_handletype) { | |
303 | case I2C_COOKIE_OF: | 303 | case I2C_COOKIE_OF: | |
304 | iicmux_attach_fdt(sc); | 304 | iicmux_attach_fdt(sc); | |
305 | break; | 305 | break; | |
306 | #if NACPICA > 0 | 306 | #if NACPICA > 0 | |
307 | case I2C_COOKIE_ACPI: | 307 | case I2C_COOKIE_ACPI: | |
308 | iicmux_attach_acpi(sc); | 308 | iicmux_attach_acpi(sc); | |
309 | break; | 309 | break; | |
310 | #endif | 310 | #endif | |
311 | default: | 311 | default: | |
312 | aprint_error_dev(sc->sc_dev, "could not configure mux: " | 312 | aprint_error_dev(sc->sc_dev, "could not configure mux: " | |
313 | "handle type %u not supported\n", sc->sc_handletype); | 313 | "handle type %u not supported\n", sc->sc_handletype); | |
314 | break; | 314 | break; | |
315 | } | 315 | } | |
316 | } | 316 | } |