18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ 28c2ecf20Sopenharmony_ci/* Copyright(c) 2015-17 Intel Corporation. */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#ifndef __SDW_BUS_H 58c2ecf20Sopenharmony_ci#define __SDW_BUS_H 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#define DEFAULT_BANK_SWITCH_TIMEOUT 3000 88c2ecf20Sopenharmony_ci#define DEFAULT_PROBE_TIMEOUT 2000 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_ACPI) 118c2ecf20Sopenharmony_ciint sdw_acpi_find_slaves(struct sdw_bus *bus); 128c2ecf20Sopenharmony_ci#else 138c2ecf20Sopenharmony_cistatic inline int sdw_acpi_find_slaves(struct sdw_bus *bus) 148c2ecf20Sopenharmony_ci{ 158c2ecf20Sopenharmony_ci return -ENOTSUPP; 168c2ecf20Sopenharmony_ci} 178c2ecf20Sopenharmony_ci#endif 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ciint sdw_of_find_slaves(struct sdw_bus *bus); 208c2ecf20Sopenharmony_civoid sdw_extract_slave_id(struct sdw_bus *bus, 218c2ecf20Sopenharmony_ci u64 addr, struct sdw_slave_id *id); 228c2ecf20Sopenharmony_ciint sdw_slave_add(struct sdw_bus *bus, struct sdw_slave_id *id, 238c2ecf20Sopenharmony_ci struct fwnode_handle *fwnode); 248c2ecf20Sopenharmony_ciint sdw_master_device_add(struct sdw_bus *bus, struct device *parent, 258c2ecf20Sopenharmony_ci struct fwnode_handle *fwnode); 268c2ecf20Sopenharmony_ciint sdw_master_device_del(struct sdw_bus *bus); 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 298c2ecf20Sopenharmony_civoid sdw_bus_debugfs_init(struct sdw_bus *bus); 308c2ecf20Sopenharmony_civoid sdw_bus_debugfs_exit(struct sdw_bus *bus); 318c2ecf20Sopenharmony_civoid sdw_slave_debugfs_init(struct sdw_slave *slave); 328c2ecf20Sopenharmony_civoid sdw_slave_debugfs_exit(struct sdw_slave *slave); 338c2ecf20Sopenharmony_civoid sdw_debugfs_init(void); 348c2ecf20Sopenharmony_civoid sdw_debugfs_exit(void); 358c2ecf20Sopenharmony_ci#else 368c2ecf20Sopenharmony_cistatic inline void sdw_bus_debugfs_init(struct sdw_bus *bus) {} 378c2ecf20Sopenharmony_cistatic inline void sdw_bus_debugfs_exit(struct sdw_bus *bus) {} 388c2ecf20Sopenharmony_cistatic inline void sdw_slave_debugfs_init(struct sdw_slave *slave) {} 398c2ecf20Sopenharmony_cistatic inline void sdw_slave_debugfs_exit(struct sdw_slave *slave) {} 408c2ecf20Sopenharmony_cistatic inline void sdw_debugfs_init(void) {} 418c2ecf20Sopenharmony_cistatic inline void sdw_debugfs_exit(void) {} 428c2ecf20Sopenharmony_ci#endif 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cienum { 458c2ecf20Sopenharmony_ci SDW_MSG_FLAG_READ = 0, 468c2ecf20Sopenharmony_ci SDW_MSG_FLAG_WRITE, 478c2ecf20Sopenharmony_ci}; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci/** 508c2ecf20Sopenharmony_ci * struct sdw_msg - Message structure 518c2ecf20Sopenharmony_ci * @addr: Register address accessed in the Slave 528c2ecf20Sopenharmony_ci * @len: number of messages 538c2ecf20Sopenharmony_ci * @dev_num: Slave device number 548c2ecf20Sopenharmony_ci * @addr_page1: SCP address page 1 Slave register 558c2ecf20Sopenharmony_ci * @addr_page2: SCP address page 2 Slave register 568c2ecf20Sopenharmony_ci * @flags: transfer flags, indicate if xfer is read or write 578c2ecf20Sopenharmony_ci * @buf: message data buffer 588c2ecf20Sopenharmony_ci * @ssp_sync: Send message at SSP (Stream Synchronization Point) 598c2ecf20Sopenharmony_ci * @page: address requires paging 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_cistruct sdw_msg { 628c2ecf20Sopenharmony_ci u16 addr; 638c2ecf20Sopenharmony_ci u16 len; 648c2ecf20Sopenharmony_ci u8 dev_num; 658c2ecf20Sopenharmony_ci u8 addr_page1; 668c2ecf20Sopenharmony_ci u8 addr_page2; 678c2ecf20Sopenharmony_ci u8 flags; 688c2ecf20Sopenharmony_ci u8 *buf; 698c2ecf20Sopenharmony_ci bool ssp_sync; 708c2ecf20Sopenharmony_ci bool page; 718c2ecf20Sopenharmony_ci}; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci#define SDW_DOUBLE_RATE_FACTOR 2 748c2ecf20Sopenharmony_ci#define SDW_STRM_RATE_GROUPING 1 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ciextern int sdw_rows[SDW_FRAME_ROWS]; 778c2ecf20Sopenharmony_ciextern int sdw_cols[SDW_FRAME_COLS]; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ciint sdw_find_row_index(int row); 808c2ecf20Sopenharmony_ciint sdw_find_col_index(int col); 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci/** 838c2ecf20Sopenharmony_ci * sdw_port_runtime: Runtime port parameters for Master or Slave 848c2ecf20Sopenharmony_ci * 858c2ecf20Sopenharmony_ci * @num: Port number. For audio streams, valid port number ranges from 868c2ecf20Sopenharmony_ci * [1,14] 878c2ecf20Sopenharmony_ci * @ch_mask: Channel mask 888c2ecf20Sopenharmony_ci * @transport_params: Transport parameters 898c2ecf20Sopenharmony_ci * @port_params: Port parameters 908c2ecf20Sopenharmony_ci * @port_node: List node for Master or Slave port_list 918c2ecf20Sopenharmony_ci * 928c2ecf20Sopenharmony_ci * SoundWire spec has no mention of ports for Master interface but the 938c2ecf20Sopenharmony_ci * concept is logically extended. 948c2ecf20Sopenharmony_ci */ 958c2ecf20Sopenharmony_cistruct sdw_port_runtime { 968c2ecf20Sopenharmony_ci int num; 978c2ecf20Sopenharmony_ci int ch_mask; 988c2ecf20Sopenharmony_ci struct sdw_transport_params transport_params; 998c2ecf20Sopenharmony_ci struct sdw_port_params port_params; 1008c2ecf20Sopenharmony_ci struct list_head port_node; 1018c2ecf20Sopenharmony_ci}; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci/** 1048c2ecf20Sopenharmony_ci * sdw_slave_runtime: Runtime Stream parameters for Slave 1058c2ecf20Sopenharmony_ci * 1068c2ecf20Sopenharmony_ci * @slave: Slave handle 1078c2ecf20Sopenharmony_ci * @direction: Data direction for Slave 1088c2ecf20Sopenharmony_ci * @ch_count: Number of channels handled by the Slave for 1098c2ecf20Sopenharmony_ci * this stream 1108c2ecf20Sopenharmony_ci * @m_rt_node: sdw_master_runtime list node 1118c2ecf20Sopenharmony_ci * @port_list: List of Slave Ports configured for this stream 1128c2ecf20Sopenharmony_ci */ 1138c2ecf20Sopenharmony_cistruct sdw_slave_runtime { 1148c2ecf20Sopenharmony_ci struct sdw_slave *slave; 1158c2ecf20Sopenharmony_ci enum sdw_data_direction direction; 1168c2ecf20Sopenharmony_ci unsigned int ch_count; 1178c2ecf20Sopenharmony_ci struct list_head m_rt_node; 1188c2ecf20Sopenharmony_ci struct list_head port_list; 1198c2ecf20Sopenharmony_ci}; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci/** 1228c2ecf20Sopenharmony_ci * sdw_master_runtime: Runtime stream parameters for Master 1238c2ecf20Sopenharmony_ci * 1248c2ecf20Sopenharmony_ci * @bus: Bus handle 1258c2ecf20Sopenharmony_ci * @stream: Stream runtime handle 1268c2ecf20Sopenharmony_ci * @direction: Data direction for Master 1278c2ecf20Sopenharmony_ci * @ch_count: Number of channels handled by the Master for 1288c2ecf20Sopenharmony_ci * this stream, can be zero. 1298c2ecf20Sopenharmony_ci * @slave_rt_list: Slave runtime list 1308c2ecf20Sopenharmony_ci * @port_list: List of Master Ports configured for this stream, can be zero. 1318c2ecf20Sopenharmony_ci * @stream_node: sdw_stream_runtime master_list node 1328c2ecf20Sopenharmony_ci * @bus_node: sdw_bus m_rt_list node 1338c2ecf20Sopenharmony_ci */ 1348c2ecf20Sopenharmony_cistruct sdw_master_runtime { 1358c2ecf20Sopenharmony_ci struct sdw_bus *bus; 1368c2ecf20Sopenharmony_ci struct sdw_stream_runtime *stream; 1378c2ecf20Sopenharmony_ci enum sdw_data_direction direction; 1388c2ecf20Sopenharmony_ci unsigned int ch_count; 1398c2ecf20Sopenharmony_ci struct list_head slave_rt_list; 1408c2ecf20Sopenharmony_ci struct list_head port_list; 1418c2ecf20Sopenharmony_ci struct list_head stream_node; 1428c2ecf20Sopenharmony_ci struct list_head bus_node; 1438c2ecf20Sopenharmony_ci}; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cistruct sdw_dpn_prop *sdw_get_slave_dpn_prop(struct sdw_slave *slave, 1468c2ecf20Sopenharmony_ci enum sdw_data_direction direction, 1478c2ecf20Sopenharmony_ci unsigned int port_num); 1488c2ecf20Sopenharmony_ciint sdw_configure_dpn_intr(struct sdw_slave *slave, int port, 1498c2ecf20Sopenharmony_ci bool enable, int mask); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ciint sdw_transfer(struct sdw_bus *bus, struct sdw_msg *msg); 1528c2ecf20Sopenharmony_ciint sdw_transfer_defer(struct sdw_bus *bus, struct sdw_msg *msg, 1538c2ecf20Sopenharmony_ci struct sdw_defer *defer); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci#define SDW_READ_INTR_CLEAR_RETRY 10 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ciint sdw_fill_msg(struct sdw_msg *msg, struct sdw_slave *slave, 1588c2ecf20Sopenharmony_ci u32 addr, size_t count, u16 dev_num, u8 flags, u8 *buf); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci/* Retrieve and return channel count from channel mask */ 1618c2ecf20Sopenharmony_cistatic inline int sdw_ch_mask_to_ch(int ch_mask) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci int c = 0; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci for (c = 0; ch_mask; ch_mask >>= 1) 1668c2ecf20Sopenharmony_ci c += ch_mask & 1; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci return c; 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci/* Fill transport parameter data structure */ 1728c2ecf20Sopenharmony_cistatic inline void sdw_fill_xport_params(struct sdw_transport_params *params, 1738c2ecf20Sopenharmony_ci int port_num, bool grp_ctrl_valid, 1748c2ecf20Sopenharmony_ci int grp_ctrl, int sample_int, 1758c2ecf20Sopenharmony_ci int off1, int off2, 1768c2ecf20Sopenharmony_ci int hstart, int hstop, 1778c2ecf20Sopenharmony_ci int pack_mode, int lane_ctrl) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci params->port_num = port_num; 1808c2ecf20Sopenharmony_ci params->blk_grp_ctrl_valid = grp_ctrl_valid; 1818c2ecf20Sopenharmony_ci params->blk_grp_ctrl = grp_ctrl; 1828c2ecf20Sopenharmony_ci params->sample_interval = sample_int; 1838c2ecf20Sopenharmony_ci params->offset1 = off1; 1848c2ecf20Sopenharmony_ci params->offset2 = off2; 1858c2ecf20Sopenharmony_ci params->hstart = hstart; 1868c2ecf20Sopenharmony_ci params->hstop = hstop; 1878c2ecf20Sopenharmony_ci params->blk_pkg_mode = pack_mode; 1888c2ecf20Sopenharmony_ci params->lane_ctrl = lane_ctrl; 1898c2ecf20Sopenharmony_ci} 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci/* Fill port parameter data structure */ 1928c2ecf20Sopenharmony_cistatic inline void sdw_fill_port_params(struct sdw_port_params *params, 1938c2ecf20Sopenharmony_ci int port_num, int bps, 1948c2ecf20Sopenharmony_ci int flow_mode, int data_mode) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci params->num = port_num; 1978c2ecf20Sopenharmony_ci params->bps = bps; 1988c2ecf20Sopenharmony_ci params->flow_mode = flow_mode; 1998c2ecf20Sopenharmony_ci params->data_mode = data_mode; 2008c2ecf20Sopenharmony_ci} 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci/* Read-Modify-Write Slave register */ 2038c2ecf20Sopenharmony_cistatic inline int sdw_update(struct sdw_slave *slave, u32 addr, u8 mask, u8 val) 2048c2ecf20Sopenharmony_ci{ 2058c2ecf20Sopenharmony_ci int tmp; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci tmp = sdw_read(slave, addr); 2088c2ecf20Sopenharmony_ci if (tmp < 0) 2098c2ecf20Sopenharmony_ci return tmp; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci tmp = (tmp & ~mask) | val; 2128c2ecf20Sopenharmony_ci return sdw_write(slave, addr, tmp); 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci/* broadcast read/write for tests */ 2168c2ecf20Sopenharmony_ciint sdw_bread_no_pm_unlocked(struct sdw_bus *bus, u16 dev_num, u32 addr); 2178c2ecf20Sopenharmony_ciint sdw_bwrite_no_pm_unlocked(struct sdw_bus *bus, u16 dev_num, u32 addr, u8 value); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci/* 2208c2ecf20Sopenharmony_ci * At the moment we only track Master-initiated hw_reset. 2218c2ecf20Sopenharmony_ci * Additional fields can be added as needed 2228c2ecf20Sopenharmony_ci */ 2238c2ecf20Sopenharmony_ci#define SDW_UNATTACH_REQUEST_MASTER_RESET BIT(0) 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_civoid sdw_clear_slave_status(struct sdw_bus *bus, u32 request); 2268c2ecf20Sopenharmony_ciint sdw_slave_modalias(const struct sdw_slave *slave, char *buf, size_t size); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci#endif /* __SDW_BUS_H */ 229