162306a36Sopenharmony_ci/* SPDX-License-Identifier: BSD-3-Clause */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2020, MIPI Alliance, Inc. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Author: Nicolas Pitre <npitre@baylibre.com> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Common HCI stuff 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#ifndef HCI_H 1162306a36Sopenharmony_ci#define HCI_H 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* Handy logging macro to save on line length */ 1562306a36Sopenharmony_ci#define DBG(x, ...) pr_devel("%s: " x "\n", __func__, ##__VA_ARGS__) 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* 32-bit word aware bit and mask macros */ 1862306a36Sopenharmony_ci#define W0_MASK(h, l) GENMASK((h) - 0, (l) - 0) 1962306a36Sopenharmony_ci#define W1_MASK(h, l) GENMASK((h) - 32, (l) - 32) 2062306a36Sopenharmony_ci#define W2_MASK(h, l) GENMASK((h) - 64, (l) - 64) 2162306a36Sopenharmony_ci#define W3_MASK(h, l) GENMASK((h) - 96, (l) - 96) 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* Same for single bit macros (trailing _ to align with W*_MASK width) */ 2462306a36Sopenharmony_ci#define W0_BIT_(x) BIT((x) - 0) 2562306a36Sopenharmony_ci#define W1_BIT_(x) BIT((x) - 32) 2662306a36Sopenharmony_ci#define W2_BIT_(x) BIT((x) - 64) 2762306a36Sopenharmony_ci#define W3_BIT_(x) BIT((x) - 96) 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistruct hci_cmd_ops; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* Our main structure */ 3362306a36Sopenharmony_cistruct i3c_hci { 3462306a36Sopenharmony_ci struct i3c_master_controller master; 3562306a36Sopenharmony_ci void __iomem *base_regs; 3662306a36Sopenharmony_ci void __iomem *DAT_regs; 3762306a36Sopenharmony_ci void __iomem *DCT_regs; 3862306a36Sopenharmony_ci void __iomem *RHS_regs; 3962306a36Sopenharmony_ci void __iomem *PIO_regs; 4062306a36Sopenharmony_ci void __iomem *EXTCAPS_regs; 4162306a36Sopenharmony_ci void __iomem *AUTOCMD_regs; 4262306a36Sopenharmony_ci void __iomem *DEBUG_regs; 4362306a36Sopenharmony_ci const struct hci_io_ops *io; 4462306a36Sopenharmony_ci void *io_data; 4562306a36Sopenharmony_ci const struct hci_cmd_ops *cmd; 4662306a36Sopenharmony_ci atomic_t next_cmd_tid; 4762306a36Sopenharmony_ci u32 caps; 4862306a36Sopenharmony_ci unsigned int quirks; 4962306a36Sopenharmony_ci unsigned int DAT_entries; 5062306a36Sopenharmony_ci unsigned int DAT_entry_size; 5162306a36Sopenharmony_ci void *DAT_data; 5262306a36Sopenharmony_ci unsigned int DCT_entries; 5362306a36Sopenharmony_ci unsigned int DCT_entry_size; 5462306a36Sopenharmony_ci u8 version_major; 5562306a36Sopenharmony_ci u8 version_minor; 5662306a36Sopenharmony_ci u8 revision; 5762306a36Sopenharmony_ci u32 vendor_mipi_id; 5862306a36Sopenharmony_ci u32 vendor_version_id; 5962306a36Sopenharmony_ci u32 vendor_product_id; 6062306a36Sopenharmony_ci void *vendor_data; 6162306a36Sopenharmony_ci}; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/* 6562306a36Sopenharmony_ci * Structure to represent a master initiated transfer. 6662306a36Sopenharmony_ci * The rnw, data and data_len fields must be initialized before calling any 6762306a36Sopenharmony_ci * hci->cmd->*() method. The cmd method will initialize cmd_desc[] and 6862306a36Sopenharmony_ci * possibly modify (clear) the data field. Then xfer->cmd_desc[0] can 6962306a36Sopenharmony_ci * be augmented with CMD_0_ROC and/or CMD_0_TOC. 7062306a36Sopenharmony_ci * The completion field needs to be initialized before queueing with 7162306a36Sopenharmony_ci * hci->io->queue_xfer(), and requires CMD_0_ROC to be set. 7262306a36Sopenharmony_ci */ 7362306a36Sopenharmony_cistruct hci_xfer { 7462306a36Sopenharmony_ci u32 cmd_desc[4]; 7562306a36Sopenharmony_ci u32 response; 7662306a36Sopenharmony_ci bool rnw; 7762306a36Sopenharmony_ci void *data; 7862306a36Sopenharmony_ci unsigned int data_len; 7962306a36Sopenharmony_ci unsigned int cmd_tid; 8062306a36Sopenharmony_ci struct completion *completion; 8162306a36Sopenharmony_ci union { 8262306a36Sopenharmony_ci struct { 8362306a36Sopenharmony_ci /* PIO specific */ 8462306a36Sopenharmony_ci struct hci_xfer *next_xfer; 8562306a36Sopenharmony_ci struct hci_xfer *next_data; 8662306a36Sopenharmony_ci struct hci_xfer *next_resp; 8762306a36Sopenharmony_ci unsigned int data_left; 8862306a36Sopenharmony_ci u32 data_word_before_partial; 8962306a36Sopenharmony_ci }; 9062306a36Sopenharmony_ci struct { 9162306a36Sopenharmony_ci /* DMA specific */ 9262306a36Sopenharmony_ci dma_addr_t data_dma; 9362306a36Sopenharmony_ci int ring_number; 9462306a36Sopenharmony_ci int ring_entry; 9562306a36Sopenharmony_ci }; 9662306a36Sopenharmony_ci }; 9762306a36Sopenharmony_ci}; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic inline struct hci_xfer *hci_alloc_xfer(unsigned int n) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci return kcalloc(n, sizeof(struct hci_xfer), GFP_KERNEL); 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic inline void hci_free_xfer(struct hci_xfer *xfer, unsigned int n) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci kfree(xfer); 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci/* This abstracts PIO vs DMA operations */ 11162306a36Sopenharmony_cistruct hci_io_ops { 11262306a36Sopenharmony_ci bool (*irq_handler)(struct i3c_hci *hci, unsigned int mask); 11362306a36Sopenharmony_ci int (*queue_xfer)(struct i3c_hci *hci, struct hci_xfer *xfer, int n); 11462306a36Sopenharmony_ci bool (*dequeue_xfer)(struct i3c_hci *hci, struct hci_xfer *xfer, int n); 11562306a36Sopenharmony_ci int (*request_ibi)(struct i3c_hci *hci, struct i3c_dev_desc *dev, 11662306a36Sopenharmony_ci const struct i3c_ibi_setup *req); 11762306a36Sopenharmony_ci void (*free_ibi)(struct i3c_hci *hci, struct i3c_dev_desc *dev); 11862306a36Sopenharmony_ci void (*recycle_ibi_slot)(struct i3c_hci *hci, struct i3c_dev_desc *dev, 11962306a36Sopenharmony_ci struct i3c_ibi_slot *slot); 12062306a36Sopenharmony_ci int (*init)(struct i3c_hci *hci); 12162306a36Sopenharmony_ci void (*cleanup)(struct i3c_hci *hci); 12262306a36Sopenharmony_ci}; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ciextern const struct hci_io_ops mipi_i3c_hci_pio; 12562306a36Sopenharmony_ciextern const struct hci_io_ops mipi_i3c_hci_dma; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci/* Our per device master private data */ 12962306a36Sopenharmony_cistruct i3c_hci_dev_data { 13062306a36Sopenharmony_ci int dat_idx; 13162306a36Sopenharmony_ci void *ibi_data; 13262306a36Sopenharmony_ci}; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci/* list of quirks */ 13662306a36Sopenharmony_ci#define HCI_QUIRK_RAW_CCC BIT(1) /* CCC framing must be explicit */ 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci/* global functions */ 14062306a36Sopenharmony_civoid mipi_i3c_hci_resume(struct i3c_hci *hci); 14162306a36Sopenharmony_civoid mipi_i3c_hci_pio_reset(struct i3c_hci *hci); 14262306a36Sopenharmony_civoid mipi_i3c_hci_dct_index_reset(struct i3c_hci *hci); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci#endif 145