1/* $NetBSD: r2025.c,v 1.10 2020/01/02 19:00:34 thorpej Exp $ */ 2 3/*- 4 * Copyright (c) 2006 Shigeyuki Fukushima. 5 * All rights reserved. 6 * 7 * Written by Shigeyuki Fukushima. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer in the documentation and/or other materials provided 17 * with the distribution. 18 * 3. The name of the author may not be used to endorse or promote 19 * products derived from this software without specific prior 20 * written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 23 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 26 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 28 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35#include <sys/cdefs.h> 36__KERNEL_RCSID(0, "$NetBSD: r2025.c,v 1.10 2020/01/02 19:00:34 thorpej Exp $"); 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/device.h> 41#include <sys/kernel.h> 42#include <sys/fcntl.h> 43#include <sys/uio.h> 44#include <sys/conf.h> 45#include <sys/event.h> 46 47#include <dev/clock_subr.h> 48 49#include <dev/i2c/i2cvar.h> 50#include <dev/i2c/r2025reg.h> 51 52struct r2025rtc_softc { 53 device_t sc_dev; 54 i2c_tag_t sc_tag; 55 int sc_address; 56 int sc_open; 57 struct todr_chip_handle sc_todr; 58}; 59 60static void r2025rtc_attach(device_t, device_t, void *); 61static int r2025rtc_match(device_t, cfdata_t, void *); 62 63CFATTACH_DECL_NEW(r2025rtc, sizeof(struct r2025rtc_softc), 64 r2025rtc_match, r2025rtc_attach, NULL, NULL); 65 66static int r2025rtc_gettime_ymdhms(struct todr_chip_handle *, 67 struct clock_ymdhms *); 68static int r2025rtc_settime_ymdhms(struct todr_chip_handle *, 69 struct clock_ymdhms *); 70static int r2025rtc_reg_write(struct r2025rtc_softc *, int, uint8_t*, int); 71static int r2025rtc_reg_read(struct r2025rtc_softc *, int, uint8_t*, int); 72 73 74static int 75r2025rtc_match(device_t parent, cfdata_t cf, void *arg) 76{ 77 struct i2c_attach_args *ia = arg; 78 79 /* match only R2025 RTC devices */ 80 if (ia->ia_addr == R2025_ADDR) 81 return I2C_MATCH_ADDRESS_ONLY; 82 83 return 0; 84} 85 86static void 87r2025rtc_attach(device_t parent, device_t self, void *arg) 88{ 89 struct r2025rtc_softc *sc = device_private(self); 90 struct i2c_attach_args *ia = arg; 91 92 aprint_normal(": RICOH R2025S/D Real-time Clock\n"); 93 94 sc->sc_tag = ia->ia_tag; 95 sc->sc_address = ia->ia_addr; 96 sc->sc_dev = self; 97 sc->sc_open = 0; 98 sc->sc_todr.cookie = sc; 99 sc->sc_todr.todr_gettime = NULL; 100 sc->sc_todr.todr_settime = NULL; 101 sc->sc_todr.todr_gettime_ymdhms = r2025rtc_gettime_ymdhms; 102 sc->sc_todr.todr_settime_ymdhms = r2025rtc_settime_ymdhms; 103 sc->sc_todr.todr_setwen = NULL; 104 105 todr_attach(&sc->sc_todr); 106} 107 108static int 109r2025rtc_gettime_ymdhms(struct todr_chip_handle *ch, struct clock_ymdhms *dt) 110{ 111 struct r2025rtc_softc *sc = ch->cookie; 112 uint8_t rctrl; 113 uint8_t bcd[R2025_CLK_SIZE]; 114 int hour; 115 int error; 116 117 memset(dt, 0, sizeof(*dt)); 118 119 if ((error = r2025rtc_reg_read(sc, R2025_REG_CTRL1, &rctrl, 1)) != 0) { 120 aprint_error_dev(sc->sc_dev, 121 "r2025rtc_gettime: failed to read registers.\n"); 122 return error; 123 } 124 125 if ((error = r2025rtc_reg_read(sc, R2025_REG_SEC, &bcd[0], 126 R2025_CLK_SIZE)) != 0) { 127 aprint_error_dev(sc->sc_dev, 128 "r2025rtc_gettime: failed to read registers.\n"); 129 return error; 130 } 131 132 dt->dt_sec = bcdtobin(bcd[R2025_REG_SEC] & R2025_REG_SEC_MASK); 133 dt->dt_min = bcdtobin(bcd[R2025_REG_MIN] & R2025_REG_MIN_MASK); 134 hour = bcdtobin(bcd[R2025_REG_HOUR] & R2025_REG_HOUR_MASK); 135 if (rctrl & R2025_REG_CTRL1_H1224) { 136 dt->dt_hour = hour; 137 } else { 138 if (hour == 12) { 139 dt->dt_hour = 0; 140 } else if (hour == 32) { 141 dt->dt_hour = 12; 142 } else if (hour > 13) { 143 dt->dt_hour = (hour - 8); 144 } else { /* (hour < 12) */ 145 dt->dt_hour = hour; 146 } 147 } 148 dt->dt_wday = bcdtobin(bcd[R2025_REG_WDAY] & R2025_REG_WDAY_MASK); 149 dt->dt_day = bcdtobin(bcd[R2025_REG_DAY] & R2025_REG_DAY_MASK); 150 dt->dt_mon = bcdtobin(bcd[R2025_REG_MON] & R2025_REG_MON_MASK); 151 dt->dt_year = bcdtobin(bcd[R2025_REG_YEAR] & R2025_REG_YEAR_MASK) 152 + ((bcd[R2025_REG_MON] & R2025_REG_MON_Y1920) ? 2000 : 1900); 153 154 return 0; 155} 156 157static int 158r2025rtc_settime_ymdhms(struct todr_chip_handle *ch, struct clock_ymdhms *dt) 159{ 160 struct r2025rtc_softc *sc = ch->cookie; 161 uint8_t rctrl; 162 uint8_t bcd[R2025_CLK_SIZE]; 163 int error; 164 165 /* Y3K problem */ 166 if (dt->dt_year >= 3000) { 167 aprint_error_dev(sc->sc_dev, 168 "r2025rtc_settime: " 169 "RTC does not support year 3000 or over.\n"); 170 return EINVAL; 171 } 172 173 if ((error = r2025rtc_reg_read(sc, R2025_REG_CTRL1, &rctrl, 1)) != 0) { 174 aprint_error_dev(sc->sc_dev, 175 "r2025rtc_settime: failed to read register.\n"); 176 return error; 177 } 178 rctrl |= R2025_REG_CTRL1_H1224; 179 180 /* setup registers 0x00-0x06 (7 byte) */ 181 bcd[R2025_REG_SEC] = bintobcd(dt->dt_sec) & R2025_REG_SEC_MASK; 182 bcd[R2025_REG_MIN] = bintobcd(dt->dt_min) & R2025_REG_MIN_MASK; 183 bcd[R2025_REG_HOUR] = bintobcd(dt->dt_hour) & R2025_REG_HOUR_MASK; 184 bcd[R2025_REG_WDAY] = bintobcd(dt->dt_wday) & R2025_REG_WDAY_MASK; 185 bcd[R2025_REG_DAY] = bintobcd(dt->dt_day) & R2025_REG_DAY_MASK; 186 bcd[R2025_REG_MON] = (bintobcd(dt->dt_mon) & R2025_REG_MON_MASK) 187 | ((dt->dt_year >= 2000) ? R2025_REG_MON_Y1920 : 0); 188 bcd[R2025_REG_YEAR] = bintobcd(dt->dt_year % 100) & R2025_REG_YEAR_MASK; 189 190 /* Write RTC register */ 191 if ((error = r2025rtc_reg_write(sc, R2025_REG_CTRL1, &rctrl, 1)) != 0) { 192 aprint_error_dev(sc->sc_dev, 193 "r2025rtc_settime: failed to write registers.\n"); 194 return error; 195 } 196 if ((error = r2025rtc_reg_write(sc, R2025_REG_SEC, bcd, 197 R2025_CLK_SIZE)) != 0) { 198 aprint_error_dev(sc->sc_dev, 199 "r2025rtc_settime: failed to write registers.\n"); 200 return error; 201 } 202 203 return 0; 204} 205 206static int 207r2025rtc_reg_write(struct r2025rtc_softc *sc, int reg, uint8_t *val, int len) 208{ 209 int i; 210 uint8_t buf[1]; 211 uint8_t cmdbuf[1]; 212 int error; 213 214 if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) { 215 aprint_error_dev(sc->sc_dev, 216 "r2025rtc_reg_write: failed to acquire I2C bus\n"); 217 return error; 218 } 219 220 for (i = 0 ; i < len ; i++) { 221 cmdbuf[0] = (((reg + i) << 4) & 0xf0); 222 buf[0] = val[i]; 223 if ((error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 224 sc->sc_address, cmdbuf, 1, buf, 1, 225 0)) != 0) { 226 iic_release_bus(sc->sc_tag, 0); 227 aprint_error_dev(sc->sc_dev, "r2025rtc_reg_write: " 228 "failed to write registers\n"); 229 return error; 230 } 231 } 232 233 iic_release_bus(sc->sc_tag, 0); 234 235 return 0; 236} 237 238static int 239r2025rtc_reg_read(struct r2025rtc_softc *sc, int reg, uint8_t *val, int len) 240{ 241 int i; 242 uint8_t buf[1]; 243 uint8_t cmdbuf[1]; 244 int error; 245 246 if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) { 247 aprint_error_dev(sc->sc_dev, 248 "r2025rtc_reg_read: failed to acquire I2C bus\n"); 249 return error; 250 } 251 252 for (i = 0 ; i < len ; i++) { 253 cmdbuf[0] = (((reg + i) << 4) & 0xf0); 254 buf[0] = 0; 255 if ((error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 256 sc->sc_address, cmdbuf, 1, buf, 1, 257 0)) != 0) { 258 iic_release_bus(sc->sc_tag, 0); 259 aprint_error_dev(sc->sc_dev, "r2025rtc_reg_read: " 260 "failed to read registers\n"); 261 return error; 262 } 263 264 *(val + i) = buf[0]; 265 } 266 267 iic_release_bus(sc->sc_tag, 0); 268 269 return 0; 270} 271