static int hci_pio_init()

in master/mipi-i3c-hci/pio.c [139:207]


static int hci_pio_init(struct i3c_hci *hci)
{
	struct hci_pio_data *pio;
	u32 val, size_val, rx_thresh, tx_thresh, ibi_val;

	pio = kzalloc(sizeof(*pio), GFP_KERNEL);
	if (!pio)
		return -ENOMEM;

	hci->io_data = pio;
	spin_lock_init(&pio->lock);

	size_val = pio_reg_read(QUEUE_SIZE);
	dev_info(&hci->master.dev, "CMD/RESP FIFO = %ld entries\n",
		 FIELD_GET(CR_QUEUE_SIZE, size_val));
	dev_info(&hci->master.dev, "IBI FIFO = %ld bytes\n",
		 4 * FIELD_GET(IBI_STATUS_SIZE, size_val));
	dev_info(&hci->master.dev, "RX data FIFO = %d bytes\n",
		 4 * (2 << FIELD_GET(RX_DATA_BUFFER_SIZE, size_val)));
	dev_info(&hci->master.dev, "TX data FIFO = %d bytes\n",
		 4 * (2 << FIELD_GET(TX_DATA_BUFFER_SIZE, size_val)));

	/*
	 * Let's initialize data thresholds to half of the actual FIFO size.
	 * The start thresholds aren't used (set to 0) as the FIFO is always
	 * serviced before the corresponding command is queued.
	 */
	rx_thresh = FIELD_GET(RX_DATA_BUFFER_SIZE, size_val);
	tx_thresh = FIELD_GET(TX_DATA_BUFFER_SIZE, size_val);
	if (hci->version_major == 1) {
		/* those are expressed as 2^[n+1), so just sub 1 if not 0 */
		if (rx_thresh)
			rx_thresh -= 1;
		if (tx_thresh)
			tx_thresh -= 1;
		pio->rx_thresh_size = 2 << rx_thresh;
		pio->tx_thresh_size = 2 << tx_thresh;
	} else {
		/* size is 2^(n+1) and threshold is 2^n i.e. already halved */
		pio->rx_thresh_size = 1 << rx_thresh;
		pio->tx_thresh_size = 1 << tx_thresh;
	}
	val = FIELD_PREP(DATA_RX_BUF_THLD,   rx_thresh) |
	      FIELD_PREP(DATA_TX_BUF_THLD,   tx_thresh);
	pio_reg_write(DATA_BUFFER_THLD_CTRL, val);

	/*
	 * Let's raise an interrupt as soon as there is one free cmd slot
	 * or one available response or IBI. For IBI data let's use half the
	 * IBI queue size within allowed bounds.
	 */
	ibi_val = FIELD_GET(IBI_STATUS_SIZE, size_val);
	pio->max_ibi_thresh = clamp_val(ibi_val/2, 1, 63);
	val = FIELD_PREP(QUEUE_IBI_STATUS_THLD, 1) |
	      FIELD_PREP(QUEUE_IBI_DATA_THLD, pio->max_ibi_thresh) |
	      FIELD_PREP(QUEUE_RESP_BUF_THLD, 1) |
	      FIELD_PREP(QUEUE_CMD_EMPTY_BUF_THLD, 1);
	pio_reg_write(QUEUE_THLD_CTRL, val);
	pio->reg_queue_thresh = val;

	/* Disable all IRQs but allow all status bits */
	pio_reg_write(INTR_SIGNAL_ENABLE, 0x0);
	pio_reg_write(INTR_STATUS_ENABLE, 0xffffffff);

	/* Always accept error interrupts (will be activated on first xfer) */
	pio->enabled_irqs = STAT_ALL_ERRORS;

	return 0;
}