1 /*- 2 * Copyright (c) 2019 Michal Meloun <mmel@FreeBSD.org> 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #include <sys/cdefs.h> 27 /* 28 * MAX77620 PMIC driver 29 */ 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/bus.h> 34 #include <sys/gpio.h> 35 #include <sys/kernel.h> 36 #include <sys/module.h> 37 #include <sys/malloc.h> 38 #include <sys/rman.h> 39 #include <sys/sx.h> 40 41 #include <machine/bus.h> 42 43 #include <dev/extres/regulator/regulator.h> 44 #include <dev/fdt/fdt_pinctrl.h> 45 #include <dev/gpio/gpiobusvar.h> 46 #include <dev/iicbus/iiconf.h> 47 #include <dev/iicbus/iicbus.h> 48 #include <dev/ofw/ofw_bus.h> 49 #include <dev/ofw/ofw_bus_subr.h> 50 51 #include <dt-bindings/mfd/max77620.h> 52 53 #include "clock_if.h" 54 #include "regdev_if.h" 55 56 #include "max77620.h" 57 58 static struct ofw_compat_data compat_data[] = { 59 {"maxim,max77620", 1}, 60 {NULL, 0}, 61 }; 62 63 #define LOCK(_sc) sx_xlock(&(_sc)->lock) 64 #define UNLOCK(_sc) sx_xunlock(&(_sc)->lock) 65 #define LOCK_INIT(_sc) sx_init(&(_sc)->lock, "max77620") 66 #define LOCK_DESTROY(_sc) sx_destroy(&(_sc)->lock); 67 #define ASSERT_LOCKED(_sc) sx_assert(&(_sc)->lock, SA_XLOCKED); 68 #define ASSERT_UNLOCKED(_sc) sx_assert(&(_sc)->lock, SA_UNLOCKED); 69 70 #define MAX77620_DEVICE_ID 0x0C 71 72 /* 73 * Raw register access function. 74 */ 75 int 76 max77620_read(struct max77620_softc *sc, uint8_t reg, uint8_t *val) 77 { 78 uint8_t addr; 79 int rv; 80 struct iic_msg msgs[2] = { 81 {0, IIC_M_WR, 1, &addr}, 82 {0, IIC_M_RD, 1, val}, 83 }; 84 85 msgs[0].slave = sc->bus_addr; 86 msgs[1].slave = sc->bus_addr; 87 addr = reg; 88 89 rv = iicbus_transfer(sc->dev, msgs, 2); 90 if (rv != 0) { 91 device_printf(sc->dev, 92 "Error when reading reg 0x%02X, rv: %d\n", reg, rv); 93 return (EIO); 94 } 95 96 return (0); 97 } 98 99 int max77620_read_buf(struct max77620_softc *sc, uint8_t reg, uint8_t *buf, 100 size_t size) 101 { 102 uint8_t addr; 103 int rv; 104 struct iic_msg msgs[2] = { 105 {0, IIC_M_WR, 1, &addr}, 106 {0, IIC_M_RD, size, buf}, 107 }; 108 109 msgs[0].slave = sc->bus_addr; 110 msgs[1].slave = sc->bus_addr; 111 addr = reg; 112 113 rv = iicbus_transfer(sc->dev, msgs, 2); 114 if (rv != 0) { 115 device_printf(sc->dev, 116 "Error when reading reg 0x%02X, rv: %d\n", reg, rv); 117 return (EIO); 118 } 119 120 return (0); 121 } 122 123 int 124 max77620_write(struct max77620_softc *sc, uint8_t reg, uint8_t val) 125 { 126 uint8_t data[2]; 127 int rv; 128 129 struct iic_msg msgs[1] = { 130 {0, IIC_M_WR, 2, data}, 131 }; 132 133 msgs[0].slave = sc->bus_addr; 134 data[0] = reg; 135 data[1] = val; 136 137 rv = iicbus_transfer(sc->dev, msgs, 1); 138 if (rv != 0) { 139 device_printf(sc->dev, 140 "Error when writing reg 0x%02X, rv: %d\n", reg, rv); 141 return (EIO); 142 } 143 return (0); 144 } 145 146 int 147 max77620_write_buf(struct max77620_softc *sc, uint8_t reg, uint8_t *buf, 148 size_t size) 149 { 150 uint8_t data[1]; 151 int rv; 152 struct iic_msg msgs[2] = { 153 {0, IIC_M_WR, 1, data}, 154 {0, IIC_M_WR | IIC_M_NOSTART, size, buf}, 155 }; 156 157 msgs[0].slave = sc->bus_addr; 158 msgs[1].slave = sc->bus_addr; 159 data[0] = reg; 160 161 rv = iicbus_transfer(sc->dev, msgs, 2); 162 if (rv != 0) { 163 device_printf(sc->dev, 164 "Error when writing reg 0x%02X, rv: %d\n", reg, rv); 165 return (EIO); 166 } 167 return (0); 168 } 169 170 int 171 max77620_modify(struct max77620_softc *sc, uint8_t reg, uint8_t clear, 172 uint8_t set) 173 { 174 uint8_t val; 175 int rv; 176 177 rv = max77620_read(sc, reg, &val); 178 if (rv != 0) 179 return (rv); 180 181 val &= ~clear; 182 val |= set; 183 184 rv = max77620_write(sc, reg, val); 185 if (rv != 0) 186 return (rv); 187 188 return (0); 189 } 190 191 static int 192 max77620_parse_fps(struct max77620_softc *sc, int id, phandle_t node) 193 { 194 int val; 195 196 if (OF_getencprop(node, "maxim,shutdown-fps-time-period-us", &val, 197 sizeof(val)) >= 0) { 198 val = min(val, MAX77620_FPS_PERIOD_MAX_US); 199 val = max(val, MAX77620_FPS_PERIOD_MIN_US); 200 sc->shutdown_fps[id] = val; 201 } 202 if (OF_getencprop(node, "maxim,suspend-fps-time-period-us", &val, 203 sizeof(val)) >= 0) { 204 val = min(val, MAX77620_FPS_PERIOD_MAX_US); 205 val = max(val, MAX77620_FPS_PERIOD_MIN_US); 206 sc->suspend_fps[id] = val; 207 } 208 if (OF_getencprop(node, "maxim,fps-event-source", &val, 209 sizeof(val)) >= 0) { 210 if (val > 2) { 211 device_printf(sc->dev, "Invalid 'fps-event-source' " 212 "value: %d\n", val); 213 return (EINVAL); 214 } 215 sc->event_source[id] = val; 216 } 217 return (0); 218 } 219 220 static int 221 max77620_parse_fdt(struct max77620_softc *sc, phandle_t node) 222 { 223 phandle_t fpsnode; 224 char fps_name[6]; 225 int i, rv; 226 227 for (i = 0; i < MAX77620_FPS_COUNT; i++) { 228 sc->shutdown_fps[i] = -1; 229 sc->suspend_fps[i] = -1; 230 sc->event_source[i] = -1; 231 } 232 233 fpsnode = ofw_bus_find_child(node, "fps"); 234 if (fpsnode > 0) { 235 for (i = 0; i < MAX77620_FPS_COUNT; i++) { 236 sprintf(fps_name, "fps%d", i); 237 node = ofw_bus_find_child(node, fps_name); 238 if (node <= 0) 239 continue; 240 rv = max77620_parse_fps(sc, i, node); 241 if (rv != 0) 242 return (rv); 243 } 244 } 245 return (0); 246 } 247 248 static int 249 max77620_get_version(struct max77620_softc *sc) 250 { 251 uint8_t buf[6]; 252 int i; 253 int rv; 254 255 /* Verify ID string (5 bytes ). */ 256 for (i = 0; i <= 6; i++) { 257 rv = RD1(sc, MAX77620_REG_CID0 + i , buf + i); 258 if (rv != 0) { 259 device_printf(sc->dev, "Cannot read chip ID: %d\n", rv); 260 return (ENXIO); 261 } 262 } 263 if (bootverbose) { 264 device_printf(sc->dev, 265 " ID: [0x%02X, 0x%02X, 0x%02X, 0x%02X]\n", 266 buf[0], buf[1], buf[2], buf[3]); 267 } 268 device_printf(sc->dev, " MAX77620 version - OTP: 0x%02X, ES: 0x%02X\n", 269 buf[4], buf[5]); 270 271 return (0); 272 } 273 274 static uint8_t 275 max77620_encode_fps_period(struct max77620_softc *sc, int val) 276 { 277 uint8_t i; 278 int period; 279 280 period = MAX77620_FPS_PERIOD_MIN_US; 281 for (i = 0; i < 7; i++) { 282 if (period >= val) 283 return (i); 284 period *= 2; 285 } 286 return (i); 287 } 288 289 static int 290 max77620_init(struct max77620_softc *sc) 291 { 292 uint8_t mask, val, tmp; 293 int i, rv; 294 295 mask = 0; 296 val = 0; 297 for (i = 0; i < MAX77620_FPS_COUNT; i++) { 298 if (sc->shutdown_fps[i] != -1) { 299 mask |= MAX77620_FPS_TIME_PERIOD_MASK; 300 tmp = max77620_encode_fps_period(sc, 301 sc->shutdown_fps[i]); 302 val |= (tmp << MAX77620_FPS_TIME_PERIOD_SHIFT) & 303 MAX77620_FPS_TIME_PERIOD_MASK; 304 } 305 306 if (sc->event_source[i] != -1) { 307 mask |= MAX77620_FPS_EN_SRC_MASK; 308 tmp = sc->event_source[i]; 309 val |= (tmp << MAX77620_FPS_EN_SRC_SHIFT) & 310 MAX77620_FPS_EN_SRC_MASK; 311 if (sc->event_source[i] == 2) { 312 mask |= MAX77620_FPS_ENFPS_SW_MASK; 313 val |= MAX77620_FPS_ENFPS_SW; 314 } 315 316 } 317 rv = RM1(sc, MAX77620_REG_FPS_CFG0 + i, mask, val); 318 if (rv != 0) { 319 device_printf(sc->dev, "I/O error: %d\n", rv); 320 return (ENXIO); 321 } 322 } 323 324 /* Global mask interrupts */ 325 rv = RM1(sc, MAX77620_REG_INTENLBT, 0x81, 0x81); 326 rv = RM1(sc, MAX77620_REG_IRQTOPM, 0x81, 0x81); 327 if (rv != 0) 328 return (ENXIO); 329 return (0); 330 } 331 #ifdef notyet 332 static void 333 max77620_intr(void *arg) 334 { 335 struct max77620_softc *sc; 336 uint8_t intenlbt, intlbt, irqtop, irqtopm, irqsd, irqmasksd; 337 uint8_t irq_lvl2_l0_7, irq_lvl2_l8, irq_lvl2_gpio, irq_msk_l0_7, irq_msk_l8; 338 uint8_t onoffirq, onoffirqm; 339 340 sc = (struct max77620_softc *)arg; 341 /* XXX Finish temperature alarms. */ 342 RD1(sc, MAX77620_REG_INTENLBT, &intenlbt); 343 RD1(sc, MAX77620_REG_INTLBT, &intlbt); 344 345 RD1(sc, MAX77620_REG_IRQTOP, &irqtop); 346 RD1(sc, MAX77620_REG_IRQTOPM, &irqtopm); 347 RD1(sc, MAX77620_REG_IRQSD, &irqsd); 348 RD1(sc, MAX77620_REG_IRQMASKSD, &irqmasksd); 349 RD1(sc, MAX77620_REG_IRQ_LVL2_L0_7, &irq_lvl2_l0_7); 350 RD1(sc, MAX77620_REG_IRQ_MSK_L0_7, &irq_msk_l0_7); 351 RD1(sc, MAX77620_REG_IRQ_LVL2_L8, &irq_lvl2_l8); 352 RD1(sc, MAX77620_REG_IRQ_MSK_L8, &irq_msk_l8); 353 RD1(sc, MAX77620_REG_IRQ_LVL2_GPIO, &irq_lvl2_gpio); 354 RD1(sc, MAX77620_REG_ONOFFIRQ, &onoffirq); 355 RD1(sc, MAX77620_REG_ONOFFIRQM, &onoffirqm); 356 printf("%s: intlbt: 0x%02X, intenlbt: 0x%02X\n", __func__, intlbt, intenlbt); 357 printf("%s: irqtop: 0x%02X, irqtopm: 0x%02X\n", __func__, irqtop, irqtopm); 358 printf("%s: irqsd: 0x%02X, irqmasksd: 0x%02X\n", __func__, irqsd, irqmasksd); 359 printf("%s: onoffirq: 0x%02X, onoffirqm: 0x%02X\n", __func__, onoffirq, onoffirqm); 360 printf("%s: irq_lvl2_l0_7: 0x%02X, irq_msk_l0_7: 0x%02X\n", __func__, irq_lvl2_l0_7, irq_msk_l0_7); 361 printf("%s: irq_lvl2_l8: 0x%02X, irq_msk_l8: 0x%02X\n", __func__, irq_lvl2_l8, irq_msk_l8); 362 printf("%s: irq_lvl2_gpio: 0x%02X\n", __func__, irq_lvl2_gpio); 363 } 364 #endif 365 366 static int 367 max77620_probe(device_t dev) 368 { 369 370 if (!ofw_bus_status_okay(dev)) 371 return (ENXIO); 372 373 if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) 374 return (ENXIO); 375 376 device_set_desc(dev, "MAX77620 PMIC"); 377 return (BUS_PROBE_DEFAULT); 378 } 379 380 static int 381 max77620_attach(device_t dev) 382 { 383 struct max77620_softc *sc; 384 int rv, rid; 385 phandle_t node; 386 387 sc = device_get_softc(dev); 388 sc->dev = dev; 389 sc->bus_addr = iicbus_get_addr(dev); 390 node = ofw_bus_get_node(sc->dev); 391 rv = 0; 392 LOCK_INIT(sc); 393 394 rid = 0; 395 sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 396 RF_ACTIVE); 397 #ifdef notyet /* Interrupt parent is not implemented */ 398 if (sc->irq_res == NULL) { 399 device_printf(dev, "Cannot allocate interrupt.\n"); 400 rv = ENXIO; 401 goto fail; 402 } 403 #endif 404 rv = max77620_parse_fdt(sc, node); 405 if (rv != 0) 406 goto fail; 407 408 rv = max77620_get_version(sc); 409 if (rv != 0) 410 goto fail; 411 412 rv = max77620_init(sc); 413 if (rv != 0) 414 goto fail; 415 rv = max77620_regulator_attach(sc, node); 416 if (rv != 0) 417 goto fail; 418 rv = max77620_gpio_attach(sc, node); 419 if (rv != 0) 420 goto fail; 421 422 rv = max77620_rtc_create(sc, node); 423 if (rv != 0) 424 goto fail; 425 426 fdt_pinctrl_register(dev, NULL); 427 fdt_pinctrl_configure_by_name(dev, "default"); 428 429 /* Setup interrupt. */ 430 #ifdef notyet 431 rv = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, 432 NULL, max77620_intr, sc, &sc->irq_h); 433 if (rv) { 434 device_printf(dev, "Cannot setup interrupt.\n"); 435 goto fail; 436 } 437 #endif 438 return (bus_generic_attach(dev)); 439 440 fail: 441 if (sc->irq_h != NULL) 442 bus_teardown_intr(dev, sc->irq_res, sc->irq_h); 443 if (sc->irq_res != NULL) 444 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); 445 LOCK_DESTROY(sc); 446 return (rv); 447 } 448 449 static int 450 max77620_detach(device_t dev) 451 { 452 struct max77620_softc *sc; 453 454 sc = device_get_softc(dev); 455 if (sc->irq_h != NULL) 456 bus_teardown_intr(dev, sc->irq_res, sc->irq_h); 457 if (sc->irq_res != NULL) 458 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); 459 LOCK_DESTROY(sc); 460 461 return (bus_generic_detach(dev)); 462 } 463 464 static phandle_t 465 max77620_gpio_get_node(device_t bus, device_t dev) 466 { 467 468 /* We only have one child, the GPIO bus, which needs our own node. */ 469 return (ofw_bus_get_node(bus)); 470 } 471 472 static device_method_t max77620_methods[] = { 473 /* Device interface */ 474 DEVMETHOD(device_probe, max77620_probe), 475 DEVMETHOD(device_attach, max77620_attach), 476 DEVMETHOD(device_detach, max77620_detach), 477 478 /* Regdev interface */ 479 DEVMETHOD(regdev_map, max77620_regulator_map), 480 481 /* GPIO protocol interface */ 482 DEVMETHOD(gpio_get_bus, max77620_gpio_get_bus), 483 DEVMETHOD(gpio_pin_max, max77620_gpio_pin_max), 484 DEVMETHOD(gpio_pin_getname, max77620_gpio_pin_getname), 485 DEVMETHOD(gpio_pin_getflags, max77620_gpio_pin_getflags), 486 DEVMETHOD(gpio_pin_getcaps, max77620_gpio_pin_getcaps), 487 DEVMETHOD(gpio_pin_setflags, max77620_gpio_pin_setflags), 488 DEVMETHOD(gpio_pin_get, max77620_gpio_pin_get), 489 DEVMETHOD(gpio_pin_set, max77620_gpio_pin_set), 490 DEVMETHOD(gpio_pin_toggle, max77620_gpio_pin_toggle), 491 DEVMETHOD(gpio_map_gpios, max77620_gpio_map_gpios), 492 493 /* fdt_pinctrl interface */ 494 DEVMETHOD(fdt_pinctrl_configure, max77620_pinmux_configure), 495 496 /* ofw_bus interface */ 497 DEVMETHOD(ofw_bus_get_node, max77620_gpio_get_node), 498 499 DEVMETHOD_END 500 }; 501 502 static DEFINE_CLASS_0(gpio, max77620_driver, max77620_methods, 503 sizeof(struct max77620_softc)); 504 EARLY_DRIVER_MODULE(max77620, iicbus, max77620_driver, NULL, NULL, 74); 505