static ssize_t cec_logical_addr_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { ssize_t ret; u32 state; u16 addr; struct tegra_cec *cec; if (!buf || !count) return -EINVAL; cec = dev_get_drvdata(dev); if (!atomic_read(&cec->init_done)) return -EAGAIN; ret = kstrtou16(buf, 0, &addr); if (ret) return ret; dev_info(dev, "tegra_cec: set logical address: %x\n", (u32)addr); cec->logical_addr = addr; state = readl(cec->cec_base + TEGRA_CEC_HW_CONTROL); state &= ~TEGRA_CEC_HWCTRL_RX_LADDR_MASK; state |= TEGRA_CEC_HWCTRL_RX_LADDR(cec->logical_addr); writel(state, cec->cec_base + TEGRA_CEC_HW_CONTROL); return count; }
static int tegra_cec_adap_log_addr(struct cec_adapter *adap, u8 logical_addr) { struct tegra_cec *cec = adap->priv; u32 state = cec_read(cec, TEGRA_CEC_HW_CONTROL); if (logical_addr == CEC_LOG_ADDR_INVALID) state &= ~TEGRA_CEC_HWCTRL_RX_LADDR_MASK; else state |= TEGRA_CEC_HWCTRL_RX_LADDR((1 << logical_addr)); cec_write(cec, TEGRA_CEC_HW_CONTROL, state); return 0; }
static void tegra_cec_init(struct tegra_cec *cec) { cec->rx_wake = 0; cec->tx_wake = 1; cec->tx_buf_cnt = 0; cec->tx_buf_cur = 0; cec->tx_error = 0; dev_notice(cec->dev, "%s started\n", __func__); writel(0x00, cec->cec_base + TEGRA_CEC_HW_CONTROL); writel(0x00, cec->cec_base + TEGRA_CEC_INT_MASK); writel(0xffffffff, cec->cec_base + TEGRA_CEC_INT_STAT); msleep(1000); writel(0x00, cec->cec_base + TEGRA_CEC_SW_CONTROL); cec->logical_addr = TEGRA_CEC_HWCTRL_RX_LADDR_UNREG; writel(TEGRA_CEC_HWCTRL_RX_LADDR(cec->logical_addr) | TEGRA_CEC_HWCTRL_TX_NAK_MODE | TEGRA_CEC_HWCTRL_TX_RX_MODE, cec->cec_base + TEGRA_CEC_HW_CONTROL); writel(0x00, cec->cec_base + TEGRA_CEC_INPUT_FILTER); writel((0x7a << TEGRA_CEC_RX_TIMING_0_RX_START_BIT_MAX_LO_TIME_MASK) | (0x6d << TEGRA_CEC_RX_TIMING_0_RX_START_BIT_MIN_LO_TIME_MASK) | (0x93 << TEGRA_CEC_RX_TIMING_0_RX_START_BIT_MAX_DURATION_MASK) | (0x86 << TEGRA_CEC_RX_TIMING_0_RX_START_BIT_MIN_DURATION_MASK), cec->cec_base + TEGRA_CEC_RX_TIMING_0); writel((0x35 << TEGRA_CEC_RX_TIMING_1_RX_DATA_BIT_MAX_LO_TIME_MASK) | (0x21 << TEGRA_CEC_RX_TIMING_1_RX_DATA_BIT_SAMPLE_TIME_MASK) | (0x56 << TEGRA_CEC_RX_TIMING_1_RX_DATA_BIT_MAX_DURATION_MASK) | (0x40 << TEGRA_CEC_RX_TIMING_1_RX_DATA_BIT_MIN_DURATION_MASK), cec->cec_base + TEGRA_CEC_RX_TIMING_1); writel((0x50 << TEGRA_CEC_RX_TIMING_2_RX_END_OF_BLOCK_TIME_MASK), cec->cec_base + TEGRA_CEC_RX_TIMING_2); writel((0x74 << TEGRA_CEC_TX_TIMING_0_TX_START_BIT_LO_TIME_MASK) | (0x8d << TEGRA_CEC_TX_TIMING_0_TX_START_BIT_DURATION_MASK) | (0x08 << TEGRA_CEC_TX_TIMING_0_TX_BUS_XITION_TIME_MASK) | (0x71 << TEGRA_CEC_TX_TIMING_0_TX_BUS_ERROR_LO_TIME_MASK), cec->cec_base + TEGRA_CEC_TX_TIMING_0); writel((0x2f << TEGRA_CEC_TX_TIMING_1_TX_LO_DATA_BIT_LO_TIME_MASK) | (0x13 << TEGRA_CEC_TX_TIMING_1_TX_HI_DATA_BIT_LO_TIME_MASK) | (0x4b << TEGRA_CEC_TX_TIMING_1_TX_DATA_BIT_DURATION_MASK) | (0x21 << TEGRA_CEC_TX_TIMING_1_TX_ACK_NAK_BIT_SAMPLE_TIME_MASK), cec->cec_base + TEGRA_CEC_TX_TIMING_1); writel((0x07 << TEGRA_CEC_TX_TIMING_2_BUS_IDLE_TIME_ADDITIONAL_FRAME_MASK) | (0x05 << TEGRA_CEC_TX_TIMING_2_BUS_IDLE_TIME_NEW_FRAME_MASK) | (0x03 << TEGRA_CEC_TX_TIMING_2_BUS_IDLE_TIME_RETRY_FRAME_MASK), cec->cec_base + TEGRA_CEC_TX_TIMING_2); writel(TEGRA_CEC_INT_MASK_TX_REGISTER_UNDERRUN | TEGRA_CEC_INT_MASK_TX_FRAME_OR_BLOCK_NAKD | TEGRA_CEC_INT_MASK_TX_ARBITRATION_FAILED | TEGRA_CEC_INT_MASK_TX_BUS_ANOMALY_DETECTED | TEGRA_CEC_INT_MASK_TX_FRAME_TRANSMITTED | TEGRA_CEC_INT_MASK_RX_REGISTER_FULL | TEGRA_CEC_INT_MASK_RX_REGISTER_OVERRUN, cec->cec_base + TEGRA_CEC_INT_MASK); atomic_set(&cec->init_done, 1); wake_up_interruptible(&cec->init_waitq); dev_notice(cec->dev, "%s Done.\n", __func__); }