Lines Matching +full:slave +full:- +full:mode
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
36 * The driver is implemented as an interrupt-driven state machine,
37 * supporting both master and slave mode.
63 /* CS5536 PCI-ISA ID. */
146 struct iic_msg *msg; /* Current master mode message. */
148 uint8_t *data; /* Current master mode data byte. */
150 int error; /* Last master mode error. */
168 #define GLXIIC_LOCK(_sc) mtx_lock(&_sc->mtx)
169 #define GLXIIC_UNLOCK(_sc) mtx_unlock(&_sc->mtx)
171 mtx_init(&_sc->mtx, device_get_nameunit(_sc->dev), "glxiic", MTX_DEF)
173 mtx_sleep(_sc, &_sc->mtx, IICPRI, "glxiic", 0)
175 #define GLXIIC_LOCK_DESTROY(_sc) mtx_destroy(&_sc->mtx);
176 #define GLXIIC_ASSERT_LOCKED(_sc) mtx_assert(&_sc->mtx, MA_OWNED);
287 if (device_find_child(parent, driver->name, -1) != NULL) in glxiic_identify()
291 if (device_add_child(parent, driver->name, -1) == NULL) in glxiic_identify()
318 sc->dev = dev; in glxiic_attach()
319 sc->state = GLXIIC_STATE_IDLE; in glxiic_attach()
323 callout_init_mtx(&sc->callout, &sc->mtx, 0); in glxiic_attach()
325 sc->smb_rid = PCIR_BAR(0); in glxiic_attach()
326 sc->smb_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->smb_rid, in glxiic_attach()
328 if (sc->smb_res == NULL) { in glxiic_attach()
334 sc->gpio_rid = PCIR_BAR(1); in glxiic_attach()
335 sc->gpio_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, in glxiic_attach()
336 &sc->gpio_rid, RF_SHAREABLE | RF_ACTIVE); in glxiic_attach()
337 if (sc->gpio_res == NULL) { in glxiic_attach()
348 sc->old_irq = GLXIIC_MAP_TO_SMB_IRQ(irq_map); in glxiic_attach()
361 } else if (sc->old_irq != 0) { in glxiic_attach()
365 irq = sc->old_irq; in glxiic_attach()
376 sc->irq_rid = 0; in glxiic_attach()
377 sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid, in glxiic_attach()
379 if (sc->irq_res == NULL) { in glxiic_attach()
385 error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, in glxiic_attach()
386 NULL, glxiic_intr, sc, &(sc->irq_handler)); in glxiic_attach()
393 if ((sc->iicbus = device_add_child(dev, "iicbus", -1)) == NULL) { in glxiic_attach()
402 sc->timeout = GLXIIC_DEFAULT_TIMEOUT; in glxiic_attach()
404 "timeout", CTLFLAG_RWTUN, &sc->timeout, 0, in glxiic_attach()
415 callout_drain(&sc->callout); in glxiic_attach()
417 if (sc->iicbus != NULL) in glxiic_attach()
418 device_delete_child(dev, sc->iicbus); in glxiic_attach()
419 if (sc->smb_res != NULL) { in glxiic_attach()
421 bus_release_resource(dev, SYS_RES_IOPORT, sc->smb_rid, in glxiic_attach()
422 sc->smb_res); in glxiic_attach()
424 if (sc->gpio_res != NULL) { in glxiic_attach()
426 bus_release_resource(dev, SYS_RES_IOPORT, sc->gpio_rid, in glxiic_attach()
427 sc->gpio_res); in glxiic_attach()
429 if (sc->irq_handler != NULL) in glxiic_attach()
430 bus_teardown_intr(dev, sc->irq_res, sc->irq_handler); in glxiic_attach()
431 if (sc->irq_res != NULL) in glxiic_attach()
432 bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, in glxiic_attach()
433 sc->irq_res); in glxiic_attach()
436 glxiic_smb_map_interrupt(sc->old_irq); in glxiic_attach()
455 if (sc->iicbus != NULL) in glxiic_detach()
456 error = device_delete_child(dev, sc->iicbus); in glxiic_detach()
459 callout_drain(&sc->callout); in glxiic_detach()
461 if (sc->smb_res != NULL) { in glxiic_detach()
463 bus_release_resource(dev, SYS_RES_IOPORT, sc->smb_rid, in glxiic_detach()
464 sc->smb_res); in glxiic_detach()
466 if (sc->gpio_res != NULL) { in glxiic_detach()
468 bus_release_resource(dev, SYS_RES_IOPORT, sc->gpio_rid, in glxiic_detach()
469 sc->gpio_res); in glxiic_detach()
471 if (sc->irq_handler != NULL) in glxiic_detach()
472 bus_teardown_intr(dev, sc->irq_res, sc->irq_handler); in glxiic_detach()
473 if (sc->irq_res != NULL) in glxiic_detach()
474 bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, in glxiic_detach()
475 sc->irq_res); in glxiic_detach()
478 glxiic_smb_map_interrupt(sc->old_irq); in glxiic_detach()
492 status = bus_read_1(sc->smb_res, GLXIIC_SMB_STS); in glxiic_read_status_locked()
495 bus_write_1(sc->smb_res, GLXIIC_SMB_STS, (GLXIIC_SMB_STS_SLVSTP_BIT | in glxiic_read_status_locked()
511 ctrl1 = bus_read_1(sc->smb_res, GLXIIC_SMB_CTRL1); in glxiic_stop_locked()
512 bus_write_1(sc->smb_res, GLXIIC_SMB_CTRL1, in glxiic_stop_locked()
516 * Perform a dummy read of SDA in master receive mode to clear in glxiic_stop_locked()
521 bus_read_1(sc->smb_res, GLXIIC_SMB_SDA); in glxiic_stop_locked()
525 bus_write_1(sc->smb_res, GLXIIC_SMB_STS, in glxiic_stop_locked()
538 GLXIIC_DEBUG_LOG("timeout in state %d", sc->state); in glxiic_timeout()
540 if (glxiic_state_table[sc->state].master) { in glxiic_timeout()
541 sc->error = IIC_ETIMEOUT; in glxiic_timeout()
545 iicbus_intr(sc->iicbus, INTR_ERROR, &error); in glxiic_timeout()
549 glxiic_smb_enable(sc, IIC_UNKNOWN, sc->addr); in glxiic_timeout()
559 callout_reset_sbt(&sc->callout, SBT_1MS * sc->timeout, 0, in glxiic_start_timeout_locked()
570 callout_stop(&sc->callout); in glxiic_set_state_locked()
571 else if (sc->timeout > 0) in glxiic_set_state_locked()
574 sc->state = state; in glxiic_set_state_locked()
584 ctrl_sts = bus_read_1(sc->smb_res, GLXIIC_SMB_CTRL_STS); in glxiic_handle_slave_match_locked()
588 addr = sc->addr | LSB; in glxiic_handle_slave_match_locked()
592 addr = sc->addr & ~LSB; in glxiic_handle_slave_match_locked()
596 iicbus_intr(sc->iicbus, INTR_START, &addr); in glxiic_handle_slave_match_locked()
600 iicbus_intr(sc->iicbus, INTR_GENERAL, &addr); in glxiic_handle_slave_match_locked()
602 GLXIIC_DEBUG_LOG("unknown slave match"); in glxiic_handle_slave_match_locked()
635 GLXIIC_DEBUG_LOG("bus error in slave tx"); in glxiic_state_slave_tx_callback()
640 iicbus_intr(sc->iicbus, INTR_STOP, NULL); in glxiic_state_slave_tx_callback()
646 iicbus_intr(sc->iicbus, INTR_NOACK, NULL); in glxiic_state_slave_tx_callback()
651 /* Handle repeated start in slave mode. */ in glxiic_state_slave_tx_callback()
656 GLXIIC_DEBUG_LOG("not awaiting data in slave tx"); in glxiic_state_slave_tx_callback()
660 iicbus_intr(sc->iicbus, INTR_TRANSMIT, &data); in glxiic_state_slave_tx_callback()
661 bus_write_1(sc->smb_res, GLXIIC_SMB_SDA, data); in glxiic_state_slave_tx_callback()
676 GLXIIC_DEBUG_LOG("bus error in slave rx"); in glxiic_state_slave_rx_callback()
681 iicbus_intr(sc->iicbus, INTR_STOP, NULL); in glxiic_state_slave_rx_callback()
687 /* Handle repeated start in slave mode. */ in glxiic_state_slave_rx_callback()
692 GLXIIC_DEBUG_LOG("no pending data in slave rx"); in glxiic_state_slave_rx_callback()
696 data = bus_read_1(sc->smb_res, GLXIIC_SMB_SDA); in glxiic_state_slave_rx_callback()
697 iicbus_intr(sc->iicbus, INTR_RECEIVE, &data); in glxiic_state_slave_rx_callback()
707 uint8_t slave; in glxiic_state_master_addr_callback() local
727 if ((sc->msg->flags & IIC_M_RD) != 0) { in glxiic_state_master_addr_callback()
728 slave = sc->msg->slave | LSB; in glxiic_state_master_addr_callback()
731 slave = sc->msg->slave & ~LSB; in glxiic_state_master_addr_callback()
735 sc->data = sc->msg->buf; in glxiic_state_master_addr_callback()
736 sc->ndata = sc->msg->len; in glxiic_state_master_addr_callback()
738 /* Handle address-only transfer. */ in glxiic_state_master_addr_callback()
739 if (sc->ndata == 0) in glxiic_state_master_addr_callback()
742 bus_write_1(sc->smb_res, GLXIIC_SMB_SDA, slave); in glxiic_state_master_addr_callback()
744 if ((sc->msg->flags & IIC_M_RD) != 0 && sc->ndata == 1) { in glxiic_state_master_addr_callback()
745 /* Last byte from slave, set NACK. */ in glxiic_state_master_addr_callback()
746 ctrl1 = bus_read_1(sc->smb_res, GLXIIC_SMB_CTRL1); in glxiic_state_master_addr_callback()
747 bus_write_1(sc->smb_res, GLXIIC_SMB_CTRL1, in glxiic_state_master_addr_callback()
771 GLXIIC_DEBUG_LOG("slave nack in master tx"); in glxiic_state_master_tx_callback()
776 bus_write_1(sc->smb_res, GLXIIC_SMB_STS, in glxiic_state_master_tx_callback()
785 bus_write_1(sc->smb_res, GLXIIC_SMB_SDA, *sc->data++); in glxiic_state_master_tx_callback()
786 if (--sc->ndata == 0) in glxiic_state_master_tx_callback()
812 GLXIIC_DEBUG_LOG("slave nack in rx"); in glxiic_state_master_rx_callback()
818 bus_write_1(sc->smb_res, GLXIIC_SMB_STS, in glxiic_state_master_rx_callback()
828 *sc->data++ = bus_read_1(sc->smb_res, GLXIIC_SMB_SDA); in glxiic_state_master_rx_callback()
829 if (--sc->ndata == 0) { in glxiic_state_master_rx_callback()
832 return (glxiic_state_table[sc->state].callback(sc, status)); in glxiic_state_master_rx_callback()
835 if (sc->ndata == 1) { in glxiic_state_master_rx_callback()
836 /* Last byte from slave, set NACK. */ in glxiic_state_master_rx_callback()
837 ctrl1 = bus_read_1(sc->smb_res, GLXIIC_SMB_CTRL1); in glxiic_state_master_rx_callback()
838 bus_write_1(sc->smb_res, GLXIIC_SMB_CTRL1, in glxiic_state_master_rx_callback()
865 GLXIIC_DEBUG_LOG("slave nack in master stop"); in glxiic_state_master_stop_callback()
869 if (--sc->nmsgs > 0) { in glxiic_state_master_stop_callback()
871 if ((sc->msg->flags & IIC_M_NOSTOP) == 0) { in glxiic_state_master_stop_callback()
875 ctrl1 = bus_read_1(sc->smb_res, GLXIIC_SMB_CTRL1); in glxiic_state_master_stop_callback()
876 bus_write_1(sc->smb_res, GLXIIC_SMB_CTRL1, in glxiic_state_master_stop_callback()
880 sc->msg++; in glxiic_state_master_stop_callback()
885 sc->error = IIC_NOERR; in glxiic_state_master_stop_callback()
909 error = glxiic_state_table[sc->state].callback(sc, status); in glxiic_intr()
912 if (glxiic_state_table[sc->state].master) { in glxiic_intr()
915 sc->error = error; in glxiic_intr()
919 iicbus_intr(sc->iicbus, INTR_ERROR, &data); in glxiic_intr()
938 *oldaddr = sc->addr; in glxiic_reset()
939 sc->addr = addr; in glxiic_reset()
945 if (glxiic_state_table[sc->state].master) { in glxiic_reset()
946 sc->error = IIC_ESTATUS; in glxiic_reset()
967 if (sc->state != GLXIIC_STATE_IDLE) { in glxiic_transfer()
972 sc->msg = msgs; in glxiic_transfer()
973 sc->nmsgs = nmsgs; in glxiic_transfer()
977 ctrl1 = bus_read_1(sc->smb_res, GLXIIC_SMB_CTRL1); in glxiic_transfer()
978 bus_write_1(sc->smb_res, GLXIIC_SMB_CTRL1, in glxiic_transfer()
982 error = sc->error; in glxiic_transfer()
995 /* Protect the read-modify-write operation. */ in glxiic_smb_map_interrupt()
1014 bus_write_4(sc->gpio_res, GLXIIC_GPIOL_IN_AUX1_SEL, in glxiic_gpio_enable()
1016 bus_write_4(sc->gpio_res, GLXIIC_GPIOL_OUT_AUX1_SEL, in glxiic_gpio_enable()
1024 bus_write_4(sc->gpio_res, GLXIIC_GPIOL_OUT_AUX1_SEL, in glxiic_gpio_disable()
1026 bus_write_4(sc->gpio_res, GLXIIC_GPIOL_IN_AUX1_SEL, in glxiic_gpio_disable()
1039 sc->sclfrq = GLXIIC_SLOW; in glxiic_smb_enable()
1042 sc->sclfrq = GLXIIC_FAST; in glxiic_smb_enable()
1045 sc->sclfrq = GLXIIC_FASTEST; in glxiic_smb_enable()
1054 bus_write_2(sc->smb_res, GLXIIC_SMB_CTRL2, in glxiic_smb_enable()
1055 GLXIIC_SCLFRQ(sc->sclfrq) | GLXIIC_SMB_CTRL2_EN_BIT); in glxiic_smb_enable()
1061 bus_write_1(sc->smb_res, GLXIIC_SMB_ADDR, in glxiic_smb_enable()
1064 bus_write_1(sc->smb_res, GLXIIC_SMB_ADDR, 0); in glxiic_smb_enable()
1068 bus_write_1(sc->smb_res, GLXIIC_SMB_CTRL1, in glxiic_smb_enable()
1077 sclfrq = bus_read_2(sc->smb_res, GLXIIC_SMB_CTRL2); in glxiic_smb_disable()
1078 bus_write_2(sc->smb_res, GLXIIC_SMB_CTRL2, in glxiic_smb_disable()