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;
}