aml8726_rtc.c revision 303975
1/*- 2 * Copyright 2013-2015 John Wehle <john@feith.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27/* 28 * Amlogic aml8726 RTC driver. 29 */ 30 31#include <sys/cdefs.h> 32__FBSDID("$FreeBSD: releng/11.0/sys/arm/amlogic/aml8726/aml8726_rtc.c 283181 2015-05-21 07:01:08Z ganbold $"); 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/bus.h> 37#include <sys/clock.h> 38#include <sys/kernel.h> 39#include <sys/module.h> 40#include <sys/lock.h> 41#include <sys/mutex.h> 42#include <sys/resource.h> 43#include <sys/rman.h> 44 45#include <sys/time.h> 46 47#include <machine/bus.h> 48#include <machine/cpu.h> 49 50#include <dev/fdt/fdt_common.h> 51#include <dev/ofw/ofw_bus.h> 52#include <dev/ofw/ofw_bus_subr.h> 53 54#include <arm/amlogic/aml8726/aml8726_soc.h> 55 56#include "clock_if.h" 57 58/* 59 * The RTC initialization various slightly between the different chips. 60 * 61 * aml8726-m1 aml8726-m3 aml8726-m6 (and later) 62 * init-always true true false 63 * xo-init 0x0004 0x3c0a 0x180a 64 * gpo-init 0x100000 0x100000 0x500000 65 */ 66 67struct aml8726_rtc_init { 68 boolean_t always; 69 uint16_t xo; 70 uint32_t gpo; 71}; 72 73struct aml8726_rtc_softc { 74 device_t dev; 75 struct aml8726_rtc_init init; 76 struct resource * res[2]; 77 struct mtx mtx; 78}; 79 80static struct resource_spec aml8726_rtc_spec[] = { 81 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 82 { SYS_RES_IRQ, 0, RF_ACTIVE }, 83 { -1, 0 } 84}; 85 86#define AML_RTC_LOCK(sc) mtx_lock_spin(&(sc)->mtx) 87#define AML_RTC_UNLOCK(sc) mtx_unlock_spin(&(sc)->mtx) 88#define AML_RTC_LOCK_INIT(sc) \ 89 mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ 90 "rtc", MTX_SPIN) 91#define AML_RTC_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx); 92 93#define AML_RTC_0_REG 0 94#define AML_RTC_SCLK (1 << 0) 95#define AML_RTC_SDI (1 << 2) 96#define AML_RTC_SEN (1 << 1) 97#define AML_RTC_AS (1 << 17) 98#define AML_RTC_ABSY (1 << 22) 99#define AML_RTC_IRQ_DIS (1 << 12) 100#define AML_RTC_1_REG 4 101#define AML_RTC_SDO (1 << 0) 102#define AML_RTC_SRDY (1 << 1) 103#define AML_RTC_2_REG 8 104#define AML_RTC_3_REG 12 105#define AML_RTC_MSR_BUSY (1 << 20) 106#define AML_RTC_MSR_CA (1 << 17) 107#define AML_RTC_MSR_DURATION_EN (1 << 16) 108#define AML_RTC_MSR_DURATION_MASK 0xffff 109#define AML_RTC_MSR_DURATION_SHIFT 0 110#define AML_RTC_4_REG 16 111 112#define AML_RTC_TIME_SREG 0 113#define AML_RTC_GPO_SREG 1 114#define AML_RTC_GPO_LEVEL (1 << 24) 115#define AML_RTC_GPO_BUSY (1 << 23) 116#define AML_RTC_GPO_ACTIVE_HIGH (1 << 22) 117#define AML_RTC_GPO_CMD_MASK (3 << 20) 118#define AML_RTC_GPO_CMD_SHIFT 20 119#define AML_RTC_GPO_CMD_NOW (1 << 20) 120#define AML_RTC_GPO_CMD_COUNT (2 << 20) 121#define AML_RTC_GPO_CMD_PULSE (3 << 20) 122#define AML_RTC_GPO_CNT_MASK 0xfffff 123#define AML_RTC_GPO_CNT_SHIFT 0 124 125#define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) 126#define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) 127#define CSR_BARRIER(sc, reg) bus_barrier((sc)->res[0], reg, 4, \ 128 (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)) 129 130static int 131aml8726_rtc_start_transfer(struct aml8726_rtc_softc *sc) 132{ 133 unsigned i; 134 135 /* idle the serial interface */ 136 CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) & 137 ~(AML_RTC_SCLK | AML_RTC_SEN | AML_RTC_SDI))); 138 139 CSR_BARRIER(sc, AML_RTC_0_REG); 140 141 /* see if it is ready for a new cycle */ 142 for (i = 40; i; i--) { 143 DELAY(5); 144 if ( (CSR_READ_4(sc, AML_RTC_1_REG) & AML_RTC_SRDY) ) 145 break; 146 } 147 148 if (i == 0) 149 return (EIO); 150 151 /* start the cycle */ 152 CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) | 153 AML_RTC_SEN)); 154 155 return (0); 156} 157 158static inline void 159aml8726_rtc_sclk_pulse(struct aml8726_rtc_softc *sc) 160{ 161 162 DELAY(5); 163 164 CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) | 165 AML_RTC_SCLK)); 166 167 CSR_BARRIER(sc, AML_RTC_0_REG); 168 169 DELAY(5); 170 171 CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) & 172 ~AML_RTC_SCLK)); 173 174 CSR_BARRIER(sc, AML_RTC_0_REG); 175} 176 177static inline void 178aml8726_rtc_send_bit(struct aml8726_rtc_softc *sc, unsigned bit) 179{ 180 181 if (bit) { 182 CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) | 183 AML_RTC_SDI)); 184 } else { 185 CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) & 186 ~AML_RTC_SDI)); 187 } 188 189 aml8726_rtc_sclk_pulse(sc); 190} 191 192static inline void 193aml8726_rtc_send_addr(struct aml8726_rtc_softc *sc, u_char addr) 194{ 195 unsigned mask; 196 197 for (mask = 1 << 3; mask; mask >>= 1) { 198 if (mask == 1) { 199 /* final bit indicates read / write mode */ 200 CSR_WRITE_4(sc, AML_RTC_0_REG, 201 (CSR_READ_4(sc, AML_RTC_0_REG) & ~AML_RTC_SEN)); 202 } 203 aml8726_rtc_send_bit(sc, (addr & mask)); 204 } 205} 206 207static inline void 208aml8726_rtc_send_data(struct aml8726_rtc_softc *sc, uint32_t data) 209{ 210 unsigned mask; 211 212 for (mask = 1U << 31; mask; mask >>= 1) 213 aml8726_rtc_send_bit(sc, (data & mask)); 214} 215 216static inline void 217aml8726_rtc_recv_data(struct aml8726_rtc_softc *sc, uint32_t *dp) 218{ 219 uint32_t data; 220 unsigned i; 221 222 data = 0; 223 224 for (i = 0; i < 32; i++) { 225 aml8726_rtc_sclk_pulse(sc); 226 data <<= 1; 227 data |= (CSR_READ_4(sc, AML_RTC_1_REG) & AML_RTC_SDO) ? 1 : 0; 228 } 229 230 *dp = data; 231} 232 233static int 234aml8726_rtc_sreg_read(struct aml8726_rtc_softc *sc, u_char sreg, uint32_t *val) 235{ 236 u_char addr; 237 int error; 238 239 /* read is indicated by lsb = 0 */ 240 addr = (sreg << 1) | 0; 241 242 error = aml8726_rtc_start_transfer(sc); 243 244 if (error) 245 return (error); 246 247 aml8726_rtc_send_addr(sc, addr); 248 aml8726_rtc_recv_data(sc, val); 249 250 return (0); 251} 252 253static int 254aml8726_rtc_sreg_write(struct aml8726_rtc_softc *sc, u_char sreg, uint32_t val) 255{ 256 u_char addr; 257 int error; 258 259 /* write is indicated by lsb = 1 */ 260 addr = (sreg << 1) | 1; 261 262 error = aml8726_rtc_start_transfer(sc); 263 264 if (error) 265 return (error); 266 267 aml8726_rtc_send_data(sc, val); 268 aml8726_rtc_send_addr(sc, addr); 269 270 return (0); 271} 272 273static int 274aml8726_rtc_initialize(struct aml8726_rtc_softc *sc) 275{ 276 int error; 277 unsigned i; 278 279 /* idle the serial interface */ 280 CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) & 281 ~(AML_RTC_SCLK | AML_RTC_SEN | AML_RTC_SDI))); 282 283 CSR_BARRIER(sc, AML_RTC_0_REG); 284 285 /* see if it is ready for a new cycle */ 286 for (i = 40; i; i--) { 287 DELAY(5); 288 if ( (CSR_READ_4(sc, AML_RTC_1_REG) & AML_RTC_SRDY) ) 289 break; 290 } 291 292 if (sc->init.always == TRUE || (CSR_READ_4(sc, AML_RTC_1_REG) & 293 AML_RTC_SRDY) == 0) { 294 295 /* 296 * The RTC has a 16 bit initialization register. The upper 297 * bits can be written directly. The lower bits are written 298 * through a shift register. 299 */ 300 301 CSR_WRITE_4(sc, AML_RTC_4_REG, ((sc->init.xo >> 8) & 0xff)); 302 303 CSR_WRITE_4(sc, AML_RTC_0_REG, 304 ((CSR_READ_4(sc, AML_RTC_0_REG) & 0xffffff) | 305 ((uint32_t)(sc->init.xo & 0xff) << 24) | AML_RTC_AS | 306 AML_RTC_IRQ_DIS)); 307 308 while ((CSR_READ_4(sc, AML_RTC_0_REG) & AML_RTC_ABSY) != 0) 309 cpu_spinwait(); 310 311 DELAY(2); 312 313 error = aml8726_rtc_sreg_write(sc, AML_RTC_GPO_SREG, 314 sc->init.gpo); 315 316 if (error) 317 return (error); 318 } 319 320 return (0); 321} 322 323static int 324aml8726_rtc_check_xo(struct aml8726_rtc_softc *sc) 325{ 326 uint32_t now, previous; 327 int i; 328 329 /* 330 * The RTC is driven by a 32.768khz clock meaning it's period 331 * is roughly 30.5 us. Check that it's working (implying the 332 * RTC could contain a valid value) by enabling count always 333 * and seeing if the value changes after 200 us (per RTC User 334 * Guide ... presumably the extra time is to cover XO startup). 335 */ 336 337 CSR_WRITE_4(sc, AML_RTC_3_REG, (CSR_READ_4(sc, AML_RTC_3_REG) | 338 AML_RTC_MSR_CA)); 339 340 previous = CSR_READ_4(sc, AML_RTC_2_REG); 341 342 for (i = 0; i < 4; i++) { 343 DELAY(50); 344 now = CSR_READ_4(sc, AML_RTC_2_REG); 345 if (now != previous) 346 break; 347 } 348 349 CSR_WRITE_4(sc, AML_RTC_3_REG, (CSR_READ_4(sc, AML_RTC_3_REG) & 350 ~AML_RTC_MSR_CA)); 351 352 if (now == previous) 353 return (EINVAL); 354 355 return (0); 356} 357 358static int 359aml8726_rtc_probe(device_t dev) 360{ 361 362 if (!ofw_bus_status_okay(dev)) 363 return (ENXIO); 364 365 if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-rtc")) 366 return (ENXIO); 367 368 device_set_desc(dev, "Amlogic aml8726 RTC"); 369 370 return (BUS_PROBE_DEFAULT); 371} 372 373static int 374aml8726_rtc_attach(device_t dev) 375{ 376 struct aml8726_rtc_softc *sc = device_get_softc(dev); 377 378 sc->dev = dev; 379 380 switch (aml8726_soc_hw_rev) { 381 case AML_SOC_HW_REV_M3: 382 sc->init.always = true; 383 sc->init.xo = 0x3c0a; 384 sc->init.gpo = 0x100000; 385 break; 386 case AML_SOC_HW_REV_M6: 387 case AML_SOC_HW_REV_M8: 388 case AML_SOC_HW_REV_M8B: 389 sc->init.always = false; 390 sc->init.xo = 0x180a; 391 sc->init.gpo = 0x500000; 392 break; 393 default: 394 device_printf(dev, "unsupported SoC\n"); 395 return (ENXIO); 396 /* NOTREACHED */ 397 } 398 399 if (bus_alloc_resources(dev, aml8726_rtc_spec, sc->res)) { 400 device_printf(dev, "can not allocate resources for device\n"); 401 return (ENXIO); 402 } 403 404 aml8726_rtc_initialize(sc); 405 406 if (aml8726_rtc_check_xo(sc) != 0) { 407 device_printf(dev, "crystal oscillator check failed\n"); 408 409 bus_release_resources(dev, aml8726_rtc_spec, sc->res); 410 411 return (ENXIO); 412 } 413 414 AML_RTC_LOCK_INIT(sc); 415 416 clock_register(dev, 1000000); 417 418 return (0); 419} 420 421static int 422aml8726_rtc_detach(device_t dev) 423{ 424 425 return (EBUSY); 426} 427 428static int 429aml8726_rtc_gettime(device_t dev, struct timespec *ts) 430{ 431 struct aml8726_rtc_softc *sc = device_get_softc(dev); 432 uint32_t sec; 433 int error; 434 435 AML_RTC_LOCK(sc); 436 437 error = aml8726_rtc_sreg_read(sc, AML_RTC_TIME_SREG, &sec); 438 439 AML_RTC_UNLOCK(sc); 440 441 ts->tv_sec = sec; 442 ts->tv_nsec = 0; 443 444 return (error); 445} 446 447static int 448aml8726_rtc_settime(device_t dev, struct timespec *ts) 449{ 450 struct aml8726_rtc_softc *sc = device_get_softc(dev); 451 uint32_t sec; 452 int error; 453 454 sec = ts->tv_sec; 455 456 /* Accuracy is only one second. */ 457 if (ts->tv_nsec >= 500000000) 458 sec++; 459 460 AML_RTC_LOCK(sc); 461 462 error = aml8726_rtc_sreg_write(sc, AML_RTC_TIME_SREG, sec); 463 464 AML_RTC_UNLOCK(sc); 465 466 return (error); 467} 468 469static device_method_t aml8726_rtc_methods[] = { 470 /* Device interface */ 471 DEVMETHOD(device_probe, aml8726_rtc_probe), 472 DEVMETHOD(device_attach, aml8726_rtc_attach), 473 DEVMETHOD(device_detach, aml8726_rtc_detach), 474 475 /* Clock interface */ 476 DEVMETHOD(clock_gettime, aml8726_rtc_gettime), 477 DEVMETHOD(clock_settime, aml8726_rtc_settime), 478 479 DEVMETHOD_END 480}; 481 482static driver_t aml8726_rtc_driver = { 483 "rtc", 484 aml8726_rtc_methods, 485 sizeof(struct aml8726_rtc_softc), 486}; 487 488static devclass_t aml8726_rtc_devclass; 489 490DRIVER_MODULE(rtc, simplebus, aml8726_rtc_driver, aml8726_rtc_devclass, 0, 0); 491