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