1*4882a593Smuzhiyun /* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
2*4882a593Smuzhiyun /* Copyright(c) 2015-17 Intel Corporation. */
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun #ifndef __SDW_BUS_H
5*4882a593Smuzhiyun #define __SDW_BUS_H
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #define DEFAULT_BANK_SWITCH_TIMEOUT 3000
8*4882a593Smuzhiyun #define DEFAULT_PROBE_TIMEOUT 2000
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_ACPI)
11*4882a593Smuzhiyun int sdw_acpi_find_slaves(struct sdw_bus *bus);
12*4882a593Smuzhiyun #else
sdw_acpi_find_slaves(struct sdw_bus * bus)13*4882a593Smuzhiyun static inline int sdw_acpi_find_slaves(struct sdw_bus *bus)
14*4882a593Smuzhiyun {
15*4882a593Smuzhiyun return -ENOTSUPP;
16*4882a593Smuzhiyun }
17*4882a593Smuzhiyun #endif
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun int sdw_of_find_slaves(struct sdw_bus *bus);
20*4882a593Smuzhiyun void sdw_extract_slave_id(struct sdw_bus *bus,
21*4882a593Smuzhiyun u64 addr, struct sdw_slave_id *id);
22*4882a593Smuzhiyun int sdw_slave_add(struct sdw_bus *bus, struct sdw_slave_id *id,
23*4882a593Smuzhiyun struct fwnode_handle *fwnode);
24*4882a593Smuzhiyun int sdw_master_device_add(struct sdw_bus *bus, struct device *parent,
25*4882a593Smuzhiyun struct fwnode_handle *fwnode);
26*4882a593Smuzhiyun int sdw_master_device_del(struct sdw_bus *bus);
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #ifdef CONFIG_DEBUG_FS
29*4882a593Smuzhiyun void sdw_bus_debugfs_init(struct sdw_bus *bus);
30*4882a593Smuzhiyun void sdw_bus_debugfs_exit(struct sdw_bus *bus);
31*4882a593Smuzhiyun void sdw_slave_debugfs_init(struct sdw_slave *slave);
32*4882a593Smuzhiyun void sdw_slave_debugfs_exit(struct sdw_slave *slave);
33*4882a593Smuzhiyun void sdw_debugfs_init(void);
34*4882a593Smuzhiyun void sdw_debugfs_exit(void);
35*4882a593Smuzhiyun #else
sdw_bus_debugfs_init(struct sdw_bus * bus)36*4882a593Smuzhiyun static inline void sdw_bus_debugfs_init(struct sdw_bus *bus) {}
sdw_bus_debugfs_exit(struct sdw_bus * bus)37*4882a593Smuzhiyun static inline void sdw_bus_debugfs_exit(struct sdw_bus *bus) {}
sdw_slave_debugfs_init(struct sdw_slave * slave)38*4882a593Smuzhiyun static inline void sdw_slave_debugfs_init(struct sdw_slave *slave) {}
sdw_slave_debugfs_exit(struct sdw_slave * slave)39*4882a593Smuzhiyun static inline void sdw_slave_debugfs_exit(struct sdw_slave *slave) {}
sdw_debugfs_init(void)40*4882a593Smuzhiyun static inline void sdw_debugfs_init(void) {}
sdw_debugfs_exit(void)41*4882a593Smuzhiyun static inline void sdw_debugfs_exit(void) {}
42*4882a593Smuzhiyun #endif
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun enum {
45*4882a593Smuzhiyun SDW_MSG_FLAG_READ = 0,
46*4882a593Smuzhiyun SDW_MSG_FLAG_WRITE,
47*4882a593Smuzhiyun };
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun /**
50*4882a593Smuzhiyun * struct sdw_msg - Message structure
51*4882a593Smuzhiyun * @addr: Register address accessed in the Slave
52*4882a593Smuzhiyun * @len: number of messages
53*4882a593Smuzhiyun * @dev_num: Slave device number
54*4882a593Smuzhiyun * @addr_page1: SCP address page 1 Slave register
55*4882a593Smuzhiyun * @addr_page2: SCP address page 2 Slave register
56*4882a593Smuzhiyun * @flags: transfer flags, indicate if xfer is read or write
57*4882a593Smuzhiyun * @buf: message data buffer
58*4882a593Smuzhiyun * @ssp_sync: Send message at SSP (Stream Synchronization Point)
59*4882a593Smuzhiyun * @page: address requires paging
60*4882a593Smuzhiyun */
61*4882a593Smuzhiyun struct sdw_msg {
62*4882a593Smuzhiyun u16 addr;
63*4882a593Smuzhiyun u16 len;
64*4882a593Smuzhiyun u8 dev_num;
65*4882a593Smuzhiyun u8 addr_page1;
66*4882a593Smuzhiyun u8 addr_page2;
67*4882a593Smuzhiyun u8 flags;
68*4882a593Smuzhiyun u8 *buf;
69*4882a593Smuzhiyun bool ssp_sync;
70*4882a593Smuzhiyun bool page;
71*4882a593Smuzhiyun };
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun #define SDW_DOUBLE_RATE_FACTOR 2
74*4882a593Smuzhiyun #define SDW_STRM_RATE_GROUPING 1
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun extern int sdw_rows[SDW_FRAME_ROWS];
77*4882a593Smuzhiyun extern int sdw_cols[SDW_FRAME_COLS];
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun int sdw_find_row_index(int row);
80*4882a593Smuzhiyun int sdw_find_col_index(int col);
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun /**
83*4882a593Smuzhiyun * sdw_port_runtime: Runtime port parameters for Master or Slave
84*4882a593Smuzhiyun *
85*4882a593Smuzhiyun * @num: Port number. For audio streams, valid port number ranges from
86*4882a593Smuzhiyun * [1,14]
87*4882a593Smuzhiyun * @ch_mask: Channel mask
88*4882a593Smuzhiyun * @transport_params: Transport parameters
89*4882a593Smuzhiyun * @port_params: Port parameters
90*4882a593Smuzhiyun * @port_node: List node for Master or Slave port_list
91*4882a593Smuzhiyun *
92*4882a593Smuzhiyun * SoundWire spec has no mention of ports for Master interface but the
93*4882a593Smuzhiyun * concept is logically extended.
94*4882a593Smuzhiyun */
95*4882a593Smuzhiyun struct sdw_port_runtime {
96*4882a593Smuzhiyun int num;
97*4882a593Smuzhiyun int ch_mask;
98*4882a593Smuzhiyun struct sdw_transport_params transport_params;
99*4882a593Smuzhiyun struct sdw_port_params port_params;
100*4882a593Smuzhiyun struct list_head port_node;
101*4882a593Smuzhiyun };
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun /**
104*4882a593Smuzhiyun * sdw_slave_runtime: Runtime Stream parameters for Slave
105*4882a593Smuzhiyun *
106*4882a593Smuzhiyun * @slave: Slave handle
107*4882a593Smuzhiyun * @direction: Data direction for Slave
108*4882a593Smuzhiyun * @ch_count: Number of channels handled by the Slave for
109*4882a593Smuzhiyun * this stream
110*4882a593Smuzhiyun * @m_rt_node: sdw_master_runtime list node
111*4882a593Smuzhiyun * @port_list: List of Slave Ports configured for this stream
112*4882a593Smuzhiyun */
113*4882a593Smuzhiyun struct sdw_slave_runtime {
114*4882a593Smuzhiyun struct sdw_slave *slave;
115*4882a593Smuzhiyun enum sdw_data_direction direction;
116*4882a593Smuzhiyun unsigned int ch_count;
117*4882a593Smuzhiyun struct list_head m_rt_node;
118*4882a593Smuzhiyun struct list_head port_list;
119*4882a593Smuzhiyun };
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun /**
122*4882a593Smuzhiyun * sdw_master_runtime: Runtime stream parameters for Master
123*4882a593Smuzhiyun *
124*4882a593Smuzhiyun * @bus: Bus handle
125*4882a593Smuzhiyun * @stream: Stream runtime handle
126*4882a593Smuzhiyun * @direction: Data direction for Master
127*4882a593Smuzhiyun * @ch_count: Number of channels handled by the Master for
128*4882a593Smuzhiyun * this stream, can be zero.
129*4882a593Smuzhiyun * @slave_rt_list: Slave runtime list
130*4882a593Smuzhiyun * @port_list: List of Master Ports configured for this stream, can be zero.
131*4882a593Smuzhiyun * @stream_node: sdw_stream_runtime master_list node
132*4882a593Smuzhiyun * @bus_node: sdw_bus m_rt_list node
133*4882a593Smuzhiyun */
134*4882a593Smuzhiyun struct sdw_master_runtime {
135*4882a593Smuzhiyun struct sdw_bus *bus;
136*4882a593Smuzhiyun struct sdw_stream_runtime *stream;
137*4882a593Smuzhiyun enum sdw_data_direction direction;
138*4882a593Smuzhiyun unsigned int ch_count;
139*4882a593Smuzhiyun struct list_head slave_rt_list;
140*4882a593Smuzhiyun struct list_head port_list;
141*4882a593Smuzhiyun struct list_head stream_node;
142*4882a593Smuzhiyun struct list_head bus_node;
143*4882a593Smuzhiyun };
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun struct sdw_dpn_prop *sdw_get_slave_dpn_prop(struct sdw_slave *slave,
146*4882a593Smuzhiyun enum sdw_data_direction direction,
147*4882a593Smuzhiyun unsigned int port_num);
148*4882a593Smuzhiyun int sdw_configure_dpn_intr(struct sdw_slave *slave, int port,
149*4882a593Smuzhiyun bool enable, int mask);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun int sdw_transfer(struct sdw_bus *bus, struct sdw_msg *msg);
152*4882a593Smuzhiyun int sdw_transfer_defer(struct sdw_bus *bus, struct sdw_msg *msg,
153*4882a593Smuzhiyun struct sdw_defer *defer);
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun #define SDW_READ_INTR_CLEAR_RETRY 10
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun int sdw_fill_msg(struct sdw_msg *msg, struct sdw_slave *slave,
158*4882a593Smuzhiyun u32 addr, size_t count, u16 dev_num, u8 flags, u8 *buf);
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun /* Retrieve and return channel count from channel mask */
sdw_ch_mask_to_ch(int ch_mask)161*4882a593Smuzhiyun static inline int sdw_ch_mask_to_ch(int ch_mask)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun int c = 0;
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun for (c = 0; ch_mask; ch_mask >>= 1)
166*4882a593Smuzhiyun c += ch_mask & 1;
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun return c;
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun /* Fill transport parameter data structure */
sdw_fill_xport_params(struct sdw_transport_params * params,int port_num,bool grp_ctrl_valid,int grp_ctrl,int sample_int,int off1,int off2,int hstart,int hstop,int pack_mode,int lane_ctrl)172*4882a593Smuzhiyun static inline void sdw_fill_xport_params(struct sdw_transport_params *params,
173*4882a593Smuzhiyun int port_num, bool grp_ctrl_valid,
174*4882a593Smuzhiyun int grp_ctrl, int sample_int,
175*4882a593Smuzhiyun int off1, int off2,
176*4882a593Smuzhiyun int hstart, int hstop,
177*4882a593Smuzhiyun int pack_mode, int lane_ctrl)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun params->port_num = port_num;
180*4882a593Smuzhiyun params->blk_grp_ctrl_valid = grp_ctrl_valid;
181*4882a593Smuzhiyun params->blk_grp_ctrl = grp_ctrl;
182*4882a593Smuzhiyun params->sample_interval = sample_int;
183*4882a593Smuzhiyun params->offset1 = off1;
184*4882a593Smuzhiyun params->offset2 = off2;
185*4882a593Smuzhiyun params->hstart = hstart;
186*4882a593Smuzhiyun params->hstop = hstop;
187*4882a593Smuzhiyun params->blk_pkg_mode = pack_mode;
188*4882a593Smuzhiyun params->lane_ctrl = lane_ctrl;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun /* Fill port parameter data structure */
sdw_fill_port_params(struct sdw_port_params * params,int port_num,int bps,int flow_mode,int data_mode)192*4882a593Smuzhiyun static inline void sdw_fill_port_params(struct sdw_port_params *params,
193*4882a593Smuzhiyun int port_num, int bps,
194*4882a593Smuzhiyun int flow_mode, int data_mode)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun params->num = port_num;
197*4882a593Smuzhiyun params->bps = bps;
198*4882a593Smuzhiyun params->flow_mode = flow_mode;
199*4882a593Smuzhiyun params->data_mode = data_mode;
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun /* Read-Modify-Write Slave register */
sdw_update(struct sdw_slave * slave,u32 addr,u8 mask,u8 val)203*4882a593Smuzhiyun static inline int sdw_update(struct sdw_slave *slave, u32 addr, u8 mask, u8 val)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun int tmp;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun tmp = sdw_read(slave, addr);
208*4882a593Smuzhiyun if (tmp < 0)
209*4882a593Smuzhiyun return tmp;
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun tmp = (tmp & ~mask) | val;
212*4882a593Smuzhiyun return sdw_write(slave, addr, tmp);
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun /* broadcast read/write for tests */
216*4882a593Smuzhiyun int sdw_bread_no_pm_unlocked(struct sdw_bus *bus, u16 dev_num, u32 addr);
217*4882a593Smuzhiyun int sdw_bwrite_no_pm_unlocked(struct sdw_bus *bus, u16 dev_num, u32 addr, u8 value);
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun /*
220*4882a593Smuzhiyun * At the moment we only track Master-initiated hw_reset.
221*4882a593Smuzhiyun * Additional fields can be added as needed
222*4882a593Smuzhiyun */
223*4882a593Smuzhiyun #define SDW_UNATTACH_REQUEST_MASTER_RESET BIT(0)
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun void sdw_clear_slave_status(struct sdw_bus *bus, u32 request);
226*4882a593Smuzhiyun int sdw_slave_modalias(const struct sdw_slave *slave, char *buf, size_t size);
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun #endif /* __SDW_BUS_H */
229