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