Sat Jan 30 17:38:57 2021 UTC ()
Add the standard compat string from the Device Tree bindings.


(thorpej)
diff -r1.6 -r1.7 src/sys/dev/i2c/s390.c

cvs diff -r1.6 -r1.7 src/sys/dev/i2c/s390.c (switch to unified diff)

--- src/sys/dev/i2c/s390.c 2020/01/02 19:00:34 1.6
+++ src/sys/dev/i2c/s390.c 2021/01/30 17:38:57 1.7
@@ -1,230 +1,235 @@ @@ -1,230 +1,235 @@
1/* $NetBSD: s390.c,v 1.6 2020/01/02 19:00:34 thorpej Exp $ */ 1/* $NetBSD: s390.c,v 1.7 2021/01/30 17:38:57 thorpej Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2011 Frank Wille. 4 * Copyright (c) 2011 Frank Wille.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Written by Frank Wille for The NetBSD Project. 7 * Written by Frank Wille for The NetBSD Project.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE. 28 * POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31#include <sys/cdefs.h> 31#include <sys/cdefs.h>
32__KERNEL_RCSID(0, "$NetBSD: s390.c,v 1.6 2020/01/02 19:00:34 thorpej Exp $"); 32__KERNEL_RCSID(0, "$NetBSD: s390.c,v 1.7 2021/01/30 17:38:57 thorpej Exp $");
33 33
34#include <sys/param.h> 34#include <sys/param.h>
35#include <sys/systm.h> 35#include <sys/systm.h>
36#include <sys/device.h> 36#include <sys/device.h>
37#include <sys/conf.h> 37#include <sys/conf.h>
38 38
39#include <dev/clock_subr.h> 39#include <dev/clock_subr.h>
40 40
41#include <dev/i2c/i2cvar.h> 41#include <dev/i2c/i2cvar.h>
42#include <dev/i2c/s390reg.h> 42#include <dev/i2c/s390reg.h>
43 43
44struct s390rtc_softc { 44struct s390rtc_softc {
45 device_t sc_dev; 45 device_t sc_dev;
46 i2c_tag_t sc_tag; 46 i2c_tag_t sc_tag;
47 i2c_addr_t sc_addr; 47 i2c_addr_t sc_addr;
48 struct todr_chip_handle sc_todr; 48 struct todr_chip_handle sc_todr;
49}; 49};
50 50
51static int s390rtc_match(device_t, cfdata_t, void *); 51static int s390rtc_match(device_t, cfdata_t, void *);
52static void s390rtc_attach(device_t, device_t, void *); 52static void s390rtc_attach(device_t, device_t, void *);
53 53
54CFATTACH_DECL_NEW(s390rtc, sizeof(struct s390rtc_softc), 54CFATTACH_DECL_NEW(s390rtc, sizeof(struct s390rtc_softc),
55 s390rtc_match, s390rtc_attach, NULL, NULL); 55 s390rtc_match, s390rtc_attach, NULL, NULL);
56 56
57static int s390rtc_gettime_ymdhms(struct todr_chip_handle *, 57static int s390rtc_gettime_ymdhms(struct todr_chip_handle *,
58 struct clock_ymdhms *); 58 struct clock_ymdhms *);
59static int s390rtc_settime_ymdhms(struct todr_chip_handle *, 59static int s390rtc_settime_ymdhms(struct todr_chip_handle *,
60 struct clock_ymdhms *); 60 struct clock_ymdhms *);
61static int s390rtc_read(struct s390rtc_softc *, int, uint8_t *, size_t); 61static int s390rtc_read(struct s390rtc_softc *, int, uint8_t *, size_t);
62static int s390rtc_write(struct s390rtc_softc *, int, uint8_t *, size_t); 62static int s390rtc_write(struct s390rtc_softc *, int, uint8_t *, size_t);
63static uint8_t bitreverse(uint8_t); 63static uint8_t bitreverse(uint8_t);
64 64
 65static const struct device_compatible_entry compat_data[] = {
 66 { .compat = "sii,s35390a" },
 67 DEVICE_COMPAT_EOL
 68};
 69
65static int 70static int
66s390rtc_match(device_t parent, cfdata_t cf, void *arg) 71s390rtc_match(device_t parent, cfdata_t cf, void *arg)
67{ 72{
68 struct i2c_attach_args *ia = arg; 73 struct i2c_attach_args *ia = arg;
69 int match_result; 74 int match_result;
70 75
71 if (iic_use_direct_match(ia, cf, NULL, &match_result)) 76 if (iic_use_direct_match(ia, cf, compat_data, &match_result))
72 return match_result; 77 return match_result;
73  78
74 /* indirect config - check typical address */ 79 /* indirect config - check typical address */
75 if (ia->ia_addr == S390_ADDR) 80 if (ia->ia_addr == S390_ADDR)
76 return I2C_MATCH_ADDRESS_ONLY; 81 return I2C_MATCH_ADDRESS_ONLY;
77 82
78 return 0; 83 return 0;
79} 84}
80 85
81static void 86static void
82s390rtc_attach(device_t parent, device_t self, void *arg) 87s390rtc_attach(device_t parent, device_t self, void *arg)
83{ 88{
84 struct s390rtc_softc *sc = device_private(self); 89 struct s390rtc_softc *sc = device_private(self);
85 struct i2c_attach_args *ia = arg; 90 struct i2c_attach_args *ia = arg;
86 uint8_t reg[1]; 91 uint8_t reg[1];
87 92
88 aprint_naive(": Real-time Clock\n"); 93 aprint_naive(": Real-time Clock\n");
89 aprint_normal(": Seiko Instruments 35390A Real-time Clock\n"); 94 aprint_normal(": Seiko Instruments 35390A Real-time Clock\n");
90 95
91 sc->sc_tag = ia->ia_tag; 96 sc->sc_tag = ia->ia_tag;
92 sc->sc_addr = ia->ia_addr; 97 sc->sc_addr = ia->ia_addr;
93 sc->sc_dev = self; 98 sc->sc_dev = self;
94 99
95 /* Reset the chip and turn on 24h mode, after power-off or battery. */ 100 /* Reset the chip and turn on 24h mode, after power-off or battery. */
96 if (s390rtc_read(sc, S390_STATUS1, reg, sizeof(reg))) 101 if (s390rtc_read(sc, S390_STATUS1, reg, sizeof(reg)))
97 return; 102 return;
98 if (reg[0] & (S390_ST1_POC | S390_ST1_BLD)) { 103 if (reg[0] & (S390_ST1_POC | S390_ST1_BLD)) {
99 reg[0] |= S390_ST1_24H | S390_ST1_RESET; 104 reg[0] |= S390_ST1_24H | S390_ST1_RESET;
100 if (s390rtc_write(sc, S390_STATUS1, reg, sizeof(reg))) 105 if (s390rtc_write(sc, S390_STATUS1, reg, sizeof(reg)))
101 return; 106 return;
102 } 107 }
103 108
104 /* Disable the test mode, when enabled. */ 109 /* Disable the test mode, when enabled. */
105 if (s390rtc_read(sc, S390_STATUS2, reg, sizeof(reg))) 110 if (s390rtc_read(sc, S390_STATUS2, reg, sizeof(reg)))
106 return; 111 return;
107 if ((reg[0] & S390_ST2_TEST)) { 112 if ((reg[0] & S390_ST2_TEST)) {
108 reg[0] &= ~S390_ST2_TEST; 113 reg[0] &= ~S390_ST2_TEST;
109 if (s390rtc_write(sc, S390_STATUS2, reg, sizeof(reg))) 114 if (s390rtc_write(sc, S390_STATUS2, reg, sizeof(reg)))
110 return; 115 return;
111 } 116 }
112 117
113 sc->sc_todr.cookie = sc; 118 sc->sc_todr.cookie = sc;
114 sc->sc_todr.todr_gettime = NULL; 119 sc->sc_todr.todr_gettime = NULL;
115 sc->sc_todr.todr_settime = NULL; 120 sc->sc_todr.todr_settime = NULL;
116 sc->sc_todr.todr_gettime_ymdhms = s390rtc_gettime_ymdhms; 121 sc->sc_todr.todr_gettime_ymdhms = s390rtc_gettime_ymdhms;
117 sc->sc_todr.todr_settime_ymdhms = s390rtc_settime_ymdhms; 122 sc->sc_todr.todr_settime_ymdhms = s390rtc_settime_ymdhms;
118 sc->sc_todr.todr_setwen = NULL; 123 sc->sc_todr.todr_setwen = NULL;
119 todr_attach(&sc->sc_todr); 124 todr_attach(&sc->sc_todr);
120} 125}
121 126
122static int 127static int
123s390rtc_gettime_ymdhms(struct todr_chip_handle *ch, struct clock_ymdhms *dt) 128s390rtc_gettime_ymdhms(struct todr_chip_handle *ch, struct clock_ymdhms *dt)
124{ 129{
125 struct s390rtc_softc *sc = ch->cookie; 130 struct s390rtc_softc *sc = ch->cookie;
126 uint8_t bcd[S390_RT1_NBYTES]; 131 uint8_t bcd[S390_RT1_NBYTES];
127 int error; 132 int error;
128 133
129 if ((error = s390rtc_read(sc, S390_REALTIME1, bcd, 134 if ((error = s390rtc_read(sc, S390_REALTIME1, bcd,
130 S390_RT1_NBYTES)) != 0) 135 S390_RT1_NBYTES)) != 0)
131 return error; 136 return error;
132 137
133 /* 138 /*
134 * Convert the register values into something useable. 139 * Convert the register values into something useable.
135 */ 140 */
136 dt->dt_sec = bcdtobin(bcd[S390_RT1_SECOND]); 141 dt->dt_sec = bcdtobin(bcd[S390_RT1_SECOND]);
137 dt->dt_min = bcdtobin(bcd[S390_RT1_MINUTE]); 142 dt->dt_min = bcdtobin(bcd[S390_RT1_MINUTE]);
138 dt->dt_hour = bcdtobin(bcd[S390_RT1_HOUR] & 0x3f); 143 dt->dt_hour = bcdtobin(bcd[S390_RT1_HOUR] & 0x3f);
139 dt->dt_day = bcdtobin(bcd[S390_RT1_DAY]); 144 dt->dt_day = bcdtobin(bcd[S390_RT1_DAY]);
140 dt->dt_mon = bcdtobin(bcd[S390_RT1_MONTH]); 145 dt->dt_mon = bcdtobin(bcd[S390_RT1_MONTH]);
141 dt->dt_year = bcdtobin(bcd[S390_RT1_YEAR]) + 2000; 146 dt->dt_year = bcdtobin(bcd[S390_RT1_YEAR]) + 2000;
142 147
143 return 0; 148 return 0;
144} 149}
145 150
146static int 151static int
147s390rtc_settime_ymdhms(struct todr_chip_handle *ch, struct clock_ymdhms *dt) 152s390rtc_settime_ymdhms(struct todr_chip_handle *ch, struct clock_ymdhms *dt)
148{ 153{
149 struct s390rtc_softc *sc = ch->cookie; 154 struct s390rtc_softc *sc = ch->cookie;
150 uint8_t bcd[S390_RT1_NBYTES]; 155 uint8_t bcd[S390_RT1_NBYTES];
151 156
152 /* 157 /*
153 * Convert our time representation into something the S-xx390 158 * Convert our time representation into something the S-xx390
154 * can understand. 159 * can understand.
155 */ 160 */
156 bcd[S390_RT1_SECOND] = bintobcd(dt->dt_sec); 161 bcd[S390_RT1_SECOND] = bintobcd(dt->dt_sec);
157 bcd[S390_RT1_MINUTE] = bintobcd(dt->dt_min); 162 bcd[S390_RT1_MINUTE] = bintobcd(dt->dt_min);
158 bcd[S390_RT1_HOUR] = bintobcd(dt->dt_hour); 163 bcd[S390_RT1_HOUR] = bintobcd(dt->dt_hour);
159 bcd[S390_RT1_DAY] = bintobcd(dt->dt_day); 164 bcd[S390_RT1_DAY] = bintobcd(dt->dt_day);
160 bcd[S390_RT1_WDAY] = bintobcd(dt->dt_wday); 165 bcd[S390_RT1_WDAY] = bintobcd(dt->dt_wday);
161 bcd[S390_RT1_MONTH] = bintobcd(dt->dt_mon); 166 bcd[S390_RT1_MONTH] = bintobcd(dt->dt_mon);
162 bcd[S390_RT1_YEAR] = bintobcd(dt->dt_year % 100); 167 bcd[S390_RT1_YEAR] = bintobcd(dt->dt_year % 100);
163 168
164 return s390rtc_write(sc, S390_REALTIME1, bcd, S390_RT1_NBYTES); 169 return s390rtc_write(sc, S390_REALTIME1, bcd, S390_RT1_NBYTES);
165} 170}
166 171
167static int 172static int
168s390rtc_read(struct s390rtc_softc *sc, int reg, uint8_t *buf, size_t len) 173s390rtc_read(struct s390rtc_softc *sc, int reg, uint8_t *buf, size_t len)
169{ 174{
170 int i, error; 175 int i, error;
171 176
172 if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) { 177 if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) {
173 aprint_error_dev(sc->sc_dev, 178 aprint_error_dev(sc->sc_dev,
174 "%s: failed to acquire I2C bus\n", __func__); 179 "%s: failed to acquire I2C bus\n", __func__);
175 return error; 180 return error;
176 } 181 }
177 182
178 if ((error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 183 if ((error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
179 sc->sc_addr + reg, NULL, 0, buf, len, 0)) != 0) { 184 sc->sc_addr + reg, NULL, 0, buf, len, 0)) != 0) {
180 iic_release_bus(sc->sc_tag, 0); 185 iic_release_bus(sc->sc_tag, 0);
181 aprint_error_dev(sc->sc_dev, 186 aprint_error_dev(sc->sc_dev,
182 "%s: failed to read reg%d\n", __func__, reg); 187 "%s: failed to read reg%d\n", __func__, reg);
183 return error; 188 return error;
184 } 189 }
185 190
186 iic_release_bus(sc->sc_tag, 0); 191 iic_release_bus(sc->sc_tag, 0);
187 192
188 /* this chip returns each byte in reverse order */ 193 /* this chip returns each byte in reverse order */
189 for (i = 0; i < len; i++) 194 for (i = 0; i < len; i++)
190 buf[i] = bitreverse(buf[i]); 195 buf[i] = bitreverse(buf[i]);
191 196
192 return 0; 197 return 0;
193} 198}
194 199
195static int 200static int
196s390rtc_write(struct s390rtc_softc *sc, int reg, uint8_t *buf, size_t len) 201s390rtc_write(struct s390rtc_softc *sc, int reg, uint8_t *buf, size_t len)
197{ 202{
198 int i, error; 203 int i, error;
199 204
200 if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) { 205 if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) {
201 aprint_error_dev(sc->sc_dev, 206 aprint_error_dev(sc->sc_dev,
202 "%s: failed to acquire I2C bus\n", __func__); 207 "%s: failed to acquire I2C bus\n", __func__);
203 return error; 208 return error;
204 } 209 }
205 210
206 /* this chip expects each byte in reverse order */ 211 /* this chip expects each byte in reverse order */
207 for (i = 0; i < len; i++) 212 for (i = 0; i < len; i++)
208 buf[i] = bitreverse(buf[i]); 213 buf[i] = bitreverse(buf[i]);
209 214
210 if ((error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 215 if ((error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
211 sc->sc_addr + reg, NULL, 0, buf, len, 0)) != 0) { 216 sc->sc_addr + reg, NULL, 0, buf, len, 0)) != 0) {
212 iic_release_bus(sc->sc_tag, 0); 217 iic_release_bus(sc->sc_tag, 0);
213 aprint_error_dev(sc->sc_dev, 218 aprint_error_dev(sc->sc_dev,
214 "%s: failed to write reg%d\n", __func__, reg); 219 "%s: failed to write reg%d\n", __func__, reg);
215 return error; 220 return error;
216 } 221 }
217 222
218 iic_release_bus(sc->sc_tag, 0); 223 iic_release_bus(sc->sc_tag, 0);
219 return 0; 224 return 0;
220} 225}
221 226
222static uint8_t 227static uint8_t
223bitreverse(uint8_t x) 228bitreverse(uint8_t x)
224{ 229{
225 static unsigned char nibbletab[16] = { 230 static unsigned char nibbletab[16] = {
226 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 231 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
227 }; 232 };
228 233
229 return (nibbletab[x & 15] << 4) | nibbletab[x >> 4]; 234 return (nibbletab[x & 15] << 4) | nibbletab[x >> 4];
230} 235}